summaryrefslogtreecommitdiff
path: root/tests/trace.c
blob: de397f53affa274767bb81e7fca6c0a56035a02f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
/* Support for diagnostic traces.

Copyright 1999-2005 Free Software Foundation, Inc.

This file is part of the GNU MP Library test suite.

The GNU MP Library test suite is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 3 of the License,
or (at your option) any later version.

The GNU MP Library test suite is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
Public License for more details.

You should have received a copy of the GNU General Public License along with
the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */


/* Future: Would like commas printed between limbs in hex or binary, but
   perhaps not always since it might upset cutting and pasting into bc or
   whatever.  */


#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* for strlen */

#include "gmp-impl.h"

#include "tests.h"


/* Number base for the various trace printing routines.
   Set this in main() or with the debugger.
   If hexadecimal is going to be fed into GNU bc, remember to use -16
   because bc requires upper case.  */

int  mp_trace_base = 10;


void
mp_trace_start (const char *name)
{
  if (name != NULL && name[0] != '\0')
    printf ("%s=", name);

  switch (ABS (mp_trace_base)) {
  case  2: printf ("bin:");                         break;
  case  8: printf ("oct:");                         break;
  case 10:                                          break;
  case 16: printf ("0x");                           break;
  default: printf ("base%d:", ABS (mp_trace_base)); break;
  }
}

/* Print "name=value\n" to stdout for an mpq_t value.  */
void
mpq_trace (const char *name, mpq_srcptr q)
{
  mp_trace_start (name);
  if (q == NULL)
    {
      printf ("NULL\n");
      return;
    }

  mpq_out_str (stdout, mp_trace_base, q);
  printf ("\n");
}


/* Print "name=value\n" to stdout for an mpz_t value.  */
void
mpz_trace (const char *name, mpz_srcptr z)
{
  mpq_t      q;
  mp_limb_t  one;

  if (z == NULL)
    {
      mpq_trace (name, NULL);
      return;
    }

  q->_mp_num._mp_alloc = ALLOC(z);
  q->_mp_num._mp_size = SIZ(z);
  q->_mp_num._mp_d = PTR(z);

  one = 1;
  q->_mp_den._mp_alloc = 1;
  q->_mp_den._mp_size = 1;
  q->_mp_den._mp_d = &one;

  mpq_trace(name, q);
}


/* Print "name=value\n" to stdout for an mpf_t value. */
void
mpf_trace (const char *name, mpf_srcptr f)
{
  mp_trace_start (name);
  if (f == NULL)
    {
      printf ("NULL\n");
      return;
    }

  mpf_out_str (stdout, ABS (mp_trace_base), 0, f);
  printf ("\n");
}


/* Print "namenum=value\n" to stdout for an mpz_t value.
   "name" should have a "%d" to get the number. */
void
mpz_tracen (const char *name, int num, mpz_srcptr z)
{
  if (name != NULL && name[0] != '\0')
    {
      printf (name, num);
      putchar ('=');
    }
  mpz_trace (NULL, z);
}


/* Print "name=value\n" to stdout for an mpn style ptr,size. */
void
mpn_trace (const char *name, mp_srcptr ptr, mp_size_t size)
{
  mpz_t  z;
  if (ptr == NULL)
    {
      mpz_trace (name, NULL);
      return;
    }
  MPN_NORMALIZE (ptr, size);
  PTR(z) = (mp_ptr) ptr;
  SIZ(z) = size;
  ALLOC(z) = size;
  mpz_trace (name, z);
}

/* Print "name=value\n" to stdout for a limb, nail doesn't have to be zero. */
void
mp_limb_trace (const char *name, mp_limb_t n)
{
#if GMP_NAIL_BITS != 0
  mp_limb_t  a[2];
  a[0] = n & GMP_NUMB_MASK;
  a[1] = n >> GMP_NUMB_BITS;
  mpn_trace (name, a, (mp_size_t) 2);
#else
  mpn_trace (name, &n, (mp_size_t) 1);
#endif
}


/* Print "namenum=value\n" to stdout for an mpn style ptr,size.
   "name" should have a "%d" to get the number.  */
void
mpn_tracen (const char *name, int num, mp_srcptr ptr, mp_size_t size)
{
  if (name != NULL && name[0] != '\0')
    {
      printf (name, num);
      putchar ('=');
    }
  mpn_trace (NULL, ptr, size);
}


/* Print "namenum=value\n" to stdout for an array of mpn style ptr,size.

   "a" is an array of pointers, each a[i] is a pointer to "size" many limbs.
   The formal parameter isn't mp_srcptr because that causes compiler
   warnings, but the values aren't modified.

   "name" should have a printf style "%d" to get the array index.  */

void
mpn_tracea (const char *name, const mp_ptr *a, int count, mp_size_t size)
{
  int i;
  for (i = 0; i < count; i++)
    mpn_tracen (name, i, a[i], size);
}


/* Print "value\n" to a file for an mpz_t value.  Any previous contents of
   the file are overwritten, so you need different file names each time this
   is called.

   Overwriting the file is a feature, it means you get old data replaced
   when you run a test program repeatedly.  */

void
mpn_trace_file (const char *filename, mp_srcptr ptr, mp_size_t size)
{
  FILE   *fp;
  mpz_t  z;

  fp = fopen (filename, "w");
  if (fp == NULL)
    {
      perror ("fopen");
      abort();
    }

  MPN_NORMALIZE (ptr, size);
  PTR(z) = (mp_ptr) ptr;
  SIZ(z) = (int) size;

  mpz_out_str (fp, mp_trace_base, z);
  fprintf (fp, "\n");

  if (ferror (fp) || fclose (fp) != 0)
    {
      printf ("error writing %s\n", filename);
      abort();
    }
}


/* Print "value\n" to a set of files, one file for each element of the given
   array of mpn style ptr,size.  Any previous contents of the files are
   overwritten, so you need different file names each time this is called.
   Each file is "filenameN" where N is 0 to count-1.

   "a" is an array of pointers, each a[i] is a pointer to "size" many limbs.
   The formal parameter isn't mp_srcptr because that causes compiler
   warnings, but the values aren't modified.

   Overwriting the files is a feature, it means you get old data replaced
   when you run a test program repeatedly.  The output style isn't
   particularly pretty, but at least it gets something out, and you can cat
   the files into bc, or whatever. */

void
mpn_tracea_file (const char *filename,
                 const mp_ptr *a, int count, mp_size_t size)
{
  char  *s;
  int   i;
  TMP_DECL;

  TMP_MARK;
  s = (char *) TMP_ALLOC (strlen (filename) + 50);

  for (i = 0; i < count; i++)
    {
      sprintf (s, "%s%d", filename, i);
      mpn_trace_file (s, a[i], size);
    }

  TMP_FREE;
}


void
byte_trace (const char *name, const void *ptr, mp_size_t size)
{
  const char *fmt;
  mp_size_t  i;

  mp_trace_start (name);

  switch (mp_trace_base) {
  case   8: fmt = " %o"; break;
  case  10: fmt = " %d"; break;
  case  16: fmt = " %x"; break;
  case -16: fmt = " %X"; break;
  default: printf ("Oops, unsupported base in byte_trace\n"); abort (); break;
  }

  for (i = 0; i < size; i++)
    printf (fmt, (int) ((unsigned char *) ptr)[i]);
  printf ("\n");
}

void
byte_tracen (const char *name, int num, const void *ptr, mp_size_t size)
{
  if (name != NULL && name[0] != '\0')
    {
      printf (name, num);
      putchar ('=');
    }
  byte_trace (NULL, ptr, size);
}


void
d_trace (const char *name, double d)
{
  union {
    double         d;
    unsigned char  b[sizeof(double)];
  } u;
  int  i;

  if (name != NULL && name[0] != '\0')
    printf ("%s=", name);

  u.d = d;
  printf ("[");
  for (i = 0; i < sizeof (u.b); i++)
    {
      if (i != 0)
        printf (" ");
      printf ("%02X", (int) u.b[i]);
    }
  printf ("] %.20g\n", d);
}