README.md (10630B)
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 # ind2sub 22 23 > Convert a linear index to an array of subscripts. 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 ind2sub = require( '@stdlib/ndarray/base/ind2sub' ); 41 ``` 42 43 #### ind2sub( shape, strides, offset, order, idx, mode ) 44 45 Converts a linear index to an array of subscripts. 46 47 ```javascript 48 var shape = [ 2, 2 ]; 49 var order = 'row-major'; 50 var strides = [ 2, 1 ]; 51 var offset = 0; 52 53 var subscripts = ind2sub( shape, strides, offset, order, 1, 'throw' ); 54 // returns [ 0, 1 ] 55 ``` 56 57 The function supports the following `modes`: 58 59 - `throw`: specifies that the function should throw an error when a linear index exceeds array dimensions. 60 - `wrap`: specifies that the function should wrap around a linear index exceeding array dimensions using modulo arithmetic. 61 - `clamp`: specifies that the function should set a linear index exceeding array dimensions to either `0` (minimum linear index) or the maximum linear index. 62 63 ```javascript 64 var shape = [ 2, 2 ]; 65 var order = 'row-major'; 66 var strides = [ 2, 1 ]; 67 var offset = 0; 68 69 var idx = ind2sub( shape, strides, offset, order, -2, 'wrap' ); 70 // returns [ 1, 0 ] 71 72 idx = ind2sub( shape, strides, offset, order, 10, 'clamp' ); 73 // returns [ 1, 1 ] 74 ``` 75 76 The `order` parameter specifies whether an array is `row-major` (C-style) or `column-major` (Fortran-style). 77 78 ```javascript 79 var shape = [ 2, 2 ]; 80 var order = 'column-major'; 81 var strides = [ 1, 2 ]; 82 var offset = 0; 83 84 var idx = ind2sub( shape, strides, offset, order, 2, 'throw' ); 85 // returns [ 0, 1 ] 86 ``` 87 88 #### ind2sub.assign( shape, strides, offset, order, idx, mode, out ) 89 90 Converts a linear index to an array of subscripts and assigns results to a provided output array. 91 92 ```javascript 93 var shape = [ 2, 2 ]; 94 var order = 'row-major'; 95 var strides = [ 2, 1 ]; 96 var offset = 0; 97 98 var out = [ 0, 0 ]; 99 var subscripts = ind2sub.assign( shape, strides, offset, order, 1, 'throw', out ); 100 // returns [ 0, 1 ] 101 102 var bool = ( subscripts === out ); 103 // returns true 104 ``` 105 106 </section> 107 108 <!-- /.usage --> 109 110 <!-- Package usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. --> 111 112 <section class="notes"> 113 114 ## Notes 115 116 - When provided a stride array containing negative strides, if an `offset` is greater than `0`, the function interprets the linear index as an index into the underlying data buffer for the array, thus returning subscripts from the perspective of that buffer. If an `offset` is equal to `0`, the function treats the linear index as an index into an array view, thus returning subscripts from the perspective of that view. 117 118 ```text 119 Dims: 2x2 120 Buffer: [ 1, 2, 3, 4 ] 121 122 View = [ a00, a01, 123 a10, a11 ] 124 125 Strides: 2,1 126 Offset: 0 127 128 View = [ 1, 2, 129 3, 4 ] 130 131 Strides: 2,-1 132 Offset: 1 133 134 View = [ 2, 1, 135 4, 3 ] 136 137 Strides: -2,1 138 Offset: 2 139 140 View = [ 3, 4, 141 1, 2 ] 142 143 Strides: -2,-1 144 Offset: 3 145 146 View = [ 4, 3, 147 2, 1 ] 148 ``` 149 150 ```javascript 151 var shape = [ 2, 2 ]; 152 var order = 'row-major'; 153 var strides = [ -2, 1 ]; 154 var offset = 2; 155 var mode = 'throw'; 156 157 // From the perspective of a view... 158 var s = ind2sub( shape, strides, 0, order, 0, mode ); 159 // returns [ 0, 0 ] 160 161 s = ind2sub( shape, strides, 0, order, 1, mode ); 162 // returns [ 0, 1 ] 163 164 s = ind2sub( shape, strides, 0, order, 2, mode ); 165 // returns [ 1, 0 ] 166 167 s = ind2sub( shape, strides, 0, order, 3, mode ); 168 // returns [ 1, 1 ] 169 170 // From the perspective of an underlying buffer... 171 s = ind2sub( shape, strides, offset, order, 0, mode ); 172 // returns [ 1, 0 ] 173 174 s = ind2sub( shape, strides, offset, order, 1, mode ); 175 // returns [ 1, 1 ] 176 177 s = ind2sub( shape, strides, offset, order, 2, mode ); 178 // returns [ 0, 0 ] 179 180 s = ind2sub( shape, strides, offset, order, 3, mode ); 181 // returns [ 0, 1 ] 182 ``` 183 184 In short, from the perspective of a view, view data is always ordered. 185 186 </section> 187 188 <!-- /.notes --> 189 190 <!-- Package usage examples. --> 191 192 <section class="examples"> 193 194 ## Examples 195 196 <!-- eslint no-undef: "error" --> 197 198 ```javascript 199 var discreteUniform = require( '@stdlib/random/base/discrete-uniform' ); 200 var shape2strides = require( '@stdlib/ndarray/base/shape2strides' ); 201 var strides2offset = require( '@stdlib/ndarray/base/strides2offset' ); 202 var numel = require( '@stdlib/ndarray/base/numel' ); 203 var randu = require( '@stdlib/random/base/randu' ); 204 var abs = require( '@stdlib/math/base/special/abs' ); 205 var ind2sub = require( '@stdlib/ndarray/base/ind2sub' ); 206 207 // Specify array characteristics: 208 var shape = [ 3, 3, 3 ]; 209 var order = 'row-major'; 210 211 // Compute array meta data: 212 var ndims = shape.length; 213 var strides = shape2strides( shape, order ); 214 var len = numel( shape ); 215 216 // Determine stride indices to be used for formatting how views are displayed... 217 var s0; 218 var s1; 219 if ( order === 'column-major' ) { 220 s0 = ndims - 1; 221 s1 = s0 - 1; 222 } else { // row-major 223 s0 = 0; 224 s1 = s0 + 1; 225 } 226 227 // Initialize a linear array... 228 var arr = []; 229 var i; 230 for ( i = 0; i < len; i++ ) { 231 arr.push( 0 ); 232 } 233 234 // Generate random views and display the mapping of elements in the linear array to view subscripts... 235 var offset; 236 var row; 237 var j; 238 var s; 239 for ( i = 0; i < 20; i++ ) { 240 // Randomly flip the sign of one of the strides... 241 j = discreteUniform( 0, ndims-1 ); 242 strides[ j ] *= ( randu() < 0.5 ) ? -1 : 1; 243 offset = strides2offset( shape, strides ); 244 245 // Print view meta data... 246 console.log( '' ); 247 console.log( 'Dimensions: %s.', shape.join( 'x' ) ); 248 console.log( 'Strides: %s.', strides.join( ',' ) ); 249 console.log( 'View (subscripts):' ); 250 251 // Print the mapping of elements in the linear array to view subscripts... 252 row = ' '; 253 for ( j = 0; j < len; j++ ) { 254 s = ind2sub( shape, strides, offset, order, j, 'throw' ); 255 row += '(' + s.join( ',' ) + ')'; 256 if ( ndims === 1 && j === len-1 ) { 257 console.log( row ); 258 } else if ( ndims === 2 && (j+1)%abs( strides[ s0 ] ) === 0 ) { 259 console.log( row ); 260 row = ' '; 261 } else if ( ndims > 2 && (j+1)%abs( strides[ s1 ] ) === 0 ) { 262 console.log( row ); 263 if ( (j+1)%abs( strides[ s0 ] ) === 0 ) { 264 console.log( '' ); 265 } 266 row = ' '; 267 } else { 268 row += ', '; 269 } 270 } 271 } 272 ``` 273 274 </section> 275 276 <!-- /.examples --> 277 278 <!-- C interface documentation. --> 279 280 * * * 281 282 <section class="c"> 283 284 ## C APIs 285 286 <!-- Section to include introductory text. Make sure to keep an empty line after the intro `section` element and another before the `/section` close. --> 287 288 <section class="intro"> 289 290 </section> 291 292 <!-- /.intro --> 293 294 <!-- C usage documentation. --> 295 296 <section class="usage"> 297 298 ### Usage 299 300 ```c 301 #include "stdlib/ndarray/base/ind2sub.h" 302 ``` 303 304 <!-- lint disable maximum-heading-length --> 305 306 #### stdlib_ndarray_ind2sub( ndims, \*shape, \*strides, offset, order, idx, mode, \*out ) 307 308 Computes the minimum and maximum linear indices in an underlying data buffer accessible to an array view. 309 310 ```c 311 #include "stdlib/ndarray/index_modes.h" 312 #include "stdlib/ndarray/orders.h" 313 #include <stdint.h> 314 315 int64_t ndims = 2; 316 int64_t shape[] = { 3, 3 }; 317 int64_t strides[] = { -3, 1 }; 318 int64_t offset = 6; 319 320 int64_t out[ 2 ]; 321 322 int8_t status = stdlib_ndarray_ind2sub( ndims, shape, strides, offset, STDLIB_NDARRAY_ROW_MAJOR, 7, STDLIB_NDARRAY_INDEX_ERROR, out ); 323 if ( status == -1 ) { 324 // Handle error... 325 } 326 ``` 327 328 The function accepts the following arguments: 329 330 - **ndims**: `[in] int64_t` number of dimensions. 331 - **shape**: `[in] int64_t*` array shape (dimensions). 332 - **strides**: `[in] int64_t*` array strides. 333 - **offset**: `[in] int64_t` index offset. 334 - **order**: `[in] enum STDLIB_NDARRAY_ORDER` specifies whether an array is row-major (C-style) or column-major (Fortran-style). 335 - **idx**: `[in] int64_t` linear index in an array view. 336 - **mode**: `[in] enum STDLIB_NDARRAY_INDEX_MODE` specifies how to handle a linear index which exceeds array dimensions. 337 - **out**: `[out] int64_t*` output array. 338 339 ```c 340 int8_t stdlib_ndarray_ind2sub( int64_t ndims, int64_t *shape, int64_t *strides, int64_t offset, enum STDLIB_NDARRAY_ORDER order, int64_t idx, enum STDLIB_NDARRAY_INDEX_MODE mode, int64_t *out ); 341 ``` 342 343 </section> 344 345 <!-- /.usage --> 346 347 <!-- C API usage notes. Make sure to keep an empty line after the `section` element and another before the `/section` close. --> 348 349 <section class="notes"> 350 351 </section> 352 353 <!-- /.notes --> 354 355 <!-- C API usage examples. --> 356 357 <section class="examples"> 358 359 ### Examples 360 361 ```c 362 #include "stdlib/ndarray/base/ind2sub.h" 363 #include "stdlib/ndarray/index_modes.h" 364 #include "stdlib/ndarray/orders.h" 365 #include <stdint.h> 366 #include <stdio.h> 367 #include <inttypes.h> 368 369 int main() { 370 int64_t ndims = 2; 371 int64_t shape[] = { 3, 3 }; 372 int64_t strides[] = { -3, 1 }; 373 int64_t offset = 6; 374 375 int64_t out[ 2 ]; 376 377 stdlib_ndarray_ind2sub( ndims, shape, strides, offset, STDLIB_NDARRAY_ROW_MAJOR, 7, STDLIB_NDARRAY_INDEX_ERROR, out ); 378 379 int i; 380 printf( "subscripts = { " ); 381 for ( i = 0; i < ndims; i++ ) { 382 printf( "%"PRId64"", out[ i ] ); 383 if ( i < ndims-1 ) { 384 printf( ", " ); 385 } 386 } 387 printf( " }\n" ); 388 } 389 ``` 390 391 </section> 392 393 <!-- /.examples --> 394 395 </section> 396 397 <!-- /.c --> 398 399 <!-- 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. --> 400 401 <section class="references"> 402 403 </section> 404 405 <!-- /.references --> 406 407 <!-- Section for all links. Make sure to keep an empty line after the `section` element and another before the `/section` close. --> 408 409 <section class="links"> 410 411 </section> 412 413 <!-- /.links -->