Exemplo n.º 1
0
DOUBLE                            /*{ ret - tanhd(x)      }*/
tanhd
(
  DOUBLE x                        /*{ (i) - input value x }*/
)
{
    DOUBLE f, g, xnum, xden;
    DOUBLE result;
    DOUBLE sign = 1.0;

    /*{ f = |x| }*/
    f = x;
    /*{ sign = 1 }*/
    /*{ if x < 0, sign = -sign }*/
    if (x < (DOUBLE)0.0)
    {
        f = -f;
        sign = -sign;
    }

    /*{ if f > TANHDOUBLE_BIGNUM, return sign }*/
    if (f > TANHDOUBLE_BIGNUM)
    {
        return sign;
    }

    /*{ if f > ln(3)/2 }*/
    if (f > LN3_2)
    {
        /*{ result = 1 - 2/(exp(2f) + 1) }*/
        result = ADDD(f, f);
        result = expd(result);
        result = ADDD(1.0, result);
        result = DIVD(2.0, result);
        result = SUBD(1.0, result);
    }
    /*{ else f <= ln(3)/2 }*/
    else
    {
        /*{ if f < EPS, return x }*/
        if (f < LDBL_EPSILON)
        {
            result = x;
            return result;
        }

        /*{ g = f * f }*/
        g = MPYD(f, f);

        /*{ R(g) = g * P(g)/Q(g) }*/
        /*{!INDENT}*/
        /*{ P(g) = (p2 * g + p1) * g + p0 }*/
        xnum = MPYD(TANHDP_COEF2, g);
        xnum = ADDD(xnum, TANHDP_COEF1);
        xnum = MPYD(xnum, g);
        xnum = ADDD(xnum, TANHDP_COEF0);

        /*{ Q(g) = ((g + q2) * g + q1) * g + q0 }*/
        xden = ADDD(TANHDQ_COEF2, g);
        xden = MPYD(xden, g);
        xden = ADDD(xden, TANHDQ_COEF1);
        xden = MPYD(xden, g);
        xden = ADDD(xden, TANHDQ_COEF0);
        /*{!OUTDENT}*/

        /*{ result = f + f * R(g) }*/
        result = DIVD(xnum, xden);
        result = MPYD(result, g);
        result = MPYD(result, f);
        result = ADDD(result, f);

    }

    /*{ if sign < 0, result = -result }*/
    if (sign < (DOUBLE)0.0)
    {
        result = -result;
    }

    /*{ return result }*/
    return result;
}
Exemplo n.º 2
0
DOUBLE                            /*{ ret - sinhd(x)      }*/
sinhd
(
  DOUBLE x                        /*{ (i) - input value x }*/
)
{
    DOUBLE y, w, z;
    DOUBLE f, xnum, xden;
    DOUBLE result;
    DOUBLE sign = 1.0;

    /*{ y = |x| }*/
    y = x;
    /*{ sign = 1.0 }*/
    /*{ if x < 0, sign = -sign }*/
    if (x < (DOUBLE)0.0)
    {
        y = -y;
        sign = -sign;
    }

    /*{ if (y > 1.0) }*/
    if (y > (DOUBLE)1.0)
    {
        /*{ if (y > XDOUBLE_MAX_EXP) }*/
        if (y > XDOUBLE_MAX_EXP)
        {
            /*{ w = y - ln(v) }*/
            w = SUBD(y, LN_V);

            /*{ if w > XDOUBLE_MAX_EXP }*/
            if (w > XDOUBLE_MAX_EXP)
            {
                /*{ result = +1.7e308 }*/
                result = LDBL_MAX;
                /*{ if sign < 0, result = -result }*/
                if (sign < 0.0)
                {
                    result = -result;
                }
                /*{ return result }*/
                return result;
            }

            /*{ z = exp(w) }*/
            z = expd(w);

            /*{ result = (v/2) * z }*/
            /* using higher precision computation */
            result = MPYD(V_2_MINUS1, z);
            result = ADDD(result, z);
        }
        /*{ else y <= XDOUBLE_MAX_EXP }*/
        else
        {
            /*{ z = exp(y) }*/
            z = expd(y);

            /*{ result = ((z - 1 / z) / 2 }*/
            result = DIVD(-0.5, z);
            z = MPYD(0.5, z);
            result = ADDD(z, result);
        }

     }
    /*{ else y <= 1.0 }*/
    else
    {
        /*{ if y < eps, result = y }*/
        if (y < LDBL_EPSILON)
        {
            result = y;
        }
        else
        {
            /*{ result = y + y * R(x^2) }*/
            /*{!INDENT}*/
            /*{ R(f) = f*P(f)/Q(f) }*/

            /*{ f = x * x }*/
            f = MPYD(x, x);

            /*{ P(f) = ((p3 * f + p2) * f + p1) * f + p0 }*/
            xnum = MPYD(SINHDP_COEF3, f);
            xnum = ADDD(xnum, SINHDP_COEF2);
            xnum = MPYD(xnum, f);
            xnum = ADDD(xnum, SINHDP_COEF1);
            xnum = MPYD(xnum, f);
            xnum = ADDD(xnum, SINHDP_COEF0);

            /*{ Q(f) = ((f + q2) *f + q1) * f + q0 }*/
            xden = ADDD(f, SINHDQ_COEF2);
            xden = MPYD(xden, f);
            xden = ADDD(xden, SINHDQ_COEF1);
            xden = MPYD(xden, f);
            xden = ADDD(xden, SINHDQ_COEF0);
            /*{!OUTDENT}*/

            result = DIVD(xnum, xden);
            result = MPYD(result, f);
            result = MPYD(result, y);
            result = ADDD(result, y);
        }
    }

    /*{ if sign < 0, result = -result }*/
    if (sign < 0.0)
    {
        result = -result;
    }
 
    /*{ return result }*/
    return result;
}
Exemplo n.º 3
0
DOUBLE                            /*{ ret - cotd(x)       }*/
cotd
(
  DOUBLE x                        /*{ (i) - input value x }*/
)
{
    LONG n;
    DOUBLE xn;
    DOUBLE f, g;
    DOUBLE x_int, x_fract;
    DOUBLE result;
    DOUBLE xnum, xden;

    /*{ If x is outside the domain or zero, return 0.0 }*/
    if ((x > COT64_X_MAX) || (x < -COT64_X_MAX) || (x == 0.0L))
    {
        return 0.0L;
    }

    /*{ split x into x_int and x_fract for better argument reduction }*/
    x_int = TO_DOUBLE(TO_LONG(x));
    x_fract = SUBD(x, x_int);

    /*{ Reduce the input to range between -PI/4, PI/4 }*/
    /*{!INDENT}*/
    /*{ n = Rounded long x/(PI/2) }*/
    if (x > 0.0)
    {
        n = TO_LONG(ADDD(MPYD(x, INV_PI_2), 0.5));
    }
    else
    {
        n = TO_LONG(ADDD(MPYD(x, INV_PI_2), -0.5));
    }

    /*{ xn = (double)n }*/
    xn = TO_DOUBLE(n);

    /*{ f = x - xn*PI  }*/
    /* (using higher precision computation) */
    f = SUBD(x_int, MPYD(xn, PI_2_DC1));
    f = ADDD(f, x_fract);
    f = SUBD(f, MPYD(xn, PI_2_DC2));
    f = SUBD(f, MPYD(xn, PI_2_DC3));
    /*{!OUTDENT}*/

    if (f < 0.0L)
    {
        g = -f;
    }
    else
    {
        g = f;
    }
    /*{ If |f| < eps }*/
    if (g < EPS_DOUBLE)
    {
        /*{ if n is odd, return -f }*/
        if (n & 0x0001)
        {
            result = -f;
        }
        /*{ if n is even, return 1/f }*/
        else
        {
            result = DIVD(1.0L, f);
        }            
        return result;
    }

    /*{ g = f * f }*/
    g = MPYD(f, f);

    /*{ Compute sin approximation on reduced argument }*/
    /*{!INDENT}*/
    /*{ xnum = (((g * p3 + p2) * g + p1) * g * f + f }*/
    xnum = MPYD(g, TANDP_COEF3);
    xnum = ADDD(xnum, TANDP_COEF2);
    xnum = MPYD(xnum, g);
    xnum = ADDD(xnum, TANDP_COEF1);
    xnum = MPYD(xnum, g);
    xnum = MPYD(xnum, f);
    xnum = ADDD(xnum, f);

    /*{ xden = (((g * q4 + q3) * g + q2) * g +q1) * g + q0 }*/
    xden = MPYD(g, TANDQ_COEF4);
    xden = ADDD(xden, TANDQ_COEF3);
    xden = MPYD(xden, g);
    xden = ADDD(xden, TANDQ_COEF2);
    xden = MPYD(xden, g);
    xden = ADDD(xden, TANDQ_COEF1);
    xden = MPYD(xden, g);
    xden = ADDD(xden, TANDQ_COEF0);
    /*{!OUTDENT}*/

    /*{ if n is odd, result = -xnum/xden }*/
    if (n & 0x0001)
    {
        xnum = -xnum;
    }
    /*{ else n is even, result = xden/xnum }*/
    else
    {
        result = xden;
        xden = xnum;
        xnum = result;
    }            
    result = DIVD(xnum, xden);

    /*{ return result }*/
    return result;
}
Exemplo n.º 4
0
DOUBLE                            /*{ ret - acosd(x)       }*/
acosd
(
  DOUBLE x                        /*{ (i) - input value x  }*/
)
{
    DOUBLE y, g;
    DOUBLE num, den, result;
    LONG i;

    /*{ y = |x| }*/
    y = x;
    if (y < (DOUBLE)0.0)
    {
        y = -y;
    }

    /*{ if y > 0.5 }*/
    if (y > (DOUBLE)0.5)
    {
        /*{ set i = 0 }*/
        i = 0;

        /*{ if y > 0, return error }*/
        if (y > (DOUBLE)1.0)
        {
            result = 0.0;
            return result;
        }    

        /*{ g = (1 - y)/2 }*/
        g = SUBD(1.0, y);
        g = MPYD(0.5, g);

        /*{ y = -2/sqrt(g) }*/
        y = sqrtd(g);
        y = MPYD(y, -2.0);
    }
    /*{ else y <= 0.5 }*/
    else
    {
        /*{ set i = 1 }*/
        i = 1;

        /*{ if y < eps }*/
        if (y < EPS_DOUBLE)
        {
            result = y;

            /*{ if x < 0, result = PI/2 + result }*/
            /* (but more mathematically stable) */
            if (x < (DOUBLE)0.0)
            {
                result = ADDD(PI_4, result);
                result = ADDD(result, PI_4);
            }
            /*{ else x >=0, result = PI/2 - result }*/
            /* (but more mathematically stable) */
            else
            {
                result = SUBD(PI_4, result);
                result = ADDD(result, PI_4);
            }

            /*{ return result }*/
            return result;
        }

        /*{ g = y * y }*/
        g = MPYD(y, y);
    }

    /*{ result = y + y*R(g) }*/
    /*{!INDENT}*/
    /*{ R(g) = g*P(g)/Q(g) }*/
    /*{ P(g) = (((p5 * g + p4) * g + p3) * g + p2) * g + p1 }*/
    num = MPYD(ASINDP_COEF5, g);
    num = ADDD(num, ASINDP_COEF4);
    num = MPYD(num, g);
    num = ADDD(num, ASINDP_COEF3);
    num = MPYD(num, g);
    num = ADDD(num, ASINDP_COEF2);
    num = MPYD(num, g);
    num = ADDD(num, ASINDP_COEF1);
    num = MPYD(num, g);

    /*{ Q(g) = ((((g + q4) * g + q3) * g + q2) * g + q1) * g + q0 }*/
    den = ADDD(g, ASINDQ_COEF4);
    den = MPYD(den, g);
    den = ADDD(den, ASINDQ_COEF3);
    den = MPYD(den, g);
    den = ADDD(den, ASINDQ_COEF2);
    den = MPYD(den, g);
    den = ADDD(den, ASINDQ_COEF1);
    den = MPYD(den, g);
    den = ADDD(den, ASINDQ_COEF0);

    result = DIVD(num, den);
    result = MPYD(result, y);
    result = ADDD(result, y);
    /*{!OUTDENT}*/

    /*{ if x < 0 }*/
    if (x < (DOUBLE)0.0)
    {
        /*{ if i == 0, result = PI + result }*/
        /* (but more mathematically stable) */
        if (i == 0)
        {
            result = ADDD(result, PI_2);
            result = ADDD(result, PI_2);
        }
        /*{ if i == 1, result = PI/2 + result }*/
        /* (but more mathematically stable) */
        else
        {
            result = ADDD(PI_4, result);
            result = ADDD(result, PI_4);
        }
    }
    /*{ else x >= 0 }*/
    else
    {
        /*{ if i == 1, result = PI/2 - result }*/
        /* (but more mathematically stable) */
        if (i == 1)
        {
            result = SUBD(PI_4, result);
            result = ADDD(result, PI_4);
        }
        /*{ if i == 0, result = -result }*/
        else
        {
            result = -result;
        }
    }

    /*{ return result }*/
    return result;
}
Exemplo n.º 5
0
void adm_decouple_d(const adm_dwt_band_t_d *ref, const adm_dwt_band_t_d *dis, const adm_dwt_band_t_d *r, const adm_dwt_band_t_d *a, int w, int h, int ref_stride, int dis_stride, int r_stride, int a_stride)
{
#ifdef ADM_OPT_AVOID_ATAN
    const double cos_1deg_sq = cos(1.0 * M_PI / 180.0) * cos(1.0 * M_PI / 180.0);
#endif
    const double eps = 1e-30;

    int ref_px_stride = ref_stride / sizeof(double);
    int dis_px_stride = dis_stride / sizeof(double);
    int r_px_stride = r_stride / sizeof(double);
    int a_px_stride = a_stride / sizeof(double);

    double oh, ov, od, th, tv, td;
    double kh, kv, kd, tmph, tmpv, tmpd;
#ifdef ADM_OPT_AVOID_ATAN
    double ot_dp, o_mag_sq, t_mag_sq;
#else
    double oa, ta, diff;
#endif
    int angle_flag;
    int i, j;

    for (i = 0; i < h; ++i) {
        for (j = 0; j < w; ++j) {
            oh = ref->band_h[i * ref_px_stride + j];
            ov = ref->band_v[i * ref_px_stride + j];
            od = ref->band_d[i * ref_px_stride + j];
            th = dis->band_h[i * dis_px_stride + j];
            tv = dis->band_v[i * dis_px_stride + j];
            td = dis->band_d[i * dis_px_stride + j];

            kh = DIVD(th, oh + eps);
            kv = DIVD(tv, ov + eps);
            kd = DIVD(td, od + eps);

            kh = kh < 0.0 ? 0.0 : (kh > 1.0 ? 1.0 : kh);
            kv = kv < 0.0 ? 0.0 : (kv > 1.0 ? 1.0 : kv);
            kd = kd < 0.0 ? 0.0 : (kd > 1.0 ? 1.0 : kd);

            tmph = kh * oh;
            tmpv = kv * ov;
            tmpd = kd * od;
#ifdef ADM_OPT_AVOID_ATAN
            /* Determine if angle between (oh,ov) and (th,tv) is less than 1 degree.
             * Given that u is the angle (oh,ov) and v is the angle (th,tv), this can
             * be done by testing the inequvality.
             *
             * { (u.v.) >= 0 } AND { (u.v)^2 >= cos(1deg)^2 * ||u||^2 * ||v||^2 }
             *
             * Proof:
             *
             * cos(theta) = (u.v) / (||u|| * ||v||)
             *
             * IF u.v >= 0 THEN
             *   cos(theta)^2 = (u.v)^2 / (||u||^2 * ||v||^2)
             *   (u.v)^2 = cos(theta)^2 * ||u||^2 * ||v||^2
             *
             *   IF |theta| < 1deg THEN
             *     (u.v)^2 >= cos(1deg)^2 * ||u||^2 * ||v||^2
             *   END
             * ELSE
             *   |theta| > 90deg
             * END
             */
            ot_dp = oh * th + ov * tv;
            o_mag_sq = oh * oh + ov * ov;
            t_mag_sq = th * th + tv * tv;

            angle_flag = (ot_dp >= 0.0) && (ot_dp * ot_dp >= cos_1deg_sq * o_mag_sq * t_mag_sq);
#else
            oa = atan(DIVD(ov, oh + eps));
            ta = atan(DIVD(tv, th + eps));

            if (oh < 0.0)
                oa += M_PI;
            if (th < 0.0)
                ta += M_PI;

            diff = fabs(oa - ta) * 180.0 / M_PI;
            angle_flag = diff < 1.0;
#endif
            if (angle_flag) {
                tmph = th;
                tmpv = tv;
                tmpd = td;
            }

            r->band_h[i * r_px_stride + j] = tmph;
            r->band_v[i * r_px_stride + j] = tmpv;
            r->band_d[i * r_px_stride + j] = tmpd;

            a->band_h[i * a_px_stride + j] = th - tmph;
            a->band_v[i * a_px_stride + j] = tv - tmpv;
            a->band_d[i * a_px_stride + j] = td - tmpd;
        }
    }
}