github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/trace.c (about)

     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  }