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