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