Home | History | Annotate | Line # | Download | only in mpz
t-io_raw.c revision 1.1.1.4
      1 /* Test mpz_inp_raw and mpz_out_raw.
      2 
      3 Copyright 2001 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 #include "config.h"
     21 
     22 #include <stdio.h>
     23 #include <stdlib.h>
     24 #include <string.h>
     25 #if HAVE_UNISTD_H
     26 #include <unistd.h>
     27 #endif
     28 
     29 #include "gmp-impl.h"
     30 #include "tests.h"
     31 
     32 #define FILENAME  "t-io_raw.tmp"
     33 
     34 
     35 /* In the fopen, "b" selects binary mode on DOS systems, meaning no
     36    conversion of '\n' to and from CRLF.  It's believed systems without such
     37    nonsense will simply ignore the "b", but in case that's not so a plain
     38    "w+" is attempted if "w+b" fails.  */
     39 
     40 FILE *
     41 fopen_wplusb_or_die (const char *filename)
     42 {
     43   FILE  *fp;
     44   fp = fopen (filename, "w+b");
     45   if (fp == NULL)
     46     fp = fopen (filename, "w+");
     47 
     48   if (fp == NULL)
     49     {
     50       printf ("Cannot create file %s\n", filename);
     51       abort ();
     52     }
     53   return fp;
     54 }
     55 
     56 /* use 0x80 to check nothing bad happens with sign extension etc */
     57 #define BYTEVAL(i)  (((i) + 1) | 0x80)
     58 
     59 void
     60 check_in (void)
     61 {
     62   int        i, j, zeros, neg, error = 0;
     63   mpz_t      want, got;
     64   size_t     want_ret, got_ret;
     65   mp_size_t  size;
     66   FILE       *fp;
     67 
     68   mpz_init (want);
     69   mpz_init (got);
     70 
     71   for (i = 0; i < 32; i++)
     72     {
     73       for (zeros = 0; zeros < 8; zeros++)
     74 	{
     75 	  for (neg = 0; neg <= 1; neg++)
     76 	    {
     77 	      want_ret = i + zeros + 4;
     78 
     79 	      /* need this to get the twos complement right */
     80 	      ASSERT_ALWAYS (sizeof (size) >= 4);
     81 
     82 	      size = i + zeros;
     83 	      if (neg)
     84 		size = -size;
     85 
     86 	      fp = fopen_wplusb_or_die (FILENAME);
     87 	      for (j = 3; j >= 0; j--)
     88 		ASSERT_ALWAYS (putc ((size >> (j*8)) & 0xFF, fp) != EOF);
     89 	      for (j = 0; j < zeros; j++)
     90 		ASSERT_ALWAYS (putc ('\0', fp) != EOF);
     91 	      for (j = 0; j < i; j++)
     92 		ASSERT_ALWAYS (putc (BYTEVAL (j), fp) != EOF);
     93 	      /* and some trailing garbage */
     94 	      ASSERT_ALWAYS (putc ('x', fp) != EOF);
     95 	      ASSERT_ALWAYS (putc ('y', fp) != EOF);
     96 	      ASSERT_ALWAYS (putc ('z', fp) != EOF);
     97 	      ASSERT_ALWAYS (fflush (fp) == 0);
     98 	      rewind (fp);
     99 
    100 	      got_ret = mpz_inp_raw (got, fp);
    101 	      ASSERT_ALWAYS (! ferror(fp));
    102 	      ASSERT_ALWAYS (fclose (fp) == 0);
    103 
    104 	      MPZ_CHECK_FORMAT (got);
    105 
    106 	      if (got_ret != want_ret)
    107 		{
    108 		  printf ("check_in: return value wrong\n");
    109 		  error = 1;
    110 		}
    111 	      if (mpz_cmp (got, want) != 0)
    112 		{
    113 		  printf ("check_in: result wrong\n");
    114 		  error = 1;
    115 		}
    116 	      if (error)
    117 		{
    118 		  printf    ("  i=%d zeros=%d neg=%d\n", i, zeros, neg);
    119 		  printf    ("  got_ret  %lu\n", (unsigned long) got_ret);
    120 		  printf    ("  want_ret %lu\n", (unsigned long) want_ret);
    121 		  mpz_trace ("  got      ", got);
    122 		  mpz_trace ("  want     ", want);
    123 		  abort ();
    124 		}
    125 
    126 	      mpz_neg (want, want);
    127 	    }
    128 	}
    129       mpz_mul_2exp (want, want, 8);
    130       mpz_add_ui (want, want, (unsigned long) BYTEVAL (i));
    131     }
    132 
    133   mpz_clear (want);
    134   mpz_clear (got);
    135 }
    136 
    137 
    138 void
    139 check_out (void)
    140 {
    141   int        i, j, neg, error = 0;
    142   mpz_t      z;
    143   char       want[256], got[256], *p;
    144   size_t     want_len, got_ret, got_read;
    145   mp_size_t  size;
    146   FILE       *fp;
    147 
    148   mpz_init (z);
    149 
    150   for (i = 0; i < 32; i++)
    151     {
    152       for (neg = 0; neg <= 1; neg++)
    153 	{
    154 	  want_len = i + 4;
    155 
    156 	  /* need this to get the twos complement right */
    157 	  ASSERT_ALWAYS (sizeof (size) >= 4);
    158 
    159 	  size = i;
    160 	  if (neg)
    161 	    size = -size;
    162 
    163 	  p = want;
    164 	  for (j = 3; j >= 0; j--)
    165 	    *p++ = size >> (j*8);
    166 	  for (j = 0; j < i; j++)
    167 	    *p++ = BYTEVAL (j);
    168 	  ASSERT_ALWAYS (p <= want + sizeof (want));
    169 
    170 	  fp = fopen_wplusb_or_die (FILENAME);
    171 	  got_ret = mpz_out_raw (fp, z);
    172 	  ASSERT_ALWAYS (fflush (fp) == 0);
    173 	  rewind (fp);
    174 	  got_read = fread (got, 1, sizeof(got), fp);
    175 	  ASSERT_ALWAYS (! ferror(fp));
    176 	  ASSERT_ALWAYS (fclose (fp) == 0);
    177 
    178 	  if (got_ret != want_len)
    179 	    {
    180 	      printf ("check_out: wrong return value\n");
    181 	      error = 1;
    182 	    }
    183 	  if (got_read != want_len)
    184 	    {
    185 	      printf ("check_out: wrong number of bytes read back\n");
    186 	      error = 1;
    187 	    }
    188 	  if (memcmp (want, got, want_len) != 0)
    189 	    {
    190 	      printf ("check_out: wrong data\n");
    191 	      error = 1;
    192 	    }
    193 	  if (error)
    194 	    {
    195 	      printf    ("  i=%d neg=%d\n", i, neg);
    196 	      mpz_trace ("  z", z);
    197 	      printf    ("  got_ret  %lu\n", (unsigned long) got_ret);
    198 	      printf    ("  got_read %lu\n", (unsigned long) got_read);
    199 	      printf    ("  want_len %lu\n", (unsigned long) want_len);
    200 	      printf    ("  want");
    201 	      for (j = 0; j < want_len; j++)
    202 		printf (" %02X", (unsigned) (unsigned char) want[j]);
    203 	      printf    ("\n");
    204 	      printf    ("  got ");
    205 	      for (j = 0; j < want_len; j++)
    206 		printf (" %02X", (unsigned) (unsigned char) got[j]);
    207 	      printf    ("\n");
    208 	      abort ();
    209 	    }
    210 
    211 	  mpz_neg (z, z);
    212 	}
    213       mpz_mul_2exp (z, z, 8);
    214       mpz_add_ui (z, z, (unsigned long) BYTEVAL (i));
    215     }
    216 
    217   mpz_clear (z);
    218 }
    219 
    220 
    221 void
    222 check_rand (void)
    223 {
    224   gmp_randstate_ptr  rands = RANDS;
    225   int        i, error = 0;
    226   mpz_t      got, want;
    227   size_t     inp_ret, out_ret;
    228   FILE       *fp;
    229 
    230   mpz_init (want);
    231   mpz_init (got);
    232 
    233   for (i = 0; i < 500; i++)
    234     {
    235       mpz_erandomb (want, rands, 10*GMP_LIMB_BITS);
    236       mpz_negrandom (want, rands);
    237 
    238       fp = fopen_wplusb_or_die (FILENAME);
    239       out_ret = mpz_out_raw (fp, want);
    240       ASSERT_ALWAYS (fflush (fp) == 0);
    241       rewind (fp);
    242       inp_ret = mpz_inp_raw (got, fp);
    243       ASSERT_ALWAYS (fclose (fp) == 0);
    244 
    245       MPZ_CHECK_FORMAT (got);
    246 
    247       if (inp_ret != out_ret)
    248 	{
    249 	  printf ("check_rand: different inp/out return values\n");
    250 	  error = 1;
    251 	}
    252       if (mpz_cmp (got, want) != 0)
    253 	{
    254 	  printf ("check_rand: wrong result\n");
    255 	  error = 1;
    256 	}
    257       if (error)
    258 	{
    259 	  printf    ("  out_ret %lu\n", (unsigned long) out_ret);
    260 	  printf    ("  inp_ret %lu\n", (unsigned long) inp_ret);
    261 	  mpz_trace ("  want", want);
    262 	  mpz_trace ("  got ", got);
    263 	  abort ();
    264 	}
    265     }
    266 
    267   mpz_clear (got);
    268   mpz_clear (want);
    269 }
    270 
    271 
    272 int
    273 main (void)
    274 {
    275   tests_start ();
    276   mp_trace_base = -16;
    277 
    278   check_in ();
    279   check_out ();
    280   check_rand ();
    281 
    282   unlink (FILENAME);
    283   tests_end ();
    284 
    285   exit (0);
    286 }
    287