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; }
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; }
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; }
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; }
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; } } }