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