mirror of
https://github.com/vale981/arb
synced 2025-03-06 01:41:39 -05:00
faster rising factorials again
This commit is contained in:
parent
79143c1c7e
commit
72e4d68b63
10 changed files with 606 additions and 9 deletions
|
@ -66,6 +66,8 @@ Bibliography
|
||||||
|
|
||||||
.. [PS1973] M.S. Paterson and L. J. Stockmeyer, "On the number of nonscalar multiplications necessary to evaluate polynomials", SIAM J. Comput (1973)
|
.. [PS1973] M.S. Paterson and L. J. Stockmeyer, "On the number of nonscalar multiplications necessary to evaluate polynomials", SIAM J. Comput (1973)
|
||||||
|
|
||||||
|
.. [Smi2001] D.M. Smith, "Algorithm: Fortran 90 Software for Floating-Point Multiple Precision Arithmetic, Gamma and Related Functions", Transactions on Mathematical Software 27 (2001) 377-387, http://myweb.lmu.edu/dmsmith/toms2001.pdf
|
||||||
|
|
||||||
.. [Tak2000] D.Takahashi, "A fast algorithm for computing large Fibonacci numbers", Information Processing Letters 75 (2000) 243-246. http://www.ii.uni.wroc.pl/~lorys/IPL/article75-6-1.pdf
|
.. [Tak2000] D.Takahashi, "A fast algorithm for computing large Fibonacci numbers", Information Processing Letters 75 (2000) 243-246. http://www.ii.uni.wroc.pl/~lorys/IPL/article75-6-1.pdf
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -170,6 +170,43 @@ Rising factorials
|
||||||
*gamma_rising_fmpcb_ui_bsplit* automatically choose
|
*gamma_rising_fmpcb_ui_bsplit* automatically choose
|
||||||
an algorithm depending on the inputs.
|
an algorithm depending on the inputs.
|
||||||
|
|
||||||
|
.. function :: void gamma_rising_fmprb_ui_delta(fmprb_t y, const fmprb_t x, ulong n, ulong m, long prec)
|
||||||
|
|
||||||
|
.. function :: void gamma_rising_fmpcb_ui_delta(fmpcb_t y, const fmpcb_t x, ulong n, ulong m, long prec)
|
||||||
|
|
||||||
|
Sets `y` to the rising factorial `x (x+1) (x+2) \cdots (x+n-1)`,
|
||||||
|
computed as a product of partial products
|
||||||
|
`(x+k)(x+k+1)\cdots(x+k+m-1)`. Each partial product is obtained
|
||||||
|
from the previous by using a precomputed table of powers of `x` to
|
||||||
|
evaluate the difference
|
||||||
|
|
||||||
|
.. math ::
|
||||||
|
|
||||||
|
\Delta_m(x,k) = (x+k+m)_{(m)} - (x+k)_{(m)}.
|
||||||
|
|
||||||
|
The instance `m = 4` of this algorithm was used by Smith ([Smi2001]_),
|
||||||
|
but we generalize it to a variable `m` which can be chosen nearly
|
||||||
|
optimally depending on the precision and `n`.
|
||||||
|
|
||||||
|
The polynomials `\Delta_m(x,k) \in \mathbb{Z}[k][x]` are generated dynamically.
|
||||||
|
Expanding the rising factorials, applying the binomial theorem
|
||||||
|
a couple of times, and doing several rearrangements of the sums, we
|
||||||
|
find the closed form
|
||||||
|
|
||||||
|
.. math ::
|
||||||
|
|
||||||
|
\Delta_m(x,k) = \sum_{v=0}^{m-1} x^v \sum_{i=0}^{m-v-1} k^i C_m(v,i),
|
||||||
|
|
||||||
|
where
|
||||||
|
|
||||||
|
.. math ::
|
||||||
|
|
||||||
|
C_m(v,i) = \sum_{j=i+1}^{m-v} m^{j-i} \left[{m \atop v+j}\right] {{v+j} \choose v} {j \choose i}
|
||||||
|
|
||||||
|
in which the square bracket denotes an unsigned Stirling number
|
||||||
|
of the first kind.
|
||||||
|
|
||||||
|
|
||||||
.. function :: void gamma_rising_fmprb_ui_multipoint(fmprb_t f, const fmprb_t c, ulong n, long prec)
|
.. function :: void gamma_rising_fmprb_ui_multipoint(fmprb_t f, const fmprb_t c, ulong n, long prec)
|
||||||
|
|
||||||
Sets `y` to the rising factorial `x (x+1) (x+2) \cdots (x+n-1)`,
|
Sets `y` to the rising factorial `x (x+1) (x+2) \cdots (x+n-1)`,
|
||||||
|
|
3
gamma.h
3
gamma.h
|
@ -81,6 +81,9 @@ void gamma_rising_fmprb_ui_bsplit_eight(fmprb_t y, const fmprb_t x, ulong n, lon
|
||||||
void gamma_rising_fmprb_ui_bsplit_rectangular(fmprb_t y, const fmprb_t x, ulong n, ulong step, long prec);
|
void gamma_rising_fmprb_ui_bsplit_rectangular(fmprb_t y, const fmprb_t x, ulong n, ulong step, long prec);
|
||||||
void gamma_rising_fmprb_ui_bsplit(fmprb_t y, const fmprb_t x, ulong n, long prec);
|
void gamma_rising_fmprb_ui_bsplit(fmprb_t y, const fmprb_t x, ulong n, long prec);
|
||||||
|
|
||||||
|
void gamma_rising_fmprb_ui_delta(fmprb_t y, const fmprb_t x, ulong n, ulong m, long prec);
|
||||||
|
void gamma_rising_fmpcb_ui_delta(fmpcb_t y, const fmpcb_t x, ulong n, ulong m, long prec);
|
||||||
|
|
||||||
void gamma_rising_fmpcb_ui_bsplit_simple(fmpcb_t y, const fmpcb_t x, ulong n, long prec);
|
void gamma_rising_fmpcb_ui_bsplit_simple(fmpcb_t y, const fmpcb_t x, ulong n, long prec);
|
||||||
void gamma_rising_fmpcb_ui_bsplit_eight(fmpcb_t y, const fmpcb_t x, ulong n, long prec);
|
void gamma_rising_fmpcb_ui_bsplit_eight(fmpcb_t y, const fmpcb_t x, ulong n, long prec);
|
||||||
void gamma_rising_fmpcb_ui_bsplit_rectangular(fmpcb_t y, const fmpcb_t x, ulong n, ulong step, long prec);
|
void gamma_rising_fmpcb_ui_bsplit_rectangular(fmpcb_t y, const fmpcb_t x, ulong n, ulong step, long prec);
|
||||||
|
|
|
@ -28,11 +28,9 @@
|
||||||
void
|
void
|
||||||
gamma_rising_fmpcb_ui_bsplit(fmpcb_t y, const fmpcb_t x, ulong n, long prec)
|
gamma_rising_fmpcb_ui_bsplit(fmpcb_t y, const fmpcb_t x, ulong n, long prec)
|
||||||
{
|
{
|
||||||
if (n < 8 || fmpcb_bits(x) < prec / 8)
|
if (prec < 256 || n < 8 || fmpcb_bits(x) < prec / 8)
|
||||||
gamma_rising_fmpcb_ui_bsplit_simple(y, x, n, prec);
|
gamma_rising_fmpcb_ui_bsplit_simple(y, x, n, prec);
|
||||||
else if (prec < 250 || n < 250000 / prec)
|
|
||||||
gamma_rising_fmpcb_ui_bsplit_eight(y, x, n, prec);
|
|
||||||
else
|
else
|
||||||
gamma_rising_fmpcb_ui_bsplit_rectangular(y, x, n, 0, prec);
|
gamma_rising_fmpcb_ui_delta(y, x, n, 0, prec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
139
gamma/rising_fmpcb_ui_delta.c
Normal file
139
gamma/rising_fmpcb_ui_delta.c
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
/*=============================================================================
|
||||||
|
|
||||||
|
This file is part of ARB.
|
||||||
|
|
||||||
|
ARB is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ARB is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with ARB; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
=============================================================================*/
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
Copyright (C) 2013 Fredrik Johansson
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "gamma.h"
|
||||||
|
#include "arith.h"
|
||||||
|
|
||||||
|
void rising_difference_polynomial(fmpz * s, fmpz * c, ulong m);
|
||||||
|
|
||||||
|
void
|
||||||
|
gamma_rising_fmpcb_ui_delta(fmpcb_t y, const fmpcb_t x, ulong n, ulong m, long prec)
|
||||||
|
{
|
||||||
|
fmpcb_struct * xs;
|
||||||
|
fmpcb_t t, u, v;
|
||||||
|
ulong i, k, rem;
|
||||||
|
fmpz_t c, h;
|
||||||
|
fmpz *s, *d;
|
||||||
|
long wp;
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
fmpcb_one(y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == 1)
|
||||||
|
{
|
||||||
|
fmpcb_set_round(y, x, prec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wp = FMPR_PREC_ADD(prec, FLINT_BIT_COUNT(n));
|
||||||
|
|
||||||
|
fmpcb_init(t);
|
||||||
|
fmpcb_init(u);
|
||||||
|
fmpcb_init(v);
|
||||||
|
fmpz_init(c);
|
||||||
|
fmpz_init(h);
|
||||||
|
|
||||||
|
if (m == 0)
|
||||||
|
{
|
||||||
|
ulong m1, m2;
|
||||||
|
m1 = 0.04 * pow(2.0 * wp, 0.65);
|
||||||
|
m2 = n_sqrt(n);
|
||||||
|
m = FLINT_MIN(m1, m2);
|
||||||
|
}
|
||||||
|
|
||||||
|
m = FLINT_MIN(m, n);
|
||||||
|
m = FLINT_MAX(m, 1);
|
||||||
|
|
||||||
|
xs = _fmpcb_vec_init(m + 1);
|
||||||
|
d = _fmpz_vec_init(m * m);
|
||||||
|
s = _fmpz_vec_init(m + 1);
|
||||||
|
|
||||||
|
for (i = 0; i <= m; i++)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
fmpcb_one(xs + i);
|
||||||
|
else if (i == 1)
|
||||||
|
fmpcb_set(xs + i, x);
|
||||||
|
else if (i % 2 == 0)
|
||||||
|
fmpcb_mul(xs + i, xs + i / 2, xs + i / 2, wp);
|
||||||
|
else
|
||||||
|
fmpcb_mul(xs + i, xs + i - 1, x, wp);
|
||||||
|
}
|
||||||
|
|
||||||
|
rising_difference_polynomial(s, d, m);
|
||||||
|
|
||||||
|
/* tail */
|
||||||
|
rem = m;
|
||||||
|
while (rem + m <= n)
|
||||||
|
rem += m;
|
||||||
|
fmpcb_one(y);
|
||||||
|
for (k = rem; k < n; k++)
|
||||||
|
{
|
||||||
|
fmpcb_add_ui(t, xs + 1, k, wp);
|
||||||
|
fmpcb_mul(y, y, t, wp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initial rising factorial */
|
||||||
|
fmpcb_zero(t);
|
||||||
|
for (i = 1; i <= m; i++)
|
||||||
|
fmpcb_addmul_fmpz(t, xs + i, s + i, wp);
|
||||||
|
|
||||||
|
fmpcb_mul(y, y, t, wp);
|
||||||
|
|
||||||
|
/* the leading coefficient is always the same */
|
||||||
|
fmpcb_mul_fmpz(xs + m - 1, xs + m - 1, d + m - 1 + 0, wp);
|
||||||
|
|
||||||
|
for (k = 0; k + 2 * m <= n; k += m)
|
||||||
|
{
|
||||||
|
for (i = 0; i < m - 1; i++)
|
||||||
|
{
|
||||||
|
fmpz_set_ui(h, k);
|
||||||
|
_fmpz_poly_evaluate_horner_fmpz(c, d + i * m, m - i, h);
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
fmpcb_add_fmpz(t, t, c, wp);
|
||||||
|
else
|
||||||
|
fmpcb_addmul_fmpz(t, xs + i, c, wp);
|
||||||
|
}
|
||||||
|
|
||||||
|
fmpcb_add(t, t, xs + m - 1, wp);
|
||||||
|
fmpcb_mul(y, y, t, wp);
|
||||||
|
}
|
||||||
|
|
||||||
|
fmpcb_set_round(y, y, prec);
|
||||||
|
|
||||||
|
fmpcb_clear(t);
|
||||||
|
fmpcb_clear(u);
|
||||||
|
fmpcb_clear(v);
|
||||||
|
_fmpcb_vec_clear(xs, m + 1);
|
||||||
|
_fmpz_vec_clear(d, m * m);
|
||||||
|
_fmpz_vec_clear(s, m + 1);
|
||||||
|
fmpz_clear(c);
|
||||||
|
fmpz_clear(h);
|
||||||
|
}
|
||||||
|
|
|
@ -28,11 +28,9 @@
|
||||||
void
|
void
|
||||||
gamma_rising_fmprb_ui_bsplit(fmprb_t y, const fmprb_t x, ulong n, long prec)
|
gamma_rising_fmprb_ui_bsplit(fmprb_t y, const fmprb_t x, ulong n, long prec)
|
||||||
{
|
{
|
||||||
if (prec < 768 || n < 8 || fmprb_bits(x) < prec / 8)
|
if (prec < 512 || n < 8 || fmprb_bits(x) < prec / 8)
|
||||||
gamma_rising_fmprb_ui_bsplit_simple(y, x, n, prec);
|
gamma_rising_fmprb_ui_bsplit_simple(y, x, n, prec);
|
||||||
else if (prec < 1500 || n < 500000 / prec)
|
|
||||||
gamma_rising_fmprb_ui_bsplit_eight(y, x, n, prec);
|
|
||||||
else
|
else
|
||||||
gamma_rising_fmprb_ui_bsplit_rectangular(y, x, n, 0, prec);
|
gamma_rising_fmprb_ui_delta(y, x, n, 0, prec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
174
gamma/rising_fmprb_ui_delta.c
Normal file
174
gamma/rising_fmprb_ui_delta.c
Normal file
|
@ -0,0 +1,174 @@
|
||||||
|
/*=============================================================================
|
||||||
|
|
||||||
|
This file is part of ARB.
|
||||||
|
|
||||||
|
ARB is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
ARB is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with ARB; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
=============================================================================*/
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
Copyright (C) 2013 Fredrik Johansson
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "gamma.h"
|
||||||
|
#include "arith.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
rising_difference_polynomial(fmpz * s, fmpz * c, ulong m)
|
||||||
|
{
|
||||||
|
long i, j, k;
|
||||||
|
fmpz_t t;
|
||||||
|
|
||||||
|
fmpz_init(t);
|
||||||
|
|
||||||
|
arith_stirling_number_1u_vec(s, m, m + 1);
|
||||||
|
|
||||||
|
for (k = 0; k < m; k++)
|
||||||
|
{
|
||||||
|
for (i = 0; i <= m - k - 1; i++)
|
||||||
|
{
|
||||||
|
fmpz_zero(c + m * k + i);
|
||||||
|
|
||||||
|
for (j = i + 1; j + k <= m; j++)
|
||||||
|
{
|
||||||
|
if (j == i + 1)
|
||||||
|
{
|
||||||
|
fmpz_bin_uiui(t, 1+i+k, k);
|
||||||
|
fmpz_mul_ui(t, t, m * (i+1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fmpz_mul_ui(t, t, m * (k + j));
|
||||||
|
fmpz_divexact_ui(t, t, j - i);
|
||||||
|
}
|
||||||
|
|
||||||
|
fmpz_addmul(c + m * k + i, s + j + k, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fmpz_clear(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gamma_rising_fmprb_ui_delta(fmprb_t y, const fmprb_t x, ulong n, ulong m, long prec)
|
||||||
|
{
|
||||||
|
fmprb_struct * xs;
|
||||||
|
fmprb_t t, u, v;
|
||||||
|
ulong i, k, rem;
|
||||||
|
fmpz_t c, h;
|
||||||
|
fmpz *s, *d;
|
||||||
|
long wp;
|
||||||
|
|
||||||
|
if (n == 0)
|
||||||
|
{
|
||||||
|
fmprb_one(y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n == 1)
|
||||||
|
{
|
||||||
|
fmprb_set_round(y, x, prec);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wp = FMPR_PREC_ADD(prec, FLINT_BIT_COUNT(n));
|
||||||
|
|
||||||
|
fmprb_init(t);
|
||||||
|
fmprb_init(u);
|
||||||
|
fmprb_init(v);
|
||||||
|
fmpz_init(c);
|
||||||
|
fmpz_init(h);
|
||||||
|
|
||||||
|
if (m == 0)
|
||||||
|
{
|
||||||
|
ulong m1, m2;
|
||||||
|
m1 = 0.04 * pow(wp, 0.65);
|
||||||
|
m2 = n_sqrt(n);
|
||||||
|
m = FLINT_MIN(m1, m2);
|
||||||
|
}
|
||||||
|
|
||||||
|
m = FLINT_MIN(m, n);
|
||||||
|
m = FLINT_MAX(m, 1);
|
||||||
|
|
||||||
|
xs = _fmprb_vec_init(m + 1);
|
||||||
|
d = _fmpz_vec_init(m * m);
|
||||||
|
s = _fmpz_vec_init(m + 1);
|
||||||
|
|
||||||
|
for (i = 0; i <= m; i++)
|
||||||
|
{
|
||||||
|
if (i == 0)
|
||||||
|
fmprb_one(xs + i);
|
||||||
|
else if (i == 1)
|
||||||
|
fmprb_set(xs + i, x);
|
||||||
|
else if (i % 2 == 0)
|
||||||
|
fmprb_mul(xs + i, xs + i / 2, xs + i / 2, wp);
|
||||||
|
else
|
||||||
|
fmprb_mul(xs + i, xs + i - 1, x, wp);
|
||||||
|
}
|
||||||
|
|
||||||
|
rising_difference_polynomial(s, d, m);
|
||||||
|
|
||||||
|
/* tail */
|
||||||
|
rem = m;
|
||||||
|
while (rem + m <= n)
|
||||||
|
rem += m;
|
||||||
|
fmprb_one(y);
|
||||||
|
for (k = rem; k < n; k++)
|
||||||
|
{
|
||||||
|
fmprb_add_ui(t, xs + 1, k, wp);
|
||||||
|
fmprb_mul(y, y, t, wp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initial rising factorial */
|
||||||
|
fmprb_zero(t);
|
||||||
|
for (i = 1; i <= m; i++)
|
||||||
|
fmprb_addmul_fmpz(t, xs + i, s + i, wp);
|
||||||
|
|
||||||
|
fmprb_mul(y, y, t, wp);
|
||||||
|
|
||||||
|
/* the leading coefficient is always the same */
|
||||||
|
fmprb_mul_fmpz(xs + m - 1, xs + m - 1, d + m - 1 + 0, wp);
|
||||||
|
|
||||||
|
for (k = 0; k + 2 * m <= n; k += m)
|
||||||
|
{
|
||||||
|
for (i = 0; i < m - 1; i++)
|
||||||
|
{
|
||||||
|
fmpz_set_ui(h, k);
|
||||||
|
_fmpz_poly_evaluate_horner_fmpz(c, d + i * m, m - i, h);
|
||||||
|
|
||||||
|
if (i == 0)
|
||||||
|
fmprb_add_fmpz(t, t, c, wp);
|
||||||
|
else
|
||||||
|
fmprb_addmul_fmpz(t, xs + i, c, wp);
|
||||||
|
}
|
||||||
|
|
||||||
|
fmprb_add(t, t, xs + m - 1, wp);
|
||||||
|
fmprb_mul(y, y, t, wp);
|
||||||
|
}
|
||||||
|
|
||||||
|
fmprb_set_round(y, y, prec);
|
||||||
|
|
||||||
|
fmprb_clear(t);
|
||||||
|
fmprb_clear(u);
|
||||||
|
fmprb_clear(v);
|
||||||
|
_fmprb_vec_clear(xs, m + 1);
|
||||||
|
_fmpz_vec_clear(d, m * m);
|
||||||
|
_fmpz_vec_clear(s, m + 1);
|
||||||
|
fmpz_clear(c);
|
||||||
|
fmpz_clear(h);
|
||||||
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
#include "bernoulli.h"
|
#include "bernoulli.h"
|
||||||
|
|
||||||
/* tuning factor */
|
/* tuning factor */
|
||||||
#define GAMMA_STIRLING_BETA 0.23
|
#define GAMMA_STIRLING_BETA 0.27
|
||||||
|
|
||||||
static __inline__ long
|
static __inline__ long
|
||||||
_fmpr_mag(const fmpr_t x)
|
_fmpr_mag(const fmpr_t x)
|
||||||
|
|
120
gamma/test/t-rising_fmpcb_ui_delta.c
Normal file
120
gamma/test/t-rising_fmpcb_ui_delta.c
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
/*=============================================================================
|
||||||
|
|
||||||
|
This file is part of fmpcb.
|
||||||
|
|
||||||
|
fmpcb is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
fmpcb is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with fmpcb; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
=============================================================================*/
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
Copyright (C) 2012 Fredrik Johansson
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "gamma.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
long iter;
|
||||||
|
flint_rand_t state;
|
||||||
|
|
||||||
|
printf("rising_fmpcb_ui_delta....");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
flint_randinit(state);
|
||||||
|
|
||||||
|
/* check functional equation */
|
||||||
|
for (iter = 0; iter < 1000; iter++)
|
||||||
|
{
|
||||||
|
fmpcb_t x, xn, y, z;
|
||||||
|
ulong n, m, step1, step2, step3;
|
||||||
|
|
||||||
|
fmpcb_init(x);
|
||||||
|
fmpcb_init(xn);
|
||||||
|
fmpcb_init(y);
|
||||||
|
fmpcb_init(z);
|
||||||
|
|
||||||
|
fmpcb_randtest(x, state, 1 + n_randint(state, 4000), 10);
|
||||||
|
n = n_randint(state, 80);
|
||||||
|
m = n_randint(state, 40);
|
||||||
|
fmpcb_add_ui(xn, x, n, 1 + n_randint(state, 4000));
|
||||||
|
|
||||||
|
step1 = n_randint(state, 20);
|
||||||
|
step2 = n_randint(state, 20);
|
||||||
|
step3 = n_randint(state, 20);
|
||||||
|
|
||||||
|
gamma_rising_fmpcb_ui_delta(y, x, n, step1, 2 + n_randint(state, 4000));
|
||||||
|
gamma_rising_fmpcb_ui_delta(z, xn, m, step2, 2 + n_randint(state, 4000));
|
||||||
|
fmpcb_mul(y, y, z, 2 + n_randint(state, 4000));
|
||||||
|
|
||||||
|
gamma_rising_fmpcb_ui_delta(z, x, n + m, step3, 2 + n_randint(state, 4000));
|
||||||
|
|
||||||
|
if (!fmpcb_overlaps(y, z))
|
||||||
|
{
|
||||||
|
printf("FAIL: overlap\n\n");
|
||||||
|
printf("n = %lu\n", n);
|
||||||
|
printf("m = %lu\n", m);
|
||||||
|
printf("x = "); fmpcb_print(x); printf("\n\n");
|
||||||
|
printf("xn = "); fmpcb_print(xn); printf("\n\n");
|
||||||
|
printf("y = "); fmpcb_print(y); printf("\n\n");
|
||||||
|
printf("z = "); fmpcb_print(z); printf("\n\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
fmpcb_clear(x);
|
||||||
|
fmpcb_clear(xn);
|
||||||
|
fmpcb_clear(y);
|
||||||
|
fmpcb_clear(z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* aliasing of y and x */
|
||||||
|
for (iter = 0; iter < 1000; iter++)
|
||||||
|
{
|
||||||
|
fmpcb_t x, y;
|
||||||
|
ulong n;
|
||||||
|
long prec;
|
||||||
|
ulong step;
|
||||||
|
|
||||||
|
fmpcb_init(x);
|
||||||
|
fmpcb_init(y);
|
||||||
|
|
||||||
|
fmpcb_randtest(x, state, 1 + n_randint(state, 200), 10);
|
||||||
|
fmpcb_randtest(y, state, 1 + n_randint(state, 200), 10);
|
||||||
|
n = n_randint(state, 100);
|
||||||
|
|
||||||
|
step = n_randint(state, 20);
|
||||||
|
|
||||||
|
prec = 2 + n_randint(state, 4000);
|
||||||
|
gamma_rising_fmpcb_ui_delta(y, x, n, step, prec);
|
||||||
|
gamma_rising_fmpcb_ui_delta(x, x, n, step, prec);
|
||||||
|
|
||||||
|
if (!fmpcb_equal(x, y))
|
||||||
|
{
|
||||||
|
printf("FAIL: aliasing\n\n");
|
||||||
|
printf("x = "); fmpcb_print(x); printf("\n\n");
|
||||||
|
printf("y = "); fmpcb_print(y); printf("\n\n");
|
||||||
|
printf("n = %lu\n", n);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
fmpcb_clear(x);
|
||||||
|
fmpcb_clear(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
flint_randclear(state);
|
||||||
|
_fmpz_cleanup();
|
||||||
|
printf("PASS\n");
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
126
gamma/test/t-rising_fmprb_ui_delta.c
Normal file
126
gamma/test/t-rising_fmprb_ui_delta.c
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
/*=============================================================================
|
||||||
|
|
||||||
|
This file is part of fmprb.
|
||||||
|
|
||||||
|
fmprb is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
fmprb is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with fmprb; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
=============================================================================*/
|
||||||
|
/******************************************************************************
|
||||||
|
|
||||||
|
Copyright (C) 2012 Fredrik Johansson
|
||||||
|
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
#include "gamma.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
long iter;
|
||||||
|
flint_rand_t state;
|
||||||
|
|
||||||
|
printf("rising_fmprb_ui_delta....");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
flint_randinit(state);
|
||||||
|
|
||||||
|
/* compare with fmpq */
|
||||||
|
for (iter = 0; iter < 1000; iter++)
|
||||||
|
{
|
||||||
|
fmprb_t a, b;
|
||||||
|
fmpq_t x, y, z;
|
||||||
|
ulong n, step;
|
||||||
|
long i;
|
||||||
|
|
||||||
|
fmprb_init(a);
|
||||||
|
fmprb_init(b);
|
||||||
|
|
||||||
|
fmpq_init(x);
|
||||||
|
fmpq_init(y);
|
||||||
|
fmpq_init(z);
|
||||||
|
|
||||||
|
fmprb_randtest(a, state, 1 + n_randint(state, 1000), 10);
|
||||||
|
fmprb_randtest(b, state, 1 + n_randint(state, 1000), 10);
|
||||||
|
n = n_randint(state, 80);
|
||||||
|
|
||||||
|
fmprb_get_rand_fmpq(x, state, a, 1 + n_randint(state, 1000));
|
||||||
|
|
||||||
|
step = n_randint(state, 20);
|
||||||
|
gamma_rising_fmprb_ui_delta(b, a, n, step, 2 + n_randint(state, 1000));
|
||||||
|
|
||||||
|
fmpq_one(y);
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
fmpq_set_si(z, i, 1);
|
||||||
|
fmpq_add(z, x, z);
|
||||||
|
fmpq_mul(y, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fmprb_contains_fmpq(b, y))
|
||||||
|
{
|
||||||
|
printf("FAIL: containment\n\n");
|
||||||
|
printf("n = %lu\n", n);
|
||||||
|
printf("a = "); fmprb_print(a); printf("\n\n");
|
||||||
|
printf("x = "); fmpq_print(x); printf("\n\n");
|
||||||
|
printf("b = "); fmprb_print(b); printf("\n\n");
|
||||||
|
printf("y = "); fmpq_print(y); printf("\n\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
fmprb_clear(a);
|
||||||
|
fmprb_clear(b);
|
||||||
|
|
||||||
|
fmpq_clear(x);
|
||||||
|
fmpq_clear(y);
|
||||||
|
fmpq_clear(z);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* aliasing of y and x */
|
||||||
|
for (iter = 0; iter < 1000; iter++)
|
||||||
|
{
|
||||||
|
fmprb_t x, y;
|
||||||
|
ulong n, step;
|
||||||
|
long prec;
|
||||||
|
|
||||||
|
fmprb_init(x);
|
||||||
|
fmprb_init(y);
|
||||||
|
|
||||||
|
fmprb_randtest(x, state, 1 + n_randint(state, 200), 10);
|
||||||
|
fmprb_randtest(y, state, 1 + n_randint(state, 200), 10);
|
||||||
|
n = n_randint(state, 100);
|
||||||
|
|
||||||
|
prec = 2 + n_randint(state, 1000);
|
||||||
|
|
||||||
|
step = n_randint(state, 20);
|
||||||
|
gamma_rising_fmprb_ui_delta(y, x, n, step, prec);
|
||||||
|
gamma_rising_fmprb_ui_delta(x, x, n, step, prec);
|
||||||
|
|
||||||
|
if (!fmprb_equal(x, y))
|
||||||
|
{
|
||||||
|
printf("FAIL: aliasing\n\n");
|
||||||
|
printf("x = "); fmprb_print(x); printf("\n\n");
|
||||||
|
printf("y = "); fmprb_print(y); printf("\n\n");
|
||||||
|
printf("n = %lu\n", n);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
fmprb_clear(x);
|
||||||
|
fmprb_clear(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
flint_randclear(state);
|
||||||
|
_fmpz_cleanup();
|
||||||
|
printf("PASS\n");
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue