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