xref: /netbsd-src/external/lgpl3/gmp/dist/tests/trace.c (revision 4391d5e9d4f291db41e3b3ba26a01b5e51364aae)
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