github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/mpf/t-sqrt.c (about) 1 /* Test mpf_sqrt, mpf_mul. 2 3 Copyright 1996, 2001, 2004 Free Software Foundation, Inc. 4 5 This file is part of the GNU MP Library test suite. 6 7 The GNU MP Library test suite is free software; you can redistribute it 8 and/or modify it under the terms of the GNU General Public License as 9 published by the Free Software Foundation; either version 3 of the License, 10 or (at your option) any later version. 11 12 The GNU MP Library test suite is distributed in the hope that it will be 13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 15 Public License for more details. 16 17 You should have received a copy of the GNU General Public License along with 18 the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ 19 20 #include <stdio.h> 21 #include <stdlib.h> 22 23 #include "gmp.h" 24 #include "gmp-impl.h" 25 #include "tests.h" 26 27 #ifndef SIZE 28 #define SIZE 16 29 #endif 30 31 void 32 check_rand1 (int argc, char **argv) 33 { 34 mp_size_t size; 35 mp_exp_t exp; 36 int reps = 20000; 37 int i; 38 mpf_t x, y, y2; 39 mp_size_t bprec = 100; 40 mpf_t rerr, max_rerr, limit_rerr; 41 42 if (argc > 1) 43 { 44 reps = strtol (argv[1], 0, 0); 45 if (argc > 2) 46 bprec = strtol (argv[2], 0, 0); 47 } 48 49 mpf_set_default_prec (bprec); 50 51 mpf_init_set_ui (limit_rerr, 1); 52 mpf_div_2exp (limit_rerr, limit_rerr, bprec); 53 #if VERBOSE 54 mpf_dump (limit_rerr); 55 #endif 56 mpf_init (rerr); 57 mpf_init_set_ui (max_rerr, 0); 58 59 mpf_init (x); 60 mpf_init (y); 61 mpf_init (y2); 62 for (i = 0; i < reps; i++) 63 { 64 size = urandom () % SIZE; 65 exp = urandom () % SIZE; 66 mpf_random2 (x, size, exp); 67 68 mpf_sqrt (y, x); 69 MPF_CHECK_FORMAT (y); 70 mpf_mul (y2, y, y); 71 72 mpf_reldiff (rerr, x, y2); 73 if (mpf_cmp (rerr, max_rerr) > 0) 74 { 75 mpf_set (max_rerr, rerr); 76 #if VERBOSE 77 mpf_dump (max_rerr); 78 #endif 79 if (mpf_cmp (rerr, limit_rerr) > 0) 80 { 81 printf ("ERROR after %d tests\n", i); 82 printf (" x = "); mpf_dump (x); 83 printf (" y = "); mpf_dump (y); 84 printf (" y2 = "); mpf_dump (y2); 85 printf (" rerr = "); mpf_dump (rerr); 86 printf (" limit_rerr = "); mpf_dump (limit_rerr); 87 printf ("in hex:\n"); 88 mp_trace_base = 16; 89 mpf_trace (" x ", x); 90 mpf_trace (" y ", y); 91 mpf_trace (" y2 ", y2); 92 mpf_trace (" rerr ", rerr); 93 mpf_trace (" limit_rerr", limit_rerr); 94 abort (); 95 } 96 } 97 } 98 99 mpf_clear (limit_rerr); 100 mpf_clear (rerr); 101 mpf_clear (max_rerr); 102 103 mpf_clear (x); 104 mpf_clear (y); 105 mpf_clear (y2); 106 } 107 108 void 109 check_rand2 (void) 110 { 111 unsigned long max_prec = 20; 112 unsigned long min_prec = __GMPF_BITS_TO_PREC (1); 113 gmp_randstate_ptr rands = RANDS; 114 unsigned long x_prec, r_prec; 115 mpf_t x, r, s; 116 int i; 117 118 mpf_init (x); 119 mpf_init (r); 120 mpf_init (s); 121 refmpf_set_prec_limbs (s, 2*max_prec+10); 122 123 for (i = 0; i < 500; i++) 124 { 125 /* input precision */ 126 x_prec = gmp_urandomm_ui (rands, max_prec-min_prec) + min_prec; 127 refmpf_set_prec_limbs (x, x_prec); 128 129 /* result precision */ 130 r_prec = gmp_urandomm_ui (rands, max_prec-min_prec) + min_prec; 131 refmpf_set_prec_limbs (r, r_prec); 132 133 mpf_random2 (x, x_prec, 1000); 134 135 mpf_sqrt (r, x); 136 MPF_CHECK_FORMAT (r); 137 138 /* Expect to prec limbs of result. 139 In the current implementation there's no stripping of low zero 140 limbs in mpf_sqrt, so size should be exactly prec. */ 141 if (SIZ(r) != r_prec) 142 { 143 printf ("mpf_sqrt wrong number of result limbs\n"); 144 mpf_trace (" x", x); 145 mpf_trace (" r", r); 146 printf (" r_prec=%lu\n", r_prec); 147 printf (" SIZ(r) %ld\n", (long) SIZ(r)); 148 printf (" PREC(r) %ld\n", (long) PREC(r)); 149 abort (); 150 } 151 152 /* Must have r^2 <= x, since r has been truncated. */ 153 mpf_mul (s, r, r); 154 if (! (mpf_cmp (s, x) <= 0)) 155 { 156 printf ("mpf_sqrt result too big\n"); 157 mpf_trace (" x", x); 158 printf (" r_prec=%lu\n", r_prec); 159 mpf_trace (" r", r); 160 mpf_trace (" s", s); 161 abort (); 162 } 163 164 /* Must have (r+ulp)^2 > x, or else r is too small. */ 165 refmpf_add_ulp (r); 166 mpf_mul (s, r, r); 167 if (! (mpf_cmp (s, x) > 0)) 168 { 169 printf ("mpf_sqrt result too small\n"); 170 mpf_trace (" x", x); 171 printf (" r_prec=%lu\n", r_prec); 172 mpf_trace (" r+ulp", r); 173 mpf_trace (" s", s); 174 abort (); 175 } 176 } 177 178 mpf_clear (x); 179 mpf_clear (r); 180 mpf_clear (s); 181 } 182 183 int 184 main (int argc, char **argv) 185 { 186 tests_start (); 187 mp_trace_base = -16; 188 189 check_rand1 (argc, argv); 190 check_rand2 (); 191 192 tests_end (); 193 exit (0); 194 }