From c8098dbfe3b198d20f1e5a26c500e689463101ef Mon Sep 17 00:00:00 2001 From: Mantra Patel Date: Tue, 13 Oct 2026 22:10:37 +0530 Subject: [PATCH] fix: advance indices in unrolled loops of portable dcopy and scopy Resolves: #15823 Signed-off-by: Mantra Patel --- .../blas/base/dcopy/src/dcopy_ndarray.c | 2 ++ .../blas/base/dcopy/test/test.ndarray.js | 29 +++++++++++++++++++ .../base/dcopy/test/test.ndarray.native.js | 29 +++++++++++++++++++ .../blas/base/scopy/src/scopy_ndarray.c | 2 ++ .../blas/base/scopy/test/test.ndarray.js | 29 +++++++++++++++++++ .../base/scopy/test/test.ndarray.native.js | 29 +++++++++++++++++++ 6 files changed, 120 insertions(+) diff --git a/lib/node_modules/@stdlib/blas/base/dcopy/src/dcopy_ndarray.c b/lib/node_modules/@stdlib/blas/base/dcopy/src/dcopy_ndarray.c index 2e9d9af5dbbb..63d72ddb4c10 100644 --- a/lib/node_modules/@stdlib/blas/base/dcopy/src/dcopy_ndarray.c +++ b/lib/node_modules/@stdlib/blas/base/dcopy/src/dcopy_ndarray.c @@ -67,6 +67,8 @@ void API_SUFFIX(c_dcopy_ndarray)( const CBLAS_INT N, const double *X, const CBLA Y[ iy+4 ] = X[ ix+4 ]; Y[ iy+5 ] = X[ ix+5 ]; Y[ iy+6 ] = X[ ix+6 ]; + ix += M; + iy += M; } return; } diff --git a/lib/node_modules/@stdlib/blas/base/dcopy/test/test.ndarray.js b/lib/node_modules/@stdlib/blas/base/dcopy/test/test.ndarray.js index 1ebfce341193..330a739d3fe7 100644 --- a/lib/node_modules/@stdlib/blas/base/dcopy/test/test.ndarray.js +++ b/lib/node_modules/@stdlib/blas/base/dcopy/test/test.ndarray.js @@ -296,3 +296,32 @@ tape( 'if both strides are equal to `1`, the function efficiently copies element t.end(); }); + +tape( 'if both strides are equal to `1` and the offsets are non-zero, the function copies all elements spanning multiple unrolled blocks', function test( t ) { + var expected; + var lens; + var x; + var y; + var i; + var j; + + lens = [ 14, 15, 16, 21, 28 ]; + for ( j = 0; j < lens.length; j++ ) { + x = new Float64Array( lens[ j ]+5 ); + y = new Float64Array( lens[ j ]+5 ); + expected = new Float64Array( lens[ j ]+5 ); + for ( i = 0; i < x.length; i++ ) { + x[ i ] = i + 1; + y[ i ] = -1.0; + expected[ i ] = -1.0; + } + for ( i = 0; i < lens[ j ]; i++ ) { + expected[ 3+i ] = x[ 2+i ]; + } + + dcopy( lens[ j ], x, 1, 2, y, 1, 3 ); + + t.deepEqual( y, expected, 'returns expected value when N='+lens[ j ] ); + } + t.end(); +}); diff --git a/lib/node_modules/@stdlib/blas/base/dcopy/test/test.ndarray.native.js b/lib/node_modules/@stdlib/blas/base/dcopy/test/test.ndarray.native.js index d48711c63d4c..0506ee8aab47 100644 --- a/lib/node_modules/@stdlib/blas/base/dcopy/test/test.ndarray.native.js +++ b/lib/node_modules/@stdlib/blas/base/dcopy/test/test.ndarray.native.js @@ -305,3 +305,32 @@ tape( 'if both strides are equal to `1`, the function efficiently copies element t.end(); }); + +tape( 'if both strides are equal to `1` and the offsets are non-zero, the function copies all elements spanning multiple unrolled blocks', opts, function test( t ) { + var expected; + var lens; + var x; + var y; + var i; + var j; + + lens = [ 14, 15, 16, 21, 28 ]; + for ( j = 0; j < lens.length; j++ ) { + x = new Float64Array( lens[ j ]+5 ); + y = new Float64Array( lens[ j ]+5 ); + expected = new Float64Array( lens[ j ]+5 ); + for ( i = 0; i < x.length; i++ ) { + x[ i ] = i + 1; + y[ i ] = -1.0; + expected[ i ] = -1.0; + } + for ( i = 0; i < lens[ j ]; i++ ) { + expected[ 3+i ] = x[ 2+i ]; + } + + dcopy( lens[ j ], x, 1, 2, y, 1, 3 ); + + t.deepEqual( y, expected, 'returns expected value when N='+lens[ j ] ); + } + t.end(); +}); diff --git a/lib/node_modules/@stdlib/blas/base/scopy/src/scopy_ndarray.c b/lib/node_modules/@stdlib/blas/base/scopy/src/scopy_ndarray.c index f9b51171ab05..e755c29e3f60 100644 --- a/lib/node_modules/@stdlib/blas/base/scopy/src/scopy_ndarray.c +++ b/lib/node_modules/@stdlib/blas/base/scopy/src/scopy_ndarray.c @@ -67,6 +67,8 @@ void API_SUFFIX(c_scopy_ndarray)( const CBLAS_INT N, const float *X, const CBLAS Y[ iy+4 ] = X[ ix+4 ]; Y[ iy+5 ] = X[ ix+5 ]; Y[ iy+6 ] = X[ ix+6 ]; + ix += M; + iy += M; } return; } diff --git a/lib/node_modules/@stdlib/blas/base/scopy/test/test.ndarray.js b/lib/node_modules/@stdlib/blas/base/scopy/test/test.ndarray.js index 19fb1552ca0f..9291a52650c4 100644 --- a/lib/node_modules/@stdlib/blas/base/scopy/test/test.ndarray.js +++ b/lib/node_modules/@stdlib/blas/base/scopy/test/test.ndarray.js @@ -296,3 +296,32 @@ tape( 'if both strides are equal to `1`, the function efficiently copies element t.end(); }); + +tape( 'if both strides are equal to `1` and the offsets are non-zero, the function copies all elements spanning multiple unrolled blocks', function test( t ) { + var expected; + var lens; + var x; + var y; + var i; + var j; + + lens = [ 14, 15, 16, 21, 28 ]; + for ( j = 0; j < lens.length; j++ ) { + x = new Float32Array( lens[ j ]+5 ); + y = new Float32Array( lens[ j ]+5 ); + expected = new Float32Array( lens[ j ]+5 ); + for ( i = 0; i < x.length; i++ ) { + x[ i ] = i + 1; + y[ i ] = -1.0; + expected[ i ] = -1.0; + } + for ( i = 0; i < lens[ j ]; i++ ) { + expected[ 3+i ] = x[ 2+i ]; + } + + scopy( lens[ j ], x, 1, 2, y, 1, 3 ); + + t.deepEqual( y, expected, 'returns expected value when N='+lens[ j ] ); + } + t.end(); +}); diff --git a/lib/node_modules/@stdlib/blas/base/scopy/test/test.ndarray.native.js b/lib/node_modules/@stdlib/blas/base/scopy/test/test.ndarray.native.js index 788dc0e6d12e..c27c810a2380 100644 --- a/lib/node_modules/@stdlib/blas/base/scopy/test/test.ndarray.native.js +++ b/lib/node_modules/@stdlib/blas/base/scopy/test/test.ndarray.native.js @@ -305,3 +305,32 @@ tape( 'if both strides are equal to `1`, the function efficiently copies element t.end(); }); + +tape( 'if both strides are equal to `1` and the offsets are non-zero, the function copies all elements spanning multiple unrolled blocks', opts, function test( t ) { + var expected; + var lens; + var x; + var y; + var i; + var j; + + lens = [ 14, 15, 16, 21, 28 ]; + for ( j = 0; j < lens.length; j++ ) { + x = new Float32Array( lens[ j ]+5 ); + y = new Float32Array( lens[ j ]+5 ); + expected = new Float32Array( lens[ j ]+5 ); + for ( i = 0; i < x.length; i++ ) { + x[ i ] = i + 1; + y[ i ] = -1.0; + expected[ i ] = -1.0; + } + for ( i = 0; i < lens[ j ]; i++ ) { + expected[ 3+i ] = x[ 2+i ]; + } + + scopy( lens[ j ], x, 1, 2, y, 1, 3 ); + + t.deepEqual( y, expected, 'returns expected value when N='+lens[ j ] ); + } + t.end(); +});