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