1 /* Test mpn_add_1 and mpn_sub_1. 2 3 Copyright 2001, 2002 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-impl.h" 24 #include "tests.h" 25 26 27 #define M GMP_NUMB_MAX 28 #define ASIZE 10 29 #define MAGIC 0x1234 30 31 #define SETUP() \ 32 do { \ 33 refmpn_random (got, data[i].size); \ 34 got[data[i].size] = MAGIC; \ 35 } while (0) 36 37 #define SETUP_INPLACE() \ 38 do { \ 39 refmpn_copyi (got, data[i].src, data[i].size); \ 40 got[data[i].size] = MAGIC; \ 41 } while (0) 42 43 #define VERIFY(name) \ 44 do { \ 45 verify (name, i, data[i].src, data[i].n, \ 46 got_c, data[i].want_c, \ 47 got, data[i].want, data[i].size); \ 48 } while (0) 49 50 typedef mp_limb_t (*mpn_aors_1_t) (mp_ptr, mp_srcptr, mp_size_t, mp_limb_t); 51 mpn_aors_1_t fudge (mpn_aors_1_t); 52 53 54 void 55 verify (const char *name, int i, 56 mp_srcptr src, mp_limb_t n, 57 mp_limb_t got_c, mp_limb_t want_c, 58 mp_srcptr got, mp_srcptr want, mp_size_t size) 59 { 60 if (got[size] != MAGIC) 61 { 62 printf ("Overwrite at %s i=%d\n", name, i); 63 abort (); 64 } 65 66 if (got_c != want_c || ! refmpn_equal_anynail (got, want, size)) 67 { 68 printf ("Wrong at %s i=%d size=%ld\n", name, i, size); 69 mpn_trace (" src", src, size); 70 mpn_trace (" n", &n, (mp_size_t) 1); 71 mpn_trace (" got", got, size); 72 mpn_trace (" want", want, size); 73 mpn_trace (" got c", &got_c, (mp_size_t) 1); 74 mpn_trace ("want c", &want_c, (mp_size_t) 1); 75 abort (); 76 } 77 } 78 79 80 void 81 check_add_1 (void) 82 { 83 static const struct { 84 mp_size_t size; 85 mp_limb_t n; 86 const mp_limb_t src[ASIZE]; 87 mp_limb_t want_c; 88 const mp_limb_t want[ASIZE]; 89 } data[] = { 90 { 1, 0, { 0 }, 0, { 0 } }, 91 { 1, 0, { 1 }, 0, { 1 } }, 92 { 1, 1, { 0 }, 0, { 1 } }, 93 { 1, 0, { M }, 0, { M } }, 94 { 1, M, { 0 }, 0, { M } }, 95 { 1, 1, { 123 }, 0, { 124 } }, 96 97 { 1, 1, { M }, 1, { 0 } }, 98 { 1, M, { 1 }, 1, { 0 } }, 99 { 1, M, { M }, 1, { M-1 } }, 100 101 { 2, 0, { 0, 0 }, 0, { 0, 0 } }, 102 { 2, 0, { 1, 0 }, 0, { 1, 0 } }, 103 { 2, 1, { 0, 0 }, 0, { 1, 0 } }, 104 { 2, 0, { M, 0 }, 0, { M, 0 } }, 105 { 2, M, { 0, 0 }, 0, { M, 0 } }, 106 { 2, 1, { M, 0 }, 0, { 0, 1 } }, 107 { 2, M, { 1, 0 }, 0, { 0, 1 } }, 108 { 2, M, { M, 0 }, 0, { M-1, 1 } }, 109 { 2, M, { M, 0 }, 0, { M-1, 1 } }, 110 111 { 2, 1, { M, M }, 1, { 0, 0 } }, 112 { 2, M, { 1, M }, 1, { 0, 0 } }, 113 { 2, M, { M, M }, 1, { M-1, 0 } }, 114 { 2, M, { M, M }, 1, { M-1, 0 } }, 115 116 { 3, 1, { M, M, M }, 1, { 0, 0, 0 } }, 117 { 3, M, { 1, M, M }, 1, { 0, 0, 0 } }, 118 { 3, M, { M, M, M }, 1, { M-1, 0, 0 } }, 119 { 3, M, { M, M, M }, 1, { M-1, 0, 0 } }, 120 121 { 4, 1, { M, M, M, M }, 1, { 0, 0, 0, 0 } }, 122 { 4, M, { 1, M, M, M }, 1, { 0, 0, 0, 0 } }, 123 { 4, M, { M, M, M, M }, 1, { M-1, 0, 0, 0 } }, 124 { 4, M, { M, M, M, M }, 1, { M-1, 0, 0, 0 } }, 125 126 { 4, M, { M, 0, M, M }, 0, { M-1, 1, M, M } }, 127 { 4, M, { M, M-1, M, M }, 0, { M-1, M, M, M } }, 128 129 { 4, M, { M, M, 0, M }, 0, { M-1, 0, 1, M } }, 130 { 4, M, { M, M, M-1, M }, 0, { M-1, 0, M, M } }, 131 }; 132 133 mp_limb_t got[ASIZE]; 134 mp_limb_t got_c; 135 /* mpn_sec_add_a_itch(n) <= n */ 136 mp_limb_t scratch[ASIZE]; 137 int i; 138 139 for (i = 0; i < numberof (data); i++) 140 { 141 SETUP (); 142 got_c = mpn_add_1 (got, data[i].src, data[i].size, data[i].n); 143 VERIFY ("check_add_1 (separate)"); 144 145 SETUP_INPLACE (); 146 got_c = mpn_add_1 (got, got, data[i].size, data[i].n); 147 VERIFY ("check_add_1 (in-place)"); 148 149 SETUP (); 150 scratch [mpn_sec_add_1_itch(data[i].size)] = MAGIC; 151 got_c = mpn_sec_add_1 (got, data[i].src, data[i].size, data[i].n, scratch); 152 got_c ^= scratch [mpn_sec_add_1_itch(data[i].size)] ^ MAGIC; 153 VERIFY ("check_sec_add_1 (separate)"); 154 155 SETUP_INPLACE (); 156 got_c = mpn_sec_add_1 (got, got, data[i].size, data[i].n, scratch); 157 VERIFY ("check_sec_add_1 (in-place)"); 158 159 if (data[i].n == 1) 160 { 161 SETUP (); 162 got_c = mpn_add_1 (got, data[i].src, data[i].size, CNST_LIMB(1)); 163 VERIFY ("check_add_1 (separate, const 1)"); 164 165 SETUP_INPLACE (); 166 got_c = mpn_add_1 (got, got, data[i].size, CNST_LIMB(1)); 167 VERIFY ("check_add_1 (in-place, const 1)"); 168 169 SETUP (); 170 got_c = mpn_sec_add_1 (got, data[i].src, data[i].size, 171 CNST_LIMB(1), scratch); 172 VERIFY ("check_sec_add_1 (separate, const 1)"); 173 174 SETUP_INPLACE (); 175 got_c = mpn_sec_add_1 (got, got, data[i].size, 176 CNST_LIMB(1), scratch); 177 VERIFY ("check_sec_add_1 (in-place, const 1)"); 178 } 179 180 /* Same again on functions, not inlines. */ 181 SETUP (); 182 got_c = (*fudge(mpn_add_1)) (got, data[i].src, data[i].size, data[i].n); 183 VERIFY ("check_add_1 (function, separate)"); 184 185 SETUP_INPLACE (); 186 got_c = (*fudge(mpn_add_1)) (got, got, data[i].size, data[i].n); 187 VERIFY ("check_add_1 (function, in-place)"); 188 } 189 } 190 191 void 192 check_sub_1 (void) 193 { 194 static const struct { 195 mp_size_t size; 196 mp_limb_t n; 197 const mp_limb_t src[ASIZE]; 198 mp_limb_t want_c; 199 const mp_limb_t want[ASIZE]; 200 } data[] = { 201 { 1, 0, { 0 }, 0, { 0 } }, 202 { 1, 0, { 1 }, 0, { 1 } }, 203 { 1, 1, { 1 }, 0, { 0 } }, 204 { 1, 0, { M }, 0, { M } }, 205 { 1, 1, { M }, 0, { M-1 } }, 206 { 1, 1, { 123 }, 0, { 122 } }, 207 208 { 1, 1, { 0 }, 1, { M } }, 209 { 1, M, { 0 }, 1, { 1 } }, 210 211 { 2, 0, { 0, 0 }, 0, { 0, 0 } }, 212 { 2, 0, { 1, 0 }, 0, { 1, 0 } }, 213 { 2, 1, { 1, 0 }, 0, { 0, 0 } }, 214 { 2, 0, { M, 0 }, 0, { M, 0 } }, 215 { 2, 1, { M, 0 }, 0, { M-1, 0 } }, 216 { 2, 1, { 123, 0 }, 0, { 122, 0 } }, 217 218 { 2, 1, { 0, 0 }, 1, { M, M } }, 219 { 2, M, { 0, 0 }, 1, { 1, M } }, 220 221 { 3, 0, { 0, 0, 0 }, 0, { 0, 0, 0 } }, 222 { 3, 0, { 123, 0, 0 }, 0, { 123, 0, 0 } }, 223 224 { 3, 1, { 0, 0, 0 }, 1, { M, M, M } }, 225 { 3, M, { 0, 0, 0 }, 1, { 1, M, M } }, 226 227 { 4, 1, { 0, 0, 0, 0 }, 1, { M, M, M, M } }, 228 { 4, M, { 0, 0, 0, 0 }, 1, { 1, M, M, M } }, 229 230 { 4, 1, { 0, 0, 1, 42 }, 0, { M, M, 0, 42 } }, 231 { 4, M, { 0, 0, 123, 24 }, 0, { 1, M, 122, 24 } }, 232 }; 233 234 mp_limb_t got[ASIZE]; 235 mp_limb_t got_c; 236 /* mpn_sec_sub_1_itch(n) <= n */ 237 mp_limb_t scratch[ASIZE]; 238 int i; 239 240 for (i = 0; i < numberof (data); i++) 241 { 242 SETUP (); 243 got_c = mpn_sub_1 (got, data[i].src, data[i].size, data[i].n); 244 VERIFY ("check_sub_1 (separate)"); 245 246 SETUP_INPLACE (); 247 got_c = mpn_sub_1 (got, got, data[i].size, data[i].n); 248 VERIFY ("check_sub_1 (in-place)"); 249 250 SETUP (); 251 scratch [mpn_sec_sub_1_itch(data[i].size)] = MAGIC; 252 got_c = mpn_sec_sub_1 (got, data[i].src, data[i].size, data[i].n, scratch); 253 got_c ^= scratch [mpn_sec_sub_1_itch(data[i].size)] ^ MAGIC; 254 VERIFY ("check_sec_sub_1 (separate)"); 255 256 SETUP_INPLACE (); 257 got_c = mpn_sec_sub_1 (got, got, data[i].size, data[i].n, scratch); 258 VERIFY ("check_sec_sub_1 (in-place)"); 259 260 if (data[i].n == 1) 261 { 262 SETUP (); 263 got_c = mpn_sub_1 (got, data[i].src, data[i].size, CNST_LIMB(1)); 264 VERIFY ("check_sub_1 (separate, const 1)"); 265 266 SETUP_INPLACE (); 267 got_c = mpn_sub_1 (got, got, data[i].size, CNST_LIMB(1)); 268 VERIFY ("check_sub_1 (in-place, const 1)"); 269 270 SETUP (); 271 got_c = mpn_sec_sub_1 (got, data[i].src, data[i].size, 272 CNST_LIMB(1), scratch); 273 VERIFY ("check_sec_sub_1 (separate, const 1)"); 274 275 SETUP_INPLACE (); 276 got_c = mpn_sec_sub_1 (got, got, data[i].size, 277 CNST_LIMB(1), scratch); 278 VERIFY ("check_sec_sub_1 (in-place, const 1)"); 279 } 280 281 /* Same again on functions, not inlines. */ 282 SETUP (); 283 got_c = (*fudge(mpn_sub_1)) (got, data[i].src, data[i].size, data[i].n); 284 VERIFY ("check_sub_1 (function, separate)"); 285 286 SETUP_INPLACE (); 287 got_c = (*fudge(mpn_sub_1)) (got, got, data[i].size, data[i].n); 288 VERIFY ("check_sub_1 (function, in-place)"); 289 } 290 } 291 292 /* Try to prevent the optimizer inlining. */ 293 mpn_aors_1_t 294 fudge (mpn_aors_1_t f) 295 { 296 return f; 297 } 298 299 int 300 main (void) 301 { 302 tests_start (); 303 mp_trace_base = -16; 304 305 check_add_1 (); 306 check_sub_1 (); 307 308 tests_end (); 309 exit (0); 310 } 311