tsqr.c revision 1.1.1.4 1 /* Test file for mpfr_sqr.
2
3 Copyright 2004-2018 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 http://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 TEST_FUNCTION mpfr_sqr
26 #include "tgeneric.c"
27
28 static int
29 inexact_sign (int x)
30 {
31 return (x < 0) ? -1 : (x > 0);
32 }
33
34 static void
35 error1 (mpfr_rnd_t rnd, mpfr_prec_t prec,
36 mpfr_t in, mpfr_t outmul, mpfr_t outsqr)
37 {
38 printf("ERROR: for %s and prec=%lu\nINPUT=", mpfr_print_rnd_mode(rnd),
39 (unsigned long) prec);
40 mpfr_dump(in);
41 printf("OutputMul="); mpfr_dump(outmul);
42 printf("OutputSqr="); mpfr_dump(outsqr);
43 exit(1);
44 }
45
46 static void
47 error2 (mpfr_rnd_t rnd, mpfr_prec_t prec, mpfr_t in, mpfr_t out,
48 int inexactmul, int inexactsqr)
49 {
50 printf("ERROR: for %s and prec=%lu\nINPUT=", mpfr_print_rnd_mode(rnd),
51 (unsigned long) prec);
52 mpfr_dump(in);
53 printf("Output="); mpfr_dump(out);
54 printf("InexactMul= %d InexactSqr= %d\n", inexactmul, inexactsqr);
55 exit(1);
56 }
57
58 static void
59 check_random (mpfr_prec_t p)
60 {
61 mpfr_t x,y,z;
62 int r;
63 int i, inexact1, inexact2;
64
65 mpfr_inits2 (p, x, y, z, (mpfr_ptr) 0);
66 for(i = 0 ; i < 500 ; i++)
67 {
68 mpfr_urandomb (x, RANDS);
69 if (MPFR_IS_PURE_FP(x))
70 RND_LOOP_NO_RNDF (r)
71 {
72 inexact1 = mpfr_mul (y, x, x, (mpfr_rnd_t) r);
73 inexact2 = mpfr_sqr (z, x, (mpfr_rnd_t) r);
74 if (mpfr_cmp (y, z))
75 error1 ((mpfr_rnd_t) r,p,x,y,z);
76 if (inexact_sign (inexact1) != inexact_sign (inexact2))
77 error2 ((mpfr_rnd_t) r,p,x,y,inexact1,inexact2);
78 }
79 }
80 mpfr_clears (x, y, z, (mpfr_ptr) 0);
81 }
82
83 static void
84 check_special (void)
85 {
86 mpfr_t x, y;
87 mpfr_exp_t emin;
88
89 mpfr_init (x);
90 mpfr_init (y);
91
92 mpfr_set_nan (x);
93 mpfr_sqr (y, x, MPFR_RNDN);
94 MPFR_ASSERTN (mpfr_nan_p (y));
95
96 mpfr_set_inf (x, 1);
97 mpfr_sqr (y, x, MPFR_RNDN);
98 MPFR_ASSERTN (mpfr_inf_p (y) && mpfr_sgn (y) > 0);
99
100 mpfr_set_inf (x, -1);
101 mpfr_sqr (y, x, MPFR_RNDN);
102 MPFR_ASSERTN (mpfr_inf_p (y) && mpfr_sgn (y) > 0);
103
104 mpfr_set_ui (x, 0, MPFR_RNDN);
105 mpfr_sqr (y, x, MPFR_RNDN);
106 MPFR_ASSERTN (mpfr_zero_p (y));
107
108 emin = mpfr_get_emin ();
109 mpfr_set_emin (0);
110 mpfr_set_ui (x, 1, MPFR_RNDN);
111 mpfr_div_2ui (x, x, 1, MPFR_RNDN);
112 MPFR_ASSERTN (!mpfr_zero_p (x));
113 mpfr_sqr (y, x, MPFR_RNDN);
114 MPFR_ASSERTN (mpfr_zero_p (y));
115 mpfr_set_emin (emin);
116
117 mpfr_clear (y);
118 mpfr_clear (x);
119 }
120
121 /* check ax < __gmpfr_emin with rnd_mode == MPFR_RNDN, rb = 0 and sb <> 0 */
122 static void
123 test_underflow (void)
124 {
125 mpfr_t x, y;
126 mpfr_exp_t emin;
127
128 emin = mpfr_get_emin ();
129 mpfr_set_emin (0);
130
131 mpfr_init2 (x, 24);
132 mpfr_init2 (y, 24);
133
134 mpfr_set_ui_2exp (x, 11863283, -24, MPFR_RNDN);
135 /* x^2 = 0.011111111111111111111111101101100111111010101001*2^(-48)
136 thus we have an underflow */
137 mpfr_clear_underflow ();
138 mpfr_sqr (y, x, MPFR_RNDN);
139 MPFR_ASSERTN(mpfr_cmp_ui_2exp (y, 1, -1) == 0);
140 MPFR_ASSERTN(mpfr_underflow_p ());
141
142 mpfr_set_prec (x, 69);
143 mpfr_set_prec (y, 69);
144 mpfr_set_str_binary (x, "0.101101010000010011110011001100111111100111011110011001001000010001011");
145 mpfr_clear_underflow ();
146 mpfr_sqr (y, x, MPFR_RNDN);
147 MPFR_ASSERTN(mpfr_cmp_ui_2exp (y, 1, -1) == 0);
148 MPFR_ASSERTN(mpfr_underflow_p ());
149
150 mpfr_clear (y);
151 mpfr_clear (x);
152
153 mpfr_set_emin (emin);
154 }
155
156 /* Test of a bug seen with GCC 4.5.2 and GMP 5.0.1 on m68k (m68000 target).
157 https://sympa.inria.fr/sympa/arc/mpfr/2011-05/msg00003.html
158 https://sympa.inria.fr/sympa/arc/mpfr/2011-05/msg00041.html
159 */
160 static void
161 check_mpn_sqr (void)
162 {
163 #if GMP_NUMB_BITS == 32 && __GNU_MP_VERSION >= 5
164 /* Note: since we test a low-level bug, src is initialized
165 without using a GMP function, just in case. */
166 mp_limb_t src[5] =
167 { 0x90000000, 0xbaa55f4f, 0x2cbec4d9, 0xfcef3242, 0xda827999 };
168 mp_limb_t exd[10] =
169 { 0x00000000, 0x31000000, 0xbd4bc59a, 0x41fbe2b5, 0x33471e7e,
170 0x90e826a7, 0xbaa55f4f, 0x2cbec4d9, 0xfcef3242, 0xba827999 };
171 mp_limb_t dst[10];
172 int i;
173
174 mpn_sqr (dst, src, 5); /* new in GMP 5 */
175 for (i = 0; i < 10; i++)
176 {
177 if (dst[i] != exd[i])
178 {
179 printf ("Error in check_mpn_sqr\n");
180 printf ("exd[%d] = 0x%08lx\n", i, (unsigned long) exd[i]);
181 printf ("dst[%d] = 0x%08lx\n", i, (unsigned long) dst[i]);
182 printf ("Note: This is not a bug in MPFR, but a bug in"
183 " either GMP or, more\nprobably, in the compiler."
184 " It may cause other tests to fail.\n");
185 exit (1);
186 }
187 }
188 #endif
189 }
190
191 int
192 main (void)
193 {
194 mpfr_prec_t p;
195
196 tests_start_mpfr ();
197
198 check_mpn_sqr ();
199 check_special ();
200 test_underflow ();
201
202 for (p = MPFR_PREC_MIN; p < 200; p++)
203 check_random (p);
204
205 test_generic (MPFR_PREC_MIN, 200, 15);
206 data_check ("data/sqr", mpfr_sqr, "mpfr_sqr");
207 bad_cases (mpfr_sqr, mpfr_sqrt, "mpfr_sqr", 8, -256, 255, 4, 128, 800, 50);
208
209 tests_end_mpfr ();
210 return 0;
211 }
212