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