1139823Simp/* Support for diagnostic traces.
25191Swollman
35191SwollmanCopyright 1999-2005 Free Software Foundation, Inc.
45191Swollman
55191SwollmanThis file is part of the GNU MP Library test suite.
65191Swollman
75191SwollmanThe GNU MP Library test suite is free software; you can redistribute it
85191Swollmanand/or modify it under the terms of the GNU General Public License as
95191Swollmanpublished by the Free Software Foundation; either version 3 of the License,
105191Swollmanor (at your option) any later version.
115191Swollman
125191SwollmanThe GNU MP Library test suite is distributed in the hope that it will be
135191Swollmanuseful, but WITHOUT ANY WARRANTY; without even the implied warranty of
145191SwollmanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
155191SwollmanPublic License for more details.
165191Swollman
175191SwollmanYou should have received a copy of the GNU General Public License along with
185191Swollmanthe GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
195191Swollman
205191Swollman
215191Swollman/* Future: Would like commas printed between limbs in hex or binary, but
225191Swollman   perhaps not always since it might upset cutting and pasting into bc or
235191Swollman   whatever.  */
245191Swollman
255191Swollman
265191Swollman#include <stdio.h>
275191Swollman#include <stdlib.h>
285191Swollman#include <string.h> /* for strlen */
295191Swollman
3050477Speter#include "gmp-impl.h"
315191Swollman
325191Swollman#include "tests.h"
335191Swollman
345191Swollman
355191Swollman/* Number base for the various trace printing routines.
365191Swollman   Set this in main() or with the debugger.
375191Swollman   If hexadecimal is going to be fed into GNU bc, remember to use -16
385191Swollman   because bc requires upper case.  */
395191Swollman
405191Swollmanint  mp_trace_base = 10;
4197290Sbrooks
4271862Speter
435191Swollmanvoid
445191Swollmanmp_trace_start (const char *name)
4524204Sbde{
465191Swollman  if (name != NULL && name[0] != '\0')
475191Swollman    printf ("%s=", name);
48130933Sbrooks
495191Swollman  switch (ABS (mp_trace_base)) {
505191Swollman  case  2: printf ("bin:");                         break;
515191Swollman  case  8: printf ("oct:");                         break;
525191Swollman  case 10:                                          break;
5332350Seivind  case 16: printf ("0x");                           break;
5454263Sshin  default: printf ("base%d:", ABS (mp_trace_base)); break;
555191Swollman  }
565191Swollman}
575191Swollman
585191Swollman/* Print "name=value\n" to stdout for an mpq_t value.  */
595191Swollmanvoid
605191Swollmanmpq_trace (const char *name, mpq_srcptr q)
615191Swollman{
6297290Sbrooks  mp_trace_start (name);
6310429Sbde  if (q == NULL)
6497290Sbrooks    {
65147256Sbrooks      printf ("NULL\n");
6697290Sbrooks      return;
675191Swollman    }
6897290Sbrooks
6997290Sbrooks  mpq_out_str (stdout, mp_trace_base, q);
7097290Sbrooks  printf ("\n");
7197290Sbrooks}
7297290Sbrooks
7397290Sbrooks
7497290Sbrooks/* Print "name=value\n" to stdout for an mpz_t value.  */
7597290Sbrooksvoid
7697290Sbrooksmpz_trace (const char *name, mpz_srcptr z)
77130933Sbrooks{
78130933Sbrooks  mpq_t      q;
7997290Sbrooks  mp_limb_t  one;
8097290Sbrooks
815191Swollman  if (z == NULL)
8297290Sbrooks    {
8397290Sbrooks      mpq_trace (name, NULL);
845191Swollman      return;
85131670Sbms    }
86147256Sbrooks
87147256Sbrooks  q->_mp_num._mp_alloc = ALLOC(z);
88147256Sbrooks  q->_mp_num._mp_size = SIZ(z);
89147256Sbrooks  q->_mp_num._mp_d = PTR(z);
90147256Sbrooks
9197290Sbrooks  one = 1;
9297290Sbrooks  q->_mp_den._mp_alloc = 1;
93121816Sbrooks  q->_mp_den._mp_size = 1;
945191Swollman  q->_mp_den._mp_d = &one;
955191Swollman
96152308Sglebius  mpq_trace(name, q);
9741757Seivind}
9841757Seivind
995191Swollman
1005191Swollman/* Print "name=value\n" to stdout for an mpf_t value. */
10153115Sphkvoid
1025191Swollmanmpf_trace (const char *name, mpf_srcptr f)
103147611Sdwmalone{
10497290Sbrooks  mp_trace_start (name);
10597290Sbrooks  if (f == NULL)
1065191Swollman    {
1075191Swollman      printf ("NULL\n");
10897290Sbrooks      return;
10997290Sbrooks    }
11097290Sbrooks
11197290Sbrooks  mpf_out_str (stdout, ABS (mp_trace_base), 0, f);
11297290Sbrooks  printf ("\n");
11397290Sbrooks}
11497290Sbrooks
115151266Sthompsa
116151266Sthompsa/* Print "namenum=value\n" to stdout for an mpz_t value.
117151266Sthompsa   "name" should have a "%d" to get the number. */
118151266Sthompsavoid
119151266Sthompsampz_tracen (const char *name, int num, mpz_srcptr z)
12097290Sbrooks{
12197290Sbrooks  if (name != NULL && name[0] != '\0')
1225191Swollman    {
123131669Sbms      printf (name, num);
124126777Srwatson      putchar ('=');
125126777Srwatson    }
126131669Sbms  mpz_trace (NULL, z);
127131669Sbms}
12897290Sbrooks
129131669Sbms
130131669Sbms/* Print "name=value\n" to stdout for an mpn style ptr,size. */
13197290Sbrooksvoid
13297290Sbrooksmpn_trace (const char *name, mp_srcptr ptr, mp_size_t size)
133132199Sphk{
134132199Sphk  mpz_t  z;
135131669Sbms  if (ptr == NULL)
136131669Sbms    {
137131669Sbms      mpz_trace (name, NULL);
13871862Speter      return;
139131669Sbms    }
140131669Sbms  MPN_NORMALIZE (ptr, size);
141131669Sbms  PTR(z) = (mp_ptr) ptr;
14271862Speter  SIZ(z) = size;
143131669Sbms  ALLOC(z) = size;
14471862Speter  mpz_trace (name, z);
14571862Speter}
14671862Speter
14771862Speter/* Print "name=value\n" to stdout for a limb, nail doesn't have to be zero. */
14878351Smarkmvoid
14978351Smarkmmp_limb_trace (const char *name, mp_limb_t n)
1505191Swollman{
151147611Sdwmalone#if GMP_NAIL_BITS != 0
152131669Sbms  mp_limb_t  a[2];
153113255Sdes  a[0] = n & GMP_NUMB_MASK;
154131669Sbms  a[1] = n >> GMP_NUMB_BITS;
155147611Sdwmalone  mpn_trace (name, a, (mp_size_t) 2);
15610957Swollman#else
157147611Sdwmalone  mpn_trace (name, &n, (mp_size_t) 1);
158147611Sdwmalone#endif
15910957Swollman}
16010957Swollman
16197290Sbrooks
1625191Swollman/* Print "namenum=value\n" to stdout for an mpn style ptr,size.
163123922Ssam   "name" should have a "%d" to get the number.  */
1645191Swollmanvoid
1655191Swollmanmpn_tracen (const char *name, int num, mp_srcptr ptr, mp_size_t size)
1665191Swollman{
1675191Swollman  if (name != NULL && name[0] != '\0')
1685191Swollman    {
1695191Swollman      printf (name, num);
1705191Swollman      putchar ('=');
171131669Sbms    }
1725191Swollman  mpn_trace (NULL, ptr, size);
1735191Swollman}
1745191Swollman
1755191Swollman
17685074Sru/* Print "namenum=value\n" to stdout for an array of mpn style ptr,size.
1775191Swollman
178120727Ssam   "a" is an array of pointers, each a[i] is a pointer to "size" many limbs.
179142352Ssam   The formal parameter isn't mp_srcptr because that causes compiler
1805191Swollman   warnings, but the values aren't modified.
1815191Swollman
1825191Swollman   "name" should have a printf style "%d" to get the array index.  */
1835191Swollman
1845191Swollmanvoid
18512611Sbdempn_tracea (const char *name, const mp_ptr *a, int count, mp_size_t size)
18678351Smarkm{
1875191Swollman  int i;
18878351Smarkm  for (i = 0; i < count; i++)
18978351Smarkm    mpn_tracen (name, i, a[i], size);
19078351Smarkm}
1915191Swollman
1925191Swollman
1935191Swollman/* Print "value\n" to a file for an mpz_t value.  Any previous contents of
1945191Swollman   the file are overwritten, so you need different file names each time this
1955191Swollman   is called.
1965191Swollman
1975191Swollman   Overwriting the file is a feature, it means you get old data replaced
19841757Seivind   when you run a test program repeatedly.  */
1995191Swollman
2005191Swollmanvoid
2015191Swollmanmpn_trace_file (const char *filename, mp_srcptr ptr, mp_size_t size)
2025191Swollman{
2035191Swollman  FILE   *fp;
2045191Swollman  mpz_t  z;
2055191Swollman
2065191Swollman  fp = fopen (filename, "w");
2075191Swollman  if (fp == NULL)
2085191Swollman    {
2095191Swollman      perror ("fopen");
2105191Swollman      abort();
2115191Swollman    }
2125191Swollman
2135191Swollman  MPN_NORMALIZE (ptr, size);
2145191Swollman  PTR(z) = (mp_ptr) ptr;
2155191Swollman  SIZ(z) = (int) size;
21654263Sshin
21754263Sshin  mpz_out_str (fp, mp_trace_base, z);
21854263Sshin  fprintf (fp, "\n");
21954263Sshin
2205191Swollman  if (ferror (fp) || fclose (fp) != 0)
2215191Swollman    {
2225191Swollman      printf ("error writing %s\n", filename);
2235191Swollman      abort();
2245191Swollman    }
2255191Swollman}
2265191Swollman
2275191Swollman
2285191Swollman/* Print "value\n" to a set of files, one file for each element of the given
2295191Swollman   array of mpn style ptr,size.  Any previous contents of the files are
2305191Swollman   overwritten, so you need different file names each time this is called.
2315191Swollman   Each file is "filenameN" where N is 0 to count-1.
2325191Swollman
2335191Swollman   "a" is an array of pointers, each a[i] is a pointer to "size" many limbs.
23487912Sjlemon   The formal parameter isn't mp_srcptr because that causes compiler
2355191Swollman   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
242void
243mpn_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
263void
264byte_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
284void
285byte_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
296void
297d_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