Example #1
0
File: sub.c Project: isuruf/arb
int
arf_sub_special(arf_t z, const arf_t x, const arf_t y, slong prec, arf_rnd_t rnd)
{
    if (arf_is_zero(x))
    {
        if (arf_is_zero(y))
        {
            arf_zero(z);
            return 0;
        }
        else
            return arf_neg_round(z, y, prec, rnd);
    }
    else if (arf_is_zero(y))
    {
        return arf_set_round(z, x, prec, rnd);
    }
    else if (arf_is_nan(x) || arf_is_nan(y)
        || (arf_is_pos_inf(x) && arf_is_pos_inf(y))
        || (arf_is_neg_inf(x) && arf_is_neg_inf(y)))
    {
        arf_nan(z);
        return 0;
    }
    else if (arf_is_special(x))
    {
        arf_set(z, x);
        return 0;
    }
    else
    {
        arf_neg(z, y);
        return 0;
    }
}
Example #2
0
File: fprint.c Project: isuruf/arb
void
arf_fprint(FILE * file, const arf_t x)
{
    if (arf_is_normal(x))
    {
        fmpz_t man, exp;

        fmpz_init(man);
        fmpz_init(exp);

        arf_get_fmpz_2exp(man, exp, x);

        flint_fprintf(file, "(");
        fmpz_fprint(file, man);
        flint_fprintf(file, " * 2^");
        fmpz_fprint(file, exp);
        flint_fprintf(file, ")");

        fmpz_clear(man);
        fmpz_clear(exp);
    }
    else
    {
        if (arf_is_zero(x)) flint_fprintf(file, "(0)");
        else if (arf_is_pos_inf(x)) flint_fprintf(file, "(+inf)");
        else if (arf_is_neg_inf(x)) flint_fprintf(file, "(-inf)");
        else flint_fprintf(file, "(nan)");
    }
}
Example #3
0
void
arf_get_fmpr(fmpr_t y, const arf_t x)
{
    if (arf_is_special(x))
    {
        if (arf_is_zero(x))
            fmpr_zero(y);
        else if (arf_is_pos_inf(x))
            fmpr_pos_inf(y);
        else if (arf_is_neg_inf(x))
            fmpr_neg_inf(y);
        else
            fmpr_nan(y);
    }
    else
    {
        arf_get_fmpz_2exp(fmpr_manref(y), fmpr_expref(y), x);
    }
}
Example #4
0
int
arf_cmp_2exp_si(const arf_t x, long e)
{
    if (arf_is_special(x))
    {
        if (arf_is_zero(x)) return -1;
        if (arf_is_pos_inf(x)) return 1;
        if (arf_is_neg_inf(x)) return -1;
        return 0;
    }

    if (ARF_SGNBIT(x))
        return -1;

    /* Fast path. */
    if (!COEFF_IS_MPZ(ARF_EXP(x)))
    {
        if (ARF_IS_POW2(x) && (ARF_EXP(x) - 1 == e))
            return 0;
        else
            return (ARF_EXP(x) <= e) ? -1 : 1;
    }

    if (ARF_IS_POW2(x))
    {
        fmpz_t t;
        fmpz_init(t);
        fmpz_one(t);
        fmpz_add_si(t, t, e);
        if (fmpz_equal(ARF_EXPREF(x), t))
        {
            fmpz_clear(t);
            return 0;
        }
        fmpz_clear(t);
    }

    return (fmpz_cmp_si(ARF_EXPREF(x), e) <= 0) ? -1 : 1;
}
Example #5
0
File: root.c Project: isuruf/arb
int
arf_root(arf_ptr z, arf_srcptr x, ulong k, slong prec, arf_rnd_t rnd)
{
    mp_size_t xn, zn, val;
    mp_srcptr xptr;
    mp_ptr tmp, zptr;
    mpfr_t xf, zf;
    fmpz_t q, r;
    int inexact;

    if (k == 0)
    {
        arf_nan(z);
        return 0;
    }

    if (k == 1)
        return arf_set_round(z, x, prec, rnd);

    if (k == 2)
        return arf_sqrt(z, x, prec, rnd);

    if (arf_is_special(x))
    {
        if (arf_is_neg_inf(x))
            arf_nan(z);
        else
            arf_set(z, x);
        return 0;
    }

    if (ARF_SGNBIT(x))
    {
        arf_nan(z);
        return 0;
    }

    fmpz_init(q);
    fmpz_init(r);

    /* x = m * 2^e where e = qk + r */
    /* x^(1/k) = (m * 2^(qk+r))^(1/k)  */
    /* x^(1/k) = (m * 2^r)^(1/k) * 2^q  */
    fmpz_set_ui(r, k);
    fmpz_fdiv_qr(q, r, ARF_EXPREF(x), r);

    ARF_GET_MPN_READONLY(xptr, xn, x);
    zn = (prec + FLINT_BITS - 1) / FLINT_BITS;

    zf->_mpfr_d = tmp = flint_malloc(zn * sizeof(mp_limb_t));
    zf->_mpfr_prec = prec;
    zf->_mpfr_sign = 1;
    zf->_mpfr_exp = 0;

    xf->_mpfr_d = (mp_ptr) xptr;
    xf->_mpfr_prec = xn * FLINT_BITS;
    xf->_mpfr_sign = 1;
    xf->_mpfr_exp = fmpz_get_ui(r);

    inexact = mpfr_root(zf, xf, k, arf_rnd_to_mpfr(rnd));
    inexact = (inexact != 0);

    val = 0;
    while (tmp[val] == 0)
        val++;

    ARF_GET_MPN_WRITE(zptr, zn - val, z);
    flint_mpn_copyi(zptr, tmp + val, zn - val);

    fmpz_add_si(ARF_EXPREF(z), q, zf->_mpfr_exp);

    flint_free(tmp);
    fmpz_clear(q);
    fmpz_clear(r);

    return inexact;
}
Example #6
0
void
arb_atan_arf(arb_t z, const arf_t x, slong prec)
{
    if (arf_is_special(x))
    {
        if (arf_is_zero(x))
        {
            arb_zero(z);
        }
        else if (arf_is_pos_inf(x))
        {
            arb_const_pi(z, prec);
            arb_mul_2exp_si(z, z, -1);
        }
        else if (arf_is_neg_inf(x))
        {
            arb_const_pi(z, prec);
            arb_mul_2exp_si(z, z, -1);
            arb_neg(z, z);
        }
        else
        {
            arb_indeterminate(z);
        }
    }
    else if (COEFF_IS_MPZ(*ARF_EXPREF(x)))
    {
        if (fmpz_sgn(ARF_EXPREF(x)) < 0)
            arb_atan_eps(z, x, prec);
        else
            arb_atan_inf_eps(z, x, prec);
    }
    else
    {
        slong exp, wp, wn, N, r;
        mp_srcptr xp;
        mp_size_t xn, tn;
        mp_ptr tmp, w, t, u;
        mp_limb_t p1, q1bits, p2, q2bits, error, error2;
        int negative, inexact, reciprocal;
        TMP_INIT;

        exp = ARF_EXP(x);
        negative = ARF_SGNBIT(x);

        if (exp < -(prec/2) - 2 || exp > prec + 2)
        {
            if (exp < 0)
                arb_atan_eps(z, x, prec);
            else
                arb_atan_inf_eps(z, x, prec);
            return;
        }

        ARF_GET_MPN_READONLY(xp, xn, x);

        /* Special case: +/- 1 (we require |x| != 1 later on) */
        if (exp == 1 && xn == 1 && xp[xn-1] == LIMB_TOP)
        {
            arb_const_pi(z, prec);
            arb_mul_2exp_si(z, z, -2);
            if (negative)
                arb_neg(z, z);
            return;
        }

        /* Absolute working precision (NOT rounded to a limb multiple) */
        wp = prec - FLINT_MIN(0, exp) + 4;

        /* Too high precision to use table */
        if (wp > ARB_ATAN_TAB2_PREC)
        {
            arb_atan_arf_bb(z, x, prec);
            return;
        }

        /* Working precision in limbs */
        wn = (wp + FLINT_BITS - 1) / FLINT_BITS;

        TMP_START;

        tmp = TMP_ALLOC_LIMBS(4 * wn + 3);
        w = tmp;        /* requires wn+1 limbs */
        t = w + wn + 1; /* requires wn+1 limbs */
        u = t + wn + 1; /* requires 2wn+1 limbs */

        /* ----------------------------------------------------------------- */
        /* Convert x or 1/x to a fixed-point number |w| < 1                  */
        /* ----------------------------------------------------------------- */

        if (exp <= 0)  /* |x| < 1 */
        {
            reciprocal = 0;

            /* todo: just zero top */
            flint_mpn_zero(w, wn);

            /* w = x as a fixed-point number */
            error = _arf_get_integer_mpn(w, xp, xn, exp + wn * FLINT_BITS);
        }
        else    /* |x| > 1 */
        {
            slong one_exp, one_limbs, one_bits;
            mp_ptr one;

            reciprocal = 1;

            one_exp = xn * FLINT_BITS + wn * FLINT_BITS - exp;

            flint_mpn_zero(w, wn);

            /* 1/x becomes zero */
            if (one_exp >= FLINT_BITS - 1)
            {
                /* w = 1/x */
                one_limbs = one_exp / FLINT_BITS;
                one_bits = one_exp % FLINT_BITS;

                if (one_limbs + 1 >= xn)
                {
                    one = TMP_ALLOC_LIMBS(one_limbs + 1);
                    flint_mpn_zero(one, one_limbs);
                    one[one_limbs] = UWORD(1) << one_bits;

                    /* todo: only zero necessary part */
                    flint_mpn_zero(w, wn);
                    mpn_tdiv_q(w, one, one_limbs + 1, xp, xn);

                    /* Now w must be < 1 since x > 1 and we rounded down; thus
                       w[wn] must be zero */
                }
            }

            /* todo: moderate powers of two would be exact... */
            error = 1;
        }

        /* ----------------------------------------------------------------- */
        /* Table-based argument reduction                                    */
        /* ----------------------------------------------------------------- */

        /* choose p such that p/q <= x < (p+1)/q */
        if (wp <= ARB_ATAN_TAB1_PREC)
            q1bits = ARB_ATAN_TAB1_BITS;
        else
            q1bits = ARB_ATAN_TAB21_BITS;

        p1 = w[wn-1] >> (FLINT_BITS - q1bits);

        /* atan(w) = atan(p/q) + atan(w2) */
        /* where w2 = (q*w-p)/(q+p*w) */
        if (p1 != 0)
        {
            t[wn] = (UWORD(1) << q1bits) + mpn_mul_1(t, w, wn, p1);
            flint_mpn_zero(u, wn);
            u[2 * wn] = mpn_lshift(u + wn, w, wn, q1bits) - p1;
            mpn_tdiv_q(w, u, 2 * wn + 1, t, wn + 1);
            error++;  /* w2 is computed with 1 ulp error */
        }

        /* Do a second round of argument reduction */
        if (wp <= ARB_ATAN_TAB1_PREC)
        {
            p2 = 0;
        }
        else
        {
            q2bits = ARB_ATAN_TAB21_BITS + ARB_ATAN_TAB22_BITS;
            p2 = w[wn-1] >> (FLINT_BITS - q2bits);

            if (p2 != 0)
            {
                t[wn] = (UWORD(1) << q2bits) + mpn_mul_1(t, w, wn, p2);
                flint_mpn_zero(u, wn);
                u[2 * wn] = mpn_lshift(u + wn, w, wn, q2bits) - p2;
                mpn_tdiv_q(w, u, 2 * wn + 1, t, wn + 1);
                error++;
            }
        }

        /* |w| <= 2^-r */
        r = _arb_mpn_leading_zeros(w, wn);

        /* N >= (wp-r)/(2r) */
        N = (wp - r + (2*r-1)) / (2*r);

        /* Evaluate Taylor series */
        _arb_atan_taylor_rs(t, &error2, w, wn, N, 1);

        /* Taylor series evaluation error */
        error += error2;

        /* Size of output number */
        tn = wn;

        /* First table lookup */
        if (p1 != 0)
        {
            if (wp <= ARB_ATAN_TAB1_PREC)
                mpn_add_n(t, t, arb_atan_tab1[p1] + ARB_ATAN_TAB1_LIMBS - tn, tn);
            else
                mpn_add_n(t, t, arb_atan_tab21[p1] + ARB_ATAN_TAB2_LIMBS - tn, tn);
            error++;
        }

        /* Second table lookup */
        if (p2 != 0)
        {
            mpn_add_n(t, t, arb_atan_tab22[p2] + ARB_ATAN_TAB2_LIMBS - tn, tn);
            error++;
        }

        /* pi/2 - atan(1/x) */
        if (reciprocal)
        {
            t[tn] = LIMB_ONE - mpn_sub_n(t,
                arb_atan_pi2_minus_one + ARB_ATAN_TAB2_LIMBS - tn, t, tn);

            /* result can be >= 1 */
            tn += (t[tn] != 0);

            /* error of pi/2 */
            error++;
        }

        /* The accumulated arithmetic error */
        mag_set_ui_2exp_si(arb_radref(z), error, -wn * FLINT_BITS);

        /* Truncation error from the Taylor series */
        mag_add_ui_2exp_si(arb_radref(z), arb_radref(z), 1, -r*(2*N+1));

        /* Set the midpoint */
        inexact = _arf_set_mpn_fixed(arb_midref(z), t, tn, wn, negative, prec, ARB_RND);
        if (inexact)
            arf_mag_add_ulp(arb_radref(z), arb_radref(z), arb_midref(z), prec);

        TMP_END;
    }
}
Example #7
0
File: sum.c Project: bluescarni/arb
int
arf_sum(arf_t s, arf_srcptr terms, long len, long prec, arf_rnd_t rnd)
{
    arf_ptr blocks;
    long i, j, used;
    int have_merged, res;

    /* first check if the result is inf or nan */
    {
        int have_pos_inf = 0;
        int have_neg_inf = 0;

        for (i = 0; i < len; i++)
        {
            if (arf_is_pos_inf(terms + i))
            {
                if (have_neg_inf)
                {
                    arf_nan(s);
                    return 0;
                }
                have_pos_inf = 1;
            }
            else if (arf_is_neg_inf(terms + i))
            {
                if (have_pos_inf)
                {
                    arf_nan(s);
                    return 0;
                }
                have_neg_inf = 1;
            }
            else if (arf_is_nan(terms + i))
            {
                arf_nan(s);
                return 0;
            }
        }

        if (have_pos_inf)
        {
            arf_pos_inf(s);
            return 0;
        }

        if (have_neg_inf)
        {
            arf_neg_inf(s);
            return 0;
        }
    }

    blocks = flint_malloc(sizeof(arf_struct) * len);
    for (i = 0; i < len; i++)
        arf_init(blocks + i);

    /* put all terms into blocks */
    used = 0;
    for (i = 0; i < len; i++)
    {
        if (!arf_is_zero(terms + i))
        {
            arf_set(blocks + used, terms + i);
            used++;
        }
    }

    /* merge blocks until all are well separated */
    have_merged = 1;
    while (used >= 2 && have_merged)
    {
        have_merged = 0;

        for (i = 0; i < used && !have_merged; i++)
        {
            for (j = i + 1; j < used && !have_merged; j++)
            {
                if (_arf_are_close(blocks + i, blocks + j, prec))
                {
                    arf_add(blocks + i, blocks + i, blocks + j,
                        ARF_PREC_EXACT, ARF_RND_DOWN);

                    /* remove the merged block */
                    arf_swap(blocks + j, blocks + used - 1);
                    used--;

                    /* remove the updated block if the sum is zero */
                    if (arf_is_zero(blocks + i))
                    {
                        arf_swap(blocks + i, blocks + used - 1);
                        used--;
                    }

                    have_merged = 1;
                }
            }
        }
    }

    if (used == 0)
    {
        arf_zero(s);
        res = 0;
    }
    else if (used == 1)
    {
        res = arf_set_round(s, blocks + 0, prec, rnd);
    }
    else
    {
        /* find the two largest blocks */
        for (i = 1; i < used; i++)
            if (arf_cmpabs(blocks + 0, blocks + i) < 0)
                arf_swap(blocks + 0, blocks + i);

        for (i = 2; i < used; i++)
            if (arf_cmpabs(blocks + 1, blocks + i) < 0)
                arf_swap(blocks + 1, blocks + i);

        res = _arf_add_eps(s, blocks + 0, arf_sgn(blocks + 1), prec, rnd);
    }

    for (i = 0; i < len; i++)
        arf_clear(blocks + i);
    flint_free(blocks);

    return res;
}