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