1 /* mpfr_tlngamma -- test file for lngamma function
2
3 Copyright 2005-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 #define TEST_FUNCTION mpfr_lngamma
26 #define TEST_RANDOM_POS 16
27 #include "tgeneric.c"
28
29 static void
special(void)30 special (void)
31 {
32 mpfr_t x, y;
33 int i, inex;
34
35 mpfr_init (x);
36 mpfr_init (y);
37
38 mpfr_set_nan (x);
39 mpfr_lngamma (y, x, MPFR_RNDN);
40 if (!mpfr_nan_p (y))
41 {
42 printf ("Error for lngamma(NaN)\n");
43 exit (1);
44 }
45
46 mpfr_set_inf (x, 1);
47 mpfr_clear_flags ();
48 mpfr_lngamma (y, x, MPFR_RNDN);
49 if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0 || __gmpfr_flags != 0)
50 {
51 printf ("Error for lngamma(+Inf)\n");
52 exit (1);
53 }
54
55 mpfr_set_inf (x, -1);
56 mpfr_clear_flags ();
57 mpfr_lngamma (y, x, MPFR_RNDN);
58 if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0 || __gmpfr_flags != 0)
59 {
60 printf ("Error for lngamma(-Inf)\n");
61 exit (1);
62 }
63
64 mpfr_set_ui (x, 0, MPFR_RNDN);
65 mpfr_clear_flags ();
66 mpfr_lngamma (y, x, MPFR_RNDN);
67 if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0 ||
68 __gmpfr_flags != MPFR_FLAGS_DIVBY0)
69 {
70 printf ("Error for lngamma(+0)\n");
71 exit (1);
72 }
73
74 mpfr_set_ui (x, 0, MPFR_RNDN);
75 mpfr_neg (x, x, MPFR_RNDN);
76 mpfr_clear_flags ();
77 mpfr_lngamma (y, x, MPFR_RNDN);
78 if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0 ||
79 __gmpfr_flags != MPFR_FLAGS_DIVBY0)
80 {
81 printf ("Error for lngamma(-0)\n");
82 exit (1);
83 }
84
85 mpfr_set_ui (x, 1, MPFR_RNDN);
86 mpfr_clear_flags ();
87 mpfr_lngamma (y, x, MPFR_RNDN);
88 if (mpfr_cmp_ui0 (y, 0) || MPFR_IS_NEG (y))
89 {
90 printf ("Error for lngamma(1)\n");
91 exit (1);
92 }
93
94 for (i = 1; i <= 5; i++)
95 {
96 int c;
97
98 mpfr_set_si (x, -i, MPFR_RNDN);
99 mpfr_clear_flags ();
100 mpfr_lngamma (y, x, MPFR_RNDN);
101 if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0 ||
102 __gmpfr_flags != MPFR_FLAGS_DIVBY0)
103 {
104 printf ("Error for lngamma(-%d)\n", i);
105 exit (1);
106 }
107 if (i & 1)
108 {
109 mpfr_nextabove (x);
110 c = '+';
111 }
112 else
113 {
114 mpfr_nextbelow (x);
115 c = '-';
116 }
117 mpfr_lngamma (y, x, MPFR_RNDN);
118 if (!mpfr_nan_p (y))
119 {
120 printf ("Error for lngamma(-%d%cepsilon)\n", i, c);
121 exit (1);
122 }
123 }
124
125 mpfr_set_ui (x, 2, MPFR_RNDN);
126 mpfr_lngamma (y, x, MPFR_RNDN);
127 if (mpfr_cmp_ui0 (y, 0) || MPFR_IS_NEG (y))
128 {
129 printf ("Error for lngamma(2)\n");
130 exit (1);
131 }
132
133 mpfr_set_prec (x, 53);
134 mpfr_set_prec (y, 53);
135
136 #define CHECK_X1 "1.0762904832837976166"
137 #define CHECK_Y1 "-0.039418362817587634939"
138
139 mpfr_set_str (x, CHECK_X1, 10, MPFR_RNDN);
140 mpfr_lngamma (y, x, MPFR_RNDN);
141 mpfr_set_str (x, CHECK_Y1, 10, MPFR_RNDN);
142 if (MPFR_IS_NAN (y) || mpfr_cmp (y, x))
143 {
144 printf ("mpfr_lngamma(" CHECK_X1 ") is wrong:\n"
145 "expected ");
146 mpfr_dump (x);
147 printf ("got ");
148 mpfr_dump (y);
149 exit (1);
150 }
151
152 #define CHECK_X2 "9.23709516716202383435e-01"
153 #define CHECK_Y2 "0.049010669407893718563"
154 mpfr_set_str (x, CHECK_X2, 10, MPFR_RNDN);
155 mpfr_lngamma (y, x, MPFR_RNDN);
156 mpfr_set_str (x, CHECK_Y2, 10, MPFR_RNDN);
157 if (mpfr_cmp0 (y, x))
158 {
159 printf ("mpfr_lngamma(" CHECK_X2 ") is wrong:\n"
160 "expected ");
161 mpfr_dump (x);
162 printf ("got ");
163 mpfr_dump (y);
164 exit (1);
165 }
166
167 mpfr_set_prec (x, 8);
168 mpfr_set_prec (y, 175);
169 mpfr_set_ui (x, 33, MPFR_RNDN);
170 mpfr_lngamma (y, x, MPFR_RNDU);
171 mpfr_set_prec (x, 175);
172 mpfr_set_str_binary (x, "0.1010001100011101101011001101110010100001000001000001110011000001101100001111001001000101011011100100010101011110100111110101010100010011010010000101010111001100011000101111E7");
173 if (mpfr_cmp0 (x, y))
174 {
175 printf ("Error in mpfr_lngamma (1)\n");
176 exit (1);
177 }
178
179 mpfr_set_prec (x, 21);
180 mpfr_set_prec (y, 8);
181 mpfr_set_ui (y, 120, MPFR_RNDN);
182 mpfr_lngamma (x, y, MPFR_RNDZ);
183 mpfr_set_prec (y, 21);
184 mpfr_set_str_binary (y, "0.111000101000001100101E9");
185 if (mpfr_cmp0 (x, y))
186 {
187 printf ("Error in mpfr_lngamma (120)\n");
188 printf ("Expected "); mpfr_dump (y);
189 printf ("Got "); mpfr_dump (x);
190 exit (1);
191 }
192
193 mpfr_set_prec (x, 3);
194 mpfr_set_prec (y, 206);
195 mpfr_set_str_binary (x, "0.110e10");
196 inex = mpfr_lngamma (y, x, MPFR_RNDN);
197 mpfr_set_prec (x, 206);
198 mpfr_set_str_binary (x, "0.10000111011000000011100010101001100110001110000111100011000100100110110010001011011110101001111011110110000001010100111011010000000011100110110101100111000111010011110010000100010111101010001101000110101001E13");
199 if (mpfr_cmp0 (x, y))
200 {
201 printf ("Error in mpfr_lngamma (768)\n");
202 exit (1);
203 }
204 if (inex >= 0)
205 {
206 printf ("Wrong flag for mpfr_lngamma (768)\n");
207 exit (1);
208 }
209
210 mpfr_set_prec (x, 4);
211 mpfr_set_prec (y, 4);
212 mpfr_set_str_binary (x, "0.1100E-66");
213 mpfr_lngamma (y, x, MPFR_RNDN);
214 mpfr_set_str_binary (x, "0.1100E6");
215 if (mpfr_cmp0 (x, y))
216 {
217 printf ("Error for lngamma(0.1100E-66)\n");
218 exit (1);
219 }
220
221 mpfr_set_prec (x, 256);
222 mpfr_set_prec (y, 32);
223 mpfr_set_si_2exp (x, -1, 200, MPFR_RNDN);
224 mpfr_add_ui (x, x, 1, MPFR_RNDN);
225 mpfr_div_2ui (x, x, 1, MPFR_RNDN);
226 mpfr_lngamma (y, x, MPFR_RNDN);
227 mpfr_set_prec (x, 32);
228 mpfr_set_str_binary (x, "-0.10001000111011111011000010100010E207");
229 if (mpfr_cmp0 (x, y))
230 {
231 printf ("Error for lngamma(-2^199+0.5)\n");
232 printf ("Got ");
233 mpfr_dump (y);
234 printf ("instead of ");
235 mpfr_dump (x);
236 exit (1);
237 }
238
239 mpfr_set_prec (x, 256);
240 mpfr_set_prec (y, 32);
241 mpfr_set_si_2exp (x, -1, 200, MPFR_RNDN);
242 mpfr_sub_ui (x, x, 1, MPFR_RNDN);
243 mpfr_div_2ui (x, x, 1, MPFR_RNDN);
244 mpfr_lngamma (y, x, MPFR_RNDN);
245 if (!mpfr_nan_p (y))
246 {
247 printf ("Error for lngamma(-2^199-0.5)\n");
248 exit (1);
249 }
250
251 mpfr_clear (x);
252 mpfr_clear (y);
253 }
254
255 /* test failing with GMP_CHECK_RANDOMIZE=1513869588 */
256 static void
bug20171220(void)257 bug20171220 (void)
258 {
259 mpfr_t x, y, z;
260 int inex;
261
262 mpfr_init2 (x, 15);
263 mpfr_init2 (y, 15);
264 mpfr_init2 (z, 15);
265
266 mpfr_set_str (x, "1.01111e+00", 10, MPFR_RNDN); /* x = 8283/8192 */
267 inex = mpfr_lngamma (y, x, MPFR_RNDN);
268 mpfr_set_str (z, "-0.0063109971733698154140545190234", 10, MPFR_RNDN);
269 MPFR_ASSERTN(mpfr_equal_p (y, z));
270 MPFR_ASSERTN(inex > 0);
271
272 mpfr_set_prec (x, 43);
273 mpfr_set_prec (y, 1);
274 mpfr_set_prec (z, 1);
275 mpfr_set_str (x, "9.8888652212918e-01", 10, MPFR_RNDN);
276 /* lngamma(x) = 0.00651701007222520, should be rounded up to 0.0078125 */
277 inex = mpfr_lngamma (y, x, MPFR_RNDU);
278 mpfr_set_ui_2exp (z, 1, -7, MPFR_RNDN);
279 MPFR_ASSERTN(mpfr_equal_p (y, z));
280 MPFR_ASSERTN(inex > 0);
281
282 mpfr_clear (x);
283 mpfr_clear (y);
284 mpfr_clear (z);
285 }
286
287 /* taway failing with GMP_CHECK_RANDOMIZE=1513888822 */
288 static void
bug20171220a(void)289 bug20171220a (void)
290 {
291 mpfr_t x, y, z;
292 int inex;
293
294 mpfr_init2 (x, 198);
295 mpfr_init2 (y, 1);
296 mpfr_init2 (z, 1);
297
298 mpfr_set_str (x, "9.999962351340362288585900348170984233205352566408878552154832e-01", 10, MPFR_RNDN);
299 inex = mpfr_lngamma (y, x, MPFR_RNDA);
300 /* lngamma(x) ~ 2.1731512683e0-6 ~ 2^-18.81, should be rounded to 2^-18 */
301 mpfr_set_si_2exp (z, 1, -18, MPFR_RNDN);
302 MPFR_ASSERTN(mpfr_equal_p (y, z));
303 MPFR_ASSERTN(inex > 0);
304
305 mpfr_clear (x);
306 mpfr_clear (y);
307 mpfr_clear (z);
308 }
309
310 int
main(void)311 main (void)
312 {
313 tests_start_mpfr ();
314
315 bug20171220 ();
316 bug20171220a ();
317
318 special ();
319 test_generic (MPFR_PREC_MIN, 100, 2);
320
321 tests_end_mpfr ();
322 return 0;
323 }
324