xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tsub_ui.c (revision ba125506a622fe649968631a56eba5d42ff57863)
1 /* Test file for mpfr_sub_ui
2 
3 Copyright 2000-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 <float.h>
24 
25 #include "mpfr-test.h"
26 
27 /* checks that x-y gives the right results with 53 bits of precision */
28 static void
check3(const char * xs,unsigned long y,mpfr_rnd_t rnd_mode,const char * zs)29 check3 (const char *xs, unsigned long y, mpfr_rnd_t rnd_mode, const char *zs)
30 {
31   mpfr_t xx,zz;
32 
33   mpfr_inits2 (53, xx, zz, (mpfr_ptr) 0);
34   mpfr_set_str1 (xx, xs);
35   mpfr_sub_ui (zz, xx, y, rnd_mode);
36   if (mpfr_cmp_str1(zz, zs))
37     {
38       printf ("expected sum is %s, got ", zs);
39       mpfr_dump (zz);
40       printf ("mpfr_sub_ui failed for x=%s y=%lu with rnd_mode=%s\n",
41               xs, y, mpfr_print_rnd_mode (rnd_mode));
42       exit (1);
43     }
44   mpfr_clears (xx, zz, (mpfr_ptr) 0);
45 }
46 
47 /* FastTwoSum: if EXP(x) >= EXP(y), u = o(x+y), v = o(u-x), w = o(y-v),
48                then x + y = u + w
49 thus if u = o(y-x), v = o(u+x), w = o(v-y), then y-x = u-w */
50 static void
check_two_sum(mpfr_prec_t p)51 check_two_sum (mpfr_prec_t p)
52 {
53   unsigned int x;
54   mpfr_t y, u, v, w;
55   mpfr_rnd_t rnd;
56   int inexact;
57 
58   mpfr_inits2 (p, y, u, v, w, (mpfr_ptr) 0);
59   do
60     {
61       x = randlimb ();
62     }
63   while (x < 1);
64   mpfr_urandomb (y, RANDS);
65   rnd = MPFR_RNDN;
66   inexact = mpfr_sub_ui (u, y, x, rnd);
67   mpfr_add_ui (v, u, x, rnd);
68   mpfr_sub (w, v, y, rnd);
69   /* as u - (y-x) = w, we should have inexact and w of same sign */
70   if (((inexact == 0) && mpfr_cmp_ui (w, 0)) ||
71       ((inexact > 0) && (mpfr_cmp_ui (w, 0) <= 0)) ||
72       ((inexact < 0) && (mpfr_cmp_ui (w, 0) >= 0)))
73     {
74       printf ("Wrong inexact flag for prec=%u, rnd=%s\n",
75               (unsigned int) p, mpfr_print_rnd_mode (rnd));
76       printf ("x=%u\n", x);
77       printf ("y="); mpfr_dump (y);
78       printf ("u="); mpfr_dump (u);
79       printf ("v="); mpfr_dump (v);
80       printf ("w="); mpfr_dump (w);
81       printf ("inexact = %d\n", inexact);
82       exit (1);
83     }
84   mpfr_clears (y, u, v, w, (mpfr_ptr) 0);
85 }
86 
87 static void
check_nans(void)88 check_nans (void)
89 {
90   mpfr_t  x, y;
91 
92   mpfr_init2 (x, 123L);
93   mpfr_init2 (y, 123L);
94 
95   /* nan - 1 == nan */
96   mpfr_set_nan (x);
97   mpfr_clear_nanflag ();
98   mpfr_sub_ui (y, x, 1L, MPFR_RNDN);
99   MPFR_ASSERTN (mpfr_nanflag_p ());
100   MPFR_ASSERTN (mpfr_nan_p (y));
101 
102   /* +inf - 1 == +inf */
103   mpfr_set_inf (x, 1);
104   mpfr_sub_ui (y, x, 1L, MPFR_RNDN);
105   MPFR_ASSERTN (mpfr_inf_p (y));
106   MPFR_ASSERTN (mpfr_sgn (y) > 0);
107 
108   /* -inf - 1 == -inf */
109   mpfr_set_inf (x, -1);
110   mpfr_sub_ui (y, x, 1L, MPFR_RNDN);
111   MPFR_ASSERTN (mpfr_inf_p (y));
112   MPFR_ASSERTN (mpfr_sgn (y) < 0);
113 
114   mpfr_clear (x);
115   mpfr_clear (y);
116 }
117 
118 #define TEST_FUNCTION mpfr_sub_ui
119 #define ULONG_ARG2
120 #define RAND_FUNCTION(x) mpfr_random2(x, MPFR_LIMB_SIZE (x), 1, RANDS)
121 #include "tgeneric.c"
122 
123 int
main(int argc,char * argv[])124 main (int argc, char *argv[])
125 {
126   mpfr_prec_t p;
127   int k;
128 
129   tests_start_mpfr ();
130 
131   check_nans ();
132 
133   for (p=2; p<200; p++)
134     for (k=0; k<200; k++)
135       check_two_sum (p);
136 
137   check3 ("0.9999999999", 1, MPFR_RNDN,
138           "-10000000827403709990903735160827636718750e-50");
139 
140   test_generic (MPFR_PREC_MIN, 1000, 100);
141 
142   tests_end_mpfr ();
143   return 0;
144 }
145