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