quinary.c (16660B)
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 /** 20 * Strided array functions for quinary callbacks. 21 * 22 * ## Notes 23 * 24 * - Character codes for data types: 25 * 26 * - d: float64 (double) 27 * - f: float32 (float) 28 * - b: int8 (signed char) 29 * - B: uint8 (unsigned char) 30 * - h: int16 (signed short) 31 * - H: uint16 (unsigned short) 32 * - i: int32 (signed int) 33 * - I: uint32 (unsigned int) 34 * 35 * - Function name suffix naming convention: 36 * 37 * ```text 38 * <base_function_name>[_<input_data_types>]_<output_data_type>[_as_<callback_arg_data_types>_<callback_return_data_type>] 39 * ``` 40 * 41 * For example, 42 * 43 * ```c 44 * void stdlib_strided_dd_d(...) {...} 45 * ``` 46 * 47 * is a function which accepts two strided input arrays containing double-precision floating-point numbers and whose results are cast as double-precision floating-point numbers. In other words, the suffix encodes the function type signature. 48 * 49 * - To support callbacks whose input arguments and/or return values are of a different data type than the input and/or output strided array data types, the naming convention supports appending an `as` suffix. For example, 50 * 51 * ```c 52 * void stdlib_strided_ff_f_as_dd_d(...) {...} 53 * ``` 54 * 55 * is a function which accepts two strided input arrays containing single-precision floating-point numbers and whose results are cast as single-precision floating-point numbers. However, the callback requires each pair of single-precision floating-point numbers be cast to double-precision floating-point numbers when provided as arguments, and the callback return value is a double-precision floating-point number. Accordingly, the conversion process would be 56 * 57 * ```text 58 * float in1 -> double in1 59 * float in2 -> double in2 60 * double out1 = f( in1, in2 ) 61 * float out1 <- double out1 62 * ``` 63 * 64 */ 65 #include "stdlib/strided/common/quinary.h" 66 #include "stdlib/strided/common/quinary_typedefs.h" 67 #include "stdlib/strided/common/quinary_macros.h" 68 #include <stdint.h> 69 70 /** 71 * Applies a quinary callback to strided input arrays. 72 * 73 * @param arrays array whose first five elements are pointers to strided input arrays and whose last element is a pointer to a strided output array 74 * @param shape array whose only element is the number of elements over which to iterate 75 * @param strides array containing strides (in bytes) for each strided array 76 * @param fcn callback 77 * 78 * @example 79 * #include "stdlib/strided/common/quinary.h" 80 * #include <stdint.h> 81 * 82 * // Create underlying byte arrays: 83 * uint8_t x[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 84 * uint8_t y[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 85 * uint8_t z[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 86 * uint8_t w[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 87 * uint8_t v[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 88 * uint8_t out[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 89 * 90 * // Define a pointer to an array containing pointers to strided arrays: 91 * uint8_t *arrays[] = { x, y, z, w, v, out }; 92 * 93 * // Define the strides: 94 * int64_t strides[] = { 8, 8, 8, 8, 8, 8 }; // 8 bytes per double 95 * 96 * // Define the number of elements over which to iterate: 97 * int64_t shape[] = { 3 }; 98 * 99 * // Define a callback: 100 * double add5( double x, double y, double z, double w, double v ) { 101 * return x + y + z + w + v; 102 * } 103 * 104 * // Apply the callback: 105 * stdlib_strided_ddddd_d( arrays, shape, strides, (void *)add5 ); 106 */ 107 void stdlib_strided_ddddd_d( uint8_t *arrays[], int64_t *shape, int64_t *strides, void *fcn ) { 108 QuinaryFcnFloat64 *f = (QuinaryFcnFloat64 *)fcn; 109 STDLIB_QUINARY_LOOP_CLBK( double, double ) 110 } 111 112 /** 113 * Applies a quinary callback to strided input arrays. 114 * 115 * @param arrays array whose first five elements are pointers to strided input arrays and whose last element is a pointer to a strided output array 116 * @param shape array whose only element is the number of elements over which to iterate 117 * @param strides array containing strides (in bytes) for each strided array 118 * @param fcn callback 119 * 120 * @example 121 * #include "stdlib/strided/common/quinary.h" 122 * #include <stdint.h> 123 * 124 * // Create underlying byte arrays: 125 * uint8_t x[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 126 * uint8_t y[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 127 * uint8_t z[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 128 * uint8_t w[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 129 * uint8_t v[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 130 * uint8_t out[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 131 * 132 * // Define a pointer to an array containing pointers to strided arrays: 133 * uint8_t *arrays[] = { x, y, z, w, v, out }; 134 * 135 * // Define the strides: 136 * int64_t strides[] = { 4, 4, 4, 4, 4, 4 }; // 4 bytes per float 137 * 138 * // Define the number of elements over which to iterate: 139 * int64_t shape[] = { 3 }; 140 * 141 * // Define a callback: 142 * float add5( float x, float y, float z, float w, float v ) { 143 * return x + y + z + w + v; 144 * } 145 * 146 * // Apply the callback: 147 * stdlib_strided_fffff_f( arrays, shape, strides, (void *)add5 ); 148 */ 149 void stdlib_strided_fffff_f( uint8_t *arrays[], int64_t *shape, int64_t *strides, void *fcn ) { 150 QuinaryFcnFloat32 *f = (QuinaryFcnFloat32 *)fcn; 151 STDLIB_QUINARY_LOOP_CLBK( float, float ) 152 } 153 154 /** 155 * Applies a quinary callback to strided input arrays, casting the callback's double-precision return value to a single-precision floating-point number. 156 * 157 * @param arrays array whose first five elements are pointers to strided input arrays and whose last element is a pointer to a strided output array 158 * @param shape array whose only element is the number of elements over which to iterate 159 * @param strides array containing strides (in bytes) for each strided array 160 * @param fcn callback 161 * 162 * @example 163 * #include "stdlib/strided/common/quinary.h" 164 * #include <stdint.h> 165 * 166 * // Create underlying byte arrays: 167 * uint8_t x[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 168 * uint8_t y[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 169 * uint8_t z[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 170 * uint8_t w[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 171 * uint8_t v[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 172 * uint8_t out[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 173 * 174 * // Define a pointer to an array containing pointers to strided arrays: 175 * uint8_t *arrays[] = { x, y, z, w, v, out }; 176 * 177 * // Define the strides: 178 * int64_t strides[] = { 4, 4, 4, 4, 4, 4 }; // 4 bytes per float 179 * 180 * // Define the number of elements over which to iterate: 181 * int64_t shape[] = { 3 }; 182 * 183 * // Define a callback: 184 * double add5( double x, double y, double z, double w, double v ) { 185 * return x + y + z + w + v; 186 * } 187 * 188 * // Apply the callback: 189 * stdlib_strided_fffff_f_as_ddddd_d( arrays, shape, strides, (void *)add5 ); 190 */ 191 void stdlib_strided_fffff_f_as_ddddd_d( uint8_t *arrays[], int64_t *shape, int64_t *strides, void *fcn ) { 192 QuinaryFcnFloat64 *f = (QuinaryFcnFloat64 *)fcn; 193 STDLIB_QUINARY_LOOP_CLBK_ARG_CAST( float, float, double ) 194 } 195 196 /** 197 * Applies a quinary callback to strided input arrays. 198 * 199 * @param arrays array whose first five elements are pointers to strided input arrays and whose last element is a pointer to a strided output array 200 * @param shape array whose only element is the number of elements over which to iterate 201 * @param strides array containing strides (in bytes) for each strided array 202 * @param fcn callback 203 * 204 * @example 205 * #include "stdlib/strided/common/quinary.h" 206 * #include <stdint.h> 207 * 208 * // Create underlying byte arrays: 209 * uint8_t x[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 210 * uint8_t y[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 211 * uint8_t z[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 212 * uint8_t w[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 213 * uint8_t v[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 214 * uint8_t out[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 215 * 216 * // Define a pointer to an array containing pointers to strided arrays: 217 * uint8_t *arrays[] = { x, y, z, w, v, out }; 218 * 219 * // Define the strides: 220 * int64_t strides[] = { 4, 4, 4, 4, 4, 4 }; // 4 bytes per uint32 221 * 222 * // Define the number of elements over which to iterate: 223 * int64_t shape[] = { 3 }; 224 * 225 * // Define a callback: 226 * uint32_t add5( uint32_t x, uint32_t y, uint32_t z, uint32_t w, uint32_t v ) { 227 * return x + y + z + w + v; 228 * } 229 * 230 * // Apply the callback: 231 * stdlib_strided_IIIII_I( arrays, shape, strides, (void *)add5 ); 232 */ 233 void stdlib_strided_IIIII_I( uint8_t *arrays[], int64_t *shape, int64_t *strides, void *fcn ) { 234 QuinaryFcnUint32 *f = (QuinaryFcnUint32 *)fcn; 235 STDLIB_QUINARY_LOOP_CLBK( uint32_t, uint32_t ) 236 } 237 238 /** 239 * Applies a quinary callback to strided input arrays. 240 * 241 * @param arrays array whose first five elements are pointers to strided input arrays and whose last element is a pointer to a strided output array 242 * @param shape array whose only element is the number of elements over which to iterate 243 * @param strides array containing strides (in bytes) for each strided array 244 * @param fcn callback 245 * 246 * @example 247 * #include "stdlib/strided/common/quinary.h" 248 * #include <stdint.h> 249 * 250 * // Create underlying byte arrays: 251 * uint8_t x[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 252 * uint8_t y[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 253 * uint8_t z[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 254 * uint8_t w[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 255 * uint8_t v[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 256 * uint8_t out[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; 257 * 258 * // Define a pointer to an array containing pointers to strided arrays: 259 * uint8_t *arrays[] = { x, y, z, w, v, out }; 260 * 261 * // Define the strides: 262 * int64_t strides[] = { 4, 4, 4, 4, 4, 4 }; // 4 bytes per int32 263 * 264 * // Define the number of elements over which to iterate: 265 * int64_t shape[] = { 3 }; 266 * 267 * // Define a callback: 268 * int32_t add5( int32_t x, int32_t y, int32_t z, int32_t w, int32_t v ) { 269 * return x + y + z + w + v; 270 * } 271 * 272 * // Apply the callback: 273 * stdlib_strided_iiiii_i( arrays, shape, strides, (void *)add5 ); 274 */ 275 void stdlib_strided_iiiii_i( uint8_t *arrays[], int64_t *shape, int64_t *strides, void *fcn ) { 276 QuinaryFcnInt32 *f = (QuinaryFcnInt32 *)fcn; 277 STDLIB_QUINARY_LOOP_CLBK( int32_t, int32_t ) 278 } 279 280 /** 281 * Applies a quinary callback to strided input arrays. 282 * 283 * @param arrays array whose first five elements are pointers to strided input arrays and whose last element is a pointer to a strided output array 284 * @param shape array whose only element is the number of elements over which to iterate 285 * @param strides array containing strides (in bytes) for each strided array 286 * @param fcn callback 287 * 288 * @example 289 * #include "stdlib/strided/common/quinary.h" 290 * #include <stdint.h> 291 * 292 * // Create underlying byte arrays: 293 * uint8_t x[] = { 0, 0, 0, 0, 0, 0 }; 294 * uint8_t y[] = { 0, 0, 0, 0, 0, 0 }; 295 * uint8_t z[] = { 0, 0, 0, 0, 0, 0 }; 296 * uint8_t w[] = { 0, 0, 0, 0, 0, 0 }; 297 * uint8_t v[] = { 0, 0, 0, 0, 0, 0 }; 298 * uint8_t out[] = { 0, 0, 0, 0, 0, 0 }; 299 * 300 * // Define a pointer to an array containing pointers to strided arrays: 301 * uint8_t *arrays[] = { x, y, z, w, v, out }; 302 * 303 * // Define the strides: 304 * int64_t strides[] = { 2, 2, 2, 2, 2, 2 }; // 2 bytes per uint16 305 * 306 * // Define the number of elements over which to iterate: 307 * int64_t shape[] = { 3 }; 308 * 309 * // Define a callback: 310 * uint16_t add5( uint16_t x, uint16_t y, uint16_t z, uint16_t w, uint16_t v ) { 311 * return x + y + z + w + v; 312 * } 313 * 314 * // Apply the callback: 315 * stdlib_strided_HHHHH_H( arrays, shape, strides, (void *)add5 ); 316 */ 317 void stdlib_strided_HHHHH_H( uint8_t *arrays[], int64_t *shape, int64_t *strides, void *fcn ) { 318 QuinaryFcnUint16 *f = (QuinaryFcnUint16 *)fcn; 319 STDLIB_QUINARY_LOOP_CLBK( uint16_t, uint16_t ) 320 } 321 322 /** 323 * Applies a quinary callback to strided input arrays. 324 * 325 * @param arrays array whose first five elements are pointers to strided input arrays and whose last element is a pointer to a strided output array 326 * @param shape array whose only element is the number of elements over which to iterate 327 * @param strides array containing strides (in bytes) for each strided array 328 * @param fcn callback 329 * 330 * @example 331 * #include "stdlib/strided/common/quinary.h" 332 * #include <stdint.h> 333 * 334 * // Create underlying byte arrays: 335 * uint8_t x[] = { 0, 0, 0, 0, 0, 0 }; 336 * uint8_t y[] = { 0, 0, 0, 0, 0, 0 }; 337 * uint8_t z[] = { 0, 0, 0, 0, 0, 0 }; 338 * uint8_t w[] = { 0, 0, 0, 0, 0, 0 }; 339 * uint8_t v[] = { 0, 0, 0, 0, 0, 0 }; 340 * uint8_t out[] = { 0, 0, 0, 0, 0, 0 }; 341 * 342 * // Define a pointer to an array containing pointers to strided arrays: 343 * uint8_t *arrays[] = { x, y, z, w, v, out }; 344 * 345 * // Define the strides: 346 * int64_t strides[] = { 2, 2, 2, 2, 2, 2 }; // 2 bytes per int16 347 * 348 * // Define the number of elements over which to iterate: 349 * int64_t shape[] = { 3 }; 350 * 351 * // Define a callback: 352 * int16_t add5( int16_t x, int16_t y, int16_t z, int16_t w, int16_t v ) { 353 * return x + y + z + w + v; 354 * } 355 * 356 * // Apply the callback: 357 * stdlib_strided_hhhhh_h( arrays, shape, strides, (void *)add5 ); 358 */ 359 void stdlib_strided_hhhhh_h( uint8_t *arrays[], int64_t *shape, int64_t *strides, void *fcn ) { 360 QuinaryFcnInt16 *f = (QuinaryFcnInt16 *)fcn; 361 STDLIB_QUINARY_LOOP_CLBK( int16_t, int16_t ) 362 } 363 364 /** 365 * Applies a quinary callback to strided input arrays. 366 * 367 * @param arrays array whose first five elements are pointers to strided input arrays and whose last element is a pointer to a strided output array 368 * @param shape array whose only element is the number of elements over which to iterate 369 * @param strides array containing strides (in bytes) for each strided array 370 * @param fcn callback 371 * 372 * @example 373 * #include "stdlib/strided/common/quinary.h" 374 * #include <stdint.h> 375 * 376 * // Create underlying byte arrays: 377 * uint8_t x[] = { 0, 0, 0 }; 378 * uint8_t y[] = { 0, 0, 0 }; 379 * uint8_t z[] = { 0, 0, 0 }; 380 * uint8_t w[] = { 0, 0, 0 }; 381 * uint8_t v[] = { 0, 0, 0 }; 382 * uint8_t out[] = { 0, 0, 0 }; 383 * 384 * // Define a pointer to an array containing pointers to strided arrays: 385 * uint8_t *arrays[] = { x, y, z, w, v, out }; 386 * 387 * // Define the strides: 388 * int64_t strides[] = { 1, 1, 1, 1, 1, 1 }; // 1 bytes per uint8 389 * 390 * // Define the number of elements over which to iterate: 391 * int64_t shape[] = { 3 }; 392 * 393 * // Define a callback: 394 * uint8_t add5( uint8_t x, uint8_t y, uint8_t z, uint8_t w, uint8_t v ) { 395 * return x + y + z + w + v; 396 * } 397 * 398 * // Apply the callback: 399 * stdlib_strided_BBBBB_B( arrays, shape, strides, (void *)add5 ); 400 */ 401 void stdlib_strided_BBBBB_B( uint8_t *arrays[], int64_t *shape, int64_t *strides, void *fcn ) { 402 QuinaryFcnUint8 *f = (QuinaryFcnUint8 *)fcn; 403 STDLIB_QUINARY_LOOP_CLBK( uint8_t, uint8_t ) 404 } 405 406 /** 407 * Applies a quinary callback to strided input arrays. 408 * 409 * @param arrays array whose first five elements are pointers to strided input arrays and whose last element is a pointer to a strided output array 410 * @param shape array whose only element is the number of elements over which to iterate 411 * @param strides array containing strides (in bytes) for each strided array 412 * @param fcn callback 413 * 414 * @example 415 * #include "stdlib/strided/common/quinary.h" 416 * #include <stdint.h> 417 * 418 * // Create underlying byte arrays: 419 * uint8_t x[] = { 0, 0, 0 }; 420 * uint8_t y[] = { 0, 0, 0 }; 421 * uint8_t z[] = { 0, 0, 0 }; 422 * uint8_t w[] = { 0, 0, 0 }; 423 * uint8_t v[] = { 0, 0, 0 }; 424 * uint8_t out[] = { 0, 0, 0 }; 425 * 426 * // Define a pointer to an array containing pointers to strided arrays: 427 * uint8_t *arrays[] = { x, y, z, w, v, out }; 428 * 429 * // Define the strides: 430 * int64_t strides[] = { 1, 1, 1, 1, 1, 1 }; // 1 bytes per int8 431 * 432 * // Define the number of elements over which to iterate: 433 * int64_t shape[] = { 3 }; 434 * 435 * // Define a callback: 436 * int8_t add5( int8_t x, int8_t y, int8_t z, int8_t w, int8_t v ) { 437 * return x + y + z + w + v; 438 * } 439 * 440 * // Apply the callback: 441 * stdlib_strided_bbbbb_b( arrays, shape, strides, (void *)add5 ); 442 */ 443 void stdlib_strided_bbbbb_b( uint8_t *arrays[], int64_t *shape, int64_t *strides, void *fcn ) { 444 QuinaryFcnInt8 *f = (QuinaryFcnInt8 *)fcn; 445 STDLIB_QUINARY_LOOP_CLBK( int8_t, int8_t ) 446 }