xref: /netbsd-src/external/lgpl3/mpfr/dist/tests/tconst_pi.c (revision ba125506a622fe649968631a56eba5d42ff57863)
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