Skip to content

Commit b8e6c48

Browse files
committed
fix: preserve the sign of zero
--- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: na - task: lint_package_json status: na - task: lint_repl_help status: na - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: passed - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: passed - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: na - task: lint_typescript_tests status: na - task: lint_license_headers status: passed ---
1 parent b415a2c commit b8e6c48

File tree

4 files changed

+79
-10
lines changed

4 files changed

+79
-10
lines changed

lib/node_modules/@stdlib/blas/ext/base/scusumkbn2/lib/ndarray.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,23 @@ function scusumkbn2( N, sum, x, strideX, offsetX, y, strideY, offsetY ) {
7373
ix = offsetX;
7474
iy = offsetY;
7575

76+
// In order to preserve the sign of zero which can be lost during compensated summation below, find the first non-zero element...
77+
if ( sum === 0.0 ) {
78+
for ( i = 0; i < N; i++ ) {
79+
v = x[ ix ];
80+
if ( v !== 0.0 ) {
81+
break;
82+
}
83+
y[ iy ] = float64ToFloat32( sum + v );
84+
ix += strideX;
85+
iy += strideY;
86+
}
87+
} else {
88+
i = 0;
89+
}
7690
ccs = 0.0; // second order correction term for lost low order bits
7791
cs = 0.0; // first order correction term for lost low order bits
78-
for ( i = 0; i < N; i++ ) {
92+
for ( ; i < N; i++ ) {
7993
v = x[ ix ];
8094
t = float64ToFloat32( sum+v );
8195
if ( abs( sum ) >= abs( v ) ) {

lib/node_modules/@stdlib/blas/ext/base/scusumkbn2/src/main.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@ void API_SUFFIX(stdlib_strided_scusumkbn2)( const CBLAS_INT N, const float sum,
5959
* @param N number of indexed elements
6060
* @param sum initial sum
6161
* @param X input array
62-
* @param strideX stride lengh for X
62+
* @param strideX stride length for X
6363
* @param offsetX starting index for X
6464
* @param Y output array
65-
* @param strideY stride lengt for Y
65+
* @param strideY stride length for Y
6666
* @param offsetY starting index for Y
6767
*/
6868
void API_SUFFIX(stdlib_strided_scusumkbn2_ndarray)( const CBLAS_INT N, const float sum, const float *X, const CBLAS_INT strideX, const CBLAS_INT offsetX, float *Y, const CBLAS_INT strideY, const CBLAS_INT offsetY ) {
@@ -83,9 +83,24 @@ void API_SUFFIX(stdlib_strided_scusumkbn2_ndarray)( const CBLAS_INT N, const flo
8383
ix = offsetX;
8484
iy = offsetY;
8585
s = sum;
86+
87+
// In order to preserve the sign of zero which can be lost during compensated summation below, find the first non-zero element...
88+
if ( s == 0.0 ) {
89+
for ( i = 0; i < N; i++ ) {
90+
v = X[ ix ];
91+
if ( v != 0.0f ) {
92+
break;
93+
}
94+
Y[ iy ] = s + v;
95+
ix += strideX;
96+
iy += strideY;
97+
}
98+
} else {
99+
i = 0;
100+
}
86101
ccs = 0.0f; // second order correction term for lost lower order bits
87102
cs = 0.0f; // first order correction term for lost low order bits
88-
for ( i = 0; i < N; i++ ) {
103+
for ( ; i < N; i++ ) {
89104
v = X[ ix ];
90105
t = s + v;
91106
if ( stdlib_base_absf( s ) >= stdlib_base_absf( v ) ) {

lib/node_modules/@stdlib/blas/ext/base/scusumkbn2/test/test.ndarray.js

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
// MODULES //
2222

2323
var tape = require( 'tape' );
24-
var floor = require( '@stdlib/math/base/special/floor' );
2524
var isnanf = require( '@stdlib/math/base/assert/is-nanf' );
25+
var isSameFloat32Array = require( '@stdlib/assert/is-same-float32array' );
2626
var Float32Array = require( '@stdlib/array/float32' );
2727
var scusumkbn2 = require( './../lib/ndarray.js' );
2828

@@ -127,6 +127,26 @@ tape( 'the function calculates the cumulative sum', function test( t ) {
127127
t.end();
128128
});
129129

130+
tape( 'the function preserves the sign of zero', function test( t ) {
131+
var expected;
132+
var x;
133+
var y;
134+
135+
x = new Float32Array( [ -0.0, -0.0, -0.0, 0.0, 1.0 ] );
136+
y = new Float32Array( x.length );
137+
138+
scusumkbn2( x.length, -0.0, x, 1, 0, y, 1, 0 );
139+
expected = new Float32Array([
140+
-0.0,
141+
-0.0,
142+
-0.0,
143+
0.0,
144+
1.0
145+
]);
146+
t.strictEqual( isSameFloat32Array( y, expected ), true, 'returns expected value' );
147+
t.end();
148+
});
149+
130150
tape( 'the function returns a reference to the output array', function test( t ) {
131151
var out;
132152
var x;
@@ -292,7 +312,7 @@ tape( 'the function supports an `x` offset', function test( t ) {
292312
0.0,
293313
0.0
294314
]);
295-
N = floor( x.length / 2 );
315+
N = 4;
296316

297317
scusumkbn2( N, 0.0, x, 2, 1, y, 1, 0 );
298318

@@ -328,7 +348,7 @@ tape( 'the function supports a `y` offset', function test( t ) {
328348
0.0,
329349
0.0 // 3
330350
]);
331-
N = floor( x.length / 2 );
351+
N = 4;
332352

333353
scusumkbn2( N, 0.0, x, 1, 0, y, 2, 1 );
334354

lib/node_modules/@stdlib/blas/ext/base/scusumkbn2/test/test.ndarray.native.js

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@
2222

2323
var resolve = require( 'path' ).resolve;
2424
var tape = require( 'tape' );
25-
var floor = require( '@stdlib/math/base/special/floor' );
2625
var isnanf = require( '@stdlib/math/base/assert/is-nanf' );
26+
var isSameFloat32Array = require( '@stdlib/assert/is-same-float32array' );
2727
var Float32Array = require( '@stdlib/array/float32' );
2828
var tryRequire = require( '@stdlib/utils/try-require' );
2929

@@ -136,6 +136,26 @@ tape( 'the function calculates the cumulative sum', opts, function test( t ) {
136136
t.end();
137137
});
138138

139+
tape( 'the function preserves the sign of zero', opts, function test( t ) {
140+
var expected;
141+
var x;
142+
var y;
143+
144+
x = new Float32Array( [ -0.0, -0.0, -0.0, 0.0, 1.0 ] );
145+
y = new Float32Array( x.length );
146+
147+
scusumkbn2( x.length, -0.0, x, 1, 0, y, 1, 0 );
148+
expected = new Float32Array([
149+
-0.0,
150+
-0.0,
151+
-0.0,
152+
0.0,
153+
1.0
154+
]);
155+
t.strictEqual( isSameFloat32Array( y, expected ), true, 'returns expected value' );
156+
t.end();
157+
});
158+
139159
tape( 'the function returns a reference to the output array', opts, function test( t ) {
140160
var out;
141161
var x;
@@ -301,7 +321,7 @@ tape( 'the function supports an `x` offset', opts, function test( t ) {
301321
0.0,
302322
0.0
303323
]);
304-
N = floor( x.length / 2 );
324+
N = 4;
305325

306326
scusumkbn2( N, 0.0, x, 2, 1, y, 1, 0 );
307327

@@ -337,7 +357,7 @@ tape( 'the function supports a `y` offset', opts, function test( t ) {
337357
0.0,
338358
0.0 // 3
339359
]);
340-
N = floor( x.length / 2 );
360+
N = 4;
341361

342362
scusumkbn2( N, 0.0, x, 1, 0, y, 2, 1 );
343363

0 commit comments

Comments
 (0)