1 /* Test mpf_div.
2
3 Copyright 2004 Free Software Foundation, Inc.
4
5 This file is part of the GNU MP Library test suite.
6
7 The GNU MP Library test suite is free software; you can redistribute it
8 and/or modify it under the terms of the GNU General Public License as
9 published by the Free Software Foundation; either version 3 of the License,
10 or (at your option) any later version.
11
12 The GNU MP Library test suite is distributed in the hope that it will be
13 useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
15 Public License for more details.
16
17 You should have received a copy of the GNU General Public License along with
18 the GNU MP Library test suite. If not, see https://www.gnu.org/licenses/. */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include "gmp.h"
23 #include "gmp-impl.h"
24 #include "tests.h"
25
26
27 void
check_one(const char * desc,mpf_ptr got,mpf_srcptr u,mpf_srcptr v)28 check_one (const char *desc, mpf_ptr got, mpf_srcptr u, mpf_srcptr v)
29 {
30 if (! refmpf_validate_division ("mpf_div", got, u, v))
31 {
32 mp_trace_base = -16;
33 mpf_trace (" u", u);
34 mpf_trace (" v", v);
35 printf (" %s\n", desc);
36 abort ();
37 }
38 }
39
40 void
check_rand(void)41 check_rand (void)
42 {
43 unsigned long min_prec = __GMPF_BITS_TO_PREC (1);
44 gmp_randstate_ptr rands = RANDS;
45 unsigned long prec;
46 mpf_t got, u, v;
47 int i;
48
49 mpf_init (got);
50 mpf_init (u);
51 mpf_init (v);
52
53 /* separate */
54 for (i = 0; i < 100; i++)
55 {
56 /* got precision */
57 prec = min_prec + gmp_urandomm_ui (rands, 15L);
58 refmpf_set_prec_limbs (got, prec);
59
60 /* u */
61 prec = min_prec + gmp_urandomm_ui (rands, 15L);
62 refmpf_set_prec_limbs (u, prec);
63 do {
64 mpf_random2 (u, PREC(u), (mp_exp_t) 20);
65 } while (SIZ(u) == 0);
66 if (gmp_urandomb_ui (rands, 1L))
67 mpf_neg (u, u);
68
69 /* v */
70 prec = min_prec + gmp_urandomm_ui (rands, 15L);
71 refmpf_set_prec_limbs (v, prec);
72 do {
73 mpf_random2 (v, PREC(v), (mp_exp_t) 20);
74 } while (SIZ(v) == 0);
75 if (gmp_urandomb_ui (rands, 1L))
76 mpf_neg (v, v);
77
78 switch (i % 3) {
79 case 0:
80 mpf_div (got, u, v);
81 check_one ("separate", got, u, v);
82 break;
83 case 1:
84 prec = refmpf_set_overlap (got, u);
85 mpf_div (got, got, v);
86 check_one ("dst == u", got, u, v);
87 mpf_set_prec_raw (got, prec);
88 break;
89 case 2:
90 prec = refmpf_set_overlap (got, v);
91 mpf_div (got, u, got);
92 check_one ("dst == v", got, u, v);
93 mpf_set_prec_raw (got, prec);
94 break;
95 }
96 }
97
98 mpf_clear (got);
99 mpf_clear (u);
100 mpf_clear (v);
101 }
102
103 /* Exercise calls mpf(x,x,x) */
104 void
check_reuse_three(void)105 check_reuse_three (void)
106 {
107 unsigned long min_prec = __GMPF_BITS_TO_PREC (1);
108 gmp_randstate_ptr rands = RANDS;
109 unsigned long result_prec, input_prec, set_prec;
110 mpf_t got;
111 int i;
112
113 mpf_init (got);
114
115 for (i = 0; i < 8; i++)
116 {
117 result_prec = min_prec + gmp_urandomm_ui (rands, 15L);
118 input_prec = min_prec + gmp_urandomm_ui (rands, 15L);
119
120 set_prec = MAX (result_prec, input_prec);
121 refmpf_set_prec_limbs (got, set_prec);
122
123 /* input, non-zero, possibly negative */
124 PREC(got) = input_prec;
125 do {
126 mpf_random2 (got, input_prec, (mp_exp_t) 20);
127 } while (SIZ(got) == 0);
128 if (gmp_urandomb_ui (rands, 1L))
129 mpf_neg (got, got);
130
131 PREC(got) = result_prec;
132
133 mpf_div (got, got, got);
134
135 /* expect exactly 1.0 always */
136 ASSERT_ALWAYS (mpf_cmp_ui (got, 1L) == 0);
137
138 PREC(got) = set_prec;
139 }
140
141 mpf_clear (got);
142 }
143
144 void
check_various(void)145 check_various (void)
146 {
147 mpf_t got, u, v;
148
149 mpf_init (got);
150 mpf_init (u);
151 mpf_init (v);
152
153 /* 100/4 == 25 */
154 mpf_set_prec (got, 20L);
155 mpf_set_ui (u, 100L);
156 mpf_set_ui (v, 4L);
157 mpf_div (got, u, v);
158 MPF_CHECK_FORMAT (got);
159 ASSERT_ALWAYS (mpf_cmp_ui (got, 25L) == 0);
160
161 /* 1/(2^n+1), a case where truncating the divisor would be wrong */
162 mpf_set_prec (got, 500L);
163 mpf_set_prec (v, 900L);
164 mpf_set_ui (v, 1L);
165 mpf_mul_2exp (v, v, 800L);
166 mpf_add_ui (v, v, 1L);
167 mpf_div (got, u, v);
168 check_one ("1/2^n+1, separate", got, u, v);
169
170 mpf_clear (got);
171 mpf_clear (u);
172 mpf_clear (v);
173 }
174
175 int
main(void)176 main (void)
177 {
178 tests_start ();
179
180 check_various ();
181 check_rand ();
182 check_reuse_three ();
183
184 tests_end ();
185 exit (0);
186 }
187