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