iget_ptr.c (3327B)
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 #include "stdlib/ndarray/ctor/iget_ptr.h" 20 #include "stdlib/ndarray/ctor/ndarray.h" 21 #include "stdlib/ndarray/ctor/macros.h" 22 #include "stdlib/ndarray/orders.h" 23 #include "stdlib/ndarray/base/bytes_per_element.h" 24 #include "stdlib/ndarray/base/ind.h" 25 #include "stdlib/ndarray/base/iteration_order.h" 26 #include <stdlib.h> 27 #include <stdint.h> 28 29 /** 30 * Returns a pointer in the underlying byte array for an ndarray data element located at a specified linear index. 31 * 32 * ## Notes 33 * 34 * - For zero-dimensional arrays, the function returns a pointer to the first (and only) indexed element, regardless of the value of `idx`. 35 * 36 * @param arr input ndarray 37 * @param idx linear view index 38 * @return underlying byte array pointer 39 */ 40 uint8_t * stdlib_ndarray_iget_ptr( const struct ndarray *arr, const int64_t idx ) { 41 int64_t *strides; 42 int64_t *shape; 43 int64_t ndims; 44 uint8_t *ind; 45 int64_t s; 46 int64_t i; 47 int64_t j; 48 int8_t io; 49 50 // Retrieve the number of dimensions 51 ndims = arr->ndims; 52 53 // For zero-dimensional ndarrays, we ignore the index argument and return a pointer to the first (and only) indexed element... 54 if ( ndims == 0 ) { 55 return (arr->data) + (arr->offset); // pointer arithmetic 56 } 57 // Copy index argument to a mutable variable: 58 j = idx; 59 60 // Resolve an ndarray index based on the ndarray index mode: 61 j = stdlib_ndarray_ind( j, (arr->length)-1, arr->imode ); 62 if ( j < 0 ) { 63 return NULL; 64 } 65 // Determine the pointer to the first indexed element: 66 ind = (arr->data) + (arr->offset); // pointer arithmetic 67 68 // Determine the iteration order based on the ndarray strides: 69 strides = arr->strides; 70 io = stdlib_ndarray_iteration_order( ndims, strides ); 71 72 // Check for trivial case... 73 if ( (arr->flags) & (STDLIB_NDARRAY_ROW_MAJOR_CONTIGUOUS_FLAG | STDLIB_NDARRAY_COLUMN_MAJOR_CONTIGUOUS_FLAG) ) { 74 // Trivial case where we have all positive strides... 75 if ( io == 1 ) { 76 return ind + (j*(arr->BYTES_PER_ELEMENT)); // pointer arithmetic 77 } 78 // Trivial case where we have all negative strides... 79 if ( io == -1 ) { 80 return ind - (j*(arr->BYTES_PER_ELEMENT)); // pointer arithmetic 81 } 82 } 83 // 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 byte array... 84 shape = arr->shape; 85 if ( (arr->order) == STDLIB_NDARRAY_COLUMN_MAJOR ) { 86 for ( i = 0; i < ndims; i++ ) { 87 s = j % shape[ i ]; 88 j -= s; 89 j /= shape[ i ]; 90 ind += s * strides[ i ]; // pointer arithmetic 91 } 92 return ind; 93 } 94 // Case: row-major 95 for ( i = ndims-1; i >= 0; i-- ) { 96 s = j % shape[ i ]; 97 j -= s; 98 j /= shape[ i ]; 99 ind += s * strides[ i ]; // pointer arithmetic 100 } 101 return ind; 102 }