1 1.1 mrg /* 2 1.1 mrg Copyright 2017 Free Software Foundation, Inc. 3 1.1 mrg 4 1.1 mrg This file is part of the GNU MP Library test suite. 5 1.1 mrg 6 1.1 mrg The GNU MP Library test suite is free software; you can redistribute it 7 1.1 mrg and/or modify it under the terms of the GNU General Public License as 8 1.1 mrg published by the Free Software Foundation; either version 3 of the License, 9 1.1 mrg or (at your option) any later version. 10 1.1 mrg 11 1.1 mrg The GNU MP Library test suite is distributed in the hope that it will be 12 1.1 mrg useful, but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 14 1.1 mrg Public License for more details. 15 1.1 mrg 16 1.1 mrg You should have received a copy of the GNU General Public License along with 17 1.1 mrg the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */ 18 1.1 mrg 19 1.1 mrg /* Usage: 20 1.1 mrg 21 1.1 mrg ./sqrtrem_1_2 x 22 1.1 mrg 23 1.1 mrg Checks mpn_sqrtrem() exhaustively, starting from 0, incrementing 24 1.1 mrg the operand by a single unit, until all values handled by 25 1.1 mrg mpn_sqrtrem{1,2} are tested. SLOW. 26 1.1 mrg 27 1.1 mrg ./sqrtrem_1_2 s 1 28 1.1 mrg 29 1.1 mrg Checks some special cases for mpn_sqrtrem(). I.e. values of the form 30 1.1 mrg 2^k*i and 2^k*(i+1)-1, with k=2^n and 0<i<2^k, until all such values, 31 1.1 mrg handled by mpn_sqrtrem{1,2}, are tested. 32 1.1 mrg Currently supports only the test of values that fits in one limb. 33 1.1 mrg Less slow than the exhaustive test. 34 1.1 mrg 35 1.1 mrg ./sqrtrem_1_2 c 36 1.1 mrg 37 1.1 mrg Checks all corner cases for mpn_sqrtrem(). I.e. values of the form 38 1.1 mrg i*i and (i+1)*(i+1)-1, for each value of i, until all such values, 39 1.1 mrg handled by mpn_sqrtrem{1,2}, are tested. 40 1.1 mrg Slightly faster than the special cases test. 41 1.1 mrg 42 1.1 mrg For larger values, use 43 1.1 mrg ./try mpn_sqrtrem 44 1.1 mrg 45 1.1 mrg */ 46 1.1 mrg 47 1.1 mrg #include <stdlib.h> 48 1.1 mrg #include <stdio.h> 49 1.1 mrg #include "gmp-impl.h" 50 1.1 mrg #include "longlong.h" 51 1.1 mrg #include "tests.h" 52 1.1 mrg #define STOP(x) return (x) 53 1.1 mrg /* #define STOP(x) x */ 54 1.1 mrg #define SPINNER(v) \ 55 1.1 mrg do { \ 56 1.1 mrg MPN_SIZEINBASE_2EXP (spinner_count, q, v, 1); \ 57 1.1 mrg --spinner_count; \ 58 1.1 mrg spinner(); \ 59 1.1 mrg } while (0) 60 1.1 mrg 61 1.1 mrg int something_wrong (mp_limb_t er, mp_limb_t ec, mp_limb_t es) 62 1.1 mrg { 63 1.1 mrg fprintf (stderr, "root = %lu , rem = {%lu , %lu}\n", (long unsigned) es,(long unsigned) ec,(long unsigned) er); 64 1.1 mrg return -1; 65 1.1 mrg } 66 1.1 mrg 67 1.1 mrg int 68 1.1 mrg check_all_values (int justone, int quick) 69 1.1 mrg { 70 1.1 mrg mp_limb_t es, mer, er, s[1], r[2], q[2]; 71 1.1 mrg mp_size_t x; 72 1.1 mrg unsigned bits; 73 1.1 mrg 74 1.1 mrg es=1; 75 1.1 mrg if (quick) { 76 1.1 mrg printf ("Quick, skipping some... (%u)\n", GMP_NUMB_BITS - 2); 77 1.1 mrg es <<= GMP_NUMB_BITS / 2 - 1; 78 1.1 mrg } 79 1.1 mrg er=0; 80 1.1 mrg mer= es << 1; 81 1.1 mrg *q = es * es; 82 1.1 mrg printf ("All values tested, up to bits:\n"); 83 1.1 mrg do { 84 1.1 mrg x = mpn_sqrtrem (s, r, q, 1); 85 1.1 mrg if (UNLIKELY (x != (er != 0)) || UNLIKELY (*s != es) 86 1.1 mrg || UNLIKELY ((x == 1) && (er != *r))) 87 1.1 mrg STOP (something_wrong (er, 0, es)); 88 1.1 mrg 89 1.1 mrg if (UNLIKELY (er == mer)) { 90 1.1 mrg ++es; 91 1.1 mrg if (UNLIKELY ((es & 0xff) == 0)) 92 1.1 mrg SPINNER(1); 93 1.1 mrg mer +=2; /* mer = es * 2 */ 94 1.1 mrg er = 0; 95 1.1 mrg } else 96 1.1 mrg ++er; 97 1.1 mrg ++*q; 98 1.1 mrg } while (*q != 0); 99 1.1 mrg q[1] = 1; 100 1.1 mrg SPINNER(2); 101 1.1 mrg printf ("\nValues of a single limb, tested.\n"); 102 1.1 mrg if (justone) return 0; 103 1.1 mrg printf ("All values tested, up to bits:\n"); 104 1.1 mrg do { 105 1.1 mrg x = mpn_sqrtrem (s, r, q, 2); 106 1.1 mrg if (UNLIKELY (x != (er != 0)) || UNLIKELY (*s != es) 107 1.1 mrg || UNLIKELY ((x == 1) && (er != *r))) 108 1.1 mrg STOP (something_wrong (er, 0, es)); 109 1.1 mrg 110 1.1 mrg if (UNLIKELY (er == mer)) { 111 1.1 mrg ++es; 112 1.1 mrg if (UNLIKELY ((es & 0x7f) == 0)) 113 1.1 mrg SPINNER(2); 114 1.1 mrg mer +=2; /* mer = es * 2 */ 115 1.1 mrg if (UNLIKELY (mer == 0)) 116 1.1 mrg break; 117 1.1 mrg er = 0; 118 1.1 mrg } else 119 1.1 mrg ++er; 120 1.1 mrg q[1] += (++*q == 0); 121 1.1 mrg } while (1); 122 1.1 mrg SPINNER(2); 123 1.1 mrg printf ("\nValues with at most a limb for reminder, tested.\n"); 124 1.1 mrg printf ("Testing more values not supported, jet.\n"); 125 1.1 mrg return 0; 126 1.1 mrg } 127 1.1 mrg 128 1.1 mrg mp_limb_t 129 1.1 mrg upd (mp_limb_t *s, mp_limb_t k) 130 1.1 mrg { 131 1.1 mrg mp_limb_t _s = *s; 132 1.1 mrg 133 1.1 mrg while (k > _s * 2) 134 1.1 mrg { 135 1.1 mrg k -= _s * 2 + 1; 136 1.1 mrg ++_s; 137 1.1 mrg } 138 1.1 mrg *s = _s; 139 1.1 mrg return k; 140 1.1 mrg } 141 1.1 mrg 142 1.1 mrg mp_limb_t 143 1.1 mrg upd1 (mp_limb_t *s, mp_limb_t k) 144 1.1 mrg { 145 1.1 mrg mp_limb_t _s = *s; 146 1.1 mrg 147 1.1 mrg if (LIKELY (k < _s * 2)) return k + 1; 148 1.1 mrg *s = _s + 1; 149 1.1 mrg return k - _s * 2; 150 1.1 mrg } 151 1.1 mrg 152 1.1 mrg int 153 1.1 mrg check_some_values (int justone, int quick) 154 1.1 mrg { 155 1.1 mrg mp_limb_t es, her, er, k, s[1], r[2], q[2]; 156 1.1 mrg mp_size_t x; 157 1.1 mrg unsigned bits; 158 1.1 mrg 159 1.1 mrg es = 1 << 1; 160 1.1 mrg if (quick) { 161 1.1 mrg es <<= GMP_NUMB_BITS / 4 - 1; 162 1.1 mrg printf ("Quick, skipping some... (%u)\n", GMP_NUMB_BITS / 2); 163 1.1 mrg } 164 1.1 mrg er = 0; 165 1.1 mrg *q = es * es; 166 1.1 mrg printf ("High-half values tested, up to bits:\n"); 167 1.1 mrg do { 168 1.1 mrg k = *q - 1; 169 1.1 mrg do { 170 1.1 mrg x = mpn_sqrtrem (s, r, q, 1); 171 1.1 mrg if (UNLIKELY (x != (er != 0)) || UNLIKELY (*s != es) 172 1.1 mrg || UNLIKELY ((x == 1) && (er != *r))) 173 1.1 mrg STOP (something_wrong (er, 0, es)); 174 1.1 mrg 175 1.1 mrg if (UNLIKELY ((es & 0xffff) == 0)) 176 1.1 mrg SPINNER(1); 177 1.1 mrg if ((*q & k) == 0) { 178 1.1 mrg *q |= k; 179 1.1 mrg er = upd (&es, k + er); 180 1.1 mrg } else { 181 1.1 mrg ++*q; 182 1.1 mrg er = upd1 (&es, er); 183 1.1 mrg } 184 1.1 mrg } while (es & k); 185 1.1 mrg } while (*q != 0); 186 1.1 mrg q[1] = 1; 187 1.1 mrg SPINNER(2); 188 1.1 mrg printf ("\nValues of a single limb, tested.\n"); 189 1.1 mrg if (justone) return 0; 190 1.1 mrg if (quick) { 191 1.1 mrg es <<= GMP_NUMB_BITS / 2 - 1; 192 1.1 mrg q[1] <<= GMP_NUMB_BITS - 2; 193 1.1 mrg printf ("Quick, skipping some... (%u)\n", GMP_NUMB_BITS - 2); 194 1.1 mrg } 195 1.1 mrg printf ("High-half values tested, up to bits:\n"); 196 1.1 mrg do { 197 1.1 mrg x = mpn_sqrtrem (s, r, q, 2); 198 1.1 mrg if (UNLIKELY (x != (er != 0)) || UNLIKELY (*s != es) 199 1.1 mrg || UNLIKELY ((x == 1) && (er != *r))) 200 1.1 mrg STOP (something_wrong (er, 0, es)); 201 1.1 mrg 202 1.1 mrg if (*q == 0) { 203 1.1 mrg *q = GMP_NUMB_MAX; 204 1.1 mrg if (UNLIKELY ((es & 0xffff) == 0)) { 205 1.1 mrg if (UNLIKELY (es == GMP_NUMB_HIGHBIT)) 206 1.1 mrg break; 207 1.1 mrg SPINNER(2); 208 1.1 mrg } 209 1.1 mrg /* er = er + GMP_NUMB_MAX - 1 - es*2 // postponed */ 210 1.1 mrg ++es; 211 1.1 mrg /* er = er + GMP_NUMB_MAX - 1 - 2*(es-1) = 212 1.1 mrg = er +(GMP_NUMB_MAX + 1)- 2* es = er - 2*es */ 213 1.1 mrg er = upd (&es, er - 2 * es); 214 1.1 mrg } else { 215 1.1 mrg *q = 0; 216 1.1 mrg ++q[1]; 217 1.1 mrg er = upd1 (&es, er); 218 1.1 mrg } 219 1.1 mrg } while (1); 220 1.1 mrg SPINNER(2); 221 1.1 mrg printf ("\nValues with at most a limb for reminder, tested.\n"); 222 1.1 mrg er = GMP_NUMB_MAX; her = 0; 223 1.1 mrg 224 1.1 mrg printf ("High-half values tested, up to bits:\n"); 225 1.1 mrg do { 226 1.1 mrg x = mpn_sqrtrem (s, r, q, 2); 227 1.1 mrg if (UNLIKELY (x != (her?2:(er != 0))) || UNLIKELY (*s != es) 228 1.1 mrg || UNLIKELY ((x != 0) && ((er != *r) || ((x == 2) && (r[1] != 1))))) 229 1.1 mrg STOP (something_wrong (er, her, es)); 230 1.1 mrg 231 1.1 mrg if (*q == 0) { 232 1.1 mrg *q = GMP_NUMB_MAX; 233 1.1 mrg if (UNLIKELY ((es & 0xffff) == 0)) { 234 1.1 mrg SPINNER(2); 235 1.1 mrg } 236 1.1 mrg if (her) { 237 1.1 mrg ++es; 238 1.1 mrg her = 0; 239 1.1 mrg er = er - 2 * es; 240 1.1 mrg } else { 241 1.1 mrg her = --er != GMP_NUMB_MAX; 242 1.1 mrg if (her & (er > es * 2)) { 243 1.1 mrg er -= es * 2 + 1; 244 1.1 mrg her = 0; 245 1.1 mrg ++es; 246 1.1 mrg } 247 1.1 mrg } 248 1.1 mrg } else { 249 1.1 mrg *q = 0; 250 1.1 mrg if (++q[1] == 0) break; 251 1.1 mrg if ((her == 0) | (er < es * 2)) { 252 1.1 mrg her += ++er == 0; 253 1.1 mrg } else { 254 1.1 mrg er -= es * 2; 255 1.1 mrg her = 0; 256 1.1 mrg ++es; 257 1.1 mrg } 258 1.1 mrg } 259 1.1 mrg } while (1); 260 1.1 mrg printf ("| %u\nValues of at most two limbs, tested.\n", GMP_NUMB_BITS*2); 261 1.1 mrg return 0; 262 1.1 mrg } 263 1.1 mrg 264 1.1 mrg int 265 1.1 mrg check_corner_cases (int justone, int quick) 266 1.1 mrg { 267 1.1 mrg mp_limb_t es, er, s[1], r[2], q[2]; 268 1.1 mrg mp_size_t x; 269 1.1 mrg unsigned bits; 270 1.1 mrg 271 1.1 mrg es = 1; 272 1.1 mrg if (quick) { 273 1.1 mrg es <<= GMP_NUMB_BITS / 2 - 1; 274 1.1 mrg printf ("Quick, skipping some... (%u)\n", GMP_NUMB_BITS - 2); 275 1.1 mrg } 276 1.1 mrg er = 0; 277 1.1 mrg *q = es*es; 278 1.1 mrg printf ("Corner cases tested, up to bits:\n"); 279 1.1 mrg do { 280 1.1 mrg x = mpn_sqrtrem (s, r, q, 1); 281 1.1 mrg if (UNLIKELY (x != (er != 0)) || UNLIKELY (*s != es) 282 1.1 mrg || UNLIKELY ((x == 1) && (er != *r))) 283 1.1 mrg STOP (something_wrong (er, 0, es)); 284 1.1 mrg 285 1.1 mrg if (er != 0) { 286 1.1 mrg ++es; 287 1.1 mrg if (UNLIKELY ((es & 0xffff) == 0)) 288 1.1 mrg SPINNER(1); 289 1.1 mrg er = 0; 290 1.1 mrg ++*q; 291 1.1 mrg } else { 292 1.1 mrg er = es * 2; 293 1.1 mrg *q += er; 294 1.1 mrg } 295 1.1 mrg } while (*q != 0); 296 1.1 mrg q[1] = 1; 297 1.1 mrg SPINNER(2); 298 1.1 mrg printf ("\nValues of a single limb, tested.\n"); 299 1.1 mrg if (justone) return 0; 300 1.1 mrg if (quick) { 301 1.1 mrg es <<= GMP_NUMB_BITS / 2 - 1; 302 1.1 mrg q[1] <<= GMP_NUMB_BITS - 2; 303 1.1 mrg printf ("Quick, skipping some... (%u)\n", GMP_NUMB_BITS - 2); 304 1.1 mrg --es; 305 1.1 mrg --q[1]; 306 1.1 mrg q[0] -= es*2+1; 307 1.1 mrg } 308 1.1 mrg printf ("Corner cases tested, up to bits:\n"); 309 1.1 mrg do { 310 1.1 mrg x = mpn_sqrtrem (s, r, q, 2); 311 1.1 mrg if (UNLIKELY (x != (er != 0)) || UNLIKELY (*s != es) 312 1.1 mrg || UNLIKELY ((x == 1) && (er != *r))) 313 1.1 mrg STOP (something_wrong (er, 0, es)); 314 1.1 mrg 315 1.1 mrg if (er != 0) { 316 1.1 mrg ++es; 317 1.1 mrg if (UNLIKELY ((es & 0xff) == 0)) 318 1.1 mrg SPINNER(2); 319 1.1 mrg er = 0; 320 1.1 mrg q[1] += (++*q == 0); 321 1.1 mrg if (UNLIKELY (es == GMP_NUMB_HIGHBIT)) 322 1.1 mrg break; 323 1.1 mrg } else { 324 1.1 mrg er = es * 2; 325 1.1 mrg add_ssaaaa (q[1], *q, q[1], *q, 0, er); 326 1.1 mrg } 327 1.1 mrg } while (1); 328 1.1 mrg SPINNER(2); 329 1.1 mrg printf ("\nValues with at most a limb for reminder, tested.\nCorner cases tested, up to bits:\n"); 330 1.1 mrg x = mpn_sqrtrem (s, r, q, 2); 331 1.1 mrg if ((*s != es) || (x != 0)) 332 1.1 mrg STOP (something_wrong (0, 0, es)); 333 1.1 mrg q[1] += 1; 334 1.1 mrg x = mpn_sqrtrem (s, r, q, 2); 335 1.1 mrg if ((*s != es) || (x != 2) || (*r != 0) || (r[1] != 1)) 336 1.1 mrg STOP (something_wrong (0, 1, es)); 337 1.1 mrg ++es; 338 1.1 mrg q[1] += (++*q == 0); 339 1.1 mrg do { 340 1.1 mrg x = mpn_sqrtrem (s, r, q, 2); 341 1.1 mrg if (UNLIKELY (x != (er != 0) * 2) || UNLIKELY (*s != es) 342 1.1 mrg || UNLIKELY ((x == 2) && ((er != *r) || (r[1] != 1)))) 343 1.1 mrg STOP (something_wrong (er, er != 0, es)); 344 1.1 mrg 345 1.1 mrg if (er != 0) { 346 1.1 mrg ++es; 347 1.1 mrg if (UNLIKELY (es == 0)) 348 1.1 mrg break; 349 1.1 mrg if (UNLIKELY ((es & 0xff) == 0)) 350 1.1 mrg SPINNER(2); 351 1.1 mrg er = 0; 352 1.1 mrg q[1] += (++*q == 0); 353 1.1 mrg } else { 354 1.1 mrg er = es * 2; 355 1.1 mrg add_ssaaaa (q[1], *q, q[1], *q, 1, er); 356 1.1 mrg } 357 1.1 mrg } while (1); 358 1.1 mrg printf ("| %u\nValues of at most two limbs, tested.\n", GMP_NUMB_BITS*2); 359 1.1 mrg return 0; 360 1.1 mrg } 361 1.1 mrg 362 1.1 mrg int 363 1.1 mrg main (int argc, char **argv) 364 1.1 mrg { 365 1.1 mrg int mode = 0; 366 1.1 mrg int justone = 0; 367 1.1 mrg int quick = 0; 368 1.1 mrg 369 1.1 mrg for (;argc > 1;--argc,++argv) 370 1.1 mrg switch (*argv[1]) { 371 1.1 mrg default: 372 1.1 mrg fprintf (stderr, "usage: sqrtrem_1_2 [x|c|s] [1|2] [q]\n"); 373 1.1 mrg exit (1); 374 1.1 mrg case 'x': 375 1.1 mrg mode = 0; 376 1.1 mrg break; 377 1.1 mrg case 'c': 378 1.1 mrg mode = 1; 379 1.1 mrg break; 380 1.1 mrg case 's': 381 1.1 mrg mode = 2; 382 1.1 mrg break; 383 1.1 mrg case 'q': 384 1.1 mrg quick = 1; 385 1.1 mrg break; 386 1.1 mrg case '1': 387 1.1 mrg justone = 1; 388 1.1 mrg break; 389 1.1 mrg case '2': 390 1.1 mrg justone = 0; 391 1.1 mrg } 392 1.1 mrg 393 1.1 mrg switch (mode) { 394 1.1 mrg default: 395 1.1 mrg return check_all_values (justone, quick); 396 1.1 mrg case 1: 397 1.1 mrg return check_corner_cases (justone, quick); 398 1.1 mrg case 2: 399 1.1 mrg return check_some_values (justone, quick); 400 1.1 mrg } 401 1.1 mrg } 402