1 /* Functions for evaluating Gamma(1/3) and Gamma(2/3). Used by mpfr_ai.
2
3 Copyright 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
4 Contributed by the AriC and Caramel 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 http://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 #define MPFR_NEED_LONGLONG_H
24 #include "mpfr-impl.h"
25
26 #define MPFR_ACC_OR_MUL(v) \
27 do \
28 { \
29 if (v <= ULONG_MAX / acc) \
30 acc *= v; \
31 else \
32 { \
33 mpfr_mul_ui (y, y, acc, mode); acc = v; \
34 } \
35 } \
36 while (0)
37
38 #define MPFR_ACC_OR_DIV(v) \
39 do \
40 { \
41 if (v <= ULONG_MAX / acc) \
42 acc *= v; \
43 else \
44 { \
45 mpfr_div_ui (y, y, acc, mode); acc = v; \
46 } \
47 } \
48 while (0)
49
50 static void
mpfr_mul_ui5(mpfr_ptr y,mpfr_srcptr x,unsigned long int v1,unsigned long int v2,unsigned long int v3,unsigned long int v4,unsigned long int v5,mpfr_rnd_t mode)51 mpfr_mul_ui5 (mpfr_ptr y, mpfr_srcptr x,
52 unsigned long int v1, unsigned long int v2,
53 unsigned long int v3, unsigned long int v4,
54 unsigned long int v5, mpfr_rnd_t mode)
55 {
56 unsigned long int acc = v1;
57 mpfr_set (y, x, mode);
58 MPFR_ACC_OR_MUL (v2);
59 MPFR_ACC_OR_MUL (v3);
60 MPFR_ACC_OR_MUL (v4);
61 MPFR_ACC_OR_MUL (v5);
62 mpfr_mul_ui (y, y, acc, mode);
63 }
64
65 void
mpfr_div_ui2(mpfr_ptr y,mpfr_srcptr x,unsigned long int v1,unsigned long int v2,mpfr_rnd_t mode)66 mpfr_div_ui2 (mpfr_ptr y, mpfr_srcptr x,
67 unsigned long int v1, unsigned long int v2, mpfr_rnd_t mode)
68 {
69 unsigned long int acc = v1;
70 mpfr_set (y, x, mode);
71 MPFR_ACC_OR_DIV (v2);
72 mpfr_div_ui (y, y, acc, mode);
73 }
74
75 static void
mpfr_div_ui8(mpfr_ptr y,mpfr_srcptr x,unsigned long int v1,unsigned long int v2,unsigned long int v3,unsigned long int v4,unsigned long int v5,unsigned long int v6,unsigned long int v7,unsigned long int v8,mpfr_rnd_t mode)76 mpfr_div_ui8 (mpfr_ptr y, mpfr_srcptr x,
77 unsigned long int v1, unsigned long int v2,
78 unsigned long int v3, unsigned long int v4,
79 unsigned long int v5, unsigned long int v6,
80 unsigned long int v7, unsigned long int v8, mpfr_rnd_t mode)
81 {
82 unsigned long int acc = v1;
83 mpfr_set (y, x, mode);
84 MPFR_ACC_OR_DIV (v2);
85 MPFR_ACC_OR_DIV (v3);
86 MPFR_ACC_OR_DIV (v4);
87 MPFR_ACC_OR_DIV (v5);
88 MPFR_ACC_OR_DIV (v6);
89 MPFR_ACC_OR_DIV (v7);
90 MPFR_ACC_OR_DIV (v8);
91 mpfr_div_ui (y, y, acc, mode);
92 }
93
94
95 /* Gives an approximation of omega = Gamma(1/3)^6 * sqrt(10) / (12pi^4) */
96 /* using C. H. Brown's formula. */
97 /* The computed value s satisfies |s-omega| <= 2^{1-prec}*omega */
98 /* As usual, the variable s is supposed to be initialized. */
99 static void
mpfr_Browns_const(mpfr_ptr s,mpfr_prec_t prec)100 mpfr_Browns_const (mpfr_ptr s, mpfr_prec_t prec)
101 {
102 mpfr_t uk;
103 unsigned long int k;
104
105 mpfr_prec_t working_prec = prec + 10 + MPFR_INT_CEIL_LOG2 (2 + prec / 10);
106
107 mpfr_init2 (uk, working_prec);
108 mpfr_set_prec (s, working_prec);
109
110 mpfr_set_ui (uk, 1, MPFR_RNDN);
111 mpfr_set (s, uk, MPFR_RNDN);
112 k = 1;
113
114 /* Invariants: uk ~ u(k-1) and s ~ sum(i=0..k-1, u(i)) */
115 for (;;)
116 {
117 mpfr_mul_ui5 (uk, uk, 6 * k - 5, 6 * k - 4, 6 * k - 3, 6 * k - 2,
118 6 * k - 1, MPFR_RNDN);
119 mpfr_div_ui8 (uk, uk, k, k, 3 * k - 2, 3 * k - 1, 3 * k, 80, 160, 160,
120 MPFR_RNDN);
121 MPFR_CHANGE_SIGN (uk);
122
123 mpfr_add (s, s, uk, MPFR_RNDN);
124 k++;
125 if (MPFR_GET_EXP (uk) + prec <= MPFR_GET_EXP (s) + 7)
126 break;
127 }
128
129 mpfr_clear (uk);
130 return;
131 }
132
133 /* Returns y such that |Gamma(1/3)-y| <= 2^{1-prec}*Gamma(1/3) */
134 static void
mpfr_gamma_one_third(mpfr_ptr y,mpfr_prec_t prec)135 mpfr_gamma_one_third (mpfr_ptr y, mpfr_prec_t prec)
136 {
137 mpfr_t tmp, tmp2, tmp3;
138
139 mpfr_init2 (tmp, prec + 9);
140 mpfr_init2 (tmp2, prec + 9);
141 mpfr_init2 (tmp3, prec + 4);
142 mpfr_set_prec (y, prec + 2);
143
144 mpfr_const_pi (tmp, MPFR_RNDN);
145 mpfr_sqr (tmp, tmp, MPFR_RNDN);
146 mpfr_sqr (tmp, tmp, MPFR_RNDN);
147 mpfr_mul_ui (tmp, tmp, 12, MPFR_RNDN);
148
149 mpfr_Browns_const (tmp2, prec + 9);
150 mpfr_mul (tmp, tmp, tmp2, MPFR_RNDN);
151
152 mpfr_set_ui (tmp2, 10, MPFR_RNDN);
153 mpfr_sqrt (tmp2, tmp2, MPFR_RNDN);
154 mpfr_div (tmp, tmp, tmp2, MPFR_RNDN);
155
156 mpfr_sqrt (tmp3, tmp, MPFR_RNDN);
157 mpfr_cbrt (y, tmp3, MPFR_RNDN);
158
159 mpfr_clear (tmp);
160 mpfr_clear (tmp2);
161 mpfr_clear (tmp3);
162 return;
163 }
164
165 /* Computes y1 and y2 such that: */
166 /* |y1-Gamma(1/3)| <= 2^{1-prec}Gamma(1/3) */
167 /* and |y2-Gamma(2/3)| <= 2^{1-prec}Gamma(2/3) */
168 /* */
169 /* Uses the formula Gamma(z)Gamma(1-z) = pi / sin(pi*z) */
170 /* to compute Gamma(2/3) from Gamma(1/3). */
171 void
mpfr_gamma_one_and_two_third(mpfr_ptr y1,mpfr_ptr y2,mpfr_prec_t prec)172 mpfr_gamma_one_and_two_third (mpfr_ptr y1, mpfr_ptr y2, mpfr_prec_t prec)
173 {
174 mpfr_t temp;
175
176 mpfr_init2 (temp, prec + 4);
177 mpfr_set_prec (y2, prec + 4);
178
179 mpfr_gamma_one_third (y1, prec + 4);
180
181 mpfr_set_ui (temp, 3, MPFR_RNDN);
182 mpfr_sqrt (temp, temp, MPFR_RNDN);
183 mpfr_mul (temp, y1, temp, MPFR_RNDN);
184
185 mpfr_const_pi (y2, MPFR_RNDN);
186 mpfr_mul_2ui (y2, y2, 1, MPFR_RNDN);
187
188 mpfr_div (y2, y2, temp, MPFR_RNDN);
189
190 mpfr_clear (temp);
191 }
192