Home | History | Annotate | Line # | Download | only in tests
      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-impl.h"
     31 
     32 #include "tests.h"
     33 
     34 
     35 /* Number base for the various trace printing routines.
     36    Set this in main() or with the debugger.
     37    If hexadecimal is going to be fed into GNU bc, remember to use -16
     38    because bc requires upper case.  */
     39 
     40 int  mp_trace_base = 10;
     41 
     42 
     43 void
     44 mp_trace_start (const char *name)
     45 {
     46   if (name != NULL && name[0] != '\0')
     47     printf ("%s=", name);
     48 
     49   switch (ABS (mp_trace_base)) {
     50   case  2: printf ("bin:");                         break;
     51   case  8: printf ("oct:");                         break;
     52   case 10:                                          break;
     53   case 16: printf ("0x");                           break;
     54   default: printf ("base%d:", ABS (mp_trace_base)); break;
     55   }
     56 }
     57 
     58 /* Print "name=value\n" to stdout for an mpq_t value.  */
     59 void
     60 mpq_trace (const char *name, mpq_srcptr q)
     61 {
     62   mp_trace_start (name);
     63   if (q == NULL)
     64     {
     65       printf ("NULL\n");
     66       return;
     67     }
     68 
     69   mpq_out_str (stdout, mp_trace_base, q);
     70   printf ("\n");
     71 }
     72 
     73 
     74 /* Print "name=value\n" to stdout for an mpz_t value.  */
     75 void
     76 mpz_trace (const char *name, mpz_srcptr z)
     77 {
     78   mpq_t      q;
     79   mp_limb_t  one;
     80 
     81   if (z == NULL)
     82     {
     83       mpq_trace (name, NULL);
     84       return;
     85     }
     86 
     87   q->_mp_num._mp_alloc = ALLOC(z);
     88   q->_mp_num._mp_size = SIZ(z);
     89   q->_mp_num._mp_d = PTR(z);
     90 
     91   one = 1;
     92   q->_mp_den._mp_alloc = 1;
     93   q->_mp_den._mp_size = 1;
     94   q->_mp_den._mp_d = &one;
     95 
     96   mpq_trace(name, q);
     97 }
     98 
     99 
    100 /* Print "name=value\n" to stdout for an mpf_t value. */
    101 void
    102 mpf_trace (const char *name, mpf_srcptr f)
    103 {
    104   mp_trace_start (name);
    105   if (f == NULL)
    106     {
    107       printf ("NULL\n");
    108       return;
    109     }
    110 
    111   mpf_out_str (stdout, ABS (mp_trace_base), 0, f);
    112   printf ("\n");
    113 }
    114 
    115 
    116 /* Print "namenum=value\n" to stdout for an mpz_t value.
    117    "name" should have a "%d" to get the number. */
    118 void
    119 mpz_tracen (const char *name, int num, mpz_srcptr z)
    120 {
    121   if (name != NULL && name[0] != '\0')
    122     {
    123       printf (name, num);
    124       putchar ('=');
    125     }
    126   mpz_trace (NULL, z);
    127 }
    128 
    129 
    130 /* Print "name=value\n" to stdout for an mpn style ptr,size. */
    131 void
    132 mpn_trace (const char *name, mp_srcptr ptr, mp_size_t size)
    133 {
    134   mpz_t  z;
    135   if (ptr == NULL)
    136     {
    137       mpz_trace (name, NULL);
    138       return;
    139     }
    140   MPN_NORMALIZE (ptr, size);
    141   PTR(z) = (mp_ptr) ptr;
    142   SIZ(z) = size;
    143   ALLOC(z) = size;
    144   mpz_trace (name, z);
    145 }
    146 
    147 /* Print "name=value\n" to stdout for a limb, nail doesn't have to be zero. */
    148 void
    149 mp_limb_trace (const char *name, mp_limb_t n)
    150 {
    151 #if GMP_NAIL_BITS != 0
    152   mp_limb_t  a[2];
    153   a[0] = n & GMP_NUMB_MASK;
    154   a[1] = n >> GMP_NUMB_BITS;
    155   mpn_trace (name, a, (mp_size_t) 2);
    156 #else
    157   mpn_trace (name, &n, (mp_size_t) 1);
    158 #endif
    159 }
    160 
    161 
    162 /* Print "namenum=value\n" to stdout for an mpn style ptr,size.
    163    "name" should have a "%d" to get the number.  */
    164 void
    165 mpn_tracen (const char *name, int num, mp_srcptr ptr, mp_size_t size)
    166 {
    167   if (name != NULL && name[0] != '\0')
    168     {
    169       printf (name, num);
    170       putchar ('=');
    171     }
    172   mpn_trace (NULL, ptr, size);
    173 }
    174 
    175 
    176 /* Print "namenum=value\n" to stdout for an array of mpn style ptr,size.
    177 
    178    "a" is an array of pointers, each a[i] is a pointer to "size" many limbs.
    179    The formal parameter isn't mp_srcptr because that causes compiler
    180    warnings, but the values aren't modified.
    181 
    182    "name" should have a printf style "%d" to get the array index.  */
    183 
    184 void
    185 mpn_tracea (const char *name, const mp_ptr *a, int count, mp_size_t size)
    186 {
    187   int i;
    188   for (i = 0; i < count; i++)
    189     mpn_tracen (name, i, a[i], size);
    190 }
    191 
    192 
    193 /* Print "value\n" to a file for an mpz_t value.  Any previous contents of
    194    the file are overwritten, so you need different file names each time this
    195    is called.
    196 
    197    Overwriting the file is a feature, it means you get old data replaced
    198    when you run a test program repeatedly.  */
    199 
    200 void
    201 mpn_trace_file (const char *filename, mp_srcptr ptr, mp_size_t size)
    202 {
    203   FILE   *fp;
    204   mpz_t  z;
    205 
    206   fp = fopen (filename, "w");
    207   if (fp == NULL)
    208     {
    209       perror ("fopen");
    210       abort();
    211     }
    212 
    213   MPN_NORMALIZE (ptr, size);
    214   PTR(z) = (mp_ptr) ptr;
    215   SIZ(z) = (int) size;
    216 
    217   mpz_out_str (fp, mp_trace_base, z);
    218   fprintf (fp, "\n");
    219 
    220   if (ferror (fp) || fclose (fp) != 0)
    221     {
    222       printf ("error writing %s\n", filename);
    223       abort();
    224     }
    225 }
    226 
    227 
    228 /* Print "value\n" to a set of files, one file for each element of the given
    229    array of mpn style ptr,size.  Any previous contents of the files are
    230    overwritten, so you need different file names each time this is called.
    231    Each file is "filenameN" where N is 0 to count-1.
    232 
    233    "a" is an array of pointers, each a[i] is a pointer to "size" many limbs.
    234    The formal parameter isn't mp_srcptr because that causes compiler
    235    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 
    242 void
    243 mpn_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 
    263 void
    264 byte_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 
    284 void
    285 byte_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 
    296 void
    297 d_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