int
juliabn_per_pixel()
{
    // old.x = xxmin + col*delx + row*delx2
    mult_bn_int(bnold.x, bnxdel, (U16)col);
    mult_bn_int(bntmp, bnxdel2, (U16)row);

    add_a_bn(bnold.x, bntmp);
    add_a_bn(bnold.x, bnxmin);

    // old.y = yymax - row*dely - col*dely2;
    // note: in next four lines, bnnew is just used as a temporary variable
    mult_bn_int(bnnew.x, bnydel, (U16)row);
    mult_bn_int(bnnew.y, bnydel2, (U16)col);
    add_a_bn(bnnew.x, bnnew.y);
    sub_bn(bnold.y, bnymax, bnnew.x);

    // square has side effect - must copy first
    copy_bn(bnnew.x, bnold.x);
    copy_bn(bnnew.y, bnold.y);

    // Square these to rlength bytes of precision
    square_bn(bntmpsqrx, bnnew.x);
    square_bn(bntmpsqry, bnnew.y);

    return (1);                  // 1st iteration has been done
}
BNComplex *cplxmul_bn(BNComplex *t, BNComplex *x, BNComplex *y)
{
    bn_t tmp1;
    int saved;
    saved = save_stack();
    tmp1 = alloc_stack(rlength);
    mult_bn(t->x, x->x, y->x);
    mult_bn(t->y, x->y, y->y);
    sub_bn(t->x, t->x+shiftfactor, t->y+shiftfactor);

    mult_bn(tmp1, x->x, y->y);
    mult_bn(t->y, x->y, y->x);
    add_bn(t->y, tmp1+shiftfactor, t->y+shiftfactor);
    restore_stack(saved);
    return (t);
}
int mandelbn_per_pixel()
{
    // parm.x = xxmin + col*delx + row*delx2
    mult_bn_int(bnparm.x, bnxdel, (U16)col);
    mult_bn_int(bntmp, bnxdel2, (U16)row);

    add_a_bn(bnparm.x, bntmp);
    add_a_bn(bnparm.x, bnxmin);

    // parm.y = yymax - row*dely - col*dely2;
    // note: in next four lines, bnold is just used as a temporary variable
    mult_bn_int(bnold.x, bnydel, (U16)row);
    mult_bn_int(bnold.y, bnydel2, (U16)col);
    add_a_bn(bnold.x, bnold.y);
    sub_bn(bnparm.y, bnymax, bnold.x);

    copy_bn(bnold.x, bnparm.x);
    copy_bn(bnold.y, bnparm.y);

    if ((inside == BOF60 || inside == BOF61) && !nobof)
    {
        /* kludge to match "Beauty of Fractals" picture since we start
           Mandelbrot iteration with init rather than 0 */
        floattobn(bnold.x, param[0]); // initial pertubation of parameters set
        floattobn(bnold.y, param[1]);
        coloriter = -1;
    }
    else
    {
        floattobn(bnnew.x, param[0]);
        floattobn(bnnew.y, param[1]);
        add_a_bn(bnold.x, bnnew.x);
        add_a_bn(bnold.y, bnnew.y);
    }

    // square has side effect - must copy first
    copy_bn(bnnew.x, bnold.x);
    copy_bn(bnnew.y, bnold.y);

    // Square these to rlength bytes of precision
    square_bn(bntmpsqrx, bnnew.x);
    square_bn(bntmpsqry, bnnew.y);

    return (1);                  // 1st iteration has been done
}
// atan2(r, ny, nx)
// uses bntmp1 - bntmp6 - global temp bigfloats
bn_t unsafe_atan2_bn(bn_t r, bn_t ny, bn_t nx)
{
    int signx, signy;

    signx = sign_bn(nx);
    signy = sign_bn(ny);

    if (signy == 0)
    {
        if (signx < 0)
            copy_bn(r, bn_pi); // negative x axis, 180 deg
        else    // signx >= 0    positive x axis, 0
            clear_bn(r);
        return (r);
    }
    if (signx == 0)
    {
        copy_bn(r, bn_pi); // y axis
        half_a_bn(r);      // +90 deg
        if (signy < 0)
            neg_a_bn(r);    // -90 deg
        return (r);
    }

    if (signy < 0)
        neg_a_bn(ny);
    if (signx < 0)
        neg_a_bn(nx);
    unsafe_div_bn(bntmp6, ny, nx);
    unsafe_atan_bn(r, bntmp6);
    if (signx < 0)
        sub_bn(r, bn_pi, r);
    if (signy < 0)
        neg_a_bn(r);
    return (r);
}
// sincos_bn(r)
// uses bntmp1 - bntmp2 - global temp bignumbers
//  SIDE-EFFECTS:
//      n ends up as |n| mod (pi/4)
bn_t unsafe_sincos_bn(bn_t s, bn_t c, bn_t n)
{
    U16 fact = 2;
    bool k = false;

#ifndef CALCULATING_BIG_PI
    // assure range 0 <= x < pi/4

    if (is_bn_zero(n))
    {
        clear_bn(s);    // sin(0) = 0
        inttobn(c, 1);  // cos(0) = 1
        return s;
    }

    bool signcos = false;
    bool signsin = false;
    bool switch_sincos = false;
    if (is_bn_neg(n))
    {
        signsin = !signsin; // sin(-x) = -sin(x), odd; cos(-x) = cos(x), even
        neg_a_bn(n);
    }
    // n >= 0

    double_bn(bntmp1, bn_pi); // 2*pi
    // this could be done with remainders, but it would probably be slower
    while (cmp_bn(n, bntmp1) >= 0) // while n >= 2*pi
        sub_a_bn(n, bntmp1);
    // 0 <= n < 2*pi

    copy_bn(bntmp1, bn_pi); // pi
    if (cmp_bn(n, bntmp1) >= 0) // if n >= pi
    {
        sub_a_bn(n, bntmp1);
        signsin = !signsin;
        signcos = !signcos;
    }
    // 0 <= n < pi

    half_bn(bntmp1, bn_pi); // pi/2
    if (cmp_bn(n, bntmp1) > 0) // if n > pi/2
    {
        sub_bn(n, bn_pi, n);   // pi - n
        signcos = !signcos;
    }
    // 0 <= n < pi/2

    half_bn(bntmp1, bn_pi); // pi/2
    half_a_bn(bntmp1);      // pi/4
    if (cmp_bn(n, bntmp1) > 0) // if n > pi/4
    {
        half_bn(bntmp1, bn_pi); // pi/2
        sub_bn(n, bntmp1, n);  // pi/2 - n
        switch_sincos = !switch_sincos;
    }
    // 0 <= n < pi/4

    // this looks redundant, but n could now be zero when it wasn't before
    if (is_bn_zero(n))
    {
        clear_bn(s);    // sin(0) = 0
        inttobn(c, 1);  // cos(0) = 1
        return s;
    }

    // at this point, the double angle trig identities could be used as many
    // times as desired to reduce the range to pi/8, pi/16, etc...  Each time
    // the range is cut in half, the number of iterations required is reduced
    // by "quite a bit."  It's just a matter of testing to see what gives the
    // optimal results.
    // halves = bnlength / 10; */ /* this is experimental
    int halves = 1;
    for (int i = 0; i < halves; i++)
        half_a_bn(n);
#endif

    // use Taylor Series (very slow convergence)
    copy_bn(s, n); // start with s=n
    inttobn(c, 1); // start with c=1
    copy_bn(bntmp1, n); // the current x^n/n!

    while (true)
    {
        // even terms for cosine
        unsafe_mult_bn(bntmp2, bntmp1, n);
        copy_bn(bntmp1, bntmp2+shiftfactor);
        div_a_bn_int(bntmp1, fact++);
        if (!is_bn_not_zero(bntmp1))
            break; // too small to register
        if (k) // alternate between adding and subtracting
            add_a_bn(c, bntmp1);
        else
            sub_a_bn(c, bntmp1);

        // odd terms for sine
        unsafe_mult_bn(bntmp2, bntmp1, n);
        copy_bn(bntmp1, bntmp2+shiftfactor);
        div_a_bn_int(bntmp1, fact++);
        if (!is_bn_not_zero(bntmp1))
            break; // too small to register
        if (k) // alternate between adding and subtracting
            add_a_bn(s, bntmp1);
        else
            sub_a_bn(s, bntmp1);
        k = !k; // toggle
#ifdef CALCULATING_BIG_PI
        printf("."); // lets you know it's doing something
#endif
    }

#ifndef CALCULATING_BIG_PI
    // now need to undo what was done by cutting angles in half
    inttobn(bntmp1, 1);
    for (int i = 0; i < halves; i++)
    {
        unsafe_mult_bn(bntmp2, s, c); // no need for safe mult
        double_bn(s, bntmp2+shiftfactor); // sin(2x) = 2*sin(x)*cos(x)
        unsafe_square_bn(bntmp2, c);
        double_a_bn(bntmp2+shiftfactor);
        sub_bn(c, bntmp2+shiftfactor, bntmp1); // cos(2x) = 2*cos(x)*cos(x) - 1
    }

    if (switch_sincos)
    {
        copy_bn(bntmp1, s);
        copy_bn(s, c);
        copy_bn(c, bntmp1);
    }
    if (signsin)
        neg_a_bn(s);
    if (signcos)
        neg_a_bn(c);
#endif

    return s; // return sine I guess
}
// r = 1/n
// uses bntmp1 - bntmp3 - global temp bignumbers
//  SIDE-EFFECTS:
//      n ends up as |n|    Make copy first if necessary.
bn_t unsafe_inv_bn(bn_t r, bn_t n)
{
    long maxval;
    LDBL f;
    bn_t orig_r, orig_n; // orig_bntmp1 not needed here
    int  orig_bnlength,
         orig_padding,
         orig_rlength,
         orig_shiftfactor;

    // use Newton's recursive method for zeroing in on 1/n : r=r(2-rn)

    bool signflag = false;
    if (is_bn_neg(n))
    {   // will be a lot easier to deal with just positives
        signflag = true;
        neg_a_bn(n);
    }

    f = bntofloat(n);
    if (f == 0) // division by zero
    {
        max_bn(r);
        return r;
    }
    f = 1/f; // approximate inverse
    maxval = (1L << ((intlength << 3)-1)) - 1;
    if (f > maxval) // check for overflow
    {
        max_bn(r);
        return r;
    }
    else if (f <= -maxval)
    {
        max_bn(r);
        neg_a_bn(r);
        return r;
    }

    // With Newton's Method, there is no need to calculate all the digits
    // every time.  The precision approximately doubles each iteration.
    // Save original values.
    orig_bnlength      = bnlength;
    orig_padding       = padding;
    orig_rlength       = rlength;
    orig_shiftfactor   = shiftfactor;
    orig_r             = r;
    orig_n             = n;
    // orig_bntmp1        = bntmp1;

    // calculate new starting values
    bnlength = intlength + (int)(LDBL_DIG/LOG10_256) + 1; // round up
    if (bnlength > orig_bnlength)
        bnlength = orig_bnlength;
    calc_lengths();

    // adjust pointers
    r = orig_r + orig_bnlength - bnlength;
    // bntmp1 = orig_bntmp1 + orig_bnlength - bnlength;

    floattobn(r, f); // start with approximate inverse
    clear_bn(bntmp2); // will be used as 1.0 and 2.0

    for (int i = 0; i < 25; i++) // safety net, this shouldn't ever be needed
    {
        // adjust lengths
        bnlength <<= 1; // double precision
        if (bnlength > orig_bnlength)
            bnlength = orig_bnlength;
        calc_lengths();
        r = orig_r + orig_bnlength - bnlength;
        n = orig_n + orig_bnlength - bnlength;
        // bntmp1 = orig_bntmp1 + orig_bnlength - bnlength;

        unsafe_mult_bn(bntmp1, r, n); // bntmp1=rn
        inttobn(bntmp2, 1);  // bntmp2 = 1.0
        if (bnlength == orig_bnlength && cmp_bn(bntmp2, bntmp1+shiftfactor) == 0)  // if not different
            break;  // they must be the same
        inttobn(bntmp2, 2); // bntmp2 = 2.0
        sub_bn(bntmp3, bntmp2, bntmp1+shiftfactor); // bntmp3=2-rn
        unsafe_mult_bn(bntmp1, r, bntmp3); // bntmp1=r(2-rn)
        copy_bn(r, bntmp1+shiftfactor); // r = bntmp1
    }

    // restore original values
    bnlength      = orig_bnlength;
    padding       = orig_padding;
    rlength       = orig_rlength;
    shiftfactor   = orig_shiftfactor;
    r             = orig_r;

    if (signflag)
    {
        neg_a_bn(r);
    }
    return r;
}
bool MandelbnSetup()
{
    // this should be set up dynamically based on corners
    bn_t bntemp1, bntemp2;
    int saved;
    saved = save_stack();
    bntemp1 = alloc_stack(bnlength);
    bntemp2 = alloc_stack(bnlength);

    bftobn(bnxmin, bfxmin);
    bftobn(bnxmax, bfxmax);
    bftobn(bnymin, bfymin);
    bftobn(bnymax, bfymax);
    bftobn(bnx3rd, bfx3rd);
    bftobn(bny3rd, bfy3rd);

    bf_math = bf_math_type::BIGNUM;

    // bnxdel = (bnxmax - bnx3rd)/(xdots-1)
    sub_bn(bnxdel, bnxmax, bnx3rd);
    div_a_bn_int(bnxdel, (U16)(xdots - 1));

    // bnydel = (bnymax - bny3rd)/(ydots-1)
    sub_bn(bnydel, bnymax, bny3rd);
    div_a_bn_int(bnydel, (U16)(ydots - 1));

    // bnxdel2 = (bnx3rd - bnxmin)/(ydots-1)
    sub_bn(bnxdel2, bnx3rd, bnxmin);
    div_a_bn_int(bnxdel2, (U16)(ydots - 1));

    // bnydel2 = (bny3rd - bnymin)/(xdots-1)
    sub_bn(bnydel2, bny3rd, bnymin);
    div_a_bn_int(bnydel2, (U16)(xdots - 1));

    abs_bn(bnclosenuff, bnxdel);
    if (cmp_bn(abs_bn(bntemp1, bnxdel2), bnclosenuff) > 0)
        copy_bn(bnclosenuff, bntemp1);
    if (cmp_bn(abs_bn(bntemp1, bnydel), abs_bn(bntemp2, bnydel2)) > 0)
    {
        if (cmp_bn(bntemp1, bnclosenuff) > 0)
            copy_bn(bnclosenuff, bntemp1);
    }
    else if (cmp_bn(bntemp2, bnclosenuff) > 0)
        copy_bn(bnclosenuff, bntemp2);
    {
        int t;
        t = abs(periodicitycheck);
        while (t--)
            half_a_bn(bnclosenuff);
    }

    c_exp = (int)param[2];
    switch (fractype)
    {
    case fractal_type::JULIAFP:
        bftobn(bnparm.x, bfparms[0]);
        bftobn(bnparm.y, bfparms[1]);
        break;
    case fractal_type::FPMANDELZPOWER:
        init_big_pi();
        if ((double)c_exp == param[2] && (c_exp & 1)) // odd exponents
            symmetry = symmetry_type::XY_AXIS_NO_PARAM;
        if (param[3] != 0)
            symmetry = symmetry_type::NONE;
        break;
    case fractal_type::FPJULIAZPOWER:
        init_big_pi();
        bftobn(bnparm.x, bfparms[0]);
        bftobn(bnparm.y, bfparms[1]);
        if ((c_exp & 1) || param[3] != 0.0 || (double)c_exp != param[2])
            symmetry = symmetry_type::NONE;
        break;
    default:
        break;
    }

    restore_stack(saved);
    return true;
}
Beispiel #8
0
	t_bignum operator - (const t_bignum& bn) const { return (sub_bn(*this, bn));        }