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