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