-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathasinh128.go
More file actions
127 lines (120 loc) · 3.15 KB
/
Copy pathasinh128.go
File metadata and controls
127 lines (120 loc) · 3.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package floats
// Asinh returns the inverse hyperbolic sine of a.
//
// Special cases are:
//
// ±0.Asinh() = ±0
// ±Inf.Asinh() = ±Inf
// NaN.Asinh() = NaN
func (a Float128) Asinh() Float128 {
// https://github.com/chewxy/math32/blob/912ef0b2e4151df0148d7645c92a7b5e22f887f5/asinh.go#L36-L66
var (
Ln2 = Float128{0x3ffe_62e4_2fef_a39e, 0xf357_93c7_6730_07e6} // 6.93147180559945286227e-01
Zero = Float128{} // 0.0
One = Float128(uvone128) // 1.0
Two = Float128{0x4000_0000_0000_0000, 0x0000_0000_0000_0000} // 2.0
NearZero = Float128{0x3fc5_0000_0000_0000, 0x0000_0000_0000_0000} // 2**-58
Large = Float128{0x4039_0000_0000_0000, 0x0000_0000_0000_0000} // 2**58
)
// special cases
if a.IsNaN() || a.IsInf(0) {
return a
}
sign := false
if a.Lt(Zero) {
a = a.Neg()
sign = true
}
var temp Float128
switch {
case a.Gt(Large):
temp = a.Log().Add(Ln2) // |a| > 2**58
case a.Gt(Two):
temp = (a.Add(a).Add(One.Quo((a.Mul(a).Add(One)).Sqrt().Add(a)))).Log() // 2**58 > |a| > 2.0
case a.Lt(NearZero):
temp = a // |a| < 2**-58
default:
a2 := a.Mul(a)
temp = (a.Add(a2.Quo(One.Add(One.Add(a2).Sqrt())))).Log1p() // 2.0 > |a| > 2**-58
}
if sign {
temp = temp.Neg()
}
return temp
}
// Acosh returns the inverse hyperbolic cosine of a.
//
// Special cases are:
//
// +Inf.Acosh() = +Inf
// x.Acosh() = NaN if x < 1
// NaN.Acosh() = NaN
func (a Float128) Acosh() Float128 {
var (
Ln2 = Float128{0x3ffe_62e4_2fef_a39e, 0xf357_93c7_6730_07e6} // 6.93147180559945286227e-01
One = Float128(uvone128) // 1.0
Two = Float128{0x4000_0000_0000_0000, 0x0000_0000_0000_0000} // 2.0
Large = Float128{0x4039_0000_0000_0000, 0x0000_0000_0000_0000} // 2**58
)
switch {
case a.Lt(One) || a.IsNaN():
return NewFloat128NaN()
case a.Eq(One):
return Float128{}
case a.Ge(Large):
return a.Log().Add(Ln2) // a > 2**58
case a.Gt(Two):
return (a.Add((a.Mul(a).Sub(One)).Sqrt())).Log() // 2**58 > a > 2.0
}
t := a.Sub(One)
return (t.Add((t.Mul(t).Add(Two.Mul(t))).Sqrt())).Log1p() // 2 >= a > 1
}
// Atanh returns the inverse hyperbolic tangent of a.
//
// Special cases are:
//
// 1.Atanh() = +Inf
// ±0.Atanh() = ±0
// -1.Atanh() = -Inf
// x.Atanh() = NaN if x < -1 or x > 1
// NaN.Atanh() = NaN
func (a Float128) Atanh() Float128 {
var (
// Zero = 0.0
Zero = Float128{}
// Half = 0.5
Half = Float128{0x3ffe_0000_0000_0000, 0x0000_0000_0000_0000}
// One = 1.0
One = Float128(uvone128)
// NearZero = 2**-58
NearZero = Float128{0x3fc5_0000_0000_0000, 0x0000_0000_0000_0000}
)
// special cases
switch {
case a.Lt(One.Neg()) || a.Gt(One) || a.IsNaN():
return NewFloat128NaN()
case a.Eq(One):
return NewFloat128Inf(1)
case a.Eq(One.Neg()):
return NewFloat128Inf(-1)
}
sign := false
if a.Lt(Zero) {
a = a.Neg()
sign = true
}
var temp Float128
switch {
case a.Lt(NearZero):
temp = a
case a.Lt(Half):
temp = a.Add(a)
temp = Half.Mul(temp.Add(temp.Mul(a).Quo(One.Sub(a))).Log1p())
default:
temp = Half.Mul((a.Add(a).Quo(One.Sub(a))).Log1p())
}
if sign {
temp = temp.Neg()
}
return temp
}