t-divrem_1.c revision 1.1.1.1.2.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.2.1 yamt This file is part of the GNU MP Library test suite.
6 1.1 mrg
7 1.1.1.1.2.1 yamt The GNU MP Library test suite is free software; you can redistribute it
8 1.1.1.1.2.1 yamt and/or modify it under the terms of the GNU General Public License as
9 1.1.1.1.2.1 yamt published by the Free Software Foundation; either version 3 of the License,
10 1.1.1.1.2.1 yamt or (at your option) any later version.
11 1.1.1.1.2.1 yamt
12 1.1.1.1.2.1 yamt The GNU MP Library test suite is distributed in the hope that it will be
13 1.1.1.1.2.1 yamt useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 1.1.1.1.2.1 yamt MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15 1.1.1.1.2.1 yamt Public License for more details.
16 1.1 mrg
17 1.1.1.1.2.1 yamt You should have received a copy of the GNU General Public License along with
18 1.1.1.1.2.1 yamt 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.2.1 yamt /* Exercises the q update in the nl == constant 0 case of
46 1.1.1.1.2.1 yamt udiv_qrnnd_preinv3. Test case copied from t-fat.c. */
47 1.1.1.1.2.1 yamt { { 287 }, 1, 7, 1,
48 1.1.1.1.2.1 yamt { 0, 41 }, 0 },
49 1.1.1.1.2.1 yamt
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