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