Example #1
0
void
mag_sqrt(mag_t y, const mag_t x)
{
    if (mag_is_special(x))
    {
        mag_set(y, x);
    }
    else
    {
        double t;
        fmpz e;

        t = MAG_MAN(x) * ldexp(1.0, -MAG_BITS);
        e = MAG_EXP(x);

        if (!COEFF_IS_MPZ(e))
        {
            if (e % 2 != 0)
            {
                e = (e - 1) >> 1;
                t *= 2.0;
            }
            else
            {
                e >>= 1;
            }
            t = sqrt(t) * (1 + 1e-13);
            mag_set_d_2exp_fmpz(y, t, &e);
        }
Example #2
0
void
mag_root(mag_t y, const mag_t x, ulong n)
{
    if (n == 0)
    {
        mag_inf(y);
    }
    else if (n == 1 || mag_is_special(x))
    {
        mag_set(y, x);
    }
    else if (n == 2)
    {
        mag_sqrt(y, x);
    }
    else if (n == 4)
    {
        mag_sqrt(y, x);
        mag_sqrt(y, y);
    }
    else
    {
        fmpz_t e, f;

        fmpz_init_set_ui(e, MAG_BITS);
        fmpz_init(f);

        /* We evaluate exp(log(1+2^(kn)x)/n) 2^-k where k is chosen
           so that 2^(kn) x ~= 2^30. TODO: this rewriting is probably
           unnecessary with the new exp/log functions. */
        fmpz_sub(e, e, MAG_EXPREF(x));
        fmpz_cdiv_q_ui(e, e, n);
        fmpz_mul_ui(f, e, n);
        mag_mul_2exp_fmpz(y, x, f);
        mag_log1p(y, y);
        mag_div_ui(y, y, n);
        mag_exp(y, y);
        fmpz_neg(e, e);
        mag_mul_2exp_fmpz(y, y, e);

        fmpz_clear(e);
        fmpz_clear(f);
    }
}
Example #3
0
File: exp.c Project: wbhart/arb
slong
_arb_mat_exp_choose_N(const mag_t norm, slong prec)
{
    if (mag_is_special(norm) || mag_cmp_2exp_si(norm, 30) > 0 ||
        mag_cmp_2exp_si(norm, -prec) < 0)
    {
        return 1;
    }
    else if (mag_cmp_2exp_si(norm, -300) < 0)
    {
        slong N = -MAG_EXP(norm);
        return (prec + N - 1) / N;
    }
    else
    {
        double c, t;

        c = mag_get_d(norm);
        t = d_lambertw(prec * LOG2_OVER_E / c);
        t = c * exp(t + 1.0);
        return FLINT_MIN((slong) (t + 1.0), 2 * prec);
    }
}
Example #4
0
static __inline__ void
_mag_vec_get_fmpz_2exp_blocks(fmpz * coeffs,
                              double * dblcoeffs, fmpz * exps, slong * blocks, const fmpz_t scale,
                              arb_srcptr x, mag_srcptr xm, slong len)
{
    fmpz_t top, bot, t, b, v, block_top, block_bot;
    slong i, j, s, block, bits, maxheight;
    int in_zero;
    mag_srcptr cur;

    fmpz_init(top);
    fmpz_init(bot);
    fmpz_init(t);
    fmpz_init(b);
    fmpz_init(v);
    fmpz_init(block_top);
    fmpz_init(block_bot);

    blocks[0] = 0;
    block = 0;
    in_zero = 1;

    maxheight = ALPHA * MAG_BITS + BETA;
    if (maxheight > DOUBLE_BLOCK_MAX_HEIGHT)
        abort();

    for (i = 0; i < len; i++)
    {
        cur = (x == NULL) ? (xm + i) : arb_radref(x + i);

        /* Skip (must be zero, since we assume there are no Infs/NaNs). */
        if (mag_is_special(cur))
            continue;

        /* Bottom and top exponent of current number */
        bits = MAG_BITS;
        fmpz_set(top, MAG_EXPREF(cur));
        fmpz_submul_ui(top, scale, i);
        fmpz_sub_ui(bot, top, bits);

        /* Extend current block. */
        if (in_zero)
        {
            fmpz_swap(block_top, top);
            fmpz_swap(block_bot, bot);
        }
        else
        {
            fmpz_max(t, top, block_top);
            fmpz_min(b, bot, block_bot);
            fmpz_sub(v, t, b);

            /* extend current block */
            if (fmpz_cmp_ui(v, maxheight) < 0)
            {
                fmpz_swap(block_top, t);
                fmpz_swap(block_bot, b);
            }
            else  /* start new block */
            {
                /* write exponent for previous block */
                fmpz_set(exps + block, block_bot);

                block++;
                blocks[block] = i;

                fmpz_swap(block_top, top);
                fmpz_swap(block_bot, bot);
            }
        }

        in_zero = 0;
    }

    /* write exponent for last block */
    fmpz_set(exps + block, block_bot);

    /* end marker */
    blocks[block + 1] = len;

    /* write the block data */
    for (i = 0; blocks[i] != len; i++)
    {
        for (j = blocks[i]; j < blocks[i + 1]; j++)
        {
            cur = (x == NULL) ? (xm + j) : arb_radref(x + j);

            if (mag_is_special(cur))
            {
                fmpz_zero(coeffs + j);
                dblcoeffs[j] = 0.0;
            }
            else
            {
                mp_limb_t man;
                double c;

                man = MAG_MAN(cur);

                /* TODO: only write and use doubles when block is short? */

                /* Divide by 2^(scale * j) */
                fmpz_mul_ui(t, scale, j);
                fmpz_sub(t, MAG_EXPREF(cur), t);

                fmpz_sub_ui(t, t, MAG_BITS); /* bottom exponent */
                s = _fmpz_sub_small(t, exps + i);

                if (s < 0) abort(); /* Bug catcher */

                fmpz_set_ui(coeffs + j, man);
                fmpz_mul_2exp(coeffs + j, coeffs + j, s);
                c = man;
                c = ldexp(c, s - DOUBLE_BLOCK_SHIFT);
                if (c < 1e-150 || c > 1e150) /* Bug catcher */
                    abort();
                dblcoeffs[j] = c;
            }
        }
    }

    fmpz_clear(top);
    fmpz_clear(bot);
    fmpz_clear(t);
    fmpz_clear(b);
    fmpz_clear(v);
    fmpz_clear(block_top);
    fmpz_clear(block_bot);
}
Example #5
0
void
mag_log1p(mag_t z, const mag_t x)
{
    if (mag_is_special(x))
    {
        if (mag_is_zero(x))
            mag_zero(z);
        else
            mag_inf(z);
    }
    else
    {
        fmpz exp = MAG_EXP(x);

        if (!COEFF_IS_MPZ(exp))
        {
            /* Quick bound by x */
            if (exp < -10)
            {
                mag_set(z, x);
                return;
            }
            else if (exp < 1000)
            {
                double t;
                t = ldexp(MAG_MAN(x), exp - MAG_BITS);
                t = (1.0 + t) * (1 + 1e-14);
                t = mag_d_log_upper_bound(t);
                mag_set_d(z, t);
                return;
            }
        }
        else if (fmpz_sgn(MAG_EXPREF(x)) < 0)
        {
            /* Quick bound by x */
            mag_set(z, x);
            return;
        }

        /* Now we must have x >= 2^1000 */
        /* Use log(2^(exp-1) * (2*v)) = exp*log(2) + log(2*v) */
        {
            double t;
            fmpz_t b;
            mag_t u;

            mag_init(u);
            fmpz_init(b);

            /* incrementing the mantissa gives an upper bound for x+1 */
            t = ldexp(MAG_MAN(x) + 1, 1 - MAG_BITS);
            t = mag_d_log_upper_bound(t);
            mag_set_d(u, t);

            /* log(2) < 744261118/2^30 */
            _fmpz_add_fast(b, MAG_EXPREF(x), -1);
            fmpz_mul_ui(b, b, 744261118);
            mag_set_fmpz(z, b);
            _fmpz_add_fast(MAG_EXPREF(z), MAG_EXPREF(z), -30);

            mag_add(z, z, u);

            mag_clear(u);
            fmpz_clear(b);
        }
    }
}