trace.c revision 1.1.1.3
1/* Support for diagnostic traces.
2
3Copyright 1999-2005 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library test suite.
6
7The GNU MP Library test suite is free software; you can redistribute it
8and/or modify it under the terms of the GNU General Public License as
9published by the Free Software Foundation; either version 3 of the License,
10or (at your option) any later version.
11
12The GNU MP Library test suite is distributed in the hope that it will be
13useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
15Public License for more details.
16
17You should have received a copy of the GNU General Public License along with
18the 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
41int  mp_trace_base = 10;
42
43
44void
45mp_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.  */
60void
61mpq_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.  */
76void
77mpz_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. */
102void
103mpf_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. */
119void
120mpz_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. */
132void
133mpn_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. */
149void
150mp_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.  */
165void
166mpn_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
185void
186mpn_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
201void
202mpn_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
243void
244mpn_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
264void
265byte_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
285void
286byte_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
297void
298d_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