MPFR v4.0.2
[mpfr.git] / tests / tsub_ui.c
1 /* Test file for mpfr_sub_ui
2
3 Copyright 2000-2019 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
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
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
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
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 }