RosettaCodeData/Task/Arrays/C/arrays-3.c
2026-04-30 12:34:36 -04:00

114 lines
3.8 KiB
C

#pragma once
/* gcc/clang flags
CFLAGS="
-march=native
-mfpmath=<your SIMD>
-O3
-ftree-vectorize
-fopenmp
-fopenmp-simd
-std=gnu23"
For MSVC see: https://learn.microsoft.com/en-us/cpp/parallel/openmp/openmp-simd?view=msvc-180
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdalign.h>
#include <sys/param.h>
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wgnu-alignof-expression"
#endif
#ifdef _MSC_VER
#define INLINE __force_inline __flatten __declspec(nothrow) __declspec(noalias) inline
#else
#define INLINE __attribute__((always_inline,flatten,nothrow,const)) inline
#endif
/* define missing bit ceil function first for power of 2 memory alignment */
#define BITOP_RUP01__(x) ( (x) | ( (x) >> 1))
#define BITOP_RUP02__(x) (BITOP_RUP01__(x) | (BITOP_RUP01__(x) >> 2))
#define BITOP_RUP04__(x) (BITOP_RUP02__(x) | (BITOP_RUP02__(x) >> 4))
#define BITOP_RUP08__(x) (BITOP_RUP04__(x) | (BITOP_RUP04__(x) >> 8))
#define BITOP_RUP16__(x) (BITOP_RUP08__(x) | (BITOP_RUP08__(x) >> 16))
#define bitceil(x) (BITOP_RUP16__(((uint32_t)(x)) - 1) + 1)
/* define different array types */
#define arr(T,N) typeof(T[N]) /* fixed static array of arbitrary length and type */
#define vla(T ) typeof(T[ ]) /* variable length array - VLA */
/* define vector extension power of 2 sized SIMD vector types for non MSVC */
#ifndef _MSC_VER
#ifdef __clang__
#define vec_ext(T,N) typeof(T __attribute__((ext_vector_type(N))))
#else
#define vec_ext(T,N) typeof(T __attribute__((vector_size(bitceil(alignof(T) * N)))))
#endif
#endif
/* sum using OpenMP */
#define sum(a,n,i) \
({ \
typeof((a)[0]) dst = i; \
_Pragma("omp simd reduction(+:dst)") \
for(size_t j = 0; j < MIN(countof(a),n); j++) \
dst += (a)[j]; \
dst; \
})
/* dot using OpenMP */
#define dot(a,b,n,i) \
({ \
typeof((a)[0]) dst = i; \
_Pragma("omp simd reduction(+:dst)") \
for(size_t j = 0; j < MIN(MIN(countof(a),countof(b)),n); j++) \
dst += (a)[j] * (b)[j]; \
dst; \
})
/* define array verification and element count */
#undef countof
#define countof(a ) (sizeof((a))/sizeof((a)[0]))
#define isarray(a ) __builtin_choose_expr(__builtin_types_compatible_p(typeof((a)[0]) [], typeof((a))), true, false)
/* define variable argument macros */
#define countargs(...) (0 __VA_OPT__(+sizeof((typeof(__VA_ARGS__)[]){__VA_ARGS__})/sizeof(__VA_ARGS__)))
#define emptyargs(...) (true __VA_OPT__(-1))
/* add missing parens and expand for permute */
#define PARENS ()
#define EXPAND(...) EXPAND4(EXPAND4(EXPAND4(EXPAND4(__VA_ARGS__))))
#define EXPAND4(...) EXPAND3(EXPAND3(EXPAND3(EXPAND3(__VA_ARGS__))))
#define EXPAND3(...) EXPAND2(EXPAND2(EXPAND2(EXPAND2(__VA_ARGS__))))
#define EXPAND2(...) EXPAND1(EXPAND1(EXPAND1(EXPAND1(__VA_ARGS__))))
#define EXPAND1(...) __VA_ARGS__
/* add permute */
#define perm(a,...) { __VA_OPT__(EXPAND(perm_helper(a,__VA_ARGS__))) }
#define perm_helper(a,i,...) (a)[i], __VA_OPT__(perm_again PARENS (a,__VA_ARGS__))
#define perm_again() perm_helper
#define perm3(a,x,y,z ) (vec_ext(typeof((a)[0]),3))perm(a,x,y,z )
#define perm4(a,x,y,z,w) (vec_ext(typeof((a)[0]),4))perm(a,x,y,z,w)
/* cross3 - 3-dimensional vector product for vector extension types only
* TODO:
* - support vector/array types without operators
* - n-dimensional hodge star operator vector product based on
* levi-civita, laplace expansion and determinant as a
* left contraction grade projection operator. See Clifford, Hodge,
*/
#define cross3(a,b) \
perm3(a,1,2,0) * perm3(b,2,0,1) \
- perm3(a,2,1,0) * perm3(b,1,2,0)
/* TODO: https://github.com/HolyBlackCat/macro_sequence_for
* duplicate array using initializer list and
* make indexed sequence unrolling for loop based on
* boilerplates.
*/
#define dup(a ) { (a)[0]...(a)[countof(a)-1] };