github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/tests/mpf/t-sub.c (about) 1 /* Test mpf_sub. 2 3 Copyright 1996, 2001, 2004, 2014 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_rand (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 u, v, w, wref; 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 (u); 60 mpf_init (v); 61 mpf_init (w); 62 mpf_init (wref); 63 for (i = 0; i < reps; i++) 64 { 65 size = urandom () % (2 * SIZE) - SIZE; 66 exp = urandom () % SIZE; 67 mpf_random2 (u, size, exp); 68 69 size = urandom () % (2 * SIZE) - SIZE; 70 exp = urandom () % SIZE; 71 mpf_random2 (v, size, exp); 72 73 if ((urandom () & 1) != 0) 74 mpf_add_ui (u, v, 1); 75 else if ((urandom () & 1) != 0) 76 mpf_sub_ui (u, v, 1); 77 78 mpf_sub (w, u, v); 79 refmpf_sub (wref, u, v); 80 81 mpf_reldiff (rerr, w, wref); 82 if (mpf_cmp (rerr, max_rerr) > 0) 83 { 84 mpf_set (max_rerr, rerr); 85 #if VERBOSE 86 mpf_dump (max_rerr); 87 #endif 88 if (mpf_cmp (rerr, limit_rerr) > 0) 89 { 90 printf ("ERROR after %d tests\n", i); 91 printf (" u = "); mpf_dump (u); 92 printf (" v = "); mpf_dump (v); 93 printf ("wref = "); mpf_dump (wref); 94 printf (" w = "); mpf_dump (w); 95 abort (); 96 } 97 } 98 } 99 100 mpf_clear (limit_rerr); 101 mpf_clear (rerr); 102 mpf_clear (max_rerr); 103 104 mpf_clear (u); 105 mpf_clear (v); 106 mpf_clear (w); 107 mpf_clear (wref); 108 } 109 110 #define W GMP_NUMB_MAX 111 112 void 113 check_data (void) 114 { 115 static const struct { 116 struct { 117 int exp, size; 118 mp_limb_t d[10]; 119 } x, y, want; 120 121 } data[] = { 122 { { 123, 2, { 8, 9 } }, { 123, 1, { 9 } }, { 122, 1, { 8 } } }, 123 { { 1, 1, { 9 } }, { 1, 1, { 8 } }, { 1, 1, { 1 } } }, 124 { { 1, 1, { 9 } }, { 1, -1, { 6 } }, { 1, 1, { 15 } } }, 125 { { 1, 2, { 8, 9 } }, { 1, 1, { 8 } }, { 1, 2, { 8, 1 } } }, 126 { { 2, 2, { 8, 1 } }, { 1, 1, { 9 } }, { 1, 1, { W } } }, 127 { { 2, 2, { 9, 8 } }, { 1, 1, { 9 } }, { 2, 1, { 8 } } }, 128 { { 2, 1, { 1 } }, { 1, 1, { 1 } }, { 1, 1, { W } } }, 129 { { 2, 1, { 9 } }, { 1, 1, { W } }, { 2, 2, { 1, 8 } } }, 130 131 { { 1, 2, { W, 8 } }, { 1, 1, { 9 } }, { 0, -1, { 1 } } }, 132 { { 1, 2, { W, 7 } }, { 1, 1, { 9 } }, { 1, -2, { 1, 1 } } }, 133 { { 1, 2, { 1, 8 } }, { 1, 1, { 9 } }, { 0, -1, { W } } }, 134 { { 1, 2, { 1, 7 } }, { 1, 1, { 9 } }, { 1, -2, { W, 1 } } }, 135 { { 1, 2, { 0, 8 } }, { 1, 1, { 9 } }, { 1, -1, { 1 } } }, 136 { { 2, 3, { 5, 8, 1 } }, { 1, 1, { 9 } }, { 1, 2, { 5, W } } }, 137 { { 3, 1, { 1 } }, { 1, 1, { 1 } }, { 2, 2, { W, W } } }, 138 { { 1, 6, { W, W, W, W, W, 8 } }, { 1, 1, { 9 } }, { -4, -1, { 1 } } }, 139 { { 5, 5, { W-6, W, W, W, W } }, { 6, 1, { 1 } }, { 1, -1, { 7 } } }, 140 141 /* f - f == 0, various sizes. 142 These exercise a past problem (gmp 4.1.3 and earlier) where the 143 result exponent was not zeroed on a zero result like this. */ 144 { { 0, 0 }, { 0, 0 }, { 0, 0 } }, 145 { { 99, 3, { 0, 0, 1 } }, { 99, 1, { 1 } }, { 0, 0 } }, 146 { { 99, 3, { 0, 123, 456 } }, { 99, 2, { 123, 456 } }, { 0, 0 } }, 147 { { 99, 3, { 123, 456, 789 } }, { 99, 3, { 123, 456, 789 } }, { 0, 0 } }, 148 149 /* High limbs cancel, leaving just the low limbs of the longer operand. 150 This exercises a past problem (gmp 4.1.3 and earlier) where high zero 151 limbs on the remainder were not stripped before truncating to the 152 destination, causing loss of precision. */ 153 { { 123, 2, { 8, 9 } }, { 123, 1, { 9 } }, { 122, 1, { 8 } } }, 154 { { 123, 3, { 8, 0, 9 } }, { 123, 1, { 9 } }, { 121, 1, { 8 } } }, 155 { { 123, 4, { 8, 0, 0, 9 } }, { 123, 1, { 9 } }, { 120, 1, { 8 } } }, 156 { { 123, 5, { 8, 0, 0, 0, 9 } }, { 123, 1, { 9 } }, { 119, 1, { 8 } } }, 157 { { 123, 6, { 8, 0, 0, 0, 0, 9 } }, { 123, 1, { 9 } }, { 118, 1, { 8 } } }, 158 /* { { 123, 6, { 8, 0, 0, 0, 0, 9 } }, { 123, 6, { 9, 0, 0, 0, 0, 8 } }, { 122, 5, { W, W, W, W, W } } }, */ 159 160 }; 161 162 mpf_t x, y, got, want; 163 int i, swap, fail; 164 165 fail = 0; 166 mp_trace_base = 16; 167 mpf_init (got); 168 169 for (i = 0; i < numberof (data); i++) 170 { 171 for (swap = 0; swap <= 7; swap++) 172 { 173 PTR(x) = (mp_ptr) data[i].x.d; 174 SIZ(x) = data[i].x.size; 175 EXP(x) = data[i].x.exp; 176 PREC(x) = numberof (data[i].x.d); 177 MPF_CHECK_FORMAT (x); 178 179 PTR(y) = (mp_ptr) data[i].y.d; 180 SIZ(y) = data[i].y.size; 181 EXP(y) = data[i].y.exp; 182 PREC(y) = numberof (data[i].y.d); 183 MPF_CHECK_FORMAT (y); 184 185 PTR(want) = (mp_ptr) data[i].want.d; 186 SIZ(want) = data[i].want.size; 187 EXP(want) = data[i].want.exp; 188 PREC(want) = numberof (data[i].want.d); 189 MPF_CHECK_FORMAT (want); 190 191 if (swap & 4) 192 { 193 mpf_swap (want, y); 194 } 195 196 if ((SIZ (x) ^ SIZ (y)) < 0) 197 continue; /* It's an addition, not a subtraction (TO BE REMOVED) */ 198 199 if (swap & 1) 200 { 201 mpf_swap (x, y); 202 SIZ(want) = - SIZ(want); 203 } 204 205 if (swap & 2) 206 { 207 SIZ(want) = - SIZ(want); 208 SIZ(x) = - SIZ(x); 209 SIZ(y) = - SIZ(y); 210 } 211 212 mpf_sub (got, x, y); 213 /* MPF_CHECK_FORMAT (got); */ 214 215 if (! refmpf_validate ("mpf_sub", got, want)) 216 { 217 printf ("check_data() wrong result at data[%d] (operands%s swapped)\n", i, swap ? "" : " not"); 218 mpf_trace ("x ", x); 219 mpf_trace ("y ", y); 220 mpf_trace ("got ", got); 221 mpf_trace ("want", want); 222 fail = 1; 223 } 224 225 if (SIZ (x) == 1 || SIZ (x) == 0 ) 226 { 227 if (SIZ (y)) EXP (y) -= EXP (x) - (mp_exp_t) SIZ (x); 228 if (SIZ (want)) EXP (want) -= EXP (x) - (mp_exp_t) SIZ (x); 229 EXP (x) = (mp_exp_t) SIZ (x); 230 231 if (mpf_fits_uint_p (x)) 232 { 233 mpf_ui_sub (got, mpf_get_ui (x), y); 234 235 if (! refmpf_validate ("mpf_ui_sub", got, want)) 236 { 237 printf ("check_data() wrong result at data[%d] (operands%s swapped)\n", i, swap ? "" : " not"); 238 mpf_trace ("x ", x); 239 mpf_trace ("y ", y); 240 mpf_trace ("got ", got); 241 mpf_trace ("want", want); 242 fail = 1; 243 } 244 } 245 } 246 247 if (SIZ (y) == 1 || SIZ (y) == 0) 248 { 249 if (SIZ (x)) EXP (x) -= EXP (y) - (mp_exp_t) SIZ (y); 250 if (SIZ (want)) EXP (want) -= EXP (y) - (mp_exp_t) SIZ (y); 251 EXP (y) = (mp_exp_t) SIZ (y); 252 253 if (mpf_fits_uint_p (x)) 254 { 255 mpf_sub_ui (got, x, mpf_get_ui (y)); 256 257 if (! refmpf_validate ("mpf_sub_ui", got, want)) 258 { 259 printf ("check_data() wrong result at data[%d] (operands%s swapped)\n", i, swap ? "" : " not"); 260 mpf_trace ("x ", x); 261 mpf_trace ("y ", y); 262 mpf_trace ("got ", got); 263 mpf_trace ("want", want); 264 fail = 1; 265 } 266 } 267 } 268 269 } 270 } 271 272 mpf_clear (got); 273 if (fail) 274 abort (); 275 } 276 277 278 int 279 main (int argc, char **argv) 280 { 281 tests_start (); 282 283 check_data (); 284 check_rand (argc, argv); 285 286 tests_end (); 287 exit (0); 288 }