trace.c revision 1.1.1.3 1 /* Support for diagnostic traces.
2
3 Copyright 1999-2005 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library test suite.
6
7 The GNU MP Library test suite is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 3 of the License,
10 or (at your option) any later version.
11
12 The GNU MP Library test suite is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15 Public License for more details.
16
17 You should have received a copy of the GNU General Public License along with
18 the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
19
20
21 /* Future: Would like commas printed between limbs in hex or binary, but
22 perhaps not always since it might upset cutting and pasting into bc or
23 whatever. */
24
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h> /* for strlen */
29
30 #include "gmp.h"
31 #include "gmp-impl.h"
32
33 #include "tests.h"
34
35
36 /* Number base for the various trace printing routines.
37 Set this in main() or with the debugger.
38 If hexadecimal is going to be fed into GNU bc, remember to use -16
39 because bc requires upper case. */
40
41 int mp_trace_base = 10;
42
43
44 void
45 mp_trace_start (const char *name)
46 {
47 if (name != NULL && name[0] != '\0')
48 printf ("%s=", name);
49
50 switch (ABS (mp_trace_base)) {
51 case 2: printf ("bin:"); break;
52 case 8: printf ("oct:"); break;
53 case 10: break;
54 case 16: printf ("0x"); break;
55 default: printf ("base%d:", ABS (mp_trace_base)); break;
56 }
57 }
58
59 /* Print "name=value\n" to stdout for an mpq_t value. */
60 void
61 mpq_trace (const char *name, mpq_srcptr q)
62 {
63 mp_trace_start (name);
64 if (q == NULL)
65 {
66 printf ("NULL\n");
67 return;
68 }
69
70 mpq_out_str (stdout, mp_trace_base, q);
71 printf ("\n");
72 }
73
74
75 /* Print "name=value\n" to stdout for an mpz_t value. */
76 void
77 mpz_trace (const char *name, mpz_srcptr z)
78 {
79 mpq_t q;
80 mp_limb_t one;
81
82 if (z == NULL)
83 {
84 mpq_trace (name, NULL);
85 return;
86 }
87
88 q->_mp_num._mp_alloc = ALLOC(z);
89 q->_mp_num._mp_size = SIZ(z);
90 q->_mp_num._mp_d = PTR(z);
91
92 one = 1;
93 q->_mp_den._mp_alloc = 1;
94 q->_mp_den._mp_size = 1;
95 q->_mp_den._mp_d = &one;
96
97 mpq_trace(name, q);
98 }
99
100
101 /* Print "name=value\n" to stdout for an mpf_t value. */
102 void
103 mpf_trace (const char *name, mpf_srcptr f)
104 {
105 mp_trace_start (name);
106 if (f == NULL)
107 {
108 printf ("NULL\n");
109 return;
110 }
111
112 mpf_out_str (stdout, ABS (mp_trace_base), 0, f);
113 printf ("\n");
114 }
115
116
117 /* Print "namenum=value\n" to stdout for an mpz_t value.
118 "name" should have a "%d" to get the number. */
119 void
120 mpz_tracen (const char *name, int num, mpz_srcptr z)
121 {
122 if (name != NULL && name[0] != '\0')
123 {
124 printf (name, num);
125 putchar ('=');
126 }
127 mpz_trace (NULL, z);
128 }
129
130
131 /* Print "name=value\n" to stdout for an mpn style ptr,size. */
132 void
133 mpn_trace (const char *name, mp_srcptr ptr, mp_size_t size)
134 {
135 mpz_t z;
136 if (ptr == NULL)
137 {
138 mpz_trace (name, NULL);
139 return;
140 }
141 MPN_NORMALIZE (ptr, size);
142 PTR(z) = (mp_ptr) ptr;
143 SIZ(z) = size;
144 ALLOC(z) = size;
145 mpz_trace (name, z);
146 }
147
148 /* Print "name=value\n" to stdout for a limb, nail doesn't have to be zero. */
149 void
150 mp_limb_trace (const char *name, mp_limb_t n)
151 {
152 #if GMP_NAIL_BITS != 0
153 mp_limb_t a[2];
154 a[0] = n & GMP_NUMB_MASK;
155 a[1] = n >> GMP_NUMB_BITS;
156 mpn_trace (name, a, (mp_size_t) 2);
157 #else
158 mpn_trace (name, &n, (mp_size_t) 1);
159 #endif
160 }
161
162
163 /* Print "namenum=value\n" to stdout for an mpn style ptr,size.
164 "name" should have a "%d" to get the number. */
165 void
166 mpn_tracen (const char *name, int num, mp_srcptr ptr, mp_size_t size)
167 {
168 if (name != NULL && name[0] != '\0')
169 {
170 printf (name, num);
171 putchar ('=');
172 }
173 mpn_trace (NULL, ptr, size);
174 }
175
176
177 /* Print "namenum=value\n" to stdout for an array of mpn style ptr,size.
178
179 "a" is an array of pointers, each a[i] is a pointer to "size" many limbs.
180 The formal parameter isn't mp_srcptr because that causes compiler
181 warnings, but the values aren't modified.
182
183 "name" should have a printf style "%d" to get the array index. */
184
185 void
186 mpn_tracea (const char *name, const mp_ptr *a, int count, mp_size_t size)
187 {
188 int i;
189 for (i = 0; i < count; i++)
190 mpn_tracen (name, i, a[i], size);
191 }
192
193
194 /* Print "value\n" to a file for an mpz_t value. Any previous contents of
195 the file are overwritten, so you need different file names each time this
196 is called.
197
198 Overwriting the file is a feature, it means you get old data replaced
199 when you run a test program repeatedly. */
200
201 void
202 mpn_trace_file (const char *filename, mp_srcptr ptr, mp_size_t size)
203 {
204 FILE *fp;
205 mpz_t z;
206
207 fp = fopen (filename, "w");
208 if (fp == NULL)
209 {
210 perror ("fopen");
211 abort();
212 }
213
214 MPN_NORMALIZE (ptr, size);
215 PTR(z) = (mp_ptr) ptr;
216 SIZ(z) = (int) size;
217
218 mpz_out_str (fp, mp_trace_base, z);
219 fprintf (fp, "\n");
220
221 if (ferror (fp) || fclose (fp) != 0)
222 {
223 printf ("error writing %s\n", filename);
224 abort();
225 }
226 }
227
228
229 /* Print "value\n" to a set of files, one file for each element of the given
230 array of mpn style ptr,size. Any previous contents of the files are
231 overwritten, so you need different file names each time this is called.
232 Each file is "filenameN" where N is 0 to count-1.
233
234 "a" is an array of pointers, each a[i] is a pointer to "size" many limbs.
235 The formal parameter isn't mp_srcptr because that causes compiler
236 warnings, but the values aren't modified.
237
238 Overwriting the files is a feature, it means you get old data replaced
239 when you run a test program repeatedly. The output style isn't
240 particularly pretty, but at least it gets something out, and you can cat
241 the files into bc, or whatever. */
242
243 void
244 mpn_tracea_file (const char *filename,
245 const mp_ptr *a, int count, mp_size_t size)
246 {
247 char *s;
248 int i;
249 TMP_DECL;
250
251 TMP_MARK;
252 s = (char *) TMP_ALLOC (strlen (filename) + 50);
253
254 for (i = 0; i < count; i++)
255 {
256 sprintf (s, "%s%d", filename, i);
257 mpn_trace_file (s, a[i], size);
258 }
259
260 TMP_FREE;
261 }
262
263
264 void
265 byte_trace (const char *name, const void *ptr, mp_size_t size)
266 {
267 const char *fmt;
268 mp_size_t i;
269
270 mp_trace_start (name);
271
272 switch (mp_trace_base) {
273 case 8: fmt = " %o"; break;
274 case 10: fmt = " %d"; break;
275 case 16: fmt = " %x"; break;
276 case -16: fmt = " %X"; break;
277 default: printf ("Oops, unsupported base in byte_trace\n"); abort (); break;
278 }
279
280 for (i = 0; i < size; i++)
281 printf (fmt, (int) ((unsigned char *) ptr)[i]);
282 printf ("\n");
283 }
284
285 void
286 byte_tracen (const char *name, int num, const void *ptr, mp_size_t size)
287 {
288 if (name != NULL && name[0] != '\0')
289 {
290 printf (name, num);
291 putchar ('=');
292 }
293 byte_trace (NULL, ptr, size);
294 }
295
296
297 void
298 d_trace (const char *name, double d)
299 {
300 union {
301 double d;
302 unsigned char b[sizeof(double)];
303 } u;
304 int i;
305
306 if (name != NULL && name[0] != '\0')
307 printf ("%s=", name);
308
309 u.d = d;
310 printf ("[");
311 for (i = 0; i < sizeof (u.b); i++)
312 {
313 if (i != 0)
314 printf (" ");
315 printf ("%02X", (int) u.b[i]);
316 }
317 printf ("] %.20g\n", d);
318 }
319