File tree 5 files changed +71
-3
lines changed
5 files changed +71
-3
lines changed Original file line number Diff line number Diff line change @@ -414,7 +414,6 @@ pub trait F64Ext: private::Sealed {
414
414
415
415
fn ln_1p ( self ) -> Self ;
416
416
417
- #[ cfg( todo) ]
418
417
fn sinh ( self ) -> Self ;
419
418
420
419
#[ cfg( todo) ]
@@ -595,7 +594,6 @@ impl F64Ext for f64 {
595
594
log1p ( self )
596
595
}
597
596
598
- #[ cfg( todo) ]
599
597
#[ inline]
600
598
fn sinh ( self ) -> Self {
601
599
sinh ( self )
Original file line number Diff line number Diff line change
1
+ use super :: { combine_words, exp} ;
2
+
3
+ /* exp(x)/2 for x >= log(DBL_MAX), slightly better than 0.5*exp(x/2)*exp(x/2) */
4
+ pub ( crate ) fn expo2 ( x : f64 ) -> f64 {
5
+ /* k is such that k*ln2 has minimal relative error and x - kln2 > log(DBL_MIN) */
6
+ const K : i32 = 2043 ;
7
+ let kln2 = f64:: from_bits ( 0x40962066151add8b ) ;
8
+
9
+ /* note that k is odd and scale*scale overflows */
10
+ let scale = combine_words ( ( ( 0x3ff + K / 2 ) as u32 ) << 20 , 0 ) ;
11
+ /* exp(x - k ln2) * 2**(k-1) */
12
+ return exp ( x - kln2) * scale * scale;
13
+ }
Original file line number Diff line number Diff line change @@ -50,6 +50,7 @@ mod scalbn;
50
50
mod scalbnf;
51
51
mod sin;
52
52
mod sinf;
53
+ mod sinh;
53
54
mod sqrt;
54
55
mod sqrtf;
55
56
mod tanf;
@@ -100,13 +101,15 @@ pub use self::scalbn::scalbn;
100
101
pub use self :: scalbnf:: scalbnf;
101
102
pub use self :: sin:: sin;
102
103
pub use self :: sinf:: sinf;
104
+ pub use self :: sinh:: sinh;
103
105
pub use self :: sqrt:: sqrt;
104
106
pub use self :: sqrtf:: sqrtf;
105
107
pub use self :: tanf:: tanf;
106
108
pub use self :: trunc:: trunc;
107
109
pub use self :: truncf:: truncf;
108
110
109
111
// Private modules
112
+ mod expo2;
110
113
mod k_cos;
111
114
mod k_cosf;
112
115
mod k_sin;
@@ -117,6 +120,7 @@ mod rem_pio2_large;
117
120
mod rem_pio2f;
118
121
119
122
// Private re-imports
123
+ use self :: expo2:: expo2;
120
124
use self :: k_cos:: k_cos;
121
125
use self :: k_cosf:: k_cosf;
122
126
use self :: k_sin:: k_sin;
@@ -151,3 +155,8 @@ pub fn with_set_low_word(f: f64, lo: u32) -> f64 {
151
155
tmp |= lo as u64 ;
152
156
f64:: from_bits ( tmp)
153
157
}
158
+
159
+ #[ inline]
160
+ fn combine_words ( hi : u32 , lo : u32 ) -> f64 {
161
+ f64:: from_bits ( ( hi as u64 ) << 32 | lo as u64 )
162
+ }
Original file line number Diff line number Diff line change
1
+ use super :: { expm1, expo2} ;
2
+
3
+ // sinh(x) = (exp(x) - 1/exp(x))/2
4
+ // = (exp(x)-1 + (exp(x)-1)/exp(x))/2
5
+ // = x + x^3/6 + o(x^5)
6
+ //
7
+ pub fn sinh ( x : f64 ) -> f64 {
8
+ // union {double f; uint64_t i;} u = {.f = x};
9
+ // uint32_t w;
10
+ // double t, h, absx;
11
+
12
+ let mut uf: f64 = x;
13
+ let mut ui: u64 = f64:: to_bits ( uf) ;
14
+ let w: u32 ;
15
+ let t: f64 ;
16
+ let mut h: f64 ;
17
+ let absx: f64 ;
18
+
19
+ h = 0.5 ;
20
+ if ui >> 63 != 0 {
21
+ h = -h;
22
+ }
23
+ /* |x| */
24
+ ui &= !1 / 2 ;
25
+ uf = f64:: from_bits ( ui) ;
26
+ absx = uf;
27
+ w = ( ui >> 32 ) as u32 ;
28
+
29
+ /* |x| < log(DBL_MAX) */
30
+ if w < 0x40862e42 {
31
+ t = expm1 ( absx) ;
32
+ if w < 0x3ff00000 {
33
+ if w < 0x3ff00000 - ( 26 << 20 ) {
34
+ /* note: inexact and underflow are raised by expm1 */
35
+ /* note: this branch avoids spurious underflow */
36
+ return x;
37
+ }
38
+ return h * ( 2.0 * t - t * t / ( t + 1.0 ) ) ;
39
+ }
40
+ /* note: |x|>log(0x1p26)+eps could be just h*exp(x) */
41
+ return h * ( t + t / ( t + 1.0 ) ) ;
42
+ }
43
+
44
+ /* |x| > log(DBL_MAX) or nan */
45
+ /* note: the result is stored to handle overflow */
46
+ t = 2.0 * h * expo2 ( absx) ;
47
+ return t;
48
+ }
Original file line number Diff line number Diff line change @@ -714,7 +714,7 @@ f64_f64! {
714
714
log2,
715
715
round,
716
716
sin,
717
- // sinh,
717
+ sinh,
718
718
sqrt,
719
719
// tan,
720
720
// tanh,
You can’t perform that action at this time.
0 commit comments