|
23 | 23 | #include <stdint.h> |
24 | 24 |
|
25 | 25 | /** |
26 | | -* Macro for operating on elements of a one-dimensional ndarray. |
| 26 | +* Macro containing the preamble for a loop which operates on elements of a one-dimensional ndarray. |
| 27 | +* |
| 28 | +* ## Notes |
| 29 | +* |
| 30 | +* - Variable naming conventions: |
| 31 | +* |
| 32 | +* - `sx#`, `px#`, and `d@x#` where `#` corresponds to the ndarray argument number, starting at `1`. |
| 33 | +* - `S@`, `i@`, and `d@x#` where `@` corresponds to the loop number, with `0` being the innermost loop. |
| 34 | +* |
| 35 | +* @example |
| 36 | +* STDLIB_NDARRAY_UNARY_1D_LOOP_PREMABLE { |
| 37 | +* // Innermost loop body... |
| 38 | +* } |
| 39 | +* STDLIB_NDARRAY_UNARY_1D_LOOP_EPILOGUE |
| 40 | +*/ |
| 41 | +#define STDLIB_NDARRAY_UNARY_1D_LOOP_PREAMBLE \ |
| 42 | + struct ndarray *x1 = arrays[ 0 ]; \ |
| 43 | + struct ndarray *x2 = arrays[ 1 ]; \ |
| 44 | + int64_t *shape = stdlib_ndarray_shape( x1 ); \ |
| 45 | + int64_t *sx1 = stdlib_ndarray_strides( x1 ); \ |
| 46 | + int64_t *sx2 = stdlib_ndarray_strides( x2 ); \ |
| 47 | + uint8_t *px1 = stdlib_ndarray_data( x1 ); \ |
| 48 | + uint8_t *px2 = stdlib_ndarray_data( x2 ); \ |
| 49 | + int64_t d0x1; \ |
| 50 | + int64_t d0x2; \ |
| 51 | + int64_t S0; \ |
| 52 | + int64_t i0; \ |
| 53 | + /* Extract loop variables: dimensions and loop offset (pointer) increments... */ \ |
| 54 | + S0 = shape[ 0 ]; \ |
| 55 | + d0x1 = sx1[ 0 ]; \ |
| 56 | + d0x2 = sx2[ 0 ]; \ |
| 57 | + /* Set the pointers to the first indexed elements... */ \ |
| 58 | + px1 += stdlib_ndarray_offset( x1 ); \ |
| 59 | + px2 += stdlib_ndarray_offset( x2 ); \ |
| 60 | + /* Iterate over the ndarray dimensions... */ \ |
| 61 | + for ( i0 = 0; i0 < S0; i0++, px1 += d0x1, px2 += d0x2 ) |
| 62 | + |
| 63 | +/** |
| 64 | +* Macro containing the preamble for a loop which operates on elements of a one-dimensional input ndarray and updates two output ndarrays. |
| 65 | +* |
| 66 | +* ## Notes |
| 67 | +* |
| 68 | +* - Variable naming conventions: |
| 69 | +* |
| 70 | +* - `sx#`, `px#`, and `d@x#` where `#` corresponds to the ndarray argument number, starting at `1`. |
| 71 | +* - `S@`, `i@`, and `d@x#` where `@` corresponds to the loop number, with `0` being the innermost loop. |
| 72 | +* |
| 73 | +* @example |
| 74 | +* STDLIB_NDARRAY_UNARY_1D_LOOP_TWO_OUT_PREMABLE { |
| 75 | +* // Innermost loop body... |
| 76 | +* } |
| 77 | +* STDLIB_NDARRAY_UNARY_1D_LOOP_EPILOGUE |
| 78 | +*/ |
| 79 | +#define STDLIB_NDARRAY_UNARY_1D_LOOP_TWO_OUT_PREAMBLE \ |
| 80 | + struct ndarray *x1 = arrays[ 0 ]; \ |
| 81 | + struct ndarray *x2 = arrays[ 1 ]; \ |
| 82 | + struct ndarray *x3 = arrays[ 2 ]; \ |
| 83 | + int64_t *shape = stdlib_ndarray_shape( x1 ); \ |
| 84 | + int64_t *sx1 = stdlib_ndarray_strides( x1 ); \ |
| 85 | + int64_t *sx2 = stdlib_ndarray_strides( x2 ); \ |
| 86 | + int64_t *sx3 = stdlib_ndarray_strides( x3 ); \ |
| 87 | + uint8_t *px1 = stdlib_ndarray_data( x1 ); \ |
| 88 | + uint8_t *px2 = stdlib_ndarray_data( x2 ); \ |
| 89 | + uint8_t *px3 = stdlib_ndarray_data( x3 ); \ |
| 90 | + int64_t d0x1; \ |
| 91 | + int64_t d0x2; \ |
| 92 | + int64_t d0x3; \ |
| 93 | + int64_t S0; \ |
| 94 | + int64_t i0; \ |
| 95 | + /* Extract loop variable: dimensions and loop offset (pointer) increments... */ \ |
| 96 | + S0 = shape[ 0 ]; \ |
| 97 | + d0x1 = sx1[ 0 ]; \ |
| 98 | + d0x2 = sx2[ 0 ]; \ |
| 99 | + d0x3 = sx3[ 0 ]; \ |
| 100 | + /* Set the pointers to the first indexed elements... */ \ |
| 101 | + px1 += stdlib_ndarray_offset( x1 ); \ |
| 102 | + px2 += stdlib_ndarray_offset( x2 ); \ |
| 103 | + px3 += stdlib_ndarray_offset( x3 ); \ |
| 104 | + /* Iterate over the ndarray dimensions... */ \ |
| 105 | + for ( i0 = 0; i0 < S0; i0++, px1 += d0x1, px2 += d0x2, px3 += d0x3 ) |
| 106 | + |
| 107 | +/** |
| 108 | +* Macro containing the epilogue for loops which operate on elements of a one-dimensional ndarray. |
| 109 | +* |
| 110 | +* @example |
| 111 | +* STDLIB_NDARRAY_UNARY_1D_LOOP_PREMABLE { |
| 112 | +* // Innermost loop body... |
| 113 | +* } |
| 114 | +* STDLIB_NDARRAY_UNARY_1D_LOOP_EPILOGUE |
| 115 | +*/ |
| 116 | +#define STDLIB_NDARRAY_UNARY_1D_LOOP_EPILOGUE |
| 117 | + |
| 118 | +/** |
| 119 | +* Macro for a unary one-dimensional ndarray loop which inlines an expression. |
| 120 | +* |
| 121 | +* ## Notes |
| 122 | +* |
| 123 | +* - Retrieves each ndarray element according to type `tin` via the pointer `px1` as `in1`. |
| 124 | +* - Creates a pointer `tout *out` to the output ndarray element. |
| 125 | +* - Expects a provided expression to operate on `tin in1` and to store the result in `tout *out`. |
| 126 | +* |
| 127 | +* @param tin input type |
| 128 | +* @param tout output type |
| 129 | +* @param expr expression to inline |
| 130 | +* |
| 131 | +* @example |
| 132 | +* STDLIB_NDARRAY_UNARY_1D_LOOP_INLINE( double, double, *out = in1 * in1 ) |
| 133 | +*/ |
| 134 | +#define STDLIB_NDARRAY_UNARY_1D_LOOP_INLINE( tin, tout, expr ) \ |
| 135 | + STDLIB_NDARRAY_UNARY_1D_LOOP_PREAMBLE { \ |
| 136 | + const tin in1 = *(tin *)px1; \ |
| 137 | + tout *out = (tout *)px2; \ |
| 138 | + expr; \ |
| 139 | + } \ |
| 140 | + STDLIB_NDARRAY_UNARY_1D_LOOP_EPILOGUE |
| 141 | + |
| 142 | +/** |
| 143 | +* Macro for a unary one-dimensional ndarray loop which invokes a callback. |
| 144 | +* |
| 145 | +* ## Notes |
| 146 | +* |
| 147 | +* - Retrieves each ndarray element according to type `tin` via the pointer `px1`. |
| 148 | +* - Explicitly casts each function `f` invocation result to `tout`. |
| 149 | +* - Stores the result in an output ndarray via the pointer `px2`. |
| 150 | +* |
| 151 | +* @param tin input type |
| 152 | +* @param tout output type |
| 153 | +* |
| 154 | +* @example |
| 155 | +* STDLIB_NDARRAY_UNARY_1D_LOOP_CLBK( double, double ) |
| 156 | +*/ |
| 157 | +#define STDLIB_NDARRAY_UNARY_1D_LOOP_CLBK( tin, tout ) \ |
| 158 | + STDLIB_NDARRAY_UNARY_1D_LOOP_PREAMBLE { \ |
| 159 | + const tin x = *(tin *)px1; \ |
| 160 | + *(tout *)px2 = (tout)f( x ); \ |
| 161 | + } \ |
| 162 | + STDLIB_NDARRAY_UNARY_1D_LOOP_EPILOGUE |
| 163 | + |
| 164 | +/** |
| 165 | +* Macro for a unary one-dimensional ndarray loop which invokes a callback requiring arguments be explicitly cast to a different type. |
| 166 | +* |
| 167 | +* ## Notes |
| 168 | +* |
| 169 | +* - Retrieves each ndarray element according to type `tin` via the pointer `px1`. |
| 170 | +* - Explicitly casts each function argument to `fin`. |
| 171 | +* - Explicitly casts each function `f` invocation result to `tout`. |
| 172 | +* - Stores the result in an output ndarray via the pointer `px2`. |
| 173 | +* |
| 174 | +* @param tin input type |
| 175 | +* @param tout output type |
| 176 | +* @param fin callback argument type |
| 177 | +* |
| 178 | +* @example |
| 179 | +* STDLIB_NDARRAY_UNARY_1D_LOOP_CLBK_ARG_CAST( float, float, double ) |
| 180 | +*/ |
| 181 | +#define STDLIB_NDARRAY_UNARY_1D_LOOP_CLBK_ARG_CAST( tin, tout, fin ) \ |
| 182 | + STDLIB_NDARRAY_UNARY_1D_LOOP_PREAMBLE { \ |
| 183 | + const tin x = *(tin *)px1; \ |
| 184 | + *(tout *)px2 = (tout)f( (fin)x ); \ |
| 185 | + } \ |
| 186 | + STDLIB_NDARRAY_UNARY_1D_LOOP_EPILOGUE |
| 187 | + |
| 188 | +/** |
| 189 | +* Macro for operating on elements of a one-dimensional ndarray using a unary strided array function. |
27 | 190 | * |
28 | 191 | * @param strided_array_fcn strided array function |
29 | 192 |
|
|
32 | 195 | * |
33 | 196 | * STDLIB_NDARRAY_UNARY_1D( stdlib_strided_b_b ) |
34 | 197 | */ |
35 | | -#define STDLIB_NDARRAY_UNARY_1D( strided_array_fcn ) \ |
| 198 | +#define STDLIB_NDARRAY_UNARY_1D_VIA_STRIDED( strided_array_fcn ) \ |
36 | 199 | struct ndarray *x1 = arrays[ 0 ]; \ |
37 | 200 | struct ndarray *x2 = arrays[ 1 ]; \ |
38 | 201 | int64_t shape[] = { \ |
|
0 commit comments