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