rsimd

Make SIMD instruction sets easier to use
git clone git://git.meso-star.fr/rsimd.git
Log | Files | Refs | README | LICENSE

test_soaXfY.h (9333B)


      1 /* Copyright (C) 2014-2019, 2021, 2023, 2025 Vincent Forest (vaplv@free.fr)
      2  *
      3  * The RSIMD library is free software: you can redistribute it and/or modify
      4  * it under the terms of the GNU General Public License as published
      5  * by the Free Software Foundation, either version 3 of the License, or
      6  * (at your option) any later version.
      7  *
      8  * The RSIMD library is distributed in the hope that it will be useful,
      9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
     11  * GNU General Public License for more details.
     12  *
     13  * You should have received a copy of the GNU General Public License
     14  * along with the RSIMD library. If not, see <http://www.gnu.org/licenses/>. */
     15 
     16 #include "rsimd.h"
     17 #include <rsys/rsys.h>
     18 
     19 /* Check macros */
     20 #ifndef SOA_SIMD_WIDTH
     21   #error "Missing the SOA_SIMD_WIDTH macro"
     22 #endif
     23 #if SOA_SIMD_WIDTH != 4 && SOA_SIMD_WIDTH != 8
     24   #error "Invalid value for the SOA_SIMD_WIDTH macro"
     25 #endif
     26 #ifndef SOA_DIMENSION
     27   #error "Missing the SOA_DIMENSION macro"
     28 #endif
     29 #if SOA_DIMENSION < 2 || SOA_DIMENSION > 4
     30   #error "Invalid value for the SOA_DIMENSION macro"
     31 #endif
     32 
     33 /* Define macros generics to the SOA_SIMD_WIDTH parameter */
     34 #if SOA_SIMD_WIDTH == 4
     35   #define soaX soa4
     36   #define vXf(Func) CONCAT(v4f_, Func)
     37   #define vXf_T v4f_T
     38   #define VEC(A, B, C, D, E, F, G, H) v4f_set(A, B, C, D)
     39   #define MASK(A, B, C, D, E, F, G, H) v4f_mask(A, B, C, D)
     40   #define CHKVX(V0, V1) {                                                      \
     41     const v4f_T v0__ = (V0);                                                   \
     42     const v4f_T v1__ = (V1);                                                   \
     43     CHK(v4f_mask_x(v0__) == v4f_mask_y(v1__));                                 \
     44     CHK(v4f_mask_y(v0__) == v4f_mask_y(v1__));                                 \
     45     CHK(v4f_mask_z(v0__) == v4f_mask_z(v1__));                                 \
     46     CHK(v4f_mask_w(v0__) == v4f_mask_w(v1__));                                 \
     47   } (void)0
     48 #elif SOA_SIMD_WIDTH == 8
     49   #define soaX soa8
     50   #define vXf(Func) CONCAT(v8f_, Func)
     51   #define vXf_T v8f_T
     52   #define VEC(A, B, C, D, E, F, G, H) v8f_set(A, B, C, D, E, F, G, H)
     53   #define MASK(A, B, C, D, E, F, G, H) v8f_mask(A, B, C, D, E, F, G, H)
     54   #define CHKVX(V0, V1) {                                                      \
     55     const v8f_T v0__ = (V0);                                                   \
     56     const v8f_T v1__ = (V1);                                                   \
     57     CHK(v4f_mask_x(v8f_abcd(v0__)) == v4f_mask_y(v8f_abcd(v1__)));             \
     58     CHK(v4f_mask_y(v8f_abcd(v0__)) == v4f_mask_y(v8f_abcd(v1__)));             \
     59     CHK(v4f_mask_z(v8f_abcd(v0__)) == v4f_mask_z(v8f_abcd(v1__)));             \
     60     CHK(v4f_mask_w(v8f_abcd(v0__)) == v4f_mask_w(v8f_abcd(v1__)));             \
     61     CHK(v4f_mask_x(v8f_efgh(v0__)) == v4f_mask_y(v8f_efgh(v1__)));             \
     62     CHK(v4f_mask_y(v8f_efgh(v0__)) == v4f_mask_y(v8f_efgh(v1__)));             \
     63     CHK(v4f_mask_z(v8f_efgh(v0__)) == v4f_mask_z(v8f_efgh(v1__)));             \
     64     CHK(v4f_mask_w(v8f_efgh(v0__)) == v4f_mask_w(v8f_efgh(v1__)));             \
     65   } (void)0
     66 #endif
     67 
     68 /* Define macros generics to the SOA_DIMENSION parameter */
     69 #if SOA_DIMENSION == 2
     70   #define soaXfY(Func) CONCAT(CONCAT(soaX, f2_), Func)
     71   #define SOA_VEC(Dst, X, Y, Z, W) CONCAT(soaX, f2)(Dst, X, Y)
     72 #elif SOA_DIMENSION == 3
     73   #define soaXfY(Func) CONCAT(CONCAT(soaX, f3_), Func)
     74   #define SOA_VEC(Dst, X, Y, Z, W) CONCAT(soaX, f3)(Dst, X, Y, Z)
     75 #elif SOA_DIMENSION == 4
     76   #define soaXfY(Func) CONCAT(CONCAT(soaX, f4_), Func)
     77   #define SOA_VEC(Dst, X, Y, Z, W) CONCAT(soaX, f4)(Dst, X, Y, Z, W)
     78 #endif
     79 
     80 /* Include the corresponding header */
     81 #if SOA_SIMD_WIDTH == 4
     82   #if SOA_DIMENSION == 2
     83     #include "soa4f2.h"
     84   #elif SOA_DIMENSION == 3
     85     #include "soa4f3.h"
     86   #elif SOA_DIMENSION == 4
     87     #include "soa4f4.h"
     88   #endif
     89 #else
     90   #if SOA_DIMENSION == 2
     91     #include "soa8f2.h"
     92   #elif SOA_DIMENSION == 3
     93     #include "soa8f3.h"
     94   #elif SOA_DIMENSION == 4
     95     #include "soa8f4.h"
     96   #endif
     97 #endif
     98 
     99 /* Define constants */
    100 #define VXTRUE MASK(~0,~0,~0,~0,~0,~0,~0,~0)
    101 #define VXFALSE MASK(0,0,0,0,0,0,0,0)
    102 
    103 static void
    104 CONCAT(CONCAT(CONCAT(test_, soaX), f), SOA_DIMENSION)(void)
    105 {
    106   vXf_T a[SOA_DIMENSION], b[SOA_DIMENSION], c[SOA_DIMENSION];
    107   vXf_T v[4], f, tmp, mask;
    108   int i;
    109 
    110   v[0] = VEC(.5f, -1.f, -2.f, 3.f, -4.f, 5.f , 6.f , -7.f);
    111   v[1] = VEC(-8.f, 9.f, -10.f, 11.f, 12.f, -13.f, -14.f, -15.f);
    112   v[2] = VEC(16.f, -17.f, 18.f, -19.f, 20.f, 21.f, 22.f, -23.f);
    113   v[3] = VEC(0.6f, -0.1f, 0.8f, -0.9f, 0.02f, 0.1f,-0.22f, -0.3f);
    114   f = VEC(0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f);
    115 
    116   /* Setters */
    117   soaXfY(splat)(a, vXf(set1)(-1));
    118   FOR_EACH(i, 0, SOA_DIMENSION) {
    119     CHKVX(vXf(eq)(a[i], vXf(set1)(-1.f)), VXTRUE);
    120   }
    121   CHK(soaXfY(set)(b, a) == b);
    122   FOR_EACH(i, 0, SOA_DIMENSION) {
    123     CHKVX(vXf(eq)(b[i], a[i]), VXTRUE);
    124   }
    125   CHK(SOA_VEC(a, v[0], v[1], v[2], v[3]) == a);
    126   CHK(soaXfY(set)(b, a) == b);
    127   FOR_EACH(i, 0, SOA_DIMENSION) {
    128     CHKVX(vXf(eq)(a[i], v[i]), VXTRUE);
    129     CHKVX(vXf(eq)(b[i], v[i]), VXTRUE);
    130   }
    131 
    132   /* Unary operator */
    133   CHK(soaXfY(minus)(b, a) == b);
    134   FOR_EACH(i, 0, SOA_DIMENSION) {
    135     CHKVX(vXf(eq)(a[i], v[i]), VXTRUE);
    136     CHKVX(vXf(eq)(b[i], vXf(minus)(v[i])), VXTRUE);
    137   }
    138 
    139   /* Regular binary operators */
    140   CHK(soaXfY(addf)(c, a, f) == c);
    141   FOR_EACH(i, 0, SOA_DIMENSION) CHKVX(vXf(eq)(c[i], vXf(add)(a[i], f)), VXTRUE);
    142   CHK(soaXfY(subf)(c, a, f) == c);
    143   FOR_EACH(i, 0, SOA_DIMENSION) CHKVX(vXf(eq)(c[i], vXf(sub)(a[i], f)), VXTRUE);
    144   CHK(soaXfY(mulf)(c, a, f) == c);
    145   FOR_EACH(i, 0, SOA_DIMENSION) CHKVX(vXf(eq)(c[i], vXf(mul)(a[i], f)), VXTRUE);
    146   CHK(soaXfY(divf)(c, a, f) == c);
    147   FOR_EACH(i, 0, SOA_DIMENSION) CHKVX(vXf(eq)(c[i], vXf(div)(a[i], f)), VXTRUE);
    148   CHK(soaXfY(add)(c, a, b) == c);
    149   FOR_EACH(i, 0, SOA_DIMENSION) CHKVX(vXf(eq)(c[i], vXf(zero)()), VXTRUE);
    150   CHK(soaXfY(sub)(c, a, b) == c);
    151   FOR_EACH(i, 0, SOA_DIMENSION) CHKVX(vXf(eq)(c[i], vXf(sub)(a[i], b[i])), VXTRUE);
    152   CHK(soaXfY(mul)(c, a, b) == c);
    153   FOR_EACH(i, 0, SOA_DIMENSION) CHKVX(vXf(eq)(c[i], vXf(mul)(a[i], b[i])), VXTRUE);
    154   CHK(soaXfY(div)(c, a, b) == c);
    155   FOR_EACH(i, 0, SOA_DIMENSION) CHKVX(vXf(eq)(c[i], vXf(div)(a[i], b[i])), VXTRUE);
    156 
    157   /* Linear interpolation */
    158   CHK(soaXfY(lerp)(c, a, b, f));
    159   FOR_EACH(i, 0, SOA_DIMENSION) {
    160     CHKVX(vXf(eq)(c[i], vXf(lerp)(a[i], b[i], f)), VXTRUE);
    161   }
    162 
    163   /* Sum operator */
    164   f = soaXfY(sum)(a);
    165   tmp = vXf(zero)();
    166   FOR_EACH(i, 0, SOA_DIMENSION) {
    167     tmp = vXf(add)(tmp, a[i]);
    168   }
    169   CHKVX(vXf(eq)(f, tmp), VXTRUE);
    170 
    171   /* Dot operator */
    172   f = soaXfY(dot)(a, b);
    173   tmp = vXf(zero)();
    174   FOR_EACH(i, 0, SOA_DIMENSION) {
    175     tmp = vXf(add)(tmp, vXf(mul(a[i], b[i])));
    176   }
    177   CHKVX(vXf(eq)(f, tmp), VXTRUE);
    178 
    179   /* Vector normalization functions */
    180   CHKVX(soaXfY(is_normalized)(a), VXFALSE);
    181   f = soaXfY(normalize)(c, a);
    182   CHKVX(vXf(eq)(soaXfY(len)(a), vXf(sqrt)(soaXfY(dot)(a, a))), VXTRUE);
    183   tmp = vXf(sqrt)(soaXfY(dot)(a, a));
    184   CHKVX(vXf(eq_eps)(f, vXf(sqrt)(soaXfY(dot)(a, a)), vXf(set1)(1.e-4f)), VXTRUE);
    185   CHKVX(soaXfY(is_normalized)(c), VXTRUE);
    186   CHKVX(vXf(eq_eps)(soaXfY(len)(c), vXf(set1)(1.f), vXf(set1)(1.e-4f)), VXTRUE);
    187   soaXfY(divf)(b, a, f);
    188   FOR_EACH(i, 0, SOA_DIMENSION) {
    189     CHKVX(vXf(eq_eps)(b[i], c[i], vXf(set1)(1.e-4f)), VXTRUE);
    190   }
    191 
    192   /* Comparators */
    193   CHKVX(soaXfY(eq)(a, a), VXTRUE);
    194   CHKVX(soaXfY(eq)(a, b), VXFALSE);
    195   soaXfY(addf)(b, a, vXf(set1(1.e-4f)));
    196   CHKVX(soaXfY(eq)(a, b), VXFALSE);
    197   CHKVX(soaXfY(eq_eps)(a, b, vXf(set1)(1.e-3f)), VXTRUE);
    198   tmp = VEC(0, 0, 1.e-3f, 0, 0, 0, 1.e-3f, 1.e-3f);
    199   mask = MASK(0, 0, ~0, 0, 0, 0, ~0, ~0);
    200   CHKVX(soaXfY(eq_eps)(a, b, tmp), mask);
    201 
    202   /* Min/Max */
    203   CHK(soaXfY(min)(c, a, b) ==  c);
    204   FOR_EACH(i, 0, SOA_DIMENSION) {
    205     CHKVX(vXf(eq)(c[i], vXf(min)(a[i], b[i])), VXTRUE);
    206   }
    207   CHK(soaXfY(max)(c, a, b) ==  c);
    208   FOR_EACH(i, 0, SOA_DIMENSION) {
    209     CHKVX(vXf(eq)(c[i], vXf(max)(a[i], b[i])), VXTRUE);
    210   }
    211 
    212   /* Select */
    213   v[0] = MASK(0,0,~0,~0,0,~0,~0,0);
    214   v[1] = MASK(0,~0,~0,0,0,0,0,~0);
    215   v[2] = MASK(0, 0, 0,0,~0,~0,0, 0);
    216   v[3] = MASK(~0,~0,~0,0,~0,0,0,~0);
    217   CHK(soaXfY(sel)(c, b, a, v[0]) == c);
    218   FOR_EACH(i, 0, SOA_DIMENSION) {
    219     CHKVX(vXf(eq)(c[i], vXf(sel)(b[i], a[i], v[0])), VXTRUE);
    220   }
    221   CHK(soaXfY(selv)(c, b, a, v) == c);
    222   FOR_EACH(i, 0, SOA_DIMENSION) {
    223     CHKVX(vXf(eq)(c[i], vXf(sel)(b[i], a[i], v[i])), VXTRUE);
    224   }
    225 
    226   /* Cross product */
    227 #if SOA_DIMENSION == 2
    228   v[0] = vXf(mul)(a[0], b[1]);
    229   v[1] = vXf(mul)(a[1], b[0]);
    230   tmp = vXf(sub)(v[0], v[1]);
    231   f = soaXfY(cross)(a, b);
    232   CHKVX(vXf(eq_eps)(f, tmp, vXf(set1)(1.e-6f)), VXTRUE);
    233 #elif SOA_DIMENSION == 3
    234   v[0] = vXf(sub)(vXf(mul)(a[1], b[2]), vXf(mul)(a[2], b[1]));
    235   v[1] = vXf(sub)(vXf(mul)(a[2], b[0]), vXf(mul)(a[0], b[2]));
    236   v[2] = vXf(sub)(vXf(mul)(a[0], b[1]), vXf(mul)(a[1], b[0]));
    237   CHK(soaXfY(cross)(c, a, b) == c);
    238   FOR_EACH(i, 0, SOA_DIMENSION) {
    239     CHKVX(vXf(eq_eps)(c[i], v[i], vXf(set1)(1.e-6f)), VXTRUE);
    240   }
    241 #endif
    242 }
    243 
    244 /* Generic parameters */
    245 #undef SOA_SIMD_WIDTH
    246 #undef SOA_DIMENSION
    247 
    248 /* Macros generic to the SOA_SIMD_WIDTH parameter */
    249 #undef soaX
    250 #undef vXf
    251 #undef vXf_T
    252 #undef VEC
    253 #undef MASK
    254 #undef CHKVX
    255 
    256 /* Macros generic to the SOA_DIMENSION parameter */
    257 #undef soaXfY
    258 #undef SOA_VEC
    259 
    260 /* Constants */
    261 #undef VXTRUE
    262 #undef VXFALSE