xref: /netbsd-src/external/lgpl3/gmp/dist/tests/mpf/t-div.c (revision 72c7faa4dbb41dbb0238d6b4a109da0d4b236dd4)
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