xref: /dragonfly/contrib/mpfr/src/gammaonethird.c (revision ab6d115f)
14a238c70SJohn Marino /* Functions for evaluating Gamma(1/3) and Gamma(2/3). Used by mpfr_ai.
24a238c70SJohn Marino 
3*ab6d115fSJohn Marino Copyright 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
4*ab6d115fSJohn Marino Contributed by the AriC and Caramel projects, INRIA.
54a238c70SJohn Marino 
64a238c70SJohn Marino This file is part of the GNU MPFR Library.
74a238c70SJohn Marino 
84a238c70SJohn Marino The GNU MPFR Library is free software; you can redistribute it and/or modify
94a238c70SJohn Marino it under the terms of the GNU Lesser General Public License as published by
104a238c70SJohn Marino the Free Software Foundation; either version 3 of the License, or (at your
114a238c70SJohn Marino option) any later version.
124a238c70SJohn Marino 
134a238c70SJohn Marino The GNU MPFR Library is distributed in the hope that it will be useful, but
144a238c70SJohn Marino WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
154a238c70SJohn Marino or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
164a238c70SJohn Marino License for more details.
174a238c70SJohn Marino 
184a238c70SJohn Marino You should have received a copy of the GNU Lesser General Public License
194a238c70SJohn Marino along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
204a238c70SJohn Marino http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
214a238c70SJohn Marino 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
224a238c70SJohn Marino 
234a238c70SJohn Marino #define MPFR_NEED_LONGLONG_H
244a238c70SJohn Marino #include "mpfr-impl.h"
254a238c70SJohn Marino 
264a238c70SJohn Marino #define MPFR_ACC_OR_MUL(v)                              \
274a238c70SJohn Marino   do                                                    \
284a238c70SJohn Marino     {                                                   \
294a238c70SJohn Marino       if (v <= ULONG_MAX / acc)                         \
304a238c70SJohn Marino         acc *= v;                                       \
314a238c70SJohn Marino       else                                              \
324a238c70SJohn Marino         {                                               \
334a238c70SJohn Marino           mpfr_mul_ui (y, y, acc, mode); acc = v;       \
344a238c70SJohn Marino         }                                               \
354a238c70SJohn Marino     }                                                   \
364a238c70SJohn Marino   while (0)
374a238c70SJohn Marino 
384a238c70SJohn Marino #define MPFR_ACC_OR_DIV(v)                              \
394a238c70SJohn Marino   do                                                    \
404a238c70SJohn Marino     {                                                   \
414a238c70SJohn Marino       if (v <= ULONG_MAX / acc)                         \
424a238c70SJohn Marino         acc *= v;                                       \
434a238c70SJohn Marino       else                                              \
444a238c70SJohn Marino         {                                               \
454a238c70SJohn Marino           mpfr_div_ui (y, y, acc, mode); acc = v;       \
464a238c70SJohn Marino         }                                               \
474a238c70SJohn Marino     }                                                   \
484a238c70SJohn Marino   while (0)
494a238c70SJohn Marino 
504a238c70SJohn Marino 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)514a238c70SJohn Marino mpfr_mul_ui5 (mpfr_ptr y, mpfr_srcptr x,
524a238c70SJohn Marino               unsigned long int v1, unsigned long int v2,
534a238c70SJohn Marino               unsigned long int v3, unsigned long int v4,
544a238c70SJohn Marino               unsigned long int v5, mpfr_rnd_t mode)
554a238c70SJohn Marino {
564a238c70SJohn Marino   unsigned long int acc = v1;
574a238c70SJohn Marino   mpfr_set (y, x, mode);
584a238c70SJohn Marino   MPFR_ACC_OR_MUL (v2);
594a238c70SJohn Marino   MPFR_ACC_OR_MUL (v3);
604a238c70SJohn Marino   MPFR_ACC_OR_MUL (v4);
614a238c70SJohn Marino   MPFR_ACC_OR_MUL (v5);
624a238c70SJohn Marino   mpfr_mul_ui (y, y, acc, mode);
634a238c70SJohn Marino }
644a238c70SJohn Marino 
654a238c70SJohn Marino void
mpfr_div_ui2(mpfr_ptr y,mpfr_srcptr x,unsigned long int v1,unsigned long int v2,mpfr_rnd_t mode)664a238c70SJohn Marino mpfr_div_ui2 (mpfr_ptr y, mpfr_srcptr x,
674a238c70SJohn Marino               unsigned long int v1, unsigned long int v2, mpfr_rnd_t mode)
684a238c70SJohn Marino {
694a238c70SJohn Marino   unsigned long int acc = v1;
704a238c70SJohn Marino   mpfr_set (y, x, mode);
714a238c70SJohn Marino   MPFR_ACC_OR_DIV (v2);
724a238c70SJohn Marino   mpfr_div_ui (y, y, acc, mode);
734a238c70SJohn Marino }
744a238c70SJohn Marino 
754a238c70SJohn Marino 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)764a238c70SJohn Marino mpfr_div_ui8 (mpfr_ptr y, mpfr_srcptr x,
774a238c70SJohn Marino               unsigned long int v1, unsigned long int v2,
784a238c70SJohn Marino               unsigned long int v3, unsigned long int v4,
794a238c70SJohn Marino               unsigned long int v5, unsigned long int v6,
804a238c70SJohn Marino               unsigned long int v7, unsigned long int v8, mpfr_rnd_t mode)
814a238c70SJohn Marino {
824a238c70SJohn Marino   unsigned long int acc = v1;
834a238c70SJohn Marino   mpfr_set (y, x, mode);
844a238c70SJohn Marino   MPFR_ACC_OR_DIV (v2);
854a238c70SJohn Marino   MPFR_ACC_OR_DIV (v3);
864a238c70SJohn Marino   MPFR_ACC_OR_DIV (v4);
874a238c70SJohn Marino   MPFR_ACC_OR_DIV (v5);
884a238c70SJohn Marino   MPFR_ACC_OR_DIV (v6);
894a238c70SJohn Marino   MPFR_ACC_OR_DIV (v7);
904a238c70SJohn Marino   MPFR_ACC_OR_DIV (v8);
914a238c70SJohn Marino   mpfr_div_ui (y, y, acc, mode);
924a238c70SJohn Marino }
934a238c70SJohn Marino 
944a238c70SJohn Marino 
954a238c70SJohn Marino /* Gives an approximation of omega = Gamma(1/3)^6 * sqrt(10) / (12pi^4) */
964a238c70SJohn Marino /* using C. H. Brown's formula.                                         */
974a238c70SJohn Marino /* The computed value s satisfies |s-omega| <= 2^{1-prec}*omega         */
984a238c70SJohn Marino /* As usual, the variable s is supposed to be initialized.              */
994a238c70SJohn Marino static void
mpfr_Browns_const(mpfr_ptr s,mpfr_prec_t prec)1004a238c70SJohn Marino mpfr_Browns_const (mpfr_ptr s, mpfr_prec_t prec)
1014a238c70SJohn Marino {
1024a238c70SJohn Marino   mpfr_t uk;
1034a238c70SJohn Marino   unsigned long int k;
1044a238c70SJohn Marino 
1054a238c70SJohn Marino   mpfr_prec_t working_prec = prec + 10 + MPFR_INT_CEIL_LOG2 (2 + prec / 10);
1064a238c70SJohn Marino 
1074a238c70SJohn Marino   mpfr_init2 (uk, working_prec);
1084a238c70SJohn Marino   mpfr_set_prec (s, working_prec);
1094a238c70SJohn Marino 
1104a238c70SJohn Marino   mpfr_set_ui (uk, 1, MPFR_RNDN);
1114a238c70SJohn Marino   mpfr_set (s, uk, MPFR_RNDN);
1124a238c70SJohn Marino   k = 1;
1134a238c70SJohn Marino 
1144a238c70SJohn Marino   /* Invariants: uk ~ u(k-1) and s ~ sum(i=0..k-1, u(i)) */
1154a238c70SJohn Marino   for (;;)
1164a238c70SJohn Marino     {
1174a238c70SJohn Marino       mpfr_mul_ui5 (uk, uk, 6 * k - 5, 6 * k - 4, 6 * k - 3, 6 * k - 2,
1184a238c70SJohn Marino                     6 * k - 1, MPFR_RNDN);
1194a238c70SJohn Marino       mpfr_div_ui8 (uk, uk, k, k, 3 * k - 2, 3 * k - 1, 3 * k, 80, 160, 160,
1204a238c70SJohn Marino                     MPFR_RNDN);
1214a238c70SJohn Marino       MPFR_CHANGE_SIGN (uk);
1224a238c70SJohn Marino 
1234a238c70SJohn Marino       mpfr_add (s, s, uk, MPFR_RNDN);
1244a238c70SJohn Marino       k++;
1254a238c70SJohn Marino       if (MPFR_GET_EXP (uk) + prec <= MPFR_GET_EXP (s) + 7)
1264a238c70SJohn Marino         break;
1274a238c70SJohn Marino     }
1284a238c70SJohn Marino 
1294a238c70SJohn Marino   mpfr_clear (uk);
1304a238c70SJohn Marino   return;
1314a238c70SJohn Marino }
1324a238c70SJohn Marino 
1334a238c70SJohn Marino /* Returns y such that |Gamma(1/3)-y| <= 2^{1-prec}*Gamma(1/3) */
1344a238c70SJohn Marino static void
mpfr_gamma_one_third(mpfr_ptr y,mpfr_prec_t prec)1354a238c70SJohn Marino mpfr_gamma_one_third (mpfr_ptr y, mpfr_prec_t prec)
1364a238c70SJohn Marino {
1374a238c70SJohn Marino   mpfr_t tmp, tmp2, tmp3;
1384a238c70SJohn Marino 
1394a238c70SJohn Marino   mpfr_init2 (tmp, prec + 9);
1404a238c70SJohn Marino   mpfr_init2 (tmp2, prec + 9);
1414a238c70SJohn Marino   mpfr_init2 (tmp3, prec + 4);
1424a238c70SJohn Marino   mpfr_set_prec (y, prec + 2);
1434a238c70SJohn Marino 
1444a238c70SJohn Marino   mpfr_const_pi (tmp, MPFR_RNDN);
1454a238c70SJohn Marino   mpfr_sqr (tmp, tmp, MPFR_RNDN);
1464a238c70SJohn Marino   mpfr_sqr (tmp, tmp, MPFR_RNDN);
1474a238c70SJohn Marino   mpfr_mul_ui (tmp, tmp, 12, MPFR_RNDN);
1484a238c70SJohn Marino 
1494a238c70SJohn Marino   mpfr_Browns_const (tmp2, prec + 9);
1504a238c70SJohn Marino   mpfr_mul (tmp, tmp, tmp2, MPFR_RNDN);
1514a238c70SJohn Marino 
1524a238c70SJohn Marino   mpfr_set_ui (tmp2, 10, MPFR_RNDN);
1534a238c70SJohn Marino   mpfr_sqrt (tmp2, tmp2, MPFR_RNDN);
1544a238c70SJohn Marino   mpfr_div (tmp, tmp, tmp2, MPFR_RNDN);
1554a238c70SJohn Marino 
1564a238c70SJohn Marino   mpfr_sqrt (tmp3, tmp, MPFR_RNDN);
1574a238c70SJohn Marino   mpfr_cbrt (y, tmp3, MPFR_RNDN);
1584a238c70SJohn Marino 
1594a238c70SJohn Marino   mpfr_clear (tmp);
1604a238c70SJohn Marino   mpfr_clear (tmp2);
1614a238c70SJohn Marino   mpfr_clear (tmp3);
1624a238c70SJohn Marino   return;
1634a238c70SJohn Marino }
1644a238c70SJohn Marino 
1654a238c70SJohn Marino /* Computes y1 and y2 such that:                                      */
1664a238c70SJohn Marino /*        |y1-Gamma(1/3)| <= 2^{1-prec}Gamma(1/3)                     */
1674a238c70SJohn Marino /*  and   |y2-Gamma(2/3)| <= 2^{1-prec}Gamma(2/3)                     */
1684a238c70SJohn Marino /*                                                                    */
1694a238c70SJohn Marino /* Uses the formula Gamma(z)Gamma(1-z) = pi / sin(pi*z)               */
1704a238c70SJohn Marino /* to compute Gamma(2/3) from Gamma(1/3).                             */
1714a238c70SJohn Marino void
mpfr_gamma_one_and_two_third(mpfr_ptr y1,mpfr_ptr y2,mpfr_prec_t prec)1724a238c70SJohn Marino mpfr_gamma_one_and_two_third (mpfr_ptr y1, mpfr_ptr y2, mpfr_prec_t prec)
1734a238c70SJohn Marino {
1744a238c70SJohn Marino   mpfr_t temp;
1754a238c70SJohn Marino 
1764a238c70SJohn Marino   mpfr_init2 (temp, prec + 4);
1774a238c70SJohn Marino   mpfr_set_prec (y2, prec + 4);
1784a238c70SJohn Marino 
1794a238c70SJohn Marino   mpfr_gamma_one_third (y1, prec + 4);
1804a238c70SJohn Marino 
1814a238c70SJohn Marino   mpfr_set_ui (temp, 3, MPFR_RNDN);
1824a238c70SJohn Marino   mpfr_sqrt (temp, temp, MPFR_RNDN);
1834a238c70SJohn Marino   mpfr_mul (temp, y1, temp, MPFR_RNDN);
1844a238c70SJohn Marino 
1854a238c70SJohn Marino   mpfr_const_pi (y2, MPFR_RNDN);
1864a238c70SJohn Marino   mpfr_mul_2ui (y2, y2, 1, MPFR_RNDN);
1874a238c70SJohn Marino 
1884a238c70SJohn Marino   mpfr_div (y2, y2, temp, MPFR_RNDN);
1894a238c70SJohn Marino 
1904a238c70SJohn Marino   mpfr_clear (temp);
1914a238c70SJohn Marino }
192