sub2ind

Convert subscripts to a linear index.

Usage

var sub2ind = require( '@stdlib/ndarray/base/sub2ind' );

sub2ind( shape, strides, offset, ...subscripts, mode )

Converts subscripts to a linear index.

var shape = [ 2, 2 ];
var strides = [ 2, 1 ];
var offset = 0;
var mode = [ 'throw' ];

var idx = sub2ind( shape, strides, offset, 1, 0, mode );
// returns 2

The function supports the following modes:

  • throw: specifies that the function should throw an error when a subscript exceeds array dimensions.
  • wrap: specifies that the function should wrap around subscripts exceeding array dimensions using modulo arithmetic.
  • clamp: specifies that the function should set subscripts exceeding array dimensions to either 0 (minimum index) or the maximum index along a particular dimension.
var shape = [ 2, 2 ];
var strides = [ 2, 1 ];
var offset = 0;

var mode = [ 'wrap' ];
var idx = sub2ind( shape, strides, offset, -2, 0, mode );
// returns 0

mode = [ 'clamp' ];
idx = sub2ind( shape, strides, offset, 10, 10, mode );
// returns 3

Notes

  • When provided fewer modes than dimensions, the function recycles modes using modulo arithmetic.

    var shape = [ 2, 2, 2 ];
    var strides = [ 4, 2, 1 ];
    var offset = 0;
    var mode = [ 'wrap', 'clamp' ];
    
    var idx = sub2ind( shape, strides, offset, -2, 10, -1, mode );
    // returns 3
    
  • When provided a stride array containing negative strides, if an offset is greater than 0, the function treats subscripts as mapping to a linear index in an underlying data buffer for the array, thus returning a linear index from the perspective of that buffer. If an offset is equal to 0, the function treats subscripts as mapping to a linear index in an array view, thus returning a linear index from the perspective of that view.

    Dims: 2x2
    Buffer: [ 1, 2, 3, 4 ]
    
    View = [ a00, a01,
             a10, a11 ]
    
    Strides: 2,1
    Offset: 0
    
    View = [ 1, 2,
             3, 4 ]
    
    Strides: 2,-1
    Offset: 1
    
    View = [ 2, 1,
             4, 3 ]
    
    Strides: -2,1
    Offset: 2
    
    View = [ 3, 4,
             1, 2 ]
    
    Strides: -2,-1
    Offset: 3
    
    View = [ 4, 3,
             2, 1 ]
    
    var shape = [ 2, 2 ];
    var strides = [ -2, 1 ];
    var offset = 2;
    var mode = [ 'throw' ];
    
    // From the perspective of a view...
    var idx = sub2ind( shape, strides, 0, 0, 0, mode );
    // returns 0
    
    idx = sub2ind( shape, strides, 0, 0, 1, mode );
    // returns 1
    
    idx = sub2ind( shape, strides, 0, 1, 0, mode );
    // returns 2
    
    idx = sub2ind( shape, strides, 0, 1, 1, mode );
    // returns 3
    
    // From the perspective of an underlying buffer...
    idx = sub2ind( shape, strides, offset, 0, 0, mode );
    // returns 2
    
    idx = sub2ind( shape, strides, offset, 0, 1, mode );
    // returns 3
    
    idx = sub2ind( shape, strides, offset, 1, 0, mode );
    // returns 0
    
    idx = sub2ind( shape, strides, offset, 1, 1, mode );
    // returns 1
    

    In short, from the perspective of a view, view data is always ordered.

Examples

var discreteUniform = require( '@stdlib/random/base/discrete-uniform' );
var shape2strides = require( '@stdlib/ndarray/base/shape2strides' );
var strides2offset = require( '@stdlib/ndarray/base/strides2offset' );
var numel = require( '@stdlib/ndarray/base/numel' );
var randu = require( '@stdlib/random/base/randu' );
var sub2ind = require( '@stdlib/ndarray/base/sub2ind' );

var shape = [ 3, 3 ];
var strides = shape2strides( shape, 'row-major' );
var mode = [ 'throw' ];
var len = numel( shape );

var arr = new Array( len );
var i;
for ( i = 0; i < len; i++ ) {
    arr[ i ] = i;
}

var offset;
var idx;
var row;
var j;
var n;
var m;
for ( i = 0; i < 20; i++ ) {
    j = discreteUniform( 0, shape.length-1 );
    strides[ j ] = ( randu() < 0.5 ) ? -1 : 1;
    offset = strides2offset( shape, strides );

    console.log( '' );
    console.log( 'Dimensions: %s.', shape.join( 'x' ) );
    console.log( 'Strides: %s.', strides.join( ',' ) );
    console.log( 'View:' );
    for ( n = 0; n < shape[ 0 ]; n++ ) {
        row = '  ';
        for ( m = 0; m < shape[ 1 ]; m++ ) {
            idx = sub2ind( shape, strides, offset, n, m, mode );
            row += arr[ idx ];
            if ( m < shape[ 1 ]-1 ) {
                row += ', ';
            }
        }
        console.log( row );
    }
}