gitee.com/quant1x/num@v0.3.2/math32/asinh.go (about) 1 package math32 2 3 // The original C code, the long comment, and the constants 4 // below are from FreeBSD's /usr/src/lib/msun/src/s_asinh.c 5 // and came with this notice. The go code is a simplified 6 // version of the original C. 7 // 8 // ==================================================== 9 // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. 10 // 11 // Developed at SunPro, a Sun Microsystems, Inc. business. 12 // Permission to use, copy, modify, and distribute this 13 // software is freely granted, provided that this notice 14 // is preserved. 15 // ==================================================== 16 // 17 // 18 // asinh(x) 19 // Method : 20 // Based on 21 // asinh(x) = sign(x) * log [ |x| + sqrt(x*x+1) ] 22 // we have 23 // asinh(x) := x if 1+x*x=1, 24 // := sign(x)*(log(x)+ln2)) for large |x|, else 25 // := sign(x)*log(2|x|+1/(|x|+sqrt(x*x+1))) if|x|>2, else 26 // := sign(x)*log1p(|x| + x**2/(1 + sqrt(1+x**2))) 27 // 28 29 // Asinh returns the inverse hyperbolic sine of x. 30 // 31 // Special cases are: 32 // 33 // Asinh(±0) = ±0 34 // Asinh(±Inf) = ±Inf 35 // Asinh(NaN) = NaN 36 func Asinh(x float32) float32 { 37 const ( 38 Ln2 = 6.93147180559945286227e-01 // 0x3FE62E42FEFA39EF 39 NearZero = 1.0 / (1 << 28) // 2**-28 40 Large = 1 << 28 // 2**28 41 ) 42 // special cases 43 if IsNaN(x) || IsInf(x, 0) { 44 return x 45 } 46 sign := false 47 if x < 0 { 48 x = -x 49 sign = true 50 } 51 var temp float32 52 switch { 53 case x > Large: 54 temp = Log(x) + Ln2 // |x| > 2**28 55 case x > 2: 56 temp = Log(2*x + 1/(Sqrt(x*x+1)+x)) // 2**28 > |x| > 2.0 57 case x < NearZero: 58 temp = x // |x| < 2**-28 59 default: 60 temp = Log1p(x + x*x/(1+Sqrt(1+x*x))) // 2.0 > |x| > 2**-28 61 } 62 if sign { 63 temp = -temp 64 } 65 return temp 66 }