Home | History | Annotate | Line # | Download | only in tests
trace.c revision 1.1.1.3
      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 }
    319