github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/trace.c (about) 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.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 41 int mp_trace_base = 10; 42 43 44 void 45 mp_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. */ 60 void 61 mpq_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. */ 76 void 77 mpz_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. */ 102 void 103 mpf_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. */ 119 void 120 mpz_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. */ 132 void 133 mpn_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. */ 149 void 150 mp_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. */ 165 void 166 mpn_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 185 void 186 mpn_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 201 void 202 mpn_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 243 void 244 mpn_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 264 void 265 byte_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 285 void 286 byte_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 297 void 298 d_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 }