xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tpow_z.c (revision ba125506a622fe649968631a56eba5d42ff57863)
1 /* Test file for mpfr_pow_z -- power function x^z with z a MPZ
2 
3 Copyright 2005-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 PRINT_ERROR(str) \
26   do { printf ("Error for %s\n", str); exit (1); } while (0)
27 
28 static void
check_special(void)29 check_special (void)
30 {
31   mpfr_t x, y;
32   mpz_t  z;
33   int res;
34 
35   mpfr_init (x);
36   mpfr_init (y);
37   mpz_init (z);
38 
39   /* x^0 = 1 except for NAN */
40   mpfr_set_ui (x, 23, MPFR_RNDN);
41   mpz_set_ui (z, 0);
42   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
43   if (res != 0 || mpfr_cmp_ui (y, 1) != 0)
44     PRINT_ERROR ("23^0");
45   mpfr_set_nan (x);
46   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
47   if (res != 0 || mpfr_nan_p (y) || mpfr_cmp_si (y, 1) != 0)
48     PRINT_ERROR ("NAN^0");
49   mpfr_set_inf (x, 1);
50   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
51   if (res != 0 || mpfr_cmp_ui (y, 1) != 0)
52     PRINT_ERROR ("INF^0");
53 
54   /* sINF^N = INF if s==1 or n even if N > 0*/
55   mpz_set_ui (z, 42);
56   mpfr_set_inf (x, 1);
57   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
58   if (res != 0 || mpfr_inf_p (y) == 0 || mpfr_sgn (y) <= 0)
59     PRINT_ERROR ("INF^42");
60   mpfr_set_inf (x, -1);
61   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
62   if (res != 0 || mpfr_inf_p (y) == 0 || mpfr_sgn (y) <= 0)
63     PRINT_ERROR ("-INF^42");
64   mpz_set_ui (z, 17);
65   mpfr_set_inf (x, 1);
66   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
67   if (res != 0 || mpfr_inf_p (y) == 0 || mpfr_sgn (y) <= 0)
68     PRINT_ERROR ("INF^17");
69   mpfr_set_inf (x, -1);
70   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
71   if (res != 0 || mpfr_inf_p (y) == 0 || mpfr_sgn (y) >= 0)
72     PRINT_ERROR ("-INF^17");
73 
74   mpz_set_si (z, -42);
75   mpfr_set_inf (x, 1);
76   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
77   if (res != 0 || mpfr_zero_p (y) == 0 || MPFR_IS_NEG (y))
78     PRINT_ERROR ("INF^-42");
79   mpfr_set_inf (x, -1);
80   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
81   if (res != 0 || mpfr_zero_p (y) == 0 || MPFR_IS_NEG (y))
82     PRINT_ERROR ("-INF^-42");
83   mpz_set_si (z, -17);
84   mpfr_set_inf (x, 1);
85   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
86   if (res != 0 || mpfr_zero_p (y) == 0 || MPFR_IS_NEG (y))
87     PRINT_ERROR ("INF^-17");
88   mpfr_set_inf (x, -1);
89   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
90   if (res != 0 || mpfr_zero_p (y) == 0 || MPFR_IS_POS (y))
91     PRINT_ERROR ("-INF^-17");
92 
93   /* s0^N = +0 if s==+ or n even if N > 0*/
94   mpz_set_ui (z, 42);
95   MPFR_SET_ZERO (x); MPFR_SET_POS (x);
96   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
97   if (res != 0 || mpfr_zero_p (y) == 0 || MPFR_IS_NEG (y))
98     PRINT_ERROR ("+0^42");
99   MPFR_SET_NEG (x);
100   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
101   if (res != 0 || mpfr_zero_p (y) == 0 || MPFR_IS_NEG (y))
102     PRINT_ERROR ("-0^42");
103   mpz_set_ui (z, 17);
104   MPFR_SET_POS (x);
105   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
106   if (res != 0 || mpfr_zero_p (y) == 0 || MPFR_IS_NEG (y))
107     PRINT_ERROR ("+0^17");
108   MPFR_SET_NEG (x);
109   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
110   if (res != 0 || mpfr_zero_p (y) == 0 || MPFR_IS_POS (y))
111     PRINT_ERROR ("-0^17");
112 
113   mpz_set_si (z, -42);
114   MPFR_SET_ZERO (x); MPFR_SET_POS (x);
115   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
116   if (res != 0 || mpfr_inf_p (y) == 0 || MPFR_IS_NEG (y))
117     PRINT_ERROR ("+0^-42");
118   MPFR_SET_NEG (x);
119   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
120   if (res != 0 || mpfr_inf_p (y) == 0 || MPFR_IS_NEG (y))
121     PRINT_ERROR ("-0^-42");
122   mpz_set_si (z, -17);
123   MPFR_SET_POS (x);
124   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
125   if (res != 0 || mpfr_inf_p (y) == 0 || MPFR_IS_NEG (y))
126     PRINT_ERROR ("+0^-17");
127   MPFR_SET_NEG (x);
128   res = mpfr_pow_z (y, x, z, MPFR_RNDN);
129   if (res != 0 || mpfr_inf_p (y) == 0 || MPFR_IS_POS (y))
130     PRINT_ERROR ("-0^-17");
131 
132   mpz_clear (z);
133   mpfr_clear (y);
134   mpfr_clear (x);
135 }
136 
137 static void
check_integer(mpfr_prec_t begin,mpfr_prec_t end,unsigned long max)138 check_integer (mpfr_prec_t begin, mpfr_prec_t end, unsigned long max)
139 {
140   mpfr_t x, y1, y2;
141   mpz_t z;
142   unsigned long i, n;
143   mpfr_prec_t p;
144   int res1, res2;
145   mpfr_rnd_t rnd;
146 
147   mpfr_inits2 (begin, x, y1, y2, (mpfr_ptr) 0);
148   mpz_init (z);
149   for (p = begin ; p < end ; p+=4)
150     {
151       mpfr_set_prec (x, p);
152       mpfr_set_prec (y1, p);
153       mpfr_set_prec (y2, p);
154       for (i = 0 ; i < max ; i++)
155         {
156           mpz_urandomb (z, RANDS, GMP_NUMB_BITS);
157           if ((i & 1) != 0)
158             mpz_neg (z, z);
159           mpfr_urandomb (x, RANDS);
160           mpfr_mul_2ui (x, x, 1, MPFR_RNDN); /* 0 <= x < 2 */
161           rnd = RND_RAND ();
162           if (mpz_fits_slong_p (z))
163             {
164               n = mpz_get_si (z);
165               /* printf ("New test for x=%ld\nCheck Pow_si\n", n); */
166               res1 = mpfr_pow_si (y1, x, n, rnd);
167               /* printf ("Check pow_z\n"); */
168               res2 = mpfr_pow_z  (y2, x, z, rnd);
169               if (! mpfr_equal_p (y1, y2))
170                 {
171                   printf ("Error for p = %lu, z = %lu, rnd = %s and x = ",
172                           (unsigned long) p, n, mpfr_print_rnd_mode (rnd));
173                   mpfr_dump (x);
174                   printf ("Ypowsi = "); mpfr_dump (y1);
175                   printf ("Ypowz  = "); mpfr_dump (y2);
176                   exit (1);
177                 }
178               /* The ternary value is unspecified with MPFR_RNDF. */
179               if (rnd != MPFR_RNDF && ! SAME_SIGN (res1, res2))
180                 {
181                   printf ("Wrong ternary value for p = %lu, z = %lu, rnd = %s"
182                           " and x = ", (unsigned long) p, n,
183                           mpfr_print_rnd_mode (rnd));
184                   mpfr_dump (x);
185                   printf ("Ypowsi(inex = %2d) = ", res1); mpfr_dump (y1);
186                   printf ("Ypowz (inex = %2d) = ", res2); mpfr_dump (y2);
187                   exit (1);
188                 }
189             }
190         } /* for i */
191     } /* for p */
192   mpfr_clears (x, y1, y2, (mpfr_ptr) 0);
193   mpz_clear (z);
194 }
195 
196 static void
check_regression(void)197 check_regression (void)
198 {
199   mpfr_t x, y;
200   mpz_t  z;
201   int res1, res2;
202 
203   mpz_init_set_ui (z, 2026876995);
204   mpfr_init2 (x, 122);
205   mpfr_init2 (y, 122);
206 
207   mpfr_set_str_binary (x, "0.10000010010000111101001110100101101010011110011100001111000001001101000110011001001001001011001011010110110110101000111011E1");
208   res1 = mpfr_pow_z (y, x, z, MPFR_RNDU);
209   res2 = mpfr_pow_ui (x, x, 2026876995UL, MPFR_RNDU);
210   if (! mpfr_equal_p (x, y) || ! SAME_SIGN (res1, res2))
211     {
212       printf ("Regression (1) tested failed (%d=?%d)\n",res1, res2);
213       printf ("pow_ui: "); mpfr_dump (x);
214       printf ("pow_z:  "); mpfr_dump (y);
215 
216       exit (1);
217     }
218 
219   mpfr_clear (x);
220   mpfr_clear (y);
221   mpz_clear (z);
222 }
223 
224 /* Bug found by Kevin P. Rauch */
225 static void
bug20071104(void)226 bug20071104 (void)
227 {
228   mpfr_t x, y;
229   mpz_t z;
230   int inex;
231 
232   mpz_init_set_si (z, -2);
233   mpfr_inits2 (20, x, y, (mpfr_ptr) 0);
234   mpfr_set_ui (x, 0, MPFR_RNDN);
235   mpfr_nextbelow (x);  /* x = -2^(emin-1) */
236   mpfr_clear_flags ();
237   inex = mpfr_pow_z (y, x, z, MPFR_RNDN);
238   if (! mpfr_inf_p (y) || MPFR_IS_NEG (y))
239     {
240       printf ("Error in bug20071104: expected +Inf, got ");
241       mpfr_dump (y);
242       exit (1);
243     }
244   if (inex <= 0)
245     {
246       printf ("Error in bug20071104: bad ternary value (%d)\n", inex);
247       exit (1);
248     }
249   if (__gmpfr_flags != (MPFR_FLAGS_OVERFLOW | MPFR_FLAGS_INEXACT))
250     {
251       printf ("Error in bug20071104: bad flags (%u)\n",
252               (unsigned int) __gmpfr_flags);
253       exit (1);
254     }
255   mpfr_clears (x, y, (mpfr_ptr) 0);
256   mpz_clear (z);
257 }
258 
259 static void
check_overflow(void)260 check_overflow (void)
261 {
262   mpfr_t a;
263   mpz_t z;
264   unsigned long n;
265   int res;
266 
267   mpfr_init2 (a, 53);
268 
269   mpfr_set_str_binary (a, "1E10");
270   mpz_init_set_ui (z, ULONG_MAX);
271   res = mpfr_pow_z (a, a, z, MPFR_RNDN);
272   if (! MPFR_IS_INF (a) || MPFR_IS_NEG (a) || res <= 0)
273     {
274       printf ("Error for (1e10)^ULONG_MAX, expected +Inf,\ngot ");
275       mpfr_dump (a);
276       exit (1);
277     }
278 
279   /* Bug in pow_z.c up to r5109: if x = y (same mpfr_t argument), the
280      input argument is negative and not a power of two, z is positive
281      and odd, an overflow or underflow occurs, and the temporary result
282      res is positive, then the result gets a wrong sign (positive
283      instead of negative). */
284   mpfr_set_str_binary (a, "-1.1E10");
285   n = (ULONG_MAX ^ (ULONG_MAX >> 1)) + 1;
286   mpz_set_ui (z, n);
287   res = mpfr_pow_z (a, a, z, MPFR_RNDN);
288   if (! MPFR_IS_INF (a) || MPFR_IS_POS (a) || res >= 0)
289     {
290       printf ("Error for (-1e10)^%lu, expected -Inf,\ngot ", n);
291       mpfr_dump (a);
292       exit (1);
293     }
294 
295   mpfr_clear (a);
296   mpz_clear (z);
297 }
298 
299 /* bug reported by Carl Witty (32-bit architecture) */
300 static void
bug20080223(void)301 bug20080223 (void)
302 {
303   mpfr_t a, exp, answer;
304 
305   mpfr_init2 (a, 53);
306   mpfr_init2 (exp, 53);
307   mpfr_init2 (answer, 53);
308 
309   mpfr_set_si (exp, -1073741824, MPFR_RNDN);
310 
311   mpfr_set_str (a, "1.999999999", 10, MPFR_RNDN);
312   /* a = 562949953139837/2^48 */
313   mpfr_pow (answer, a, exp, MPFR_RNDN);
314   mpfr_set_str_binary (a, "0.110110101111011001110000111111100011101000111011101E-1073741823");
315   MPFR_ASSERTN(mpfr_cmp0 (answer, a) == 0);
316 
317   mpfr_clear (a);
318   mpfr_clear (exp);
319   mpfr_clear (answer);
320 }
321 
322 static void
bug20080904(void)323 bug20080904 (void)
324 {
325   mpz_t exp;
326   mpfr_t a, answer;
327   mpfr_exp_t emin_default;
328 
329   mpz_init (exp);
330   mpfr_init2 (a, 70);
331   mpfr_init2 (answer, 70);
332 
333   emin_default = mpfr_get_emin ();
334   set_emin (MPFR_EMIN_MIN);
335 
336   mpz_set_str (exp, "-4eb92f8c7b7bf81e", 16);
337   mpfr_set_str_binary (a, "1.110000101110100110100011111000011110111101000011111001111001010011100");
338 
339   mpfr_pow_z (answer, a, exp, MPFR_RNDN);
340   /* The correct result is near 2^(-2^62), so it underflows when
341      MPFR_EMIN_MIN > -2^62 (i.e. with 32 and 64 bits machines). */
342   mpfr_set_str (a, "AA500C0D7A69275DBp-4632850503556296886", 16, MPFR_RNDN);
343   if (! mpfr_equal_p (answer, a))
344     {
345       printf ("Error in bug20080904:\n");
346       printf ("Expected ");
347       mpfr_out_str (stdout, 16, 0, a, MPFR_RNDN);
348       putchar ('\n');
349       printf ("Got      ");
350       mpfr_out_str (stdout, 16, 0, answer, MPFR_RNDN);
351       putchar ('\n');
352       exit (1);
353     }
354 
355   set_emin (emin_default);
356 
357   mpz_clear (exp);
358   mpfr_clear (a);
359   mpfr_clear (answer);
360 }
361 
362 int
main(void)363 main (void)
364 {
365   tests_start_mpfr ();
366 
367   check_special ();
368 
369   check_integer (2, 163, 100);
370   check_regression ();
371   bug20071104 ();
372   bug20080223 ();
373   bug20080904 ();
374   check_overflow ();
375 
376   tests_end_mpfr ();
377   return 0;
378 }
379