xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpz/t-io_raw.c (revision 72c7faa4dbb41dbb0238d6b4a109da0d4b236dd4)
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 *
fopen_wplusb_or_die(const char * filename)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
check_in(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
check_out(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
check_rand(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
main(void)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