trace.c revision 1.1.1.4
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-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} 318