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