Home | History | Annotate | Line # | Download | only in mpn
t-divrem_1.c revision 1.1.1.1.2.1
      1 /* Test mpn_divrem_1 and mpn_preinv_divrem_1.
      2 
      3 Copyright 2003 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 http://www.gnu.org/licenses/.  */
     19 
     20 #include <stdio.h>
     21 #include <stdlib.h>
     22 
     23 #include "gmp.h"
     24 #include "gmp-impl.h"
     25 #include "tests.h"
     26 
     27 
     28 void
     29 check_data (void)
     30 {
     31   static const struct {
     32     mp_limb_t  n[1];
     33     mp_size_t  nsize;
     34     mp_limb_t  d;
     35     mp_size_t  qxn;
     36     mp_limb_t  want_q[5];
     37     mp_limb_t  want_r;
     38   } data[] = {
     39     { { 0 }, 1, 1, 0,
     40       { 0 }, 0},
     41 
     42     { { 5 }, 1, 2, 0,
     43       { 2 }, 1},
     44 
     45     /* Exercises the q update in the nl == constant 0 case of
     46        udiv_qrnnd_preinv3. Test case copied from t-fat.c. */
     47     { { 287 }, 1, 7, 1,
     48       { 0, 41 }, 0 },
     49 
     50 #if GMP_NUMB_BITS == 32
     51     { { 0x3C }, 1, 0xF2, 1,
     52       { 0x3F789854, 0 }, 0x98 },
     53 #endif
     54 
     55 #if GMP_NUMB_BITS == 64
     56     { { 0x3C }, 1, 0xF2, 1,
     57       { CNST_LIMB(0x3F789854A0CB1B81), 0 }, 0x0E },
     58 
     59     /* This case exposed some wrong code generated by SGI cc on mips64 irix
     60        6.5 with -n32 -O2, in the fractional loop for normalized divisor
     61        using udiv_qrnnd_preinv.  A test "x>al" in one of the sub_ddmmss
     62        expansions came out wrong, leading to an incorrect quotient.  */
     63     { { CNST_LIMB(0x3C00000000000000) }, 1, CNST_LIMB(0xF200000000000000), 1,
     64       { CNST_LIMB(0x3F789854A0CB1B81), 0 }, CNST_LIMB(0x0E00000000000000) },
     65 #endif
     66   };
     67 
     68   mp_limb_t  dinv, got_r, got_q[numberof(data[0].want_q)];
     69   mp_size_t  qsize;
     70   int        i, shift;
     71 
     72   for (i = 0; i < numberof (data); i++)
     73     {
     74       qsize = data[i].nsize + data[i].qxn;
     75       ASSERT_ALWAYS (qsize <= numberof (got_q));
     76 
     77       got_r = mpn_divrem_1 (got_q, data[i].qxn, data[i].n, data[i].nsize,
     78                             data[i].d);
     79       if (got_r != data[i].want_r
     80           || refmpn_cmp (got_q, data[i].want_q, qsize) != 0)
     81         {
     82           printf        ("mpn_divrem_1 wrong at data[%d]\n", i);
     83         bad:
     84           mpn_trace     ("  n", data[i].n, data[i].nsize);
     85           printf        ("  nsize=%ld\n", (long) data[i].nsize);
     86           mp_limb_trace ("  d", data[i].d);
     87           printf        ("  qxn=%ld\n", (long) data[i].qxn);
     88           mpn_trace     ("  want q", data[i].want_q, qsize);
     89           mpn_trace     ("  got  q", got_q, qsize);
     90           mp_limb_trace ("  want r", data[i].want_r);
     91           mp_limb_trace ("  got  r", got_r);
     92           abort ();
     93         }
     94 
     95       /* test if available */
     96 #if USE_PREINV_DIVREM_1 || HAVE_NATIVE_mpn_preinv_divrem_1
     97       shift = refmpn_count_leading_zeros (data[i].d);
     98       dinv = refmpn_invert_limb (data[i].d << shift);
     99       got_r = mpn_preinv_divrem_1 (got_q, data[i].qxn,
    100                                    data[i].n, data[i].nsize,
    101                                    data[i].d, dinv, shift);
    102       if (got_r != data[i].want_r
    103           || refmpn_cmp (got_q, data[i].want_q, qsize) != 0)
    104         {
    105           printf        ("mpn_preinv divrem_1 wrong at data[%d]\n", i);
    106           printf        ("  shift=%d\n", shift);
    107           mp_limb_trace ("  dinv", dinv);
    108           goto bad;
    109         }
    110 #endif
    111     }
    112 }
    113 
    114 int
    115 main (void)
    116 {
    117   tests_start ();
    118   mp_trace_base = -16;
    119 
    120   check_data ();
    121 
    122   tests_end ();
    123   exit (0);
    124 }
    125