main.js (3169B)
1 /** 2 * @license Apache-2.0 3 * 4 * Copyright (c) 2018 The Stdlib Authors. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 'use strict'; 20 21 // MAIN // 22 23 /** 24 * Converts a linear index in an array view to a linear index in an underlying data buffer. 25 * 26 * @param {NonNegativeIntegerArray} shape - array shape 27 * @param {IntegerArray} strides - stride array 28 * @param {NonNegativeInteger} offset - location of the first indexed value **based** on the stride array 29 * @param {string} order - specifies whether an array is row-major (C-style) or column-major (Fortran-style) 30 * @param {integer} idx - linear index in an array view 31 * @param {string} mode - specifies how to handle a linear index which exceeds array dimensions 32 * @throws {RangeError} linear index must not exceed array dimensions 33 * @returns {NonNegativeInteger} linear index in an underlying data buffer 34 * 35 * @example 36 * var shape = [ 3, 3 ]; 37 * var strides = [ -3, 1 ]; 38 * var offset = 6; 39 * var order = 'row-major'; 40 * var mode = 'throw'; 41 * 42 * var ind = vind2bind( shape, strides, offset, order, 1, mode ); 43 * // returns 7 44 */ 45 function vind2bind( shape, strides, offset, order, idx, mode ) { 46 var ndims; 47 var len; 48 var ind; 49 var s; 50 var i; 51 52 ndims = shape.length; 53 len = 1; 54 for ( i = 0; i < ndims; i++ ) { 55 len *= shape[ i ]; 56 } 57 if ( mode === 'clamp' ) { 58 if ( idx < 0 ) { 59 idx = 0; 60 } else if ( idx >= len ) { 61 idx = len - 1; 62 } 63 } else if ( mode === 'wrap' ) { 64 if ( idx < 0 ) { 65 idx += len; // slight optimization to avoid modulo arithmetic when |idx| <= len 66 if ( idx < 0 ) { 67 idx %= len; 68 if ( idx !== 0 ) { 69 idx += len; 70 } 71 } 72 } else if ( idx >= len ) { 73 idx -= len; // slight optimization to avoid modulo arithmetic when len < idx <= 2*len 74 if ( idx >= len ) { 75 idx %= len; 76 } 77 } 78 } else if ( idx < 0 || idx >= len ) { 79 throw new RangeError( 'invalid argument. Linear index must not exceed array dimensions. Number of array elements: ' + len + '. Value: `' + idx + '`.' ); 80 } 81 // Trivial case where the offset into the underlying data buffer is 0... 82 if ( offset === 0 ) { 83 return idx; 84 } 85 // 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... 86 ind = offset; 87 if ( order === 'column-major' ) { 88 for ( i = 0; i < ndims; i++ ) { 89 s = idx % shape[ i ]; 90 idx -= s; 91 idx /= shape[ i ]; 92 ind += s * strides[ i ]; 93 } 94 return ind; 95 } 96 // Case: row-major 97 for ( i = ndims-1; i >= 0; i-- ) { 98 s = idx % shape[ i ]; 99 idx -= s; 100 idx /= shape[ i ]; 101 ind += s * strides[ i ]; 102 } 103 return ind; 104 } 105 106 107 // EXPORTS // 108 109 module.exports = vind2bind;