@img/sharp-libvips-dev-wasm32 1.3.0-rc.5 → 1.3.0-rc.7

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 (105) hide show
  1. package/README.md +23 -23
  2. package/include/expat.h +14 -2
  3. package/include/expat_config.h +6 -3
  4. package/include/expat_external.h +3 -2
  5. package/include/glib-2.0/glib/gvarianttype.h +16 -16
  6. package/include/glib-2.0/glib/gversionmacros.h +13 -0
  7. package/include/hwy/aligned_allocator.h +44 -2
  8. package/include/hwy/auto_tune.h +22 -6
  9. package/include/hwy/base.h +60 -90
  10. package/include/hwy/bit_set.h +410 -0
  11. package/include/hwy/cache_control.h +3 -2
  12. package/include/hwy/detect_compiler_arch.h +134 -14
  13. package/include/hwy/detect_targets.h +82 -36
  14. package/include/hwy/highway.h +15 -0
  15. package/include/hwy/nanobenchmark.h +12 -3
  16. package/include/hwy/ops/arm_neon-inl.h +96 -25
  17. package/include/hwy/ops/arm_sve-inl.h +250 -95
  18. package/include/hwy/ops/emu128-inl.h +12 -7
  19. package/include/hwy/ops/generic_ops-inl.h +271 -131
  20. package/include/hwy/ops/loongarch_lasx-inl.h +31 -9
  21. package/include/hwy/ops/loongarch_lsx-inl.h +33 -12
  22. package/include/hwy/ops/ppc_vsx-inl.h +99 -19
  23. package/include/hwy/ops/rvv-inl.h +239 -130
  24. package/include/hwy/ops/scalar-inl.h +22 -7
  25. package/include/hwy/ops/set_macros-inl.h +163 -107
  26. package/include/hwy/ops/wasm_128-inl.h +13 -22
  27. package/include/hwy/ops/x86_128-inl.h +223 -120
  28. package/include/hwy/ops/x86_256-inl.h +70 -134
  29. package/include/hwy/ops/x86_512-inl.h +130 -134
  30. package/include/hwy/print-inl.h +2 -0
  31. package/include/hwy/profiler.h +355 -264
  32. package/include/hwy/robust_statistics.h +3 -1
  33. package/include/hwy/timer.h +44 -0
  34. package/include/lcms2.h +34 -4
  35. package/include/libexif/exif-utils.h +1 -1
  36. package/include/libheif/heif_sequences.h +12 -2
  37. package/include/libheif/heif_uncompressed.h +8 -0
  38. package/include/libpng16/png.h +7 -7
  39. package/include/libpng16/pngconf.h +1 -1
  40. package/include/libpng16/pnglibconf.h +1 -1
  41. package/include/png.h +7 -7
  42. package/include/pngconf.h +1 -1
  43. package/include/pnglibconf.h +1 -1
  44. package/include/tiffconf.h +9 -10
  45. package/include/tiffio.h +10 -9
  46. package/include/tiffvers.h +1 -1
  47. package/include/ultrahdr_api.h +5 -11
  48. package/lib/glib-2.0/include/glibconfig.h +1 -1
  49. package/lib/libaom.a +0 -0
  50. package/lib/libcgif.a +0 -0
  51. package/lib/libexif.a +0 -0
  52. package/lib/libexif.la +1 -1
  53. package/lib/libexpat.a +0 -0
  54. package/lib/libexpat.la +3 -3
  55. package/lib/libffi.a +0 -0
  56. package/lib/libgio-2.0.a +0 -0
  57. package/lib/libglib-2.0.a +0 -0
  58. package/lib/libgmodule-2.0.a +0 -0
  59. package/lib/libgobject-2.0.a +0 -0
  60. package/lib/libgthread-2.0.a +0 -0
  61. package/lib/libheif.a +0 -0
  62. package/lib/libhwy.a +0 -0
  63. package/lib/libimagequant.a +0 -0
  64. package/lib/libjpeg.a +0 -0
  65. package/lib/liblcms2.a +0 -0
  66. package/lib/libpng.a +0 -0
  67. package/lib/libpng.la +2 -2
  68. package/lib/libpng16.a +0 -0
  69. package/lib/libpng16.la +2 -2
  70. package/lib/libresvg.a +0 -0
  71. package/lib/libsharpyuv.a +0 -0
  72. package/lib/libtiff.a +0 -0
  73. package/lib/libuhdr.a +0 -0
  74. package/lib/libvips-cpp.a +0 -0
  75. package/lib/libvips.a +0 -0
  76. package/lib/libwebp.a +0 -0
  77. package/lib/libwebpdecoder.a +0 -0
  78. package/lib/libwebpdemux.a +0 -0
  79. package/lib/libwebpmux.a +0 -0
  80. package/lib/libz.a +0 -0
  81. package/lib/pkgconfig/expat.pc +1 -1
  82. package/lib/pkgconfig/gio-2.0.pc +1 -1
  83. package/lib/pkgconfig/glib-2.0.pc +1 -1
  84. package/lib/pkgconfig/gmodule-2.0.pc +1 -1
  85. package/lib/pkgconfig/gmodule-export-2.0.pc +1 -1
  86. package/lib/pkgconfig/gmodule-no-export-2.0.pc +1 -1
  87. package/lib/pkgconfig/gobject-2.0.pc +1 -1
  88. package/lib/pkgconfig/gthread-2.0.pc +1 -1
  89. package/lib/pkgconfig/lcms2.pc +1 -1
  90. package/lib/pkgconfig/libexif.pc +1 -1
  91. package/lib/pkgconfig/libhwy.pc +3 -4
  92. package/lib/pkgconfig/libpng.pc +1 -1
  93. package/lib/pkgconfig/libpng16.pc +1 -1
  94. package/lib/pkgconfig/libsharpyuv.pc +1 -1
  95. package/lib/pkgconfig/libtiff-4.pc +2 -2
  96. package/lib/pkgconfig/libwebp.pc +1 -1
  97. package/lib/pkgconfig/libwebpdecoder.pc +11 -0
  98. package/lib/pkgconfig/libwebpmux.pc +1 -1
  99. package/package.json +1 -1
  100. package/versions.json +10 -10
  101. package/lib/libsharpyuv.la +0 -41
  102. package/lib/libtiff.la +0 -41
  103. package/lib/libwebp.la +0 -41
  104. package/lib/libwebpdemux.la +0 -41
  105. package/lib/libwebpmux.la +0 -41
@@ -555,78 +555,48 @@ HWY_API Vec256<double> Xor(Vec256<double> a, Vec256<double> b) {
555
555
  return Vec256<double>{_mm256_xor_pd(a.raw, b.raw)};
556
556
  }
557
557
 
558
- // ------------------------------ Not
559
- template <typename T>
560
- HWY_API Vec256<T> Not(const Vec256<T> v) {
561
- const DFromV<decltype(v)> d;
562
- using TU = MakeUnsigned<T>;
563
- #if HWY_TARGET <= HWY_AVX3 && !HWY_IS_MSAN
564
- const __m256i vu = BitCast(RebindToUnsigned<decltype(d)>(), v).raw;
565
- return BitCast(d, Vec256<TU>{_mm256_ternarylogic_epi32(vu, vu, vu, 0x55)});
566
- #else
567
- return Xor(v, BitCast(d, Vec256<TU>{_mm256_set1_epi32(-1)}));
568
- #endif
569
- }
570
-
571
- // ------------------------------ Xor3
572
- template <typename T>
573
- HWY_API Vec256<T> Xor3(Vec256<T> x1, Vec256<T> x2, Vec256<T> x3) {
574
- #if HWY_TARGET <= HWY_AVX3 && !HWY_IS_MSAN
575
- const DFromV<decltype(x1)> d;
576
- const RebindToUnsigned<decltype(d)> du;
577
- using VU = VFromD<decltype(du)>;
578
- const __m256i ret = _mm256_ternarylogic_epi64(
579
- BitCast(du, x1).raw, BitCast(du, x2).raw, BitCast(du, x3).raw, 0x96);
580
- return BitCast(d, VU{ret});
581
- #else
582
- return Xor(x1, Xor(x2, x3));
583
- #endif
584
- }
558
+ #if HWY_X86_HAVE_TERNARY_LOGIC
559
+ namespace detail {
585
560
 
586
- // ------------------------------ Or3
587
- template <typename T>
588
- HWY_API Vec256<T> Or3(Vec256<T> o1, Vec256<T> o2, Vec256<T> o3) {
589
- #if HWY_TARGET <= HWY_AVX3 && !HWY_IS_MSAN
590
- const DFromV<decltype(o1)> d;
591
- const RebindToUnsigned<decltype(d)> du;
592
- using VU = VFromD<decltype(du)>;
593
- const __m256i ret = _mm256_ternarylogic_epi64(
594
- BitCast(du, o1).raw, BitCast(du, o2).raw, BitCast(du, o3).raw, 0xFE);
595
- return BitCast(d, VU{ret});
596
- #else
597
- return Or(o1, Or(o2, o3));
598
- #endif
599
- }
561
+ // Per-target partial specialization.
562
+ template <uint8_t kTernLogOp>
563
+ struct TernaryLogicImpl<kTernLogOp, 32> {
564
+ template <class V>
565
+ HWY_INLINE V operator()(V a, V b, V c) const {
566
+ const DFromV<decltype(a)> d;
567
+ const RebindToUnsigned<decltype(d)> du;
568
+ using VU = VFromD<decltype(du)>;
569
+ const __m256i ret = _mm256_ternarylogic_epi64(
570
+ BitCast(du, a).raw, BitCast(du, b).raw, BitCast(du, c).raw, kTernLogOp);
571
+ return BitCast(d, VU{ret});
572
+ }
573
+ };
600
574
 
601
- // ------------------------------ OrAnd
602
- template <typename T>
603
- HWY_API Vec256<T> OrAnd(Vec256<T> o, Vec256<T> a1, Vec256<T> a2) {
604
- #if HWY_TARGET <= HWY_AVX3 && !HWY_IS_MSAN
605
- const DFromV<decltype(o)> d;
606
- const RebindToUnsigned<decltype(d)> du;
607
- using VU = VFromD<decltype(du)>;
608
- const __m256i ret = _mm256_ternarylogic_epi64(
609
- BitCast(du, o).raw, BitCast(du, a1).raw, BitCast(du, a2).raw, 0xF8);
610
- return BitCast(d, VU{ret});
611
- #else
612
- return Or(o, And(a1, a2));
613
- #endif
614
- }
575
+ // Same, but with writemask. If !mask, returns a.
576
+ template <uint8_t kTernLogOp>
577
+ struct MaskedTernaryLogicImpl<kTernLogOp, 32> {
578
+ template <class V, class D = DFromV<V>, HWY_IF_T_SIZE_D(D, 4)>
579
+ HWY_INLINE V operator()(MFromD<D> mask, V a, V b, V c) const {
580
+ const D d;
581
+ const RebindToUnsigned<decltype(d)> du;
582
+ using VU = VFromD<decltype(du)>;
583
+ const __m256i ret = _mm256_mask_ternarylogic_epi32(a.raw, mask.raw, b.raw,
584
+ c.raw, kTernLogOp);
585
+ return BitCast(d, VU{ret});
586
+ }
587
+ template <class V, class D = DFromV<V>, HWY_IF_T_SIZE_D(D, 8)>
588
+ HWY_INLINE V operator()(MFromD<D> mask, V a, V b, V c) const {
589
+ const D d;
590
+ const RebindToUnsigned<decltype(d)> du;
591
+ using VU = VFromD<decltype(du)>;
592
+ const __m256i ret = _mm256_mask_ternarylogic_epi64(a.raw, mask.raw, b.raw,
593
+ c.raw, kTernLogOp);
594
+ return BitCast(d, VU{ret});
595
+ }
596
+ };
615
597
 
616
- // ------------------------------ IfVecThenElse
617
- template <typename T>
618
- HWY_API Vec256<T> IfVecThenElse(Vec256<T> mask, Vec256<T> yes, Vec256<T> no) {
619
- #if HWY_TARGET <= HWY_AVX3 && !HWY_IS_MSAN
620
- const DFromV<decltype(yes)> d;
621
- const RebindToUnsigned<decltype(d)> du;
622
- using VU = VFromD<decltype(du)>;
623
- return BitCast(d, VU{_mm256_ternarylogic_epi64(BitCast(du, mask).raw,
624
- BitCast(du, yes).raw,
625
- BitCast(du, no).raw, 0xCA)});
626
- #else
627
- return IfThenElse(MaskFromVec(mask), yes, no);
628
- #endif
629
- }
598
+ } // namespace detail
599
+ #endif // HWY_X86_HAVE_TERNARY_LOGIC
630
600
 
631
601
  // ------------------------------ Operator overloads (internal-only if float)
632
602
 
@@ -2113,8 +2083,8 @@ HWY_INLINE Vec256<uint32_t> SumsOf4(hwy::UnsignedTag /*type_tag*/,
2113
2083
  // ------------------------------ SumsOfAdjQuadAbsDiff
2114
2084
 
2115
2085
  template <int kAOffset, int kBOffset>
2116
- static Vec256<uint16_t> SumsOfAdjQuadAbsDiff(Vec256<uint8_t> a,
2117
- Vec256<uint8_t> b) {
2086
+ HWY_API Vec256<uint16_t> SumsOfAdjQuadAbsDiff(Vec256<uint8_t> a,
2087
+ Vec256<uint8_t> b) {
2118
2088
  static_assert(0 <= kAOffset && kAOffset <= 1,
2119
2089
  "kAOffset must be between 0 and 1");
2120
2090
  static_assert(0 <= kBOffset && kBOffset <= 3,
@@ -2159,30 +2129,6 @@ HWY_API Vec256<int16_t> SaturatedAdd(Vec256<int16_t> a, Vec256<int16_t> b) {
2159
2129
  return Vec256<int16_t>{_mm256_adds_epi16(a.raw, b.raw)};
2160
2130
  }
2161
2131
 
2162
- #if HWY_TARGET <= HWY_AVX3 && !HWY_IS_MSAN
2163
- HWY_API Vec256<int32_t> SaturatedAdd(Vec256<int32_t> a, Vec256<int32_t> b) {
2164
- const DFromV<decltype(a)> d;
2165
- const auto sum = a + b;
2166
- const auto overflow_mask = MaskFromVec(
2167
- Vec256<int32_t>{_mm256_ternarylogic_epi32(a.raw, b.raw, sum.raw, 0x42)});
2168
- const auto i32_max = Set(d, LimitsMax<int32_t>());
2169
- const Vec256<int32_t> overflow_result{_mm256_mask_ternarylogic_epi32(
2170
- i32_max.raw, MaskFromVec(a).raw, i32_max.raw, i32_max.raw, 0x55)};
2171
- return IfThenElse(overflow_mask, overflow_result, sum);
2172
- }
2173
-
2174
- HWY_API Vec256<int64_t> SaturatedAdd(Vec256<int64_t> a, Vec256<int64_t> b) {
2175
- const DFromV<decltype(a)> d;
2176
- const auto sum = a + b;
2177
- const auto overflow_mask = MaskFromVec(
2178
- Vec256<int64_t>{_mm256_ternarylogic_epi64(a.raw, b.raw, sum.raw, 0x42)});
2179
- const auto i64_max = Set(d, LimitsMax<int64_t>());
2180
- const Vec256<int64_t> overflow_result{_mm256_mask_ternarylogic_epi64(
2181
- i64_max.raw, MaskFromVec(a).raw, i64_max.raw, i64_max.raw, 0x55)};
2182
- return IfThenElse(overflow_mask, overflow_result, sum);
2183
- }
2184
- #endif // HWY_TARGET <= HWY_AVX3 && !HWY_IS_MSAN
2185
-
2186
2132
  // ------------------------------ SaturatedSub
2187
2133
 
2188
2134
  // Returns a - b clamped to the destination range.
@@ -2203,35 +2149,8 @@ HWY_API Vec256<int16_t> SaturatedSub(Vec256<int16_t> a, Vec256<int16_t> b) {
2203
2149
  return Vec256<int16_t>{_mm256_subs_epi16(a.raw, b.raw)};
2204
2150
  }
2205
2151
 
2206
- #if HWY_TARGET <= HWY_AVX3 && !HWY_IS_MSAN
2207
- HWY_API Vec256<int32_t> SaturatedSub(Vec256<int32_t> a, Vec256<int32_t> b) {
2208
- const DFromV<decltype(a)> d;
2209
- const auto diff = a - b;
2210
- const auto overflow_mask = MaskFromVec(
2211
- Vec256<int32_t>{_mm256_ternarylogic_epi32(a.raw, b.raw, diff.raw, 0x18)});
2212
- const auto i32_max = Set(d, LimitsMax<int32_t>());
2213
- const Vec256<int32_t> overflow_result{_mm256_mask_ternarylogic_epi32(
2214
- i32_max.raw, MaskFromVec(a).raw, i32_max.raw, i32_max.raw, 0x55)};
2215
- return IfThenElse(overflow_mask, overflow_result, diff);
2216
- }
2217
-
2218
- HWY_API Vec256<int64_t> SaturatedSub(Vec256<int64_t> a, Vec256<int64_t> b) {
2219
- const DFromV<decltype(a)> d;
2220
- const auto diff = a - b;
2221
- const auto overflow_mask = MaskFromVec(
2222
- Vec256<int64_t>{_mm256_ternarylogic_epi64(a.raw, b.raw, diff.raw, 0x18)});
2223
- const auto i64_max = Set(d, LimitsMax<int64_t>());
2224
- const Vec256<int64_t> overflow_result{_mm256_mask_ternarylogic_epi64(
2225
- i64_max.raw, MaskFromVec(a).raw, i64_max.raw, i64_max.raw, 0x55)};
2226
- return IfThenElse(overflow_mask, overflow_result, diff);
2227
- }
2228
- #endif // HWY_TARGET <= HWY_AVX3 && !HWY_IS_MSAN
2229
-
2230
2152
  // ------------------------------ Average
2231
2153
 
2232
- // Returns (a + b + 1) / 2
2233
-
2234
- // Unsigned
2235
2154
  HWY_API Vec256<uint8_t> AverageRound(Vec256<uint8_t> a, Vec256<uint8_t> b) {
2236
2155
  return Vec256<uint8_t>{_mm256_avg_epu8(a.raw, b.raw)};
2237
2156
  }
@@ -4937,6 +4856,17 @@ HWY_API V InterleaveOddBlocks(D d, V a, V b) {
4937
4856
  return ConcatUpperUpper(d, b, a);
4938
4857
  }
4939
4858
 
4859
+ // ------------------------------ InterleaveLowerBlocks
4860
+ template <class D, class V = VFromD<D>, HWY_IF_V_SIZE_D(D, 32)>
4861
+ HWY_API V InterleaveLowerBlocks(D d, V a, V b) {
4862
+ return InterleaveEvenBlocks(d, a, b);
4863
+ }
4864
+ // ------------------------------ InterleaveUpperBlocks
4865
+ template <class D, class V = VFromD<D>, HWY_IF_V_SIZE_D(D, 32)>
4866
+ HWY_API V InterleaveUpperBlocks(D d, V a, V b) {
4867
+ return InterleaveOddBlocks(d, a, b);
4868
+ }
4869
+
4940
4870
  // ------------------------------ Reverse (RotateRight)
4941
4871
 
4942
4872
  template <class D, HWY_IF_V_SIZE_D(D, 32), HWY_IF_T_SIZE_D(D, 4)>
@@ -6402,17 +6332,6 @@ HWY_API VFromD<D> ReorderWidenMulAccumulate(D d, Vec256<int16_t> a,
6402
6332
  #endif
6403
6333
  }
6404
6334
 
6405
- // ------------------------------ RearrangeToOddPlusEven
6406
- HWY_API Vec256<int32_t> RearrangeToOddPlusEven(const Vec256<int32_t> sum0,
6407
- Vec256<int32_t> /*sum1*/) {
6408
- return sum0; // invariant already holds
6409
- }
6410
-
6411
- HWY_API Vec256<uint32_t> RearrangeToOddPlusEven(const Vec256<uint32_t> sum0,
6412
- Vec256<uint32_t> /*sum1*/) {
6413
- return sum0; // invariant already holds
6414
- }
6415
-
6416
6335
  // ------------------------------ SumOfMulQuadAccumulate
6417
6336
 
6418
6337
  #if HWY_TARGET <= HWY_AVX3_DL
@@ -6424,7 +6343,24 @@ HWY_API VFromD<DI32> SumOfMulQuadAccumulate(
6424
6343
  return VFromD<DI32>{_mm256_dpbusd_epi32(sum.raw, a_u.raw, b_i.raw)};
6425
6344
  }
6426
6345
 
6427
- #endif
6346
+ #if HWY_X86_HAVE_AVX10_2_OPS
6347
+ template <class DI32, HWY_IF_I32_D(DI32), HWY_IF_V_SIZE_D(DI32, 32)>
6348
+ HWY_API VFromD<DI32> SumOfMulQuadAccumulate(DI32 /*di32*/,
6349
+ VFromD<Repartition<int8_t, DI32>> a,
6350
+ VFromD<Repartition<int8_t, DI32>> b,
6351
+ VFromD<DI32> sum) {
6352
+ return VFromD<DI32>{_mm256_dpbssd_epi32(sum.raw, a.raw, b.raw)};
6353
+ }
6354
+
6355
+ template <class DU32, HWY_IF_U32_D(DU32), HWY_IF_V_SIZE_D(DU32, 32)>
6356
+ HWY_API VFromD<DU32> SumOfMulQuadAccumulate(
6357
+ DU32 /*du32*/, VFromD<Repartition<uint8_t, DU32>> a,
6358
+ VFromD<Repartition<uint8_t, DU32>> b, VFromD<DU32> sum) {
6359
+ return VFromD<DU32>{_mm256_dpbuud_epi32(sum.raw, a.raw, b.raw)};
6360
+ }
6361
+ #endif // HWY_X86_HAVE_AVX10_2_OPS
6362
+
6363
+ #endif // HWY_TARGET <= HWY_AVX3_DL
6428
6364
 
6429
6365
  // ================================================== CONVERT
6430
6366
 
@@ -637,16 +637,48 @@ HWY_API VFromD<D> Iota(D d, const T2 first) {
637
637
 
638
638
  // ================================================== LOGICAL
639
639
 
640
- // ------------------------------ Not
640
+ #if HWY_X86_HAVE_TERNARY_LOGIC
641
+ namespace detail {
641
642
 
642
- template <typename T>
643
- HWY_API Vec512<T> Not(const Vec512<T> v) {
644
- const DFromV<decltype(v)> d;
645
- const RebindToUnsigned<decltype(d)> du;
646
- using VU = VFromD<decltype(du)>;
647
- const __m512i vu = BitCast(du, v).raw;
648
- return BitCast(d, VU{_mm512_ternarylogic_epi32(vu, vu, vu, 0x55)});
649
- }
643
+ // Per-target partial specialization.
644
+ template <uint8_t kTernLogOp>
645
+ struct TernaryLogicImpl<kTernLogOp, 64> {
646
+ template <class V>
647
+ HWY_INLINE V operator()(V a, V b, V c) const {
648
+ const DFromV<decltype(a)> d;
649
+ const RebindToUnsigned<decltype(d)> du;
650
+ using VU = VFromD<decltype(du)>;
651
+ const __m512i ret = _mm512_ternarylogic_epi64(
652
+ BitCast(du, a).raw, BitCast(du, b).raw, BitCast(du, c).raw, kTernLogOp);
653
+ return BitCast(d, VU{ret});
654
+ }
655
+ };
656
+
657
+ // Same, but with writemask. If !mask, returns a.
658
+ template <uint8_t kTernLogOp>
659
+ struct MaskedTernaryLogicImpl<kTernLogOp, 64> {
660
+ template <class V, class D = DFromV<V>, HWY_IF_T_SIZE_D(D, 4)>
661
+ HWY_INLINE V operator()(MFromD<D> mask, V a, V b, V c) const {
662
+ const D d;
663
+ const RebindToUnsigned<decltype(d)> du;
664
+ using VU = VFromD<decltype(du)>;
665
+ const __m512i ret = _mm512_mask_ternarylogic_epi32(a.raw, mask.raw, b.raw,
666
+ c.raw, kTernLogOp);
667
+ return BitCast(d, VU{ret});
668
+ }
669
+ template <class V, class D = DFromV<V>, HWY_IF_T_SIZE_D(D, 8)>
670
+ HWY_INLINE V operator()(MFromD<D> mask, V a, V b, V c) const {
671
+ const D d;
672
+ const RebindToUnsigned<decltype(d)> du;
673
+ using VU = VFromD<decltype(du)>;
674
+ const __m512i ret = _mm512_mask_ternarylogic_epi64(a.raw, mask.raw, b.raw,
675
+ c.raw, kTernLogOp);
676
+ return BitCast(d, VU{ret});
677
+ }
678
+ };
679
+
680
+ } // namespace detail
681
+ #endif // HWY_X86_HAVE_TERNARY_LOGIC
650
682
 
651
683
  // ------------------------------ And
652
684
 
@@ -718,66 +750,6 @@ HWY_API Vec512<double> Xor(const Vec512<double> a, const Vec512<double> b) {
718
750
  return Vec512<double>{_mm512_xor_pd(a.raw, b.raw)};
719
751
  }
720
752
 
721
- // ------------------------------ Xor3
722
- template <typename T>
723
- HWY_API Vec512<T> Xor3(Vec512<T> x1, Vec512<T> x2, Vec512<T> x3) {
724
- #if !HWY_IS_MSAN
725
- const DFromV<decltype(x1)> d;
726
- const RebindToUnsigned<decltype(d)> du;
727
- using VU = VFromD<decltype(du)>;
728
- const __m512i ret = _mm512_ternarylogic_epi64(
729
- BitCast(du, x1).raw, BitCast(du, x2).raw, BitCast(du, x3).raw, 0x96);
730
- return BitCast(d, VU{ret});
731
- #else
732
- return Xor(x1, Xor(x2, x3));
733
- #endif
734
- }
735
-
736
- // ------------------------------ Or3
737
- template <typename T>
738
- HWY_API Vec512<T> Or3(Vec512<T> o1, Vec512<T> o2, Vec512<T> o3) {
739
- #if !HWY_IS_MSAN
740
- const DFromV<decltype(o1)> d;
741
- const RebindToUnsigned<decltype(d)> du;
742
- using VU = VFromD<decltype(du)>;
743
- const __m512i ret = _mm512_ternarylogic_epi64(
744
- BitCast(du, o1).raw, BitCast(du, o2).raw, BitCast(du, o3).raw, 0xFE);
745
- return BitCast(d, VU{ret});
746
- #else
747
- return Or(o1, Or(o2, o3));
748
- #endif
749
- }
750
-
751
- // ------------------------------ OrAnd
752
- template <typename T>
753
- HWY_API Vec512<T> OrAnd(Vec512<T> o, Vec512<T> a1, Vec512<T> a2) {
754
- #if !HWY_IS_MSAN
755
- const DFromV<decltype(o)> d;
756
- const RebindToUnsigned<decltype(d)> du;
757
- using VU = VFromD<decltype(du)>;
758
- const __m512i ret = _mm512_ternarylogic_epi64(
759
- BitCast(du, o).raw, BitCast(du, a1).raw, BitCast(du, a2).raw, 0xF8);
760
- return BitCast(d, VU{ret});
761
- #else
762
- return Or(o, And(a1, a2));
763
- #endif
764
- }
765
-
766
- // ------------------------------ IfVecThenElse
767
- template <typename T>
768
- HWY_API Vec512<T> IfVecThenElse(Vec512<T> mask, Vec512<T> yes, Vec512<T> no) {
769
- #if !HWY_IS_MSAN
770
- const DFromV<decltype(yes)> d;
771
- const RebindToUnsigned<decltype(d)> du;
772
- using VU = VFromD<decltype(du)>;
773
- return BitCast(d, VU{_mm512_ternarylogic_epi64(BitCast(du, mask).raw,
774
- BitCast(du, yes).raw,
775
- BitCast(du, no).raw, 0xCA)});
776
- #else
777
- return IfThenElse(MaskFromVec(mask), yes, no);
778
- #endif
779
- }
780
-
781
753
  // ------------------------------ Operator overloads (internal-only if float)
782
754
 
783
755
  template <typename T>
@@ -4856,6 +4828,65 @@ HWY_API Vec512<T> InterleaveOddBlocks(Full512<T> d, Vec512<T> a, Vec512<T> b) {
4856
4828
  return OddEvenBlocks(b, SlideDownBlocks<1>(d, a));
4857
4829
  }
4858
4830
 
4831
+ // ------------------------------ InterleaveLowerBlocks (TwoTablesLookupLanes)
4832
+
4833
+ // Note that _mm512_shuffle_f32x4 etc. can only use `a` to populate the lower
4834
+ // half of the result, so we would require at least two instructions. We instead
4835
+ // use table lookups.
4836
+
4837
+ template <typename T>
4838
+ HWY_API Vec512<T> InterleaveLowerBlocks(Full512<T> d, Vec512<T> a,
4839
+ Vec512<T> b) {
4840
+ const Repartition<uint64_t, decltype(d)> du64;
4841
+ HWY_ALIGN static constexpr int64_t kIdx[8] = {0, 1, 8, 9, 2, 3, 10, 11};
4842
+ const auto idx = SetTableIndices(du64, kIdx);
4843
+ return BitCast(d,
4844
+ TwoTablesLookupLanes(BitCast(du64, a), BitCast(du64, b), idx));
4845
+ }
4846
+
4847
+ HWY_API Vec512<float> InterleaveLowerBlocks(Full512<float> d, Vec512<float> a,
4848
+ Vec512<float> b) {
4849
+ HWY_ALIGN static constexpr int32_t kIdx[16] = {0, 1, 2, 3, 16, 17, 18, 19,
4850
+ 4, 5, 6, 7, 20, 21, 22, 23};
4851
+ const auto idx = SetTableIndices(d, kIdx);
4852
+ return TwoTablesLookupLanes(a, b, idx);
4853
+ }
4854
+
4855
+ HWY_API Vec512<double> InterleaveLowerBlocks(Full512<double> d,
4856
+ Vec512<double> a,
4857
+ Vec512<double> b) {
4858
+ HWY_ALIGN static constexpr int64_t kIdx[8] = {0, 1, 8, 9, 2, 3, 10, 11};
4859
+ const auto idx = SetTableIndices(d, kIdx);
4860
+ return TwoTablesLookupLanes(a, b, idx);
4861
+ }
4862
+
4863
+ // ------------------------------ InterleaveUpperBlocks (TwoTablesLookupLanes)
4864
+ template <typename T>
4865
+ HWY_API Vec512<T> InterleaveUpperBlocks(Full512<T> d, Vec512<T> a,
4866
+ Vec512<T> b) {
4867
+ const Repartition<uint64_t, decltype(d)> du64;
4868
+ HWY_ALIGN static constexpr int64_t kIdx[8] = {4, 5, 12, 13, 6, 7, 14, 15};
4869
+ const auto idx = SetTableIndices(du64, kIdx);
4870
+ return BitCast(
4871
+ d, TwoTablesLookupLanes(du64, BitCast(du64, a), BitCast(du64, b), idx));
4872
+ }
4873
+
4874
+ HWY_API Vec512<float> InterleaveUpperBlocks(Full512<float> d, Vec512<float> a,
4875
+ Vec512<float> b) {
4876
+ HWY_ALIGN static constexpr int32_t kIdx[16] = {
4877
+ 8, 9, 10, 11, 24, 25, 26, 27, 12, 13, 14, 15, 28, 29, 30, 31};
4878
+ const auto idx = SetTableIndices(d, kIdx);
4879
+ return TwoTablesLookupLanes(a, b, idx);
4880
+ }
4881
+
4882
+ HWY_API Vec512<double> InterleaveUpperBlocks(Full512<double> d,
4883
+ Vec512<double> a,
4884
+ Vec512<double> b) {
4885
+ HWY_ALIGN static constexpr int64_t kIdx[8] = {4, 5, 12, 13, 6, 7, 14, 15};
4886
+ const auto idx = SetTableIndices(d, kIdx);
4887
+ return TwoTablesLookupLanes(a, b, idx);
4888
+ }
4889
+
4859
4890
  // ------------------------------ ReverseBlocks
4860
4891
 
4861
4892
  template <class D, HWY_IF_V_SIZE_D(D, 64), HWY_IF_NOT_FLOAT3264_D(D)>
@@ -6744,74 +6775,32 @@ HWY_API Vec512<uint64_t> CLMulUpper(Vec512<uint64_t> va, Vec512<uint64_t> vb) {
6744
6775
  // SumsOfAdjShufQuadAbsDiff)
6745
6776
 
6746
6777
  template <int kAOffset, int kBOffset>
6747
- static Vec512<uint16_t> SumsOfAdjQuadAbsDiff(Vec512<uint8_t> a,
6748
- Vec512<uint8_t> b) {
6778
+ HWY_API Vec512<uint16_t> SumsOfAdjQuadAbsDiff(Vec512<uint8_t> a,
6779
+ Vec512<uint8_t> b) {
6749
6780
  static_assert(0 <= kAOffset && kAOffset <= 1,
6750
6781
  "kAOffset must be between 0 and 1");
6751
6782
  static_assert(0 <= kBOffset && kBOffset <= 3,
6752
6783
  "kBOffset must be between 0 and 3");
6753
6784
 
6785
+ #if HWY_X86_HAVE_AVX10_2_OPS
6786
+ // AVX10.2 now has the _mm512_mpsadbw_epu8 intrinsic available
6787
+ return Vec512<uint16_t>{_mm512_mpsadbw_epu8(
6788
+ a.raw, b.raw,
6789
+ (kAOffset << 5) | (kBOffset << 3) | (kAOffset << 2) | kBOffset)};
6790
+ #else
6754
6791
  const DFromV<decltype(a)> d;
6755
6792
  const RepartitionToWideX2<decltype(d)> du32;
6756
6793
 
6757
- // While AVX3 does not have a _mm512_mpsadbw_epu8 intrinsic, the
6758
- // SumsOfAdjQuadAbsDiff operation is implementable for 512-bit vectors on
6759
- // AVX3 using SumsOfShuffledQuadAbsDiff and U32 Broadcast.
6794
+ // The _mm512_mpsadbw_epu8 intrinsic is not available prior to AVX10.2.
6795
+ // The SumsOfAdjQuadAbsDiff operation is implementable for 512-bit vectors on
6796
+ // pre-AVX10.2 targets that support AVX3 using SumsOfShuffledQuadAbsDiff and
6797
+ // U32 Broadcast.
6760
6798
  return SumsOfShuffledQuadAbsDiff<kAOffset + 2, kAOffset + 1, kAOffset + 1,
6761
6799
  kAOffset>(
6762
6800
  a, BitCast(d, Broadcast<kBOffset>(BitCast(du32, b))));
6801
+ #endif
6763
6802
  }
6764
6803
 
6765
- #if !HWY_IS_MSAN
6766
- // ------------------------------ I32/I64 SaturatedAdd (MaskFromVec)
6767
-
6768
- HWY_API Vec512<int32_t> SaturatedAdd(Vec512<int32_t> a, Vec512<int32_t> b) {
6769
- const DFromV<decltype(a)> d;
6770
- const auto sum = a + b;
6771
- const auto overflow_mask = MaskFromVec(
6772
- Vec512<int32_t>{_mm512_ternarylogic_epi32(a.raw, b.raw, sum.raw, 0x42)});
6773
- const auto i32_max = Set(d, LimitsMax<int32_t>());
6774
- const Vec512<int32_t> overflow_result{_mm512_mask_ternarylogic_epi32(
6775
- i32_max.raw, MaskFromVec(a).raw, i32_max.raw, i32_max.raw, 0x55)};
6776
- return IfThenElse(overflow_mask, overflow_result, sum);
6777
- }
6778
-
6779
- HWY_API Vec512<int64_t> SaturatedAdd(Vec512<int64_t> a, Vec512<int64_t> b) {
6780
- const DFromV<decltype(a)> d;
6781
- const auto sum = a + b;
6782
- const auto overflow_mask = MaskFromVec(
6783
- Vec512<int64_t>{_mm512_ternarylogic_epi64(a.raw, b.raw, sum.raw, 0x42)});
6784
- const auto i64_max = Set(d, LimitsMax<int64_t>());
6785
- const Vec512<int64_t> overflow_result{_mm512_mask_ternarylogic_epi64(
6786
- i64_max.raw, MaskFromVec(a).raw, i64_max.raw, i64_max.raw, 0x55)};
6787
- return IfThenElse(overflow_mask, overflow_result, sum);
6788
- }
6789
-
6790
- // ------------------------------ I32/I64 SaturatedSub (MaskFromVec)
6791
-
6792
- HWY_API Vec512<int32_t> SaturatedSub(Vec512<int32_t> a, Vec512<int32_t> b) {
6793
- const DFromV<decltype(a)> d;
6794
- const auto diff = a - b;
6795
- const auto overflow_mask = MaskFromVec(
6796
- Vec512<int32_t>{_mm512_ternarylogic_epi32(a.raw, b.raw, diff.raw, 0x18)});
6797
- const auto i32_max = Set(d, LimitsMax<int32_t>());
6798
- const Vec512<int32_t> overflow_result{_mm512_mask_ternarylogic_epi32(
6799
- i32_max.raw, MaskFromVec(a).raw, i32_max.raw, i32_max.raw, 0x55)};
6800
- return IfThenElse(overflow_mask, overflow_result, diff);
6801
- }
6802
-
6803
- HWY_API Vec512<int64_t> SaturatedSub(Vec512<int64_t> a, Vec512<int64_t> b) {
6804
- const DFromV<decltype(a)> d;
6805
- const auto diff = a - b;
6806
- const auto overflow_mask = MaskFromVec(
6807
- Vec512<int64_t>{_mm512_ternarylogic_epi64(a.raw, b.raw, diff.raw, 0x18)});
6808
- const auto i64_max = Set(d, LimitsMax<int64_t>());
6809
- const Vec512<int64_t> overflow_result{_mm512_mask_ternarylogic_epi64(
6810
- i64_max.raw, MaskFromVec(a).raw, i64_max.raw, i64_max.raw, 0x55)};
6811
- return IfThenElse(overflow_mask, overflow_result, diff);
6812
- }
6813
- #endif // !HWY_IS_MSAN
6814
-
6815
6804
  // ------------------------------ Mask testing
6816
6805
 
6817
6806
  // Beware: the suffix indicates the number of mask bits, not lane size!
@@ -7615,16 +7604,6 @@ HWY_API VFromD<D> ReorderWidenMulAccumulate(D d, Vec512<int16_t> a,
7615
7604
  #endif
7616
7605
  }
7617
7606
 
7618
- HWY_API Vec512<int32_t> RearrangeToOddPlusEven(const Vec512<int32_t> sum0,
7619
- Vec512<int32_t> /*sum1*/) {
7620
- return sum0; // invariant already holds
7621
- }
7622
-
7623
- HWY_API Vec512<uint32_t> RearrangeToOddPlusEven(const Vec512<uint32_t> sum0,
7624
- Vec512<uint32_t> /*sum1*/) {
7625
- return sum0; // invariant already holds
7626
- }
7627
-
7628
7607
  // ------------------------------ SumOfMulQuadAccumulate
7629
7608
 
7630
7609
  #if HWY_TARGET <= HWY_AVX3_DL
@@ -7636,6 +7615,23 @@ HWY_API VFromD<DI32> SumOfMulQuadAccumulate(
7636
7615
  return VFromD<DI32>{_mm512_dpbusd_epi32(sum.raw, a_u.raw, b_i.raw)};
7637
7616
  }
7638
7617
 
7618
+ #if HWY_X86_HAVE_AVX10_2_OPS
7619
+ template <class DI32, HWY_IF_I32_D(DI32), HWY_IF_V_SIZE_D(DI32, 64)>
7620
+ HWY_API VFromD<DI32> SumOfMulQuadAccumulate(DI32 /*di32*/,
7621
+ VFromD<Repartition<int8_t, DI32>> a,
7622
+ VFromD<Repartition<int8_t, DI32>> b,
7623
+ VFromD<DI32> sum) {
7624
+ return VFromD<DI32>{_mm512_dpbssd_epi32(sum.raw, a.raw, b.raw)};
7625
+ }
7626
+
7627
+ template <class DU32, HWY_IF_U32_D(DU32), HWY_IF_V_SIZE_D(DU32, 64)>
7628
+ HWY_API VFromD<DU32> SumOfMulQuadAccumulate(
7629
+ DU32 /*du32*/, VFromD<Repartition<uint8_t, DU32>> a,
7630
+ VFromD<Repartition<uint8_t, DU32>> b, VFromD<DU32> sum) {
7631
+ return VFromD<DU32>{_mm512_dpbuud_epi32(sum.raw, a.raw, b.raw)};
7632
+ }
7633
+ #endif // HWY_X86_HAVE_AVX10_2_OPS
7634
+
7639
7635
  #endif
7640
7636
 
7641
7637
  // ------------------------------ Reductions
@@ -15,6 +15,8 @@
15
15
 
16
16
  // Print() function
17
17
 
18
+ #include <stddef.h>
19
+
18
20
  #include "hwy/highway.h"
19
21
  #include "hwy/print.h"
20
22