xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tfpif.c (revision d90047b5d07facf36e6c01dcc0bded8997ce9cc2)
1 /* Test file for mpfr_fpif.
2 
3 Copyright 2012-2018 Free Software Foundation, Inc.
4 Contributed by Olivier Demengeon.
5 
6 This file is part of the GNU MPFR Library.
7 
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
16 License for more details.
17 
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
20 http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22 
23 #include "mpfr-test.h"
24 
25 #define FILE_NAME_RW "tfpif_rw.dat" /* temporary name (written then read) */
26 #define FILE_NAME_R  "tfpif_r1.dat" /* fixed file name (read only) */
27 #define FILE_NAME_R2 "tfpif_r2.dat" /* fixed file name (read only) with a
28                                        precision > MPFR_PREC_MAX */
29 
30 static void
31 doit (int argc, char *argv[], mpfr_prec_t p1, mpfr_prec_t p2)
32 {
33   char *filenameCompressed = FILE_NAME_RW;
34   char *data = FILE_NAME_R;
35   int status;
36   FILE *fh;
37   mpfr_t x[9];
38   mpfr_t y;
39   int i, neg;
40   long pos;
41 
42   mpfr_init2 (x[0], p1);
43   mpfr_init2 (x[8], p1);
44   mpfr_inits2 (p2, x[1], x[2], x[3], x[4], x[5], x[6], x[7], (mpfr_ptr) 0);
45   mpfr_set_str1 (x[0], "45.2564215000000018562786863185465335845947265625");
46   mpfr_set_str1 (x[1], "45.2564215000000018562786863185465335845947265625");
47   mpfr_set_str1 (x[2], "45.2564215000000018562786863185465335845947265625");
48   mpfr_set_exp (x[2], -48000);
49   mpfr_set_inf (x[3], 1);
50   mpfr_set_zero (x[4], 1);
51   mpfr_set_nan (x[5]);
52   mpfr_set_ui (x[6], 104348, MPFR_RNDN);
53   mpfr_set_ui (x[7], 33215, MPFR_RNDN);
54   mpfr_div (x[8], x[6], x[7], MPFR_RNDN);
55   mpfr_div (x[6], x[6], x[7], MPFR_RNDN);
56 
57   /* we first write to file FILE_NAME_RW the numbers x[i] */
58   fh = fopen (filenameCompressed, "w");
59   if (fh == NULL)
60     {
61       printf ("Failed to open for writing %s\n", filenameCompressed);
62       exit (1);
63     }
64 
65   for (neg = 0; neg < 2; neg++)
66     for (i = 0; i < 9; i++)
67       {
68         if (neg)
69           MPFR_CHANGE_SIGN (x[i]);
70 
71         status = mpfr_fpif_export (fh, x[i]);
72         if (status != 0)
73           {
74             fclose (fh);
75             printf ("Failed to export number %d, neg=%d\n", i, neg);
76             exit (1);
77           }
78 
79         if (neg)
80           MPFR_CHANGE_SIGN (x[i]);
81       }
82 
83   fclose (fh);
84 
85   /* we then read back FILE_NAME_RW and check we get the same numbers x[i] */
86   fh = fopen (filenameCompressed, "r");
87   if (fh == NULL)
88     {
89       printf ("Failed to open for reading %s\n", filenameCompressed);
90       exit (1);
91     }
92 
93   for (neg = 0; neg < 2; neg++)
94     for (i = 0; i < 9; i++)
95       {
96         mpfr_prec_t px, py;
97 
98         if (neg)
99           MPFR_CHANGE_SIGN (x[i]);
100 
101         mpfr_init2 (y, 2);
102         /* Set the sign bit of y to the opposite of the expected one.
103            Thus, if mpfr_fpif_import forgets to set the sign, this will
104            be detected. */
105         MPFR_SET_SIGN (y, - MPFR_SIGN (x[i]));
106         mpfr_fpif_import (y, fh);
107         px = mpfr_get_prec (x[i]);
108         py = mpfr_get_prec (y);
109         if (px != py)
110           {
111             printf ("doit failed on written number %d, neg=%d:"
112                     " bad precision\n", i, neg);
113             printf ("expected %ld\n", (long) px);
114             printf ("got      %ld\n", (long) py);
115             exit (1);
116           }
117         if (MPFR_SIGN (x[i]) != MPFR_SIGN (y))
118           {
119             printf ("doit failed on written number %d, neg=%d:"
120                     " bad sign\n", i, neg);
121             printf ("expected %d\n", (int) MPFR_SIGN (x[i]));
122             printf ("got      %d\n", (int) MPFR_SIGN (y));
123             exit (1);
124           }
125         if (! SAME_VAL (x[i], y))
126           {
127             printf ("doit failed on written number %d, neg=%d\n", i, neg);
128             printf ("expected "); mpfr_dump (x[i]);
129             printf ("got      "); mpfr_dump (y);
130             exit (1);
131           }
132         mpfr_clear (y);
133 
134         if (neg)
135           MPFR_CHANGE_SIGN (x[i]);
136       }
137   fclose (fh);
138 
139   /* we do the same for the fixed file FILE_NAME_R, this ensures
140      we get same results with different word size or endianness */
141   fh = src_fopen (data, "r");
142   if (fh == NULL)
143     {
144       printf ("Failed to open for reading %s in srcdir\n", data);
145       exit (1);
146     }
147 
148   /* the fixed file FILE_NAME_R assumes p1=130 and p2=2048 */
149   for (i = 0; i < 9 && (p1 == 130 && p2 == 2048); i++)
150     {
151       mpfr_prec_t px, py;
152 
153       mpfr_init2 (y, 2);
154       /* Set the sign bit of y to the opposite of the expected one.
155          Thus, if mpfr_fpif_import forgets to set the sign, this will
156          be detected. */
157       MPFR_SET_SIGN (y, - MPFR_SIGN (x[i]));
158       pos = ftell (fh);
159       mpfr_fpif_import (y, fh);
160       px = mpfr_get_prec (x[i]);
161       py = mpfr_get_prec (y);
162       if (px != py)
163         {
164           printf ("doit failed on data number %d, neg=%d:"
165                   " bad precision\n", i, neg);
166           printf ("expected %ld\n", (long) px);
167           printf ("got      %ld\n", (long) py);
168           exit (1);
169         }
170       if (MPFR_SIGN (x[i]) != MPFR_SIGN (y))
171         {
172           printf ("doit failed on data number %d, neg=%d:"
173                   " bad sign\n", i, neg);
174           printf ("expected %d\n", (int) MPFR_SIGN (x[i]));
175           printf ("got      %d\n", (int) MPFR_SIGN (y));
176           exit (1);
177         }
178       if (! SAME_VAL (x[i], y))
179         {
180           printf ("doit failed on data number %d, neg=%d, at offset 0x%lx\n",
181                   i, neg, (unsigned long) pos);
182           printf ("expected "); mpfr_dump (x[i]);
183           printf ("got      "); mpfr_dump (y);
184           exit (1);
185         }
186       mpfr_clear (y);
187     }
188   fclose (fh);
189 
190   for (i = 0; i < 9; i++)
191     mpfr_clear (x[i]);
192 
193   remove (filenameCompressed);
194 }
195 
196 static void
197 check_bad (void)
198 {
199   char *filenameCompressed = FILE_NAME_RW;
200   int status;
201   FILE *fh;
202   mpfr_t x;
203   unsigned char badData[6][2] =
204     { { 7, 0 }, { 16, 0 }, { 23, 118 }, { 23, 95 }, { 23, 127 }, { 23, 47 } };
205   int badDataSize[6] = { 1, 1, 2, 2, 2, 2 };
206   int i;
207 
208   mpfr_init2 (x, 2);
209   status = mpfr_fpif_export (NULL, x);
210   if (status == 0)
211     {
212       printf ("mpfr_fpif_export did not fail with a NULL file\n");
213       exit(1);
214     }
215   status = mpfr_fpif_import (x, NULL);
216   if (status == 0)
217     {
218       printf ("mpfr_fpif_import did not fail with a NULL file\n");
219       exit(1);
220     }
221 
222   fh = fopen (filenameCompressed, "w+");
223   if (fh == NULL)
224     {
225       printf ("Failed to open for reading/writing %s, exiting...\n",
226             filenameCompressed);
227       fclose (fh);
228       remove (filenameCompressed);
229       exit (1);
230     }
231   status = mpfr_fpif_import (x, fh);
232   if (status == 0)
233     {
234       printf ("mpfr_fpif_import did not fail on a empty file\n");
235       fclose (fh);
236       remove (filenameCompressed);
237       exit(1);
238     }
239 
240   for (i = 0; i < 6; i++)
241     {
242       rewind (fh);
243       status = fwrite (&badData[i][0], badDataSize[i], 1, fh);
244       if (status != 1)
245         {
246           printf ("Write error on the test file\n");
247           fclose (fh);
248           remove (filenameCompressed);
249           exit(1);
250         }
251       rewind (fh);
252       status = mpfr_fpif_import (x, fh);
253       if (status == 0)
254         {
255           printf ("mpfr_fpif_import did not fail on a bad imported data\n");
256           switch (i)
257             {
258             case 0:
259               printf ("  not enough precision data\n");
260               break;
261             case 1:
262               printf ("  no exponent data\n");
263               break;
264             case 2:
265               printf ("  too big exponent\n");
266               break;
267             case 3:
268               printf ("  not enough exponent data\n");
269               break;
270             case 4:
271               printf ("  exponent data wrong\n");
272               break;
273             case 5:
274               printf ("  no limb data\n");
275               break;
276             default:
277               printf ("Test fatal error, unknown case\n");
278               break;
279             }
280           fclose (fh);
281           remove (filenameCompressed);
282           exit(1);
283         }
284     }
285 
286   fclose (fh);
287   mpfr_clear (x);
288 
289   fh = fopen (filenameCompressed, "r");
290   if (fh == NULL)
291     {
292       printf ("Failed to open for reading %s, exiting...\n",
293               filenameCompressed);
294       exit (1);
295     }
296 
297   mpfr_init2 (x, 2);
298   status = mpfr_fpif_export (fh, x);
299   if (status == 0)
300     {
301       printf ("mpfr_fpif_export did not fail on a read only stream\n");
302       exit(1);
303     }
304   fclose (fh);
305   remove (filenameCompressed);
306   mpfr_clear (x);
307 }
308 
309 /* exercise error when precision > MPFR_PREC_MAX */
310 static void
311 extra (void)
312 {
313   char *data = FILE_NAME_R2;
314   mpfr_t x;
315   FILE *fp;
316   int ret;
317 
318   mpfr_init2 (x, 17);
319   mpfr_set_ui (x, 42, MPFR_RNDN);
320   fp = src_fopen (data, "r");
321   if (fp == NULL)
322     {
323       printf ("Failed to open for reading %s in srcdir, exiting...\n", data);
324       exit (1);
325     }
326   ret = mpfr_fpif_import (x, fp);
327   MPFR_ASSERTN (ret != 0);  /* import failure */
328   MPFR_ASSERTN (mpfr_get_prec (x) == 17);  /* precision did not change */
329   MPFR_ASSERTN (mpfr_cmp_ui0 (x, 42) == 0);  /* value is still 42 */
330   fclose (fp);
331   mpfr_clear (x);
332 }
333 
334 int
335 main (int argc, char *argv[])
336 {
337   if (argc != 1)
338     {
339       printf ("Usage: %s\n", argv[0]);
340       exit (1);
341     }
342 
343   tests_start_mpfr ();
344 
345   extra ();
346   doit (argc, argv, 130, 2048);
347   doit (argc, argv, 1, 53);
348   check_bad ();
349 
350   tests_end_mpfr ();
351 
352   return 0;
353 }
354