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,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Set Similarity Measures for RISC-V with Zvbb.
|
|
3
|
+
* @file include/numkong/set/rvvbb.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date February 9, 2026
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/set.h
|
|
8
|
+
*
|
|
9
|
+
* Zvbb (Vector Basic Bit-manipulation) provides native per-element popcount via `vcpop.v`,
|
|
10
|
+
* replacing the 11-instruction SWAR approach in set/rvv.h with a single instruction.
|
|
11
|
+
*
|
|
12
|
+
* Only `nk_hamming_u1` and `nk_jaccard_u1` benefit from Zvbb (they need byte-level popcount).
|
|
13
|
+
* Integer set operations (hamming_u8, jaccard_u16, jaccard_u32) use mask-level vcpop.m
|
|
14
|
+
* which is already available in base RVV 1.0.
|
|
15
|
+
*
|
|
16
|
+
* Requires: RVV 1.0 + Zvbb extension (GCC 14+ or Clang 18+)
|
|
17
|
+
*/
|
|
18
|
+
#ifndef NK_SET_RVVBB_H
|
|
19
|
+
#define NK_SET_RVVBB_H
|
|
20
|
+
|
|
21
|
+
#if NK_TARGET_RISCV_
|
|
22
|
+
#if NK_TARGET_RVVBB
|
|
23
|
+
|
|
24
|
+
#include "numkong/types.h"
|
|
25
|
+
|
|
26
|
+
#if defined(__clang__)
|
|
27
|
+
#pragma clang attribute push(__attribute__((target("arch=+v,+zvbb"))), apply_to = function)
|
|
28
|
+
#elif defined(__GNUC__)
|
|
29
|
+
#pragma GCC push_options
|
|
30
|
+
#pragma GCC target("arch=+v,+zvbb")
|
|
31
|
+
#endif
|
|
32
|
+
|
|
33
|
+
#if defined(__cplusplus)
|
|
34
|
+
extern "C" {
|
|
35
|
+
#endif
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @brief Native per-element popcount using Zvbb vcpop.v (1 instruction).
|
|
39
|
+
*
|
|
40
|
+
* Replaces the 11-instruction SWAR approach in nk_popcount_u8m4_rvv_.
|
|
41
|
+
*/
|
|
42
|
+
NK_INTERNAL vuint8m4_t nk_popcount_u8m4_rvvbb_(vuint8m4_t v_u8m4) {
|
|
43
|
+
vuint8m4_t result_u8m4;
|
|
44
|
+
__asm__ volatile("vcpop.v %0, %1" : "=vr"(result_u8m4) : "vr"(v_u8m4));
|
|
45
|
+
return result_u8m4;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
NK_PUBLIC void nk_hamming_u1_rvvbb(nk_u1x8_t const *a, nk_u1x8_t const *b, nk_size_t n, nk_u32_t *result) {
|
|
49
|
+
nk_size_t count_bytes = nk_size_divide_round_up_(n, NK_BITS_PER_BYTE);
|
|
50
|
+
|
|
51
|
+
vuint32m1_t sum_u32m1 = __riscv_vmv_v_x_u32m1(0, 1);
|
|
52
|
+
|
|
53
|
+
nk_size_t i = 0;
|
|
54
|
+
for (nk_size_t vector_length; i + 1 <= count_bytes; i += vector_length) {
|
|
55
|
+
vector_length = __riscv_vsetvl_e8m4(count_bytes - i);
|
|
56
|
+
|
|
57
|
+
vuint8m4_t a_u8m4 = __riscv_vle8_v_u8m4(a + i, vector_length);
|
|
58
|
+
vuint8m4_t b_u8m4 = __riscv_vle8_v_u8m4(b + i, vector_length);
|
|
59
|
+
vuint8m4_t xor_u8m4 = __riscv_vxor_vv_u8m4(a_u8m4, b_u8m4, vector_length);
|
|
60
|
+
|
|
61
|
+
// Native per-element popcount via Zvbb (1 instruction vs 11 SWAR)
|
|
62
|
+
vuint8m4_t popcount_u8m4 = nk_popcount_u8m4_rvvbb_(xor_u8m4);
|
|
63
|
+
|
|
64
|
+
// Widen to u16 and accumulate via widening reduction sum
|
|
65
|
+
vuint16m8_t popcount_u16m8 = __riscv_vwaddu_vx_u16m8(popcount_u8m4, 0, vector_length);
|
|
66
|
+
sum_u32m1 = __riscv_vwredsumu_vs_u16m8_u32m1(popcount_u16m8, sum_u32m1, vector_length);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
*result = __riscv_vmv_x_s_u32m1_u32(sum_u32m1);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
NK_PUBLIC void nk_jaccard_u1_rvvbb(nk_u1x8_t const *a, nk_u1x8_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
73
|
+
nk_size_t count_bytes = nk_size_divide_round_up_(n, NK_BITS_PER_BYTE);
|
|
74
|
+
|
|
75
|
+
vuint32m1_t intersection_sum_u32m1 = __riscv_vmv_v_x_u32m1(0, 1);
|
|
76
|
+
vuint32m1_t union_sum_u32m1 = __riscv_vmv_v_x_u32m1(0, 1);
|
|
77
|
+
|
|
78
|
+
nk_size_t i = 0;
|
|
79
|
+
for (nk_size_t vector_length; i + 1 <= count_bytes; i += vector_length) {
|
|
80
|
+
vector_length = __riscv_vsetvl_e8m4(count_bytes - i);
|
|
81
|
+
|
|
82
|
+
vuint8m4_t a_u8m4 = __riscv_vle8_v_u8m4(a + i, vector_length);
|
|
83
|
+
vuint8m4_t b_u8m4 = __riscv_vle8_v_u8m4(b + i, vector_length);
|
|
84
|
+
|
|
85
|
+
vuint8m4_t intersection_u8m4 = __riscv_vand_vv_u8m4(a_u8m4, b_u8m4, vector_length);
|
|
86
|
+
vuint8m4_t union_u8m4 = __riscv_vor_vv_u8m4(a_u8m4, b_u8m4, vector_length);
|
|
87
|
+
|
|
88
|
+
// Native per-element popcount via Zvbb
|
|
89
|
+
vuint8m4_t intersection_popcount_u8m4 = nk_popcount_u8m4_rvvbb_(intersection_u8m4);
|
|
90
|
+
vuint8m4_t union_popcount_u8m4 = nk_popcount_u8m4_rvvbb_(union_u8m4);
|
|
91
|
+
|
|
92
|
+
// Widen and accumulate
|
|
93
|
+
vuint16m8_t intersection_popcount_u16m8 = __riscv_vwaddu_vx_u16m8(intersection_popcount_u8m4, 0, vector_length);
|
|
94
|
+
vuint16m8_t union_popcount_u16m8 = __riscv_vwaddu_vx_u16m8(union_popcount_u8m4, 0, vector_length);
|
|
95
|
+
intersection_sum_u32m1 = __riscv_vwredsumu_vs_u16m8_u32m1(intersection_popcount_u16m8, intersection_sum_u32m1,
|
|
96
|
+
vector_length);
|
|
97
|
+
union_sum_u32m1 = __riscv_vwredsumu_vs_u16m8_u32m1(union_popcount_u16m8, union_sum_u32m1, vector_length);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
nk_u32_t intersection_count_u32 = __riscv_vmv_x_s_u32m1_u32(intersection_sum_u32m1);
|
|
101
|
+
nk_u32_t union_count_u32 = __riscv_vmv_x_s_u32m1_u32(union_sum_u32m1);
|
|
102
|
+
*result = (union_count_u32 != 0) ? 1.0f - (nk_f32_t)intersection_count_u32 / (nk_f32_t)union_count_u32 : 0.0f;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
#if defined(__cplusplus)
|
|
106
|
+
} // extern "C"
|
|
107
|
+
#endif
|
|
108
|
+
|
|
109
|
+
#if defined(__clang__)
|
|
110
|
+
#pragma clang attribute pop
|
|
111
|
+
#elif defined(__GNUC__)
|
|
112
|
+
#pragma GCC pop_options
|
|
113
|
+
#endif
|
|
114
|
+
|
|
115
|
+
#endif // NK_TARGET_RVVBB
|
|
116
|
+
#endif // NK_TARGET_RISCV_
|
|
117
|
+
#endif // NK_SET_RVVBB_H
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SWAR-accelerated Set Similarity Measures for SIMD-free CPUs.
|
|
3
|
+
* @file include/numkong/set/serial.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date December 27, 2025
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/set.h
|
|
8
|
+
*
|
|
9
|
+
* @section set_serial_instructions Key SWAR Set Instructions
|
|
10
|
+
*
|
|
11
|
+
* Serial backend uses lookup-table-based popcount for bit operations.
|
|
12
|
+
* No SIMD instructions required - works on any architecture.
|
|
13
|
+
*
|
|
14
|
+
* @section set_serial_stateful Stateful Streaming Logic
|
|
15
|
+
*
|
|
16
|
+
* To build memory-optimal tiled algorithms, this file defines:
|
|
17
|
+
*
|
|
18
|
+
* - nk_hamming_u1x128_state_serial_t for streaming Hamming distance
|
|
19
|
+
* - nk_jaccard_u1x128_state_serial_t for streaming Jaccard similarity
|
|
20
|
+
*
|
|
21
|
+
* @code{c}
|
|
22
|
+
* nk_jaccard_u1x128_state_serial_t state_first, state_second, state_third, state_fourth;
|
|
23
|
+
* nk_jaccard_u1x128_init_serial(&state_first);
|
|
24
|
+
* // ... stream through packed binary vectors ...
|
|
25
|
+
* nk_jaccard_u1x128_finalize_serial(&state_first, &state_second, &state_third, &state_fourth,
|
|
26
|
+
* query_popcount, target_popcount_a, target_popcount_b, target_popcount_c, target_popcount_d,
|
|
27
|
+
* total_dimensions, &results);
|
|
28
|
+
* @endcode
|
|
29
|
+
*/
|
|
30
|
+
#ifndef NK_SET_SERIAL_H
|
|
31
|
+
#define NK_SET_SERIAL_H
|
|
32
|
+
#include "numkong/types.h"
|
|
33
|
+
|
|
34
|
+
#if defined(__cplusplus)
|
|
35
|
+
extern "C" {
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
#pragma region - Binary Sets
|
|
39
|
+
|
|
40
|
+
NK_PUBLIC void nk_hamming_u1_serial(nk_u1x8_t const *a, nk_u1x8_t const *b, nk_size_t n, nk_u32_t *result) {
|
|
41
|
+
nk_size_t n_bytes = nk_size_divide_round_up_(n, NK_BITS_PER_BYTE);
|
|
42
|
+
nk_u32_t differences = 0;
|
|
43
|
+
for (nk_size_t i = 0; i != n_bytes; ++i) differences += nk_u1x8_popcount_(a[i] ^ b[i]);
|
|
44
|
+
*result = differences;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
NK_PUBLIC void nk_jaccard_u1_serial(nk_u1x8_t const *a, nk_u1x8_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
48
|
+
nk_size_t n_bytes = nk_size_divide_round_up_(n, NK_BITS_PER_BYTE);
|
|
49
|
+
nk_u32_t intersection_count = 0, union_count = 0;
|
|
50
|
+
for (nk_size_t i = 0; i != n_bytes; ++i)
|
|
51
|
+
intersection_count += nk_u1x8_popcount_(a[i] & b[i]), union_count += nk_u1x8_popcount_(a[i] | b[i]);
|
|
52
|
+
*result = (union_count != 0) ? 1.0f - (nk_f32_t)intersection_count / (nk_f32_t)union_count : 0.0f;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
#pragma endregion - Binary Sets
|
|
56
|
+
|
|
57
|
+
#pragma region - Integer Sets
|
|
58
|
+
|
|
59
|
+
NK_PUBLIC void nk_jaccard_u32_serial(nk_u32_t const *a, nk_u32_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
60
|
+
nk_u32_t intersection_count = 0;
|
|
61
|
+
for (nk_size_t i = 0; i != n; ++i) intersection_count += (a[i] == b[i]);
|
|
62
|
+
*result = (n != 0) ? 1.0f - (nk_f32_t)intersection_count / (nk_f32_t)n : 0.0f;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
NK_PUBLIC void nk_hamming_u8_serial(nk_u8_t const *a, nk_u8_t const *b, nk_size_t n, nk_u32_t *result) {
|
|
66
|
+
nk_u32_t differences = 0;
|
|
67
|
+
for (nk_size_t i = 0; i != n; ++i) differences += (a[i] != b[i]);
|
|
68
|
+
*result = differences;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
NK_PUBLIC void nk_jaccard_u16_serial(nk_u16_t const *a, nk_u16_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
72
|
+
nk_u32_t matches = 0;
|
|
73
|
+
for (nk_size_t i = 0; i != n; ++i) matches += (a[i] == b[i]);
|
|
74
|
+
*result = (n != 0) ? 1.0f - (nk_f32_t)matches / (nk_f32_t)n : 0.0f;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
#pragma endregion - Integer Sets
|
|
78
|
+
|
|
79
|
+
#pragma region - Stateful Streaming
|
|
80
|
+
|
|
81
|
+
typedef struct nk_jaccard_u1x128_state_serial_t {
|
|
82
|
+
nk_u64_t intersection_count;
|
|
83
|
+
} nk_jaccard_u1x128_state_serial_t;
|
|
84
|
+
|
|
85
|
+
NK_INTERNAL void nk_jaccard_u1x128_init_serial(nk_jaccard_u1x128_state_serial_t *state) {
|
|
86
|
+
state->intersection_count = 0;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
NK_INTERNAL void nk_jaccard_u1x128_update_serial(nk_jaccard_u1x128_state_serial_t *state, nk_b128_vec_t a,
|
|
90
|
+
nk_b128_vec_t b, nk_size_t depth_offset, nk_size_t active_dimensions) {
|
|
91
|
+
nk_unused_(depth_offset);
|
|
92
|
+
nk_unused_(active_dimensions);
|
|
93
|
+
nk_u64_t intersection_low = a.u64s[0] & b.u64s[0];
|
|
94
|
+
nk_u64_t intersection_high = a.u64s[1] & b.u64s[1];
|
|
95
|
+
state->intersection_count += nk_u64_popcount_(intersection_low);
|
|
96
|
+
state->intersection_count += nk_u64_popcount_(intersection_high);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
NK_INTERNAL void nk_jaccard_u1x128_finalize_serial( //
|
|
100
|
+
nk_jaccard_u1x128_state_serial_t const *state_a, nk_jaccard_u1x128_state_serial_t const *state_b,
|
|
101
|
+
nk_jaccard_u1x128_state_serial_t const *state_c, nk_jaccard_u1x128_state_serial_t const *state_d,
|
|
102
|
+
nk_f32_t query_popcount, nk_f32_t target_popcount_a, nk_f32_t target_popcount_b, nk_f32_t target_popcount_c,
|
|
103
|
+
nk_f32_t target_popcount_d, nk_size_t total_dimensions, nk_b128_vec_t *result) {
|
|
104
|
+
nk_unused_(total_dimensions);
|
|
105
|
+
|
|
106
|
+
nk_f32_t intersection_a = (nk_f32_t)state_a->intersection_count;
|
|
107
|
+
nk_f32_t intersection_b = (nk_f32_t)state_b->intersection_count;
|
|
108
|
+
nk_f32_t intersection_c = (nk_f32_t)state_c->intersection_count;
|
|
109
|
+
nk_f32_t intersection_d = (nk_f32_t)state_d->intersection_count;
|
|
110
|
+
|
|
111
|
+
nk_f32_t union_a = query_popcount + target_popcount_a - intersection_a;
|
|
112
|
+
nk_f32_t union_b = query_popcount + target_popcount_b - intersection_b;
|
|
113
|
+
nk_f32_t union_c = query_popcount + target_popcount_c - intersection_c;
|
|
114
|
+
nk_f32_t union_d = query_popcount + target_popcount_d - intersection_d;
|
|
115
|
+
|
|
116
|
+
result->f32s[0] = (union_a != 0) ? 1.0f - intersection_a / union_a : 0.0f;
|
|
117
|
+
result->f32s[1] = (union_b != 0) ? 1.0f - intersection_b / union_b : 0.0f;
|
|
118
|
+
result->f32s[2] = (union_c != 0) ? 1.0f - intersection_c / union_c : 0.0f;
|
|
119
|
+
result->f32s[3] = (union_d != 0) ? 1.0f - intersection_d / union_d : 0.0f;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
typedef struct nk_hamming_u1x128_state_serial_t {
|
|
123
|
+
nk_u64_t intersection_count;
|
|
124
|
+
} nk_hamming_u1x128_state_serial_t;
|
|
125
|
+
|
|
126
|
+
NK_INTERNAL void nk_hamming_u1x128_init_serial(nk_hamming_u1x128_state_serial_t *state) {
|
|
127
|
+
state->intersection_count = 0;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
NK_INTERNAL void nk_hamming_u1x128_update_serial(nk_hamming_u1x128_state_serial_t *state, nk_b128_vec_t a,
|
|
131
|
+
nk_b128_vec_t b, nk_size_t depth_offset, nk_size_t active_dimensions) {
|
|
132
|
+
nk_unused_(depth_offset);
|
|
133
|
+
nk_unused_(active_dimensions);
|
|
134
|
+
nk_u64_t intersection_low = a.u64s[0] ^ b.u64s[0];
|
|
135
|
+
nk_u64_t intersection_high = a.u64s[1] ^ b.u64s[1];
|
|
136
|
+
state->intersection_count += nk_u64_popcount_(intersection_low);
|
|
137
|
+
state->intersection_count += nk_u64_popcount_(intersection_high);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
NK_INTERNAL void nk_hamming_u1x128_finalize_serial( //
|
|
141
|
+
nk_hamming_u1x128_state_serial_t const *state_a, nk_hamming_u1x128_state_serial_t const *state_b,
|
|
142
|
+
nk_hamming_u1x128_state_serial_t const *state_c, nk_hamming_u1x128_state_serial_t const *state_d,
|
|
143
|
+
nk_size_t total_dimensions, nk_b128_vec_t *result) {
|
|
144
|
+
nk_unused_(total_dimensions);
|
|
145
|
+
|
|
146
|
+
result->u32s[0] = (nk_u32_t)state_a->intersection_count;
|
|
147
|
+
result->u32s[1] = (nk_u32_t)state_b->intersection_count;
|
|
148
|
+
result->u32s[2] = (nk_u32_t)state_c->intersection_count;
|
|
149
|
+
result->u32s[3] = (nk_u32_t)state_d->intersection_count;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** @brief Hamming from_dot: computes pop_a + pop_b - 2*dot for 4 pairs (serial). */
|
|
153
|
+
NK_INTERNAL void nk_hamming_u32x4_from_dot_serial_(nk_b128_vec_t dots, nk_u32_t query_pop, nk_b128_vec_t target_pops,
|
|
154
|
+
nk_b128_vec_t *results) {
|
|
155
|
+
for (int i = 0; i < 4; ++i) results->u32s[i] = query_pop + target_pops.u32s[i] - 2 * dots.u32s[i];
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/** @brief Jaccard from_dot: computes 1 - dot / (pop_a + pop_b - dot) for 4 pairs (serial). */
|
|
159
|
+
NK_INTERNAL void nk_jaccard_f32x4_from_dot_serial_(nk_b128_vec_t dots, nk_u32_t query_pop, nk_b128_vec_t target_pops,
|
|
160
|
+
nk_b128_vec_t *results) {
|
|
161
|
+
for (int i = 0; i < 4; ++i) {
|
|
162
|
+
nk_f32_t dot = (nk_f32_t)dots.u32s[i];
|
|
163
|
+
nk_f32_t union_val = (nk_f32_t)query_pop + (nk_f32_t)target_pops.u32s[i] - dot;
|
|
164
|
+
results->f32s[i] = (union_val != 0) ? 1.0f - dot / union_val : 0.0f;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
#pragma endregion - Stateful Streaming
|
|
169
|
+
|
|
170
|
+
#if defined(__cplusplus)
|
|
171
|
+
} // extern "C"
|
|
172
|
+
#endif
|
|
173
|
+
|
|
174
|
+
#endif // NK_SET_SERIAL_H
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @brief SIMD-accelerated Set Similarity Measures for SVE.
|
|
3
|
+
* @file include/numkong/set/sve.h
|
|
4
|
+
* @author Ash Vardanian
|
|
5
|
+
* @date December 27, 2025
|
|
6
|
+
*
|
|
7
|
+
* @sa include/numkong/set.h
|
|
8
|
+
*
|
|
9
|
+
* @section set_sve_instructions ARM SVE Instructions
|
|
10
|
+
*
|
|
11
|
+
* Intrinsic Instruction Latency Throughput
|
|
12
|
+
* svld1_u8 LD1B (Z.B, P/Z, [Xn]) 4-6cy 2/cy
|
|
13
|
+
* svld1_u32 LD1W (Z.S, P/Z, [Xn]) 4-6cy 2/cy
|
|
14
|
+
* sveor_u8_m EOR (Z.B, P/M, Z.B, Z.B) 1cy 2/cy
|
|
15
|
+
* svand_u8_m AND (Z.B, P/M, Z.B, Z.B) 1cy 2/cy
|
|
16
|
+
* svorr_u8_m ORR (Z.B, P/M, Z.B, Z.B) 1cy 2/cy
|
|
17
|
+
* svcnt_u8_x CNT (Z.B, P/M, Z.B) 2cy 2/cy
|
|
18
|
+
* svadd_u8_z ADD (Z.B, P/M, Z.B, Z.B) 1cy 2/cy
|
|
19
|
+
* svaddv_u8 UADDV (D, P, Z.B) 6cy 1/cy
|
|
20
|
+
* svcmpeq_u32 CMPEQ (P.S, P/Z, Z.S, Z.S) 2cy 1/cy
|
|
21
|
+
* svcntp_b32 CNTP (Xd, P, P.S) 2cy 1/cy
|
|
22
|
+
* svdup_n_u8 DUP (Z.B, #imm) 1cy 2/cy
|
|
23
|
+
* svwhilelt_b8 WHILELT (P.B, Xn, Xm) 2cy 1/cy
|
|
24
|
+
* svwhilelt_b32 WHILELT (P.S, Xn, Xm) 2cy 1/cy
|
|
25
|
+
* svptrue_b8 PTRUE (P.B, pattern) 1cy 2/cy
|
|
26
|
+
* svcntb CNTB (Xd) 1cy 2/cy
|
|
27
|
+
* svcntw CNTW (Xd) 1cy 2/cy
|
|
28
|
+
*/
|
|
29
|
+
#ifndef NK_SET_SVE_H
|
|
30
|
+
#define NK_SET_SVE_H
|
|
31
|
+
|
|
32
|
+
#if NK_TARGET_ARM_
|
|
33
|
+
#if NK_TARGET_SVE
|
|
34
|
+
|
|
35
|
+
#include "numkong/types.h" // `nk_u1x8_t`
|
|
36
|
+
#include "numkong/set/neon.h" // `nk_hamming_u1_neon`
|
|
37
|
+
|
|
38
|
+
#if defined(__cplusplus)
|
|
39
|
+
extern "C" {
|
|
40
|
+
#endif
|
|
41
|
+
|
|
42
|
+
#if defined(__clang__)
|
|
43
|
+
#pragma clang attribute push(__attribute__((target("arch=armv8.2-a+sve"))), apply_to = function)
|
|
44
|
+
#elif defined(__GNUC__)
|
|
45
|
+
#pragma GCC push_options
|
|
46
|
+
#pragma GCC target("arch=armv8.2-a+sve")
|
|
47
|
+
#endif
|
|
48
|
+
|
|
49
|
+
#pragma region - Binary Sets
|
|
50
|
+
|
|
51
|
+
NK_PUBLIC void nk_hamming_u1_sve(nk_u1x8_t const *a, nk_u1x8_t const *b, nk_size_t n, nk_u32_t *result) {
|
|
52
|
+
nk_size_t n_bytes = nk_size_divide_round_up_(n, NK_BITS_PER_BYTE);
|
|
53
|
+
|
|
54
|
+
// On very small register sizes, NEON is at least as fast as SVE.
|
|
55
|
+
nk_size_t const words_per_register = svcntb();
|
|
56
|
+
if (words_per_register <= 32) {
|
|
57
|
+
nk_hamming_u1_neon(a, b, n, result);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// On larger register sizes, SVE is faster.
|
|
62
|
+
nk_size_t i = 0, cycle = 0;
|
|
63
|
+
nk_u32_t differences = 0;
|
|
64
|
+
svuint8_t popcount_u8 = svdup_n_u8(0);
|
|
65
|
+
svbool_t const all_predicate = svptrue_b8();
|
|
66
|
+
while (i < n_bytes) {
|
|
67
|
+
do {
|
|
68
|
+
svbool_t active_predicate = svwhilelt_b8_u64(i, n_bytes);
|
|
69
|
+
svuint8_t a_u8 = svld1_u8(active_predicate, a + i);
|
|
70
|
+
svuint8_t b_u8 = svld1_u8(active_predicate, b + i);
|
|
71
|
+
popcount_u8 = svadd_u8_z(all_predicate, popcount_u8,
|
|
72
|
+
svcnt_u8_x(all_predicate, sveor_u8_m(all_predicate, a_u8, b_u8)));
|
|
73
|
+
i += words_per_register;
|
|
74
|
+
++cycle;
|
|
75
|
+
} while (i < n_bytes && cycle < 31);
|
|
76
|
+
differences += svaddv_u8(all_predicate, popcount_u8);
|
|
77
|
+
popcount_u8 = svdup_n_u8(0);
|
|
78
|
+
cycle = 0; // Reset the cycle counter.
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
*result = differences;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
NK_PUBLIC void nk_jaccard_u1_sve(nk_u1x8_t const *a, nk_u1x8_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
85
|
+
nk_size_t n_bytes = nk_size_divide_round_up_(n, NK_BITS_PER_BYTE);
|
|
86
|
+
|
|
87
|
+
// On very small register sizes, NEON is at least as fast as SVE.
|
|
88
|
+
nk_size_t const words_per_register = svcntb();
|
|
89
|
+
if (words_per_register <= 32) {
|
|
90
|
+
nk_jaccard_u1_neon(a, b, n, result);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// On larger register sizes, SVE is faster.
|
|
95
|
+
nk_size_t i = 0, cycle = 0;
|
|
96
|
+
nk_u32_t intersection_count = 0, union_count = 0;
|
|
97
|
+
svuint8_t intersection_popcount_u8 = svdup_n_u8(0);
|
|
98
|
+
svuint8_t union_popcount_u8 = svdup_n_u8(0);
|
|
99
|
+
svbool_t const all_predicate = svptrue_b8();
|
|
100
|
+
while (i < n_bytes) {
|
|
101
|
+
do {
|
|
102
|
+
svbool_t active_predicate = svwhilelt_b8_u64(i, n_bytes);
|
|
103
|
+
svuint8_t a_u8 = svld1_u8(active_predicate, a + i);
|
|
104
|
+
svuint8_t b_u8 = svld1_u8(active_predicate, b + i);
|
|
105
|
+
intersection_popcount_u8 = svadd_u8_z(all_predicate, intersection_popcount_u8,
|
|
106
|
+
svcnt_u8_x(all_predicate, svand_u8_m(all_predicate, a_u8, b_u8)));
|
|
107
|
+
union_popcount_u8 = svadd_u8_z(all_predicate, union_popcount_u8,
|
|
108
|
+
svcnt_u8_x(all_predicate, svorr_u8_m(all_predicate, a_u8, b_u8)));
|
|
109
|
+
i += words_per_register;
|
|
110
|
+
++cycle;
|
|
111
|
+
} while (i < n_bytes && cycle < 31);
|
|
112
|
+
intersection_count += svaddv_u8(all_predicate, intersection_popcount_u8);
|
|
113
|
+
intersection_popcount_u8 = svdup_n_u8(0);
|
|
114
|
+
union_count += svaddv_u8(all_predicate, union_popcount_u8);
|
|
115
|
+
union_popcount_u8 = svdup_n_u8(0);
|
|
116
|
+
cycle = 0; // Reset the cycle counter.
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
*result = (union_count != 0) ? 1.0f - (nk_f32_t)intersection_count / (nk_f32_t)union_count : 0.0f;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
#pragma endregion - Binary Sets
|
|
123
|
+
|
|
124
|
+
#pragma region - Integer Sets
|
|
125
|
+
|
|
126
|
+
NK_PUBLIC void nk_jaccard_u32_sve(nk_u32_t const *a, nk_u32_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
127
|
+
nk_size_t const words_per_register = svcntw();
|
|
128
|
+
nk_size_t i = 0;
|
|
129
|
+
nk_u32_t intersection_count = 0;
|
|
130
|
+
while (i < n) {
|
|
131
|
+
svbool_t active_predicate = svwhilelt_b32_u64(i, n);
|
|
132
|
+
svuint32_t a_u32 = svld1_u32(active_predicate, a + i);
|
|
133
|
+
svuint32_t b_u32 = svld1_u32(active_predicate, b + i);
|
|
134
|
+
svbool_t equality_predicate = svcmpeq_u32(active_predicate, a_u32, b_u32);
|
|
135
|
+
intersection_count += svcntp_b32(active_predicate, equality_predicate);
|
|
136
|
+
i += words_per_register;
|
|
137
|
+
}
|
|
138
|
+
*result = (n != 0) ? 1.0f - (nk_f32_t)intersection_count / (nk_f32_t)n : 0.0f;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
NK_PUBLIC void nk_hamming_u8_sve(nk_u8_t const *a, nk_u8_t const *b, nk_size_t n, nk_u32_t *result) {
|
|
142
|
+
nk_size_t const bytes_per_register = svcntb();
|
|
143
|
+
nk_size_t i = 0;
|
|
144
|
+
nk_u32_t differences = 0;
|
|
145
|
+
while (i < n) {
|
|
146
|
+
svbool_t active_predicate = svwhilelt_b8_u64(i, n);
|
|
147
|
+
svuint8_t a_u8 = svld1_u8(active_predicate, a + i);
|
|
148
|
+
svuint8_t b_u8 = svld1_u8(active_predicate, b + i);
|
|
149
|
+
svbool_t neq_predicate = svcmpne_u8(active_predicate, a_u8, b_u8);
|
|
150
|
+
differences += svcntp_b8(active_predicate, neq_predicate);
|
|
151
|
+
i += bytes_per_register;
|
|
152
|
+
}
|
|
153
|
+
*result = differences;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
NK_PUBLIC void nk_jaccard_u16_sve(nk_u16_t const *a, nk_u16_t const *b, nk_size_t n, nk_f32_t *result) {
|
|
157
|
+
nk_size_t const halfwords_per_register = svcnth();
|
|
158
|
+
nk_size_t i = 0;
|
|
159
|
+
nk_u32_t intersection_count = 0;
|
|
160
|
+
while (i < n) {
|
|
161
|
+
svbool_t active_predicate = svwhilelt_b16_u64(i, n);
|
|
162
|
+
svuint16_t a_u16 = svld1_u16(active_predicate, a + i);
|
|
163
|
+
svuint16_t b_u16 = svld1_u16(active_predicate, b + i);
|
|
164
|
+
svbool_t equality_predicate = svcmpeq_u16(active_predicate, a_u16, b_u16);
|
|
165
|
+
intersection_count += svcntp_b16(active_predicate, equality_predicate);
|
|
166
|
+
i += halfwords_per_register;
|
|
167
|
+
}
|
|
168
|
+
*result = (n != 0) ? 1.0f - (nk_f32_t)intersection_count / (nk_f32_t)n : 0.0f;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
#pragma endregion - Integer Sets
|
|
172
|
+
|
|
173
|
+
#if defined(__clang__)
|
|
174
|
+
#pragma clang attribute pop
|
|
175
|
+
#elif defined(__GNUC__)
|
|
176
|
+
#pragma GCC pop_options
|
|
177
|
+
#endif
|
|
178
|
+
|
|
179
|
+
#if defined(__cplusplus)
|
|
180
|
+
} // extern "C"
|
|
181
|
+
#endif
|
|
182
|
+
|
|
183
|
+
#endif // NK_TARGET_SVE
|
|
184
|
+
#endif // NK_TARGET_ARM_
|
|
185
|
+
#endif // NK_SET_SVE_H
|