1 /* Test file for mpfr_const_pi.
2
3 Copyright 1999, 2001-2023 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramba projects, INRIA.
5
6 This file is part of the GNU MPFR Library.
7
8 The GNU MPFR Library is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12
13 The GNU MPFR Library is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16 License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see
20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
22
23 #include "mpfr-test.h"
24
25 #if defined(MPFR_WANT_SHARED_CACHE) && defined(HAVE_PTHREAD)
26
27 # include <pthread.h>
28
29 #define MAX_THREAD 100
30
31 static void *
start_routine(void * arg)32 start_routine (void *arg)
33 {
34 mpfr_prec_t p;
35 mpfr_t x;
36 mpfr_prec_t inc = *(int *) arg;
37 mp_limb_t *m;
38
39 for (p = 100; p < 20000; p += 64 + 100 * (inc % 10))
40 {
41 mpfr_init2 (x, p);
42 m = MPFR_MANT (x);
43 mpfr_const_pi (x, MPFR_RNDD);
44 mpfr_prec_round (x, 53, MPFR_RNDD);
45 if (mpfr_cmp_str1 (x, "3.141592653589793116"))
46 {
47 printf ("mpfr_const_pi failed with threading\n");
48 mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar('\n');
49 exit (1);
50 }
51 /* Check that no reallocation has been performed */
52 MPFR_ASSERTN (m == MPFR_MANT (x));
53 mpfr_clear (x);
54 }
55
56 pthread_exit (NULL);
57 }
58
59 static void
run_pthread_test(void)60 run_pthread_test (void)
61 {
62 int i;
63 int error_code;
64 pthread_t thread_id[MAX_THREAD];
65 int table[MAX_THREAD];
66
67 for (i = 0; i < MAX_THREAD; i++)
68 {
69 table[i] = i;
70 error_code = pthread_create(&thread_id[i],
71 NULL, start_routine, &table[i]);
72 MPFR_ASSERTN (error_code == 0);
73 }
74
75 for (i = 0; i < MAX_THREAD; i++)
76 {
77 error_code = pthread_join (thread_id[i], NULL);
78 MPFR_ASSERTN (error_code == 0);
79 }
80 }
81
82 # define RUN_PTHREAD_TEST() \
83 (MPFR_ASSERTN(mpfr_buildopt_sharedcache_p() == 1), run_pthread_test())
84
85 #else
86
87 # define RUN_PTHREAD_TEST() ((void) 0)
88
89 #endif
90
91 /* tconst_pi [prec] [rnd] [0 = no print] */
92
93 static void
check_large(void)94 check_large (void)
95 {
96 mpfr_t x, y, z;
97
98 mpfr_init2 (x, 20000);
99 mpfr_init2 (y, 21000);
100 mpfr_init2 (z, 11791);
101
102 /* The algo failed to round for p=11791. */
103 (mpfr_const_pi) (z, MPFR_RNDU);
104 mpfr_const_pi (x, MPFR_RNDN); /* First one ! */
105 mpfr_const_pi (y, MPFR_RNDN); /* Then the other - cache - */
106 mpfr_prec_round (y, 20000, MPFR_RNDN);
107 if (mpfr_cmp (x, y)) {
108 printf ("const_pi: error for large prec (%d)\n", 1);
109 exit (1);
110 }
111 mpfr_prec_round (y, 11791, MPFR_RNDU);
112 if (mpfr_cmp (z, y)) {
113 printf ("const_pi: error for large prec (%d)\n", 2);
114 exit (1);
115 }
116
117 /* a worst-case to exercise recomputation */
118 if (MPFR_PREC_MAX > 33440) {
119 mpfr_set_prec (x, 33440);
120 mpfr_const_pi (x, MPFR_RNDZ);
121 }
122
123 mpfr_clears (x, y, z, (mpfr_ptr) 0);
124 }
125
126 /* Wrapper for tgeneric */
127 static int
my_const_pi(mpfr_ptr x,mpfr_srcptr y,mpfr_rnd_t r)128 my_const_pi (mpfr_ptr x, mpfr_srcptr y, mpfr_rnd_t r)
129 {
130 return mpfr_const_pi (x, r);
131 }
132
133 #define RAND_FUNCTION(x) mpfr_set_ui ((x), 0, MPFR_RNDN)
134 #define TEST_FUNCTION my_const_pi
135 #include "tgeneric.c"
136
137 static void
bug20091030(void)138 bug20091030 (void)
139 {
140 mpfr_t x, x_ref;
141 int inex, inex_ref;
142 mpfr_prec_t p;
143 int r;
144
145 mpfr_free_cache ();
146 mpfr_init2 (x, MPFR_PREC_MIN);
147 for (p = MPFR_PREC_MIN; p <= 100; p++)
148 {
149 mpfr_set_prec (x, p);
150 inex = mpfr_const_pi (x, MPFR_RNDU);
151 if (inex < 0)
152 {
153 printf ("Error, inex < 0 for RNDU (prec=%lu)\n",
154 (unsigned long) p);
155 exit (1);
156 }
157 inex = mpfr_const_pi (x, MPFR_RNDD);
158 if (inex > 0)
159 {
160 printf ("Error, inex > 0 for RNDD (prec=%lu)\n",
161 (unsigned long) p);
162 exit (1);
163 }
164 }
165 mpfr_free_cache ();
166 mpfr_init2 (x_ref, MPFR_PREC_MIN);
167 for (p = MPFR_PREC_MIN; p <= 100; p++)
168 {
169 mpfr_set_prec (x, p + 10);
170 mpfr_const_pi (x, MPFR_RNDN);
171 mpfr_set_prec (x, p);
172 mpfr_set_prec (x_ref, p);
173 RND_LOOP (r)
174 {
175 if (r == MPFR_RNDF)
176 continue; /* the test below makes no sense */
177 inex = mpfr_const_pi (x, (mpfr_rnd_t) r);
178 inex_ref = mpfr_const_pi_internal (x_ref, (mpfr_rnd_t) r);
179 if (inex != inex_ref || mpfr_cmp (x, x_ref) != 0)
180 {
181 printf ("mpfr_const_pi and mpfr_const_pi_internal disagree for rnd=%s\n", mpfr_print_rnd_mode ((mpfr_rnd_t) r));
182 printf ("mpfr_const_pi gives ");
183 mpfr_dump (x);
184 printf ("mpfr_const_pi_internal gives ");
185 mpfr_dump (x_ref);
186 printf ("inex=%d inex_ref=%d\n", inex, inex_ref);
187 exit (1);
188 }
189 }
190 }
191 mpfr_clear (x);
192 mpfr_clear (x_ref);
193 }
194
195 int
main(int argc,char * argv[])196 main (int argc, char *argv[])
197 {
198 mpfr_t x;
199 mpfr_prec_t p;
200 mpfr_rnd_t rnd;
201
202 tests_start_mpfr ();
203
204 p = 53;
205 if (argc > 1)
206 {
207 long a = atol (argv[1]);
208 if (MPFR_PREC_COND (a))
209 p = a;
210 }
211
212 rnd = (argc > 2) ? (mpfr_rnd_t) atoi(argv[2]) : MPFR_RNDZ;
213
214 mpfr_init2 (x, p);
215 mpfr_const_pi (x, rnd);
216 if (argc >= 2)
217 {
218 if (argc < 4 || atoi (argv[3]) != 0)
219 {
220 printf ("Pi=");
221 mpfr_out_str (stdout, 10, 0, x, rnd);
222 puts ("");
223 }
224 }
225 else if (mpfr_cmp_str1 (x, "3.141592653589793116") )
226 {
227 printf ("mpfr_const_pi failed for prec=53\n");
228 mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); putchar('\n');
229 exit (1);
230 }
231
232 mpfr_set_prec (x, 32);
233 mpfr_const_pi (x, MPFR_RNDN);
234 if (mpfr_cmp_str1 (x, "3.141592653468251") )
235 {
236 printf ("mpfr_const_pi failed for prec=32\n");
237 exit (1);
238 }
239
240 mpfr_clear (x);
241
242 bug20091030 ();
243
244 check_large ();
245
246 test_generic (MPFR_PREC_MIN, 200, 1);
247
248 RUN_PTHREAD_TEST();
249
250 /* the following is just to test mpfr_free_cache2 with MPFR_FREE_LOCAL_CACHE,
251 it should not hurt, since the call to mpfr_free_cache in tests_end_mpfr
252 will do nothing */
253 mpfr_free_cache2 (MPFR_FREE_LOCAL_CACHE);
254
255 tests_end_mpfr ();
256
257 /* another test of mpfr_free_cache2 with MPFR_FREE_LOCAL_CACHE, to check
258 that we can call it when the caches are already freed */
259 mpfr_free_cache2 (MPFR_FREE_LOCAL_CACHE);
260
261 return 0;
262 }
263