t-divrem_1.c revision 1.1.1.4 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