From 52b85a01f04768dd8d824c14c60ff65d88cca7dc Mon Sep 17 00:00:00 2001 From: Neerajpathak07 Date: Wed, 19 Mar 2025 12:10:57 +0530 Subject: [PATCH 1/7] chore: refactor atanh implementation --- .../math/base/special/atanh/lib/main.js | 2 +- .../math/base/special/atanh/src/main.c | 60 ++++++++++++------- 2 files changed, 39 insertions(+), 23 deletions(-) diff --git a/lib/node_modules/@stdlib/math/base/special/atanh/lib/main.js b/lib/node_modules/@stdlib/math/base/special/atanh/lib/main.js index ae3f302923e4..feb81eac2d9d 100644 --- a/lib/node_modules/@stdlib/math/base/special/atanh/lib/main.js +++ b/lib/node_modules/@stdlib/math/base/special/atanh/lib/main.js @@ -18,7 +18,7 @@ * * ## Notice * -* The following copyright, license, and long comment were part of the original implementation available as part of [FreeBSD]{@link https://svnweb.freebsd.org/base/release/9.3.0/lib/msun/src/e_atanh.c?view=markup}. The implementation follows the original, but has been modified for JavaScript. +* The following copyright, license, and long comment were part of the original implementation available as part of [FreeBSD]{@link https://svnweb.freebsd.org/base/release/12.2.0/lib/msun/src/e_atanh.c?view=markup}. The implementation follows the original, but has been modified for JavaScript. * * ```text * Copyright (C) 2004 by Sun Microsystems, Inc. All rights reserved. diff --git a/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c b/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c index 954b9f671f17..c5f2e517a55a 100644 --- a/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c +++ b/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c @@ -33,11 +33,27 @@ #include "stdlib/math/base/special/atanh.h" #include "stdlib/math/base/assert/is_nan.h" #include "stdlib/math/base/special/log1p.h" +#include "stdlib/constants/float64/high_word_abs_mask.h" +#include "stdlib/number/float64/base/set_high_word.h" +#include "stdlib/number/float64/base/to_words.h" #include "stdlib/constants/float64/pinf.h" #include "stdlib/constants/float64/ninf.h" #include -static const double NEAR_ZERO = 1.0 / (1 << 28); // 2**-28 +static const double one = 1.0; + +static const double zero = 0.0; + +static const double huge = 1e300; + +// 0x3ff00000 = 1072693248 => 0 01111111111 00000000000000000000 => biased exponent: 1023 = 0+1023 => 2^0 = 1 +static const int32_t HIGH_BIASED_EXP_0 = 0x3ff00000; + +// 0x3e300000 = 1040187392 => 0 01111100011 00000000000000000000 => biased exponent: 100 = -23+127 +static const int32_t HIGH_BIASED_EXP_NEG_7 = 0x3e300000; + +// 0x3fe00000 = 1071644672 => 0 01111111110 00000000000000000000 => biased exponent: 1022 = -1+1023 => 2^-1 +static const int32_t HIGH_BIASED_EXP_NEG_1 = 0x3fe00000; /** * Computes the hyperbolic arctangent of a double-precision floating-point number. @@ -79,34 +95,34 @@ static const double NEAR_ZERO = 1.0 / (1 << 28); // 2**-28 * // returns ~1.472 */ double stdlib_base_atanh( const double x ) { - int32_t sgn; - double ax; + u_int32_t lx; + double hx; + double ahx; double t; if ( stdlib_base_is_nan( x ) || x < -1.0 || x > 1.0 ) { return 0.0 / 0.0; // NaN } - if ( x == 1.0 ) { - return STDLIB_CONSTANT_FLOAT64_PINF; + // Split `x` into high and low words: + stdlib_base_float64_to_words( x, &hx, &lx ); + + ahx = hx & STDLIB_CONSTANT_FLOAT64_HIGH_WORD_ABS_MASK; + + if( ( ahx | ( ( lx | (-lx) )>>31 ))> HIGH_BIASED_EXP_0 ) { + return ( x - x ) / ( x - x ); // |x|>1 } - if ( x == -1.0 ) { - return STDLIB_CONSTANT_FLOAT64_NINF; + if( ahx == HIGH_BIASED_EXP_0 ) { + return x / zero; } - if ( x < 0.0 ) { - sgn = 1; - ax = -x; - } else { - sgn = 0; - ax = x; + if( ahx < HIGH_BIASED_EXP_NEG_7 && ( huge+x ) > zero) { + return x; // x<2**-28 } - // Case: |x| < 2**-28 - if ( ax < NEAR_ZERO ) { - return ( sgn == 1 ) ? -ax : ax; - } - if ( ax < 0.5 ) { - t = ax + ax; - t = 0.5 * stdlib_base_log1p( t + ( t * ax / ( 1 - ax ) ) ); + stdlib_base_float64_set_high_word( x, &ahx ); + if( ahx < HIGH_BIASED_EXP_NEG_1 ) { + t = x + x; + t = 0.5 * stdlib_base_log1p( t + ( t * x / ( one - x ) ) ); + } else { - t = 0.5 * stdlib_base_log1p( ( ax + ax ) / ( 1 - ax ) ); + t = 0.5 * stdlib_base_log1p( ( x + x ) / ( one - x ) ); } - return ( sgn == 1 ) ? -t : t; + return ( hx >= 0 ) ? -t : t; } From eac4d5dcba0414233361772e35141ea21f5c3dc2 Mon Sep 17 00:00:00 2001 From: Neerajpathak07 Date: Wed, 19 Mar 2025 12:44:46 +0530 Subject: [PATCH 2/7] chore: minor clean up --- .../math/base/special/atanh/manifest.json | 9 +++++++++ .../math/base/special/atanh/src/main.c | 19 +++++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/lib/node_modules/@stdlib/math/base/special/atanh/manifest.json b/lib/node_modules/@stdlib/math/base/special/atanh/manifest.json index 4678a491a177..2a6733339c24 100644 --- a/lib/node_modules/@stdlib/math/base/special/atanh/manifest.json +++ b/lib/node_modules/@stdlib/math/base/special/atanh/manifest.json @@ -39,6 +39,9 @@ "@stdlib/math/base/napi/unary", "@stdlib/math/base/special/log1p", "@stdlib/math/base/assert/is-nan", + "@stdlib/constants/float64/high-word-abs-mask", + "@stdlib/number/float64/base/set-high-word", + "@stdlib/number/float64/base/to-words", "@stdlib/constants/float64/pinf", "@stdlib/constants/float64/ninf" ] @@ -56,6 +59,9 @@ "dependencies": [ "@stdlib/math/base/special/log1p", "@stdlib/math/base/assert/is-nan", + "@stdlib/constants/float64/high-word-abs-mask", + "@stdlib/number/float64/base/set-high-word", + "@stdlib/number/float64/base/to-words", "@stdlib/constants/float64/pinf", "@stdlib/constants/float64/ninf" ] @@ -73,6 +79,9 @@ "dependencies": [ "@stdlib/math/base/special/log1p", "@stdlib/math/base/assert/is-nan", + "@stdlib/constants/float64/high-word-abs-mask", + "@stdlib/number/float64/base/set-high-word", + "@stdlib/number/float64/base/to-words", "@stdlib/constants/float64/pinf", "@stdlib/constants/float64/ninf" ] diff --git a/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c b/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c index c5f2e517a55a..82e9e6a9552b 100644 --- a/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c +++ b/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c @@ -95,9 +95,10 @@ static const int32_t HIGH_BIASED_EXP_NEG_1 = 0x3fe00000; * // returns ~1.472 */ double stdlib_base_atanh( const double x ) { - u_int32_t lx; - double hx; - double ahx; + uint32_t lx; + uint32_t hx; + uint32_t ahx; + double ax; double t; if ( stdlib_base_is_nan( x ) || x < -1.0 || x > 1.0 ) { return 0.0 / 0.0; // NaN @@ -116,13 +117,15 @@ double stdlib_base_atanh( const double x ) { if( ahx < HIGH_BIASED_EXP_NEG_7 && ( huge+x ) > zero) { return x; // x<2**-28 } - stdlib_base_float64_set_high_word( x, &ahx ); - if( ahx < HIGH_BIASED_EXP_NEG_1 ) { - t = x + x; - t = 0.5 * stdlib_base_log1p( t + ( t * x / ( one - x ) ) ); + ax = (double *)&x; + stdlib_base_float64_set_high_word( ahx, &ax ); + + if( ahx < HIGH_BIASED_EXP_NEG_1 ) { + t = ax + ax; + t = 0.5 * stdlib_base_log1p( t + ( t * ax / ( one - ax ) ) ); } else { - t = 0.5 * stdlib_base_log1p( ( x + x ) / ( one - x ) ); + t = 0.5 * stdlib_base_log1p( ( ax + ax ) / ( one - ax ) ); } return ( hx >= 0 ) ? -t : t; } From 2dc8d294ee77ea98df90b89baf7233ce907dbc30 Mon Sep 17 00:00:00 2001 From: Neerajpathak07 Date: Wed, 19 Mar 2025 12:58:23 +0530 Subject: [PATCH 3/7] chore: add new var --- lib/node_modules/@stdlib/math/base/special/atanh/src/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c b/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c index 82e9e6a9552b..ed142825999b 100644 --- a/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c +++ b/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c @@ -118,8 +118,8 @@ double stdlib_base_atanh( const double x ) { return x; // x<2**-28 } - ax = (double *)&x; - stdlib_base_float64_set_high_word( ahx, &ax ); + ax = x; + stdlib_base_float64_set_high_word( ahx, ax ); if( ahx < HIGH_BIASED_EXP_NEG_1 ) { t = ax + ax; @@ -127,5 +127,5 @@ double stdlib_base_atanh( const double x ) { } else { t = 0.5 * stdlib_base_log1p( ( ax + ax ) / ( one - ax ) ); } - return ( hx >= 0 ) ? -t : t; + return ( hx == 1 ) ? -t : t; } From c83baa6aaf209cd2f41c1851cbd0ad047bd2f2ec Mon Sep 17 00:00:00 2001 From: Neerajpathak07 Date: Wed, 19 Mar 2025 13:01:33 +0530 Subject: [PATCH 4/7] chore: pointer conversion --- lib/node_modules/@stdlib/math/base/special/atanh/src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c b/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c index ed142825999b..c0fe1c20f1c1 100644 --- a/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c +++ b/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c @@ -119,7 +119,7 @@ double stdlib_base_atanh( const double x ) { } ax = x; - stdlib_base_float64_set_high_word( ahx, ax ); + stdlib_base_float64_set_high_word( ahx, &ax ); if( ahx < HIGH_BIASED_EXP_NEG_1 ) { t = ax + ax; From 6244749b4d47cdc818fe90a48026949628c199f1 Mon Sep 17 00:00:00 2001 From: Neerajpathak07 Date: Wed, 19 Mar 2025 16:43:58 +0530 Subject: [PATCH 5/7] chore: refactor native tests --- .../@stdlib/math/base/special/atanh/test/test.native.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/math/base/special/atanh/test/test.native.js b/lib/node_modules/@stdlib/math/base/special/atanh/test/test.native.js index 84ee90a41633..3625887e2b7f 100644 --- a/lib/node_modules/@stdlib/math/base/special/atanh/test/test.native.js +++ b/lib/node_modules/@stdlib/math/base/special/atanh/test/test.native.js @@ -74,7 +74,7 @@ tape( 'the function computes the hyperbolic arctangent (negative values)', opts, t.strictEqual( y, expected[ i ], 'x: '+x[i]+'. E: '+expected[i] ); } else { delta = abs( y - expected[i] ); - tol = 1.0 * EPS * abs( expected[i] ); + tol = 10.0 * EPS * abs( expected[i] ); t.ok( delta <= tol, 'within tolerance. x: '+x[i]+'. y: '+y+'. E: '+expected[i]+'. Δ: '+delta+'. tol: '+tol+'.' ); } } From a2e6cd9c714049317272aa22309530c6d1042505 Mon Sep 17 00:00:00 2001 From: Neerajpathak07 Date: Wed, 19 Mar 2025 22:48:06 +0530 Subject: [PATCH 6/7] chore: refactor implementation --- .../math/base/special/atanh/src/main.c | 42 ++++++++----------- .../base/special/atanh/test/test.native.js | 2 +- 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c b/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c index c0fe1c20f1c1..5d7ae4006c14 100644 --- a/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c +++ b/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c @@ -40,20 +40,7 @@ #include "stdlib/constants/float64/ninf.h" #include -static const double one = 1.0; - -static const double zero = 0.0; - -static const double huge = 1e300; - -// 0x3ff00000 = 1072693248 => 0 01111111111 00000000000000000000 => biased exponent: 1023 = 0+1023 => 2^0 = 1 -static const int32_t HIGH_BIASED_EXP_0 = 0x3ff00000; - -// 0x3e300000 = 1040187392 => 0 01111100011 00000000000000000000 => biased exponent: 100 = -23+127 -static const int32_t HIGH_BIASED_EXP_NEG_7 = 0x3e300000; - -// 0x3fe00000 = 1071644672 => 0 01111111110 00000000000000000000 => biased exponent: 1022 = -1+1023 => 2^-1 -static const int32_t HIGH_BIASED_EXP_NEG_1 = 0x3fe00000; +static const double NEAR_ZERO = 1.0 / (1 << 28); // 2**-28 /** * Computes the hyperbolic arctangent of a double-precision floating-point number. @@ -95,37 +82,42 @@ static const int32_t HIGH_BIASED_EXP_NEG_1 = 0x3fe00000; * // returns ~1.472 */ double stdlib_base_atanh( const double x ) { + uint32_t ahx; uint32_t lx; uint32_t hx; - uint32_t ahx; double ax; double t; + if ( stdlib_base_is_nan( x ) || x < -1.0 || x > 1.0 ) { return 0.0 / 0.0; // NaN } + // Split `x` into high and low words: stdlib_base_float64_to_words( x, &hx, &lx ); + ax = x; ahx = hx & STDLIB_CONSTANT_FLOAT64_HIGH_WORD_ABS_MASK; - if( ( ahx | ( ( lx | (-lx) )>>31 ))> HIGH_BIASED_EXP_0 ) { - return ( x - x ) / ( x - x ); // |x|>1 + // special cases + if ( ax == 1.0 ) { + return STDLIB_CONSTANT_FLOAT64_PINF; } - if( ahx == HIGH_BIASED_EXP_0 ) { - return x / zero; + if ( ax == -1.0 ) { + return STDLIB_CONSTANT_FLOAT64_NINF; } - if( ahx < HIGH_BIASED_EXP_NEG_7 && ( huge+x ) > zero) { - return x; // x<2**-28 + + // Case: |x| < 2**-28 + if ( ax < NEAR_ZERO ) { + return ( hx == 1 ) ? -ax : ax; } - ax = x; stdlib_base_float64_set_high_word( ahx, &ax ); - if( ahx < HIGH_BIASED_EXP_NEG_1 ) { + if( ahx < 0.5 ) { t = ax + ax; - t = 0.5 * stdlib_base_log1p( t + ( t * ax / ( one - ax ) ) ); + t = 0.5 * stdlib_base_log1p( t + ( t * ax / ( 1.0 - ax ) ) ); } else { - t = 0.5 * stdlib_base_log1p( ( ax + ax ) / ( one - ax ) ); + t = 0.5 * stdlib_base_log1p( ( ax + ax ) / ( 1.0 - ax ) ); } return ( hx == 1 ) ? -t : t; } diff --git a/lib/node_modules/@stdlib/math/base/special/atanh/test/test.native.js b/lib/node_modules/@stdlib/math/base/special/atanh/test/test.native.js index 3625887e2b7f..84ee90a41633 100644 --- a/lib/node_modules/@stdlib/math/base/special/atanh/test/test.native.js +++ b/lib/node_modules/@stdlib/math/base/special/atanh/test/test.native.js @@ -74,7 +74,7 @@ tape( 'the function computes the hyperbolic arctangent (negative values)', opts, t.strictEqual( y, expected[ i ], 'x: '+x[i]+'. E: '+expected[i] ); } else { delta = abs( y - expected[i] ); - tol = 10.0 * EPS * abs( expected[i] ); + tol = 1.0 * EPS * abs( expected[i] ); t.ok( delta <= tol, 'within tolerance. x: '+x[i]+'. y: '+y+'. E: '+expected[i]+'. Δ: '+delta+'. tol: '+tol+'.' ); } } From 80012d66856dafe6c84410db7bd7a1d1b66adec2 Mon Sep 17 00:00:00 2001 From: Neerajpathak07 Date: Wed, 19 Mar 2025 22:54:51 +0530 Subject: [PATCH 7/7] chore: adding case for x < 0.0 --- .../@stdlib/math/base/special/atanh/src/main.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c b/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c index 5d7ae4006c14..a932542d7233 100644 --- a/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c +++ b/lib/node_modules/@stdlib/math/base/special/atanh/src/main.c @@ -95,17 +95,23 @@ double stdlib_base_atanh( const double x ) { // Split `x` into high and low words: stdlib_base_float64_to_words( x, &hx, &lx ); - ax = x; ahx = hx & STDLIB_CONSTANT_FLOAT64_HIGH_WORD_ABS_MASK; // special cases - if ( ax == 1.0 ) { + if ( x == 1.0 ) { return STDLIB_CONSTANT_FLOAT64_PINF; } - if ( ax == -1.0 ) { + if ( x == -1.0 ) { return STDLIB_CONSTANT_FLOAT64_NINF; } + if ( x < 0.0 ) { + hx = 1; + ax = -x; + } else { + hx = 0; + ax = x; + } // Case: |x| < 2**-28 if ( ax < NEAR_ZERO ) { return ( hx == 1 ) ? -ax : ax; @@ -113,7 +119,7 @@ double stdlib_base_atanh( const double x ) { stdlib_base_float64_set_high_word( ahx, &ax ); - if( ahx < 0.5 ) { + if( ax < 0.5 ) { t = ax + ax; t = 0.5 * stdlib_base_log1p( t + ( t * ax / ( 1.0 - ax ) ) ); } else {