xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tgeneric_ui.c (revision ba125506a622fe649968631a56eba5d42ff57863)
1 /* Generic test file for functions with one mpfr_t argument and an integer.
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 /* define INTEGER_TYPE to what we want */
24 #ifndef INTEGER_TYPE
25 # define INTEGER_TYPE mp_limb_t
26 #endif
27 #ifndef RAND_FUNCTION
28 # define RAND_FUNCTION(x) mpfr_urandomb ((x), RANDS)
29 #endif
30 #ifndef INT_RAND_FUNCTION
31 # define INT_RAND_FUNCTION() (INTEGER_TYPE) randlimb ()
32 #endif
33 
34 static void
test_generic_ui(mpfr_prec_t p0,mpfr_prec_t p1,unsigned int N)35 test_generic_ui (mpfr_prec_t p0, mpfr_prec_t p1, unsigned int N)
36 {
37   mpfr_prec_t prec, yprec;
38   mpfr_t x, y, z, t;
39   INTEGER_TYPE u;
40   mpfr_rnd_t rnd;
41   int inexact, compare, compare2;
42   unsigned int n;
43 
44   mpfr_init (x);
45   mpfr_init (y);
46   mpfr_init (z);
47   mpfr_init (t);
48 
49   /* generic test */
50   for (prec = p0; prec <= p1; prec++)
51     {
52       mpfr_set_prec (x, prec);
53       mpfr_set_prec (z, prec);
54       mpfr_set_prec (t, prec);
55       yprec = prec + 10;
56 
57       for (n = 0; n <= N; n++)
58         {
59           if (n > 1 || prec < p1)
60             RAND_FUNCTION (x);
61           else
62             {
63               /* Special cases tested in precision p1 if n <= 1. */
64               mpfr_set_si (x, n == 0 ? 1 : -1, MPFR_RNDN);
65               mpfr_set_exp (x, mpfr_get_emin ());
66             }
67           if (n < 2 || n > 3 || prec < p1)
68             u = INT_RAND_FUNCTION ();
69           else
70             {
71               /* Special cases tested in precision p1 if n = 2 or 3. */
72               if ((INTEGER_TYPE) -1 < 0)  /* signed, type long assumed */
73                 u = n == 2 ? LONG_MIN : LONG_MAX;
74               else  /* unsigned */
75                 u = n == 2 ? 0 : -1;
76             }
77           rnd = RND_RAND_NO_RNDF ();
78           mpfr_set_prec (y, yprec);
79           compare = TEST_FUNCTION (y, x, u, rnd);
80           if (mpfr_can_round (y, yprec, rnd, rnd, prec))
81             {
82               mpfr_set (t, y, rnd);
83               inexact = TEST_FUNCTION (z, x, u, rnd);
84               if (mpfr_cmp (t, z))
85                 {
86                   printf ("results differ for x=");
87                   mpfr_out_str (stdout, 2, prec, x, MPFR_RNDN);
88                   printf ("\nu=%lu", (unsigned long) u);
89                   printf (" prec=%lu rnd_mode=%s\n",
90                           (unsigned long ) prec, mpfr_print_rnd_mode (rnd));
91 #ifdef TEST_FUNCTION_NAME
92                   printf ("Function: %s\n", TEST_FUNCTION_NAME);
93 #endif
94                   printf ("got      ");
95                   mpfr_dump (z);
96                   printf ("expected ");
97                   mpfr_dump (t);
98                   printf ("approx   ");
99                   mpfr_dump (y);
100                   exit (1);
101                 }
102               compare2 = mpfr_cmp (t, y);
103               /* if rounding to nearest, cannot know the sign of t - f(x)
104                  because of composed rounding: y = o(f(x)) and t = o(y) */
105               if (compare * compare2 >= 0)
106                 compare = compare + compare2;
107               else
108                 compare = inexact; /* cannot determine sign(t-f(x)) */
109               if (! SAME_SIGN (inexact, compare) && rnd != MPFR_RNDF)
110                 {
111                   printf ("Wrong inexact flag for rnd=%s: expected %d, got %d"
112                           "\n", mpfr_print_rnd_mode (rnd), compare, inexact);
113                   printf ("x = "); mpfr_dump (x);
114                   printf ("u = %lu\n", (unsigned long) u);
115                   printf ("y = "); mpfr_dump (y);
116                   printf ("t = "); mpfr_dump (t);
117                   exit (1);
118                 }
119             }
120         }
121     }
122 
123   mpfr_clear (x);
124   mpfr_clear (y);
125   mpfr_clear (z);
126   mpfr_clear (t);
127 }
128 
129 #undef RAND_FUNCTION
130 #undef INTEGER_TYPE
131 #undef TEST_FUNCTION
132 #undef TEST_FUNCTION_NAME
133 #undef test_generic_ui
134 #undef INT_RAND_FUNCTION
135