xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tget_sj.c (revision ba125506a622fe649968631a56eba5d42ff57863)
1 /* Test file for mpfr_get_sj and mpfr_get_uj.
2 
3 Copyright 2004-2023 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramba projects, INRIA.
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 https://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 #define MPFR_NEED_INTMAX_H
24 #include "mpfr-test.h"
25 
26 #ifndef _MPFR_H_HAVE_INTMAX_T
27 
28 int
main(void)29 main (void)
30 {
31   return 77;
32 }
33 
34 #else
35 
36 #ifndef NPRINTF_J
37 #define PRMAX(SPEC,V) printf (" %j" SPEC ",", V)
38 #else
39 #define PRMAX(SPEC,V) (void) 0
40 #endif
41 
42 static void
check_sj(intmax_t s,mpfr_ptr x)43 check_sj (intmax_t s, mpfr_ptr x)
44 {
45   mpfr_exp_t emin, emax;
46   mpfr_t y;
47   int i;
48 
49   mpfr_init2 (y, MPFR_PREC (x) + 2);
50 
51   emin = mpfr_get_emin ();
52   emax = mpfr_get_emax ();
53 
54   for (i = -1; i <= 1; i++)
55     {
56       int rnd;
57       int inex;
58       int fi, e;
59       mpfr_flags_t flags[2] = { 0, MPFR_FLAGS_ALL }, ex_flags, gt_flags;
60 
61       inex = mpfr_set_si_2exp (y, i, -2, MPFR_RNDN);
62       MPFR_ASSERTN (inex == 0);
63       inex = mpfr_add (y, y, x, MPFR_RNDN);
64       MPFR_ASSERTN (inex == 0);
65       /* y = x + i/4, with -1 <= i <= 1 */
66       RND_LOOP (rnd)
67         for (fi = 0; fi < numberof (flags); fi++)
68           {
69             intmax_t r;
70 
71             if (rnd == MPFR_RNDZ && i < 0 && s >= 0)
72               continue;
73             if (rnd == MPFR_RNDZ && i > 0 && s <= 0)
74               continue;
75             if (rnd == MPFR_RNDD && i < 0)
76               continue;
77             if (rnd == MPFR_RNDU && i > 0)
78               continue;
79             if (rnd == MPFR_RNDA && ((MPFR_IS_POS(y) && i > 0) ||
80                                      (MPFR_IS_NEG(y) && i < 0)))
81               continue;
82 
83             for (e = 0; e < 2; e++)
84               {
85                 if (e)
86                   {
87                     mpfr_exp_t ey;
88 
89                     if (MPFR_IS_ZERO (y))
90                       break;
91                     ey = MPFR_GET_EXP (y);
92                     set_emin (ey);
93                     set_emax (ey);
94                   }
95                 /* rint (y) == x == s */
96                 __gmpfr_flags = ex_flags = flags[fi];
97                 if (i != 0)
98                   ex_flags |= MPFR_FLAGS_INEXACT;
99                 r = mpfr_get_sj (y, (mpfr_rnd_t) rnd);
100                 gt_flags = __gmpfr_flags;
101                 set_emin (emin);
102                 set_emax (emax);
103                 if ((r != s || gt_flags != ex_flags) && rnd != MPFR_RNDF)
104                   {
105                     printf ("Error in check_sj for fi = %d, y = ", fi);
106                     mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
107                     printf (" in %s%s\n",
108                             mpfr_print_rnd_mode ((mpfr_rnd_t) rnd),
109                             e ? ", reduced exponent range" : "");
110                     printf ("Expected:");
111                     PRMAX ("d", s);
112                     flags_out (ex_flags);
113                     printf ("Got:     ");
114                     PRMAX ("d", r);
115                     flags_out (gt_flags);
116                     exit (1);
117                   }
118               }
119           }
120     }
121 
122   mpfr_clear (y);
123 }
124 
125 static void
check_uj(uintmax_t u,mpfr_ptr x)126 check_uj (uintmax_t u, mpfr_ptr x)
127 {
128   mpfr_exp_t emin, emax;
129   mpfr_t y;
130   int i;
131 
132   mpfr_init2 (y, MPFR_PREC (x) + 2);
133 
134   emin = mpfr_get_emin ();
135   emax = mpfr_get_emax ();
136 
137   for (i = -1; i <= 1; i++)
138     {
139       int rnd;
140       int inex;
141       int fi, e;
142       mpfr_flags_t flags[2] = { 0, MPFR_FLAGS_ALL }, ex_flags, gt_flags;
143 
144       inex = mpfr_set_si_2exp (y, i, -2, MPFR_RNDN);
145       MPFR_ASSERTN (inex == 0);
146       inex = mpfr_add (y, y, x, MPFR_RNDN);
147       MPFR_ASSERTN (inex == 0);
148       /* y = x + i/4, with -1 <= i <= 1 */
149       RND_LOOP (rnd)
150         for (fi = 0; fi < numberof (flags); fi++)
151           {
152             uintmax_t r;
153 
154             if (rnd == MPFR_RNDZ && i < 0)
155               continue;
156             if (rnd == MPFR_RNDD && i < 0)
157               continue;
158             if (rnd == MPFR_RNDU && i > 0)
159               continue;
160             if (rnd == MPFR_RNDA && ((MPFR_IS_POS(y) && i > 0) ||
161                                      (MPFR_IS_NEG(y) && i < 0)))
162               continue;
163 
164             for (e = 0; e < 2; e++)
165               {
166                 if (e)
167                   {
168                     mpfr_exp_t ey;
169 
170                     if (MPFR_IS_ZERO (y))
171                       break;
172                     ey = MPFR_GET_EXP (y);
173                     set_emin (ey);
174                     set_emax (ey);
175                   }
176                 /* rint (y) == x == u */
177                 __gmpfr_flags = ex_flags = flags[fi];
178                 if (i != 0)
179                   ex_flags |= MPFR_FLAGS_INEXACT;
180                 r = mpfr_get_uj (y, (mpfr_rnd_t) rnd);
181                 gt_flags = __gmpfr_flags;
182                 set_emin (emin);
183                 set_emax (emax);
184                 if ((r != u || gt_flags != ex_flags) && rnd != MPFR_RNDF)
185                   {
186                     printf ("Error in check_uj for fi = %d, y = ", fi);
187                     mpfr_out_str (stdout, 2, 0, y, MPFR_RNDN);
188                     printf (" in %s%s\n",
189                             mpfr_print_rnd_mode ((mpfr_rnd_t) rnd),
190                             e ? ", reduced exponent range" : "");
191                     printf ("Expected:");
192                     PRMAX ("u", u);
193                     flags_out (ex_flags);
194                     printf ("Got:     ");
195                     PRMAX ("u", r);
196                     flags_out (gt_flags);
197                     exit (1);
198                   }
199               }
200           }
201     }
202 
203   mpfr_clear (y);
204 }
205 
206 #define CHECK_ERANGE(F,FMT,RES,INPUT,VALUE,E)                           \
207   do                                                                    \
208     {                                                                   \
209       __gmpfr_flags = ex_flags = flags[fi];                             \
210       RES = F (x, (mpfr_rnd_t) rnd);                                    \
211       gt_flags = __gmpfr_flags;                                         \
212       if (E)                                                            \
213         ex_flags |= MPFR_FLAGS_ERANGE;                                  \
214       if (RES == VALUE && gt_flags == ex_flags)                         \
215         continue;                                                       \
216       printf ("Error in check_erange for %s, %s, fi = %d on %s\n",      \
217               #F, mpfr_print_rnd_mode ((mpfr_rnd_t) rnd), fi, INPUT);   \
218       printf ("Expected:");                                             \
219       PRMAX (FMT, VALUE);                                               \
220       flags_out (ex_flags);                                             \
221       printf ("Got:     ");                                             \
222       PRMAX (FMT, RES);                                                 \
223       flags_out (gt_flags);                                             \
224       exit (1);                                                         \
225     }                                                                   \
226   while (0)
227 
228 #define CHECK_ERANGE_U(INPUT,VALUE,E) \
229   CHECK_ERANGE (mpfr_get_uj, "u", u, INPUT, (uintmax_t) VALUE, E)
230 #define CHECK_ERANGE_S(INPUT,VALUE,E) \
231   CHECK_ERANGE (mpfr_get_sj, "d", d, INPUT, (intmax_t) VALUE, E)
232 
233 static void
check_erange(void)234 check_erange (void)
235 {
236   mpfr_t x;
237   uintmax_t u;
238   intmax_t d;
239   int rnd;
240   int fi;
241   mpfr_flags_t flags[3] = { 0, MPFR_FLAGS_ALL ^ MPFR_FLAGS_ERANGE,
242                             MPFR_FLAGS_ALL }, ex_flags, gt_flags;
243 
244   /* Test for ERANGE flag + correct behavior if overflow */
245 
246   mpfr_init2 (x, 256);
247 
248   RND_LOOP (rnd)
249     for (fi = 0; fi < numberof (flags); fi++)
250       {
251         mpfr_set_uj (x, UINTMAX_MAX, MPFR_RNDN);
252         CHECK_ERANGE_U ("UINTMAX_MAX", UINTMAX_MAX, 0);
253         mpfr_add_ui (x, x, 1, MPFR_RNDN);
254         CHECK_ERANGE_U ("UINTMAX_MAX+1", UINTMAX_MAX, 1);
255         mpfr_set_sj (x, -1, MPFR_RNDN);
256         CHECK_ERANGE_U ("-1", 0, 1);
257         mpfr_set_sj (x, INTMAX_MAX, MPFR_RNDN);
258         CHECK_ERANGE_S ("INTMAX_MAX", INTMAX_MAX, 0);
259         mpfr_add_ui (x, x, 1, MPFR_RNDN);
260         CHECK_ERANGE_S ("INTMAX_MAX+1", INTMAX_MAX, 1);
261         mpfr_set_sj (x, INTMAX_MIN, MPFR_RNDN);
262         CHECK_ERANGE_S ("INTMAX_MIN", INTMAX_MIN, 0);
263         mpfr_sub_ui (x, x, 1, MPFR_RNDN);
264         CHECK_ERANGE_S ("INTMAX_MIN-1", INTMAX_MIN, 1);
265         mpfr_set_nan (x);
266         CHECK_ERANGE_U ("NaN", 0, 1);
267         CHECK_ERANGE_S ("NaN", 0, 1);
268       }
269 
270   mpfr_clear (x);
271 }
272 
273 static void
test_get_uj_smallneg(void)274 test_get_uj_smallneg (void)
275 {
276   mpfr_t x;
277   int i;
278 
279   mpfr_init2 (x, 64);
280 
281   for (i = 1; i <= 4; i++)
282     {
283       int r;
284 
285       mpfr_set_si_2exp (x, -i, -2, MPFR_RNDN);
286       RND_LOOP (r)
287         {
288           intmax_t s;
289           uintmax_t u;
290 
291           mpfr_clear_erangeflag ();
292           s = mpfr_get_sj (x, r != MPFR_RNDF ? (mpfr_rnd_t) r : MPFR_RNDA);
293           if (mpfr_erangeflag_p ())
294             {
295               printf ("ERROR for get_sj + ERANGE + small negative op"
296                       " for rnd = %s and x = -%d/4\n",
297                       mpfr_print_rnd_mode ((mpfr_rnd_t) r), i);
298               exit (1);
299             }
300           u = mpfr_get_uj (x, (mpfr_rnd_t) r);
301           if (u != 0)
302             {
303               printf ("ERROR for get_uj + ERANGE + small negative op"
304                       " for rnd = %s and x = -%d/4\n",
305                       mpfr_print_rnd_mode ((mpfr_rnd_t) r), i);
306 #ifndef NPRINTF_J
307               printf ("Expected 0, got %ju\n", u);
308 #endif
309               exit (1);
310             }
311           if ((s == 0) ^ !mpfr_erangeflag_p ())
312             {
313               const char *Not = s == 0 ? "" : " not";
314 
315               printf ("ERROR for get_uj + ERANGE + small negative op"
316                       " for rnd = %s and x = -%d/4\n",
317                       mpfr_print_rnd_mode ((mpfr_rnd_t) r), i);
318               printf ("The rounded integer ");
319 #ifndef NPRINTF_J
320               printf("(%jd) ", s);
321 #endif
322               printf("is%s representable in unsigned long,\n"
323                      "but the erange flag is%s set.\n", Not, Not);
324               exit (1);
325             }
326         }
327     }
328 
329   mpfr_clear (x);
330 }
331 
332 int
main(void)333 main (void)
334 {
335   mpfr_prec_t prec;
336   mpfr_t x, y;
337   intmax_t s;
338   uintmax_t u;
339 
340   tests_start_mpfr ();
341 
342   for (u = UINTMAX_MAX, prec = 0; u != 0; u /= 2, prec++)
343     { }
344 
345   mpfr_init2 (x, prec + 4);
346   mpfr_init2 (y, prec + 4);
347 
348   mpfr_set_ui (x, 0, MPFR_RNDN);
349   check_sj (0, x);
350   check_uj (0, x);
351 
352   mpfr_set_ui (x, 1, MPFR_RNDN);
353   check_sj (1, x);
354   check_uj (1, x);
355 
356   mpfr_neg (x, x, MPFR_RNDN);
357   check_sj (-1, x);
358 
359   mpfr_set_si_2exp (x, 1, prec, MPFR_RNDN);
360   mpfr_sub_ui (x, x, 1, MPFR_RNDN); /* UINTMAX_MAX */
361 
362   mpfr_div_ui (y, x, 2, MPFR_RNDZ);
363   mpfr_trunc (y, y); /* INTMAX_MAX */
364   for (s = INTMAX_MAX; s != 0; s /= 17)
365     {
366       check_sj (s, y);
367       mpfr_div_ui (y, y, 17, MPFR_RNDZ);
368       mpfr_trunc (y, y);
369     }
370 
371   mpfr_div_ui (y, x, 2, MPFR_RNDZ);
372   mpfr_trunc (y, y); /* INTMAX_MAX */
373   mpfr_neg (y, y, MPFR_RNDN);
374   if (INTMAX_MIN + INTMAX_MAX != 0)
375     mpfr_sub_ui (y, y, 1, MPFR_RNDN); /* INTMAX_MIN */
376   for (s = INTMAX_MIN; s != 0; s /= 17)
377     {
378       check_sj (s, y);
379       mpfr_div_ui (y, y, 17, MPFR_RNDZ);
380       mpfr_trunc (y, y);
381     }
382 
383   for (u = UINTMAX_MAX; u != 0; u /= 17)
384     {
385       check_uj (u, x);
386       mpfr_div_ui (x, x, 17, MPFR_RNDZ);
387       mpfr_trunc (x, x);
388     }
389 
390   mpfr_clear (x);
391   mpfr_clear (y);
392 
393   check_erange ();
394   test_get_uj_smallneg ();
395 
396   tests_end_mpfr ();
397   return 0;
398 }
399 
400 #endif
401