1/* Test file for mpfr_sqr. 2 3Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. 4Contributed by the AriC and Caramel projects, INRIA. 5 6This file is part of the GNU MPFR Library. 7 8The GNU MPFR Library is free software; you can redistribute it and/or modify 9it under the terms of the GNU Lesser General Public License as published by 10the Free Software Foundation; either version 3 of the License, or (at your 11option) any later version. 12 13The GNU MPFR Library is distributed in the hope that it will be useful, but 14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16License for more details. 17 18You should have received a copy of the GNU Lesser General Public License 19along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 2151 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 31static int 32inexact_sign (int x) 33{ 34 return (x < 0) ? -1 : (x > 0); 35} 36 37static void 38error1 (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 49static void 50error2 (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 61static void 62check_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 86static void 87check_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*/ 128static void 129check_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 159int 160main (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} 179