static DEC_TYPE IEEE_FUNCTION_NAME (DEC_TYPE x) { decContext context; decNumber dn_result; DEC_TYPE result; decNumber dn_x; decNumber dn_one; decNumber dn_exponent; DEC_TYPE one = DFP_CONSTANT(1.0); FUNC_CONVERT_TO_DN(&x, &dn_x); FUNC_CONVERT_TO_DN(&one, &dn_one); if (decNumberIsNaN (&dn_x)) return x+x; if (decNumberIsInfinite (&dn_x)) return decNumberIsNegative (&dn_x) ? DFP_CONSTANT(-1.0) : x; decContextDefault(&context, DEFAULT_CONTEXT); decNumberExp(&dn_exponent, &dn_x, &context); decNumberSubtract(&dn_result, &dn_exponent, &dn_one, &context); FUNC_CONVERT_FROM_DN(&dn_result, &result, &context); if (context.status & DEC_Overflow) DFP_EXCEPT (FE_OVERFLOW); return result; }
static DEC_TYPE IEEE_FUNCTION_NAME (DEC_TYPE x) { decContext context; decNumber dn_result; DEC_TYPE result; decNumber dn_x; decNumber dn_two; DEC_TYPE two = DFP_CONSTANT(2.0); FUNC_CONVERT_TO_DN (&two, &dn_two); FUNC_CONVERT_TO_DN (&x, &dn_x); if (decNumberIsNaN (&dn_x)) return x+x; if (decNumberIsInfinite (&dn_x) ) return decNumberIsNegative (&dn_x) ? DFP_CONSTANT(0.0) : x; decContextDefault (&context, DEFAULT_CONTEXT); /* decNumberPow (&dn_result, &dn_two, &dn_x, &context); */ decNumberPower (&dn_result, &dn_two, &dn_x, &context); FUNC_CONVERT_FROM_DN (&dn_result, &result, &context); if(context.status & DEC_Overflow) DFP_EXCEPT (FE_OVERFLOW); return result; }
DEC_TYPE INTERNAL_FUNCTION_NAME (DEC_TYPE x) { DEC_TYPE z = IEEE_FUNCTION_NAME (x); if (x > DFP_CONSTANT(1.0) || x < DFP_CONSTANT(-1.0)) DFP_ERRNO (EDOM); return z; }
DEC_TYPE INTERNAL_FUNCTION_NAME (DEC_TYPE x) { DEC_TYPE z = IEEE_FUNCTION_NAME (x); if (x == DFP_CONSTANT(0.0)) DFP_ERRNO (ERANGE); if (x < DFP_CONSTANT(0.0)) DFP_ERRNO (EDOM); return z; }
DEC_TYPE INTERNAL_FUNCTION_NAME (DEC_TYPE x) { DEC_TYPE z = IEEE_FUNCTION_NAME (x); if (x < DFP_CONSTANT(-1.0) || x > DFP_CONSTANT(1.0)) DFP_ERRNO (EDOM); /* The normal glibc ieee754 k_standard.c file does not follow c99 or POSIX * with regard to atanh pole errors. atan(+-1.0) [the binary version] will * set errno to EDOM. Hopefully this will get worked out soon. */ if (x == DFP_CONSTANT(-1.0) || x == DFP_CONSTANT(1.0)) DFP_ERRNO (ERANGE); return z; }
DEC_TYPE INTERNAL_FUNCTION_NAME (DEC_TYPE x) { decContext context; decNumber dn_result; DEC_TYPE result, one; decNumber dn_x, dn_one; one = DFP_CONSTANT(1.0); FUNC_CONVERT_TO_DN (&one, &dn_one); FUNC_CONVERT_TO_DN (&x, &dn_x); if (decNumberIsNaN (&dn_x) || decNumberIsZero (&dn_x) || decNumberIsInfinite (&dn_x)) { return x + x; } decContextDefault (&context, DEFAULT_CONTEXT); /* using trig identity: acosh(x) = log(x+sqrt(x*x-1)) */ decNumberMultiply (&dn_result, &dn_x, &dn_x, &context); decNumberAdd (&dn_result, &dn_result, &dn_one, &context); decNumberSquareRoot (&dn_result, &dn_result, &context); decNumberAdd (&dn_result, &dn_result, &dn_x, &context); decNumberLn (&dn_result, &dn_result, &context); FUNC_CONVERT_FROM_DN (&dn_result, &result, &context); return result; }
DEC_TYPE INTERNAL_FUNCTION_NAME (DEC_TYPE x, DEC_TYPE y) { DEC_TYPE z = IEEE_FUNCTION_NAME (x, y); /* Pole error: x = 0, y < 0 (non-inf). Set ERANGE in accordance with C99 */ if (x == DFP_CONSTANT(0.0) && FUNC_D(__isfinite)(y) && y < DFP_CONSTANT(0.0)) DFP_ERRNO (ERANGE); if (!FUNC_D(__isfinite) (z) && FUNC_D(__isfinite) (x) && FUNC_D(__isfinite) (y)) { if (FUNC_D(__isnan) (z)) /* Domain error was triggered, x < 0 and y was not an odd int */ DFP_ERRNO (EDOM); else /* Overflow */ DFP_ERRNO (ERANGE); } return z; }
DEC_TYPE INTERNAL_FUNCTION_NAME (DEC_TYPE x) { DEC_TYPE z = IEEE_FUNCTION_NAME (x); if (!FUNC_D(__isfinite) (z) && FUNC_D(__isfinite) (x)) DFP_ERRNO (ERANGE); if (x < DFP_CONSTANT(0.0) && (FUNC_D (__isinf) (x) && FUNC_D (__rint) (x) == x) ) DFP_ERRNO (EDOM); return z; }
static DEC_TYPE IEEE_FUNCTION_NAME (DEC_TYPE x) { decContext context; decNumber dn_result; DEC_TYPE result, one, temp; decNumber dn_x, dn_temp, dn_one; /* int comp;*/ one=DFP_CONSTANT(1.0); FUNC_CONVERT_TO_DN (&one, &dn_one); FUNC_CONVERT_TO_DN (&x, &dn_x); /* Handle NaN and early exit for x==0 */ if (decNumberIsNaN (&dn_x) || decNumberIsZero (&dn_x)) return x + x; decContextDefault (&context, DEFAULT_CONTEXT); decNumberAbs (&dn_temp, &dn_x, &context); FUNC_CONVERT_FROM_DN (&dn_temp, &temp, &context); if(temp==one) { /* |x| == 1 -> Pole Error */ DFP_EXCEPT (FE_DIVBYZERO); return decNumberIsNegative(&dn_x) ? -DFP_HUGE_VAL:DFP_HUGE_VAL; } else if (temp>one) { /* |x| > 1 -> Domain Error (this handles +-Inf too) */ DFP_EXCEPT (FE_INVALID); return DFP_NAN; } // comp = decCompare (&dn_temp, &dn_one); // switch (comp) // { // case 0: /* |x| == 1 -> Pole Error */ // DFP_EXCEPT (FE_DIVBYZERO); // return decNumberIsNegative(&dn_x) ? -DFP_HUGE_VAL:DFP_HUGE_VAL; // case 1: /* |x| > 1 -> Domain Error (this handles +-Inf too) */ // DFP_EXCEPT (FE_INVALID); // return DFP_NAN; // } /* Using trig identity: atanh(x) = 1/2 * log((1+x)/(1-x)) */ decNumberAdd (&dn_result, &dn_one, &dn_x, &context); decNumberSubtract (&dn_temp, &dn_one, &dn_x, &context); decNumberDivide (&dn_result, &dn_result, &dn_temp, &context); decNumberLn (&dn_result, &dn_result, &context); decNumberAdd (&dn_temp, &dn_one, &dn_one, &context); /* 2 */ decNumberDivide (&dn_result, &dn_result, &dn_temp, &context); FUNC_CONVERT_FROM_DN (&dn_result, &result, &context); return result; }
static DEC_TYPE IEEE_FUNCTION_NAME (DEC_TYPE x) { DEC_TYPE result, gamma; int local_signgam; if (x == DFP_CONSTANT(0.0)) /* Pole error if x== +-0 */ { DFP_EXCEPT (FE_DIVBYZERO); // return FUNC_D (__builtin_signbit) (x) ? -DFP_HUGE_VAL : DFP_HUGE_VAL; return (x<0) ? -DFP_HUGE_VAL : DFP_HUGE_VAL; } if (x < DFP_CONSTANT(0.0) && (!FUNC_D (__isinf) (x) && FUNC_D (__rint) (x) == x) ) { DFP_EXCEPT (FE_INVALID); return DFP_NAN; } gamma = FUNC_D(__lgamma_r) (x,&local_signgam); result = local_signgam * FUNC_D(__exp) (gamma); return result; }
static DEC_TYPE IEEE_FUNCTION_NAME (DEC_TYPE x) { decContext context; decNumber dn_result; DEC_TYPE result; decNumber dn_x; decNumber dn_sum; decNumber dn_one; DEC_TYPE one = DFP_CONSTANT(1.0); FUNC_CONVERT_TO_DN (&x, &dn_x); FUNC_CONVERT_TO_DN (&one, &dn_one); /* For NaN, 0, or +Inf, just return x */ if (decNumberIsNaN (&dn_x) || decNumberIsZero (&dn_x) || (decNumberIsInfinite (&dn_x) && !decNumberIsNegative (&dn_x))) return x+x; decContextDefault(&context, DEFAULT_CONTEXT); decNumberAdd(&dn_sum, &dn_x, &dn_one, &context); if (decNumberIsZero(&dn_sum)) /* Pole Error if x was -1 */ { DFP_EXCEPT (FE_DIVBYZERO); return -DFP_HUGE_VAL; } if (decNumberIsNegative(&dn_sum)) /* Domain Error if x < -1 */ { DFP_EXCEPT (FE_INVALID); return DFP_NAN; } decNumberLn(&dn_result, &dn_sum, &context); FUNC_CONVERT_FROM_DN(&dn_result, &result, &context); return result; }
DEC_TYPE INTERNAL_FUNCTION_NAME (DEC_TYPE x) { int e, rem, sign; _Decimal128 z; if (! FUNC_D(__isfinite) (x)) /* cbrt(x:x=inf/nan/-inf) = x+x (for sNaN) */ return x + x; if (x == DFP_CONSTANT(0.0)) /* cbrt(0) = 0 */ return (x); if (x > DFP_CONSTANT(0.0)) sign = 1; else { sign = -1; x = -x; } z = x; /* extract power of 2, leaving mantissa between 0.5 and 1 */ x = FUNC_D(__frexp) (x, &e); /* Approximate cube root of number between .5 and 1, peak relative error = 1.2e-6 */ x = ((((1.3584464340920900529734e-1DL * x - 6.3986917220457538402318e-1DL) * x + 1.2875551670318751538055e0DL) * x - 1.4897083391357284957891e0DL) * x + 1.3304961236013647092521e0DL) * x + 3.7568280825958912391243e-1DL; /* exponent divided by 3 */ if (e >= 0) { rem = e; e /= 3; rem -= 3 * e; if (rem == 1) //x *= CBRT2; x *= CBRT10; else if (rem == 2) //x *= CBRT4; x *= CBRT100; } else { /* argument less than 1 */ e = -e; rem = e; e /= 3; rem -= 3 * e; if (rem == 1) //x *= CBRT2I; x *= CBRT10I; else if (rem == 2) //x *= CBRT4I; x *= CBRT100I; e = -e; } /* multiply by power of 2 */ x = FUNC_D(__ldexp) (x, e); /* Newton iteration */ x -= (x - (z / (x * x))) * 0.3333333333333333333333333333333333333333DL; x -= (x - (z / (x * x))) * 0.3333333333333333333333333333333333333333DL; x -= (x - (z / (x * x))) * 0.3333333333333333333333333333333333333333DL; if (sign < 0) x = -x; return (x); }
/* Core implementation of expd64(x). Separate into integer and fractional parts, where e^(i+f) == (e^i)*(e^f). We use a table lookup (expIntXDL(i)) for e^i and taylor series for e^f. Effectively: e^x = e^i * (1 + (x-i) + (((x-i)^2)/2!) + (((x-i)^3)/3!) + ...) The real expd64 will need add checks for NAN, INF and handle negative values of x. */ static DEC_TYPE IEEE_FUNCTION_NAME (DEC_TYPE val) { DEC_TYPE result, top, fraction, a, x, tp; DEC_TYPE t1, t2, t3, t4, t5, t6, t7, t8; DEC_TYPE t9, t10, t11, t12, t13, t14, t15, t16; DEC_TYPE t17, t18, t19, t20; long exp; long tmp; int neg = 0; if (__isinfd64(val)) { if (val < DFP_CONSTANT(0.0)) return DFP_CONSTANT(0.0); /* exp(-inf) = 0 */ else return val; /* exp(inf) = inf */ } if (val < DFP_CONSTANT(0.0)) { neg = 1; val = FUNC_D(__fabs) (val); } tmp = val; top = tmp; fraction = val - top; exp = tmp; if (fraction != 0.0DD) { a = top; x = val; t1 = (x - a); tp = t1 * t1; /* tp == ((x-a))^2 */ t2 = tp * __oneOverfactDD[2]; /* t2 == (((x-a))^2)/2! */ tp = tp * t1; /* tp == ((x-a))^3 */ t3 = tp * __oneOverfactDD[3]; /* t3 == (((x-a))^3)/3! */ tp = tp * t1; /* tp == ((x-a)/a)^4 */ t4 = tp * __oneOverfactDD[4]; /* t4 == (((x-a))^4)/4! */ tp = tp * t1; /* tp == ((x-a))^5 */ t5 = tp * __oneOverfactDD[5]; /* t5 == (((x-a))^5)/5! */ tp = tp * t1; /* tp == ((x-a))^6 */ t6 = tp * __oneOverfactDD[6]; /* t6 == (((x-a))^6)/6! */ tp = tp * t1; /* tp == ((x-a))^7 */ t7 = tp * __oneOverfactDD[7]; /* t7 == (((x-a))^7)/7! */ tp = tp * t1; /* tp == ((x-a))^8 */ t8 = tp * __oneOverfactDD[8]; /* t8 == (((x-a))^8)/8! */ if ( t8 > 1.0E-16DD) { tp = tp * t1; /* tp == ((x-a))^9 */ t9 = tp * __oneOverfactDD[9]; /* t9 == (((x-a))^9)/9! */ tp = tp * t1; /* tp == ((x-a))^10 */ t10 = tp * __oneOverfactDD[10]; /* t10 == (((x-a))^10)/10! */ tp = tp * t1; /* tp == ((x-a))^11 */ t11 = tp * __oneOverfactDD[11]; /* t12 == (((x-a))^11)/11! */ tp = tp * t1; /* tp == ((x-a))^12 */ t12 = tp * __oneOverfactDD[12]; /* t12 == (((x-a))^11)/12! */ if (t12 > 1.0E-16DD) { tp = tp * t1; /* tp == ((x-a))^13 */ t13 = tp * __oneOverfactDD[13]; /* t13 == (((x-a))^13)/13! */ tp = tp * t1; /* tp == ((x-a))^14 */ t14 = tp * __oneOverfactDD[14]; /* t14 == (((x-a))^14)/14! */ tp = tp * t1; /* tp == ((x-a))^15 */ t15 = tp * __oneOverfactDD[15]; /* t15 == (((x-a))^15)/15! */ tp = tp * t1; /* tp == ((x-a))^16 */ t16 = tp * __oneOverfactDD[16]; /* t16 == (((x-a))^16)/16! */ if (t12 > 1.0E-16DD) { tp = tp * t1; /* tp == ((x-a))^17 */ t17 = tp * __oneOverfactDD[17]; /* t17 == (((x-a))^17)/17! */ tp = tp * t1; /* tp == ((x-a))^18 */ t18 = tp * __oneOverfactDD[18]; /* t18 == (((x-a))^18)/18! */ tp = tp * t1; /* tp == ((x-a))^19 */ t19 = tp * __oneOverfactDD[19]; /* t19 == (((x-a))^19)/19! */ tp = tp * t1; /* tp == ((x-a))^20 */ t20 = tp * __oneOverfactDD[20]; /* t20 == (((x-a))^20)/20! */ tp = t19 + t20; tp = tp + t18; tp = tp + t17; tp = tp + t16; tp = tp + t15; } else { tp = t15 + t16; } tp = tp + t14; tp = tp + t13; tp = tp + t12; tp = tp + t11; } else { tp = t11 + t12; } tp = tp + t10; tp = tp + t9; tp = tp + t8; tp = tp + t7; } else tp = t7 + t8; /* now sum the terms from smallest to largest to avoid lose of percision */ tp = tp + t6; tp = tp + t5; tp = tp + t4; tp = tp + t3; tp = tp + t2; tp = tp + t1; tp = tp + 1.DD; if (exp!=0) result = __expIntXDL[exp] * tp; else result = tp; } else { if (exp!=0) result = __expIntXDL[exp]; else result = 1.DD; } if (neg) result = 1/result; return result; }
static DEC_TYPE IEEE_FUNCTION_NAME (DEC_TYPE x, DEC_TYPE y) { decContext context; decNumber dn_result; DEC_TYPE result; DEC_TYPE absx; decNumber dn_x; decNumber dn_absx; decNumber dn_y; decNumber dn_one; decNumber dn_two; decNumber dn_temp; decNumber dn_temp2; decNumber dn_temp3; int y_is_int; int y_is_oddint=0; int abs_x_vs_1; DEC_TYPE one = DFP_CONSTANT(1.0); DEC_TYPE two = DFP_CONSTANT(2.0); FUNC_CONVERT_TO_DN (&x, &dn_x); FUNC_CONVERT_TO_DN (&y, &dn_y); FUNC_CONVERT_TO_DN (&one, &dn_one); decContextDefault (&context, DEFAULT_CONTEXT); if (decNumberIsZero (&dn_y)) return one; if (decNumberIsNaN (&dn_x)) return x+x; decNumberAbs (&dn_absx, &dn_x, &context); FUNC_CONVERT_FROM_DN (&dn_absx, &absx, &context); if(absx<one) abs_x_vs_1 = -1; else if (absx==one) abs_x_vs_1 = 0; else abs_x_vs_1 = 1; /* abs_x_vs_1 = decCompare(&dn_absx, &dn_one); */ if(abs_x_vs_1 == 0 && !decNumberIsNegative (&dn_x)) /* If x == +1 */ return one; if (decNumberIsNaN (&dn_y)) return y+y; /* Detect if y is odd/an integer */ decNumberToIntegralValue (&dn_temp, &dn_y, &context); decNumberSubtract (&dn_temp2, &dn_temp, &dn_y, &context); y_is_int = decNumberIsZero (&dn_temp2); if (y_is_int) { FUNC_CONVERT_TO_DN (&two, &dn_two); decNumberDivide (&dn_temp, &dn_y, &dn_two, &context); decNumberToIntegralValue (&dn_temp2, &dn_temp, &context); decNumberSubtract (&dn_temp3, &dn_temp2, &dn_temp, &context); y_is_oddint = !decNumberIsZero (&dn_temp3); } /* Handle all special cases for which x = +-0 */ if (decNumberIsZero (&dn_x)) { if(decNumberIsNegative (&dn_y)) { if (decNumberIsInfinite (&dn_y)) /* +-0^-Inf = +Inf */ return -y; /* Pole Error for x = +-0, y < 0 */ DFP_EXCEPT (FE_DIVBYZERO); return decNumberIsNegative(&dn_x) && y_is_oddint ? -DFP_HUGE_VAL : DFP_HUGE_VAL; } return decNumberIsNegative(&dn_x) && y_is_oddint ? -DFP_CONSTANT(0.0) : DFP_CONSTANT(0.0); } /* Handle remaining special cases for x = +-Inf or y = +-Inf */ if (decNumberIsInfinite (&dn_x) || decNumberIsInfinite (&dn_y)) { if (abs_x_vs_1 == 0) /* If (-1)^(+-Inf) */ return one; if (abs_x_vs_1 < 0) /* x^(+-Inf), where 0<x<1 */ return decNumberIsNegative (&dn_y) ? DFP_HUGE_VAL : DFP_CONSTANT(0.0); if (decNumberIsNegative (&dn_y)) result = DFP_CONSTANT(0.0); else result = (DEC_TYPE)DEC_INFINITY; if (y_is_oddint && decNumberIsNegative(&dn_x)) result = -result; return result; } /* Domain Error: x < 0 && y is a finite non-int */ if (decNumberIsNegative (&dn_x) && !y_is_int) { DFP_EXCEPT (FE_INVALID); return DFP_NAN; } decNumberPower (&dn_result, &dn_x, &dn_y, &context); FUNC_CONVERT_FROM_DN (&dn_result, &result, &context); if (context.status & DEC_Overflow) DFP_EXCEPT (FE_OVERFLOW); if (context.status & DEC_Underflow) DFP_EXCEPT (FE_UNDERFLOW); return result; }
static DEC_TYPE IEEE_FUNCTION_NAME (DEC_TYPE val) { _Decimal64 result, top, fraction, a, x, tp; _Decimal64 t1, t2, t3, t4, t5, t6, t7, t8; _Decimal64 t9, t10, t11, t12, t13, t14, t15, t16; int exp; long tmp; if (__isnand64(val)) return val+val; if (val == DFP_CONSTANT(0.0)) { DFP_EXCEPT (FE_DIVBYZERO); return -DFP_HUGE_VAL; } if (val < DFP_CONSTANT(0.0)) { DFP_EXCEPT (FE_INVALID); return DFP_NAN; } if (__isinfd64(val)) return val; result = __frexpd64 (val, &exp); tmp = result * 100.0DD; top = tmp; top = top * 0.01DD; fraction = result - top; if (fraction != 0.00DD) { a = top; x = result; t1 = (x - a) / a; tp = t1 * t1; /* tp == ((x-a)/a)^2 */ t2 = tp / 2.0DD; /* t2 == (((x-a)/a)^2)/2 */ tp = tp * t1; /* tp == ((x-a)/a)^3 */ t3 = tp / 3.0DD; /* t3 == (((x-a)/a)^3)/3 */ tp = tp * t1; /* tp == ((x-a)/a)^4 */ t4 = tp / 4.0DD; /* t4 == (((x-a)/a)^4)/4 */ tp = tp * t1; /* tp == ((x-a)/a)^5 */ t5 = tp / 5.0DD; /* t5 == (((x-a)/a)^5)/5 */ tp = tp * t1; /* tp == ((x-a)/a)^6 */ t6 = tp / 6.0DD; /* t6 == (((x-a)/a)^6)/6 */ tp = tp * t1; /* tp == ((x-a)/a)^7 */ t7 = tp / 7.0DD; /* t7 == (((x-a)/a)^7)/7 */ tp = tp * t1; /* tp == ((x-a)/a)^8 */ t8 = tp / 8.0DD; /* t8 == (((x-a)/a)^8)/8 */ if ( t8 > 1.0E-16DD) { tp = tp * t1; /* tp == ((x-a)/a)^9 */ t9 = tp / 9.0DD; /* t9 == (((x-a)/a)^9)/9 */ tp = tp * t1; /* tp == ((x-a)/a)^10 */ t10 = tp / 10.0DD; /* t10 == (((x-a)/a)^10)/10 */ tp = tp * t1; /* tp == ((x-a)/a)^11 */ t11 = tp / 11.0DD; /* t12 == (((x-a)/a)^11)/11 */ tp = tp * t1; /* tp == ((x-a)/a)^12 */ t12 = tp / 12.0DD; /* t12 == (((x-a)/a)^11)/12 */ if (t12 > 1.0E-16DD) { tp = tp * t1; /* tp == ((x-a)/a)^13 */ t13 = tp / 13.0DD; /* t13 == (((x-a)/a)^13)/13 */ tp = tp * t1; /* tp == ((x-a)/a)^14 */ t14 = tp / 14.0DD; /* t14 == (((x-a)/a)^14)/14 */ tp = tp * t1; /* tp == ((x-a)/a)^15 */ t15 = tp / 15.0DD; /* t15 == (((x-a)/a)^15)/15 */ tp = tp * t1; /* tp == ((x-a)/a)^16 */ t16 = tp / 16.0DD; /* t16 == (((x-a)/a)^16)/16 */ tp = t15 - t16; tp = tp + (t13 - t14); tp = tp + (t11 - t12); } else { tp = t11 - t12; } tp = tp + (t9 - t10); tp = tp + (t7 - t8); } else tp = t7 - t8; /* now sum the terms from smallest to largest to avoid loss of percision */ tp = tp + (t5 - t6); tp = tp + (t3 - t4); tp = tp + (t1 - t2); if (exp!=0) result = (__LN_10 * exp) + __LN2digits[tmp] + tp; else result = __LN2digits[tmp] + tp; } else { if (exp!=0) result = (__LN_10 * exp) + __LN2digits[tmp]; else result = __LN2digits[tmp]; } return result; }