README.md (6211B)
1 <!-- 2 3 @license Apache-2.0 4 5 Copyright (c) 2018 The Stdlib Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 19 --> 20 21 # sub2ind 22 23 > Convert subscripts to a linear index. 24 25 <!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. --> 26 27 <section class="intro"> 28 29 </section> 30 31 <!-- /.intro --> 32 33 <!-- Package usage documentation. --> 34 35 <section class="usage"> 36 37 ## Usage 38 39 ```javascript 40 var sub2ind = require( '@stdlib/ndarray/base/sub2ind' ); 41 ``` 42 43 #### sub2ind( shape, strides, offset, ...subscripts, mode ) 44 45 Converts subscripts to a linear index. 46 47 ```javascript 48 var shape = [ 2, 2 ]; 49 var strides = [ 2, 1 ]; 50 var offset = 0; 51 var mode = [ 'throw' ]; 52 53 var idx = sub2ind( shape, strides, offset, 1, 0, mode ); 54 // returns 2 55 ``` 56 57 The function supports the following `modes`: 58 59 - `throw`: specifies that the function should throw an error when a subscript exceeds array dimensions. 60 - `wrap`: specifies that the function should wrap around subscripts exceeding array dimensions using modulo arithmetic. 61 - `clamp`: specifies that the function should set subscripts exceeding array dimensions to either `0` (minimum index) or the maximum index along a particular dimension. 62 63 ```javascript 64 var shape = [ 2, 2 ]; 65 var strides = [ 2, 1 ]; 66 var offset = 0; 67 68 var mode = [ 'wrap' ]; 69 var idx = sub2ind( shape, strides, offset, -2, 0, mode ); 70 // returns 0 71 72 mode = [ 'clamp' ]; 73 idx = sub2ind( shape, strides, offset, 10, 10, mode ); 74 // returns 3 75 ``` 76 77 </section> 78 79 <!-- /.usage --> 80 81 <!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. --> 82 83 <section class="notes"> 84 85 ## Notes 86 87 - When provided fewer `modes` than dimensions, the function recycles `modes` using modulo arithmetic. 88 89 ```javascript 90 var shape = [ 2, 2, 2 ]; 91 var strides = [ 4, 2, 1 ]; 92 var offset = 0; 93 var mode = [ 'wrap', 'clamp' ]; 94 95 var idx = sub2ind( shape, strides, offset, -2, 10, -1, mode ); 96 // returns 3 97 ``` 98 99 - 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. 100 101 ```text 102 Dims: 2x2 103 Buffer: [ 1, 2, 3, 4 ] 104 105 View = [ a00, a01, 106 a10, a11 ] 107 108 Strides: 2,1 109 Offset: 0 110 111 View = [ 1, 2, 112 3, 4 ] 113 114 Strides: 2,-1 115 Offset: 1 116 117 View = [ 2, 1, 118 4, 3 ] 119 120 Strides: -2,1 121 Offset: 2 122 123 View = [ 3, 4, 124 1, 2 ] 125 126 Strides: -2,-1 127 Offset: 3 128 129 View = [ 4, 3, 130 2, 1 ] 131 ``` 132 133 ```javascript 134 var shape = [ 2, 2 ]; 135 var strides = [ -2, 1 ]; 136 var offset = 2; 137 var mode = [ 'throw' ]; 138 139 // From the perspective of a view... 140 var idx = sub2ind( shape, strides, 0, 0, 0, mode ); 141 // returns 0 142 143 idx = sub2ind( shape, strides, 0, 0, 1, mode ); 144 // returns 1 145 146 idx = sub2ind( shape, strides, 0, 1, 0, mode ); 147 // returns 2 148 149 idx = sub2ind( shape, strides, 0, 1, 1, mode ); 150 // returns 3 151 152 // From the perspective of an underlying buffer... 153 idx = sub2ind( shape, strides, offset, 0, 0, mode ); 154 // returns 2 155 156 idx = sub2ind( shape, strides, offset, 0, 1, mode ); 157 // returns 3 158 159 idx = sub2ind( shape, strides, offset, 1, 0, mode ); 160 // returns 0 161 162 idx = sub2ind( shape, strides, offset, 1, 1, mode ); 163 // returns 1 164 ``` 165 166 In short, from the perspective of a view, view data is always ordered. 167 168 </section> 169 170 <!-- /.notes --> 171 172 <!-- Package usage examples. --> 173 174 <section class="examples"> 175 176 ## Examples 177 178 <!-- eslint no-undef: "error" --> 179 180 ```javascript 181 var discreteUniform = require( '@stdlib/random/base/discrete-uniform' ); 182 var shape2strides = require( '@stdlib/ndarray/base/shape2strides' ); 183 var strides2offset = require( '@stdlib/ndarray/base/strides2offset' ); 184 var numel = require( '@stdlib/ndarray/base/numel' ); 185 var randu = require( '@stdlib/random/base/randu' ); 186 var sub2ind = require( '@stdlib/ndarray/base/sub2ind' ); 187 188 var shape = [ 3, 3 ]; 189 var strides = shape2strides( shape, 'row-major' ); 190 var mode = [ 'throw' ]; 191 var len = numel( shape ); 192 193 var arr = []; 194 var i; 195 for ( i = 0; i < len; i++ ) { 196 arr.push( i ); 197 } 198 199 var offset; 200 var idx; 201 var row; 202 var j; 203 var n; 204 var m; 205 for ( i = 0; i < 20; i++ ) { 206 j = discreteUniform( 0, shape.length-1 ); 207 strides[ j ] = ( randu() < 0.5 ) ? -1 : 1; 208 offset = strides2offset( shape, strides ); 209 210 console.log( '' ); 211 console.log( 'Dimensions: %s.', shape.join( 'x' ) ); 212 console.log( 'Strides: %s.', strides.join( ',' ) ); 213 console.log( 'View:' ); 214 for ( n = 0; n < shape[ 0 ]; n++ ) { 215 row = ' '; 216 for ( m = 0; m < shape[ 1 ]; m++ ) { 217 idx = sub2ind( shape, strides, offset, n, m, mode ); 218 row += arr[ idx ]; 219 if ( m < shape[ 1 ]-1 ) { 220 row += ', '; 221 } 222 } 223 console.log( row ); 224 } 225 } 226 ``` 227 228 </section> 229 230 <!-- /.examples --> 231 232 <!-- Section to include cited references. If references are included, add a horizontal rule *before* the section. Make sure to keep an empty line after the `section` element and another before the `/section` close. --> 233 234 <section class="references"> 235 236 </section> 237 238 <!-- /.references --> 239 240 <!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. --> 241 242 <section class="links"> 243 244 </section> 245 246 <!-- /.links -->