Skip to content

Commit 8af2d8d

Browse files
fix: update hypotf to follow the IEEE 754-2019 standard
PR-URL: #6511 Reviewed-by: Athan Reines <[email protected]>
1 parent 0dc5e1f commit 8af2d8d

File tree

6 files changed

+47
-13
lines changed

6 files changed

+47
-13
lines changed

Diff for: lib/node_modules/@stdlib/math/base/special/hypotf/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ h = hypotf( -0.0, -0.0 );
5252
// returns +0.0
5353
```
5454

55-
If either argument is `NaN`, the function returns `NaN`.
55+
If either argument is `NaN` and the other argument is not `+-Infinity`, the function returns `NaN`.
5656

5757
```javascript
5858
var h = hypotf( NaN, 12.0 );

Diff for: lib/node_modules/@stdlib/math/base/special/hypotf/docs/repl.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
{{alias}}( x, y )
33
Computes the hypotenuse avoiding overflow and underflow (single-precision).
44

5-
If either argument is `NaN`, the function returns `NaN`.
5+
If either argument is `NaN` and the other argument is not `+-Infinity`,
6+
the function returns `NaN`.
67

78
Parameters
89
----------

Diff for: lib/node_modules/@stdlib/math/base/special/hypotf/lib/main.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ var float64ToFloat32 = require( '@stdlib/number/float64/base/to-float32' );
2424
var isnanf = require( '@stdlib/math/base/assert/is-nanf' );
2525
var isInfinitef = require( '@stdlib/math/base/assert/is-infinitef' );
2626
var PINF = require( '@stdlib/constants/float32/pinf' );
27-
var sqrt = require( '@stdlib/math/base/special/sqrt' );
27+
var sqrtf = require( '@stdlib/math/base/special/sqrtf' );
2828

2929

3030
// MAIN //
@@ -50,12 +50,14 @@ var sqrt = require( '@stdlib/math/base/special/sqrt' );
5050
*/
5151
function hypotf( x, y ) {
5252
var tmp;
53-
if ( isnanf( x ) || isnanf( y ) ) {
54-
return NaN;
55-
}
53+
54+
// If one of the arguments is `+-infinity`, return `+infinity` even if the other argument is `NaN` (IEEE 754-2019)...
5655
if ( isInfinitef( x ) || isInfinitef( y ) ) {
5756
return PINF;
5857
}
58+
if ( isnanf( x ) || isnanf( y ) ) {
59+
return NaN;
60+
}
5961
x = float64ToFloat32( x );
6062
y = float64ToFloat32( y );
6163
if ( x < 0.0 ) {
@@ -73,7 +75,7 @@ function hypotf( x, y ) {
7375
return 0.0;
7476
}
7577
y = float64ToFloat32( y / x );
76-
return float64ToFloat32( x * float64ToFloat32( sqrt( float64ToFloat32( 1.0 + float64ToFloat32(y*y) ) ) ) ); // eslint-disable-line max-len
78+
return float64ToFloat32( x * sqrtf( float64ToFloat32( 1.0 + float64ToFloat32(y*y) ) ) ); // eslint-disable-line max-len
7779
}
7880

7981

Diff for: lib/node_modules/@stdlib/math/base/special/hypotf/src/main.c

+5-3
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ float stdlib_base_hypotf( const float x, const float y ) {
3737
float tmp;
3838
float a;
3939
float b;
40-
if ( stdlib_base_is_nanf( x ) || stdlib_base_is_nanf( y ) ) {
41-
return 0.0f / 0.0f; // NaN
42-
}
40+
41+
// If one of the arguments is `+-infinity`, return `+infinity` even if the other argument is `NaN` (IEEE 754-2019)...
4342
if ( stdlib_base_is_infinitef( x ) || stdlib_base_is_infinitef( y ) ) {
4443
return STDLIB_CONSTANT_FLOAT32_PINF;
4544
}
45+
if ( stdlib_base_is_nanf( x ) || stdlib_base_is_nanf( y ) ) {
46+
return 0.0f / 0.0f; // NaN
47+
}
4648
a = x;
4749
b = y;
4850
if ( a < 0.0f ) {

Diff for: lib/node_modules/@stdlib/math/base/special/hypotf/test/test.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,22 @@ tape( 'the function returns `+infinity` if either argument is `+-infinity`', fun
7373
h = hypotf( NINF, NINF );
7474
t.strictEqual( h, PINF, 'returns expected value' );
7575

76+
h = hypotf( NaN, PINF );
77+
t.strictEqual( h, PINF, 'returns expected value' );
78+
79+
h = hypotf( PINF, NaN );
80+
t.strictEqual( h, PINF, 'returns expected value' );
81+
82+
h = hypotf( NINF, NaN );
83+
t.strictEqual( h, PINF, 'returns expected value' );
84+
85+
h = hypotf( NaN, NINF );
86+
t.strictEqual( h, PINF, 'returns expected value' );
87+
7688
t.end();
7789
});
7890

79-
tape( 'the function returns `NaN` if either argument is `NaN`', function test( t ) {
91+
tape( 'the function returns `NaN` if either argument is `NaN` but not `+-infinity`', function test( t ) {
8092
var h;
8193

8294
h = hypotf( NaN, 3.14 );

Diff for: lib/node_modules/@stdlib/math/base/special/hypotf/test/test.native.js

+19-2
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,22 @@ tape( 'the function returns `+infinity` if either argument is `+-infinity`', opt
8282
h = hypotf( NINF, NINF );
8383
t.strictEqual( h, PINF, 'returns expected value' );
8484

85+
h = hypotf( NaN, PINF );
86+
t.strictEqual( h, PINF, 'returns expected value' );
87+
88+
h = hypotf( PINF, NaN );
89+
t.strictEqual( h, PINF, 'returns expected value' );
90+
91+
h = hypotf( NINF, NaN );
92+
t.strictEqual( h, PINF, 'returns expected value' );
93+
94+
h = hypotf( NaN, NINF );
95+
t.strictEqual( h, PINF, 'returns expected value' );
96+
8597
t.end();
8698
});
8799

88-
tape( 'the function returns `NaN` if either argument is `NaN`', opts, function test( t ) {
100+
tape( 'the function returns `NaN` if either argument is `NaN` but not `+-infinity`', opts, function test( t ) {
89101
var h;
90102

91103
h = hypotf( NaN, 3.14 );
@@ -145,6 +157,8 @@ tape( 'the function computes the hypotenuse', opts, function test( t ) {
145157
});
146158

147159
tape( 'the function computes the hypotenuse (canonical inputs)', opts, function test( t ) {
160+
var delta;
161+
var tol;
148162
var h;
149163

150164
h = hypotf( 3.0, 4.0 );
@@ -153,8 +167,11 @@ tape( 'the function computes the hypotenuse (canonical inputs)', opts, function
153167
h = hypotf( 6.0, 8.0 );
154168
t.strictEqual( h, 10.0, 'returns expected value' );
155169

170+
// NOTE: the tolerance here is larger than for the JavaScript implementation due to compiler optimizations which may be performed resulting in result divergence. For discussion, see https://github.com/stdlib-js/stdlib/pull/2298#discussion_r1624765205
156171
h = hypotf( 5.0, 12.0 );
157-
t.strictEqual( h, 13.0, 'returns expected value' );
172+
delta = absf( h - 13.0 );
173+
tol = EPS * absf( 13.0 );
174+
t.strictEqual( delta <= tol, true, 'within tolerance. h: '+h+'. Expected: 13.0. Delta: '+delta+'. Tol: '+tol+'.' );
158175

159176
t.end();
160177
});

0 commit comments

Comments
 (0)