From 3f43dc14331be1b6638cac664d264f824aae5779 Mon Sep 17 00:00:00 2001 From: aman-095 Date: Sun, 3 Mar 2024 18:00:40 +0530 Subject: [PATCH 01/18] Add C implementation for pow --- .../@stdlib/math/base/special/pow/README.md | 95 +- .../special/pow/benchmark/benchmark.native.js | 62 + .../special/pow/benchmark/c/native/Makefile | 146 +++ .../pow/benchmark/c/native/benchmark.c | 138 +++ .../@stdlib/math/base/special/pow/binding.gyp | 170 +++ .../math/base/special/pow/examples/c/Makefile | 146 +++ .../base/special/pow/examples/c/example.c | 35 + .../math/base/special/pow/include.gypi | 53 + .../include/stdlib/math/base/special/pow.h | 38 + .../math/base/special/pow/lib/native.js | 62 + .../math/base/special/pow/lib/polyval_l.js | 2 +- .../math/base/special/pow/lib/polyval_p.js | 2 +- .../math/base/special/pow/lib/polyval_w.js | 2 +- .../math/base/special/pow/manifest.json | 123 ++ .../math/base/special/pow/scripts/evalpoly.js | 58 +- .../math/base/special/pow/src/Makefile | 70 ++ .../@stdlib/math/base/special/pow/src/addon.c | 23 + .../@stdlib/math/base/special/pow/src/main.c | 702 +++++++++++ .../math/base/special/pow/test/test.native.js | 1030 +++++++++++++++++ 19 files changed, 2952 insertions(+), 5 deletions(-) create mode 100644 lib/node_modules/@stdlib/math/base/special/pow/benchmark/benchmark.native.js create mode 100644 lib/node_modules/@stdlib/math/base/special/pow/benchmark/c/native/Makefile create mode 100644 lib/node_modules/@stdlib/math/base/special/pow/benchmark/c/native/benchmark.c create mode 100644 lib/node_modules/@stdlib/math/base/special/pow/binding.gyp create mode 100644 lib/node_modules/@stdlib/math/base/special/pow/examples/c/Makefile create mode 100644 lib/node_modules/@stdlib/math/base/special/pow/examples/c/example.c create mode 100644 lib/node_modules/@stdlib/math/base/special/pow/include.gypi create mode 100644 lib/node_modules/@stdlib/math/base/special/pow/include/stdlib/math/base/special/pow.h create mode 100644 lib/node_modules/@stdlib/math/base/special/pow/lib/native.js create mode 100644 lib/node_modules/@stdlib/math/base/special/pow/manifest.json create mode 100644 lib/node_modules/@stdlib/math/base/special/pow/src/Makefile create mode 100644 lib/node_modules/@stdlib/math/base/special/pow/src/addon.c create mode 100644 lib/node_modules/@stdlib/math/base/special/pow/src/main.c create mode 100644 lib/node_modules/@stdlib/math/base/special/pow/test/test.native.js diff --git a/lib/node_modules/@stdlib/math/base/special/pow/README.md b/lib/node_modules/@stdlib/math/base/special/pow/README.md index 68c771136232..b9794e9b6f7f 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/README.md +++ b/lib/node_modules/@stdlib/math/base/special/pow/README.md @@ -2,7 +2,7 @@ @license Apache-2.0 -Copyright (c) 2018 The Stdlib Authors. +Copyright (c) 2024 The Stdlib Authors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -113,6 +113,99 @@ for ( i = 0; i < 100; i++ ) { + + +* * * + +
+ +## C APIs + + + +
+ +
+ + + + + +
+ +### Usage + +```c +#include "stdlib/math/base/special/pow.h" +``` + +#### stdlib_base_pow( base, exponent ) + +Evaluates the [exponential function][exponential-function]. + +```c +double out = stdlib_base_pow( 3.141592653589793, 5.0 ); +// returns ~306.0197 + +out = stdlib_base_pow( 4.0, 0.5 ); +// returns 2.0 +``` + +The function accepts the following arguments: + +- **b**: `[in] double` input value. +- **x**: `[in] double` input value. + +```c +double stdlib_base_pow( const double b, const double x ); +``` + +
+ + + + + +
+ +
+ + + + + +
+ +### Examples + +```c +#include "stdlib/math/base/special/pow.h" +#include +#include + +int main( void ) { + double b; + double x; + double out; + int i; + + for ( i = 0; i < 100; i++ ) { + b = round( randu()*10.0 ); + x = round( randu()*10.0 ) - 5.0; + out = stdlib_base_pow ( b, x ); + printf( "pow(%lf, %lf) = %lf\n", b, x, v ); + } +} +``` + +
+ + + +
+ + + @@ -184,9 +184,9 @@ double stdlib_base_pow( const double b, const double x ); #include int main( void ) { + double out; double b; double x; - double out; int i; for ( i = 0; i < 100; i++ ) { From 57f8a165426e59cf53911b4e1ac45c6067df6db7 Mon Sep 17 00:00:00 2001 From: Athan Date: Wed, 6 Mar 2024 18:01:13 -0800 Subject: [PATCH 05/18] Apply suggestions from code review Signed-off-by: Athan --- .../math/base/special/pow/benchmark/c/native/benchmark.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/math/base/special/pow/benchmark/c/native/benchmark.c b/lib/node_modules/@stdlib/math/base/special/pow/benchmark/c/native/benchmark.c index 64d35e2f73b0..880a68893fa1 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/benchmark/c/native/benchmark.c +++ b/lib/node_modules/@stdlib/math/base/special/pow/benchmark/c/native/benchmark.c @@ -17,7 +17,7 @@ */ /** -* Benchmark `ellipk`. +* Benchmark `pow`. */ #include "stdlib/math/base/special/pow.h" #include From 763b5c49dba5e2c2b3e9a31c4ce1abf335bbb986 Mon Sep 17 00:00:00 2001 From: Athan Date: Wed, 6 Mar 2024 18:01:59 -0800 Subject: [PATCH 06/18] Apply suggestions from code review Signed-off-by: Athan --- lib/node_modules/@stdlib/math/base/special/pow/binding.gyp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/math/base/special/pow/binding.gyp b/lib/node_modules/@stdlib/math/base/special/pow/binding.gyp index 507cb00291e7..ec3992233442 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/binding.gyp +++ b/lib/node_modules/@stdlib/math/base/special/pow/binding.gyp @@ -167,4 +167,4 @@ ], # end actions }, # end target copy_addon ], # end targets -} \ No newline at end of file +} From 348099a5e99f3f8c91025e76a7884ecf7c54d1c9 Mon Sep 17 00:00:00 2001 From: Athan Date: Wed, 6 Mar 2024 18:02:58 -0800 Subject: [PATCH 07/18] Apply suggestions from code review Signed-off-by: Athan --- lib/node_modules/@stdlib/math/base/special/pow/include.gypi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/math/base/special/pow/include.gypi b/lib/node_modules/@stdlib/math/base/special/pow/include.gypi index c6495fc1da3f..575cb043c0bf 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/include.gypi +++ b/lib/node_modules/@stdlib/math/base/special/pow/include.gypi @@ -50,4 +50,4 @@ ' Date: Wed, 6 Mar 2024 18:04:04 -0800 Subject: [PATCH 08/18] Apply suggestions from code review Signed-off-by: Athan --- .../base/special/pow/include/stdlib/math/base/special/pow.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/node_modules/@stdlib/math/base/special/pow/include/stdlib/math/base/special/pow.h b/lib/node_modules/@stdlib/math/base/special/pow/include/stdlib/math/base/special/pow.h index 4e56dd164877..5fddb2ea091f 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/include/stdlib/math/base/special/pow.h +++ b/lib/node_modules/@stdlib/math/base/special/pow/include/stdlib/math/base/special/pow.h @@ -29,10 +29,10 @@ extern "C" { /** * Evaluates the exponential function. */ -double stdlib_base_pow( const double b, const double x ); +double stdlib_base_pow( const double base, const double exponent ); #ifdef __cplusplus } #endif -#endif // !STDLIB_MATH_BASE_SPECIAL_POW_H \ No newline at end of file +#endif // !STDLIB_MATH_BASE_SPECIAL_POW_H From eabee3a47bc23d94249862fe9ec747af8f2882cb Mon Sep 17 00:00:00 2001 From: Athan Date: Wed, 6 Mar 2024 18:07:35 -0800 Subject: [PATCH 09/18] Apply suggestions from code review Signed-off-by: Athan --- .../math/base/special/pow/lib/native.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/node_modules/@stdlib/math/base/special/pow/lib/native.js b/lib/node_modules/@stdlib/math/base/special/pow/lib/native.js index ff804513f5e9..16b7078f8e08 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/lib/native.js +++ b/lib/node_modules/@stdlib/math/base/special/pow/lib/native.js @@ -29,31 +29,31 @@ var addon = require( './../src/addon.node' ); Evaluates the exponential function. * * @private -* @param {number} b - input value -* @param {number} x - input value +* @param {number} x - base +* @param {number} y - exponent * @returns {number} exponential value * * @example * var v = pow( 2.0, 3.0 ); * // returns 8.0 * -* v = ellipk( 4.0, 0.5 ); +* v = pow( 4.0, 0.5 ); * // returns 2.0 * -* v = ellipk( 100.0, 0.0 ); +* v = pow( 100.0, 0.0 ); * // returns 1.0 * -* v = ellipk( 3.141592653589793, -0.2 ); +* v = pow( 3.141592653589793, -0.2 ); * // returns ~0.7954 * -* v = ellipk( NaN, 3.0 ); +* v = pow( NaN, 3.0 ); * // returns NaN * -* v = ellipk( 5.0, NaN ); +* v = pow( 5.0, NaN ); * // returns NaN */ -function pow( b, x ) { - return addon( b, x ); +function pow( x, y ) { + return addon( x, y ); } From ad9750aab405e5bdf467b8ab8ff8b244cbe0e40d Mon Sep 17 00:00:00 2001 From: Athan Date: Wed, 6 Mar 2024 18:07:53 -0800 Subject: [PATCH 10/18] Apply suggestions from code review Signed-off-by: Athan --- lib/node_modules/@stdlib/math/base/special/pow/lib/native.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/math/base/special/pow/lib/native.js b/lib/node_modules/@stdlib/math/base/special/pow/lib/native.js index 16b7078f8e08..9a527c6001a0 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/lib/native.js +++ b/lib/node_modules/@stdlib/math/base/special/pow/lib/native.js @@ -26,7 +26,7 @@ var addon = require( './../src/addon.node' ); // MAIN // /** -Evaluates the exponential function. +* Evaluates the exponential function. * * @private * @param {number} x - base From a27095aeb7e868fa53c3d0652a6c003af124124c Mon Sep 17 00:00:00 2001 From: Athan Date: Wed, 6 Mar 2024 18:08:40 -0800 Subject: [PATCH 11/18] Apply suggestions from code review Signed-off-by: Athan --- lib/node_modules/@stdlib/math/base/special/pow/lib/native.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/math/base/special/pow/lib/native.js b/lib/node_modules/@stdlib/math/base/special/pow/lib/native.js index 9a527c6001a0..8c7b26489b92 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/lib/native.js +++ b/lib/node_modules/@stdlib/math/base/special/pow/lib/native.js @@ -31,7 +31,7 @@ var addon = require( './../src/addon.node' ); * @private * @param {number} x - base * @param {number} y - exponent -* @returns {number} exponential value +* @returns {number} function value * * @example * var v = pow( 2.0, 3.0 ); From aa62c7139e663a998152a2b0ffc4ae063bbde6c3 Mon Sep 17 00:00:00 2001 From: Athan Date: Wed, 6 Mar 2024 18:09:46 -0800 Subject: [PATCH 12/18] Apply suggestions from code review Signed-off-by: Athan --- .../math/base/special/pow/lib/native.js | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/node_modules/@stdlib/math/base/special/pow/lib/native.js b/lib/node_modules/@stdlib/math/base/special/pow/lib/native.js index 8c7b26489b92..e37dc181675c 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/lib/native.js +++ b/lib/node_modules/@stdlib/math/base/special/pow/lib/native.js @@ -37,20 +37,32 @@ var addon = require( './../src/addon.node' ); * var v = pow( 2.0, 3.0 ); * // returns 8.0 * -* v = pow( 4.0, 0.5 ); +* @example +* var v = pow( 4.0, 0.5 ); * // returns 2.0 * -* v = pow( 100.0, 0.0 ); +* @example +* var v = pow( 100.0, 0.0 ); * // returns 1.0 * -* v = pow( 3.141592653589793, -0.2 ); +* @example +* var v = pow( 3.141592653589793, 5.0 ); +* // returns ~306.0197 +* +* @example +* var v = pow( 3.141592653589793, -0.2 ); * // returns ~0.7954 * -* v = pow( NaN, 3.0 ); +* @example +* var v = pow( NaN, 3.0 ); * // returns NaN * -* v = pow( 5.0, NaN ); +* @example +* var v = pow( 5.0, NaN ); * // returns NaN +* +* @example +* var v = pow( NaN, NaN ); */ function pow( x, y ) { return addon( x, y ); From 019b21e6f7d857b4f86cf6e4e1b4b26b2b882abc Mon Sep 17 00:00:00 2001 From: Athan Date: Wed, 6 Mar 2024 18:12:07 -0800 Subject: [PATCH 13/18] Apply suggestions from code review Signed-off-by: Athan --- lib/node_modules/@stdlib/math/base/special/pow/src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/math/base/special/pow/src/Makefile b/lib/node_modules/@stdlib/math/base/special/pow/src/Makefile index 81bb164286c3..bcf18aa46655 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/src/Makefile +++ b/lib/node_modules/@stdlib/math/base/special/pow/src/Makefile @@ -67,4 +67,4 @@ clean-addon: #/ clean: clean-addon -.PHONY: clean \ No newline at end of file +.PHONY: clean From 86115e5a63bedd267d8c6a58655f2f77af4b8285 Mon Sep 17 00:00:00 2001 From: aman-095 Date: Fri, 8 Mar 2024 15:20:19 +0530 Subject: [PATCH 14/18] fix: incorrect implementation of pow --- .../special/pow/benchmark/benchmark.native.js | 4 +- .../base/special/pow/examples/c/example.c | 6 +- .../@stdlib/math/base/special/pow/src/addon.c | 1 - .../@stdlib/math/base/special/pow/src/main.c | 228 +++++++++--------- 4 files changed, 115 insertions(+), 124 deletions(-) diff --git a/lib/node_modules/@stdlib/math/base/special/pow/benchmark/benchmark.native.js b/lib/node_modules/@stdlib/math/base/special/pow/benchmark/benchmark.native.js index 007e3b2fabc4..1713caa183dd 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/benchmark/benchmark.native.js +++ b/lib/node_modules/@stdlib/math/base/special/pow/benchmark/benchmark.native.js @@ -46,8 +46,8 @@ bench( pkg+'::native', opts, function benchmark( b ) { b.tic(); for ( i = 0; i < b.iterations; i++ ) { - v = round( randu()*10.0 ); - x = round( randu()*10.0 ) - 5.0; + v = ( randu()*10.0 ); + x = ( randu()*10.0 ) - 5.0; y = pow( v, x ); if ( isnan( y ) ) { b.fail( 'should not return NaN' ); diff --git a/lib/node_modules/@stdlib/math/base/special/pow/examples/c/example.c b/lib/node_modules/@stdlib/math/base/special/pow/examples/c/example.c index f4880a23de60..6eb35dea0850 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/examples/c/example.c +++ b/lib/node_modules/@stdlib/math/base/special/pow/examples/c/example.c @@ -21,14 +21,14 @@ #include int main( void ) { - double out; + double out; double b; double x; int i; for ( i = 0; i < 100; i++ ) { - b = ( ( (double)rand() / (double)RAND_MAX ) * 10.0 ); - x = ( ( (double)rand() / (double)RAND_MAX ) * 10.0 ) - 5.0; + b = ( ( (double)rand() / (double)RAND_MAX ) * 10.0 ); + x = ( ( (double)rand() / (double)RAND_MAX ) * 10.0 ) - 5.0; out = stdlib_base_pow( b, x ); printf( "pow(%lf, %lf) = %lf\n", b, x, out ); } diff --git a/lib/node_modules/@stdlib/math/base/special/pow/src/addon.c b/lib/node_modules/@stdlib/math/base/special/pow/src/addon.c index 89a949de9196..ff8767b9e48c 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/src/addon.c +++ b/lib/node_modules/@stdlib/math/base/special/pow/src/addon.c @@ -19,5 +19,4 @@ #include "stdlib/math/base/special/pow.h" #include "stdlib/math/base/napi/binary.h" -// cppcheck-suppress shadowFunction STDLIB_MATH_BASE_NAPI_MODULE_DD_D( stdlib_base_pow ) diff --git a/lib/node_modules/@stdlib/math/base/special/pow/src/main.c b/lib/node_modules/@stdlib/math/base/special/pow/src/main.c index 5c75bbad7660..11f85dc28827 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/src/main.c +++ b/lib/node_modules/@stdlib/math/base/special/pow/src/main.c @@ -36,23 +36,21 @@ #include "stdlib/math/base/special/sqrt.h" #include "stdlib/number/float64/base/to_words.h" - - // 0x3fefffff = 1072693247 => 0 01111111110 11111111111111111111 => biased exponent: 1022 = -1+1023 => 2^-1 -static const uint32_t HIGH_MAX_NEAR_UNITY = 0x3fefffff; +static const int32_t HIGH_MAX_NEAR_UNITY = 0x3fefffff; -static const double HUGE = 1.0e300; +static const double HUGE_VALUE = 1.0e300; -static const double TINY = 1.0e-300; +static const double TINY_VALUE = 1.0e-300; // 0x00100000 = 1048576 => 0 00000000001 00000000000000000000 => biased exponent: 1 = -1022+1023 => 2^-1022 -static const uint32_t HIGH_MIN_NORMAL_EXP = 0x00100000; +static const int32_t HIGH_MIN_NORMAL_EXP = 0x00100000; // 0x3fe00000 = 1071644672 => 0 01111111110 00000000000000000000 => biased exponent: 1022 = -1+1023 => 2^-1 -static const uint32_t HIGH_BIASED_EXP_NEG_1 = 0x3fe00000; +static const int32_t HIGH_BIASED_EXP_NEG_1 = 0x3fe00000; // TODO: consider making into an external constant -static const uint32_t HIGH_NUM_SIGNIFICAND_BITS = 20; +static const int32_t HIGH_NUM_SIGNIFICAND_BITS = 20; // High: LN2 static const double LN2_HI = 6.93147182464599609375e-01; // 0x3FE62E43, 0x00000000 @@ -70,16 +68,16 @@ static const double INV_LN2_HI = 1.44269502162933349609e+00; // 0x3FF71547, 0x60 static const double INV_LN2_LO = 1.92596299112661746887e-08; // 0x3E54AE0B, 0xF85DDF44 // 0x000fffff = 1048575 => 0 00000000000 11111111111111111111 -static const uint32_t HIGH_SIGNIFICAND_MASK = 0x000fffff; +static const int32_t HIGH_SIGNIFICAND_MASK = 0x000fffff; // 0x3ff00000 = 1072693248 => 0 01111111111 00000000000000000000 => biased exponent: 1023 = 0+1023 => 2^0 = 1 -static const uint32_t HIGH_BIASED_EXP_0 = 0x3ff00000; +static const int32_t HIGH_BIASED_EXP_0 = 0x3ff00000; // 0x20000000 = 536870912 => 0 01000000000 00000000000000000000 => biased exponent: 512 = -511+1023 -static const uint32_t HIGH_BIASED_EXP_NEG_512 = 0x20000000; +static const int32_t HIGH_BIASED_EXP_NEG_512 = 0x20000000; // 0x00080000 = 524288 => 0 00000000000 10000000000000000000 -static const uint32_t HIGH_SIGNIFICAND_HALF = 0x00080000; +static const int32_t HIGH_SIGNIFICAND_HALF = 0x00080000; static const double TWO53 = 9007199254740992.0; // 0x43400000, 0x00000000 @@ -92,17 +90,17 @@ static const double CP_HI = 9.61796700954437255859e-01; // 0x3FEEC709, 0xE000000 // Low: CP_HI static const double CP_LO = -7.02846165095275826516e-09; // 0xBE3E2FE0, 0x145B01F5 -double BP [2] = { 1.0, 1.5 }; +static const double BP [2] = { 1.0, 1.5 }; -double DP_HI [2] = { 0.0, 5.84962487220764160156e-01 }; // 0x3FE2B803, 0x40000000 +static const double DP_HI [2] = { 0.0, 5.84962487220764160156e-01 }; // 0x3FE2B803, 0x40000000 -double DP_LO [2] = { 0.0, 1.35003920212974897128e-08 }; // 0x3E4CFDEB, 0x43CFD006 +static const double DP_LO [2] = { 0.0, 1.35003920212974897128e-08 }; // 0x3E4CFDEB, 0x43CFD006 // 0x41e00000 = 1105199104 => 0 10000011110 00000000000000000000 => biased exponent: 1054 = 31+1023 => 2^31 -static const uint32_t HIGH_BIASED_EXP_31 = 0x41e00000; +static const int32_t HIGH_BIASED_EXP_31 = 0x41e00000; // 0x43f00000 = 1139802112 => 0 10000111111 00000000000000000000 => biased exponent: 1087 = 64+1023 => 2^64 -static const uint32_t HIGH_BIASED_EXP_64 = 0x43f00000; +static const int32_t HIGH_BIASED_EXP_64 = 0x43f00000; // 0x40900000 = 1083179008 => 0 10000001001 00000000000000000000 => biased exponent: 1033 = 10+1023 => 2^10 = 1024 static const int32_t HIGH_BIASED_EXP_10 = 0x40900000; @@ -111,16 +109,13 @@ static const int32_t HIGH_BIASED_EXP_10 = 0x40900000; static const int32_t HIGH_1075 = 0x4090cc00; // 0xc090cc00 = 3230714880 => 1 10000001001 00001100110000000000 -static const int32_t HIGH_NEG_1075 = 0xc090cc00; +static const uint32_t HIGH_NEG_1075 = 0xc090cc00; -static const uint32_t HIGH_NUM_NONSIGN_BITS = 31; +static const int32_t HIGH_NUM_NONSIGN_BITS = 31; // -(1024-log2(ovfl+.5ulp)) static const double OVT = 8.0085662595372944372e-17; -// Log workspace: -double LOG_WORKSPACE[2] = { 0.0, 0.0 }; - /* Begin auto-generated functions. The following functions are auto-generated. Do not edit directly. */ // BEGIN: polyval_l @@ -188,19 +183,19 @@ static double polyval_p( const double x ) { /** * Evaluates the exponential function when \\( y = \pm \infty\\). * -* @param x input value -* @param y input value +* @param x base +* @param y exponent * @return output value * * @example -* double out = y_is_infinite( -1.0, Infinity ); +* double out = y_is_infinite( -1.0, 1.0/0.0 ); * // returns NaN * * @example -* double out = y_is_infinite( 1.5, -Infinity ); +* double out = y_is_infinite( 1.5, -1.0/0.0 ); * // returns 0.0 */ -double y_is_infinite( const double x, const double y ) { +static double y_is_infinite( const double x, const double y ) { if ( x == -1.0 ) { return 0.0 / 0.0; // NaN } @@ -208,7 +203,7 @@ double y_is_infinite( const double x, const double y ) { return 1.0; } // (|x| > 1 && y == NINF) || (|x| < 1 && y === PINF) - if ( (stdlib_base_abs( x ) < 1.0) == (y == STDLIB_CONSTANT_FLOAT64_PINF) ) { + if ( ( stdlib_base_abs( x ) < 1.0 ) == ( y == STDLIB_CONSTANT_FLOAT64_PINF ) ) { return 0.0; } // (|x| > 1 && y == PINF) || (|x| < 1 && y == NINF) @@ -218,8 +213,8 @@ double y_is_infinite( const double x, const double y ) { /** * Evaluates the exponential function when \\(|y| > 2^64\\). * -* @param x input value -* @param y input value +* @param x base +* @param y exponent * @return output value * * @example @@ -230,39 +225,37 @@ double y_is_infinite( const double x, const double y ) { * double out = y_is_huge( -3.14, -3.6893488147419103e19 ); * // returns 0.0 */ -double y_is_huge( const double x, const double y ) { +static double y_is_huge( const double x, const double y ) { + uint32_t ahx; uint32_t hx; - double ahx; - double xc; - xc = x; - stdlib_base_float64_get_high_word( xc, &hx ); + stdlib_base_float64_get_high_word( x, &hx ); ahx = ( hx & STDLIB_CONSTANT_FLOAT64_HIGH_WORD_ABS_MASK ); if ( ahx <= HIGH_MAX_NEAR_UNITY ) { if ( y < 0 ) { // Signal overflow... - return HUGE * HUGE; + return HUGE_VALUE * HUGE_VALUE; } // Signal underflow... - return TINY * TINY; + return TINY_VALUE * TINY_VALUE; } // `x` has a biased exponent greater than or equal to `0`... if ( y > 0 ) { // Signal overflow... - return HUGE * HUGE; + return HUGE_VALUE * HUGE_VALUE; } // Signal underflow... - return TINY * TINY; + return TINY_VALUE * TINY_VALUE; } /** * Evaluates the exponential function when \\(|x| = 0\\). * -* @param x input value -* @param y input value -* @return output value +* @param x base +* @param y exponent +* @return output value * * @example * double out = x_is_zero( 0.0, 2 ); @@ -272,7 +265,7 @@ double y_is_huge( const double x, const double y ) { * double out = x_is_zero( 0.0, -9 ); * // returns Infinity */ -double x_is_zero( const double x, const double y ) { +static double x_is_zero( const double x, const double y ) { if ( y == STDLIB_CONSTANT_FLOAT64_NINF ) { return STDLIB_CONSTANT_FLOAT64_PINF; } @@ -295,17 +288,24 @@ double x_is_zero( const double x, const double y ) { /** * Computes \\(2^{\mathrm{hp} + \mathrm{lp}\\). * -* @param j high word of hp + lp -* @param hp first power summand -* @param lp second power summand -* @return function value +* @param j high word of `hp + lp` +* @param hp first power summand +* @param lp second power summand +* @return function value * * @example * double out = pow2( 1065961648, -0.3398475646972656, -0.000002438187359100815 ); * // returns ~0.79 */ -double pow2( const uint32_t j, const double hp, const double lp ) { - int32_t tmp; +static double pow2( const int32_t j, const double hp, const double lp ) { + uint32_t jcc; + uint32_t tmp; + double hpc; + int32_t jc; + int32_t nc; + int32_t i; + int32_t k; + int32_t n; double t1; double t; double r; @@ -313,30 +313,26 @@ double pow2( const uint32_t j, const double hp, const double lp ) { double v; double w; double z; - int32_t n; - uint32_t i; - int32_t k; - int32_t jc; - uint32_t jcc; - double hpc; hpc = hp; jc = j; - jcc = j; + jcc = (uint32_t)j; i = ( j & STDLIB_CONSTANT_FLOAT64_HIGH_WORD_ABS_MASK ); k = ( ( i >> HIGH_NUM_SIGNIFICAND_BITS ) - STDLIB_CONSTANT_FLOAT64_EXPONENT_BIAS ); n = 0; + nc = (int32_t)n; // `|z| > 0.5`, set `n = z+0.5` if ( i > HIGH_BIASED_EXP_NEG_1 ) { - n = ( j + ( HIGH_MIN_NORMAL_EXP >> ( k + 1 ) ) ) >> 0; // asm type annotation + n = ( j + ( HIGH_MIN_NORMAL_EXP >> ( k + 1 ) ) ); k = ( ( ( n & STDLIB_CONSTANT_FLOAT64_HIGH_WORD_ABS_MASK ) >> HIGH_NUM_SIGNIFICAND_BITS ) - STDLIB_CONSTANT_FLOAT64_EXPONENT_BIAS ); // new k for n - tmp = ( ( n & !( HIGH_SIGNIFICAND_MASK >> k ) ) ) >> 0; // asm type annotation + tmp = ( ( n & ~( HIGH_SIGNIFICAND_MASK >> k ) ) ); t = 0.0; stdlib_base_float64_set_high_word( tmp, &t ); - n = ( ( ( n & HIGH_SIGNIFICAND_MASK ) | HIGH_MIN_NORMAL_EXP ) >> ( HIGH_NUM_SIGNIFICAND_BITS - k ) ) >> 0; // eslint-disable-line max-len + n = ( ( ( n & HIGH_SIGNIFICAND_MASK ) | HIGH_MIN_NORMAL_EXP ) >> ( HIGH_NUM_SIGNIFICAND_BITS - k ) ); + nc = (int32_t)n; if ( jc < 0 ) { - n = -n; + nc = -nc; } hpc -= t; } @@ -351,12 +347,13 @@ double pow2( const uint32_t j, const double hp, const double lp ) { r = ( ( z * t1 ) / ( t1 - 2.0 ) ) - ( w + ( z * w ) ); z = 1.0 - ( r - z ); stdlib_base_float64_get_high_word( z, &jcc ); - jc = jcc|0; - jc += ( n << HIGH_NUM_SIGNIFICAND_BITS ) >> 0; // asm type annotation + jc = (int32_t)jcc; + jcc = jc + ( nc << HIGH_NUM_SIGNIFICAND_BITS ); + jc = (int32_t)jcc; // Check for subnormal output... if ( ( jc >> HIGH_NUM_SIGNIFICAND_BITS ) <= 0 ) { - z = stdlib_base_ldexp( z, n ); + z = stdlib_base_ldexp( z, nc ); } else { stdlib_base_float64_set_high_word( jcc, &z ); } @@ -366,15 +363,14 @@ double pow2( const uint32_t j, const double hp, const double lp ) { /** * Computes \\(\operatorname{log}(x)\\) assuming \\(|1-x|\\) is small and using the approximation \\(x - x^2/2 + x^3/3 - x^4/4\\). * -* @param out output array * @param ax absolute value of x -* @return output array containing a tuple comprised of high and low parts +* @param o1 destination for output1 +* @param o2 destination for output2 * * @example -* double out[2] = logx( [ 0.0, 0.0 ], 9.0 ); // => [ t1, t2 ] -* // returns [ -1265.7236328125, -0.0008163940840404393 ] +* logx( 9.0, &o1, &o2 ); */ -void logx( double *out, const double ax ) { +void logx( const double ax, double *o1, double *o2 ) { double t2; double t1; double t; @@ -390,25 +386,29 @@ void logx( double *out, const double ax ) { stdlib_base_float64_set_low_word( 0, &t1 ); t2 = v - (t1 - u); - out[ 0 ] = t1; - out[ 1 ] = t2; + *o1 = t1; + *o2 = t2; } /** * Computes \\(\operatorname{log2}(ax)\\). * -* @param out output array * @param ax absolute value of x * @param ahx high word of ax -* @return output array containing a tuple comprised of high and low parts +* @param o1 destination for output1 +* @param o2 destination for output2 * * @example -* double out[2] = logax( [ 0.0, 0.0 ], 9.0, 1075970048 ); // => [ t1, t2 ] -* // returns [ 3.169923782348633, 0.0000012190936795504075 ] +* log2ax( 9.0, 1075970048, &o1, &o2 ); */ -void log2ax( double *out, const double ax, const uint32_t ahx ) { - uint32_t ahxc; +void log2ax( const double ax, const int32_t ahx, double *o1, double *o2 ) { + uint32_t ahxcc; uint32_t tmp; + int32_t ahxc; + double axc; + int32_t n; + int32_t j; + int32_t k; double ss; // hs + ls double s2; // ss squared double hs; @@ -427,20 +427,17 @@ void log2ax( double *out, const double ax, const uint32_t ahx ) { double r; double u; double v; - int32_t n; - int32_t j; - uint32_t k; - double axc; n = 0; axc = ax; ahxc = ahx; - + ahxcc = (uint32_t)ahx; // Check if `x` is subnormal... if ( ahxc < HIGH_MIN_NORMAL_EXP ) { axc *= TWO53; n -= 53; - stdlib_base_float64_get_high_word( axc, &ahxc ); + stdlib_base_float64_get_high_word( axc, &ahxcc ); + ahxc = (int32_t)ahxcc; } // Extract the unbiased exponent of `x`: n += ( ( ahxc >> HIGH_NUM_SIGNIFICAND_BITS ) - STDLIB_CONSTANT_FLOAT64_EXPONENT_BIAS ); @@ -467,8 +464,9 @@ void log2ax( double *out, const double ax, const uint32_t ahx ) { n += 1; ahxc -= HIGH_MIN_NORMAL_EXP; } + ahxcc = (uint32_t)ahxc; // Load the normalized high word into `|x|`: - stdlib_base_float64_set_high_word( ahxc, &axc ); + stdlib_base_float64_set_high_word( ahxcc, &axc ); // Compute `ss = hs + ls = (x-1)/(x+1)` or `(x-1.5)/(x+1.5)`: bp = BP[ k ]; // BP[0] = 1.0, BP[1] = 1.5 @@ -514,8 +512,8 @@ void log2ax( double *out, const double ax, const uint32_t ahx ) { stdlib_base_float64_set_low_word( 0, &t1 ); t2 = lz - ( ( ( t1 - t ) - dp ) - hz ); - out[ 0 ] = t1; - out[ 1 ] = t2; + *o1 = t1; + *o2 = t2; } /** @@ -534,30 +532,32 @@ void log2ax( double *out, const double ax, const uint32_t ahx ) { * // returns 2.0 */ double stdlib_base_pow( const double x, const double y ) { - uint32_t ahx; // absolute value high word `x` - uint32_t ahy; // absolute value high word `y` - double ax; // absolute value `x` uint32_t hx; // high word `x` uint32_t lx; // low word `x` uint32_t hy; // high word `y` uint32_t ly; // low word `y` + int32_t ahx; // absolute value high word `x` + int32_t ahy; // absolute value high word `y` + uint32_t i; + uint32_t j; + int32_t ic; + int32_t jc; int32_t sx; // sign `x` int32_t sy; // sign `y` + double ax; // absolute value `x` double y1; double hp; double lp; - double t[ 2 ] = {0.0, 0.0}; - double z; // y prime - uint32_t j; - uint32_t i; + double t1; + double t2; double xc; - int32_t jc; - int32_t ic; + double z; // y prime xc = x; if ( stdlib_base_is_nan( xc ) || stdlib_base_is_nan( y ) ) { return 0.0/0.0; // NaN } + // Split `y` into high and low words: stdlib_base_float64_to_words( y, &hy, &ly ); @@ -594,7 +594,6 @@ double stdlib_base_pow( const double x, const double y ) { } // Split `x` into high and low words: stdlib_base_float64_to_words( xc, &hx, &lx ); - // Special cases `x`... if ( lx == 0 ) { if ( hx == 0 ) { @@ -632,11 +631,9 @@ double stdlib_base_pow( const double x, const double y ) { // Remove the sign bits (i.e., get absolute values): ahx = ( hx & STDLIB_CONSTANT_FLOAT64_HIGH_WORD_ABS_MASK ); ahy = ( hy & STDLIB_CONSTANT_FLOAT64_HIGH_WORD_ABS_MASK ); - // Extract the sign bits: sx = ( hx >> HIGH_NUM_NONSIGN_BITS ); sy = ( hy >> HIGH_NUM_NONSIGN_BITS ); - // Determine the sign of the result... if ( sx && stdlib_base_is_odd( y ) ) { sx = -1; @@ -657,69 +654,64 @@ double stdlib_base_pow( const double x, const double y ) { // y < 0 if ( sy == 1 ) { // Signal overflow... - return sx * HUGE * HUGE; + return sx * HUGE_VALUE * HUGE_VALUE; } // Signal underflow... - return sx * TINY * TINY; + return sx * TINY_VALUE * TINY_VALUE; } if ( ahx > HIGH_BIASED_EXP_0 ) { // y > 0 if ( sy == 0 ) { // Signal overflow... - return sx * HUGE * HUGE; + return sx * HUGE_VALUE * HUGE_VALUE; } // Signal underflow... - return sx * TINY * TINY; + return sx * TINY_VALUE * TINY_VALUE; } // At this point, `|1-x|` is tiny (`<= 2^-20`). Suffice to compute `log(x)` by `x - x^2/2 + x^3/3 - x^4/4`. - t[0] = LOG_WORKSPACE[0]; - t[1] = LOG_WORKSPACE[1]; - logx( t, ax ); + logx( ax, &t1, &t2 ); } // Case 2: `|y|` is not huge... else { - t[0] = LOG_WORKSPACE[0]; - t[1] = LOG_WORKSPACE[1]; - log2ax( t, ax, ahx ); + log2ax( ax, ahx, &t1, &t2 ); } // Split `y` into `y1 + y2` and compute `(y1+y2) * (t1+t2)`... y1 = y; stdlib_base_float64_set_low_word( 0, &y1 ); - lp = ( ( y - y1 ) * t[0] ) + ( y * t[1] ); - hp = y1 * t[0]; + lp = ( ( y - y1 ) * t1 ) + ( y * t2 ); + hp = y1 * t1; z = lp + hp; // Note: *can* be more performant to use `getHighWord` and `getLowWord` directly, but using `toWords` looks cleaner. stdlib_base_float64_to_words( z, &j, &i ); - jc = j; - ic = i; + jc = (int32_t)j; + ic = (int32_t)i; // z >= 1024 if ( jc >= HIGH_BIASED_EXP_10 ) { // z > 1024 if ( ( ( jc - HIGH_BIASED_EXP_10 )|ic ) != 0 ) { // Signal overflow... - return sx * HUGE * HUGE; + return sx * HUGE_VALUE * HUGE_VALUE; } if ( ( lp + OVT ) > ( z - hp ) ) { // Signal overflow... - return sx * HUGE * HUGE; + return sx * HUGE_VALUE * HUGE_VALUE; } } // z <= -1075 - else if ( ( jc & STDLIB_CONSTANT_FLOAT64_HIGH_WORD_ABS_MASK ) >= HIGH_1075 ) { + else if ( ( j & STDLIB_CONSTANT_FLOAT64_HIGH_WORD_ABS_MASK ) >= HIGH_1075 ) { // z < -1075 - if ( ( ( jc - HIGH_NEG_1075 )|ic ) != 0 ) { + if ( ( ( j - HIGH_NEG_1075 )|i ) != 0 ) { // Signal underflow... - return sx * TINY * TINY; + return sx * TINY_VALUE * TINY_VALUE; } if ( lp <= ( z - hp ) ) { // Signal underflow... - return sx * TINY * TINY; + return sx * TINY_VALUE * TINY_VALUE; } } // Compute `2^(hp+lp)`... z = pow2( jc, hp, lp ); - return sx * z; } From 300f9d3604dbcd38200bef08c71fdb236163acc2 Mon Sep 17 00:00:00 2001 From: aman-095 Date: Wed, 13 Mar 2024 14:47:09 +0530 Subject: [PATCH 15/18] chore: apply review changes --- .../base/special/pow/examples/c/example.c | 20 ++++---- .../@stdlib/math/base/special/pow/src/main.c | 46 +++++++++---------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/lib/node_modules/@stdlib/math/base/special/pow/examples/c/example.c b/lib/node_modules/@stdlib/math/base/special/pow/examples/c/example.c index 6eb35dea0850..ee26d99bea68 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/examples/c/example.c +++ b/lib/node_modules/@stdlib/math/base/special/pow/examples/c/example.c @@ -21,15 +21,15 @@ #include int main( void ) { - double out; - double b; - double x; - int i; + double out; + double b; + double x; + int i; - for ( i = 0; i < 100; i++ ) { - b = ( ( (double)rand() / (double)RAND_MAX ) * 10.0 ); - x = ( ( (double)rand() / (double)RAND_MAX ) * 10.0 ) - 5.0; - out = stdlib_base_pow( b, x ); - printf( "pow(%lf, %lf) = %lf\n", b, x, out ); - } + for ( i = 0; i < 100; i++ ) { + b = ( ( (double)rand() / (double)RAND_MAX ) * 10.0 ); + x = ( ( (double)rand() / (double)RAND_MAX ) * 10.0 ) - 5.0; + out = stdlib_base_pow( b, x ); + printf( "pow(%lf, %lf) = %lf\n", b, x, out ); + } } diff --git a/lib/node_modules/@stdlib/math/base/special/pow/src/main.c b/lib/node_modules/@stdlib/math/base/special/pow/src/main.c index 11f85dc28827..1ba8af724bda 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/src/main.c +++ b/lib/node_modules/@stdlib/math/base/special/pow/src/main.c @@ -196,18 +196,18 @@ static double polyval_p( const double x ) { * // returns 0.0 */ static double y_is_infinite( const double x, const double y ) { - if ( x == -1.0 ) { - return 0.0 / 0.0; // NaN - } - if ( x == 1.0 ) { - return 1.0; - } + if ( x == -1.0 ) { + return 0.0 / 0.0; // NaN + } + if ( x == 1.0 ) { + return 1.0; + } // (|x| > 1 && y == NINF) || (|x| < 1 && y === PINF) if ( ( stdlib_base_abs( x ) < 1.0 ) == ( y == STDLIB_CONSTANT_FLOAT64_PINF ) ) { return 0.0; } // (|x| > 1 && y == PINF) || (|x| < 1 && y == NINF) - return STDLIB_CONSTANT_FLOAT64_PINF; + return STDLIB_CONSTANT_FLOAT64_PINF; } /** @@ -229,23 +229,23 @@ static double y_is_huge( const double x, const double y ) { uint32_t ahx; uint32_t hx; - stdlib_base_float64_get_high_word( x, &hx ); - ahx = ( hx & STDLIB_CONSTANT_FLOAT64_HIGH_WORD_ABS_MASK ); + stdlib_base_float64_get_high_word( x, &hx ); + ahx = ( hx & STDLIB_CONSTANT_FLOAT64_HIGH_WORD_ABS_MASK ); - if ( ahx <= HIGH_MAX_NEAR_UNITY ) { - if ( y < 0 ) { + if ( ahx <= HIGH_MAX_NEAR_UNITY ) { + if ( y < 0 ) { // Signal overflow... - return HUGE_VALUE * HUGE_VALUE; - } + return HUGE_VALUE * HUGE_VALUE; + } // Signal underflow... - return TINY_VALUE * TINY_VALUE; - } + return TINY_VALUE * TINY_VALUE; + } // `x` has a biased exponent greater than or equal to `0`... - if ( y > 0 ) { + if ( y > 0 ) { // Signal overflow... - return HUGE_VALUE * HUGE_VALUE; - } + return HUGE_VALUE * HUGE_VALUE; + } // Signal underflow... return TINY_VALUE * TINY_VALUE; } @@ -266,9 +266,9 @@ static double y_is_huge( const double x, const double y ) { * // returns Infinity */ static double x_is_zero( const double x, const double y ) { - if ( y == STDLIB_CONSTANT_FLOAT64_NINF ) { - return STDLIB_CONSTANT_FLOAT64_PINF; - } + if ( y == STDLIB_CONSTANT_FLOAT64_NINF ) { + return STDLIB_CONSTANT_FLOAT64_PINF; + } if ( y == STDLIB_CONSTANT_FLOAT64_PINF ) { return 0.0; } @@ -323,7 +323,7 @@ static double pow2( const int32_t j, const double hp, const double lp ) { nc = (int32_t)n; // `|z| > 0.5`, set `n = z+0.5` - if ( i > HIGH_BIASED_EXP_NEG_1 ) { + if ( i > HIGH_BIASED_EXP_NEG_1 ) { n = ( j + ( HIGH_MIN_NORMAL_EXP >> ( k + 1 ) ) ); k = ( ( ( n & STDLIB_CONSTANT_FLOAT64_HIGH_WORD_ABS_MASK ) >> HIGH_NUM_SIGNIFICAND_BITS ) - STDLIB_CONSTANT_FLOAT64_EXPONENT_BIAS ); // new k for n tmp = ( ( n & ~( HIGH_SIGNIFICAND_MASK >> k ) ) ); @@ -335,7 +335,7 @@ static double pow2( const int32_t j, const double hp, const double lp ) { nc = -nc; } hpc -= t; - } + } t = lp + hpc; stdlib_base_float64_set_low_word( 0, &t ); u = t * LN2_HI; From 922a55e23537bffe6e9322b2cac9c413cdc5f695 Mon Sep 17 00:00:00 2001 From: Philipp Burckhardt Date: Fri, 7 Jun 2024 10:14:11 -0400 Subject: [PATCH 16/18] style: fix indentation, add empty lines before comments where applicable --- .../@stdlib/math/base/special/pow/src/main.c | 44 ++++++++++--------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/lib/node_modules/@stdlib/math/base/special/pow/src/main.c b/lib/node_modules/@stdlib/math/base/special/pow/src/main.c index 1ba8af724bda..6a653e2c3b82 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/src/main.c +++ b/lib/node_modules/@stdlib/math/base/special/pow/src/main.c @@ -185,7 +185,7 @@ static double polyval_p( const double x ) { * * @param x base * @param y exponent -* @return output value +* @return output value * * @example * double out = y_is_infinite( -1.0, 1.0/0.0 ); @@ -215,7 +215,7 @@ static double y_is_infinite( const double x, const double y ) { * * @param x base * @param y exponent -* @return output value +* @return output value * * @example * double out = y_is_huge( 9.0, 3.6893488147419103e19 ); @@ -253,9 +253,9 @@ static double y_is_huge( const double x, const double y ) { /** * Evaluates the exponential function when \\(|x| = 0\\). * -* @param x base -* @param y exponent -* @return output value +* @param x base +* @param y exponent +* @return output value * * @example * double out = x_is_zero( 0.0, 2 ); @@ -288,10 +288,10 @@ static double x_is_zero( const double x, const double y ) { /** * Computes \\(2^{\mathrm{hp} + \mathrm{lp}\\). * -* @param j high word of `hp + lp` -* @param hp first power summand -* @param lp second power summand -* @return function value +* @param j high word of `hp + lp` +* @param hp first power summand +* @param lp second power summand +* @return function value * * @example * double out = pow2( 1065961648, -0.3398475646972656, -0.000002438187359100815 ); @@ -393,10 +393,10 @@ void logx( const double ax, double *o1, double *o2 ) { /** * Computes \\(\operatorname{log2}(ax)\\). * -* @param ax absolute value of x +* @param ax absolute value of x * @param ahx high word of ax -* @param o1 destination for output1 -* @param o2 destination for output2 +* @param o1 destination for output1 +* @param o2 destination for output2 * * @example * log2ax( 9.0, 1075970048, &o1, &o2 ); @@ -465,6 +465,7 @@ void log2ax( const double ax, const int32_t ahx, double *o1, double *o2 ) { ahxc -= HIGH_MIN_NORMAL_EXP; } ahxcc = (uint32_t)ahxc; + // Load the normalized high word into `|x|`: stdlib_base_float64_set_high_word( ahxcc, &axc ); @@ -521,7 +522,7 @@ void log2ax( const double ax, const int32_t ahx, double *o1, double *o2 ) { * * @param x base * @param y exponent -* @return function value +* @return function value * * @example * double out = stdlib_base_pow( 2.0, 3.0 ); @@ -532,10 +533,10 @@ void log2ax( const double ax, const int32_t ahx, double *o1, double *o2 ) { * // returns 2.0 */ double stdlib_base_pow( const double x, const double y ) { - uint32_t hx; // high word `x` - uint32_t lx; // low word `x` - uint32_t hy; // high word `y` - uint32_t ly; // low word `y` + uint32_t hx; // high word `x` + uint32_t lx; // low word `x` + uint32_t hy; // high word `y` + uint32_t ly; // low word `y` int32_t ahx; // absolute value high word `x` int32_t ahy; // absolute value high word `y` uint32_t i; @@ -544,14 +545,14 @@ double stdlib_base_pow( const double x, const double y ) { int32_t jc; int32_t sx; // sign `x` int32_t sy; // sign `y` - double ax; // absolute value `x` + double ax; // absolute value `x` double y1; double hp; double lp; double t1; double t2; double xc; - double z; // y prime + double z; // y prime xc = x; if ( stdlib_base_is_nan( xc ) || stdlib_base_is_nan( y ) ) { @@ -594,6 +595,7 @@ double stdlib_base_pow( const double x, const double y ) { } // Split `x` into high and low words: stdlib_base_float64_to_words( xc, &hx, &lx ); + // Special cases `x`... if ( lx == 0 ) { if ( hx == 0 ) { @@ -631,9 +633,11 @@ double stdlib_base_pow( const double x, const double y ) { // Remove the sign bits (i.e., get absolute values): ahx = ( hx & STDLIB_CONSTANT_FLOAT64_HIGH_WORD_ABS_MASK ); ahy = ( hy & STDLIB_CONSTANT_FLOAT64_HIGH_WORD_ABS_MASK ); + // Extract the sign bits: sx = ( hx >> HIGH_NUM_NONSIGN_BITS ); sy = ( hy >> HIGH_NUM_NONSIGN_BITS ); + // Determine the sign of the result... if ( sx && stdlib_base_is_odd( y ) ) { sx = -1; @@ -649,7 +653,6 @@ double stdlib_base_pow( const double x, const double y ) { return y_is_huge( xc, y ); } // Over- or underflow if `x` is not close to unity... - if ( ahx < HIGH_MAX_NEAR_UNITY ) { // y < 0 if ( sy == 1 ) { @@ -675,6 +678,7 @@ double stdlib_base_pow( const double x, const double y ) { else { log2ax( ax, ahx, &t1, &t2 ); } + // Split `y` into `y1 + y2` and compute `(y1+y2) * (t1+t2)`... y1 = y; stdlib_base_float64_set_low_word( 0, &y1 ); From a20a1fb3f0623fcff28cf360bbd33f02d0fe03e4 Mon Sep 17 00:00:00 2001 From: Philipp Burckhardt Date: Wed, 19 Jun 2024 20:37:34 +0000 Subject: [PATCH 17/18] test: increase tolerance due to divergence from compiler optimizations --- .../math/base/special/pow/test/test.native.js | 75 +++++++++++++++++-- 1 file changed, 68 insertions(+), 7 deletions(-) diff --git a/lib/node_modules/@stdlib/math/base/special/pow/test/test.native.js b/lib/node_modules/@stdlib/math/base/special/pow/test/test.native.js index 639a00b35600..9fafa645e19d 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/test/test.native.js +++ b/lib/node_modules/@stdlib/math/base/special/pow/test/test.native.js @@ -221,6 +221,8 @@ tape( 'the function evaluates the exponential function (`x ~ 1`, `y` large)', op tape( 'the function evaluates the exponential function (`x ~ 1`, `y` huge)', opts, function test( t ) { var expected; var actual; + var delta; + var tol; var x; var y; var i; @@ -230,7 +232,14 @@ tape( 'the function evaluates the exponential function (`x ~ 1`, `y` huge)', opt expected = baseNearUnityHuge.expected; for ( i = 0; i < x.length; i++ ) { actual = pow( x[i], y[i] ); - t.equal( actual, expected[i], 'pow('+x[i]+','+y[i]+') returns '+expected[i] ); + if ( actual === expected[i] ) { + t.strictEqual( actual, expected[i], 'pow('+x[i]+','+y[i]+') returns '+expected[i] ); + } else { + // NOTE: the results may differ slightly from the reference and JavaScript implementations 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 + delta = abs( actual - expected[i] ); + tol = EPS * abs( expected[i] ); + t.ok( delta <= tol, 'within tolerance. pow('+x[i]+','+y[i]+'). Expected: '+expected[i]+'. Actual: '+actual+'. Delta: '+delta+'. Tol: '+tol+'.' ); + } } t.end(); }); @@ -411,6 +420,8 @@ tape( 'the function evaluates the exponential function (near underflow)', opts, tape( 'the function evaluates the exponential function (small `x`, large `y`)', opts, function test( t ) { var expected; var actual; + var delta; + var tol; var x; var y; var i; @@ -422,8 +433,13 @@ tape( 'the function evaluates the exponential function (small `x`, large `y`)', actual = pow( x[i], y[i] ); if ( expected[i] === 5.0e-324 ) { t.equal( actual === expected[i] || actual === 0.0, true, 'pow('+x[i]+','+y[i]+') returns 5e-324 or 0' ); + } else if ( actual === expected[i] ) { + t.strictEqual( actual, expected[i], 'pow('+x[i]+','+y[i]+') returns '+expected[i] ); } else { - t.equal( actual, expected[i], 'pow('+x[i]+','+y[i]+') returns '+expected[i] ); + // NOTE: the results may differ slightly from the reference and JavaScript implementations 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 + delta = abs( actual - expected[i] ); + tol = EPS * abs( expected[i] ); + t.ok( delta <= tol, 'within tolerance. pow('+x[i]+','+y[i]+'). Expected: '+expected[i]+'. Actual: '+actual+'. Delta: '+delta+'. Tol: '+tol+'.' ); } } t.end(); @@ -449,6 +465,8 @@ tape( 'the function evaluates the exponential function (large `x`, small `y`)', tape( 'the function evaluates the exponential function (small `x`, small `y`)', opts, function test( t ) { var expected; var actual; + var delta; + var tol; var x; var y; var i; @@ -458,7 +476,14 @@ tape( 'the function evaluates the exponential function (small `x`, small `y`)', expected = smallSmall.expected; for ( i = 0; i < x.length; i++ ) { actual = pow( x[i], y[i] ); - t.equal( actual, expected[i], 'pow('+x[i]+','+y[i]+') returns '+expected[i] ); + if ( actual === expected[i] ) { + t.strictEqual( actual, expected[i], 'pow('+x[i]+','+y[i]+') returns '+expected[i] ); + } else { + // NOTE: the results may differ slightly from the reference and JavaScript implementations 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 + delta = abs( actual - expected[i] ); + tol = EPS * abs( expected[i] ); + t.ok( delta <= tol, 'within tolerance. pow('+x[i]+','+y[i]+'). Expected: '+expected[i]+'. Actual: '+actual+'. Delta: '+delta+'. Tol: '+tol+'.' ); + } } t.end(); }); @@ -466,6 +491,8 @@ tape( 'the function evaluates the exponential function (small `x`, small `y`)', tape( 'the function evaluates the exponential function (decimal `x`, decimal `y`)', opts, function test( t ) { var expected; var actual; + var delta; + var tol; var x; var y; var i; @@ -475,7 +502,14 @@ tape( 'the function evaluates the exponential function (decimal `x`, decimal `y` expected = decimalDecimal.expected; for ( i = 0; i < x.length; i++ ) { actual = pow( x[i], y[i] ); - t.equal( actual, expected[i], 'pow('+x[i]+','+y[i]+') returns '+expected[i] ); + if ( actual === expected[i] ) { + t.strictEqual( actual, expected[i], 'pow('+x[i]+','+y[i]+') returns '+expected[i] ); + } else { + // NOTE: the results may differ slightly from the reference and JavaScript implementations 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 + delta = abs( actual - expected[i] ); + tol = EPS * abs( expected[i] ); + t.ok( delta <= tol, 'within tolerance. pow('+x[i]+','+y[i]+'). Expected: '+expected[i]+'. Actual: '+actual+'. Delta: '+delta+'. Tol: '+tol+'.' ); + } } t.end(); }); @@ -483,6 +517,8 @@ tape( 'the function evaluates the exponential function (decimal `x`, decimal `y` tape( 'the function evaluates the exponential function (decimal `x`, integer `y`)', opts, function test( t ) { var expected; var actual; + var delta; + var tol; var x; var y; var i; @@ -492,7 +528,14 @@ tape( 'the function evaluates the exponential function (decimal `x`, integer `y` expected = decimalInteger.expected; for ( i = 0; i < x.length; i++ ) { actual = pow( x[i], y[i] ); - t.equal( actual, expected[i], 'pow('+x[i]+','+y[i]+') returns '+expected[i] ); + if ( actual === expected[i] ) { + t.strictEqual( actual, expected[i], 'pow('+x[i]+','+y[i]+') returns '+expected[i] ); + } else { + // NOTE: the results may differ slightly from the reference and JavaScript implementations 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 + delta = abs( actual - expected[i] ); + tol = EPS * abs( expected[i] ); + t.ok( delta <= tol, 'within tolerance. pow('+x[i]+','+y[i]+'). Expected: '+expected[i]+'. Actual: '+actual+'. Delta: '+delta+'. Tol: '+tol+'.' ); + } } t.end(); }); @@ -500,6 +543,8 @@ tape( 'the function evaluates the exponential function (decimal `x`, integer `y` tape( 'the function evaluates the exponential function (integer `x`, decimal `y`)', opts, function test( t ) { var expected; var actual; + var delta; + var tol; var x; var y; var i; @@ -509,7 +554,14 @@ tape( 'the function evaluates the exponential function (integer `x`, decimal `y` expected = integerDecimal.expected; for ( i = 0; i < x.length; i++ ) { actual = pow( x[i], y[i] ); - t.equal( actual, expected[i], 'pow('+x[i]+','+y[i]+') returns '+expected[i] ); + if ( actual === expected[i] ) { + t.strictEqual( actual, expected[i], 'pow('+x[i]+','+y[i]+') returns '+expected[i] ); + } else { + // NOTE: the results may differ slightly from the reference and JavaScript implementations 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 + delta = abs( actual - expected[i] ); + tol = EPS * abs( expected[i] ); + t.ok( delta <= tol, 'within tolerance. pow('+x[i]+','+y[i]+'). Expected: '+expected[i]+'. Actual: '+actual+'. Delta: '+delta+'. Tol: '+tol+'.' ); + } } t.end(); }); @@ -517,6 +569,8 @@ tape( 'the function evaluates the exponential function (integer `x`, decimal `y` tape( 'the function evaluates the exponential function (integer `x`, integer `y`)', opts, function test( t ) { var expected; var actual; + var delta; + var tol; var x; var y; var i; @@ -526,7 +580,14 @@ tape( 'the function evaluates the exponential function (integer `x`, integer `y` expected = integerInteger.expected; for ( i = 0; i < x.length; i++ ) { actual = pow( x[i], y[i] ); - t.equal( actual, expected[i], 'pow('+x[i]+','+y[i]+') returns '+expected[i] ); + if ( actual === expected[i] ) { + t.strictEqual( actual, expected[i], 'pow('+x[i]+','+y[i]+') returns '+expected[i] ); + } else { + // NOTE: the results may differ slightly from the reference and JavaScript implementations 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 + delta = abs( actual - expected[i] ); + tol = EPS * abs( expected[i] ); + t.ok( delta <= tol, 'within tolerance. pow('+x[i]+','+y[i]+'). Expected: '+expected[i]+'. Actual: '+actual+'. Delta: '+delta+'. Tol: '+tol+'.' ); + } } t.end(); }); From feb89d6768d1092b7e7d1226b32cb59f95d08d8c Mon Sep 17 00:00:00 2001 From: Philipp Burckhardt Date: Wed, 19 Jun 2024 21:04:45 +0000 Subject: [PATCH 18/18] fix: address cppcheck lint errors --- .../@stdlib/math/base/special/pow/src/main.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/lib/node_modules/@stdlib/math/base/special/pow/src/main.c b/lib/node_modules/@stdlib/math/base/special/pow/src/main.c index 6a653e2c3b82..29360167b486 100644 --- a/lib/node_modules/@stdlib/math/base/special/pow/src/main.c +++ b/lib/node_modules/@stdlib/math/base/special/pow/src/main.c @@ -297,8 +297,7 @@ static double x_is_zero( const double x, const double y ) { * double out = pow2( 1065961648, -0.3398475646972656, -0.000002438187359100815 ); * // returns ~0.79 */ -static double pow2( const int32_t j, const double hp, const double lp ) { - uint32_t jcc; +static double pow2( uint32_t j, const double hp, const double lp ) { uint32_t tmp; double hpc; int32_t jc; @@ -315,8 +314,7 @@ static double pow2( const int32_t j, const double hp, const double lp ) { double z; hpc = hp; - jc = j; - jcc = (uint32_t)j; + jc = (int32_t)j; i = ( j & STDLIB_CONSTANT_FLOAT64_HIGH_WORD_ABS_MASK ); k = ( ( i >> HIGH_NUM_SIGNIFICAND_BITS ) - STDLIB_CONSTANT_FLOAT64_EXPONENT_BIAS ); n = 0; @@ -346,16 +344,15 @@ static double pow2( const int32_t j, const double hp, const double lp ) { t1 = z - ( t * polyval_p( t ) ); r = ( ( z * t1 ) / ( t1 - 2.0 ) ) - ( w + ( z * w ) ); z = 1.0 - ( r - z ); - stdlib_base_float64_get_high_word( z, &jcc ); - jc = (int32_t)jcc; - jcc = jc + ( nc << HIGH_NUM_SIGNIFICAND_BITS ); - jc = (int32_t)jcc; + stdlib_base_float64_get_high_word( z, &j ); + j = j + ( nc << HIGH_NUM_SIGNIFICAND_BITS ); + jc = (int32_t)j; // Check for subnormal output... if ( ( jc >> HIGH_NUM_SIGNIFICAND_BITS ) <= 0 ) { z = stdlib_base_ldexp( z, nc ); } else { - stdlib_base_float64_set_high_word( jcc, &z ); + stdlib_base_float64_set_high_word( j, &z ); } return z; } @@ -716,6 +713,6 @@ double stdlib_base_pow( const double x, const double y ) { } } // Compute `2^(hp+lp)`... - z = pow2( jc, hp, lp ); + z = pow2( j, hp, lp ); return sx * z; }