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