Home | History | Annotate | Line # | Download | only in devel
      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