| 
 | 1 | +/**  | 
 | 2 | +* @license Apache-2.0  | 
 | 3 | +*  | 
 | 4 | +* Copyright (c) 2025 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 | +#ifndef STDLIB_NDARRAY_BASE_EVERY_MACROS_2D_H  | 
 | 20 | +#define STDLIB_NDARRAY_BASE_EVERY_MACROS_2D_H  | 
 | 21 | + | 
 | 22 | +#include "stdlib/ndarray/ctor.h"  | 
 | 23 | +#include "stdlib/ndarray/orders.h"  | 
 | 24 | +#include <stdint.h>  | 
 | 25 | +#include <stdbool.h>  | 
 | 26 | + | 
 | 27 | +/**  | 
 | 28 | +* Macro containing the preamble for nested loops which operate on elements of a two-dimensional ndarray.  | 
 | 29 | +*  | 
 | 30 | +* ## Notes  | 
 | 31 | +*  | 
 | 32 | +* -   Variable naming conventions:  | 
 | 33 | +*  | 
 | 34 | +*     -   `sx#`, `px#`, and `d@x#` where `#` corresponds to the ndarray argument number, starting at `1`.  | 
 | 35 | +*     -   `S@`, `i@`, and `d@x#` where `@` corresponds to the loop number, with `0` being the innermost loop.  | 
 | 36 | +*  | 
 | 37 | +* @example  | 
 | 38 | +* STDLIB_NDARRAY_EVERY_2D_LOOP_PREMABLE {  | 
 | 39 | +*     // Innermost loop body...  | 
 | 40 | +* }  | 
 | 41 | +* STDLIB_NDARRAY_EVERY_2D_LOOP_EPILOGUE  | 
 | 42 | +*/  | 
 | 43 | +#define STDLIB_NDARRAY_EVERY_2D_LOOP_PREAMBLE                                  \  | 
 | 44 | +	const struct ndarray *x1 = arrays[ 0 ];                                    \  | 
 | 45 | +	const struct ndarray *x2 = arrays[ 1 ];                                    \  | 
 | 46 | +	const int64_t *shape = stdlib_ndarray_shape( x1 );                         \  | 
 | 47 | +	const int64_t *sx1 = stdlib_ndarray_strides( x1 );                         \  | 
 | 48 | +	uint8_t *px1 = stdlib_ndarray_data( x1 );                                  \  | 
 | 49 | +	bool *px2 = stdlib_ndarray_data( x2 );                                     \  | 
 | 50 | +	int64_t d0x1;                                                              \  | 
 | 51 | +	int64_t d1x1;                                                              \  | 
 | 52 | +	int64_t S0;                                                                \  | 
 | 53 | +	int64_t S1;                                                                \  | 
 | 54 | +	int64_t i0;                                                                \  | 
 | 55 | +	int64_t i1;                                                                \  | 
 | 56 | +	/* Extract loop variables for purposes of loop interchange: dimensions and loop offset (pointer) increments... */ \  | 
 | 57 | +	if ( stdlib_ndarray_order( x1 ) == STDLIB_NDARRAY_ROW_MAJOR ) {            \  | 
 | 58 | +		/* For row-major ndarrays, the last dimensions have the fastest changing indices... */ \  | 
 | 59 | +		S0 = shape[ 1 ];                                                       \  | 
 | 60 | +		S1 = shape[ 0 ];                                                       \  | 
 | 61 | +		d0x1 = sx1[ 1 ];                                                       \  | 
 | 62 | +		d1x1 = sx1[ 0 ] - ( S0*sx1[1] );                                       \  | 
 | 63 | +	} else {                                                                   \  | 
 | 64 | +		/* For column-major ndarrays, the first dimensions have the fastest changing indices... */ \  | 
 | 65 | +		S0 = shape[ 0 ];                                                       \  | 
 | 66 | +		S1 = shape[ 1 ];                                                       \  | 
 | 67 | +		d0x1 = sx1[ 0 ];                                                       \  | 
 | 68 | +		d1x1 = sx1[ 1 ] - ( S0*sx1[0] );                                       \  | 
 | 69 | +	}                                                                          \  | 
 | 70 | +	/* Set a pointer to the first indexed elements... */                       \  | 
 | 71 | +	px1 += stdlib_ndarray_offset( x1 );                                        \  | 
 | 72 | +	px2 += stdlib_ndarray_offset( x2 );                                        \  | 
 | 73 | +	/* Iterate over the ndarray dimensions... */                               \  | 
 | 74 | +	for ( i1 = 0; i1 < S1; i1++, px1 += d1x1 ) {                               \  | 
 | 75 | +		for ( i0 = 0; i0 < S0; i0++, px1 += d0x1 )  | 
 | 76 | + | 
 | 77 | +/**  | 
 | 78 | +* Macro containing the epilogue for nested loops which operate on elements of a two-dimensional ndarray.  | 
 | 79 | +*  | 
 | 80 | +* @example  | 
 | 81 | +* STDLIB_NDARRAY_EVERY_2D_LOOP_PREMABLE {  | 
 | 82 | +*     // Innermost loop body...  | 
 | 83 | +* }  | 
 | 84 | +* STDLIB_NDARRAY_EVERY_2D_LOOP_EPILOGUE  | 
 | 85 | +*/  | 
 | 86 | +#define STDLIB_NDARRAY_EVERY_2D_LOOP_EPILOGUE                                  \  | 
 | 87 | +	}                                                                          \  | 
 | 88 | +	*px2 = true;  | 
 | 89 | + | 
 | 90 | +/**  | 
 | 91 | +* Macro for a two-dimensional ndarray loop which inlines an expression.  | 
 | 92 | +*  | 
 | 93 | +* ## Notes  | 
 | 94 | +*  | 
 | 95 | +* -   Retrieves each input ndarray element according to type `tin` via the pointer `px1` as `in1`.  | 
 | 96 | +* -   Expects a provided expression to operate on `tin in1`.  | 
 | 97 | +* -   Stores the final result in an output ndarray via the pointer `px2`.  | 
 | 98 | +*  | 
 | 99 | +* @param tin   input type  | 
 | 100 | +* @param expr  expression to inline  | 
 | 101 | +*  | 
 | 102 | +* @example  | 
 | 103 | +* STDLIB_NDARRAY_EVERY_2D_LOOP_INLINE( double, in1 )  | 
 | 104 | +*/  | 
 | 105 | +#define STDLIB_NDARRAY_EVERY_2D_LOOP_INLINE( tin, expr )                       \  | 
 | 106 | +	STDLIB_NDARRAY_EVERY_2D_LOOP_PREAMBLE {                                    \  | 
 | 107 | +		tin *in1 = (tin *)px1;                                                 \  | 
 | 108 | +		if ( !( expr ) ) {                                                     \  | 
 | 109 | +			*px2 = false;                                                      \  | 
 | 110 | +			return;                                                            \  | 
 | 111 | +		}                                                                      \  | 
 | 112 | +	}                                                                          \  | 
 | 113 | +	STDLIB_NDARRAY_EVERY_2D_LOOP_EPILOGUE  | 
 | 114 | + | 
 | 115 | +/**  | 
 | 116 | +* Macro for a two-dimensional ndarray loop which invokes a callback.  | 
 | 117 | +*  | 
 | 118 | +* ## Notes  | 
 | 119 | +*  | 
 | 120 | +* -   Retrieves each ndarray element according to type `tin` via the pointer `px1`.  | 
 | 121 | +* -   Stores the final result in an output ndarray via the pointer `px2`.  | 
 | 122 | +*  | 
 | 123 | +* @param tin   input type  | 
 | 124 | +*  | 
 | 125 | +* @example  | 
 | 126 | +* // e.g., d_x  | 
 | 127 | +* STDLIB_NDARRAY_EVERY_2D_LOOP_CLBK( double )  | 
 | 128 | +*/  | 
 | 129 | +#define STDLIB_NDARRAY_EVERY_2D_LOOP_CLBK( tin )                               \  | 
 | 130 | +	STDLIB_NDARRAY_EVERY_2D_LOOP_PREAMBLE {                                    \  | 
 | 131 | +		const tin x = *(tin *)px1;                                             \  | 
 | 132 | +		if ( !( f( x ) ) ) {                                                   \  | 
 | 133 | +			*px2 = false;                                                      \  | 
 | 134 | +			return;                                                            \  | 
 | 135 | +		}                                                                      \  | 
 | 136 | +	}                                                                          \  | 
 | 137 | +	STDLIB_NDARRAY_EVERY_2D_LOOP_EPILOGUE  | 
 | 138 | + | 
 | 139 | +/**  | 
 | 140 | +* Macro for a two-dimensional ndarray loop which invokes a callback requiring arguments be explicitly cast to a different type.  | 
 | 141 | +*  | 
 | 142 | +* ## Notes  | 
 | 143 | +*  | 
 | 144 | +* -   Retrieves each ndarray element according to type `tin` via the pointer `px1`.  | 
 | 145 | +* -   Explicitly casts each function argument to `fin`.  | 
 | 146 | +* -   Stores the final result in an output ndarray via the pointer `px2`.  | 
 | 147 | +*  | 
 | 148 | +* @param tin   input type  | 
 | 149 | +* @param fin   callback argument type  | 
 | 150 | +*  | 
 | 151 | +* @example  | 
 | 152 | +* // e.g., f_x_as_d_x  | 
 | 153 | +* STDLIB_NDARRAY_EVERY_2D_LOOP_CLBK_ARG_CAST( float, double )  | 
 | 154 | +*/  | 
 | 155 | +#define STDLIB_NDARRAY_EVERY_2D_LOOP_CLBK_ARG_CAST( tin, fin )                 \  | 
 | 156 | +	STDLIB_NDARRAY_EVERY_2D_LOOP_PREAMBLE {                                    \  | 
 | 157 | +		const tin x = *(tin *)px1;                                             \  | 
 | 158 | +		if ( !( f( (fin)x ) ) ) {                                              \  | 
 | 159 | +			*px2 = false;                                                      \  | 
 | 160 | +			return;                                                            \  | 
 | 161 | +		}                                                                      \  | 
 | 162 | +	}                                                                          \  | 
 | 163 | +	STDLIB_NDARRAY_EVERY_2D_LOOP_EPILOGUE  | 
 | 164 | + | 
 | 165 | +/**  | 
 | 166 | +* Macro for a two-dimensional ndarray loop which invokes a callback requiring arguments be cast to a different type via casting functions.  | 
 | 167 | +*  | 
 | 168 | +* ## Notes  | 
 | 169 | +*  | 
 | 170 | +* -   Retrieves each ndarray element according to type `tin` via a pointer `px1`.  | 
 | 171 | +* -   Explicitly casts each function argument via `cin`.  | 
 | 172 | +* -   Stores the final result in an output ndarray via the pointer `px2`.  | 
 | 173 | +*  | 
 | 174 | +* @param tin   input type  | 
 | 175 | +* @param cin   input casting function  | 
 | 176 | +*  | 
 | 177 | +* @example  | 
 | 178 | +* #include "stdlib/complex/float64/ctor.h"  | 
 | 179 | +*  | 
 | 180 | +* // e.g., f_x_as_z_x  | 
 | 181 | +* STDLIB_NDARRAY_EVERY_2D_LOOP_CLBK_ARG_CAST_FCN( float, stdlib_complex128_from_float32 )  | 
 | 182 | +*/  | 
 | 183 | +#define STDLIB_NDARRAY_EVERY_2D_LOOP_CLBK_ARG_CAST_FCN( tin, cin )             \  | 
 | 184 | +	STDLIB_NDARRAY_EVERY_2D_LOOP_PREAMBLE {                                    \  | 
 | 185 | +		const tin x = *(tin *)px1;                                             \  | 
 | 186 | +		if ( !( f( cin( x ) ) ) ) {                                            \  | 
 | 187 | +			*px2 = false;                                                      \  | 
 | 188 | +			return;                                                            \  | 
 | 189 | +		}                                                                      \  | 
 | 190 | +	}                                                                          \  | 
 | 191 | +	STDLIB_NDARRAY_EVERY_2D_LOOP_EPILOGUE  | 
 | 192 | + | 
 | 193 | +#endif // !STDLIB_NDARRAY_BASE_EVERY_MACROS_2D_H  | 
0 commit comments