t-divrem_1.c revision 1.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 mrg This file is part of the GNU MP Library.
6 1.1 mrg
7 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify
8 1.1 mrg it under the terms of the GNU Lesser General Public License as published by
9 1.1 mrg the Free Software Foundation; either version 3 of the License, or (at your
10 1.1 mrg option) any later version.
11 1.1 mrg
12 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but
13 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 1.1 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 1.1 mrg License for more details.
16 1.1 mrg
17 1.1 mrg You should have received a copy of the GNU Lesser General Public License
18 1.1 mrg along with the GNU MP Library. 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 mrg #if GMP_NUMB_BITS == 32
46 1.1 mrg { { 0x3C }, 1, 0xF2, 1,
47 1.1 mrg { 0x3F789854, 0 }, 0x98 },
48 1.1 mrg #endif
49 1.1 mrg
50 1.1 mrg #if GMP_NUMB_BITS == 64
51 1.1 mrg { { 0x3C }, 1, 0xF2, 1,
52 1.1 mrg { CNST_LIMB(0x3F789854A0CB1B81), 0 }, 0x0E },
53 1.1 mrg
54 1.1 mrg /* This case exposed some wrong code generated by SGI cc on mips64 irix
55 1.1 mrg 6.5 with -n32 -O2, in the fractional loop for normalized divisor
56 1.1 mrg using udiv_qrnnd_preinv. A test "x>al" in one of the sub_ddmmss
57 1.1 mrg expansions came out wrong, leading to an incorrect quotient. */
58 1.1 mrg { { CNST_LIMB(0x3C00000000000000) }, 1, CNST_LIMB(0xF200000000000000), 1,
59 1.1 mrg { CNST_LIMB(0x3F789854A0CB1B81), 0 }, CNST_LIMB(0x0E00000000000000) },
60 1.1 mrg #endif
61 1.1 mrg };
62 1.1 mrg
63 1.1 mrg mp_limb_t dinv, got_r, got_q[numberof(data[0].want_q)];
64 1.1 mrg mp_size_t qsize;
65 1.1 mrg int i, shift;
66 1.1 mrg
67 1.1 mrg for (i = 0; i < numberof (data); i++)
68 1.1 mrg {
69 1.1 mrg qsize = data[i].nsize + data[i].qxn;
70 1.1 mrg ASSERT_ALWAYS (qsize <= numberof (got_q));
71 1.1 mrg
72 1.1 mrg got_r = mpn_divrem_1 (got_q, data[i].qxn, data[i].n, data[i].nsize,
73 1.1 mrg data[i].d);
74 1.1 mrg if (got_r != data[i].want_r
75 1.1 mrg || refmpn_cmp (got_q, data[i].want_q, qsize) != 0)
76 1.1 mrg {
77 1.1 mrg printf ("mpn_divrem_1 wrong at data[%d]\n", i);
78 1.1 mrg bad:
79 1.1 mrg mpn_trace (" n", data[i].n, data[i].nsize);
80 1.1 mrg printf (" nsize=%ld\n", (long) data[i].nsize);
81 1.1 mrg mp_limb_trace (" d", data[i].d);
82 1.1 mrg printf (" qxn=%ld\n", (long) data[i].qxn);
83 1.1 mrg mpn_trace (" want q", data[i].want_q, qsize);
84 1.1 mrg mpn_trace (" got q", got_q, qsize);
85 1.1 mrg mp_limb_trace (" want r", data[i].want_r);
86 1.1 mrg mp_limb_trace (" got r", got_r);
87 1.1 mrg abort ();
88 1.1 mrg }
89 1.1 mrg
90 1.1 mrg /* test if available */
91 1.1 mrg #if USE_PREINV_DIVREM_1 || HAVE_NATIVE_mpn_preinv_divrem_1
92 1.1 mrg shift = refmpn_count_leading_zeros (data[i].d);
93 1.1 mrg dinv = refmpn_invert_limb (data[i].d << shift);
94 1.1 mrg got_r = mpn_preinv_divrem_1 (got_q, data[i].qxn,
95 1.1 mrg data[i].n, data[i].nsize,
96 1.1 mrg data[i].d, dinv, shift);
97 1.1 mrg if (got_r != data[i].want_r
98 1.1 mrg || refmpn_cmp (got_q, data[i].want_q, qsize) != 0)
99 1.1 mrg {
100 1.1 mrg printf ("mpn_preinv divrem_1 wrong at data[%d]\n", i);
101 1.1 mrg printf (" shift=%d\n", shift);
102 1.1 mrg mp_limb_trace (" dinv", dinv);
103 1.1 mrg goto bad;
104 1.1 mrg }
105 1.1 mrg #endif
106 1.1 mrg }
107 1.1 mrg }
108 1.1 mrg
109 1.1 mrg int
110 1.1 mrg main (void)
111 1.1 mrg {
112 1.1 mrg tests_start ();
113 1.1 mrg mp_trace_base = -16;
114 1.1 mrg
115 1.1 mrg check_data ();
116 1.1 mrg
117 1.1 mrg tests_end ();
118 1.1 mrg exit (0);
119 1.1 mrg }
120