xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tcompound.c (revision 901e7e84758515fbf39dfc064cb0b45ab146d8b0)
1 /* Test file for mpfr_compound_si.
2 
3 Copyright 2021-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 #include "mpfr-test.h"
24 
25 #define TEST_FUNCTION mpfr_compound_si
26 #define INTEGER_TYPE long
27 #define RAND_FUNCTION(x) mpfr_random2(x, MPFR_LIMB_SIZE (x), 1, RANDS)
28 #define test_generic_ui test_generic_si
29 #include "tgeneric_ui.c"
30 
31 /* Special cases from IEEE 754-2019 */
32 static void
33 check_ieee754 (void)
34 {
35   mpfr_t x, y;
36   long i;
37   long t[] = { 0, 1, 2, 3, 17, LONG_MAX-1, LONG_MAX };
38   int j;
39   mpfr_prec_t prec = 2; /* we need at least 2 so that 3/4 is exact */
40 
41   mpfr_init2 (x, prec);
42   mpfr_init2 (y, prec);
43 
44   /* compound(x,n) = NaN for x < -1, and set invalid exception */
45   for (i = 0; i < numberof(t); i++)
46     for (j = 0; j < 2; j++)
47       {
48         const char *s;
49 
50         mpfr_clear_nanflag ();
51         if (j == 0)
52           {
53             mpfr_set_si (x, -2, MPFR_RNDN);
54             s = "-2";
55           }
56         else
57           {
58             mpfr_set_inf (x, -1);
59             s = "-Inf";
60           }
61         mpfr_compound_si (y, x, t[i], MPFR_RNDN);
62         if (!mpfr_nan_p (y))
63           {
64             printf ("Error, compound(%s,%ld) should give NaN\n", s, t[i]);
65             printf ("got "); mpfr_dump (y);
66             exit (1);
67           }
68         if (!mpfr_nanflag_p ())
69           {
70             printf ("Error, compound(%s,%ld) should raise invalid flag\n",
71                     s, t[i]);
72             exit (1);
73           }
74       }
75 
76   /* compound(x,0) = 1 for x >= -1 or x = NaN */
77   for (i = -2; i <= 2; i++)
78     {
79       if (i == -2)
80         mpfr_set_nan (x);
81       else if (i == 2)
82         mpfr_set_inf (x, 1);
83       else
84         mpfr_set_si (x, i, MPFR_RNDN);
85       mpfr_compound_si (y, x, 0, MPFR_RNDN);
86       if (mpfr_cmp_ui (y, 1) != 0)
87         {
88           printf ("Error, compound(x,0) should give 1 on\nx = ");
89           mpfr_dump (x);
90           printf ("got "); mpfr_dump (y);
91           exit (1);
92         }
93     }
94 
95   /* compound(-1,n) = +Inf for n < 0, and raise divide-by-zero flag */
96   mpfr_clear_divby0 ();
97   mpfr_set_si (x, -1, MPFR_RNDN);
98   mpfr_compound_si (y, x, -1, MPFR_RNDN);
99   if (!mpfr_inf_p (y) || MPFR_SIGN(y) < 0)
100     {
101       printf ("Error, compound(-1,-1) should give +Inf\n");
102       printf ("got "); mpfr_dump (y);
103       exit (1);
104     }
105   if (!mpfr_divby0_p ())
106     {
107       printf ("Error, compound(-1,-1) should raise divide-by-zero flag\n");
108       exit (1);
109     }
110 
111   /* compound(-1,n) = +0 for n > 0 */
112   mpfr_set_si (x, -1, MPFR_RNDN);
113   mpfr_compound_si (y, x, 1, MPFR_RNDN);
114   if (!mpfr_zero_p (y) || MPFR_SIGN(y) < 0)
115     {
116       printf ("Error, compound(-1,1) should give +0\n");
117       printf ("got "); mpfr_dump (y);
118       exit (1);
119     }
120 
121   /* compound(+/-0,n) = 1 */
122   for (i = -1; i <= 1; i++)
123     {
124       mpfr_set_zero (x, -1);
125       mpfr_compound_si (y, x, i, MPFR_RNDN);
126       if (mpfr_cmp_ui (y, 1) != 0)
127         {
128           printf ("Error1, compound(x,%ld) should give 1\non x = ", i);
129           mpfr_dump (x);
130           printf ("got "); mpfr_dump (y);
131           exit (1);
132         }
133       mpfr_set_zero (x, +1);
134       mpfr_compound_si (y, x, i, MPFR_RNDN);
135       if (mpfr_cmp_ui (y, 1) != 0)
136         {
137           printf ("Error, compound(x,%ld) should give 1\non x = ", i);
138           mpfr_dump (x);
139           printf ("got "); mpfr_dump (y);
140           exit (1);
141         }
142     }
143 
144   /* compound(+Inf,n) = +Inf for n > 0 */
145   mpfr_set_inf (x, 1);
146   mpfr_compound_si (y, x, 1, MPFR_RNDN);
147   if (!mpfr_inf_p (y) || MPFR_SIGN(y) < 0)
148     {
149       printf ("Error, compound(+Inf,1) should give +Inf\n");
150       printf ("got "); mpfr_dump (y);
151       exit (1);
152     }
153 
154   /* compound(+Inf,n) = +0 for n < 0 */
155   mpfr_set_inf (x, 1);
156   mpfr_compound_si (y, x, -1, MPFR_RNDN);
157   if (!mpfr_zero_p (y) || MPFR_SIGN(y) < 0)
158     {
159       printf ("Error, compound(+Inf,-1) should give +0\n");
160       printf ("got "); mpfr_dump (y);
161       exit (1);
162     }
163 
164   /* compound(NaN,n) = NaN for n <> 0 */
165   mpfr_set_nan (x);
166   mpfr_compound_si (y, x, -1, MPFR_RNDN);
167   if (!mpfr_nan_p (y))
168     {
169       printf ("Error, compound(NaN,-1) should give NaN\n");
170       printf ("got "); mpfr_dump (y);
171       exit (1);
172     }
173   mpfr_compound_si (y, x, +1, MPFR_RNDN);
174   if (!mpfr_nan_p (y))
175     {
176       printf ("Error, compound(NaN,+1) should give NaN\n");
177       printf ("got "); mpfr_dump (y);
178       exit (1);
179     }
180 
181   /* hard-coded test: x is the 32-bit nearest approximation of 17/42 */
182   mpfr_set_prec (x, 32);
183   mpfr_set_prec (y, 32);
184   mpfr_set_ui_2exp (x, 3476878287UL, -33, MPFR_RNDN);
185   mpfr_compound_si (y, x, 12, MPFR_RNDN);
186   mpfr_set_ui_2exp (x, 1981447393UL, -25, MPFR_RNDN);
187   if (!mpfr_equal_p (y, x))
188     {
189       printf ("Error for compound(3476878287/2^33,12)\n");
190       printf ("expected "); mpfr_dump (x);
191       printf ("got      "); mpfr_dump (y);
192       exit (1);
193     }
194 
195   /* test for negative n */
196   i = -1;
197   while (1)
198     {
199       /* i has the form -(2^k-1) */
200       mpfr_set_si_2exp (x, -1, -1, MPFR_RNDN); /* x = -0.5 */
201       mpfr_compound_si (y, x, i, MPFR_RNDN);
202       mpfr_set_ui_2exp (x, 1, -i, MPFR_RNDN);
203       if (!mpfr_equal_p (y, x))
204         {
205           printf ("Error for compound(-0.5,%ld)\n", i);
206           printf ("expected "); mpfr_dump (x);
207           printf ("got      "); mpfr_dump (y);
208           exit (1);
209         }
210       if (i == -2147483647) /* largest possible value on 32-bit machine */
211         break;
212       i = 2 * i - 1;
213     }
214 
215   /* The "#if" makes sure that 64-bit constants are supported, avoiding
216      a compilation failure. The "if" makes sure that the constant is
217      representable in a long (this would not be the case with 32-bit
218      unsigned long and 64-bit limb). */
219 #if GMP_NUMB_BITS >= 64 || MPFR_PREC_BITS >= 64
220   if (4994322635099777669 <= LONG_MAX)
221     {
222       i = -4994322635099777669;
223       mpfr_set_ui (x, 1, MPFR_RNDN);
224       mpfr_compound_si (y, x, i, MPFR_RNDN);
225       mpfr_set_si (x, 1, MPFR_RNDN);
226       mpfr_mul_2si (x, x, i, MPFR_RNDN);
227       if (!mpfr_equal_p (y, x))
228         {
229           printf ("Error for compound(1,%ld)\n", i);
230           printf ("expected "); mpfr_dump (x);
231           printf ("got      "); mpfr_dump (y);
232           exit (1);
233         }
234     }
235 #endif
236 
237   mpfr_clear (x);
238   mpfr_clear (y);
239 }
240 
241 static int
242 mpfr_compound2 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
243 {
244   return mpfr_compound_si (y, x, 2, rnd_mode);
245 }
246 
247 static int
248 mpfr_compound3 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
249 {
250   return mpfr_compound_si (y, x, 3, rnd_mode);
251 }
252 
253 #define TEST_FUNCTION mpfr_compound2
254 #define test_generic test_generic_compound2
255 #include "tgeneric.c"
256 
257 #define TEST_FUNCTION mpfr_compound3
258 #define test_generic test_generic_compound3
259 #include "tgeneric.c"
260 
261 int
262 main (void)
263 {
264   tests_start_mpfr ();
265 
266   check_ieee754 ();
267 
268   test_generic_si (MPFR_PREC_MIN, 100, 100);
269 
270   test_generic_compound2 (MPFR_PREC_MIN, 100, 100);
271   test_generic_compound3 (MPFR_PREC_MIN, 100, 100);
272 
273   tests_end_mpfr ();
274   return 0;
275 }
276