casinh: Use approximations for small real part and absolute imaginary part < 1 Signed-off-by: Martin Storsjö <martin@martin.st>
diff --git a/mingw-w64-crt/complex/casinh.def.h b/mingw-w64-crt/complex/casinh.def.h index 40ff675..39d20f1 100644 --- a/mingw-w64-crt/complex/casinh.def.h +++ b/mingw-w64-crt/complex/casinh.def.h
@@ -104,6 +104,37 @@ ret = __FLT_ABI(clog) (x); __real__ ret += M_LN2; } + else if (aiz < __FLT_CST(1.0) && arz <= __FLT_EPSILON) + { + /* Taylor series expansion around arz=0 for z + sqrt(z*z + 1): + c = arz + sqrt(1-aiz^2) + i*(aiz + arz*aiz / sqrt(1-aiz^2)) + O(arz^2) + Identity: clog(c) = log(|c|) + i*arg(c) + For real part of result: + |c| = 1 + arz / sqrt(1-aiz^2) + O(arz^2) (Taylor series expansion) + For imaginary part of result: + c = (arz + sqrt(1-aiz^2))/sqrt(1-aiz^2) * (sqrt(1-aiz^2) + i*aiz) + O(arz^6) + */ + __FLT_TYPE s1maiz2 = __FLT_ABI(sqrt) ((__FLT_CST(1.0)+aiz)*(__FLT_CST(1.0)-aiz)); + __real__ ret = __FLT_ABI(log1p) (arz / s1maiz2); + __imag__ ret = __FLT_ABI(atan2) (aiz, s1maiz2); + } + else if (aiz < __FLT_CST(1.0) && arz*arz <= __FLT_EPSILON) + { + /* Taylor series expansion around arz=0 for z + sqrt(z*z + 1): + c = arz + sqrt(1-aiz^2) + arz^2 / (2*(1-aiz^2)^(3/2)) + i*(aiz + arz*aiz / sqrt(1-aiz^2)) + O(arz^4) + Identity: clog(c) = log(|c|) + i*arg(c) + For real part of result: + |c| = 1 + arz / sqrt(1-aiz^2) + arz^2/(2*(1-aiz^2)) + O(arz^3) (Taylor series expansion) + For imaginary part of result: + c = 1/sqrt(1-aiz^2) * ((1-aiz^2) + arz*sqrt(1-aiz^2) + arz^2/(2*(1-aiz^2)) + i*aiz*(sqrt(1-aiz^2)+arz)) + O(arz^3) + */ + __FLT_TYPE onemaiz2 = (__FLT_CST(1.0)+aiz)*(__FLT_CST(1.0)-aiz); + __FLT_TYPE s1maiz2 = __FLT_ABI(sqrt) (onemaiz2); + __FLT_TYPE arz2red = arz * arz / __FLT_CST(2.0) / s1maiz2; + __real__ ret = __FLT_ABI(log1p) ((arz + arz2red) / s1maiz2); + __imag__ ret = __FLT_ABI(atan2) (aiz * (s1maiz2 + arz), + onemaiz2 + arz*s1maiz2 + arz2red); + } else { __real__ x = (arz - aiz) * (arz + aiz) + __FLT_CST(1.0);