Home | History | Annotate | Line # | Download | only in mpn
t-divrem_1.c revision 1.1.1.4
      1      1.1  mrg /* Test mpn_divrem_1 and mpn_preinv_divrem_1.
      2      1.1  mrg 
      3      1.1  mrg Copyright 2003 Free Software Foundation, Inc.
      4      1.1  mrg 
      5  1.1.1.2  mrg This file is part of the GNU MP Library test suite.
      6      1.1  mrg 
      7  1.1.1.2  mrg The GNU MP Library test suite is free software; you can redistribute it
      8  1.1.1.2  mrg and/or modify it under the terms of the GNU General Public License as
      9  1.1.1.2  mrg published by the Free Software Foundation; either version 3 of the License,
     10  1.1.1.2  mrg or (at your option) any later version.
     11  1.1.1.2  mrg 
     12  1.1.1.2  mrg The GNU MP Library test suite is distributed in the hope that it will be
     13  1.1.1.2  mrg useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
     14  1.1.1.2  mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
     15  1.1.1.2  mrg Public License for more details.
     16      1.1  mrg 
     17  1.1.1.2  mrg You should have received a copy of the GNU General Public License along with
     18  1.1.1.3  mrg the GNU MP Library test suite.  If not, see https://www.gnu.org/licenses/.  */
     19      1.1  mrg 
     20      1.1  mrg #include <stdio.h>
     21      1.1  mrg #include <stdlib.h>
     22      1.1  mrg 
     23      1.1  mrg #include "gmp-impl.h"
     24      1.1  mrg #include "tests.h"
     25      1.1  mrg 
     26      1.1  mrg 
     27      1.1  mrg void
     28      1.1  mrg check_data (void)
     29      1.1  mrg {
     30      1.1  mrg   static const struct {
     31      1.1  mrg     mp_limb_t  n[1];
     32      1.1  mrg     mp_size_t  nsize;
     33      1.1  mrg     mp_limb_t  d;
     34      1.1  mrg     mp_size_t  qxn;
     35      1.1  mrg     mp_limb_t  want_q[5];
     36      1.1  mrg     mp_limb_t  want_r;
     37      1.1  mrg   } data[] = {
     38      1.1  mrg     { { 0 }, 1, 1, 0,
     39      1.1  mrg       { 0 }, 0},
     40      1.1  mrg 
     41      1.1  mrg     { { 5 }, 1, 2, 0,
     42      1.1  mrg       { 2 }, 1},
     43      1.1  mrg 
     44  1.1.1.2  mrg     /* Exercises the q update in the nl == constant 0 case of
     45  1.1.1.2  mrg        udiv_qrnnd_preinv3. Test case copied from t-fat.c. */
     46  1.1.1.2  mrg     { { 287 }, 1, 7, 1,
     47  1.1.1.2  mrg       { 0, 41 }, 0 },
     48  1.1.1.2  mrg 
     49      1.1  mrg #if GMP_NUMB_BITS == 32
     50      1.1  mrg     { { 0x3C }, 1, 0xF2, 1,
     51      1.1  mrg       { 0x3F789854, 0 }, 0x98 },
     52      1.1  mrg #endif
     53      1.1  mrg 
     54      1.1  mrg #if GMP_NUMB_BITS == 64
     55      1.1  mrg     { { 0x3C }, 1, 0xF2, 1,
     56      1.1  mrg       { CNST_LIMB(0x3F789854A0CB1B81), 0 }, 0x0E },
     57      1.1  mrg 
     58      1.1  mrg     /* This case exposed some wrong code generated by SGI cc on mips64 irix
     59      1.1  mrg        6.5 with -n32 -O2, in the fractional loop for normalized divisor
     60      1.1  mrg        using udiv_qrnnd_preinv.  A test "x>al" in one of the sub_ddmmss
     61      1.1  mrg        expansions came out wrong, leading to an incorrect quotient.  */
     62      1.1  mrg     { { CNST_LIMB(0x3C00000000000000) }, 1, CNST_LIMB(0xF200000000000000), 1,
     63      1.1  mrg       { CNST_LIMB(0x3F789854A0CB1B81), 0 }, CNST_LIMB(0x0E00000000000000) },
     64      1.1  mrg #endif
     65      1.1  mrg   };
     66      1.1  mrg 
     67      1.1  mrg   mp_limb_t  dinv, got_r, got_q[numberof(data[0].want_q)];
     68      1.1  mrg   mp_size_t  qsize;
     69      1.1  mrg   int        i, shift;
     70      1.1  mrg 
     71      1.1  mrg   for (i = 0; i < numberof (data); i++)
     72      1.1  mrg     {
     73      1.1  mrg       qsize = data[i].nsize + data[i].qxn;
     74      1.1  mrg       ASSERT_ALWAYS (qsize <= numberof (got_q));
     75      1.1  mrg 
     76      1.1  mrg       got_r = mpn_divrem_1 (got_q, data[i].qxn, data[i].n, data[i].nsize,
     77      1.1  mrg                             data[i].d);
     78      1.1  mrg       if (got_r != data[i].want_r
     79      1.1  mrg           || refmpn_cmp (got_q, data[i].want_q, qsize) != 0)
     80      1.1  mrg         {
     81      1.1  mrg           printf        ("mpn_divrem_1 wrong at data[%d]\n", i);
     82      1.1  mrg         bad:
     83      1.1  mrg           mpn_trace     ("  n", data[i].n, data[i].nsize);
     84      1.1  mrg           printf        ("  nsize=%ld\n", (long) data[i].nsize);
     85      1.1  mrg           mp_limb_trace ("  d", data[i].d);
     86      1.1  mrg           printf        ("  qxn=%ld\n", (long) data[i].qxn);
     87      1.1  mrg           mpn_trace     ("  want q", data[i].want_q, qsize);
     88      1.1  mrg           mpn_trace     ("  got  q", got_q, qsize);
     89      1.1  mrg           mp_limb_trace ("  want r", data[i].want_r);
     90      1.1  mrg           mp_limb_trace ("  got  r", got_r);
     91      1.1  mrg           abort ();
     92      1.1  mrg         }
     93      1.1  mrg 
     94      1.1  mrg       /* test if available */
     95      1.1  mrg #if USE_PREINV_DIVREM_1 || HAVE_NATIVE_mpn_preinv_divrem_1
     96      1.1  mrg       shift = refmpn_count_leading_zeros (data[i].d);
     97      1.1  mrg       dinv = refmpn_invert_limb (data[i].d << shift);
     98      1.1  mrg       got_r = mpn_preinv_divrem_1 (got_q, data[i].qxn,
     99      1.1  mrg                                    data[i].n, data[i].nsize,
    100      1.1  mrg                                    data[i].d, dinv, shift);
    101      1.1  mrg       if (got_r != data[i].want_r
    102      1.1  mrg           || refmpn_cmp (got_q, data[i].want_q, qsize) != 0)
    103      1.1  mrg         {
    104      1.1  mrg           printf        ("mpn_preinv divrem_1 wrong at data[%d]\n", i);
    105      1.1  mrg           printf        ("  shift=%d\n", shift);
    106      1.1  mrg           mp_limb_trace ("  dinv", dinv);
    107      1.1  mrg           goto bad;
    108      1.1  mrg         }
    109      1.1  mrg #endif
    110      1.1  mrg     }
    111      1.1  mrg }
    112      1.1  mrg 
    113      1.1  mrg int
    114      1.1  mrg main (void)
    115      1.1  mrg {
    116      1.1  mrg   tests_start ();
    117      1.1  mrg   mp_trace_base = -16;
    118      1.1  mrg 
    119      1.1  mrg   check_data ();
    120      1.1  mrg 
    121      1.1  mrg   tests_end ();
    122      1.1  mrg   exit (0);
    123      1.1  mrg }
    124