1
- /*
2
- Copyright (c) 2022 Alexei Sibidanov.
3
-
4
- This file is part of the CORE-MATH project
5
- (https://core-math.gitlabpages.inria.fr/).
6
- */
1
+ /* SPDX-License-Identifier: MIT */
2
+ /* origin: core-math/src/binary64/hypot/hypot.c
3
+ * Copyright (c) 2022 Alexei Sibidanov.
4
+ * Ported to Rust in 2025 by Trevor Gross.
5
+ */
6
+
7
+ //! Euclidian distance via the pythagorean theorem (`√(x2 + y2)`).
8
+ //!
9
+ //! Per IEEE 754-2019:
10
+ //!
11
+ //! - Domain: `[−∞, +∞] × [−∞, +∞]`
12
+ //! - `hypot(±0, ±0)` is +0
13
+ //! - `hypot(±∞, qNaN)` is +∞
14
+ //! - `hypot(qNaN, ±∞)` is +∞.
15
+ //! - May raise overflow or underflow
7
16
8
17
use super :: sqrt;
18
+ use super :: support:: cold_path;
9
19
10
20
#[ cfg_attr( all( test, assert_no_panic) , no_panic:: no_panic) ]
11
21
pub fn hypot ( x : f64 , y : f64 ) -> f64 {
@@ -22,9 +32,11 @@ fn cr_hypot(mut x: f64, mut y: f64) -> f64 {
22
32
let mut ex: u64 = xi & emsk;
23
33
let mut ey: u64 = yi & emsk;
24
34
/* emsk corresponds to the upper bits of NaN and Inf (apart the sign bit) */
25
- x = __builtin_fabs ( x) ;
26
- y = __builtin_fabs ( y) ;
27
- if __builtin_expect ( ex == emsk || ey == emsk, false ) {
35
+ x = x. abs ( ) ;
36
+ y = y. abs ( ) ;
37
+ if ex == emsk || ey == emsk {
38
+ cold_path ( ) ;
39
+
28
40
/* Either x or y is NaN or Inf */
29
41
let wx: u64 = xi << 1 ;
30
42
let wy: u64 = yi << 1 ;
@@ -46,14 +58,18 @@ fn cr_hypot(mut x: f64, mut y: f64) -> f64 {
46
58
let mut yd: u64 = v. to_bits ( ) ;
47
59
ey = yd;
48
60
49
- if __builtin_expect ( ey >> 52 == 0 , false ) {
61
+ if ey >> 52 == 0 {
62
+ cold_path ( ) ;
63
+
50
64
if yd == 0 {
51
65
return f64:: from_bits ( xd) ;
52
66
}
53
67
54
68
ex = xd;
55
69
56
- if __builtin_expect ( ex >> 52 == 0 , false ) {
70
+ if ex >> 52 == 0 {
71
+ cold_path ( ) ;
72
+
57
73
if ex == 0 {
58
74
return 0.0 ;
59
75
}
@@ -70,7 +86,8 @@ fn cr_hypot(mut x: f64, mut y: f64) -> f64 {
70
86
}
71
87
72
88
let de: u64 = xd. wrapping_sub ( yd) ;
73
- if __builtin_expect ( de > ( 27_u64 << 52 ) , false ) {
89
+ if de > ( 27_u64 << 52 ) {
90
+ cold_path ( ) ;
74
91
return __builtin_fma ( hf64 ! ( "0x1p-27" ) , v, u) ;
75
92
}
76
93
@@ -98,14 +115,13 @@ fn cr_hypot(mut x: f64, mut y: f64) -> f64 {
98
115
ex &= 0x7ff_u64 << 52 ;
99
116
let aidr: u64 = ey + ( 0x3fe_u64 << 52 ) - ex;
100
117
let mid: u64 = ( aidr. wrapping_sub ( 0x3c90000000000000 ) + 16 ) >> 5 ;
101
- if __builtin_expect (
102
- mid == 0 || aidr < 0x39b0000000000000_u64 || aidr > 0x3c9fffffffffff80_u64 ,
103
- false ,
104
- ) {
118
+ if mid == 0 || aidr < 0x39b0000000000000_u64 || aidr > 0x3c9fffffffffff80_u64 {
119
+ cold_path ( ) ;
105
120
thd = as_hypot_hard ( x, y, flag) . to_bits ( ) ;
106
121
}
107
122
thd = thd. wrapping_sub ( off as u64 ) ;
108
- if __builtin_expect ( thd >= ( 0x7ff_u64 << 52 ) , false ) {
123
+ if thd >= ( 0x7ff_u64 << 52 ) {
124
+ cold_path ( ) ;
109
125
return as_hypot_overflow ( ) ;
110
126
}
111
127
@@ -169,8 +185,6 @@ fn as_hypot_hard(x: f64, y: f64, flag: FExcept) -> f64 {
169
185
ls *= 2 ;
170
186
m2 += ( lm2 >> -ls) as u64 ;
171
187
m2 |= ( ( lm2 << ( 128 + ls) ) != 0 ) as u64 ;
172
- extern crate std;
173
- std:: println!( "here" ) ;
174
188
}
175
189
176
190
let k: i32 = bs + re;
@@ -179,7 +193,7 @@ fn as_hypot_hard(x: f64, y: f64, flag: FExcept) -> f64 {
179
193
loop {
180
194
rm += 1 + ( rm >= ( 1u64 << 53 ) ) as u64 ;
181
195
let tm: u64 = rm << k;
182
- let rm2: u64 = tm * tm ;
196
+ let rm2: u64 = tm. wrapping_mul ( tm ) ;
183
197
d = m2 as i64 - rm2 as i64 ;
184
198
185
199
if d <= 0 {
@@ -192,10 +206,10 @@ fn as_hypot_hard(x: f64, y: f64, flag: FExcept) -> f64 {
192
206
} else {
193
207
if __builtin_expect ( op == om, true ) {
194
208
let tm: u64 = ( rm << k) - ( 1 << ( k - ( rm <= ( 1u64 << 53 ) ) as i32 ) ) ;
195
- d = m2 as i64 - ( tm * tm ) as i64 ;
209
+ d = m2 as i64 - ( tm. wrapping_mul ( tm ) ) as i64 ;
196
210
197
211
if __builtin_expect ( d != 0 , true ) {
198
- rm += d as u64 >> 63 ;
212
+ rm = rm . wrapping_add ( ( d >> 63 ) as u64 ) ;
199
213
} else {
200
214
rm -= rm & 1 ;
201
215
}
@@ -239,25 +253,31 @@ fn as_hypot_denorm(mut a: u64, mut b: u64) -> f64 {
239
253
p_d = d;
240
254
rm = rm. wrapping_add ( drm as u64 ) ;
241
255
d = d. wrapping_sub ( dd) ;
242
- dd = d. wrapping_add ( 8 ) ;
243
- if !__builtin_expect ( ( d ^ p_d) > 0 , false ) {
256
+ dd = dd. wrapping_add ( 8 ) ;
257
+ if ( d ^ p_d) <= 0 {
258
+ cold_path ( ) ;
244
259
break ;
245
260
}
246
261
}
247
262
p_d = ( sd & d) + ( !sd & p_d) ;
248
- if __builtin_expect ( p_d != 0 , true ) {
249
- if __builtin_expect ( op == om, true ) {
250
- let sum: i64 = p_d. wrapping_sub ( 4_i64 . wrapping_mul ( rm as i64 ) ) . wrapping_sub ( 1 ) ;
263
+ if p_d != 0 {
264
+ if op == om {
265
+ let sum: i64 = p_d. wrapping_sub ( 4u64 . wrapping_mul ( rm) as i64 ) . wrapping_sub ( 1 ) ;
251
266
252
- if __builtin_expect ( sum != 0 , true ) {
253
- rm = rm. wrapping_add ( ( sum as u64 >> 63 ) + 1 ) ;
267
+ if sum != 0 {
268
+ rm = rm. wrapping_add ( ( sum >> 63 ) . wrapping_add ( 1 ) as u64 ) ;
254
269
} else {
270
+ cold_path ( ) ;
255
271
rm += rm & 1 ;
256
272
}
257
273
} else {
274
+ cold_path ( ) ;
258
275
rm += ( op > 1.0 ) as u64 ;
259
276
}
277
+ } else {
278
+ cold_path ( ) ;
260
279
}
280
+
261
281
let xi: u64 = rm;
262
282
f64:: from_bits ( xi)
263
283
}
@@ -280,11 +300,6 @@ fn __builtin_fma(x: f64, y: f64, z: f64) -> f64 {
280
300
281
301
type FExcept = u32 ;
282
302
283
- fn get_rounding_mode ( _flag : & mut FExcept ) -> i32 {
284
- // Always nearest
285
- 0
286
- }
287
-
288
303
fn set_flags ( _flag : FExcept ) { }
289
304
290
305
fn get_flags ( ) -> FExcept {
0 commit comments