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