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
716
817use super :: sqrt;
18+ use super :: support:: cold_path;
919
1020#[ cfg_attr( all( test, assert_no_panic) , no_panic:: no_panic) ]
1121pub fn hypot ( x : f64 , y : f64 ) -> f64 {
@@ -22,9 +32,11 @@ fn cr_hypot(mut x: f64, mut y: f64) -> f64 {
2232 let mut ex: u64 = xi & emsk;
2333 let mut ey: u64 = yi & emsk;
2434 /* 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+
2840 /* Either x or y is NaN or Inf */
2941 let wx: u64 = xi << 1 ;
3042 let wy: u64 = yi << 1 ;
@@ -46,14 +58,18 @@ fn cr_hypot(mut x: f64, mut y: f64) -> f64 {
4658 let mut yd: u64 = v. to_bits ( ) ;
4759 ey = yd;
4860
49- if __builtin_expect ( ey >> 52 == 0 , false ) {
61+ if ey >> 52 == 0 {
62+ cold_path ( ) ;
63+
5064 if yd == 0 {
5165 return f64:: from_bits ( xd) ;
5266 }
5367
5468 ex = xd;
5569
56- if __builtin_expect ( ex >> 52 == 0 , false ) {
70+ if ex >> 52 == 0 {
71+ cold_path ( ) ;
72+
5773 if ex == 0 {
5874 return 0.0 ;
5975 }
@@ -70,7 +86,8 @@ fn cr_hypot(mut x: f64, mut y: f64) -> f64 {
7086 }
7187
7288 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 ( ) ;
7491 return __builtin_fma ( hf64 ! ( "0x1p-27" ) , v, u) ;
7592 }
7693
@@ -98,14 +115,13 @@ fn cr_hypot(mut x: f64, mut y: f64) -> f64 {
98115 ex &= 0x7ff_u64 << 52 ;
99116 let aidr: u64 = ey + ( 0x3fe_u64 << 52 ) - ex;
100117 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 ( ) ;
105120 thd = as_hypot_hard ( x, y, flag) . to_bits ( ) ;
106121 }
107122 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 ( ) ;
109125 return as_hypot_overflow ( ) ;
110126 }
111127
@@ -169,8 +185,6 @@ fn as_hypot_hard(x: f64, y: f64, flag: FExcept) -> f64 {
169185 ls *= 2 ;
170186 m2 += ( lm2 >> -ls) as u64 ;
171187 m2 |= ( ( lm2 << ( 128 + ls) ) != 0 ) as u64 ;
172- extern crate std;
173- std:: println!( "here" ) ;
174188 }
175189
176190 let k: i32 = bs + re;
@@ -179,7 +193,7 @@ fn as_hypot_hard(x: f64, y: f64, flag: FExcept) -> f64 {
179193 loop {
180194 rm += 1 + ( rm >= ( 1u64 << 53 ) ) as u64 ;
181195 let tm: u64 = rm << k;
182- let rm2: u64 = tm * tm ;
196+ let rm2: u64 = tm. wrapping_mul ( tm ) ;
183197 d = m2 as i64 - rm2 as i64 ;
184198
185199 if d <= 0 {
@@ -192,10 +206,10 @@ fn as_hypot_hard(x: f64, y: f64, flag: FExcept) -> f64 {
192206 } else {
193207 if __builtin_expect ( op == om, true ) {
194208 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 ;
196210
197211 if __builtin_expect ( d != 0 , true ) {
198- rm += d as u64 >> 63 ;
212+ rm = rm . wrapping_add ( ( d >> 63 ) as u64 ) ;
199213 } else {
200214 rm -= rm & 1 ;
201215 }
@@ -239,25 +253,31 @@ fn as_hypot_denorm(mut a: u64, mut b: u64) -> f64 {
239253 p_d = d;
240254 rm = rm. wrapping_add ( drm as u64 ) ;
241255 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 ( ) ;
244259 break ;
245260 }
246261 }
247262 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 ) ;
251266
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 ) ;
254269 } else {
270+ cold_path ( ) ;
255271 rm += rm & 1 ;
256272 }
257273 } else {
274+ cold_path ( ) ;
258275 rm += ( op > 1.0 ) as u64 ;
259276 }
277+ } else {
278+ cold_path ( ) ;
260279 }
280+
261281 let xi: u64 = rm;
262282 f64:: from_bits ( xi)
263283}
@@ -280,11 +300,6 @@ fn __builtin_fma(x: f64, y: f64, z: f64) -> f64 {
280300
281301type FExcept = u32 ;
282302
283- fn get_rounding_mode ( _flag : & mut FExcept ) -> i32 {
284- // Always nearest
285- 0
286- }
287-
288303fn set_flags ( _flag : FExcept ) { }
289304
290305fn get_flags ( ) -> FExcept {
0 commit comments