1139823Simp/* Support for diagnostic traces. 25191Swollman 35191SwollmanCopyright 1999-2005 Free Software Foundation, Inc. 45191Swollman 55191SwollmanThis file is part of the GNU MP Library test suite. 65191Swollman 75191SwollmanThe GNU MP Library test suite is free software; you can redistribute it 85191Swollmanand/or modify it under the terms of the GNU General Public License as 95191Swollmanpublished by the Free Software Foundation; either version 3 of the License, 105191Swollmanor (at your option) any later version. 115191Swollman 125191SwollmanThe GNU MP Library test suite is distributed in the hope that it will be 135191Swollmanuseful, but WITHOUT ANY WARRANTY; without even the implied warranty of 145191SwollmanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 155191SwollmanPublic License for more details. 165191Swollman 175191SwollmanYou should have received a copy of the GNU General Public License along with 185191Swollmanthe GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ 195191Swollman 205191Swollman 215191Swollman/* Future: Would like commas printed between limbs in hex or binary, but 225191Swollman perhaps not always since it might upset cutting and pasting into bc or 235191Swollman whatever. */ 245191Swollman 255191Swollman 265191Swollman#include <stdio.h> 275191Swollman#include <stdlib.h> 285191Swollman#include <string.h> /* for strlen */ 295191Swollman 3050477Speter#include "gmp-impl.h" 315191Swollman 325191Swollman#include "tests.h" 335191Swollman 345191Swollman 355191Swollman/* Number base for the various trace printing routines. 365191Swollman Set this in main() or with the debugger. 375191Swollman If hexadecimal is going to be fed into GNU bc, remember to use -16 385191Swollman because bc requires upper case. */ 395191Swollman 405191Swollmanint mp_trace_base = 10; 4197290Sbrooks 4271862Speter 435191Swollmanvoid 445191Swollmanmp_trace_start (const char *name) 4524204Sbde{ 465191Swollman if (name != NULL && name[0] != '\0') 475191Swollman printf ("%s=", name); 48130933Sbrooks 495191Swollman switch (ABS (mp_trace_base)) { 505191Swollman case 2: printf ("bin:"); break; 515191Swollman case 8: printf ("oct:"); break; 525191Swollman case 10: break; 5332350Seivind case 16: printf ("0x"); break; 5454263Sshin default: printf ("base%d:", ABS (mp_trace_base)); break; 555191Swollman } 565191Swollman} 575191Swollman 585191Swollman/* Print "name=value\n" to stdout for an mpq_t value. */ 595191Swollmanvoid 605191Swollmanmpq_trace (const char *name, mpq_srcptr q) 615191Swollman{ 6297290Sbrooks mp_trace_start (name); 6310429Sbde if (q == NULL) 6497290Sbrooks { 65147256Sbrooks printf ("NULL\n"); 6697290Sbrooks return; 675191Swollman } 6897290Sbrooks 6997290Sbrooks mpq_out_str (stdout, mp_trace_base, q); 7097290Sbrooks printf ("\n"); 7197290Sbrooks} 7297290Sbrooks 7397290Sbrooks 7497290Sbrooks/* Print "name=value\n" to stdout for an mpz_t value. */ 7597290Sbrooksvoid 7697290Sbrooksmpz_trace (const char *name, mpz_srcptr z) 77130933Sbrooks{ 78130933Sbrooks mpq_t q; 7997290Sbrooks mp_limb_t one; 8097290Sbrooks 815191Swollman if (z == NULL) 8297290Sbrooks { 8397290Sbrooks mpq_trace (name, NULL); 845191Swollman return; 85131670Sbms } 86147256Sbrooks 87147256Sbrooks q->_mp_num._mp_alloc = ALLOC(z); 88147256Sbrooks q->_mp_num._mp_size = SIZ(z); 89147256Sbrooks q->_mp_num._mp_d = PTR(z); 90147256Sbrooks 9197290Sbrooks one = 1; 9297290Sbrooks q->_mp_den._mp_alloc = 1; 93121816Sbrooks q->_mp_den._mp_size = 1; 945191Swollman q->_mp_den._mp_d = &one; 955191Swollman 96152308Sglebius mpq_trace(name, q); 9741757Seivind} 9841757Seivind 995191Swollman 1005191Swollman/* Print "name=value\n" to stdout for an mpf_t value. */ 10153115Sphkvoid 1025191Swollmanmpf_trace (const char *name, mpf_srcptr f) 103147611Sdwmalone{ 10497290Sbrooks mp_trace_start (name); 10597290Sbrooks if (f == NULL) 1065191Swollman { 1075191Swollman printf ("NULL\n"); 10897290Sbrooks return; 10997290Sbrooks } 11097290Sbrooks 11197290Sbrooks mpf_out_str (stdout, ABS (mp_trace_base), 0, f); 11297290Sbrooks printf ("\n"); 11397290Sbrooks} 11497290Sbrooks 115151266Sthompsa 116151266Sthompsa/* Print "namenum=value\n" to stdout for an mpz_t value. 117151266Sthompsa "name" should have a "%d" to get the number. */ 118151266Sthompsavoid 119151266Sthompsampz_tracen (const char *name, int num, mpz_srcptr z) 12097290Sbrooks{ 12197290Sbrooks if (name != NULL && name[0] != '\0') 1225191Swollman { 123131669Sbms printf (name, num); 124126777Srwatson putchar ('='); 125126777Srwatson } 126131669Sbms mpz_trace (NULL, z); 127131669Sbms} 12897290Sbrooks 129131669Sbms 130131669Sbms/* Print "name=value\n" to stdout for an mpn style ptr,size. */ 13197290Sbrooksvoid 13297290Sbrooksmpn_trace (const char *name, mp_srcptr ptr, mp_size_t size) 133132199Sphk{ 134132199Sphk mpz_t z; 135131669Sbms if (ptr == NULL) 136131669Sbms { 137131669Sbms mpz_trace (name, NULL); 13871862Speter return; 139131669Sbms } 140131669Sbms MPN_NORMALIZE (ptr, size); 141131669Sbms PTR(z) = (mp_ptr) ptr; 14271862Speter SIZ(z) = size; 143131669Sbms ALLOC(z) = size; 14471862Speter mpz_trace (name, z); 14571862Speter} 14671862Speter 14771862Speter/* Print "name=value\n" to stdout for a limb, nail doesn't have to be zero. */ 14878351Smarkmvoid 14978351Smarkmmp_limb_trace (const char *name, mp_limb_t n) 1505191Swollman{ 151147611Sdwmalone#if GMP_NAIL_BITS != 0 152131669Sbms mp_limb_t a[2]; 153113255Sdes a[0] = n & GMP_NUMB_MASK; 154131669Sbms a[1] = n >> GMP_NUMB_BITS; 155147611Sdwmalone mpn_trace (name, a, (mp_size_t) 2); 15610957Swollman#else 157147611Sdwmalone mpn_trace (name, &n, (mp_size_t) 1); 158147611Sdwmalone#endif 15910957Swollman} 16010957Swollman 16197290Sbrooks 1625191Swollman/* Print "namenum=value\n" to stdout for an mpn style ptr,size. 163123922Ssam "name" should have a "%d" to get the number. */ 1645191Swollmanvoid 1655191Swollmanmpn_tracen (const char *name, int num, mp_srcptr ptr, mp_size_t size) 1665191Swollman{ 1675191Swollman if (name != NULL && name[0] != '\0') 1685191Swollman { 1695191Swollman printf (name, num); 1705191Swollman putchar ('='); 171131669Sbms } 1725191Swollman mpn_trace (NULL, ptr, size); 1735191Swollman} 1745191Swollman 1755191Swollman 17685074Sru/* Print "namenum=value\n" to stdout for an array of mpn style ptr,size. 1775191Swollman 178120727Ssam "a" is an array of pointers, each a[i] is a pointer to "size" many limbs. 179142352Ssam The formal parameter isn't mp_srcptr because that causes compiler 1805191Swollman warnings, but the values aren't modified. 1815191Swollman 1825191Swollman "name" should have a printf style "%d" to get the array index. */ 1835191Swollman 1845191Swollmanvoid 18512611Sbdempn_tracea (const char *name, const mp_ptr *a, int count, mp_size_t size) 18678351Smarkm{ 1875191Swollman int i; 18878351Smarkm for (i = 0; i < count; i++) 18978351Smarkm mpn_tracen (name, i, a[i], size); 19078351Smarkm} 1915191Swollman 1925191Swollman 1935191Swollman/* Print "value\n" to a file for an mpz_t value. Any previous contents of 1945191Swollman the file are overwritten, so you need different file names each time this 1955191Swollman is called. 1965191Swollman 1975191Swollman Overwriting the file is a feature, it means you get old data replaced 19841757Seivind when you run a test program repeatedly. */ 1995191Swollman 2005191Swollmanvoid 2015191Swollmanmpn_trace_file (const char *filename, mp_srcptr ptr, mp_size_t size) 2025191Swollman{ 2035191Swollman FILE *fp; 2045191Swollman mpz_t z; 2055191Swollman 2065191Swollman fp = fopen (filename, "w"); 2075191Swollman if (fp == NULL) 2085191Swollman { 2095191Swollman perror ("fopen"); 2105191Swollman abort(); 2115191Swollman } 2125191Swollman 2135191Swollman MPN_NORMALIZE (ptr, size); 2145191Swollman PTR(z) = (mp_ptr) ptr; 2155191Swollman SIZ(z) = (int) size; 21654263Sshin 21754263Sshin mpz_out_str (fp, mp_trace_base, z); 21854263Sshin fprintf (fp, "\n"); 21954263Sshin 2205191Swollman if (ferror (fp) || fclose (fp) != 0) 2215191Swollman { 2225191Swollman printf ("error writing %s\n", filename); 2235191Swollman abort(); 2245191Swollman } 2255191Swollman} 2265191Swollman 2275191Swollman 2285191Swollman/* Print "value\n" to a set of files, one file for each element of the given 2295191Swollman array of mpn style ptr,size. Any previous contents of the files are 2305191Swollman overwritten, so you need different file names each time this is called. 2315191Swollman Each file is "filenameN" where N is 0 to count-1. 2325191Swollman 2335191Swollman "a" is an array of pointers, each a[i] is a pointer to "size" many limbs. 23487912Sjlemon The formal parameter isn't mp_srcptr because that causes compiler 2355191Swollman 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