Blame tests/trace.c

Packit 5c3484
/* Support for diagnostic traces.
Packit 5c3484
Packit 5c3484
Copyright 1999-2005 Free Software Foundation, Inc.
Packit 5c3484
Packit 5c3484
This file is part of the GNU MP Library test suite.
Packit 5c3484
Packit 5c3484
The GNU MP Library test suite is free software; you can redistribute it
Packit 5c3484
and/or modify it under the terms of the GNU General Public License as
Packit 5c3484
published by the Free Software Foundation; either version 3 of the License,
Packit 5c3484
or (at your option) any later version.
Packit 5c3484
Packit 5c3484
The GNU MP Library test suite is distributed in the hope that it will be
Packit 5c3484
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 5c3484
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
Packit 5c3484
Public License for more details.
Packit 5c3484
Packit 5c3484
You should have received a copy of the GNU General Public License along with
Packit 5c3484
the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
Packit 5c3484
Packit 5c3484
Packit 5c3484
/* Future: Would like commas printed between limbs in hex or binary, but
Packit 5c3484
   perhaps not always since it might upset cutting and pasting into bc or
Packit 5c3484
   whatever.  */
Packit 5c3484
Packit 5c3484
Packit 5c3484
#include <stdio.h>
Packit 5c3484
#include <stdlib.h>
Packit 5c3484
#include <string.h> /* for strlen */
Packit 5c3484
Packit 5c3484
#include "gmp.h"
Packit 5c3484
#include "gmp-impl.h"
Packit 5c3484
Packit 5c3484
#include "tests.h"
Packit 5c3484
Packit 5c3484
Packit 5c3484
/* Number base for the various trace printing routines.
Packit 5c3484
   Set this in main() or with the debugger.
Packit 5c3484
   If hexadecimal is going to be fed into GNU bc, remember to use -16
Packit 5c3484
   because bc requires upper case.  */
Packit 5c3484
Packit 5c3484
int  mp_trace_base = 10;
Packit 5c3484
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
mp_trace_start (const char *name)
Packit 5c3484
{
Packit 5c3484
  if (name != NULL && name[0] != '\0')
Packit 5c3484
    printf ("%s=", name);
Packit 5c3484
Packit 5c3484
  switch (ABS (mp_trace_base)) {
Packit 5c3484
  case  2: printf ("bin:");                         break;
Packit 5c3484
  case  8: printf ("oct:");                         break;
Packit 5c3484
  case 10:                                          break;
Packit 5c3484
  case 16: printf ("0x");                           break;
Packit 5c3484
  default: printf ("base%d:", ABS (mp_trace_base)); break;
Packit 5c3484
  }
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
/* Print "name=value\n" to stdout for an mpq_t value.  */
Packit 5c3484
void
Packit 5c3484
mpq_trace (const char *name, mpq_srcptr q)
Packit 5c3484
{
Packit 5c3484
  mp_trace_start (name);
Packit 5c3484
  if (q == NULL)
Packit 5c3484
    {
Packit 5c3484
      printf ("NULL\n");
Packit 5c3484
      return;
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  mpq_out_str (stdout, mp_trace_base, q);
Packit 5c3484
  printf ("\n");
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
Packit 5c3484
/* Print "name=value\n" to stdout for an mpz_t value.  */
Packit 5c3484
void
Packit 5c3484
mpz_trace (const char *name, mpz_srcptr z)
Packit 5c3484
{
Packit 5c3484
  mpq_t      q;
Packit 5c3484
  mp_limb_t  one;
Packit 5c3484
Packit 5c3484
  if (z == NULL)
Packit 5c3484
    {
Packit 5c3484
      mpq_trace (name, NULL);
Packit 5c3484
      return;
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  q->_mp_num._mp_alloc = ALLOC(z);
Packit 5c3484
  q->_mp_num._mp_size = SIZ(z);
Packit 5c3484
  q->_mp_num._mp_d = PTR(z);
Packit 5c3484
Packit 5c3484
  one = 1;
Packit 5c3484
  q->_mp_den._mp_alloc = 1;
Packit 5c3484
  q->_mp_den._mp_size = 1;
Packit 5c3484
  q->_mp_den._mp_d = &on;;
Packit 5c3484
Packit 5c3484
  mpq_trace(name, q);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
Packit 5c3484
/* Print "name=value\n" to stdout for an mpf_t value. */
Packit 5c3484
void
Packit 5c3484
mpf_trace (const char *name, mpf_srcptr f)
Packit 5c3484
{
Packit 5c3484
  mp_trace_start (name);
Packit 5c3484
  if (f == NULL)
Packit 5c3484
    {
Packit 5c3484
      printf ("NULL\n");
Packit 5c3484
      return;
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  mpf_out_str (stdout, ABS (mp_trace_base), 0, f);
Packit 5c3484
  printf ("\n");
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
Packit 5c3484
/* Print "namenum=value\n" to stdout for an mpz_t value.
Packit 5c3484
   "name" should have a "%d" to get the number. */
Packit 5c3484
void
Packit 5c3484
mpz_tracen (const char *name, int num, mpz_srcptr z)
Packit 5c3484
{
Packit 5c3484
  if (name != NULL && name[0] != '\0')
Packit 5c3484
    {
Packit 5c3484
      printf (name, num);
Packit 5c3484
      putchar ('=');
Packit 5c3484
    }
Packit 5c3484
  mpz_trace (NULL, z);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
Packit 5c3484
/* Print "name=value\n" to stdout for an mpn style ptr,size. */
Packit 5c3484
void
Packit 5c3484
mpn_trace (const char *name, mp_srcptr ptr, mp_size_t size)
Packit 5c3484
{
Packit 5c3484
  mpz_t  z;
Packit 5c3484
  if (ptr == NULL)
Packit 5c3484
    {
Packit 5c3484
      mpz_trace (name, NULL);
Packit 5c3484
      return;
Packit 5c3484
    }
Packit 5c3484
  MPN_NORMALIZE (ptr, size);
Packit 5c3484
  PTR(z) = (mp_ptr) ptr;
Packit 5c3484
  SIZ(z) = size;
Packit 5c3484
  ALLOC(z) = size;
Packit 5c3484
  mpz_trace (name, z);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
/* Print "name=value\n" to stdout for a limb, nail doesn't have to be zero. */
Packit 5c3484
void
Packit 5c3484
mp_limb_trace (const char *name, mp_limb_t n)
Packit 5c3484
{
Packit 5c3484
#if GMP_NAIL_BITS != 0
Packit 5c3484
  mp_limb_t  a[2];
Packit 5c3484
  a[0] = n & GMP_NUMB_MASK;
Packit 5c3484
  a[1] = n >> GMP_NUMB_BITS;
Packit 5c3484
  mpn_trace (name, a, (mp_size_t) 2);
Packit 5c3484
#else
Packit 5c3484
  mpn_trace (name, &n, (mp_size_t) 1);
Packit 5c3484
#endif
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
Packit 5c3484
/* Print "namenum=value\n" to stdout for an mpn style ptr,size.
Packit 5c3484
   "name" should have a "%d" to get the number.  */
Packit 5c3484
void
Packit 5c3484
mpn_tracen (const char *name, int num, mp_srcptr ptr, mp_size_t size)
Packit 5c3484
{
Packit 5c3484
  if (name != NULL && name[0] != '\0')
Packit 5c3484
    {
Packit 5c3484
      printf (name, num);
Packit 5c3484
      putchar ('=');
Packit 5c3484
    }
Packit 5c3484
  mpn_trace (NULL, ptr, size);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
Packit 5c3484
/* Print "namenum=value\n" to stdout for an array of mpn style ptr,size.
Packit 5c3484
Packit 5c3484
   "a" is an array of pointers, each a[i] is a pointer to "size" many limbs.
Packit 5c3484
   The formal parameter isn't mp_srcptr because that causes compiler
Packit 5c3484
   warnings, but the values aren't modified.
Packit 5c3484
Packit 5c3484
   "name" should have a printf style "%d" to get the array index.  */
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
mpn_tracea (const char *name, const mp_ptr *a, int count, mp_size_t size)
Packit 5c3484
{
Packit 5c3484
  int i;
Packit 5c3484
  for (i = 0; i < count; i++)
Packit 5c3484
    mpn_tracen (name, i, a[i], size);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
Packit 5c3484
/* Print "value\n" to a file for an mpz_t value.  Any previous contents of
Packit 5c3484
   the file are overwritten, so you need different file names each time this
Packit 5c3484
   is called.
Packit 5c3484
Packit 5c3484
   Overwriting the file is a feature, it means you get old data replaced
Packit 5c3484
   when you run a test program repeatedly.  */
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
mpn_trace_file (const char *filename, mp_srcptr ptr, mp_size_t size)
Packit 5c3484
{
Packit 5c3484
  FILE   *fp;
Packit 5c3484
  mpz_t  z;
Packit 5c3484
Packit 5c3484
  fp = fopen (filename, "w");
Packit 5c3484
  if (fp == NULL)
Packit 5c3484
    {
Packit 5c3484
      perror ("fopen");
Packit 5c3484
      abort();
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  MPN_NORMALIZE (ptr, size);
Packit 5c3484
  PTR(z) = (mp_ptr) ptr;
Packit 5c3484
  SIZ(z) = (int) size;
Packit 5c3484
Packit 5c3484
  mpz_out_str (fp, mp_trace_base, z);
Packit 5c3484
  fprintf (fp, "\n");
Packit 5c3484
Packit 5c3484
  if (ferror (fp) || fclose (fp) != 0)
Packit 5c3484
    {
Packit 5c3484
      printf ("error writing %s\n", filename);
Packit 5c3484
      abort();
Packit 5c3484
    }
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
Packit 5c3484
/* Print "value\n" to a set of files, one file for each element of the given
Packit 5c3484
   array of mpn style ptr,size.  Any previous contents of the files are
Packit 5c3484
   overwritten, so you need different file names each time this is called.
Packit 5c3484
   Each file is "filenameN" where N is 0 to count-1.
Packit 5c3484
Packit 5c3484
   "a" is an array of pointers, each a[i] is a pointer to "size" many limbs.
Packit 5c3484
   The formal parameter isn't mp_srcptr because that causes compiler
Packit 5c3484
   warnings, but the values aren't modified.
Packit 5c3484
Packit 5c3484
   Overwriting the files is a feature, it means you get old data replaced
Packit 5c3484
   when you run a test program repeatedly.  The output style isn't
Packit 5c3484
   particularly pretty, but at least it gets something out, and you can cat
Packit 5c3484
   the files into bc, or whatever. */
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
mpn_tracea_file (const char *filename,
Packit 5c3484
                 const mp_ptr *a, int count, mp_size_t size)
Packit 5c3484
{
Packit 5c3484
  char  *s;
Packit 5c3484
  int   i;
Packit 5c3484
  TMP_DECL;
Packit 5c3484
Packit 5c3484
  TMP_MARK;
Packit 5c3484
  s = (char *) TMP_ALLOC (strlen (filename) + 50);
Packit 5c3484
Packit 5c3484
  for (i = 0; i < count; i++)
Packit 5c3484
    {
Packit 5c3484
      sprintf (s, "%s%d", filename, i);
Packit 5c3484
      mpn_trace_file (s, a[i], size);
Packit 5c3484
    }
Packit 5c3484
Packit 5c3484
  TMP_FREE;
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
byte_trace (const char *name, const void *ptr, mp_size_t size)
Packit 5c3484
{
Packit 5c3484
  const char *fmt;
Packit 5c3484
  mp_size_t  i;
Packit 5c3484
Packit 5c3484
  mp_trace_start (name);
Packit 5c3484
Packit 5c3484
  switch (mp_trace_base) {
Packit 5c3484
  case   8: fmt = " %o"; break;
Packit 5c3484
  case  10: fmt = " %d"; break;
Packit 5c3484
  case  16: fmt = " %x"; break;
Packit 5c3484
  case -16: fmt = " %X"; break;
Packit 5c3484
  default: printf ("Oops, unsupported base in byte_trace\n"); abort (); break;
Packit 5c3484
  }
Packit 5c3484
Packit 5c3484
  for (i = 0; i < size; i++)
Packit 5c3484
    printf (fmt, (int) ((unsigned char *) ptr)[i]);
Packit 5c3484
  printf ("\n");
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
byte_tracen (const char *name, int num, const void *ptr, mp_size_t size)
Packit 5c3484
{
Packit 5c3484
  if (name != NULL && name[0] != '\0')
Packit 5c3484
    {
Packit 5c3484
      printf (name, num);
Packit 5c3484
      putchar ('=');
Packit 5c3484
    }
Packit 5c3484
  byte_trace (NULL, ptr, size);
Packit 5c3484
}
Packit 5c3484
Packit 5c3484
Packit 5c3484
void
Packit 5c3484
d_trace (const char *name, double d)
Packit 5c3484
{
Packit 5c3484
  union {
Packit 5c3484
    double         d;
Packit 5c3484
    unsigned char  b[sizeof(double)];
Packit 5c3484
  } u;
Packit 5c3484
  int  i;
Packit 5c3484
Packit 5c3484
  if (name != NULL && name[0] != '\0')
Packit 5c3484
    printf ("%s=", name);
Packit 5c3484
Packit 5c3484
  u.d = d;
Packit 5c3484
  printf ("[");
Packit 5c3484
  for (i = 0; i < sizeof (u.b); i++)
Packit 5c3484
    {
Packit 5c3484
      if (i != 0)
Packit 5c3484
        printf (" ");
Packit 5c3484
      printf ("%02X", (int) u.b[i]);
Packit 5c3484
    }
Packit 5c3484
  printf ("] %.20g\n", d);
Packit 5c3484
}