1 /* Test mpf_sub. 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 http://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 111 void 112 check_data (void) 113 { 114 static const struct { 115 struct { 116 int exp, size; 117 mp_limb_t d[10]; 118 } x, y, want; 119 120 } data[] = { 121 { { 123, 2, { 8, 9 } }, { 123, 1, { 9 } }, { 122, 1, { 8 } } }, 122 123 /* f - f == 0, various sizes. 124 These exercise a past problem (gmp 4.1.3 and earlier) where the 125 result exponent was not zeroed on a zero result like this. */ 126 { { 0, 0 }, { 0, 0 }, { 0, 0 } }, 127 { { 99, 1, { 1 } }, { 99, 1, { 1 } }, { 0, 0 } }, 128 { { 99, 2, { 123, 456 } }, { 99, 2, { 123, 456 } }, { 0, 0 } }, 129 { { 99, 3, { 123, 456, 789 } }, { 99, 3, { 123, 456, 789 } }, { 0, 0 } }, 130 131 /* High limbs cancel, leaving just the low limbs of the longer operand. 132 This exercises a past problem (gmp 4.1.3 and earlier) where high zero 133 limbs on the remainder were not stripped before truncating to the 134 destination, causing loss of precision. */ 135 { { 123, 2, { 8, 9 } }, { 123, 1, { 9 } }, { 122, 1, { 8 } } }, 136 { { 123, 3, { 8, 0, 9 } }, { 123, 1, { 9 } }, { 121, 1, { 8 } } }, 137 { { 123, 4, { 8, 0, 0, 9 } }, { 123, 1, { 9 } }, { 120, 1, { 8 } } }, 138 { { 123, 5, { 8, 0, 0, 0, 9 } }, { 123, 1, { 9 } }, { 119, 1, { 8 } } }, 139 { { 123, 6, { 8, 0, 0, 0, 0, 9 } }, { 123, 1, { 9 } }, { 118, 1, { 8 } } }, 140 141 }; 142 143 mpf_t x, y, got, want; 144 int i, swap; 145 146 mp_trace_base = 16; 147 mpf_init (got); 148 149 for (i = 0; i < numberof (data); i++) 150 { 151 for (swap = 0; swap <= 1; swap++) 152 { 153 PTR(x) = (mp_ptr) data[i].x.d; 154 SIZ(x) = data[i].x.size; 155 EXP(x) = data[i].x.exp; 156 PREC(x) = numberof (data[i].x.d); 157 MPF_CHECK_FORMAT (x); 158 159 PTR(y) = (mp_ptr) data[i].y.d; 160 SIZ(y) = data[i].y.size; 161 EXP(y) = data[i].y.exp; 162 PREC(y) = numberof (data[i].y.d); 163 MPF_CHECK_FORMAT (y); 164 165 PTR(want) = (mp_ptr) data[i].want.d; 166 SIZ(want) = data[i].want.size; 167 EXP(want) = data[i].want.exp; 168 PREC(want) = numberof (data[i].want.d); 169 MPF_CHECK_FORMAT (want); 170 171 if (swap) 172 { 173 mpf_swap (x, y); 174 SIZ(want) = - SIZ(want); 175 } 176 177 mpf_sub (got, x, y); 178 /* MPF_CHECK_FORMAT (got); */ 179 180 if (mpf_cmp (got, want) != 0) 181 { 182 printf ("check_data() wrong reault at data[%d] (operands%s swapped)\n", i, swap ? "" : " not"); 183 mpf_trace ("x ", x); 184 mpf_trace ("y ", y); 185 mpf_trace ("got ", got); 186 mpf_trace ("want", want); 187 abort (); 188 } 189 } 190 } 191 192 mpf_clear (got); 193 } 194 195 196 int 197 main (int argc, char **argv) 198 { 199 tests_start (); 200 201 check_data (); 202 check_rand (argc, argv); 203 204 tests_end (); 205 exit (0); 206 } 207