(root)/
gmp-6.3.0/
tests/
trace.c
       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  }