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-impl.h"
23 #include "tests.h"
24
25
26 void
check_one(const char * desc,mpf_ptr got,mpf_srcptr u,mpf_srcptr v)27 check_one (const char *desc, mpf_ptr got, mpf_srcptr u, mpf_srcptr v)
28 {
29 if (! refmpf_validate_division ("mpf_div", got, u, v))
30 {
31 mp_trace_base = -16;
32 mpf_trace (" u", u);
33 mpf_trace (" v", v);
34 printf (" %s\n", desc);
35 abort ();
36 }
37 }
38
39 void
check_rand(void)40 check_rand (void)
41 {
42 unsigned long min_prec = __GMPF_BITS_TO_PREC (1);
43 gmp_randstate_ptr rands = RANDS;
44 unsigned long prec;
45 mpf_t got, u, v;
46 int i;
47
48 mpf_init (got);
49 mpf_init (u);
50 mpf_init (v);
51
52 /* separate */
53 for (i = 0; i < 100; i++)
54 {
55 /* got precision */
56 prec = min_prec + gmp_urandomm_ui (rands, 15L);
57 refmpf_set_prec_limbs (got, prec);
58
59 /* u */
60 prec = min_prec + gmp_urandomm_ui (rands, 15L);
61 refmpf_set_prec_limbs (u, prec);
62 do {
63 mpf_random2 (u, PREC(u), (mp_exp_t) 20);
64 } while (SIZ(u) == 0);
65 if (gmp_urandomb_ui (rands, 1L))
66 mpf_neg (u, u);
67
68 /* v */
69 prec = min_prec + gmp_urandomm_ui (rands, 15L);
70 refmpf_set_prec_limbs (v, prec);
71 do {
72 mpf_random2 (v, PREC(v), (mp_exp_t) 20);
73 } while (SIZ(v) == 0);
74 if (gmp_urandomb_ui (rands, 1L))
75 mpf_neg (v, v);
76
77 switch (i % 3) {
78 case 0:
79 mpf_div (got, u, v);
80 check_one ("separate", got, u, v);
81 break;
82 case 1:
83 prec = refmpf_set_overlap (got, u);
84 mpf_div (got, got, v);
85 check_one ("dst == u", got, u, v);
86 mpf_set_prec_raw (got, prec);
87 break;
88 case 2:
89 prec = refmpf_set_overlap (got, v);
90 mpf_div (got, u, got);
91 check_one ("dst == v", got, u, v);
92 mpf_set_prec_raw (got, prec);
93 break;
94 }
95 }
96
97 mpf_clear (got);
98 mpf_clear (u);
99 mpf_clear (v);
100 }
101
102 /* Exercise calls mpf(x,x,x) */
103 void
check_reuse_three(void)104 check_reuse_three (void)
105 {
106 unsigned long min_prec = __GMPF_BITS_TO_PREC (1);
107 gmp_randstate_ptr rands = RANDS;
108 unsigned long result_prec, input_prec, set_prec;
109 mpf_t got;
110 int i;
111
112 mpf_init (got);
113
114 for (i = 0; i < 8; i++)
115 {
116 result_prec = min_prec + gmp_urandomm_ui (rands, 15L);
117 input_prec = min_prec + gmp_urandomm_ui (rands, 15L);
118
119 set_prec = MAX (result_prec, input_prec);
120 refmpf_set_prec_limbs (got, set_prec);
121
122 /* input, non-zero, possibly negative */
123 PREC(got) = input_prec;
124 do {
125 mpf_random2 (got, input_prec, (mp_exp_t) 20);
126 } while (SIZ(got) == 0);
127 if (gmp_urandomb_ui (rands, 1L))
128 mpf_neg (got, got);
129
130 PREC(got) = result_prec;
131
132 mpf_div (got, got, got);
133
134 /* expect exactly 1.0 always */
135 ASSERT_ALWAYS (mpf_cmp_ui (got, 1L) == 0);
136
137 PREC(got) = set_prec;
138 }
139
140 mpf_clear (got);
141 }
142
143 void
check_various(void)144 check_various (void)
145 {
146 mpf_t got, u, v;
147
148 mpf_init (got);
149 mpf_init (u);
150 mpf_init (v);
151
152 /* 100/4 == 25 */
153 mpf_set_prec (got, 20L);
154 mpf_set_ui (u, 100L);
155 mpf_set_ui (v, 4L);
156 mpf_div (got, u, v);
157 MPF_CHECK_FORMAT (got);
158 ASSERT_ALWAYS (mpf_cmp_ui (got, 25L) == 0);
159
160 /* 1/(2^n+1), a case where truncating the divisor would be wrong */
161 mpf_set_prec (got, 500L);
162 mpf_set_prec (v, 900L);
163 mpf_set_ui (v, 1L);
164 mpf_mul_2exp (v, v, 800L);
165 mpf_add_ui (v, v, 1L);
166 mpf_div (got, u, v);
167 check_one ("1/2^n+1, separate", got, u, v);
168
169 mpf_clear (got);
170 mpf_clear (u);
171 mpf_clear (v);
172 }
173
174 int
main(void)175 main (void)
176 {
177 tests_start ();
178
179 check_various ();
180 check_rand ();
181 check_reuse_three ();
182
183 tests_end ();
184 exit (0);
185 }
186