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