usearch 2.26.0 → 2.26.2

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.
Files changed (148) hide show
  1. package/README.md +2 -2
  2. package/cpp/test.cpp +66 -3
  3. package/include/usearch/index.hpp +9 -1
  4. package/include/usearch/index_dense.hpp +16 -5
  5. package/numkong/CITATION.cff +13 -9
  6. package/numkong/CONTRIBUTING.md +29 -24
  7. package/numkong/Cargo.toml +1 -1
  8. package/numkong/README.md +21 -7
  9. package/numkong/binding.gyp +47 -31
  10. package/numkong/build.rs +15 -5
  11. package/numkong/c/dispatch.h +0 -1
  12. package/numkong/c/parallel.c +139 -0
  13. package/numkong/c/parallel.h +47 -0
  14. package/numkong/cmake/toolchain-wasi.cmake +39 -5
  15. package/numkong/include/README.md +24 -17
  16. package/numkong/include/numkong/attention/sapphireamx.h +6 -6
  17. package/numkong/include/numkong/attention/sme.h +2 -2
  18. package/numkong/include/numkong/capabilities.h +2 -2
  19. package/numkong/include/numkong/cast/README.md +9 -7
  20. package/numkong/include/numkong/cast/loongsonasx.h +48 -40
  21. package/numkong/include/numkong/cast/serial.h +89 -11
  22. package/numkong/include/numkong/cast.h +3 -3
  23. package/numkong/include/numkong/curved/README.md +10 -10
  24. package/numkong/include/numkong/curved/neon.h +1 -0
  25. package/numkong/include/numkong/curved/neonbfdot.h +1 -0
  26. package/numkong/include/numkong/curved/smef64.h +1 -0
  27. package/numkong/include/numkong/dot/README.md +18 -18
  28. package/numkong/include/numkong/dot/alder.h +8 -8
  29. package/numkong/include/numkong/dot/haswell.h +8 -8
  30. package/numkong/include/numkong/dot/icelake.h +12 -12
  31. package/numkong/include/numkong/dot/loongsonasx.h +6 -6
  32. package/numkong/include/numkong/dot/neon.h +2 -1
  33. package/numkong/include/numkong/dot/neonbfdot.h +1 -0
  34. package/numkong/include/numkong/dot/neonfhm.h +1 -0
  35. package/numkong/include/numkong/dot/neonsdot.h +1 -0
  36. package/numkong/include/numkong/dot/powervsx.h +3 -3
  37. package/numkong/include/numkong/dot/serial.h +19 -6
  38. package/numkong/include/numkong/dot/skylake.h +4 -4
  39. package/numkong/include/numkong/dot/svehalf.h +1 -1
  40. package/numkong/include/numkong/dot/v128relaxed.h +24 -23
  41. package/numkong/include/numkong/dots/README.md +26 -26
  42. package/numkong/include/numkong/dots/genoa.h +3 -1
  43. package/numkong/include/numkong/dots/icelake.h +1 -0
  44. package/numkong/include/numkong/dots/powervsx.h +1 -1
  45. package/numkong/include/numkong/dots/serial.h +32 -33
  46. package/numkong/include/numkong/dots/sierra.h +4 -3
  47. package/numkong/include/numkong/each/README.md +5 -3
  48. package/numkong/include/numkong/each/sapphire.h +2 -0
  49. package/numkong/include/numkong/each/skylake.h +1 -0
  50. package/numkong/include/numkong/geospatial/README.md +6 -6
  51. package/numkong/include/numkong/geospatial/v128relaxed.h +1 -0
  52. package/numkong/include/numkong/maxsim/README.md +5 -5
  53. package/numkong/include/numkong/maxsim/genoa.h +4 -0
  54. package/numkong/include/numkong/maxsim/icelake.h +1 -0
  55. package/numkong/include/numkong/maxsim/serial.h +22 -9
  56. package/numkong/include/numkong/maxsim/sme.h +3 -2
  57. package/numkong/include/numkong/mesh/README.md +7 -4
  58. package/numkong/include/numkong/mesh/genoa.h +2 -2
  59. package/numkong/include/numkong/mesh/haswell.h +8 -8
  60. package/numkong/include/numkong/mesh/neon.h +6 -6
  61. package/numkong/include/numkong/mesh/neonbfdot.h +3 -2
  62. package/numkong/include/numkong/mesh/neonfhm.h +3 -2
  63. package/numkong/include/numkong/mesh/rvv.h +4 -4
  64. package/numkong/include/numkong/mesh/serial.h +17 -17
  65. package/numkong/include/numkong/mesh/skylake.h +4 -4
  66. package/numkong/include/numkong/mesh/v128relaxed.h +4 -4
  67. package/numkong/include/numkong/mesh.hpp +2 -2
  68. package/numkong/include/numkong/numkong.h +1 -1
  69. package/numkong/include/numkong/numkong.hpp +1 -1
  70. package/numkong/include/numkong/probability/README.md +17 -15
  71. package/numkong/include/numkong/probability/skylake.h +1 -1
  72. package/numkong/include/numkong/reduce/README.md +27 -21
  73. package/numkong/include/numkong/reduce/genoa.h +2 -1
  74. package/numkong/include/numkong/reduce/icelake.h +1 -0
  75. package/numkong/include/numkong/reduce/neon.h +1 -1
  76. package/numkong/include/numkong/reduce/serial.h +9 -9
  77. package/numkong/include/numkong/reduce/skylake.h +4 -4
  78. package/numkong/include/numkong/reduce.hpp +38 -0
  79. package/numkong/include/numkong/scalar/README.md +29 -28
  80. package/numkong/include/numkong/set/README.md +17 -14
  81. package/numkong/include/numkong/set/haswell.h +15 -16
  82. package/numkong/include/numkong/set/icelake.h +15 -16
  83. package/numkong/include/numkong/set/loongsonasx.h +12 -10
  84. package/numkong/include/numkong/set/neon.h +15 -19
  85. package/numkong/include/numkong/set/powervsx.h +15 -21
  86. package/numkong/include/numkong/set/serial.h +19 -20
  87. package/numkong/include/numkong/set/v128relaxed.h +10 -8
  88. package/numkong/include/numkong/sets/icelake.h +1 -0
  89. package/numkong/include/numkong/sparse/README.md +4 -4
  90. package/numkong/include/numkong/sparse/icelake.h +1 -0
  91. package/numkong/include/numkong/sparse/neon.h +1 -0
  92. package/numkong/include/numkong/sparse/serial.h +10 -3
  93. package/numkong/include/numkong/sparse/turin.h +1 -0
  94. package/numkong/include/numkong/spatial/README.md +25 -24
  95. package/numkong/include/numkong/spatial/alder.h +2 -1
  96. package/numkong/include/numkong/spatial/haswell.h +48 -40
  97. package/numkong/include/numkong/spatial/icelake.h +2 -1
  98. package/numkong/include/numkong/spatial/neon.h +54 -46
  99. package/numkong/include/numkong/spatial/neonbfdot.h +1 -1
  100. package/numkong/include/numkong/spatial/powervsx.h +54 -46
  101. package/numkong/include/numkong/spatial/serial.h +56 -46
  102. package/numkong/include/numkong/spatial/sierra.h +4 -3
  103. package/numkong/include/numkong/spatial/skylake.h +27 -22
  104. package/numkong/include/numkong/spatial/sve.h +6 -6
  105. package/numkong/include/numkong/spatial/svebfdot.h +1 -1
  106. package/numkong/include/numkong/spatial/svehalf.h +1 -1
  107. package/numkong/include/numkong/spatial/v128relaxed.h +36 -30
  108. package/numkong/include/numkong/spatials/README.md +15 -15
  109. package/numkong/include/numkong/spatials/genoa.h +3 -0
  110. package/numkong/include/numkong/spatials/graniteamx.h +2 -0
  111. package/numkong/include/numkong/spatials/icelake.h +1 -0
  112. package/numkong/include/numkong/spatials/sierra.h +1 -0
  113. package/numkong/include/numkong/tensor.hpp +236 -123
  114. package/numkong/include/numkong/trigonometry/README.md +4 -4
  115. package/numkong/include/numkong/trigonometry/serial.h +6 -6
  116. package/numkong/include/numkong/trigonometry/v128relaxed.h +1 -0
  117. package/numkong/include/numkong/types.hpp +46 -16
  118. package/numkong/include/numkong/vector.hpp +116 -23
  119. package/numkong/javascript/@numkong-darwin-arm64/package.json +1 -1
  120. package/numkong/javascript/@numkong-darwin-x64/package.json +1 -1
  121. package/numkong/javascript/@numkong-linux-arm64/package.json +1 -1
  122. package/numkong/javascript/@numkong-linux-x64/package.json +1 -1
  123. package/numkong/javascript/@numkong-win32-arm64/package.json +1 -1
  124. package/numkong/javascript/@numkong-win32-x64/package.json +1 -1
  125. package/numkong/javascript/README.md +18 -16
  126. package/numkong/javascript/numkong.c +70 -40
  127. package/numkong/package.json +8 -8
  128. package/numkong/rust/README.md +19 -9
  129. package/numkong/rust/cast.rs +52 -1
  130. package/numkong/rust/each.rs +480 -7
  131. package/numkong/rust/matrix.rs +877 -216
  132. package/numkong/rust/numkong.rs +12 -8
  133. package/numkong/rust/reduce.rs +433 -5
  134. package/numkong/rust/tensor.rs +450 -842
  135. package/numkong/rust/vector.rs +520 -101
  136. package/numkong/swift/README.md +5 -3
  137. package/numkong/test/README.md +4 -4
  138. package/numkong/test/test-wasi.mjs +17 -0
  139. package/numkong/test/test_each.cpp +30 -1
  140. package/numkong/test/test_each.py +74 -1
  141. package/numkong/test/test_reduce.cpp +51 -0
  142. package/numkong/test/test_tensor.cpp +2 -63
  143. package/numkong/test/test_tensor.py +93 -0
  144. package/package.json +1 -1
  145. package/prebuilds/darwin-arm64+x64/usearch.node +0 -0
  146. package/prebuilds/linux-arm64/usearch.node +0 -0
  147. package/prebuilds/linux-x64/usearch.node +0 -0
  148. package/prebuilds/win32-x64/usearch.node +0 -0
@@ -670,13 +670,14 @@ nk_angular_e5m2_neon_cycle:
670
670
  }
671
671
 
672
672
  /** @brief Angular from_dot: computes 1 − dot × rsqrt(query_sumsq × target_sumsq) for 4 pairs in f64. */
673
- NK_INTERNAL void nk_angular_through_f64_from_dot_neon_(nk_b256_vec_t dots, nk_f64_t query_sumsq,
674
- nk_b256_vec_t target_sumsqs, nk_b256_vec_t *results) {
675
- float64x2_t dots_ab_f64x2 = dots.f64x2s[0];
676
- float64x2_t dots_cd_f64x2 = dots.f64x2s[1];
673
+ NK_INTERNAL void nk_angular_through_f64_from_dot_neon_(nk_b256_vec_t const *dots_vec, nk_f64_t query_sumsq,
674
+ nk_b256_vec_t const *target_sumsqs_vec,
675
+ nk_b256_vec_t *result_vec) {
676
+ float64x2_t dots_ab_f64x2 = dots_vec->f64x2s[0];
677
+ float64x2_t dots_cd_f64x2 = dots_vec->f64x2s[1];
677
678
  float64x2_t query_sumsq_f64x2 = vdupq_n_f64(query_sumsq);
678
- float64x2_t target_sumsqs_ab_f64x2 = target_sumsqs.f64x2s[0];
679
- float64x2_t target_sumsqs_cd_f64x2 = target_sumsqs.f64x2s[1];
679
+ float64x2_t target_sumsqs_ab_f64x2 = target_sumsqs_vec->f64x2s[0];
680
+ float64x2_t target_sumsqs_cd_f64x2 = target_sumsqs_vec->f64x2s[1];
680
681
 
681
682
  // products = query_sumsq * target_sumsq
682
683
  float64x2_t products_ab_f64x2 = vmulq_f64(query_sumsq_f64x2, target_sumsqs_ab_f64x2);
@@ -723,18 +724,19 @@ NK_INTERNAL void nk_angular_through_f64_from_dot_neon_(nk_b256_vec_t dots, nk_f6
723
724
  result_ab_f64x2 = vbslq_f64(prod_zero_dot_nonzero_ab_u64x2, ones_f64x2, result_ab_f64x2);
724
725
  result_cd_f64x2 = vbslq_f64(prod_zero_dot_nonzero_cd_u64x2, ones_f64x2, result_cd_f64x2);
725
726
 
726
- results->f64x2s[0] = result_ab_f64x2;
727
- results->f64x2s[1] = result_cd_f64x2;
727
+ result_vec->f64x2s[0] = result_ab_f64x2;
728
+ result_vec->f64x2s[1] = result_cd_f64x2;
728
729
  }
729
730
 
730
731
  /** @brief Euclidean from_dot: computes √(query_sumsq + target_sumsq − 2 × dot) for 4 pairs in f64. */
731
- NK_INTERNAL void nk_euclidean_through_f64_from_dot_neon_(nk_b256_vec_t dots, nk_f64_t query_sumsq,
732
- nk_b256_vec_t target_sumsqs, nk_b256_vec_t *results) {
733
- float64x2_t dots_ab_f64x2 = dots.f64x2s[0];
734
- float64x2_t dots_cd_f64x2 = dots.f64x2s[1];
732
+ NK_INTERNAL void nk_euclidean_through_f64_from_dot_neon_(nk_b256_vec_t const *dots_vec, nk_f64_t query_sumsq,
733
+ nk_b256_vec_t const *target_sumsqs_vec,
734
+ nk_b256_vec_t *result_vec) {
735
+ float64x2_t dots_ab_f64x2 = dots_vec->f64x2s[0];
736
+ float64x2_t dots_cd_f64x2 = dots_vec->f64x2s[1];
735
737
  float64x2_t query_sumsq_f64x2 = vdupq_n_f64(query_sumsq);
736
- float64x2_t target_sumsqs_ab_f64x2 = target_sumsqs.f64x2s[0];
737
- float64x2_t target_sumsqs_cd_f64x2 = target_sumsqs.f64x2s[1];
738
+ float64x2_t target_sumsqs_ab_f64x2 = target_sumsqs_vec->f64x2s[0];
739
+ float64x2_t target_sumsqs_cd_f64x2 = target_sumsqs_vec->f64x2s[1];
738
740
 
739
741
  // dist_sq = query_sumsq + target_sumsq − 2 × dot
740
742
  float64x2_t neg_two_f64x2 = vdupq_n_f64(-2.0);
@@ -750,16 +752,17 @@ NK_INTERNAL void nk_euclidean_through_f64_from_dot_neon_(nk_b256_vec_t dots, nk_
750
752
  float64x2_t dist_ab_f64x2 = vsqrtq_f64(dist_sq_ab_f64x2);
751
753
  float64x2_t dist_cd_f64x2 = vsqrtq_f64(dist_sq_cd_f64x2);
752
754
 
753
- results->f64x2s[0] = dist_ab_f64x2;
754
- results->f64x2s[1] = dist_cd_f64x2;
755
+ result_vec->f64x2s[0] = dist_ab_f64x2;
756
+ result_vec->f64x2s[1] = dist_cd_f64x2;
755
757
  }
756
758
 
757
759
  /** @brief Angular from_dot: computes 1 − dot × rsqrt(query_sumsq × target_sumsq) for 4 pairs in f32. */
758
- NK_INTERNAL void nk_angular_through_f32_from_dot_neon_(nk_b128_vec_t dots, nk_f32_t query_sumsq,
759
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
760
- float32x4_t dots_f32x4 = dots.f32x4;
760
+ NK_INTERNAL void nk_angular_through_f32_from_dot_neon_(nk_b128_vec_t const *dots_vec, nk_f32_t query_sumsq,
761
+ nk_b128_vec_t const *target_sumsqs_vec,
762
+ nk_b128_vec_t *result_vec) {
763
+ float32x4_t dots_f32x4 = dots_vec->f32x4;
761
764
  float32x4_t query_sumsq_f32x4 = vdupq_n_f32(query_sumsq);
762
- float32x4_t products_f32x4 = vmulq_f32(query_sumsq_f32x4, target_sumsqs.f32x4);
765
+ float32x4_t products_f32x4 = vmulq_f32(query_sumsq_f32x4, target_sumsqs_vec->f32x4);
763
766
 
764
767
  // rsqrt with Newton-Raphson refinement (2 iterations)
765
768
  float32x4_t rsqrt_f32x4 = vrsqrteq_f32(products_f32x4);
@@ -768,66 +771,71 @@ NK_INTERNAL void nk_angular_through_f32_from_dot_neon_(nk_b128_vec_t dots, nk_f3
768
771
 
769
772
  float32x4_t normalized_f32x4 = vmulq_f32(dots_f32x4, rsqrt_f32x4);
770
773
  float32x4_t angular_f32x4 = vsubq_f32(vdupq_n_f32(1.0f), normalized_f32x4);
771
- results->f32x4 = vmaxq_f32(angular_f32x4, vdupq_n_f32(0.0f));
774
+ result_vec->f32x4 = vmaxq_f32(angular_f32x4, vdupq_n_f32(0.0f));
772
775
  }
773
776
 
774
777
  /** @brief Euclidean from_dot: computes √(query_sumsq + target_sumsq − 2 × dot) for 4 pairs in f32. */
775
- NK_INTERNAL void nk_euclidean_through_f32_from_dot_neon_(nk_b128_vec_t dots, nk_f32_t query_sumsq,
776
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
777
- float32x4_t dots_f32x4 = dots.f32x4;
778
+ NK_INTERNAL void nk_euclidean_through_f32_from_dot_neon_(nk_b128_vec_t const *dots_vec, nk_f32_t query_sumsq,
779
+ nk_b128_vec_t const *target_sumsqs_vec,
780
+ nk_b128_vec_t *result_vec) {
781
+ float32x4_t dots_f32x4 = dots_vec->f32x4;
778
782
  float32x4_t query_sumsq_f32x4 = vdupq_n_f32(query_sumsq);
779
- float32x4_t sum_sq_f32x4 = vaddq_f32(query_sumsq_f32x4, target_sumsqs.f32x4);
783
+ float32x4_t sum_sq_f32x4 = vaddq_f32(query_sumsq_f32x4, target_sumsqs_vec->f32x4);
780
784
  // dist_sq = sum_sq − 2 × dot
781
785
  float32x4_t dist_sq_f32x4 = vfmsq_f32(sum_sq_f32x4, vdupq_n_f32(2.0f), dots_f32x4);
782
786
  // Clamp and sqrt
783
787
  dist_sq_f32x4 = vmaxq_f32(dist_sq_f32x4, vdupq_n_f32(0.0f));
784
- results->f32x4 = vsqrtq_f32(dist_sq_f32x4);
788
+ result_vec->f32x4 = vsqrtq_f32(dist_sq_f32x4);
785
789
  }
786
790
 
787
791
  /** @brief Angular from_dot for i32 accumulators: cast to f32, rsqrt+NR, clamp. 4 pairs. */
788
- NK_INTERNAL void nk_angular_through_i32_from_dot_neon_(nk_b128_vec_t dots, nk_i32_t query_sumsq,
789
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
790
- float32x4_t dots_f32x4 = vcvtq_f32_s32(dots.i32x4);
792
+ NK_INTERNAL void nk_angular_through_i32_from_dot_neon_(nk_b128_vec_t const *dots_vec, nk_i32_t query_sumsq,
793
+ nk_b128_vec_t const *target_sumsqs_vec,
794
+ nk_b128_vec_t *result_vec) {
795
+ float32x4_t dots_f32x4 = vcvtq_f32_s32(dots_vec->i32x4);
791
796
  float32x4_t query_sumsq_f32x4 = vdupq_n_f32((nk_f32_t)query_sumsq);
792
- float32x4_t products_f32x4 = vmulq_f32(query_sumsq_f32x4, vcvtq_f32_s32(target_sumsqs.i32x4));
797
+ float32x4_t products_f32x4 = vmulq_f32(query_sumsq_f32x4, vcvtq_f32_s32(target_sumsqs_vec->i32x4));
793
798
  float32x4_t rsqrt_f32x4 = nk_rsqrt_f32x4_neon_(products_f32x4);
794
799
  float32x4_t normalized_f32x4 = vmulq_f32(dots_f32x4, rsqrt_f32x4);
795
800
  float32x4_t angular_f32x4 = vsubq_f32(vdupq_n_f32(1.0f), normalized_f32x4);
796
- results->f32x4 = vmaxq_f32(angular_f32x4, vdupq_n_f32(0.0f));
801
+ result_vec->f32x4 = vmaxq_f32(angular_f32x4, vdupq_n_f32(0.0f));
797
802
  }
798
803
 
799
804
  /** @brief Euclidean from_dot for i32 accumulators: cast to f32, then √(a² + b² − 2ab). 4 pairs. */
800
- NK_INTERNAL void nk_euclidean_through_i32_from_dot_neon_(nk_b128_vec_t dots, nk_i32_t query_sumsq,
801
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
802
- float32x4_t dots_f32x4 = vcvtq_f32_s32(dots.i32x4);
805
+ NK_INTERNAL void nk_euclidean_through_i32_from_dot_neon_(nk_b128_vec_t const *dots_vec, nk_i32_t query_sumsq,
806
+ nk_b128_vec_t const *target_sumsqs_vec,
807
+ nk_b128_vec_t *result_vec) {
808
+ float32x4_t dots_f32x4 = vcvtq_f32_s32(dots_vec->i32x4);
803
809
  float32x4_t query_sumsq_f32x4 = vdupq_n_f32((nk_f32_t)query_sumsq);
804
- float32x4_t sum_sq_f32x4 = vaddq_f32(query_sumsq_f32x4, vcvtq_f32_s32(target_sumsqs.i32x4));
810
+ float32x4_t sum_sq_f32x4 = vaddq_f32(query_sumsq_f32x4, vcvtq_f32_s32(target_sumsqs_vec->i32x4));
805
811
  float32x4_t dist_sq_f32x4 = vfmsq_f32(sum_sq_f32x4, vdupq_n_f32(2.0f), dots_f32x4);
806
812
  dist_sq_f32x4 = vmaxq_f32(dist_sq_f32x4, vdupq_n_f32(0.0f));
807
- results->f32x4 = vsqrtq_f32(dist_sq_f32x4);
813
+ result_vec->f32x4 = vsqrtq_f32(dist_sq_f32x4);
808
814
  }
809
815
 
810
816
  /** @brief Angular from_dot for u32 accumulators: cast to f32, rsqrt+NR, clamp. 4 pairs. */
811
- NK_INTERNAL void nk_angular_through_u32_from_dot_neon_(nk_b128_vec_t dots, nk_u32_t query_sumsq,
812
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
813
- float32x4_t dots_f32x4 = vcvtq_f32_u32(dots.u32x4);
817
+ NK_INTERNAL void nk_angular_through_u32_from_dot_neon_(nk_b128_vec_t const *dots_vec, nk_u32_t query_sumsq,
818
+ nk_b128_vec_t const *target_sumsqs_vec,
819
+ nk_b128_vec_t *result_vec) {
820
+ float32x4_t dots_f32x4 = vcvtq_f32_u32(dots_vec->u32x4);
814
821
  float32x4_t query_sumsq_f32x4 = vdupq_n_f32((nk_f32_t)query_sumsq);
815
- float32x4_t products_f32x4 = vmulq_f32(query_sumsq_f32x4, vcvtq_f32_u32(target_sumsqs.u32x4));
822
+ float32x4_t products_f32x4 = vmulq_f32(query_sumsq_f32x4, vcvtq_f32_u32(target_sumsqs_vec->u32x4));
816
823
  float32x4_t rsqrt_f32x4 = nk_rsqrt_f32x4_neon_(products_f32x4);
817
824
  float32x4_t normalized_f32x4 = vmulq_f32(dots_f32x4, rsqrt_f32x4);
818
825
  float32x4_t angular_f32x4 = vsubq_f32(vdupq_n_f32(1.0f), normalized_f32x4);
819
- results->f32x4 = vmaxq_f32(angular_f32x4, vdupq_n_f32(0.0f));
826
+ result_vec->f32x4 = vmaxq_f32(angular_f32x4, vdupq_n_f32(0.0f));
820
827
  }
821
828
 
822
829
  /** @brief Euclidean from_dot for u32 accumulators: cast to f32, then √(a² + b² − 2ab). 4 pairs. */
823
- NK_INTERNAL void nk_euclidean_through_u32_from_dot_neon_(nk_b128_vec_t dots, nk_u32_t query_sumsq,
824
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
825
- float32x4_t dots_f32x4 = vcvtq_f32_u32(dots.u32x4);
830
+ NK_INTERNAL void nk_euclidean_through_u32_from_dot_neon_(nk_b128_vec_t const *dots_vec, nk_u32_t query_sumsq,
831
+ nk_b128_vec_t const *target_sumsqs_vec,
832
+ nk_b128_vec_t *result_vec) {
833
+ float32x4_t dots_f32x4 = vcvtq_f32_u32(dots_vec->u32x4);
826
834
  float32x4_t query_sumsq_f32x4 = vdupq_n_f32((nk_f32_t)query_sumsq);
827
- float32x4_t sum_sq_f32x4 = vaddq_f32(query_sumsq_f32x4, vcvtq_f32_u32(target_sumsqs.u32x4));
835
+ float32x4_t sum_sq_f32x4 = vaddq_f32(query_sumsq_f32x4, vcvtq_f32_u32(target_sumsqs_vec->u32x4));
828
836
  float32x4_t dist_sq_f32x4 = vfmsq_f32(sum_sq_f32x4, vdupq_n_f32(2.0f), dots_f32x4);
829
837
  dist_sq_f32x4 = vmaxq_f32(dist_sq_f32x4, vdupq_n_f32(0.0f));
830
- results->f32x4 = vsqrtq_f32(dist_sq_f32x4);
838
+ result_vec->f32x4 = vsqrtq_f32(dist_sq_f32x4);
831
839
  }
832
840
 
833
841
  #if defined(__clang__)
@@ -49,7 +49,7 @@ extern "C" {
49
49
 
50
50
  NK_PUBLIC void nk_angular_bf16_neonbfdot(nk_bf16_t const *a, nk_bf16_t const *b, nk_size_t n, nk_f32_t *result) {
51
51
 
52
- // Similar to `nk_angular_i8_neon`, we can use the `BFMMLA` instruction through
52
+ // Similar to `nk_angular_i8_neonsdot`, we can use the `BFMMLA` instruction through
53
53
  // the `vbfmmlaq_f32` intrinsic to compute matrix products and later drop 1/4 of values.
54
54
  // The only difference is that `zip` isn't provided for `bf16` and we need to reinterpret back
55
55
  // and forth before zipping. Same as with integers, on modern Arm CPUs, this "smart"
@@ -587,13 +587,14 @@ nk_angular_u8_powervsx_cycle:
587
587
  }
588
588
 
589
589
  /** @brief Angular from_dot: computes 1 − dot × rsqrt(query_sumsq × target_sumsq) for 4 pairs in f64. */
590
- NK_INTERNAL void nk_angular_through_f64_from_dot_powervsx_(nk_b256_vec_t dots, nk_f64_t query_sumsq,
591
- nk_b256_vec_t target_sumsqs, nk_b256_vec_t *results) {
592
- nk_vf64x2_t dots_ab_f64x2 = dots.vf64x2s[0];
593
- nk_vf64x2_t dots_cd_f64x2 = dots.vf64x2s[1];
590
+ NK_INTERNAL void nk_angular_through_f64_from_dot_powervsx_(nk_b256_vec_t const *dots_vec, nk_f64_t query_sumsq,
591
+ nk_b256_vec_t const *target_sumsqs_vec,
592
+ nk_b256_vec_t *result_vec) {
593
+ nk_vf64x2_t dots_ab_f64x2 = dots_vec->vf64x2s[0];
594
+ nk_vf64x2_t dots_cd_f64x2 = dots_vec->vf64x2s[1];
594
595
  nk_vf64x2_t query_f64x2 = vec_splats(query_sumsq);
595
- nk_vf64x2_t targets_ab_f64x2 = target_sumsqs.vf64x2s[0];
596
- nk_vf64x2_t targets_cd_f64x2 = target_sumsqs.vf64x2s[1];
596
+ nk_vf64x2_t targets_ab_f64x2 = target_sumsqs_vec->vf64x2s[0];
597
+ nk_vf64x2_t targets_cd_f64x2 = target_sumsqs_vec->vf64x2s[1];
597
598
 
598
599
  nk_vf64x2_t products_ab_f64x2 = vec_mul(query_f64x2, targets_ab_f64x2);
599
600
  nk_vf64x2_t products_cd_f64x2 = vec_mul(query_f64x2, targets_cd_f64x2);
@@ -616,109 +617,116 @@ NK_INTERNAL void nk_angular_through_f64_from_dot_powervsx_(nk_b256_vec_t dots, n
616
617
  result_cd_f64x2 = vec_sel(result_cd_f64x2, zeros_f64x2, vec_and(prodzero_cd_u64x2, dotzero_cd_u64x2));
617
618
  result_cd_f64x2 = vec_sel(result_cd_f64x2, ones_f64x2, vec_andc(prodzero_cd_u64x2, dotzero_cd_u64x2));
618
619
 
619
- results->vf64x2s[0] = result_ab_f64x2;
620
- results->vf64x2s[1] = result_cd_f64x2;
620
+ result_vec->vf64x2s[0] = result_ab_f64x2;
621
+ result_vec->vf64x2s[1] = result_cd_f64x2;
621
622
  }
622
623
 
623
624
  /** @brief Euclidean from_dot: computes √(query_sumsq + target_sumsq − 2×dot) for 4 pairs in f64. */
624
- NK_INTERNAL void nk_euclidean_through_f64_from_dot_powervsx_(nk_b256_vec_t dots, nk_f64_t query_sumsq,
625
- nk_b256_vec_t target_sumsqs, nk_b256_vec_t *results) {
625
+ NK_INTERNAL void nk_euclidean_through_f64_from_dot_powervsx_(nk_b256_vec_t const *dots_vec, nk_f64_t query_sumsq,
626
+ nk_b256_vec_t const *target_sumsqs_vec,
627
+ nk_b256_vec_t *result_vec) {
626
628
  nk_vf64x2_t query_f64x2 = vec_splats(query_sumsq);
627
629
  nk_vf64x2_t neg_two_f64x2 = vec_splats(-2.0);
628
630
  nk_vf64x2_t zeros_f64x2 = vec_splats(0.0);
629
631
 
630
- nk_vf64x2_t sum_sq_ab_f64x2 = vec_add(query_f64x2, target_sumsqs.vf64x2s[0]);
631
- nk_vf64x2_t sum_sq_cd_f64x2 = vec_add(query_f64x2, target_sumsqs.vf64x2s[1]);
632
- nk_vf64x2_t dist_sq_ab_f64x2 = vec_max(vec_madd(neg_two_f64x2, dots.vf64x2s[0], sum_sq_ab_f64x2), zeros_f64x2);
633
- nk_vf64x2_t dist_sq_cd_f64x2 = vec_max(vec_madd(neg_two_f64x2, dots.vf64x2s[1], sum_sq_cd_f64x2), zeros_f64x2);
632
+ nk_vf64x2_t sum_sq_ab_f64x2 = vec_add(query_f64x2, target_sumsqs_vec->vf64x2s[0]);
633
+ nk_vf64x2_t sum_sq_cd_f64x2 = vec_add(query_f64x2, target_sumsqs_vec->vf64x2s[1]);
634
+ nk_vf64x2_t dist_sq_ab_f64x2 = vec_max(vec_madd(neg_two_f64x2, dots_vec->vf64x2s[0], sum_sq_ab_f64x2), zeros_f64x2);
635
+ nk_vf64x2_t dist_sq_cd_f64x2 = vec_max(vec_madd(neg_two_f64x2, dots_vec->vf64x2s[1], sum_sq_cd_f64x2), zeros_f64x2);
634
636
 
635
- results->vf64x2s[0] = vec_sqrt(dist_sq_ab_f64x2);
636
- results->vf64x2s[1] = vec_sqrt(dist_sq_cd_f64x2);
637
+ result_vec->vf64x2s[0] = vec_sqrt(dist_sq_ab_f64x2);
638
+ result_vec->vf64x2s[1] = vec_sqrt(dist_sq_cd_f64x2);
637
639
  }
638
640
 
639
641
  /** @brief Angular from_dot: computes 1 − dot × rsqrt(query_sumsq × target_sumsq) for 4 pairs in f32. */
640
- NK_INTERNAL void nk_angular_through_f32_from_dot_powervsx_(nk_b128_vec_t dots, nk_f32_t query_sumsq,
641
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
642
- nk_vf32x4_t dots_f32x4 = dots.vf32x4;
642
+ NK_INTERNAL void nk_angular_through_f32_from_dot_powervsx_(nk_b128_vec_t const *dots_vec, nk_f32_t query_sumsq,
643
+ nk_b128_vec_t const *target_sumsqs_vec,
644
+ nk_b128_vec_t *result_vec) {
645
+ nk_vf32x4_t dots_f32x4 = dots_vec->vf32x4;
643
646
  nk_vf32x4_t query_f32x4 = vec_splats(query_sumsq);
644
- nk_vf32x4_t products_f32x4 = vec_mul(query_f32x4, target_sumsqs.vf32x4);
647
+ nk_vf32x4_t products_f32x4 = vec_mul(query_f32x4, target_sumsqs_vec->vf32x4);
645
648
  nk_vf32x4_t rsqrt_f32x4 = nk_rsqrt_f32x4_powervsx_(products_f32x4);
646
649
  nk_vf32x4_t normalized_f32x4 = vec_mul(dots_f32x4, rsqrt_f32x4);
647
650
  nk_vf32x4_t angular_f32x4 = vec_sub(vec_splats(1.0f), normalized_f32x4);
648
651
  nk_vf32x4_t result_f32x4 = vec_max(angular_f32x4, vec_splats(0.0f));
649
- results->vf32x4 = result_f32x4;
652
+ result_vec->vf32x4 = result_f32x4;
650
653
  }
651
654
 
652
655
  /** @brief Euclidean from_dot: computes √(query_sumsq + target_sumsq − 2×dot) for 4 pairs in f32. */
653
- NK_INTERNAL void nk_euclidean_through_f32_from_dot_powervsx_(nk_b128_vec_t dots, nk_f32_t query_sumsq,
654
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
655
- nk_vf32x4_t dots_f32x4 = dots.vf32x4;
656
+ NK_INTERNAL void nk_euclidean_through_f32_from_dot_powervsx_(nk_b128_vec_t const *dots_vec, nk_f32_t query_sumsq,
657
+ nk_b128_vec_t const *target_sumsqs_vec,
658
+ nk_b128_vec_t *result_vec) {
659
+ nk_vf32x4_t dots_f32x4 = dots_vec->vf32x4;
656
660
  nk_vf32x4_t query_f32x4 = vec_splats(query_sumsq);
657
- nk_vf32x4_t sum_sq_f32x4 = vec_add(query_f32x4, target_sumsqs.vf32x4);
661
+ nk_vf32x4_t sum_sq_f32x4 = vec_add(query_f32x4, target_sumsqs_vec->vf32x4);
658
662
  // dist_sq = sum_sq − 2 × dot
659
663
  nk_vf32x4_t dist_sq_f32x4 = vec_madd(vec_splats(-2.0f), dots_f32x4, sum_sq_f32x4);
660
664
  // Clamp and sqrt
661
665
  dist_sq_f32x4 = vec_max(dist_sq_f32x4, vec_splats(0.0f));
662
666
  nk_vf32x4_t dist_f32x4 = vec_sqrt(dist_sq_f32x4);
663
- results->vf32x4 = dist_f32x4;
667
+ result_vec->vf32x4 = dist_f32x4;
664
668
  }
665
669
 
666
670
  /** @brief Angular from_dot for i32 accumulators: cast to f32, rsqrt+NR, clamp. 4 pairs. */
667
- NK_INTERNAL void nk_angular_through_i32_from_dot_powervsx_(nk_b128_vec_t dots, nk_i32_t query_sumsq,
668
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
669
- nk_vi32x4_t dots_i32x4 = dots.vi32x4;
671
+ NK_INTERNAL void nk_angular_through_i32_from_dot_powervsx_(nk_b128_vec_t const *dots_vec, nk_i32_t query_sumsq,
672
+ nk_b128_vec_t const *target_sumsqs_vec,
673
+ nk_b128_vec_t *result_vec) {
674
+ nk_vi32x4_t dots_i32x4 = dots_vec->vi32x4;
670
675
  nk_vf32x4_t dots_f32x4 = vec_ctf(dots_i32x4, 0);
671
676
  nk_vf32x4_t query_f32x4 = vec_splats((nk_f32_t)query_sumsq);
672
- nk_vi32x4_t targets_i32x4 = target_sumsqs.vi32x4;
677
+ nk_vi32x4_t targets_i32x4 = target_sumsqs_vec->vi32x4;
673
678
  nk_vf32x4_t products_f32x4 = vec_mul(query_f32x4, vec_ctf(targets_i32x4, 0));
674
679
  nk_vf32x4_t rsqrt_f32x4 = nk_rsqrt_f32x4_powervsx_(products_f32x4);
675
680
  nk_vf32x4_t normalized_f32x4 = vec_mul(dots_f32x4, rsqrt_f32x4);
676
681
  nk_vf32x4_t angular_f32x4 = vec_sub(vec_splats(1.0f), normalized_f32x4);
677
682
  nk_vf32x4_t result_f32x4 = vec_max(angular_f32x4, vec_splats(0.0f));
678
- results->vf32x4 = result_f32x4;
683
+ result_vec->vf32x4 = result_f32x4;
679
684
  }
680
685
 
681
686
  /** @brief Euclidean from_dot for i32 accumulators: cast to f32, then √(a² + b² − 2ab). 4 pairs. */
682
- NK_INTERNAL void nk_euclidean_through_i32_from_dot_powervsx_(nk_b128_vec_t dots, nk_i32_t query_sumsq,
683
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
684
- nk_vi32x4_t dots_i32x4 = dots.vi32x4;
687
+ NK_INTERNAL void nk_euclidean_through_i32_from_dot_powervsx_(nk_b128_vec_t const *dots_vec, nk_i32_t query_sumsq,
688
+ nk_b128_vec_t const *target_sumsqs_vec,
689
+ nk_b128_vec_t *result_vec) {
690
+ nk_vi32x4_t dots_i32x4 = dots_vec->vi32x4;
685
691
  nk_vf32x4_t dots_f32x4 = vec_ctf(dots_i32x4, 0);
686
692
  nk_vf32x4_t query_f32x4 = vec_splats((nk_f32_t)query_sumsq);
687
- nk_vi32x4_t targets_i32x4 = target_sumsqs.vi32x4;
693
+ nk_vi32x4_t targets_i32x4 = target_sumsqs_vec->vi32x4;
688
694
  nk_vf32x4_t sum_sq_f32x4 = vec_add(query_f32x4, vec_ctf(targets_i32x4, 0));
689
695
  nk_vf32x4_t dist_sq_f32x4 = vec_madd(vec_splats(-2.0f), dots_f32x4, sum_sq_f32x4);
690
696
  dist_sq_f32x4 = vec_max(dist_sq_f32x4, vec_splats(0.0f));
691
697
  nk_vf32x4_t dist_f32x4 = vec_sqrt(dist_sq_f32x4);
692
- results->vf32x4 = dist_f32x4;
698
+ result_vec->vf32x4 = dist_f32x4;
693
699
  }
694
700
 
695
701
  /** @brief Angular from_dot for u32 accumulators: cast to f32, rsqrt+NR, clamp. 4 pairs. */
696
- NK_INTERNAL void nk_angular_through_u32_from_dot_powervsx_(nk_b128_vec_t dots, nk_u32_t query_sumsq,
697
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
698
- nk_vu32x4_t dots_u32x4 = dots.vu32x4;
702
+ NK_INTERNAL void nk_angular_through_u32_from_dot_powervsx_(nk_b128_vec_t const *dots_vec, nk_u32_t query_sumsq,
703
+ nk_b128_vec_t const *target_sumsqs_vec,
704
+ nk_b128_vec_t *result_vec) {
705
+ nk_vu32x4_t dots_u32x4 = dots_vec->vu32x4;
699
706
  nk_vf32x4_t dots_f32x4 = vec_ctf(dots_u32x4, 0);
700
707
  nk_vf32x4_t query_f32x4 = vec_splats((nk_f32_t)query_sumsq);
701
- nk_vu32x4_t targets_u32x4 = target_sumsqs.vu32x4;
708
+ nk_vu32x4_t targets_u32x4 = target_sumsqs_vec->vu32x4;
702
709
  nk_vf32x4_t products_f32x4 = vec_mul(query_f32x4, vec_ctf(targets_u32x4, 0));
703
710
  nk_vf32x4_t rsqrt_f32x4 = nk_rsqrt_f32x4_powervsx_(products_f32x4);
704
711
  nk_vf32x4_t normalized_f32x4 = vec_mul(dots_f32x4, rsqrt_f32x4);
705
712
  nk_vf32x4_t angular_f32x4 = vec_sub(vec_splats(1.0f), normalized_f32x4);
706
713
  nk_vf32x4_t result_f32x4 = vec_max(angular_f32x4, vec_splats(0.0f));
707
- results->vf32x4 = result_f32x4;
714
+ result_vec->vf32x4 = result_f32x4;
708
715
  }
709
716
 
710
717
  /** @brief Euclidean from_dot for u32 accumulators: cast to f32, then √(a² + b² − 2ab). 4 pairs. */
711
- NK_INTERNAL void nk_euclidean_through_u32_from_dot_powervsx_(nk_b128_vec_t dots, nk_u32_t query_sumsq,
712
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
713
- nk_vu32x4_t dots_u32x4 = dots.vu32x4;
718
+ NK_INTERNAL void nk_euclidean_through_u32_from_dot_powervsx_(nk_b128_vec_t const *dots_vec, nk_u32_t query_sumsq,
719
+ nk_b128_vec_t const *target_sumsqs_vec,
720
+ nk_b128_vec_t *result_vec) {
721
+ nk_vu32x4_t dots_u32x4 = dots_vec->vu32x4;
714
722
  nk_vf32x4_t dots_f32x4 = vec_ctf(dots_u32x4, 0);
715
723
  nk_vf32x4_t query_f32x4 = vec_splats((nk_f32_t)query_sumsq);
716
- nk_vu32x4_t targets_u32x4 = target_sumsqs.vu32x4;
724
+ nk_vu32x4_t targets_u32x4 = target_sumsqs_vec->vu32x4;
717
725
  nk_vf32x4_t sum_sq_f32x4 = vec_add(query_f32x4, vec_ctf(targets_u32x4, 0));
718
726
  nk_vf32x4_t dist_sq_f32x4 = vec_madd(vec_splats(-2.0f), dots_f32x4, sum_sq_f32x4);
719
727
  dist_sq_f32x4 = vec_max(dist_sq_f32x4, vec_splats(0.0f));
720
728
  nk_vf32x4_t dist_f32x4 = vec_sqrt(dist_sq_f32x4);
721
- results->vf32x4 = dist_f32x4;
729
+ result_vec->vf32x4 = dist_f32x4;
722
730
  }
723
731
 
724
732
  #pragma endregion I8 and U8 Integers
@@ -253,108 +253,118 @@ NK_PUBLIC void nk_angular_u4_serial(nk_u4x2_t const *a, nk_u4x2_t const *b, nk_s
253
253
  }
254
254
  }
255
255
 
256
+ #if defined(__clang__)
257
+ #pragma clang attribute pop
258
+ #elif defined(__GNUC__)
259
+ #pragma GCC pop_options
260
+ #endif
261
+
256
262
  /** @brief Angular from_dot: computes 1 − dot × rsqrt(query_sumsq × target_sumsq) for 4 pairs (serial). */
257
- NK_INTERNAL void nk_angular_through_f32_from_dot_serial_(nk_b128_vec_t dots, nk_f32_t query_sumsq,
258
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
263
+ NK_INTERNAL void nk_angular_through_f32_from_dot_serial_(nk_b128_vec_t const *dots_vec, nk_f32_t query_sumsq,
264
+ nk_b128_vec_t const *target_sumsqs_vec,
265
+ nk_b128_vec_t *result_vec) {
259
266
  for (int i = 0; i < 4; ++i) {
260
- nk_f32_t product = query_sumsq * target_sumsqs.f32s[i];
267
+ nk_f32_t product = query_sumsq * target_sumsqs_vec->f32s[i];
261
268
  if (product > 0) {
262
269
  nk_f32_t rsqrt_val = nk_f32_rsqrt_serial(product);
263
- nk_f32_t normalized = dots.f32s[i] * rsqrt_val;
270
+ nk_f32_t normalized = dots_vec->f32s[i] * rsqrt_val;
264
271
  nk_f32_t result = 1.0f - normalized;
265
- results->f32s[i] = result > 0 ? result : 0;
272
+ result_vec->f32s[i] = result > 0 ? result : 0;
266
273
  }
267
- else { results->f32s[i] = (dots.f32s[i] == 0) ? 0.0f : 1.0f; }
274
+ else { result_vec->f32s[i] = (dots_vec->f32s[i] == 0) ? 0.0f : 1.0f; }
268
275
  }
269
276
  }
270
277
 
271
278
  /** @brief Euclidean from_dot: computes √(query_sumsq + target_sumsq − 2 × dot) for 4 pairs (serial). */
272
- NK_INTERNAL void nk_euclidean_through_f32_from_dot_serial_(nk_b128_vec_t dots, nk_f32_t query_sumsq,
273
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
279
+ NK_INTERNAL void nk_euclidean_through_f32_from_dot_serial_(nk_b128_vec_t const *dots_vec, nk_f32_t query_sumsq,
280
+ nk_b128_vec_t const *target_sumsqs_vec,
281
+ nk_b128_vec_t *result_vec) {
274
282
  for (int i = 0; i < 4; ++i) {
275
- nk_f32_t dist_sq = query_sumsq + target_sumsqs.f32s[i] - 2.0f * dots.f32s[i];
276
- results->f32s[i] = dist_sq > 0 ? nk_f32_sqrt_serial(dist_sq) : 0.0f;
283
+ nk_f32_t dist_sq = query_sumsq + target_sumsqs_vec->f32s[i] - 2.0f * dots_vec->f32s[i];
284
+ result_vec->f32s[i] = dist_sq > 0 ? nk_f32_sqrt_serial(dist_sq) : 0.0f;
277
285
  }
278
286
  }
279
287
 
280
288
  /** @brief Angular from_dot for f64 precision. */
281
- NK_INTERNAL void nk_angular_through_f64_from_dot_serial_(nk_b256_vec_t dots, nk_f64_t query_sumsq,
282
- nk_b256_vec_t target_sumsqs, nk_b256_vec_t *results) {
289
+ NK_INTERNAL void nk_angular_through_f64_from_dot_serial_(nk_b256_vec_t const *dots_vec, nk_f64_t query_sumsq,
290
+ nk_b256_vec_t const *target_sumsqs_vec,
291
+ nk_b256_vec_t *result_vec) {
283
292
  for (int i = 0; i < 4; ++i) {
284
- nk_f64_t product = query_sumsq * target_sumsqs.f64s[i];
293
+ nk_f64_t product = query_sumsq * target_sumsqs_vec->f64s[i];
285
294
  if (product > 0) {
286
295
  nk_f64_t rsqrt_val = nk_f64_rsqrt_serial(product);
287
- nk_f64_t normalized = dots.f64s[i] * rsqrt_val;
296
+ nk_f64_t normalized = dots_vec->f64s[i] * rsqrt_val;
288
297
  nk_f64_t result = 1.0 - normalized;
289
- results->f64s[i] = result > 0 ? result : 0;
298
+ result_vec->f64s[i] = result > 0 ? result : 0;
290
299
  }
291
- else { results->f64s[i] = (dots.f64s[i] == 0) ? 0.0 : 1.0; }
300
+ else { result_vec->f64s[i] = (dots_vec->f64s[i] == 0) ? 0.0 : 1.0; }
292
301
  }
293
302
  }
294
303
 
295
304
  /** @brief Euclidean from_dot for f64 precision. */
296
- NK_INTERNAL void nk_euclidean_through_f64_from_dot_serial_(nk_b256_vec_t dots, nk_f64_t query_sumsq,
297
- nk_b256_vec_t target_sumsqs, nk_b256_vec_t *results) {
305
+ NK_INTERNAL void nk_euclidean_through_f64_from_dot_serial_(nk_b256_vec_t const *dots_vec, nk_f64_t query_sumsq,
306
+ nk_b256_vec_t const *target_sumsqs_vec,
307
+ nk_b256_vec_t *result_vec) {
298
308
  for (int i = 0; i < 4; ++i) {
299
- nk_f64_t dist_sq = query_sumsq + target_sumsqs.f64s[i] - 2.0 * dots.f64s[i];
300
- results->f64s[i] = dist_sq > 0 ? nk_f64_sqrt_serial(dist_sq) : 0.0;
309
+ nk_f64_t dist_sq = query_sumsq + target_sumsqs_vec->f64s[i] - 2.0 * dots_vec->f64s[i];
310
+ result_vec->f64s[i] = dist_sq > 0 ? nk_f64_sqrt_serial(dist_sq) : 0.0;
301
311
  }
302
312
  }
303
313
 
304
314
  /** @brief Angular from_dot for i32 accumulators: cast to f32, then same math as f32 variant. */
305
- NK_INTERNAL void nk_angular_through_i32_from_dot_serial_(nk_b128_vec_t dots, nk_i32_t query_sumsq,
306
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
315
+ NK_INTERNAL void nk_angular_through_i32_from_dot_serial_(nk_b128_vec_t const *dots_vec, nk_i32_t query_sumsq,
316
+ nk_b128_vec_t const *target_sumsqs_vec,
317
+ nk_b128_vec_t *result_vec) {
307
318
  for (int i = 0; i < 4; ++i) {
308
- nk_f32_t product = (nk_f32_t)query_sumsq * (nk_f32_t)target_sumsqs.i32s[i];
319
+ nk_f32_t product = (nk_f32_t)query_sumsq * (nk_f32_t)target_sumsqs_vec->i32s[i];
309
320
  if (product > 0) {
310
321
  nk_f32_t rsqrt_val = nk_f32_rsqrt_serial(product);
311
- nk_f32_t normalized = (nk_f32_t)dots.i32s[i] * rsqrt_val;
322
+ nk_f32_t normalized = (nk_f32_t)dots_vec->i32s[i] * rsqrt_val;
312
323
  nk_f32_t result = 1.0f - normalized;
313
- results->f32s[i] = result > 0 ? result : 0;
324
+ result_vec->f32s[i] = result > 0 ? result : 0;
314
325
  }
315
- else { results->f32s[i] = (dots.i32s[i] == 0) ? 0.0f : 1.0f; }
326
+ else { result_vec->f32s[i] = (dots_vec->i32s[i] == 0) ? 0.0f : 1.0f; }
316
327
  }
317
328
  }
318
329
 
319
330
  /** @brief Euclidean from_dot for i32 accumulators: cast to f32, then same math as f32 variant. */
320
- NK_INTERNAL void nk_euclidean_through_i32_from_dot_serial_(nk_b128_vec_t dots, nk_i32_t query_sumsq,
321
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
331
+ NK_INTERNAL void nk_euclidean_through_i32_from_dot_serial_(nk_b128_vec_t const *dots_vec, nk_i32_t query_sumsq,
332
+ nk_b128_vec_t const *target_sumsqs_vec,
333
+ nk_b128_vec_t *result_vec) {
322
334
  for (int i = 0; i < 4; ++i) {
323
- nk_f32_t dist_sq = (nk_f32_t)query_sumsq + (nk_f32_t)target_sumsqs.i32s[i] - 2.0f * (nk_f32_t)dots.i32s[i];
324
- results->f32s[i] = dist_sq > 0 ? nk_f32_sqrt_serial(dist_sq) : 0.0f;
335
+ nk_f32_t dist_sq = (nk_f32_t)query_sumsq + (nk_f32_t)target_sumsqs_vec->i32s[i] -
336
+ 2.0f * (nk_f32_t)dots_vec->i32s[i];
337
+ result_vec->f32s[i] = dist_sq > 0 ? nk_f32_sqrt_serial(dist_sq) : 0.0f;
325
338
  }
326
339
  }
327
340
 
328
341
  /** @brief Angular from_dot for u32 accumulators: cast to f32, then same math as f32 variant. */
329
- NK_INTERNAL void nk_angular_through_u32_from_dot_serial_(nk_b128_vec_t dots, nk_u32_t query_sumsq,
330
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
342
+ NK_INTERNAL void nk_angular_through_u32_from_dot_serial_(nk_b128_vec_t const *dots_vec, nk_u32_t query_sumsq,
343
+ nk_b128_vec_t const *target_sumsqs_vec,
344
+ nk_b128_vec_t *result_vec) {
331
345
  for (int i = 0; i < 4; ++i) {
332
- nk_f32_t product = (nk_f32_t)query_sumsq * (nk_f32_t)target_sumsqs.u32s[i];
346
+ nk_f32_t product = (nk_f32_t)query_sumsq * (nk_f32_t)target_sumsqs_vec->u32s[i];
333
347
  if (product > 0) {
334
348
  nk_f32_t rsqrt_val = nk_f32_rsqrt_serial(product);
335
- nk_f32_t normalized = (nk_f32_t)dots.u32s[i] * rsqrt_val;
349
+ nk_f32_t normalized = (nk_f32_t)dots_vec->u32s[i] * rsqrt_val;
336
350
  nk_f32_t result = 1.0f - normalized;
337
- results->f32s[i] = result > 0 ? result : 0;
351
+ result_vec->f32s[i] = result > 0 ? result : 0;
338
352
  }
339
- else { results->f32s[i] = (dots.u32s[i] == 0) ? 0.0f : 1.0f; }
353
+ else { result_vec->f32s[i] = (dots_vec->u32s[i] == 0) ? 0.0f : 1.0f; }
340
354
  }
341
355
  }
342
356
 
343
357
  /** @brief Euclidean from_dot for u32 accumulators: cast to f32, then same math as f32 variant. */
344
- NK_INTERNAL void nk_euclidean_through_u32_from_dot_serial_(nk_b128_vec_t dots, nk_u32_t query_sumsq,
345
- nk_b128_vec_t target_sumsqs, nk_b128_vec_t *results) {
358
+ NK_INTERNAL void nk_euclidean_through_u32_from_dot_serial_(nk_b128_vec_t const *dots_vec, nk_u32_t query_sumsq,
359
+ nk_b128_vec_t const *target_sumsqs_vec,
360
+ nk_b128_vec_t *result_vec) {
346
361
  for (int i = 0; i < 4; ++i) {
347
- nk_f32_t dist_sq = (nk_f32_t)query_sumsq + (nk_f32_t)target_sumsqs.u32s[i] - 2.0f * (nk_f32_t)dots.u32s[i];
348
- results->f32s[i] = dist_sq > 0 ? nk_f32_sqrt_serial(dist_sq) : 0.0f;
362
+ nk_f32_t dist_sq = (nk_f32_t)query_sumsq + (nk_f32_t)target_sumsqs_vec->u32s[i] -
363
+ 2.0f * (nk_f32_t)dots_vec->u32s[i];
364
+ result_vec->f32s[i] = dist_sq > 0 ? nk_f32_sqrt_serial(dist_sq) : 0.0f;
349
365
  }
350
366
  }
351
367
 
352
- #if defined(__clang__)
353
- #pragma clang attribute pop
354
- #elif defined(__GNUC__)
355
- #pragma GCC pop_options
356
- #endif
357
-
358
368
  #if defined(__cplusplus)
359
369
  } // extern "C"
360
370
  #endif
@@ -26,9 +26,10 @@
26
26
  #if NK_TARGET_SIERRA
27
27
 
28
28
  #include "numkong/types.h"
29
- #include "numkong/scalar/haswell.h" // `nk_f32_sqrt_haswell`
30
- #include "numkong/reduce/haswell.h" // `nk_reduce_add_i32x8_haswell_`
31
- #include "numkong/cast/serial.h" // `nk_partial_load_b8x32_serial_`
29
+ #include "numkong/scalar/haswell.h" // `nk_f32_sqrt_haswell`
30
+ #include "numkong/reduce/haswell.h" // `nk_reduce_add_i32x8_haswell_`
31
+ #include "numkong/spatial/haswell.h" // `nk_angular_normalize_f32_haswell_`
32
+ #include "numkong/cast/serial.h" // `nk_partial_load_b8x32_serial_`
32
33
 
33
34
  #if defined(__cplusplus)
34
35
  extern "C" {