示例#1
0
void
_arb_poly_log1p_series(arb_ptr res, arb_srcptr f, slong flen, slong n, slong prec)
{
    arb_t a;

    flen = FLINT_MIN(flen, n);

    arb_init(a);
    arb_log1p(a, f, prec);

    if (flen == 1)
    {
        _arb_vec_zero(res + 1, n - 1);
    }
    else if (n == 2)
    {
        arb_add_ui(res, f + 0, 1, prec);
        arb_div(res + 1, f + 1, res + 0, prec);
    }
    else if (_arb_vec_is_zero(f + 1, flen - 2))  /* f = a + bx^d */
    {
        slong i, j, d = flen - 1;

        arb_add_ui(res, f + 0, 1, prec);

        for (i = 1, j = d; j < n; j += d, i++)
        {
            if (i == 1)
                arb_div(res + j, f + d, res, prec);
            else
                arb_mul(res + j, res + j - d, res + d, prec);
            _arb_vec_zero(res + j - d + 1, flen - 2);
        }
        _arb_vec_zero(res + j - d + 1, n - (j - d + 1));

        for (i = 2, j = 2 * d; j < n; j += d, i++)
            arb_div_si(res + j, res + j, i % 2 ? i : -i, prec);
    }
    else
    {
        arb_ptr f_diff, f_inv;
        slong alloc;

        alloc = n + flen;
        f_inv = _arb_vec_init(alloc);
        f_diff = f_inv + n;

        arb_add_ui(f_diff, f, 1, prec);
        _arb_vec_set(f_diff + 1, f + 1, flen - 1);
        _arb_poly_inv_series(f_inv, f_diff, flen, n, prec);
        _arb_poly_derivative(f_diff, f, flen, prec);
        _arb_poly_mullow(res, f_inv, n - 1, f_diff, flen - 1, n - 1, prec);
        _arb_poly_integral(res, res, n, prec);

        _arb_vec_clear(f_inv, alloc);
    }

    arb_swap(res, a);
    arb_clear(a);
}
示例#2
0
void
_arb_poly_sinh_cosh_series(arb_ptr s, arb_ptr c, const arb_srcptr h, slong hlen, slong n, slong prec)
{
    hlen = FLINT_MIN(hlen, n);

    if (hlen == 1)
    {
        arb_sinh_cosh(s, c, h, prec);
        _arb_vec_zero(s + 1, n - 1);
        _arb_vec_zero(c + 1, n - 1);
    }
    else if (n == 2)
    {
        arb_t t;
        arb_init(t);
        arb_set(t, h + 1);
        arb_sinh_cosh(s, c, h, prec);
        arb_mul(s + 1, c, t, prec);
        arb_mul(c + 1, s, t, prec);
        arb_clear(t);
    }
    else if (hlen < 60 || n < 120)
        _arb_poly_sinh_cosh_series_basecase(s, c, h, hlen, n, prec);
    else
        _arb_poly_sinh_cosh_series_exponential(s, c, h, hlen, n, prec);
}
示例#3
0
void
_arb_poly_sin_cos_pi_series(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec)
{
    hlen = FLINT_MIN(hlen, n);

    if (hlen == 1)
    {
        arb_sin_cos_pi(s, c, h, prec);
        _arb_vec_zero(s + 1, n - 1);
        _arb_vec_zero(c + 1, n - 1);
    }
    else if (n == 2)
    {
        arb_t t;
        arb_init(t);
        arb_const_pi(t, prec);
        arb_mul(t, t, h + 1, prec);
        arb_sin_cos_pi(s, c, h, prec);
        arb_mul(s + 1, c, t, prec);
        arb_neg(t, t);
        arb_mul(c + 1, s, t, prec);
        arb_clear(t);
    }
    else if (hlen < TANGENT_CUTOFF)
        _arb_poly_sin_cos_series_basecase(s, c, h, hlen, n, prec, 1);
    else
        _arb_poly_sin_cos_series_tangent(s, c, h, hlen, n, prec, 1);
}
void
_arb_poly_sinh_cosh_series_exponential(arb_ptr s, arb_ptr c,
    const arb_srcptr h, slong hlen, slong len, slong prec)
{
    arb_ptr t, u, v;
    arb_t s0, c0;
    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        arb_sinh_cosh(s, c, h, prec);
        _arb_vec_zero(s + 1, len - 1);
        _arb_vec_zero(c + 1, len - 1);
        return;
    }

    arb_init(s0);
    arb_init(c0);

    t = _arb_vec_init(3 * len);
    u = t + len;
    v = u + len;

    arb_sinh_cosh(s0, c0, h, prec);

    _arb_vec_set(t + 1, h + 1, hlen - 1);
    _arb_poly_exp_series(t, t, len, len, prec);

    /* todo: part of the inverse could be avoided since exp computes
       it internally to half the length */
    _arb_poly_inv_series(u, t, len, len, prec);

    /* hyperbolic sine */
    _arb_vec_sub(s, t, u, len, prec);
    _arb_vec_scalar_mul_2exp_si(s, s, len, -1);

    /* hyperbolic cosine */
    _arb_vec_add(c, t, u, len, prec);
    _arb_vec_scalar_mul_2exp_si(c, c, len, -1);

    /* sinh(h0 + h1) = cosh(h0) sinh(h1) + sinh(h0) cosh(h1)
       cosh(h0 + h1) = cosh(h0) cosh(h1) + sinh(h0) sinh(h1) */
    if (!arb_is_zero(s0))
    {
        _arb_vec_scalar_mul(t, s, len, c0, prec);
        _arb_vec_scalar_mul(u, c, len, s0, prec);
        _arb_vec_scalar_mul(v, s, len, s0, prec);
        _arb_vec_add(s, t, u, len, prec);
        _arb_vec_scalar_mul(t, c, len, c0, prec);
        _arb_vec_add(c, t, v, len, prec);
    }

    _arb_vec_clear(t, 3 * len);

    arb_clear(s0);
    arb_clear(c0);
}
示例#5
0
void
_arb_poly_sqrt_series(arb_ptr g,
    arb_srcptr h, long hlen, long len, long prec)
{
    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        arb_sqrt(g, h, prec);
        _arb_vec_zero(g + 1, len - 1);
    }
    else if (len == 2)
    {
        arb_sqrt(g, h, prec);
        arb_div(g + 1, h + 1, h, prec);
        arb_mul(g + 1, g + 1, g, prec);
        arb_mul_2exp_si(g + 1, g + 1, -1);
    }
    else
    {
        arb_ptr t;
        t = _arb_vec_init(len);
        _arb_poly_rsqrt_series(t, h, hlen, len, prec);
        _arb_poly_mullow(g, t, len, h, hlen, len, prec);
        _arb_vec_clear(t, len);
    }
}
示例#6
0
void
_arb_poly_sinh_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec)
{
    hlen = FLINT_MIN(hlen, n);

    if (hlen == 1)
    {
        arb_sinh(g, h, prec);
        _arb_vec_zero(g + 1, n - 1);
    }
    else if (n == 2)
    {
        arb_t t;
        arb_init(t);
        arb_sinh_cosh(g, t, h, prec);
        arb_mul(g + 1, h + 1, t, prec);  /* safe since hlen >= 2 */
        arb_clear(t);
    }
    else
    {
        arb_ptr t = _arb_vec_init(n);
        _arb_poly_sinh_cosh_series(g, t, h, hlen, n, prec);
        _arb_vec_clear(t, n);
    }
}
示例#7
0
void
_arb_poly_sinh_cosh_series_basecase(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen,
        slong n, slong prec)
{
    slong j, k, alen = FLINT_MIN(n, hlen);
    arb_ptr a;
    arb_t t, u;

    arb_sinh_cosh(s, c, h, prec);

    if (hlen == 1)
    {
        _arb_vec_zero(s + 1, n - 1);
        _arb_vec_zero(c + 1, n - 1);
        return;
    }

    arb_init(t);
    arb_init(u);
    a = _arb_vec_init(alen);

    for (k = 1; k < alen; k++)
        arb_mul_ui(a + k, h + k, k, prec);

    for (k = 1; k < n; k++)
    {
        arb_zero(t);
        arb_zero(u);

        for (j = 1; j < FLINT_MIN(k + 1, hlen); j++)
        {
            arb_addmul(t, a + j, s + k - j, prec);
            arb_addmul(u, a + j, c + k - j, prec);
        }

        arb_div_ui(c + k, t, k, prec);
        arb_div_ui(s + k, u, k, prec);
    }

    arb_clear(t);
    arb_clear(u);
    _arb_vec_clear(a, alen);
}
示例#8
0
void
_arb_poly_sin_cos_series(arb_ptr s, arb_ptr c, arb_srcptr h, slong hlen, slong n, slong prec)
{
    hlen = FLINT_MIN(hlen, n);

    if (hlen == 1)
    {
        arb_sin_cos(s, c, h, prec);
        _arb_vec_zero(s + 1, n - 1);
        _arb_vec_zero(c + 1, n - 1);
    }
    else if (n == 2)
    {
        arb_t t;
        arb_init(t);
        arb_set(t, h + 1);
        arb_sin_cos(s, c, h, prec);
        arb_mul(s + 1, c, t, prec);
        arb_neg(t, t);
        arb_mul(c + 1, s, t, prec);
        arb_clear(t);
    }
    else
    {
        slong cutoff;

        if (prec <= 128)
        {
            cutoff = 1400;
        }
        else
        {
            cutoff = 100000 / pow(log(prec), 3);
            cutoff = FLINT_MIN(cutoff, 700);
        }

        if (hlen < cutoff)
            _arb_poly_sin_cos_series_basecase(s, c, h, hlen, n, prec, 0);
        else
            _arb_poly_sin_cos_series_tangent(s, c, h, hlen, n, prec, 0);
    }
}
示例#9
0
void
arb_poly_set_coeff_arb(arb_poly_t poly, long n, const arb_t x)
{
    arb_poly_fit_length(poly, n + 1);

    if (n + 1 > poly->length)
    {
        _arb_vec_zero(poly->coeffs + poly->length, n - poly->length);
        poly->length = n + 1;
    }

    arb_set(poly->coeffs + n, x);
    _arb_poly_normalise(poly);
}
示例#10
0
文件: tan_series.c 项目: isuruf/arb
void
_arb_poly_tan_series(arb_ptr g,
    arb_srcptr h, slong hlen, slong len, slong prec)
{
    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        arb_tan(g, h, prec);
        _arb_vec_zero(g + 1, len - 1);
    }
    else if (len == 2)
    {
        arb_t t;
        arb_init(t);
        arb_tan(g, h, prec);
        arb_mul(t, g, g, prec);
        arb_add_ui(t, t, 1, prec);
        arb_mul(g + 1, t, h + 1, prec);  /* safe since hlen >= 2 */
        arb_clear(t);
    }
    else
    {
        arb_ptr t, u;

        t = _arb_vec_init(2 * len);
        u = t + len;

        NEWTON_INIT(TAN_NEWTON_CUTOFF, len)

        NEWTON_BASECASE(n)
        _arb_poly_sin_cos_series_basecase(t, u, h, hlen, n, prec, 0);
        _arb_poly_div_series(g, t, n, u, n, n, prec);
        NEWTON_END_BASECASE

        NEWTON_LOOP(m, n)
        _arb_poly_mullow(u, g, m, g, m, n, prec);
        arb_add_ui(u, u, 1, prec);
        _arb_poly_atan_series(t, g, m, n, prec);
        _arb_poly_sub(t + m, h + m, FLINT_MAX(0, hlen - m), t + m, n - m, prec);
        _arb_poly_mullow(g + m, u, n, t + m, n - m, n - m, prec);
        NEWTON_END_LOOP

        NEWTON_END

        _arb_vec_clear(t, 2 * len);
    }
}
示例#11
0
文件: compose.c 项目: isuruf/arb
/* compose by poly2 = a*x^n + c, no aliasing; n >= 1 */
void
_arb_poly_compose_axnc(arb_ptr res, arb_srcptr poly1, slong len1,
    const arb_t c, const arb_t a, slong n, slong prec)
{
    slong i;

    _arb_vec_set_round(res, poly1, len1, prec);
    /* shift by c (c = 0 case will be fast) */
    _arb_poly_taylor_shift(res, c, len1, prec);

    /* multiply by powers of a */
    if (!arb_is_one(a))
    {
        if (arb_equal_si(a, -1))
        {
            for (i = 1; i < len1; i += 2)
                arb_neg(res + i, res + i);
        }
        else if (len1 == 2)
        {
            arb_mul(res + 1, res + 1, a, prec);
        }
        else
        {
            arb_t t;
            arb_init(t);
            arb_set(t, a);

            for (i = 1; i < len1; i++)
            {
                arb_mul(res + i, res + i, t, prec);
                if (i + 1 < len1)
                    arb_mul(t, t, a, prec);
            }

            arb_clear(t);
        }
    }

    /* stretch */
    for (i = len1 - 1; i >= 1 && n > 1; i--)
    {
        arb_swap(res + i * n, res + i);
        _arb_vec_zero(res + (i - 1) * n + 1, n - 1);
    }
}
示例#12
0
void
_arb_poly_compose_series(arb_ptr res, arb_srcptr poly1, slong len1,
                            arb_srcptr poly2, slong len2, slong n, slong prec)
{
    if (len2 == 1)
    {
        arb_set_round(res, poly1, prec);
        _arb_vec_zero(res + 1, n - 1);
    }
    else if (_arb_vec_is_zero(poly2 + 1, len2 - 2))  /* poly2 is a monomial */
    {
        slong i, j;
        arb_t t;

        arb_init(t);
        arb_set(t, poly2 + len2 - 1);
        arb_set_round(res, poly1, prec);

        for (i = 1, j = len2 - 1; i < len1 && j < n; i++, j += len2 - 1)
        {
            arb_mul(res + j, poly1 + i, t, prec);

            if (i + 1 < len1 && j + len2 - 1 < n)
                arb_mul(t, t, poly2 + len2 - 1, prec);
        }

        if (len2 != 2)
            for (i = 1; i < n; i++)
                if (i % (len2 - 1) != 0)
                    arb_zero(res + i);

        arb_clear(t);
    }
    else if (len1 < 6 || n < 6)
    {
        _arb_poly_compose_series_horner(res, poly1, len1, poly2, len2, n, prec);
    }
    else
    {
        _arb_poly_compose_series_brent_kung(res, poly1, len1, poly2, len2, n, prec);
    }
}
示例#13
0
void
_arb_poly_rising_ui_series(arb_ptr res,
    arb_srcptr f, slong flen, ulong r,
        slong trunc, slong prec)
{
    if (trunc == 1 || flen == 1)
    {
        arb_rising_ui(res, f, r, prec);
        _arb_vec_zero(res + 1, trunc - 1);
    }
    else if (trunc == 2)
    {
        arb_rising2_ui(res, res + 1, f, r, prec);
        arb_mul(res + 1, res + 1, f + 1, prec);
    }
    else
    {
        _arb_poly_rising_ui_series_bsplit(res, f, flen, 0, r, trunc, prec);
    }
}
示例#14
0
void 
_arb_poly_div_series(arb_ptr Q, arb_srcptr A, long Alen,
    arb_srcptr B, long Blen, long n, long prec)
{
    Alen = FLINT_MIN(Alen, n);
    Blen = FLINT_MIN(Blen, n);

    if (Blen == 1)
    {
        _arb_vec_scalar_div(Q, A, Alen, B, prec);
        _arb_vec_zero(Q + Alen, n - Alen);
    }
    else
    {
        arb_ptr Binv;
        Binv = _arb_vec_init(n);
        _arb_poly_inv_series(Binv, B, Blen, n, prec);
        _arb_poly_mullow(Q, Binv, n, A, Alen, n, prec);
        _arb_vec_clear(Binv, n);
    }
}
示例#15
0
文件: asin_series.c 项目: isuruf/arb
void
_arb_poly_asin_series(arb_ptr g, arb_srcptr h, slong hlen, slong n, slong prec)
{
    arb_t c;
    arb_init(c);

    arb_asin(c, h, prec);

    hlen = FLINT_MIN(hlen, n);

    if (hlen == 1)
    {
        _arb_vec_zero(g + 1, n - 1);
    }
    else
    {
        arb_ptr t, u;
        slong ulen;

        t = _arb_vec_init(n);
        u = _arb_vec_init(n);

        /* asin(h(x)) = integral(h'(x)/sqrt(1-h(x)^2)) */
        ulen = FLINT_MIN(n, 2 * hlen - 1);
        _arb_poly_mullow(u, h, hlen, h, hlen, ulen, prec);
        arb_sub_ui(u, u, 1, prec);
        _arb_vec_neg(u, u, ulen);
        _arb_poly_rsqrt_series(t, u, ulen, n, prec);
        _arb_poly_derivative(u, h, hlen, prec);
        _arb_poly_mullow(g, t, n, u, hlen - 1, n, prec);
        _arb_poly_integral(g, g, n, prec);

        _arb_vec_clear(t, n);
        _arb_vec_clear(u, n);
    }

    arb_swap(g, c);
    arb_clear(c);
}
示例#16
0
文件: inv_series.c 项目: isuruf/arb
void
_arb_poly_inv_series(arb_ptr Qinv,
    arb_srcptr Q, slong Qlen, slong len, slong prec)
{
    arb_inv(Qinv, Q, prec);

    if (Qlen == 1)
    {
        _arb_vec_zero(Qinv + 1, len - 1);
    }
    else if (len == 2)
    {
        arb_div(Qinv + 1, Qinv, Q, prec);
        arb_mul(Qinv + 1, Qinv + 1, Q + 1, prec);
        arb_neg(Qinv + 1, Qinv + 1);
    }
    else
    {
        slong Qnlen, Wlen, W2len;
        arb_ptr W;

        W = _arb_vec_init(len);

        NEWTON_INIT(1, len)
        NEWTON_LOOP(m, n)

        Qnlen = FLINT_MIN(Qlen, n);
        Wlen = FLINT_MIN(Qnlen + m - 1, n);
        W2len = Wlen - m;
        MULLOW(W, Q, Qnlen, Qinv, m, Wlen, prec);
        MULLOW(Qinv + m, Qinv, m, W + m, W2len, n - m, prec);
        _arb_vec_neg(Qinv + m, Qinv + m, n - m);

        NEWTON_END_LOOP
        NEWTON_END

        _arb_vec_clear(W, len);
    }
}
示例#17
0
static void
bound_rfac(arb_ptr F, const acb_t s, ulong n, slong len, slong wp)
{
    if (len == 1)
    {
        acb_rising_ui_get_mag(arb_radref(F), s, n);
        arf_set_mag(arb_midref(F), arb_radref(F));
        mag_zero(arb_radref(F + 0));
    }
    else
    {
        arb_struct sx[2];
        arb_init(sx + 0);
        arb_init(sx + 1);
        acb_abs(sx + 0, s, wp);
        arb_one(sx + 1);
        _arb_vec_zero(F, len);
        _arb_poly_rising_ui_series(F, sx, 2, n, len, wp);
        arb_clear(sx + 0);
        arb_clear(sx + 1);
    }
}
示例#18
0
void
_arb_poly_sqrt_series(arb_ptr g,
    arb_srcptr h, slong hlen, slong len, slong prec)
{
    hlen = FLINT_MIN(hlen, len);

    while (hlen > 0 && arb_is_zero(h + hlen - 1))
        hlen--;

    if (hlen <= 1)
    {
        arb_sqrt(g, h, prec);
        _arb_vec_zero(g + 1, len - 1);
    }
    else if (len == 2)
    {
        arb_sqrt(g, h, prec);
        arb_div(g + 1, h + 1, h, prec);
        arb_mul(g + 1, g + 1, g, prec);
        arb_mul_2exp_si(g + 1, g + 1, -1);
    }
    else if (_arb_vec_is_zero(h + 1, hlen - 2))
    {
        arb_t t;
        arb_init(t);
        arf_set_si_2exp_si(arb_midref(t), 1, -1);
        _arb_poly_binomial_pow_arb_series(g, h, hlen, t, len, prec);
        arb_clear(t);
    }
    else
    {
        arb_ptr t;
        t = _arb_vec_init(len);
        _arb_poly_rsqrt_series(t, h, hlen, len, prec);
        _arb_poly_mullow(g, t, len, h, hlen, len, prec);
        _arb_vec_clear(t, len);
    }
}
示例#19
0
void
_arb_poly_cot_pi_series(arb_ptr g, arb_srcptr h, slong hlen, slong len, slong prec)
{
    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        arb_cot_pi(g, h, prec);
        _arb_vec_zero(g + 1, len - 1);
    }
    else
    {
        arb_ptr t, u;

        t = _arb_vec_init(len);
        u = _arb_vec_init(len);

        _arb_poly_sin_cos_pi_series(t, u, h, hlen, len, prec);
        _arb_poly_div_series(g, u, len, t, len, len, prec);

        _arb_vec_clear(t, len);
        _arb_vec_clear(u, len);
    }
}
示例#20
0
/* with inverse=1 simultaneously computes g = exp(-x) to length n
with inverse=0 uses g as scratch space, computing
g = exp(-x) only to length (n+1)/2 */
static void
_arb_poly_exp_series_newton(arb_ptr f, arb_ptr g,
                            arb_srcptr h, slong len, slong prec, int inverse, slong cutoff)
{
    slong alloc;
    arb_ptr T, U, hprime;

    alloc = 3 * len;
    T = _arb_vec_init(alloc);
    U = T + len;
    hprime = U + len;

    _arb_poly_derivative(hprime, h, len, prec);
    arb_zero(hprime + len - 1);

    NEWTON_INIT(cutoff, len)

    /* f := exp(h) + O(x^m), g := exp(-h) + O(x^m2) */
    NEWTON_BASECASE(n)
    _arb_poly_exp_series_basecase(f, h, n, n, prec);
    _arb_poly_inv_series(g, f, (n + 1) / 2, (n + 1) / 2, prec);
    NEWTON_END_BASECASE

    /* extend from length m to length n */
    NEWTON_LOOP(m, n)

    slong m2 = (m + 1) / 2;
    slong l = m - 1; /* shifted for derivative */

    /* g := exp(-h) + O(x^m) */
    _arb_poly_mullow(T, f, m, g, m2, m, prec);
    _arb_poly_mullow(g + m2, g, m2, T + m2, m - m2, m - m2, prec);
    _arb_vec_neg(g + m2, g + m2, m - m2);

    /* U := h' + g (f' - f h') + O(x^(n-1))
        Note: should replace h' by h' mod x^(m-1) */
    _arb_vec_zero(f + m, n - m);
    _arb_poly_mullow(T, f, n, hprime, n, n, prec); /* should be mulmid */
    _arb_poly_derivative(U, f, n, prec);
    arb_zero(U + n - 1); /* should skip low terms */
    _arb_vec_sub(U + l, U + l, T + l, n - l, prec);
    _arb_poly_mullow(T + l, g, n - m, U + l, n - m, n - m, prec);
    _arb_vec_add(U + l, hprime + l, T + l, n - m, prec);

    /* f := f + f * (h - int U) + O(x^n) = exp(h) + O(x^n) */
    _arb_poly_integral(U, U, n, prec); /* should skip low terms */
    _arb_vec_sub(U + m, h + m, U + m, n - m, prec);
    _arb_poly_mullow(f + m, f, n - m, U + m, n - m, n - m, prec);

    /* g := exp(-h) + O(x^n) */
    /* not needed if we only want exp(x) */
    if (n == len && inverse)
    {
        _arb_poly_mullow(T, f, n, g, m, n, prec);
        _arb_poly_mullow(g + m, g, m, T + m, n - m, n - m, prec);
        _arb_vec_neg(g + m, g + m, n - m);
    }

    NEWTON_END_LOOP

    NEWTON_END

    _arb_vec_clear(T, alloc);
}
示例#21
0
/*
 * Note that the expectations are multiplied by the rates.
 * This is a difference from the analogous function in arbplfdwell.c.
 */
static void
_update_site(nd_accum_t arr,
        likelihood_ws_t w, cross_site_ws_t csw, model_and_data_t m,
        int *coords, slong site, slong prec)
{
    int edge, idx, cat;
    arb_t site_lhood, cat_lhood, lhood;
    arb_t tmp;

    slong state_count = model_and_data_state_count(m);
    slong edge_count = model_and_data_edge_count(m);
    slong node_count = model_and_data_node_count(m);
    slong rate_category_count = model_and_data_rate_category_count(m);

    arb_init(site_lhood);
    arb_init(cat_lhood);
    arb_init(lhood);
    arb_init(tmp);

    /* only the edge axis is handled at this depth */
    nd_axis_struct *edge_axis = arr->axes + EDGE_AXIS;

    /* update base node vectors */
    pmat_update_base_node_vectors(w->base_node_vectors, m->p, site);

    /* clear cross-category expectations and site lhood */
    _arb_vec_zero(w->cc_edge_expectations, edge_count);
    arb_zero(site_lhood);

    for (cat = 0; cat < rate_category_count; cat++)
    {
        const arb_struct * cat_rate = csw->rate_mix_rates + cat;
        const arb_struct * prior_prob = csw->rate_mix_prior + cat;
        arb_mat_struct *tmat_base, *fmat_base;
        tmat_base = cross_site_ws_transition_matrix(csw, cat, 0);
        fmat_base = cross_site_ws_trans_frechet_matrix(csw, cat, 0);

        /*
         * Update per-node and per-edge likelihood vectors.
         * Actually the likelihood vectors on edges are not used.
         * This is a backward pass from the leaves to the root.
         */
        evaluate_site_lhood(lhood,
                w->lhood_node_vectors,
                w->lhood_edge_vectors,
                w->base_node_vectors,
                m->root_prior, csw->equilibrium,
                tmat_base,
                m->g, m->navigation->preorder, node_count, prec);

        /* Update forward vectors. */
        evaluate_site_forward(
                w->forward_edge_vectors,
                w->forward_node_vectors,
                w->base_node_vectors,
                w->lhood_edge_vectors,
                m->root_prior, csw->equilibrium,
                tmat_base, m->g, m->navigation,
                csw->node_count, csw->state_count, prec);

        /* Update expectations at edges. */
        evaluate_site_frechet(
                w->edge_expectations,
                w->lhood_node_vectors,
                w->forward_edge_vectors,
                fmat_base,
                m->g, m->navigation->preorder, node_count, state_count, prec);

        /* compute category likelihood */
        arb_mul(cat_lhood, lhood, prior_prob, prec);
        arb_add(site_lhood, site_lhood, cat_lhood, prec);

        /* Accumulate cross-category expectations. */
        for (edge = 0; edge < edge_count; edge++)
        {
            if (!edge_axis->request_update[edge]) continue;
            idx = m->edge_map->order[edge];

            /*
             * Multiply by the product of the category rate,
             * the edge rate, and the prior category probability.
             * In the analogous 'dwell' function (as opposed to 'trans'),
             * only the prior category probability is included.
             */
            arb_mul(tmp, cat_rate, csw->edge_rates + idx, prec);
            arb_mul(tmp, tmp, prior_prob, prec);
            arb_addmul(w->cc_edge_expectations + idx,
                       w->edge_expectations + idx, tmp, prec);
        }
    }

    /* Divide cross-category expectations by site lhood */
    for (edge = 0; edge < edge_count; edge++)
    {
        if (!edge_axis->request_update[edge]) continue;
        idx = m->edge_map->order[edge];
        arb_div(w->cc_edge_expectations + idx,
                w->cc_edge_expectations + idx,
                site_lhood, prec);
    }

    /* Update the nd accumulator. */
    for (edge = 0; edge < edge_count; edge++)
    {
        /* skip edges that are not requested */
        if (!edge_axis->request_update[edge]) continue;
        coords[EDGE_AXIS] = edge;

        /*
         * Accumulate.
         * Note that the axes, accumulator, and json interface
         * work with "user" edge indices,
         * whereas the workspace arrays work with
         * tree graph preorder edge indices.
         */
        idx = m->edge_map->order[edge];
        nd_accum_accumulate(arr,
                coords, w->cc_edge_expectations + idx, prec);
    }

    arb_clear(site_lhood);
    arb_clear(cat_lhood);
    arb_clear(lhood);
    arb_clear(tmp);
}
示例#22
0
文件: mullow_block.c 项目: isuruf/arb
void
_arb_poly_mullow_block(arb_ptr z, arb_srcptr x, slong xlen,
                       arb_srcptr y, slong ylen, slong n, slong prec)
{
    slong xmlen, xrlen, ymlen, yrlen, i;
    fmpz *xz, *yz, *zz;
    fmpz *xe, *ye;
    slong *xblocks, *yblocks;
    int squaring;
    fmpz_t scale, t;

    xlen = FLINT_MIN(xlen, n);
    ylen = FLINT_MIN(ylen, n);

    squaring = (x == y) && (xlen == ylen);

    /* Strip trailing zeros */
    xmlen = xrlen = xlen;
    while (xmlen > 0 && arf_is_zero(arb_midref(x + xmlen - 1))) xmlen--;
    while (xrlen > 0 && mag_is_zero(arb_radref(x + xrlen - 1))) xrlen--;

    if (squaring)
    {
        ymlen = xmlen;
        yrlen = xrlen;
    }
    else
    {
        ymlen = yrlen = ylen;
        while (ymlen > 0 && arf_is_zero(arb_midref(y + ymlen - 1))) ymlen--;
        while (yrlen > 0 && mag_is_zero(arb_radref(y + yrlen - 1))) yrlen--;
    }

    /* We don't know how to deal with infinities or NaNs */
    if (!_arb_vec_is_finite(x, xlen) ||
            (!squaring && !_arb_vec_is_finite(y, ylen)))
    {
        _arb_poly_mullow_classical(z, x, xlen, y, ylen, n, prec);
        return;
    }

    xlen = FLINT_MAX(xmlen, xrlen);
    ylen = FLINT_MAX(ymlen, yrlen);

    /* Start with the zero polynomial */
    _arb_vec_zero(z, n);

    /* Nothing to do */
    if (xlen == 0 || ylen == 0)
        return;

    n = FLINT_MIN(n, xlen + ylen - 1);

    fmpz_init(scale);
    fmpz_init(t);
    xz = _fmpz_vec_init(xlen);
    yz = _fmpz_vec_init(ylen);
    zz = _fmpz_vec_init(n);
    xe = _fmpz_vec_init(xlen);
    ye = _fmpz_vec_init(ylen);
    xblocks = flint_malloc(sizeof(slong) * (xlen + 1));
    yblocks = flint_malloc(sizeof(slong) * (ylen + 1));

    _arb_poly_get_scale(scale, x, xlen, y, ylen);

    /* Error propagation */
    /* (xm + xr)*(ym + yr) = (xm*ym) + (xr*ym + xm*yr + xr*yr)
                           = (xm*ym) + (xm*yr + xr*(ym + yr))  */
    if (xrlen != 0 || yrlen != 0)
    {
        mag_ptr tmp;
        double *xdbl, *ydbl;

        tmp = _mag_vec_init(FLINT_MAX(xlen, ylen));
        xdbl = flint_malloc(sizeof(double) * xlen);
        ydbl = flint_malloc(sizeof(double) * ylen);

        /* (xm + xr)^2 = (xm*ym) + (xr^2 + 2 xm xr)
                       = (xm*ym) + xr*(2 xm + xr)    */
        if (squaring)
        {
            _mag_vec_get_fmpz_2exp_blocks(xz, xdbl, xe, xblocks, scale, x, NULL, xrlen);

            for (i = 0; i < xlen; i++)
            {
                arf_get_mag(tmp + i, arb_midref(x + i));
                mag_mul_2exp_si(tmp + i, tmp + i, 1);
                mag_add(tmp + i, tmp + i, arb_radref(x + i));
            }

            _mag_vec_get_fmpz_2exp_blocks(yz, ydbl, ye, yblocks, scale, NULL, tmp, xlen);
            _arb_poly_addmullow_rad(z, zz, xz, xdbl, xe, xblocks, xrlen, yz, ydbl, ye, yblocks, xlen, n);
        }
        else if (yrlen == 0)
        {
            /* xr * |ym| */
            _mag_vec_get_fmpz_2exp_blocks(xz, xdbl, xe, xblocks, scale, x, NULL, xrlen);

            for (i = 0; i < ymlen; i++)
                arf_get_mag(tmp + i, arb_midref(y + i));

            _mag_vec_get_fmpz_2exp_blocks(yz, ydbl, ye, yblocks, scale, NULL, tmp, ymlen);
            _arb_poly_addmullow_rad(z, zz, xz, xdbl, xe, xblocks, xrlen, yz, ydbl, ye, yblocks, ymlen, n);
        }
        else
        {
            /* |xm| * yr */
            for (i = 0; i < xmlen; i++)
                arf_get_mag(tmp + i, arb_midref(x + i));

            _mag_vec_get_fmpz_2exp_blocks(xz, xdbl, xe, xblocks, scale, NULL, tmp, xmlen);
            _mag_vec_get_fmpz_2exp_blocks(yz, ydbl, ye, yblocks, scale, y, NULL, yrlen);
            _arb_poly_addmullow_rad(z, zz, xz, xdbl, xe, xblocks, xmlen, yz, ydbl, ye, yblocks, yrlen, n);

            /* xr*(|ym| + yr) */
            if (xrlen != 0)
            {
                _mag_vec_get_fmpz_2exp_blocks(xz, xdbl, xe, xblocks, scale, x, NULL, xrlen);

                for (i = 0; i < ylen; i++)
                    arb_get_mag(tmp + i, y + i);

                _mag_vec_get_fmpz_2exp_blocks(yz, ydbl, ye, yblocks, scale, NULL, tmp, ylen);
                _arb_poly_addmullow_rad(z, zz, xz, xdbl, xe, xblocks, xrlen, yz, ydbl, ye, yblocks, ylen, n);
            }
        }

        _mag_vec_clear(tmp, FLINT_MAX(xlen, ylen));
        flint_free(xdbl);
        flint_free(ydbl);
    }

    /* multiply midpoints */
    if (xmlen != 0 && ymlen != 0)
    {
        _arb_vec_get_fmpz_2exp_blocks(xz, xe, xblocks, scale, x, xmlen, prec);

        if (squaring)
        {
            _arb_poly_addmullow_block(z, zz, xz, xe, xblocks, xmlen, xz, xe, xblocks, xmlen, n, prec, 1);
        }
        else
        {
            _arb_vec_get_fmpz_2exp_blocks(yz, ye, yblocks, scale, y, ymlen, prec);
            _arb_poly_addmullow_block(z, zz, xz, xe, xblocks, xmlen, yz, ye, yblocks, ymlen, n, prec, 0);
        }
    }

    /* Unscale. */
    if (!fmpz_is_zero(scale))
    {
        fmpz_zero(t);
        for (i = 0; i < n; i++)
        {
            arb_mul_2exp_fmpz(z + i, z + i, t);
            fmpz_add(t, t, scale);
        }
    }

    _fmpz_vec_clear(xz, xlen);
    _fmpz_vec_clear(yz, ylen);
    _fmpz_vec_clear(zz, n);
    _fmpz_vec_clear(xe, xlen);
    _fmpz_vec_clear(ye, ylen);
    flint_free(xblocks);
    flint_free(yblocks);
    fmpz_clear(scale);
    fmpz_clear(t);
}
void
_arb_poly_sin_cos_series_tangent(arb_ptr s, arb_ptr c,
        arb_srcptr h, slong hlen, slong len, slong prec, int times_pi)
{
    arb_ptr t, u, v;
    arb_t s0, c0;
    hlen = FLINT_MIN(hlen, len);

    if (hlen == 1)
    {
        if (times_pi)
            arb_sin_cos_pi(s, c, h, prec);
        else
            arb_sin_cos(s, c, h, prec);
        _arb_vec_zero(s + 1, len - 1);
        _arb_vec_zero(c + 1, len - 1);
        return;
    }

    /*
    sin(x) = 2*tan(x/2)/(1+tan(x/2)^2)
    cos(x) = (1-tan(x/2)^2)/(1+tan(x/2)^2)
    */

    arb_init(s0);
    arb_init(c0);

    t = _arb_vec_init(3 * len);
    u = t + len;
    v = u + len;

    /* sin, cos of h0 */
    if (times_pi)
        arb_sin_cos_pi(s0, c0, h, prec);
    else
        arb_sin_cos(s0, c0, h, prec);

    /* t = tan((h-h0)/2) */
    arb_zero(u);
    _arb_vec_scalar_mul_2exp_si(u + 1, h + 1, hlen - 1, -1);
    if (times_pi)
    {
        arb_const_pi(t, prec);
        _arb_vec_scalar_mul(u + 1, u + 1, hlen - 1, t, prec);
    }

    _arb_poly_tan_series(t, u, hlen, len, prec);

    /* v = 1 + t^2 */
    _arb_poly_mullow(v, t, len, t, len, len, prec);
    arb_add_ui(v, v, 1, prec);

    /* u = 1/(1+t^2) */
    _arb_poly_inv_series(u, v, len, len, prec);

    /* sine */
    _arb_poly_mullow(s, t, len, u, len, len, prec);
    _arb_vec_scalar_mul_2exp_si(s, s, len, 1);

    /* cosine */
    arb_sub_ui(v, v, 2, prec);
    _arb_vec_neg(v, v, len);
    _arb_poly_mullow(c, v, len, u, len, len, prec);

    /* sin(h0 + h1) = cos(h0) sin(h1) + sin(h0) cos(h1)
       cos(h0 + h1) = cos(h0) cos(h1) - sin(h0) sin(h1) */
    if (!arb_is_zero(s0))
    {
        _arb_vec_scalar_mul(t, s, len, c0, prec);
        _arb_vec_scalar_mul(u, c, len, s0, prec);
        _arb_vec_scalar_mul(v, s, len, s0, prec);
        _arb_vec_add(s, t, u, len, prec);
        _arb_vec_scalar_mul(t, c, len, c0, prec);
        _arb_vec_sub(c, t, v, len, prec);
    }

    _arb_vec_clear(t, 3 * len);

    arb_clear(s0);
    arb_clear(c0);
}
示例#24
0
void
_arb_poly_pow_ui_trunc_binexp(arb_ptr res,
    arb_srcptr f, slong flen, ulong exp, slong len, slong prec)
{
    arb_ptr v, R, S, T;
    slong rlen;
    ulong bit;

    if (exp <= 1)
    {
        if (exp == 0)
            arb_one(res);
        else if (exp == 1)
            _arb_vec_set_round(res, f, len, prec);
        return;
    }

    /* (f * x^r)^m = x^(rm) * f^m */
    while (flen > 1 && arb_is_zero(f))
    {
        if (((ulong) len) > exp)
        {
            _arb_vec_zero(res, exp);
            len -= exp;
            res += exp;
        }
        else
        {
            _arb_vec_zero(res, len);
            return;
        }

        f++;
        flen--;
    }

    if (exp == 2)
    {
        _arb_poly_mullow(res, f, flen, f, flen, len, prec);
        return;
    }

    if (flen == 1)
    {
        arb_pow_ui(res, f, exp, prec);
        return;
    }

    v = _arb_vec_init(len);
    bit = UWORD(1) << (FLINT_BIT_COUNT(exp) - 2);
    
    if (n_zerobits(exp) % 2)
    {
        R = res;
        S = v;
    }
    else
    {
        R = v;
        S = res;
    }

    MUL(R, rlen, f, flen, f, flen, len, prec);

    if (bit & exp)
    {
        MUL(S, rlen, R, rlen, f, flen, len, prec);
        T = R;
        R = S;
        S = T;
    }
    
    while (bit >>= 1)
    {
        if (bit & exp)
        {
            MUL(S, rlen, R, rlen, R, rlen, len, prec);
            MUL(R, rlen, S, rlen, f, flen, len, prec);
        }
        else
        {
            MUL(S, rlen, R, rlen, R, rlen, len, prec);
            T = R;
            R = S;
            S = T;
        }
    }
    
    _arb_vec_clear(v, len);
}
示例#25
0
void
_arb_poly_evaluate_vec_fast_precomp(arb_ptr vs, arb_srcptr poly,
                                    long plen, arb_ptr * tree, long len, long prec)
{
    long height, i, j, pow, left;
    long tree_height;
    long tlen;
    arb_ptr t, u, swap, pa, pb, pc;

    /* avoid worrying about some degenerate cases */
    if (len < 2 || plen < 2)
    {
        if (len == 1)
        {
            arb_t tmp;
            arb_init(tmp);
            arb_neg(tmp, tree[0] + 0);
            _arb_poly_evaluate(vs + 0, poly, plen, tmp, prec);
            arb_clear(tmp);
        }
        else if (len != 0 && plen == 0)
        {
            _arb_vec_zero(vs, len);
        }
        else if (len != 0 && plen == 1)
        {
            for (i = 0; i < len; i++)
                arb_set(vs + i, poly + 0);
        }
        return;
    }

    t = _arb_vec_init(len);
    u = _arb_vec_init(len);

    left = len;

    /* Initial reduction. We allow the polynomial to be larger
        or smaller than the number of points. */
    height = FLINT_BIT_COUNT(plen - 1) - 1;
    tree_height = FLINT_CLOG2(len);
    while (height >= tree_height)
        height--;
    pow = 1L << height;

    for (i = j = 0; i < len; i += pow, j += (pow + 1))
    {
        tlen = ((i + pow) <= len) ? pow : len % pow;
        _arb_poly_rem(t + i, poly, plen, tree[height] + j, tlen + 1, prec);
    }

    for (i = height - 1; i >= 0; i--)
    {
        pow = 1L << i;
        left = len;
        pa = tree[i];
        pb = t;
        pc = u;

        while (left >= 2 * pow)
        {
            _arb_poly_rem_2(pc, pb, 2 * pow, pa, pow + 1, prec);
            _arb_poly_rem_2(pc + pow, pb, 2 * pow, pa + pow + 1, pow + 1, prec);

            pa += 2 * pow + 2;
            pb += 2 * pow;
            pc += 2 * pow;
            left -= 2 * pow;
        }

        if (left > pow)
        {
            _arb_poly_rem(pc, pb, left, pa, pow + 1, prec);
            _arb_poly_rem(pc + pow, pb, left, pa + pow + 1, left - pow + 1, prec);
        }
        else if (left > 0)
            _arb_vec_set(pc, pb, left);

        swap = t;
        t = u;
        u = swap;
    }

    _arb_vec_set(vs, t, len);
    _arb_vec_clear(t, len);
    _arb_vec_clear(u, len);
}
示例#26
0
void
_arb_poly_exp_series(arb_ptr f, arb_srcptr h, slong hlen, slong n, slong prec)
{
    hlen = FLINT_MIN(hlen, n);

    if (hlen == 1)
    {
        arb_exp(f, h, prec);
        _arb_vec_zero(f + 1, n - 1);
    }
    else if (n == 2)
    {
        arb_exp(f, h, prec);
        arb_mul(f + 1, f, h + 1, prec);  /* safe since hlen >= 2 */
    }
    else if (_arb_vec_is_zero(h + 1, hlen - 2)) /* h = a + bx^d */
    {
        slong i, j, d = hlen - 1;
        arb_t t;
        arb_init(t);
        arb_set(t, h + d);
        arb_exp(f, h, prec);
        for (i = 1, j = d; j < n; j += d, i++)
        {
            arb_mul(f + j, f + j - d, t, prec);
            arb_div_ui(f + j, f + j, i, prec);
            _arb_vec_zero(f + j - d + 1, hlen - 2);
        }
        _arb_vec_zero(f + j - d + 1, n - (j - d + 1));
        arb_clear(t);
    }
    else if (hlen <= arb_poly_newton_exp_cutoff)
    {
        _arb_poly_exp_series_basecase(f, h, hlen, n, prec);
    }
    else
    {
        arb_ptr g, t;
        arb_t u;
        int fix;

        g = _arb_vec_init((n + 1) / 2);
        fix = (hlen < n || h == f || !arb_is_zero(h));

        if (fix)
        {
            t = _arb_vec_init(n);
            _arb_vec_set(t + 1, h + 1, hlen - 1);
        }
        else
            t = (arb_ptr) h;

        arb_init(u);
        arb_exp(u, h, prec);

        _arb_poly_exp_series_newton(f, g, t, n, prec, 0, arb_poly_newton_exp_cutoff);

        if (!arb_is_one(u))
            _arb_vec_scalar_mul(f, f, n, u, prec);

        _arb_vec_clear(g, (n + 1) / 2);
        if (fix)
            _arb_vec_clear(t, n);
        arb_clear(u);
    }
}
示例#27
0
void
_arb_poly_inv_series(arb_ptr Qinv,
    arb_srcptr Q, slong Qlen, slong len, slong prec)
{
    Qlen = FLINT_MIN(Qlen, len);

    arb_inv(Qinv, Q, prec);

    if (Qlen == 1)
    {
        _arb_vec_zero(Qinv + 1, len - 1);
    }
    else if (len == 2)
    {
        arb_mul(Qinv + 1, Qinv, Qinv, prec);
        arb_mul(Qinv + 1, Qinv + 1, Q + 1, prec);
        arb_neg(Qinv + 1, Qinv + 1);
    }
    else
    {
        slong i, j, blen;

        /* The basecase algorithm is faster for much larger Qlen or len than
           this, but unfortunately also much less numerically stable. */
        if (Qlen == 2 || len <= 8)
            blen = len;
        else
            blen = FLINT_MIN(len, 4);

        for (i = 1; i < blen; i++)
        {
            arb_mul(Qinv + i, Q + 1, Qinv + i - 1, prec);

            for (j = 2; j < FLINT_MIN(i + 1, Qlen); j++)
                arb_addmul(Qinv + i, Q + j, Qinv + i - j, prec);

            if (!arb_is_one(Qinv))
                arb_mul(Qinv + i, Qinv + i, Qinv, prec);

            arb_neg(Qinv + i, Qinv + i);
        }

        if (len > blen)
        {
            slong Qnlen, Wlen, W2len;
            arb_ptr W;

            W = _arb_vec_init(len);

            NEWTON_INIT(blen, len)
            NEWTON_LOOP(m, n)

            Qnlen = FLINT_MIN(Qlen, n);
            Wlen = FLINT_MIN(Qnlen + m - 1, n);
            W2len = Wlen - m;
            MULLOW(W, Q, Qnlen, Qinv, m, Wlen, prec);
            MULLOW(Qinv + m, Qinv, m, W + m, W2len, n - m, prec);
            _arb_vec_neg(Qinv + m, Qinv + m, n - m);

            NEWTON_END_LOOP
            NEWTON_END

            _arb_vec_clear(W, len);
        }
    }
}