Skip to content

Commit caaa778

Browse files
committed
Fix linear indexing bug when ndarray is noncontiguous
1 parent 54db2e0 commit caaa778

File tree

3 files changed

+162
-16
lines changed

3 files changed

+162
-16
lines changed

lib/node_modules/@stdlib/ndarray/base/ctor/lib/iget.js

+9-7
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,15 @@ function iget( idx ) {
3636
var s;
3737
var i;
3838

39-
// Trivial case where we have all positive strides...
40-
if ( this._iterationOrder === 1 ) {
41-
return this._buffer[ this._offset + idx ];
42-
}
43-
// Trivial case where we have all negative strides...
44-
if ( this._iterationOrder === -1 ) {
45-
return this._buffer[ this._offset - idx ];
39+
if ( this._flags.ROW_MAJOR_CONTIGUOUS || this._flags.COLUMN_MAJOR_CONTIGUOUS ) { // eslint-disable-line max-len
40+
// Trivial case where we have all positive strides...
41+
if ( this._iterationOrder === 1 ) {
42+
return this._buffer[ this._offset + idx ];
43+
}
44+
// Trivial case where we have all negative strides...
45+
if ( this._iterationOrder === -1 ) {
46+
return this._buffer[ this._offset - idx ];
47+
}
4648
}
4749
// The approach which follows is to resolve a view index to its subscripts and then plug the subscripts into the standard formula for computing the linear index in the underlying data buffer...
4850
shape = this._shape;

lib/node_modules/@stdlib/ndarray/base/ctor/lib/iset.js

+11-9
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,17 @@ function iset( idx, v ) {
3737
var s;
3838
var i;
3939

40-
// Trivial case where we have all positive strides...
41-
if ( this._iterationOrder === 1 ) {
42-
this._buffer[ this._offset + idx ] = v;
43-
return this;
44-
}
45-
// Trivial case where we have all negative strides...
46-
if ( this._iterationOrder === -1 ) {
47-
this._buffer[ this._offset - idx ] = v;
48-
return this;
40+
if ( this._flags.ROW_MAJOR_CONTIGUOUS || this._flags.COLUMN_MAJOR_CONTIGUOUS ) { // eslint-disable-line max-len
41+
// Trivial case where we have all positive strides...
42+
if ( this._iterationOrder === 1 ) {
43+
this._buffer[ this._offset + idx ] = v;
44+
return this;
45+
}
46+
// Trivial case where we have all negative strides...
47+
if ( this._iterationOrder === -1 ) {
48+
this._buffer[ this._offset - idx ] = v;
49+
return this;
50+
}
4951
}
5052
// The approach which follows is to resolve a view index to its subscripts and then plug the subscripts into the standard formula for computing the linear index in the underlying data buffer...
5153
shape = this._shape;

lib/node_modules/@stdlib/ndarray/base/ctor/test/test.js

+142
Original file line numberDiff line numberDiff line change
@@ -1136,6 +1136,38 @@ tape( 'an ndarray constructor returns an instance which has an `iget` method for
11361136
t.end();
11371137
});
11381138

1139+
tape( 'an ndarray constructor returns an instance which has an `iget` method for retrieving an array element using a linear index (row-major; noncontiguous)', function test( t ) {
1140+
var strides;
1141+
var buffer;
1142+
var offset;
1143+
var dtype;
1144+
var order;
1145+
var shape;
1146+
var arr;
1147+
var f;
1148+
1149+
dtype = 'float64';
1150+
buffer = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] );
1151+
shape = [ 2, 2, 1 ];
1152+
order = 'row-major';
1153+
strides = [ 4, 1, 1 ];
1154+
offset = 0;
1155+
1156+
f = ctor( dtype, shape.length );
1157+
arr = f( buffer, shape, strides, offset, order );
1158+
1159+
t.strictEqual( hasOwnProp( arr, 'iget' ), false, 'does not have own property' );
1160+
t.strictEqual( hasProp( arr, 'iget' ), true, 'has property' );
1161+
t.strictEqual( isFunction( arr.iget ), true, 'has method' );
1162+
1163+
t.strictEqual( arr.iget( 0 ), 1.0, 'returns expected value' );
1164+
t.strictEqual( arr.iget( 1 ), 2.0, 'returns expected value' );
1165+
t.strictEqual( arr.iget( 2 ), 5.0, 'returns expected value' );
1166+
t.strictEqual( arr.iget( 3 ), 6.0, 'returns expected value' );
1167+
1168+
t.end();
1169+
});
1170+
11391171
tape( 'an ndarray constructor returns an instance which has an `iget` method for retrieving an array element using a linear index (column-major)', function test( t ) {
11401172
var strides;
11411173
var buffer;
@@ -1264,6 +1296,38 @@ tape( 'an ndarray constructor returns an instance which has an `iget` method for
12641296
t.end();
12651297
});
12661298

1299+
tape( 'an ndarray constructor returns an instance which has an `iget` method for retrieving an array element using a linear index (column-major; noncontiguous)', function test( t ) {
1300+
var strides;
1301+
var buffer;
1302+
var offset;
1303+
var dtype;
1304+
var order;
1305+
var shape;
1306+
var arr;
1307+
var f;
1308+
1309+
dtype = 'float64';
1310+
buffer = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ] );
1311+
shape = [ 2, 2, 1 ];
1312+
order = 'column-major';
1313+
strides = [ 1, 4, 8 ];
1314+
offset = 0;
1315+
1316+
f = ctor( dtype, shape.length );
1317+
arr = f( buffer, shape, strides, offset, order );
1318+
1319+
t.strictEqual( hasOwnProp( arr, 'iget' ), false, 'does not have own property' );
1320+
t.strictEqual( hasProp( arr, 'iget' ), true, 'has property' );
1321+
t.strictEqual( isFunction( arr.iget ), true, 'has method' );
1322+
1323+
t.strictEqual( arr.iget( 0 ), 1.0, 'returns expected value' );
1324+
t.strictEqual( arr.iget( 1 ), 2.0, 'returns expected value' );
1325+
t.strictEqual( arr.iget( 2 ), 5.0, 'returns expected value' );
1326+
t.strictEqual( arr.iget( 3 ), 6.0, 'returns expected value' );
1327+
1328+
t.end();
1329+
});
1330+
12671331
tape( 'an ndarray constructor returns an instance which has a `set` method for setting an array element using subscripts (row-major)', function test( t ) {
12681332
var strides;
12691333
var buffer;
@@ -1732,6 +1796,45 @@ tape( 'an ndarray constructor returns an instance which has an `iset` method for
17321796
t.end();
17331797
});
17341798

1799+
tape( 'an ndarray constructor returns an instance which has an `iset` method for setting an array element using a linear index (row-major; noncontiguous)', function test( t ) {
1800+
var strides;
1801+
var buffer;
1802+
var offset;
1803+
var dtype;
1804+
var order;
1805+
var shape;
1806+
var arr;
1807+
var f;
1808+
1809+
dtype = 'generic';
1810+
buffer = [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ];
1811+
shape = [ 2, 2, 1 ];
1812+
order = 'row-major';
1813+
strides = [ 4, 1, 1 ];
1814+
offset = 0;
1815+
1816+
f = ctor( dtype, shape.length );
1817+
arr = f( buffer, shape, strides, offset, order );
1818+
1819+
t.strictEqual( hasOwnProp( arr, 'iset' ), false, 'does not have own property' );
1820+
t.strictEqual( hasProp( arr, 'iset' ), true, 'has property' );
1821+
t.strictEqual( isFunction( arr.iset ), true, 'has method' );
1822+
1823+
arr.iset( 0, -5.0 );
1824+
arr.iset( 1, -6.0 );
1825+
arr.iset( 2, -7.0 );
1826+
arr.iset( 3, -8.0 );
1827+
1828+
t.strictEqual( arr.iget( 0 ), -5.0, 'returns expected value' );
1829+
t.strictEqual( arr.iget( 1 ), -6.0, 'returns expected value' );
1830+
t.strictEqual( arr.iget( 2 ), -7.0, 'returns expected value' );
1831+
t.strictEqual( arr.iget( 3 ), -8.0, 'returns expected value' );
1832+
1833+
t.deepEqual( buffer, [ -5.0, -6.0, 3.0, 4.0, -7.0, -8.0, 7.0, 8.0 ], 'has expected values' );
1834+
1835+
t.end();
1836+
});
1837+
17351838
tape( 'an ndarray constructor returns an instance which has an `iset` method for setting an array element using a linear index (column-major)', function test( t ) {
17361839
var strides;
17371840
var buffer;
@@ -1888,6 +1991,45 @@ tape( 'an ndarray constructor returns an instance which has an `iset` method for
18881991
t.end();
18891992
});
18901993

1994+
tape( 'an ndarray constructor returns an instance which has an `iset` method for setting an array element using a linear index (column-major; noncontiguous)', function test( t ) {
1995+
var strides;
1996+
var buffer;
1997+
var offset;
1998+
var dtype;
1999+
var order;
2000+
var shape;
2001+
var arr;
2002+
var f;
2003+
2004+
dtype = 'generic';
2005+
buffer = [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0 ];
2006+
shape = [ 2, 2, 1 ];
2007+
order = 'column-major';
2008+
strides = [ 1, 4, 8 ];
2009+
offset = 0;
2010+
2011+
f = ctor( dtype, shape.length );
2012+
arr = f( buffer, shape, strides, offset, order );
2013+
2014+
t.strictEqual( hasOwnProp( arr, 'iset' ), false, 'does not have own property' );
2015+
t.strictEqual( hasProp( arr, 'iset' ), true, 'has property' );
2016+
t.strictEqual( isFunction( arr.iset ), true, 'has method' );
2017+
2018+
arr.iset( 0, -5.0 );
2019+
arr.iset( 1, -6.0 );
2020+
arr.iset( 2, -7.0 );
2021+
arr.iset( 3, -8.0 );
2022+
2023+
t.strictEqual( arr.iget( 0 ), -5.0, 'returns expected value' );
2024+
t.strictEqual( arr.iget( 1 ), -6.0, 'returns expected value' );
2025+
t.strictEqual( arr.iget( 2 ), -7.0, 'returns expected value' );
2026+
t.strictEqual( arr.iget( 3 ), -8.0, 'returns expected value' );
2027+
2028+
t.deepEqual( buffer, [ -5.0, -6.0, 3.0, 4.0, -7.0, -8.0, 7.0, 8.0 ], 'has expected values' );
2029+
2030+
t.end();
2031+
});
2032+
18912033
tape( 'an ndarray constructor returns an instance which has a `get` method for retrieving an array element using subscripts (row-major; codegen=false)', function test( t ) {
18922034
var strides;
18932035
var buffer;

0 commit comments

Comments
 (0)