numkong 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +495 -0
- package/binding.gyp +540 -0
- package/c/dispatch.h +512 -0
- package/c/dispatch_bf16.c +389 -0
- package/c/dispatch_bf16c.c +52 -0
- package/c/dispatch_e2m3.c +263 -0
- package/c/dispatch_e3m2.c +243 -0
- package/c/dispatch_e4m3.c +276 -0
- package/c/dispatch_e5m2.c +272 -0
- package/c/dispatch_f16.c +376 -0
- package/c/dispatch_f16c.c +58 -0
- package/c/dispatch_f32.c +378 -0
- package/c/dispatch_f32c.c +99 -0
- package/c/dispatch_f64.c +296 -0
- package/c/dispatch_f64c.c +98 -0
- package/c/dispatch_i16.c +96 -0
- package/c/dispatch_i32.c +89 -0
- package/c/dispatch_i4.c +150 -0
- package/c/dispatch_i64.c +86 -0
- package/c/dispatch_i8.c +289 -0
- package/c/dispatch_other.c +330 -0
- package/c/dispatch_u1.c +148 -0
- package/c/dispatch_u16.c +124 -0
- package/c/dispatch_u32.c +118 -0
- package/c/dispatch_u4.c +150 -0
- package/c/dispatch_u64.c +102 -0
- package/c/dispatch_u8.c +303 -0
- package/c/numkong.c +950 -0
- package/include/README.md +573 -0
- package/include/module.modulemap +129 -0
- package/include/numkong/attention/sapphireamx.h +1361 -0
- package/include/numkong/attention/sme.h +2066 -0
- package/include/numkong/attention.h +49 -0
- package/include/numkong/capabilities.h +748 -0
- package/include/numkong/cast/README.md +262 -0
- package/include/numkong/cast/haswell.h +975 -0
- package/include/numkong/cast/icelake.h +470 -0
- package/include/numkong/cast/neon.h +1192 -0
- package/include/numkong/cast/rvv.h +1021 -0
- package/include/numkong/cast/sapphire.h +262 -0
- package/include/numkong/cast/serial.h +2262 -0
- package/include/numkong/cast/skylake.h +856 -0
- package/include/numkong/cast/v128relaxed.h +180 -0
- package/include/numkong/cast.h +230 -0
- package/include/numkong/curved/README.md +223 -0
- package/include/numkong/curved/genoa.h +182 -0
- package/include/numkong/curved/haswell.h +276 -0
- package/include/numkong/curved/neon.h +205 -0
- package/include/numkong/curved/neonbfdot.h +212 -0
- package/include/numkong/curved/neonhalf.h +212 -0
- package/include/numkong/curved/rvv.h +305 -0
- package/include/numkong/curved/serial.h +207 -0
- package/include/numkong/curved/skylake.h +457 -0
- package/include/numkong/curved/smef64.h +506 -0
- package/include/numkong/curved.h +517 -0
- package/include/numkong/curved.hpp +144 -0
- package/include/numkong/dot/README.md +425 -0
- package/include/numkong/dot/alder.h +563 -0
- package/include/numkong/dot/genoa.h +315 -0
- package/include/numkong/dot/haswell.h +1688 -0
- package/include/numkong/dot/icelake.h +883 -0
- package/include/numkong/dot/neon.h +818 -0
- package/include/numkong/dot/neonbfdot.h +244 -0
- package/include/numkong/dot/neonfhm.h +360 -0
- package/include/numkong/dot/neonhalf.h +198 -0
- package/include/numkong/dot/neonsdot.h +508 -0
- package/include/numkong/dot/rvv.h +714 -0
- package/include/numkong/dot/rvvbb.h +72 -0
- package/include/numkong/dot/rvvbf16.h +123 -0
- package/include/numkong/dot/rvvhalf.h +129 -0
- package/include/numkong/dot/sapphire.h +141 -0
- package/include/numkong/dot/serial.h +838 -0
- package/include/numkong/dot/sierra.h +405 -0
- package/include/numkong/dot/skylake.h +1084 -0
- package/include/numkong/dot/sve.h +379 -0
- package/include/numkong/dot/svebfdot.h +74 -0
- package/include/numkong/dot/svehalf.h +123 -0
- package/include/numkong/dot/v128relaxed.h +1258 -0
- package/include/numkong/dot.h +1070 -0
- package/include/numkong/dot.hpp +94 -0
- package/include/numkong/dots/README.md +496 -0
- package/include/numkong/dots/alder.h +114 -0
- package/include/numkong/dots/genoa.h +94 -0
- package/include/numkong/dots/haswell.h +295 -0
- package/include/numkong/dots/icelake.h +171 -0
- package/include/numkong/dots/neon.h +120 -0
- package/include/numkong/dots/neonbfdot.h +58 -0
- package/include/numkong/dots/neonfhm.h +94 -0
- package/include/numkong/dots/neonhalf.h +57 -0
- package/include/numkong/dots/neonsdot.h +108 -0
- package/include/numkong/dots/rvv.h +2486 -0
- package/include/numkong/dots/sapphireamx.h +3973 -0
- package/include/numkong/dots/serial.h +2844 -0
- package/include/numkong/dots/sierra.h +97 -0
- package/include/numkong/dots/skylake.h +196 -0
- package/include/numkong/dots/sme.h +5372 -0
- package/include/numkong/dots/smebi32.h +461 -0
- package/include/numkong/dots/smef64.h +1318 -0
- package/include/numkong/dots/smehalf.h +47 -0
- package/include/numkong/dots/v128relaxed.h +294 -0
- package/include/numkong/dots.h +2804 -0
- package/include/numkong/dots.hpp +639 -0
- package/include/numkong/each/README.md +469 -0
- package/include/numkong/each/haswell.h +1658 -0
- package/include/numkong/each/icelake.h +272 -0
- package/include/numkong/each/neon.h +1104 -0
- package/include/numkong/each/neonbfdot.h +212 -0
- package/include/numkong/each/neonhalf.h +410 -0
- package/include/numkong/each/rvv.h +1121 -0
- package/include/numkong/each/sapphire.h +477 -0
- package/include/numkong/each/serial.h +260 -0
- package/include/numkong/each/skylake.h +1562 -0
- package/include/numkong/each.h +2146 -0
- package/include/numkong/each.hpp +434 -0
- package/include/numkong/geospatial/README.md +147 -0
- package/include/numkong/geospatial/haswell.h +593 -0
- package/include/numkong/geospatial/neon.h +571 -0
- package/include/numkong/geospatial/rvv.h +701 -0
- package/include/numkong/geospatial/serial.h +309 -0
- package/include/numkong/geospatial/skylake.h +577 -0
- package/include/numkong/geospatial/v128relaxed.h +613 -0
- package/include/numkong/geospatial.h +453 -0
- package/include/numkong/geospatial.hpp +235 -0
- package/include/numkong/matrix.hpp +336 -0
- package/include/numkong/maxsim/README.md +187 -0
- package/include/numkong/maxsim/alder.h +511 -0
- package/include/numkong/maxsim/genoa.h +115 -0
- package/include/numkong/maxsim/haswell.h +553 -0
- package/include/numkong/maxsim/icelake.h +480 -0
- package/include/numkong/maxsim/neonsdot.h +394 -0
- package/include/numkong/maxsim/sapphireamx.h +877 -0
- package/include/numkong/maxsim/serial.h +490 -0
- package/include/numkong/maxsim/sme.h +929 -0
- package/include/numkong/maxsim/v128relaxed.h +280 -0
- package/include/numkong/maxsim.h +571 -0
- package/include/numkong/maxsim.hpp +133 -0
- package/include/numkong/mesh/README.md +227 -0
- package/include/numkong/mesh/haswell.h +2235 -0
- package/include/numkong/mesh/neon.h +1329 -0
- package/include/numkong/mesh/neonbfdot.h +842 -0
- package/include/numkong/mesh/neonhalf.h +616 -0
- package/include/numkong/mesh/rvv.h +916 -0
- package/include/numkong/mesh/serial.h +742 -0
- package/include/numkong/mesh/skylake.h +1135 -0
- package/include/numkong/mesh/v128relaxed.h +1052 -0
- package/include/numkong/mesh.h +652 -0
- package/include/numkong/mesh.hpp +762 -0
- package/include/numkong/numkong.h +78 -0
- package/include/numkong/numkong.hpp +57 -0
- package/include/numkong/probability/README.md +173 -0
- package/include/numkong/probability/haswell.h +267 -0
- package/include/numkong/probability/neon.h +225 -0
- package/include/numkong/probability/rvv.h +409 -0
- package/include/numkong/probability/serial.h +169 -0
- package/include/numkong/probability/skylake.h +324 -0
- package/include/numkong/probability.h +383 -0
- package/include/numkong/probability.hpp +120 -0
- package/include/numkong/random.h +50 -0
- package/include/numkong/random.hpp +285 -0
- package/include/numkong/reduce/README.md +547 -0
- package/include/numkong/reduce/alder.h +632 -0
- package/include/numkong/reduce/genoa.h +201 -0
- package/include/numkong/reduce/haswell.h +3783 -0
- package/include/numkong/reduce/icelake.h +549 -0
- package/include/numkong/reduce/neon.h +3841 -0
- package/include/numkong/reduce/neonbfdot.h +353 -0
- package/include/numkong/reduce/neonfhm.h +665 -0
- package/include/numkong/reduce/neonhalf.h +157 -0
- package/include/numkong/reduce/neonsdot.h +357 -0
- package/include/numkong/reduce/rvv.h +3407 -0
- package/include/numkong/reduce/serial.h +757 -0
- package/include/numkong/reduce/sierra.h +338 -0
- package/include/numkong/reduce/skylake.h +3792 -0
- package/include/numkong/reduce/v128relaxed.h +2302 -0
- package/include/numkong/reduce.h +1597 -0
- package/include/numkong/reduce.hpp +633 -0
- package/include/numkong/scalar/README.md +89 -0
- package/include/numkong/scalar/haswell.h +113 -0
- package/include/numkong/scalar/neon.h +122 -0
- package/include/numkong/scalar/neonhalf.h +70 -0
- package/include/numkong/scalar/rvv.h +211 -0
- package/include/numkong/scalar/sapphire.h +63 -0
- package/include/numkong/scalar/serial.h +332 -0
- package/include/numkong/scalar/v128relaxed.h +56 -0
- package/include/numkong/scalar.h +683 -0
- package/include/numkong/set/README.md +179 -0
- package/include/numkong/set/haswell.h +334 -0
- package/include/numkong/set/icelake.h +485 -0
- package/include/numkong/set/neon.h +364 -0
- package/include/numkong/set/rvv.h +226 -0
- package/include/numkong/set/rvvbb.h +117 -0
- package/include/numkong/set/serial.h +174 -0
- package/include/numkong/set/sve.h +185 -0
- package/include/numkong/set/v128relaxed.h +240 -0
- package/include/numkong/set.h +457 -0
- package/include/numkong/set.hpp +114 -0
- package/include/numkong/sets/README.md +149 -0
- package/include/numkong/sets/haswell.h +63 -0
- package/include/numkong/sets/icelake.h +66 -0
- package/include/numkong/sets/neon.h +61 -0
- package/include/numkong/sets/serial.h +43 -0
- package/include/numkong/sets/smebi32.h +1099 -0
- package/include/numkong/sets/v128relaxed.h +58 -0
- package/include/numkong/sets.h +339 -0
- package/include/numkong/sparse/README.md +156 -0
- package/include/numkong/sparse/icelake.h +463 -0
- package/include/numkong/sparse/neon.h +288 -0
- package/include/numkong/sparse/serial.h +117 -0
- package/include/numkong/sparse/sve2.h +507 -0
- package/include/numkong/sparse/turin.h +322 -0
- package/include/numkong/sparse.h +363 -0
- package/include/numkong/sparse.hpp +113 -0
- package/include/numkong/spatial/README.md +435 -0
- package/include/numkong/spatial/alder.h +607 -0
- package/include/numkong/spatial/genoa.h +290 -0
- package/include/numkong/spatial/haswell.h +960 -0
- package/include/numkong/spatial/icelake.h +586 -0
- package/include/numkong/spatial/neon.h +773 -0
- package/include/numkong/spatial/neonbfdot.h +165 -0
- package/include/numkong/spatial/neonhalf.h +118 -0
- package/include/numkong/spatial/neonsdot.h +261 -0
- package/include/numkong/spatial/rvv.h +984 -0
- package/include/numkong/spatial/rvvbf16.h +123 -0
- package/include/numkong/spatial/rvvhalf.h +117 -0
- package/include/numkong/spatial/sapphire.h +343 -0
- package/include/numkong/spatial/serial.h +346 -0
- package/include/numkong/spatial/sierra.h +323 -0
- package/include/numkong/spatial/skylake.h +606 -0
- package/include/numkong/spatial/sve.h +224 -0
- package/include/numkong/spatial/svebfdot.h +122 -0
- package/include/numkong/spatial/svehalf.h +109 -0
- package/include/numkong/spatial/v128relaxed.h +717 -0
- package/include/numkong/spatial.h +1425 -0
- package/include/numkong/spatial.hpp +183 -0
- package/include/numkong/spatials/README.md +580 -0
- package/include/numkong/spatials/alder.h +94 -0
- package/include/numkong/spatials/genoa.h +94 -0
- package/include/numkong/spatials/haswell.h +219 -0
- package/include/numkong/spatials/icelake.h +113 -0
- package/include/numkong/spatials/neon.h +109 -0
- package/include/numkong/spatials/neonbfdot.h +60 -0
- package/include/numkong/spatials/neonfhm.h +92 -0
- package/include/numkong/spatials/neonhalf.h +58 -0
- package/include/numkong/spatials/neonsdot.h +109 -0
- package/include/numkong/spatials/rvv.h +1960 -0
- package/include/numkong/spatials/sapphireamx.h +1149 -0
- package/include/numkong/spatials/serial.h +226 -0
- package/include/numkong/spatials/sierra.h +96 -0
- package/include/numkong/spatials/skylake.h +184 -0
- package/include/numkong/spatials/sme.h +1901 -0
- package/include/numkong/spatials/smef64.h +465 -0
- package/include/numkong/spatials/v128relaxed.h +240 -0
- package/include/numkong/spatials.h +3021 -0
- package/include/numkong/spatials.hpp +508 -0
- package/include/numkong/tensor.hpp +1592 -0
- package/include/numkong/trigonometry/README.md +184 -0
- package/include/numkong/trigonometry/haswell.h +652 -0
- package/include/numkong/trigonometry/neon.h +639 -0
- package/include/numkong/trigonometry/rvv.h +699 -0
- package/include/numkong/trigonometry/serial.h +703 -0
- package/include/numkong/trigonometry/skylake.h +721 -0
- package/include/numkong/trigonometry/v128relaxed.h +666 -0
- package/include/numkong/trigonometry.h +467 -0
- package/include/numkong/trigonometry.hpp +166 -0
- package/include/numkong/types.h +1384 -0
- package/include/numkong/types.hpp +5603 -0
- package/include/numkong/vector.hpp +698 -0
- package/javascript/README.md +246 -0
- package/javascript/dist/cjs/numkong-wasm.d.ts +166 -0
- package/javascript/dist/cjs/numkong-wasm.js +617 -0
- package/javascript/dist/cjs/numkong.d.ts +343 -0
- package/javascript/dist/cjs/numkong.js +523 -0
- package/javascript/dist/cjs/package.json +3 -0
- package/javascript/dist/cjs/types.d.ts +284 -0
- package/javascript/dist/cjs/types.js +653 -0
- package/javascript/dist/esm/numkong-wasm.d.ts +166 -0
- package/javascript/dist/esm/numkong-wasm.js +595 -0
- package/javascript/dist/esm/numkong.d.ts +343 -0
- package/javascript/dist/esm/numkong.js +452 -0
- package/javascript/dist/esm/package.json +3 -0
- package/javascript/dist/esm/types.d.ts +284 -0
- package/javascript/dist/esm/types.js +630 -0
- package/javascript/dist-package-cjs.json +3 -0
- package/javascript/dist-package-esm.json +3 -0
- package/javascript/node-gyp-build.d.ts +1 -0
- package/javascript/numkong-wasm.ts +756 -0
- package/javascript/numkong.c +689 -0
- package/javascript/numkong.ts +575 -0
- package/javascript/tsconfig-base.json +39 -0
- package/javascript/tsconfig-cjs.json +8 -0
- package/javascript/tsconfig-esm.json +8 -0
- package/javascript/types.ts +674 -0
- package/package.json +87 -0
|
@@ -0,0 +1,666 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Trigonometric Functions for WASM.
|
|
3
|
+
* @file include/numkong/trigonometry/v128relaxed.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date February 6, 2026
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/trigonometry.h
|
|
8
|
+
* @see https://sleef.org
|
|
9
|
+
*
|
|
10
|
+
* Implements sin, cos, atan, atan2 for f32x4 and f64x2 using minimax polynomial approximations.
|
|
11
|
+
* F32 sin/cos use 3-term polynomials with Cody-Waite range reduction; f64 uses 8-term Estrin.
|
|
12
|
+
* F32 atan uses an 8-term Horner scheme; f64 atan uses 19 terms. Atan2 adds quadrant correction.
|
|
13
|
+
*
|
|
14
|
+
* Polynomial chains rely on relaxed FMA (`relaxed_madd`/`relaxed_nmadd`) for throughput.
|
|
15
|
+
* Range reduction uses `nearest` rounding (avoiding int-float roundtrips); `trunc_sat` only
|
|
16
|
+
* for integer parity checks. F32 atan uses division for reciprocal (no approximate reciprocal
|
|
17
|
+
* available in WASM). All type punning is free since `v128_t` is untyped.
|
|
18
|
+
*
|
|
19
|
+
* @section wasm_trig_instructions Key WASM SIMD Instructions
|
|
20
|
+
*
|
|
21
|
+
* Intrinsic Operation
|
|
22
|
+
* wasm_f32x4_relaxed_madd(a, b, c) a*b + c (relaxed FMA)
|
|
23
|
+
* wasm_f32x4_relaxed_nmadd(a, b, c) -(a*b) + c (relaxed FNMA)
|
|
24
|
+
* wasm_f64x2_relaxed_madd(a, b, c) a*b + c (relaxed FMA)
|
|
25
|
+
* wasm_f64x2_relaxed_nmadd(a, b, c) -(a*b) + c (relaxed FNMA)
|
|
26
|
+
* wasm_f32x4_nearest(a) Round to nearest integer
|
|
27
|
+
* wasm_f64x2_nearest(a) Round to nearest integer
|
|
28
|
+
* wasm_v128_bitselect(true, false, mask) Bitwise select
|
|
29
|
+
* wasm_i32x4_relaxed_laneselect(a, b, m) Lane select (1 instr vs 3 on x86)
|
|
30
|
+
* wasm_i64x2_relaxed_laneselect(a, b, m) Lane select for f64 masks
|
|
31
|
+
* wasm_i32x4_relaxed_trunc_f32x4(a) Truncate without sat fixup (1 vs 7 on x86)
|
|
32
|
+
* wasm_i32x4_relaxed_trunc_f64x2_zero(a) Truncate f64→i32 without sat fixup (1 vs 7 on x86)
|
|
33
|
+
*/
|
|
34
|
+
#ifndef NK_TRIGONOMETRY_V128RELAXED_H
|
|
35
|
+
#define NK_TRIGONOMETRY_V128RELAXED_H
|
|
36
|
+
|
|
37
|
+
#if NK_TARGET_V128RELAXED
|
|
38
|
+
|
|
39
|
+
#include "numkong/types.h"
|
|
40
|
+
|
|
41
|
+
#if defined(__cplusplus)
|
|
42
|
+
extern "C" {
|
|
43
|
+
#endif
|
|
44
|
+
|
|
45
|
+
#if defined(__clang__)
|
|
46
|
+
#pragma clang attribute push(__attribute__((target("relaxed-simd"))), apply_to = function)
|
|
47
|
+
#endif
|
|
48
|
+
|
|
49
|
+
/* WASM Relaxed SIMD trigonometry kernels (4-way f32, 2-way f64)
|
|
50
|
+
* These implement polynomial approximations using 128-bit WASM SIMD vectors.
|
|
51
|
+
*/
|
|
52
|
+
|
|
53
|
+
NK_INTERNAL v128_t nk_f32x4_sin_v128relaxed_(v128_t const angles_radians) {
|
|
54
|
+
// Constants for argument reduction
|
|
55
|
+
v128_t const pi = wasm_f32x4_splat(3.14159265358979323846f);
|
|
56
|
+
v128_t const pi_reciprocal = wasm_f32x4_splat(0.31830988618379067154f);
|
|
57
|
+
v128_t const coeff_5 = wasm_f32x4_splat(-0.0001881748176f);
|
|
58
|
+
v128_t const coeff_3 = wasm_f32x4_splat(+0.008323502727f);
|
|
59
|
+
v128_t const coeff_1 = wasm_f32x4_splat(-0.1666651368f);
|
|
60
|
+
|
|
61
|
+
// Compute (multiples_of_pi) = round(angle / pi) using nearest rounding
|
|
62
|
+
v128_t quotients = wasm_f32x4_mul(angles_radians, pi_reciprocal);
|
|
63
|
+
v128_t rounded_quotients = wasm_f32x4_nearest(quotients);
|
|
64
|
+
// relaxed_trunc: 1 instruction (cvttps2dq) vs 7 (with NaN/overflow fixup) on x86.
|
|
65
|
+
// Safe because rounded_quotients are small integers from nearest(), never NaN or out of i32 range.
|
|
66
|
+
v128_t multiples_of_pi = wasm_i32x4_relaxed_trunc_f32x4(rounded_quotients);
|
|
67
|
+
|
|
68
|
+
// Reduce the angle: angle - rounded_quotients * pi
|
|
69
|
+
// vfmsq_f32(acc, a, b) = acc - a*b -> wasm_f32x4_relaxed_nmadd(a, b, acc)
|
|
70
|
+
v128_t const angles = wasm_f32x4_relaxed_nmadd(rounded_quotients, pi, angles_radians);
|
|
71
|
+
v128_t const angles_squared = wasm_f32x4_mul(angles, angles);
|
|
72
|
+
v128_t const angles_cubed = wasm_f32x4_mul(angles, angles_squared);
|
|
73
|
+
|
|
74
|
+
// Compute the polynomial approximation
|
|
75
|
+
// vfmaq_f32(acc, a, b) = acc + a*b -> wasm_f32x4_relaxed_madd(a, b, acc)
|
|
76
|
+
v128_t polynomials = coeff_5;
|
|
77
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, angles_squared, coeff_3);
|
|
78
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, angles_squared, coeff_1);
|
|
79
|
+
v128_t results = wasm_f32x4_relaxed_madd(angles_cubed, polynomials, angles);
|
|
80
|
+
|
|
81
|
+
// If multiples_of_pi is odd, flip the sign
|
|
82
|
+
v128_t parity = wasm_v128_and(multiples_of_pi, wasm_i32x4_splat(1));
|
|
83
|
+
v128_t odd_mask = wasm_i32x4_eq(parity, wasm_i32x4_splat(1));
|
|
84
|
+
v128_t negated = wasm_f32x4_neg(results);
|
|
85
|
+
// relaxed_laneselect: 1 instruction (vblendvps) vs 3 (vpand+vpandn+vpor) on x86.
|
|
86
|
+
// Safe because mask is from comparison (all-ones or all-zeros per lane).
|
|
87
|
+
results = wasm_i32x4_relaxed_laneselect(negated, results, odd_mask);
|
|
88
|
+
return results;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
NK_INTERNAL v128_t nk_f32x4_cos_v128relaxed_(v128_t const angles_radians) {
|
|
92
|
+
// Constants for argument reduction
|
|
93
|
+
v128_t const pi = wasm_f32x4_splat(3.14159265358979323846f);
|
|
94
|
+
v128_t const pi_half = wasm_f32x4_splat(1.57079632679489661923f);
|
|
95
|
+
v128_t const pi_reciprocal = wasm_f32x4_splat(0.31830988618379067154f);
|
|
96
|
+
v128_t const coeff_5 = wasm_f32x4_splat(-0.0001881748176f);
|
|
97
|
+
v128_t const coeff_3 = wasm_f32x4_splat(+0.008323502727f);
|
|
98
|
+
v128_t const coeff_1 = wasm_f32x4_splat(-0.1666651368f);
|
|
99
|
+
|
|
100
|
+
// Compute round((angle / pi) - 0.5)
|
|
101
|
+
v128_t const neg_half = wasm_f32x4_splat(-0.5f);
|
|
102
|
+
v128_t quotients = wasm_f32x4_relaxed_madd(angles_radians, pi_reciprocal, neg_half);
|
|
103
|
+
v128_t rounded_quotients = wasm_f32x4_nearest(quotients);
|
|
104
|
+
// relaxed_trunc: 1 instruction (cvttps2dq) vs 7 (with NaN/overflow fixup) on x86.
|
|
105
|
+
// Safe because rounded_quotients are small integers from nearest(), never NaN or out of i32 range.
|
|
106
|
+
v128_t multiples_of_pi = wasm_i32x4_relaxed_trunc_f32x4(rounded_quotients);
|
|
107
|
+
|
|
108
|
+
// Reduce the angle: (angle - pi/2) - rounded_quotients * pi
|
|
109
|
+
v128_t shifted = wasm_f32x4_sub(angles_radians, pi_half);
|
|
110
|
+
v128_t const angles = wasm_f32x4_relaxed_nmadd(rounded_quotients, pi, shifted);
|
|
111
|
+
v128_t const angles_squared = wasm_f32x4_mul(angles, angles);
|
|
112
|
+
v128_t const angles_cubed = wasm_f32x4_mul(angles, angles_squared);
|
|
113
|
+
|
|
114
|
+
// Compute the polynomial approximation
|
|
115
|
+
v128_t polynomials = coeff_5;
|
|
116
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, angles_squared, coeff_3);
|
|
117
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, angles_squared, coeff_1);
|
|
118
|
+
v128_t results = wasm_f32x4_relaxed_madd(angles_cubed, polynomials, angles);
|
|
119
|
+
|
|
120
|
+
// If multiples_of_pi is even, flip the sign
|
|
121
|
+
v128_t parity = wasm_v128_and(multiples_of_pi, wasm_i32x4_splat(1));
|
|
122
|
+
v128_t even_mask = wasm_i32x4_eq(parity, wasm_i32x4_splat(0));
|
|
123
|
+
v128_t negated = wasm_f32x4_neg(results);
|
|
124
|
+
// relaxed_laneselect: 1 instruction (vblendvps) vs 3 (vpand+vpandn+vpor) on x86.
|
|
125
|
+
// Safe because mask is from comparison (all-ones or all-zeros per lane).
|
|
126
|
+
results = wasm_i32x4_relaxed_laneselect(negated, results, even_mask);
|
|
127
|
+
return results;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
NK_INTERNAL v128_t nk_f32x4_atan_v128relaxed_(v128_t const inputs) {
|
|
131
|
+
// Polynomial coefficients for atan approximation (8 terms)
|
|
132
|
+
v128_t const coeff_8 = wasm_f32x4_splat(-0.333331018686294555664062f);
|
|
133
|
+
v128_t const coeff_7 = wasm_f32x4_splat(+0.199926957488059997558594f);
|
|
134
|
+
v128_t const coeff_6 = wasm_f32x4_splat(-0.142027363181114196777344f);
|
|
135
|
+
v128_t const coeff_5 = wasm_f32x4_splat(+0.106347933411598205566406f);
|
|
136
|
+
v128_t const coeff_4 = wasm_f32x4_splat(-0.0748900920152664184570312f);
|
|
137
|
+
v128_t const coeff_3 = wasm_f32x4_splat(+0.0425049886107444763183594f);
|
|
138
|
+
v128_t const coeff_2 = wasm_f32x4_splat(-0.0159569028764963150024414f);
|
|
139
|
+
v128_t const coeff_1 = wasm_f32x4_splat(+0.00282363896258175373077393f);
|
|
140
|
+
v128_t const half_pi = wasm_f32x4_splat(1.5707963267948966f);
|
|
141
|
+
|
|
142
|
+
// Detect negative values and take absolute value
|
|
143
|
+
v128_t const zeros = wasm_f32x4_splat(0);
|
|
144
|
+
v128_t negative_mask = wasm_f32x4_lt(inputs, zeros);
|
|
145
|
+
v128_t values = wasm_f32x4_abs(inputs);
|
|
146
|
+
|
|
147
|
+
// Check if values > 1 (need reciprocal)
|
|
148
|
+
v128_t reciprocal_mask = wasm_f32x4_gt(values, wasm_f32x4_splat(1.0f));
|
|
149
|
+
|
|
150
|
+
// No fast reciprocal in WASM — use division
|
|
151
|
+
v128_t recip = wasm_f32x4_div(wasm_f32x4_splat(1.0f), values);
|
|
152
|
+
// relaxed_laneselect: 1 instruction (vblendvps) vs 3 (vpand+vpandn+vpor) on x86.
|
|
153
|
+
// Safe because mask is from comparison (all-ones or all-zeros per lane).
|
|
154
|
+
values = wasm_i32x4_relaxed_laneselect(recip, values, reciprocal_mask);
|
|
155
|
+
|
|
156
|
+
// Compute powers
|
|
157
|
+
v128_t const values_squared = wasm_f32x4_mul(values, values);
|
|
158
|
+
v128_t const values_cubed = wasm_f32x4_mul(values, values_squared);
|
|
159
|
+
|
|
160
|
+
// Polynomial evaluation using Horner's method
|
|
161
|
+
v128_t polynomials = coeff_1;
|
|
162
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, values_squared, coeff_2);
|
|
163
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, values_squared, coeff_3);
|
|
164
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, values_squared, coeff_4);
|
|
165
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, values_squared, coeff_5);
|
|
166
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, values_squared, coeff_6);
|
|
167
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, values_squared, coeff_7);
|
|
168
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, values_squared, coeff_8);
|
|
169
|
+
|
|
170
|
+
// Compute result: atan(x) ~ x + x^3 * P(x^2)
|
|
171
|
+
v128_t result = wasm_f32x4_relaxed_madd(values_cubed, polynomials, values);
|
|
172
|
+
|
|
173
|
+
// Adjust for reciprocal: result = pi/2 - result
|
|
174
|
+
v128_t adjusted = wasm_f32x4_sub(half_pi, result);
|
|
175
|
+
// relaxed_laneselect: 1 instruction (vblendvps) vs 3 (vpand+vpandn+vpor) on x86.
|
|
176
|
+
// Safe because mask is from comparison (all-ones or all-zeros per lane).
|
|
177
|
+
result = wasm_i32x4_relaxed_laneselect(adjusted, result, reciprocal_mask);
|
|
178
|
+
|
|
179
|
+
// Adjust for negative: result = -result
|
|
180
|
+
v128_t negated = wasm_f32x4_neg(result);
|
|
181
|
+
// relaxed_laneselect: 1 instruction (vblendvps) vs 3 (vpand+vpandn+vpor) on x86.
|
|
182
|
+
// Safe because mask is from comparison (all-ones or all-zeros per lane).
|
|
183
|
+
result = wasm_i32x4_relaxed_laneselect(negated, result, negative_mask);
|
|
184
|
+
return result;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
NK_INTERNAL v128_t nk_f32x4_atan2_v128relaxed_(v128_t const ys_inputs, v128_t const xs_inputs) {
|
|
188
|
+
// Polynomial coefficients (same as atan)
|
|
189
|
+
v128_t const coeff_8 = wasm_f32x4_splat(-0.333331018686294555664062f);
|
|
190
|
+
v128_t const coeff_7 = wasm_f32x4_splat(+0.199926957488059997558594f);
|
|
191
|
+
v128_t const coeff_6 = wasm_f32x4_splat(-0.142027363181114196777344f);
|
|
192
|
+
v128_t const coeff_5 = wasm_f32x4_splat(+0.106347933411598205566406f);
|
|
193
|
+
v128_t const coeff_4 = wasm_f32x4_splat(-0.0748900920152664184570312f);
|
|
194
|
+
v128_t const coeff_3 = wasm_f32x4_splat(+0.0425049886107444763183594f);
|
|
195
|
+
v128_t const coeff_2 = wasm_f32x4_splat(-0.0159569028764963150024414f);
|
|
196
|
+
v128_t const coeff_1 = wasm_f32x4_splat(+0.00282363896258175373077393f);
|
|
197
|
+
v128_t const pi = wasm_f32x4_splat(3.14159265358979323846f);
|
|
198
|
+
v128_t const half_pi = wasm_f32x4_splat(1.5707963267948966f);
|
|
199
|
+
v128_t const zeros = wasm_f32x4_splat(0);
|
|
200
|
+
|
|
201
|
+
// Quadrant adjustments - take absolute values
|
|
202
|
+
v128_t xs_negative_mask = wasm_f32x4_lt(xs_inputs, zeros);
|
|
203
|
+
v128_t xs = wasm_f32x4_abs(xs_inputs);
|
|
204
|
+
v128_t ys = wasm_f32x4_abs(ys_inputs);
|
|
205
|
+
|
|
206
|
+
// Ensure proper fraction where numerator < denominator
|
|
207
|
+
v128_t swap_mask = wasm_f32x4_gt(ys, xs);
|
|
208
|
+
v128_t temps = xs;
|
|
209
|
+
// relaxed_laneselect: 1 instruction (vblendvps) vs 3 (vpand+vpandn+vpor) on x86.
|
|
210
|
+
// Safe because mask is from comparison (all-ones or all-zeros per lane).
|
|
211
|
+
xs = wasm_i32x4_relaxed_laneselect(ys, xs, swap_mask);
|
|
212
|
+
ys = wasm_i32x4_relaxed_laneselect(wasm_f32x4_neg(temps), ys, swap_mask);
|
|
213
|
+
|
|
214
|
+
// Division for ratio: ratio = ys / xs
|
|
215
|
+
v128_t const ratio = wasm_f32x4_div(ys, xs);
|
|
216
|
+
v128_t const ratio_squared = wasm_f32x4_mul(ratio, ratio);
|
|
217
|
+
v128_t const ratio_cubed = wasm_f32x4_mul(ratio, ratio_squared);
|
|
218
|
+
|
|
219
|
+
// Polynomial evaluation using Horner's method
|
|
220
|
+
v128_t polynomials = coeff_1;
|
|
221
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, ratio_squared, coeff_2);
|
|
222
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, ratio_squared, coeff_3);
|
|
223
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, ratio_squared, coeff_4);
|
|
224
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, ratio_squared, coeff_5);
|
|
225
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, ratio_squared, coeff_6);
|
|
226
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, ratio_squared, coeff_7);
|
|
227
|
+
polynomials = wasm_f32x4_relaxed_madd(polynomials, ratio_squared, coeff_8);
|
|
228
|
+
|
|
229
|
+
// Compute the result
|
|
230
|
+
v128_t results = wasm_f32x4_relaxed_madd(ratio_cubed, polynomials, ratio);
|
|
231
|
+
|
|
232
|
+
// Compute quadrant value: 0 for x>=0 && !swap, 1 for x>=0 && swap,
|
|
233
|
+
// -2 for x<0 && !swap, -1 for x<0 && swap
|
|
234
|
+
v128_t quadrant = wasm_f32x4_splat(0.0f);
|
|
235
|
+
v128_t neg_two = wasm_f32x4_splat(-2.0f);
|
|
236
|
+
// relaxed_laneselect: 1 instruction (vblendvps) vs 3 (vpand+vpandn+vpor) on x86.
|
|
237
|
+
// Safe because mask is from comparison (all-ones or all-zeros per lane).
|
|
238
|
+
quadrant = wasm_i32x4_relaxed_laneselect(neg_two, quadrant, xs_negative_mask);
|
|
239
|
+
v128_t quadrant_incremented = wasm_f32x4_add(quadrant, wasm_f32x4_splat(1.0f));
|
|
240
|
+
quadrant = wasm_i32x4_relaxed_laneselect(quadrant_incremented, quadrant, swap_mask);
|
|
241
|
+
|
|
242
|
+
// Adjust for quadrant: result += quadrant * pi/2
|
|
243
|
+
results = wasm_f32x4_relaxed_madd(quadrant, half_pi, results);
|
|
244
|
+
|
|
245
|
+
// Transfer sign from x and y by XOR with sign bits
|
|
246
|
+
v128_t sign_mask = wasm_f32x4_splat(-0.0f);
|
|
247
|
+
v128_t xs_sign = wasm_v128_and(xs_inputs, sign_mask);
|
|
248
|
+
v128_t ys_sign = wasm_v128_and(ys_inputs, sign_mask);
|
|
249
|
+
results = wasm_v128_xor(results, xs_sign);
|
|
250
|
+
results = wasm_v128_xor(results, ys_sign);
|
|
251
|
+
|
|
252
|
+
return results;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
NK_INTERNAL v128_t nk_f64x2_sin_v128relaxed_(v128_t const angles_radians) {
|
|
256
|
+
// Constants for argument reduction
|
|
257
|
+
v128_t const pi_high = wasm_f64x2_splat(3.141592653589793116);
|
|
258
|
+
v128_t const pi_low = wasm_f64x2_splat(1.2246467991473532072e-16);
|
|
259
|
+
v128_t const pi_reciprocal = wasm_f64x2_splat(0.31830988618379067154);
|
|
260
|
+
|
|
261
|
+
// Polynomial coefficients for sine approximation
|
|
262
|
+
v128_t const coeff_0 = wasm_f64x2_splat(+0.00833333333333332974823815);
|
|
263
|
+
v128_t const coeff_1 = wasm_f64x2_splat(-0.000198412698412696162806809);
|
|
264
|
+
v128_t const coeff_2 = wasm_f64x2_splat(+2.75573192239198747630416e-06);
|
|
265
|
+
v128_t const coeff_3 = wasm_f64x2_splat(-2.50521083763502045810755e-08);
|
|
266
|
+
v128_t const coeff_4 = wasm_f64x2_splat(+1.60590430605664501629054e-10);
|
|
267
|
+
v128_t const coeff_5 = wasm_f64x2_splat(-7.64712219118158833288484e-13);
|
|
268
|
+
v128_t const coeff_6 = wasm_f64x2_splat(+2.81009972710863200091251e-15);
|
|
269
|
+
v128_t const coeff_7 = wasm_f64x2_splat(-7.97255955009037868891952e-18);
|
|
270
|
+
v128_t const coeff_8 = wasm_f64x2_splat(-0.166666666666666657414808);
|
|
271
|
+
|
|
272
|
+
// Compute round(angle / pi)
|
|
273
|
+
v128_t const quotients = wasm_f64x2_mul(angles_radians, pi_reciprocal);
|
|
274
|
+
v128_t rounded_quotients = wasm_f64x2_nearest(quotients);
|
|
275
|
+
// relaxed_trunc: 1 instruction (cvttpd2dq) vs 7 (with NaN/overflow fixup) on x86.
|
|
276
|
+
// Safe because rounded_quotients are small integers from nearest(), never NaN or out of i32 range.
|
|
277
|
+
v128_t multiples_i32 = wasm_i32x4_relaxed_trunc_f64x2_zero(rounded_quotients);
|
|
278
|
+
|
|
279
|
+
// Two-step Cody-Waite reduction: angle - rounded * pi_high - rounded * pi_low
|
|
280
|
+
v128_t angles = angles_radians;
|
|
281
|
+
angles = wasm_f64x2_relaxed_nmadd(rounded_quotients, pi_high, angles);
|
|
282
|
+
angles = wasm_f64x2_relaxed_nmadd(rounded_quotients, pi_low, angles);
|
|
283
|
+
|
|
284
|
+
// Check parity in i32, then widen to i64 mask for laneselect
|
|
285
|
+
v128_t parity_i32 = wasm_v128_and(multiples_i32, wasm_i32x4_splat(1));
|
|
286
|
+
v128_t odd_i32 = wasm_i32x4_eq(parity_i32, wasm_i32x4_splat(1));
|
|
287
|
+
// Widen: lane0 of i32 -> lanes 0-1 of i64, lane1 -> lanes 2-3
|
|
288
|
+
// Shuffle i32 lanes [0,0,1,1] to broadcast each i32 parity into both halves of each i64
|
|
289
|
+
v128_t odd_mask = wasm_i32x4_shuffle(odd_i32, odd_i32, 0, 0, 1, 1);
|
|
290
|
+
v128_t negated_angles = wasm_f64x2_neg(angles);
|
|
291
|
+
// relaxed_laneselect: 1 instruction (vblendvpd) vs 3 (vpand+vpandn+vpor) on x86.
|
|
292
|
+
// Safe because mask is lane-granular at i64 width (all-ones or all-zeros per 64-bit lane).
|
|
293
|
+
angles = wasm_i64x2_relaxed_laneselect(negated_angles, angles, odd_mask);
|
|
294
|
+
|
|
295
|
+
v128_t const angles_squared = wasm_f64x2_mul(angles, angles);
|
|
296
|
+
v128_t const angles_cubed = wasm_f64x2_mul(angles, angles_squared);
|
|
297
|
+
v128_t const angles_quadratic = wasm_f64x2_mul(angles_squared, angles_squared);
|
|
298
|
+
v128_t const angles_octic = wasm_f64x2_mul(angles_quadratic, angles_quadratic);
|
|
299
|
+
|
|
300
|
+
// Compute polynomial terms using Estrin's scheme for better ILP
|
|
301
|
+
v128_t const poly_67 = wasm_f64x2_relaxed_madd(angles_squared, coeff_7, coeff_6);
|
|
302
|
+
v128_t const poly_45 = wasm_f64x2_relaxed_madd(angles_squared, coeff_5, coeff_4);
|
|
303
|
+
v128_t const poly_4567 = wasm_f64x2_relaxed_madd(angles_quadratic, poly_67, poly_45);
|
|
304
|
+
|
|
305
|
+
v128_t const poly_23 = wasm_f64x2_relaxed_madd(angles_squared, coeff_3, coeff_2);
|
|
306
|
+
v128_t const poly_01 = wasm_f64x2_relaxed_madd(angles_squared, coeff_1, coeff_0);
|
|
307
|
+
v128_t const poly_0123 = wasm_f64x2_relaxed_madd(angles_quadratic, poly_23, poly_01);
|
|
308
|
+
|
|
309
|
+
// Combine polynomial terms
|
|
310
|
+
v128_t results = wasm_f64x2_relaxed_madd(angles_octic, poly_4567, poly_0123);
|
|
311
|
+
results = wasm_f64x2_relaxed_madd(results, angles_squared, coeff_8);
|
|
312
|
+
results = wasm_f64x2_relaxed_madd(results, angles_cubed, angles);
|
|
313
|
+
|
|
314
|
+
// Handle zero input (preserve sign of zero)
|
|
315
|
+
v128_t const non_zero_mask = wasm_f64x2_eq(angles_radians, wasm_f64x2_splat(0));
|
|
316
|
+
// relaxed_laneselect: 1 instruction (vblendvpd) vs 3 (vpand+vpandn+vpor) on x86.
|
|
317
|
+
// Safe because mask is from comparison (all-ones or all-zeros per lane).
|
|
318
|
+
results = wasm_i64x2_relaxed_laneselect(angles_radians, results, non_zero_mask);
|
|
319
|
+
return results;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
NK_INTERNAL v128_t nk_f64x2_cos_v128relaxed_(v128_t const angles_radians) {
|
|
323
|
+
// Constants for argument reduction
|
|
324
|
+
v128_t const pi_high_half = wasm_f64x2_splat(3.141592653589793116 * 0.5);
|
|
325
|
+
v128_t const pi_low_half = wasm_f64x2_splat(1.2246467991473532072e-16 * 0.5);
|
|
326
|
+
v128_t const pi_reciprocal = wasm_f64x2_splat(0.31830988618379067154);
|
|
327
|
+
|
|
328
|
+
// Polynomial coefficients for cosine approximation
|
|
329
|
+
v128_t const coeff_0 = wasm_f64x2_splat(+0.00833333333333332974823815);
|
|
330
|
+
v128_t const coeff_1 = wasm_f64x2_splat(-0.000198412698412696162806809);
|
|
331
|
+
v128_t const coeff_2 = wasm_f64x2_splat(+2.75573192239198747630416e-06);
|
|
332
|
+
v128_t const coeff_3 = wasm_f64x2_splat(-2.50521083763502045810755e-08);
|
|
333
|
+
v128_t const coeff_4 = wasm_f64x2_splat(+1.60590430605664501629054e-10);
|
|
334
|
+
v128_t const coeff_5 = wasm_f64x2_splat(-7.64712219118158833288484e-13);
|
|
335
|
+
v128_t const coeff_6 = wasm_f64x2_splat(+2.81009972710863200091251e-15);
|
|
336
|
+
v128_t const coeff_7 = wasm_f64x2_splat(-7.97255955009037868891952e-18);
|
|
337
|
+
v128_t const coeff_8 = wasm_f64x2_splat(-0.166666666666666657414808);
|
|
338
|
+
|
|
339
|
+
// Compute 2 * round(angle / pi - 0.5) + 1
|
|
340
|
+
v128_t const neg_half = wasm_f64x2_splat(-0.5);
|
|
341
|
+
v128_t const quotients = wasm_f64x2_relaxed_madd(angles_radians, pi_reciprocal, neg_half);
|
|
342
|
+
v128_t const rounded = wasm_f64x2_nearest(quotients);
|
|
343
|
+
v128_t const rounded_quotients = wasm_f64x2_relaxed_madd(wasm_f64x2_splat(2.0), rounded, wasm_f64x2_splat(1.0));
|
|
344
|
+
// relaxed_trunc: 1 instruction (cvttpd2dq) vs 7 (with NaN/overflow fixup) on x86.
|
|
345
|
+
// Safe because rounded_quotients are small integers from nearest(), never NaN or out of i32 range.
|
|
346
|
+
v128_t quotients_i32 = wasm_i32x4_relaxed_trunc_f64x2_zero(rounded_quotients);
|
|
347
|
+
|
|
348
|
+
// Two-step Cody-Waite reduction
|
|
349
|
+
v128_t angles = angles_radians;
|
|
350
|
+
angles = wasm_f64x2_relaxed_nmadd(rounded_quotients, pi_high_half, angles);
|
|
351
|
+
angles = wasm_f64x2_relaxed_nmadd(rounded_quotients, pi_low_half, angles);
|
|
352
|
+
|
|
353
|
+
// Check bit 1 in i32, then widen to i64 mask for laneselect
|
|
354
|
+
v128_t bit2_i32 = wasm_v128_and(quotients_i32, wasm_i32x4_splat(2));
|
|
355
|
+
v128_t flip_i32 = wasm_i32x4_eq(bit2_i32, wasm_i32x4_splat(0));
|
|
356
|
+
v128_t flip_mask = wasm_i32x4_shuffle(flip_i32, flip_i32, 0, 0, 1, 1);
|
|
357
|
+
v128_t negated_angles = wasm_f64x2_neg(angles);
|
|
358
|
+
// relaxed_laneselect: 1 instruction (vblendvpd) vs 3 (vpand+vpandn+vpor) on x86.
|
|
359
|
+
// Safe because mask is lane-granular at i64 width (all-ones or all-zeros per 64-bit lane).
|
|
360
|
+
angles = wasm_i64x2_relaxed_laneselect(negated_angles, angles, flip_mask);
|
|
361
|
+
|
|
362
|
+
v128_t const angles_squared = wasm_f64x2_mul(angles, angles);
|
|
363
|
+
v128_t const angles_cubed = wasm_f64x2_mul(angles, angles_squared);
|
|
364
|
+
v128_t const angles_quadratic = wasm_f64x2_mul(angles_squared, angles_squared);
|
|
365
|
+
v128_t const angles_octic = wasm_f64x2_mul(angles_quadratic, angles_quadratic);
|
|
366
|
+
|
|
367
|
+
// Compute polynomial terms using Estrin's scheme
|
|
368
|
+
v128_t const poly_67 = wasm_f64x2_relaxed_madd(angles_squared, coeff_7, coeff_6);
|
|
369
|
+
v128_t const poly_45 = wasm_f64x2_relaxed_madd(angles_squared, coeff_5, coeff_4);
|
|
370
|
+
v128_t const poly_4567 = wasm_f64x2_relaxed_madd(angles_quadratic, poly_67, poly_45);
|
|
371
|
+
|
|
372
|
+
v128_t const poly_23 = wasm_f64x2_relaxed_madd(angles_squared, coeff_3, coeff_2);
|
|
373
|
+
v128_t const poly_01 = wasm_f64x2_relaxed_madd(angles_squared, coeff_1, coeff_0);
|
|
374
|
+
v128_t const poly_0123 = wasm_f64x2_relaxed_madd(angles_quadratic, poly_23, poly_01);
|
|
375
|
+
|
|
376
|
+
// Combine polynomial terms
|
|
377
|
+
v128_t results = wasm_f64x2_relaxed_madd(angles_octic, poly_4567, poly_0123);
|
|
378
|
+
results = wasm_f64x2_relaxed_madd(results, angles_squared, coeff_8);
|
|
379
|
+
results = wasm_f64x2_relaxed_madd(results, angles_cubed, angles);
|
|
380
|
+
return results;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
NK_INTERNAL v128_t nk_f64x2_atan_v128relaxed_(v128_t const inputs) {
|
|
384
|
+
// Polynomial coefficients for atan approximation (19 terms)
|
|
385
|
+
v128_t const coeff_19 = wasm_f64x2_splat(-1.88796008463073496563746e-05);
|
|
386
|
+
v128_t const coeff_18 = wasm_f64x2_splat(+0.000209850076645816976906797);
|
|
387
|
+
v128_t const coeff_17 = wasm_f64x2_splat(-0.00110611831486672482563471);
|
|
388
|
+
v128_t const coeff_16 = wasm_f64x2_splat(+0.00370026744188713119232403);
|
|
389
|
+
v128_t const coeff_15 = wasm_f64x2_splat(-0.00889896195887655491740809);
|
|
390
|
+
v128_t const coeff_14 = wasm_f64x2_splat(+0.016599329773529201970117);
|
|
391
|
+
v128_t const coeff_13 = wasm_f64x2_splat(-0.0254517624932312641616861);
|
|
392
|
+
v128_t const coeff_12 = wasm_f64x2_splat(+0.0337852580001353069993897);
|
|
393
|
+
v128_t const coeff_11 = wasm_f64x2_splat(-0.0407629191276836500001934);
|
|
394
|
+
v128_t const coeff_10 = wasm_f64x2_splat(+0.0466667150077840625632675);
|
|
395
|
+
v128_t const coeff_9 = wasm_f64x2_splat(-0.0523674852303482457616113);
|
|
396
|
+
v128_t const coeff_8 = wasm_f64x2_splat(+0.0587666392926673580854313);
|
|
397
|
+
v128_t const coeff_7 = wasm_f64x2_splat(-0.0666573579361080525984562);
|
|
398
|
+
v128_t const coeff_6 = wasm_f64x2_splat(+0.0769219538311769618355029);
|
|
399
|
+
v128_t const coeff_5 = wasm_f64x2_splat(-0.090908995008245008229153);
|
|
400
|
+
v128_t const coeff_4 = wasm_f64x2_splat(+0.111111105648261418443745);
|
|
401
|
+
v128_t const coeff_3 = wasm_f64x2_splat(-0.14285714266771329383765);
|
|
402
|
+
v128_t const coeff_2 = wasm_f64x2_splat(+0.199999999996591265594148);
|
|
403
|
+
v128_t const coeff_1 = wasm_f64x2_splat(-0.333333333333311110369124);
|
|
404
|
+
v128_t const half_pi = wasm_f64x2_splat(1.5707963267948966);
|
|
405
|
+
v128_t const zeros = wasm_f64x2_splat(0);
|
|
406
|
+
|
|
407
|
+
// Detect negative and take absolute value
|
|
408
|
+
v128_t negative_mask = wasm_f64x2_lt(inputs, zeros);
|
|
409
|
+
v128_t values = wasm_f64x2_abs(inputs);
|
|
410
|
+
|
|
411
|
+
// Check if values > 1 (need reciprocal) - use division for f64 precision
|
|
412
|
+
v128_t reciprocal_mask = wasm_f64x2_gt(values, wasm_f64x2_splat(1.0));
|
|
413
|
+
v128_t reciprocal_values = wasm_f64x2_div(wasm_f64x2_splat(1.0), values);
|
|
414
|
+
// relaxed_laneselect: 1 instruction (vblendvpd) vs 3 (vpand+vpandn+vpor) on x86.
|
|
415
|
+
// Safe because mask is from comparison (all-ones or all-zeros per lane).
|
|
416
|
+
values = wasm_i64x2_relaxed_laneselect(reciprocal_values, values, reciprocal_mask);
|
|
417
|
+
|
|
418
|
+
// Compute powers
|
|
419
|
+
v128_t const values_squared = wasm_f64x2_mul(values, values);
|
|
420
|
+
v128_t const values_cubed = wasm_f64x2_mul(values, values_squared);
|
|
421
|
+
|
|
422
|
+
// Polynomial evaluation using Horner's method
|
|
423
|
+
v128_t polynomials = coeff_19;
|
|
424
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_18);
|
|
425
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_17);
|
|
426
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_16);
|
|
427
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_15);
|
|
428
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_14);
|
|
429
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_13);
|
|
430
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_12);
|
|
431
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_11);
|
|
432
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_10);
|
|
433
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_9);
|
|
434
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_8);
|
|
435
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_7);
|
|
436
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_6);
|
|
437
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_5);
|
|
438
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_4);
|
|
439
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_3);
|
|
440
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_2);
|
|
441
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, values_squared, coeff_1);
|
|
442
|
+
|
|
443
|
+
// Compute result
|
|
444
|
+
v128_t result = wasm_f64x2_relaxed_madd(values_cubed, polynomials, values);
|
|
445
|
+
|
|
446
|
+
// Adjust for reciprocal: result = pi/2 - result
|
|
447
|
+
v128_t adjusted = wasm_f64x2_sub(half_pi, result);
|
|
448
|
+
// relaxed_laneselect: 1 instruction (vblendvpd) vs 3 (vpand+vpandn+vpor) on x86.
|
|
449
|
+
// Safe because mask is from comparison (all-ones or all-zeros per lane).
|
|
450
|
+
result = wasm_i64x2_relaxed_laneselect(adjusted, result, reciprocal_mask);
|
|
451
|
+
|
|
452
|
+
// Adjust for negative: result = -result
|
|
453
|
+
v128_t negated = wasm_f64x2_neg(result);
|
|
454
|
+
// relaxed_laneselect: 1 instruction (vblendvpd) vs 3 (vpand+vpandn+vpor) on x86.
|
|
455
|
+
// Safe because mask is from comparison (all-ones or all-zeros per lane).
|
|
456
|
+
result = wasm_i64x2_relaxed_laneselect(negated, result, negative_mask);
|
|
457
|
+
return result;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
NK_INTERNAL v128_t nk_f64x2_atan2_v128relaxed_(v128_t const ys_inputs, v128_t const xs_inputs) {
|
|
461
|
+
// Polynomial coefficients (same as atan)
|
|
462
|
+
v128_t const coeff_19 = wasm_f64x2_splat(-1.88796008463073496563746e-05);
|
|
463
|
+
v128_t const coeff_18 = wasm_f64x2_splat(+0.000209850076645816976906797);
|
|
464
|
+
v128_t const coeff_17 = wasm_f64x2_splat(-0.00110611831486672482563471);
|
|
465
|
+
v128_t const coeff_16 = wasm_f64x2_splat(+0.00370026744188713119232403);
|
|
466
|
+
v128_t const coeff_15 = wasm_f64x2_splat(-0.00889896195887655491740809);
|
|
467
|
+
v128_t const coeff_14 = wasm_f64x2_splat(+0.016599329773529201970117);
|
|
468
|
+
v128_t const coeff_13 = wasm_f64x2_splat(-0.0254517624932312641616861);
|
|
469
|
+
v128_t const coeff_12 = wasm_f64x2_splat(+0.0337852580001353069993897);
|
|
470
|
+
v128_t const coeff_11 = wasm_f64x2_splat(-0.0407629191276836500001934);
|
|
471
|
+
v128_t const coeff_10 = wasm_f64x2_splat(+0.0466667150077840625632675);
|
|
472
|
+
v128_t const coeff_9 = wasm_f64x2_splat(-0.0523674852303482457616113);
|
|
473
|
+
v128_t const coeff_8 = wasm_f64x2_splat(+0.0587666392926673580854313);
|
|
474
|
+
v128_t const coeff_7 = wasm_f64x2_splat(-0.0666573579361080525984562);
|
|
475
|
+
v128_t const coeff_6 = wasm_f64x2_splat(+0.0769219538311769618355029);
|
|
476
|
+
v128_t const coeff_5 = wasm_f64x2_splat(-0.090908995008245008229153);
|
|
477
|
+
v128_t const coeff_4 = wasm_f64x2_splat(+0.111111105648261418443745);
|
|
478
|
+
v128_t const coeff_3 = wasm_f64x2_splat(-0.14285714266771329383765);
|
|
479
|
+
v128_t const coeff_2 = wasm_f64x2_splat(+0.199999999996591265594148);
|
|
480
|
+
v128_t const coeff_1 = wasm_f64x2_splat(-0.333333333333311110369124);
|
|
481
|
+
v128_t const pi = wasm_f64x2_splat(3.14159265358979323846);
|
|
482
|
+
v128_t const half_pi = wasm_f64x2_splat(1.5707963267948966);
|
|
483
|
+
v128_t const zeros = wasm_f64x2_splat(0);
|
|
484
|
+
|
|
485
|
+
// Quadrant adjustments - take absolute values
|
|
486
|
+
v128_t xs_negative_mask = wasm_f64x2_lt(xs_inputs, zeros);
|
|
487
|
+
v128_t xs = wasm_f64x2_abs(xs_inputs);
|
|
488
|
+
v128_t ys = wasm_f64x2_abs(ys_inputs);
|
|
489
|
+
|
|
490
|
+
// Ensure proper fraction where numerator < denominator
|
|
491
|
+
v128_t swap_mask = wasm_f64x2_gt(ys, xs);
|
|
492
|
+
v128_t temps = xs;
|
|
493
|
+
// relaxed_laneselect: 1 instruction (vblendvpd) vs 3 (vpand+vpandn+vpor) on x86.
|
|
494
|
+
// Safe because mask is from comparison (all-ones or all-zeros per lane).
|
|
495
|
+
xs = wasm_i64x2_relaxed_laneselect(ys, xs, swap_mask);
|
|
496
|
+
ys = wasm_i64x2_relaxed_laneselect(wasm_f64x2_neg(temps), ys, swap_mask);
|
|
497
|
+
|
|
498
|
+
// Division for f64 precision
|
|
499
|
+
v128_t const ratio = wasm_f64x2_div(ys, xs);
|
|
500
|
+
v128_t const ratio_squared = wasm_f64x2_mul(ratio, ratio);
|
|
501
|
+
v128_t const ratio_cubed = wasm_f64x2_mul(ratio, ratio_squared);
|
|
502
|
+
|
|
503
|
+
// Polynomial evaluation using Horner's method
|
|
504
|
+
v128_t polynomials = coeff_19;
|
|
505
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_18);
|
|
506
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_17);
|
|
507
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_16);
|
|
508
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_15);
|
|
509
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_14);
|
|
510
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_13);
|
|
511
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_12);
|
|
512
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_11);
|
|
513
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_10);
|
|
514
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_9);
|
|
515
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_8);
|
|
516
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_7);
|
|
517
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_6);
|
|
518
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_5);
|
|
519
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_4);
|
|
520
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_3);
|
|
521
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_2);
|
|
522
|
+
polynomials = wasm_f64x2_relaxed_madd(polynomials, ratio_squared, coeff_1);
|
|
523
|
+
|
|
524
|
+
// Compute the result
|
|
525
|
+
v128_t results = wasm_f64x2_relaxed_madd(ratio_cubed, polynomials, ratio);
|
|
526
|
+
|
|
527
|
+
// Compute quadrant value: 0 for x>=0 && !swap, 1 for x>=0 && swap,
|
|
528
|
+
// -2 for x<0 && !swap, -1 for x<0 && swap
|
|
529
|
+
v128_t quadrant = wasm_f64x2_splat(0.0);
|
|
530
|
+
v128_t neg_two = wasm_f64x2_splat(-2.0);
|
|
531
|
+
// relaxed_laneselect: 1 instruction (vblendvpd) vs 3 (vpand+vpandn+vpor) on x86.
|
|
532
|
+
// Safe because mask is from comparison (all-ones or all-zeros per lane).
|
|
533
|
+
quadrant = wasm_i64x2_relaxed_laneselect(neg_two, quadrant, xs_negative_mask);
|
|
534
|
+
v128_t quadrant_incremented = wasm_f64x2_add(quadrant, wasm_f64x2_splat(1.0));
|
|
535
|
+
quadrant = wasm_i64x2_relaxed_laneselect(quadrant_incremented, quadrant, swap_mask);
|
|
536
|
+
|
|
537
|
+
// Adjust for quadrant: result += quadrant * pi/2
|
|
538
|
+
results = wasm_f64x2_relaxed_madd(quadrant, half_pi, results);
|
|
539
|
+
|
|
540
|
+
// Transfer sign from x and y by XOR with sign bits
|
|
541
|
+
v128_t sign_mask = wasm_f64x2_splat(-0.0);
|
|
542
|
+
v128_t xs_sign = wasm_v128_and(xs_inputs, sign_mask);
|
|
543
|
+
v128_t ys_sign = wasm_v128_and(ys_inputs, sign_mask);
|
|
544
|
+
results = wasm_v128_xor(results, xs_sign);
|
|
545
|
+
results = wasm_v128_xor(results, ys_sign);
|
|
546
|
+
|
|
547
|
+
return results;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/* NK_PUBLIC wrappers — same loop+tail pattern as neon.h.
|
|
551
|
+
* Full loads use wasm_v128_load/wasm_v128_store.
|
|
552
|
+
* Tails use nk_partial_load_b32x4_serial_/nk_partial_store_b32x4_serial_ via .v128 union member.
|
|
553
|
+
*/
|
|
554
|
+
|
|
555
|
+
NK_PUBLIC void nk_each_sin_f32_v128relaxed(nk_f32_t const *ins, nk_size_t n, nk_f32_t *outs) {
|
|
556
|
+
nk_size_t i = 0;
|
|
557
|
+
for (; i + 4 <= n; i += 4) {
|
|
558
|
+
v128_t angles = wasm_v128_load(ins + i);
|
|
559
|
+
v128_t results = nk_f32x4_sin_v128relaxed_(angles);
|
|
560
|
+
wasm_v128_store(outs + i, results);
|
|
561
|
+
}
|
|
562
|
+
if (i < n) {
|
|
563
|
+
nk_size_t remaining = n - i;
|
|
564
|
+
nk_b128_vec_t angles_vec;
|
|
565
|
+
nk_partial_load_b32x4_serial_(ins + i, &angles_vec, remaining);
|
|
566
|
+
nk_b128_vec_t results_vec;
|
|
567
|
+
results_vec.v128 = nk_f32x4_sin_v128relaxed_(angles_vec.v128);
|
|
568
|
+
nk_partial_store_b32x4_serial_(&results_vec, outs + i, remaining);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
NK_PUBLIC void nk_each_cos_f32_v128relaxed(nk_f32_t const *ins, nk_size_t n, nk_f32_t *outs) {
|
|
573
|
+
nk_size_t i = 0;
|
|
574
|
+
for (; i + 4 <= n; i += 4) {
|
|
575
|
+
v128_t angles = wasm_v128_load(ins + i);
|
|
576
|
+
v128_t results = nk_f32x4_cos_v128relaxed_(angles);
|
|
577
|
+
wasm_v128_store(outs + i, results);
|
|
578
|
+
}
|
|
579
|
+
if (i < n) {
|
|
580
|
+
nk_size_t remaining = n - i;
|
|
581
|
+
nk_b128_vec_t angles_vec;
|
|
582
|
+
nk_partial_load_b32x4_serial_(ins + i, &angles_vec, remaining);
|
|
583
|
+
nk_b128_vec_t results_vec;
|
|
584
|
+
results_vec.v128 = nk_f32x4_cos_v128relaxed_(angles_vec.v128);
|
|
585
|
+
nk_partial_store_b32x4_serial_(&results_vec, outs + i, remaining);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
NK_PUBLIC void nk_each_atan_f32_v128relaxed(nk_f32_t const *ins, nk_size_t n, nk_f32_t *outs) {
|
|
590
|
+
nk_size_t i = 0;
|
|
591
|
+
for (; i + 4 <= n; i += 4) {
|
|
592
|
+
v128_t values = wasm_v128_load(ins + i);
|
|
593
|
+
v128_t results = nk_f32x4_atan_v128relaxed_(values);
|
|
594
|
+
wasm_v128_store(outs + i, results);
|
|
595
|
+
}
|
|
596
|
+
if (i < n) {
|
|
597
|
+
nk_size_t remaining = n - i;
|
|
598
|
+
nk_b128_vec_t values_vec;
|
|
599
|
+
nk_partial_load_b32x4_serial_(ins + i, &values_vec, remaining);
|
|
600
|
+
nk_b128_vec_t results_vec;
|
|
601
|
+
results_vec.v128 = nk_f32x4_atan_v128relaxed_(values_vec.v128);
|
|
602
|
+
nk_partial_store_b32x4_serial_(&results_vec, outs + i, remaining);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
NK_PUBLIC void nk_each_sin_f64_v128relaxed(nk_f64_t const *ins, nk_size_t n, nk_f64_t *outs) {
|
|
607
|
+
nk_size_t i = 0;
|
|
608
|
+
for (; i + 2 <= n; i += 2) {
|
|
609
|
+
v128_t angles = wasm_v128_load(ins + i);
|
|
610
|
+
v128_t results = nk_f64x2_sin_v128relaxed_(angles);
|
|
611
|
+
wasm_v128_store(outs + i, results);
|
|
612
|
+
}
|
|
613
|
+
if (i < n) {
|
|
614
|
+
nk_size_t remaining = n - i;
|
|
615
|
+
nk_b128_vec_t angles_vec;
|
|
616
|
+
nk_partial_load_b64x2_serial_(ins + i, &angles_vec, remaining);
|
|
617
|
+
nk_b128_vec_t results_vec;
|
|
618
|
+
results_vec.v128 = nk_f64x2_sin_v128relaxed_(angles_vec.v128);
|
|
619
|
+
nk_partial_store_b64x2_serial_(&results_vec, outs + i, remaining);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
NK_PUBLIC void nk_each_cos_f64_v128relaxed(nk_f64_t const *ins, nk_size_t n, nk_f64_t *outs) {
|
|
624
|
+
nk_size_t i = 0;
|
|
625
|
+
for (; i + 2 <= n; i += 2) {
|
|
626
|
+
v128_t angles = wasm_v128_load(ins + i);
|
|
627
|
+
v128_t results = nk_f64x2_cos_v128relaxed_(angles);
|
|
628
|
+
wasm_v128_store(outs + i, results);
|
|
629
|
+
}
|
|
630
|
+
if (i < n) {
|
|
631
|
+
nk_size_t remaining = n - i;
|
|
632
|
+
nk_b128_vec_t angles_vec;
|
|
633
|
+
nk_partial_load_b64x2_serial_(ins + i, &angles_vec, remaining);
|
|
634
|
+
nk_b128_vec_t results_vec;
|
|
635
|
+
results_vec.v128 = nk_f64x2_cos_v128relaxed_(angles_vec.v128);
|
|
636
|
+
nk_partial_store_b64x2_serial_(&results_vec, outs + i, remaining);
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
NK_PUBLIC void nk_each_atan_f64_v128relaxed(nk_f64_t const *ins, nk_size_t n, nk_f64_t *outs) {
|
|
641
|
+
nk_size_t i = 0;
|
|
642
|
+
for (; i + 2 <= n; i += 2) {
|
|
643
|
+
v128_t values = wasm_v128_load(ins + i);
|
|
644
|
+
v128_t results = nk_f64x2_atan_v128relaxed_(values);
|
|
645
|
+
wasm_v128_store(outs + i, results);
|
|
646
|
+
}
|
|
647
|
+
if (i < n) {
|
|
648
|
+
nk_size_t remaining = n - i;
|
|
649
|
+
nk_b128_vec_t values_vec;
|
|
650
|
+
nk_partial_load_b64x2_serial_(ins + i, &values_vec, remaining);
|
|
651
|
+
nk_b128_vec_t results_vec;
|
|
652
|
+
results_vec.v128 = nk_f64x2_atan_v128relaxed_(values_vec.v128);
|
|
653
|
+
nk_partial_store_b64x2_serial_(&results_vec, outs + i, remaining);
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
#if defined(__clang__)
|
|
658
|
+
#pragma clang attribute pop
|
|
659
|
+
#endif
|
|
660
|
+
|
|
661
|
+
#if defined(__cplusplus)
|
|
662
|
+
} // extern "C"
|
|
663
|
+
#endif
|
|
664
|
+
|
|
665
|
+
#endif // NK_TARGET_V128RELAXED
|
|
666
|
+
#endif // NK_TRIGONOMETRY_V128RELAXED_H
|