@img/sharp-libvips-dev-wasm32 1.3.0-rc.1 → 1.3.0-rc.10
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/README.md +23 -23
- package/include/aom/aom_codec.h +1 -1
- package/include/aom/aom_decoder.h +4 -0
- package/include/aom/aom_encoder.h +19 -8
- package/include/aom/aom_ext_ratectrl.h +664 -0
- package/include/aom/aom_image.h +93 -30
- package/include/aom/aom_tpl.h +99 -0
- package/include/aom/aomcx.h +89 -16
- package/include/aom/aomdx.h +12 -0
- package/include/expat.h +15 -3
- package/include/expat_config.h +6 -6
- package/include/expat_external.h +4 -4
- package/include/glib-2.0/gio/gdbusconnection.h +2 -8
- package/include/glib-2.0/gio/gfileattribute.h +1 -1
- package/include/glib-2.0/gio/gfileinfo.h +5 -0
- package/include/glib-2.0/gio/gicon.h +1 -1
- package/include/glib-2.0/gio/gio-autocleanups.h +0 -1
- package/include/glib-2.0/gio/gio-visibility.h +34 -0
- package/include/glib-2.0/gio/gio.h +2 -0
- package/include/glib-2.0/gio/gioenums.h +66 -44
- package/include/glib-2.0/gio/gioenumtypes.h +2 -0
- package/include/glib-2.0/gio/giptosmessage.h +46 -0
- package/include/glib-2.0/gio/gipv6tclassmessage.h +46 -0
- package/include/glib-2.0/gio/gresolver.h +1 -1
- package/include/glib-2.0/gio/gsettings.h +1 -1
- package/include/glib-2.0/gio/gsocketcontrolmessage.h +2 -0
- package/include/glib-2.0/glib/gatomic.h +26 -2
- package/include/glib-2.0/glib/gfileutils.h +2 -2
- package/include/glib-2.0/glib/ghook.h +3 -1
- package/include/glib-2.0/glib/giochannel.h +1 -1
- package/include/glib-2.0/glib/gkeyfile.h +1 -1
- package/include/glib-2.0/glib/glib-visibility.h +34 -0
- package/include/glib-2.0/glib/gmacros.h +32 -0
- package/include/glib-2.0/glib/gmain.h +4 -0
- package/include/glib-2.0/glib/gmarkup.h +18 -1
- package/include/glib-2.0/glib/gmem.h +4 -4
- package/include/glib-2.0/glib/gmessages.h +7 -9
- package/include/glib-2.0/glib/gnode.h +1 -1
- package/include/glib-2.0/glib/goption.h +1 -1
- package/include/glib-2.0/glib/gsequence.h +2 -2
- package/include/glib-2.0/glib/gslice.h +12 -4
- package/include/glib-2.0/glib/gspawn.h +1 -1
- package/include/glib-2.0/glib/gstrfuncs.h +191 -1
- package/include/glib-2.0/glib/gtestutils.h +6 -3
- package/include/glib-2.0/glib/gtimer.h +1 -0
- package/include/glib-2.0/glib/guri.h +3 -3
- package/include/glib-2.0/glib/gutils.h +10 -1
- package/include/glib-2.0/glib/gvarianttype.h +16 -16
- package/include/glib-2.0/glib/gversionmacros.h +22 -0
- package/include/glib-2.0/gmodule/gmodule-visibility.h +34 -0
- package/include/glib-2.0/gmodule.h +1 -1
- package/include/glib-2.0/gobject/gbinding.h +1 -1
- package/include/glib-2.0/gobject/gobject-visibility.h +34 -0
- package/include/glib-2.0/gobject/gobject.h +1 -1
- package/include/glib-2.0/gobject/gparam.h +1 -1
- package/include/glib-2.0/gobject/gsignal.h +8 -8
- package/include/glib-2.0/gobject/gtype.h +17 -17
- package/include/hwy/aligned_allocator.h +44 -2
- package/include/hwy/auto_tune.h +22 -6
- package/include/hwy/base.h +60 -90
- package/include/hwy/bit_set.h +410 -0
- package/include/hwy/cache_control.h +3 -2
- package/include/hwy/detect_compiler_arch.h +134 -14
- package/include/hwy/detect_targets.h +82 -36
- package/include/hwy/highway.h +15 -0
- package/include/hwy/nanobenchmark.h +12 -3
- package/include/hwy/ops/arm_neon-inl.h +96 -25
- package/include/hwy/ops/arm_sve-inl.h +250 -95
- package/include/hwy/ops/emu128-inl.h +12 -7
- package/include/hwy/ops/generic_ops-inl.h +271 -131
- package/include/hwy/ops/loongarch_lasx-inl.h +31 -9
- package/include/hwy/ops/loongarch_lsx-inl.h +33 -12
- package/include/hwy/ops/ppc_vsx-inl.h +99 -19
- package/include/hwy/ops/rvv-inl.h +239 -130
- package/include/hwy/ops/scalar-inl.h +22 -7
- package/include/hwy/ops/set_macros-inl.h +163 -107
- package/include/hwy/ops/wasm_128-inl.h +13 -22
- package/include/hwy/ops/x86_128-inl.h +223 -120
- package/include/hwy/ops/x86_256-inl.h +70 -134
- package/include/hwy/ops/x86_512-inl.h +130 -134
- package/include/hwy/print-inl.h +2 -0
- package/include/hwy/profiler.h +355 -264
- package/include/hwy/robust_statistics.h +3 -1
- package/include/hwy/timer.h +44 -0
- package/include/lcms2.h +35 -5
- package/include/lcms2_plugin.h +1 -1
- package/include/libexif/exif-utils.h +1 -1
- package/include/libheif/heif.h +2 -0
- package/include/libheif/heif_aux_images.h +2 -2
- package/include/libheif/heif_brands.h +16 -4
- package/include/libheif/heif_color.h +147 -25
- package/include/libheif/heif_components.h +264 -0
- package/include/libheif/heif_context.h +18 -4
- package/include/libheif/heif_cxx.h +20 -18
- package/include/libheif/heif_decoding.h +63 -9
- package/include/libheif/heif_encoding.h +46 -12
- package/include/libheif/heif_error.h +15 -6
- package/include/libheif/heif_export.h +48 -0
- package/include/libheif/heif_image.h +94 -32
- package/include/libheif/heif_image_handle.h +54 -3
- package/include/libheif/heif_items.h +25 -2
- package/include/libheif/heif_library.h +13 -18
- package/include/libheif/heif_metadata.h +5 -2
- package/include/libheif/heif_omaf.h +104 -0
- package/include/libheif/heif_plugin.h +80 -13
- package/include/libheif/heif_properties.h +259 -5
- package/include/libheif/heif_regions.h +5 -3
- package/include/libheif/heif_security.h +24 -2
- package/include/libheif/heif_sequences.h +163 -14
- package/include/libheif/heif_text.h +161 -0
- package/include/libheif/heif_tiling.h +2 -2
- package/include/libheif/heif_uncompressed.h +29 -5
- package/include/libheif/heif_version.h +2 -2
- package/include/libpng16/png.h +637 -488
- package/include/libpng16/pngconf.h +2 -2
- package/include/libpng16/pnglibconf.h +2 -2
- package/include/png.h +637 -488
- package/include/pngconf.h +2 -2
- package/include/pnglibconf.h +2 -2
- package/include/resvg.h +3 -3
- package/include/tiffconf.h +9 -10
- package/include/tiffio.h +10 -9
- package/include/tiffvers.h +1 -1
- package/include/ultrahdr_api.h +5 -11
- package/include/vips/colour.h +2 -2
- package/include/vips/memory.h +1 -1
- package/include/vips/version.h +4 -4
- package/include/zlib.h +3 -3
- package/lib/glib-2.0/include/glibconfig.h +1 -3
- package/lib/libaom.a +0 -0
- package/lib/libcgif.a +0 -0
- package/lib/libexif.a +0 -0
- package/lib/libexif.la +1 -1
- package/lib/libexpat.a +0 -0
- package/lib/libexpat.la +2 -2
- package/lib/libffi.a +0 -0
- package/lib/libgio-2.0.a +0 -0
- package/lib/libglib-2.0.a +0 -0
- package/lib/libgmodule-2.0.a +0 -0
- package/lib/libgobject-2.0.a +0 -0
- package/lib/libgthread-2.0.a +0 -0
- package/lib/libheif.a +0 -0
- package/lib/libhwy.a +0 -0
- package/lib/libimagequant.a +0 -0
- package/lib/libjpeg.a +0 -0
- package/lib/liblcms2.a +0 -0
- package/lib/libpng.a +0 -0
- package/lib/libpng.la +2 -2
- package/lib/libpng16.a +0 -0
- package/lib/libpng16.la +2 -2
- package/lib/libresvg.a +0 -0
- package/lib/libsharpyuv.a +0 -0
- package/lib/libtiff.a +0 -0
- package/lib/libuhdr.a +0 -0
- package/lib/libvips-cpp.a +0 -0
- package/lib/libvips.a +0 -0
- package/lib/libwebp.a +0 -0
- package/lib/libwebpdecoder.a +0 -0
- package/lib/libwebpdemux.a +0 -0
- package/lib/libwebpmux.a +0 -0
- package/lib/libz.a +0 -0
- package/lib/pkgconfig/aom.pc +2 -2
- package/lib/pkgconfig/cgif.pc +1 -1
- package/lib/pkgconfig/expat.pc +1 -1
- package/lib/pkgconfig/gio-2.0.pc +1 -1
- package/lib/pkgconfig/glib-2.0.pc +1 -1
- package/lib/pkgconfig/gmodule-2.0.pc +1 -1
- package/lib/pkgconfig/gmodule-export-2.0.pc +1 -1
- package/lib/pkgconfig/gmodule-no-export-2.0.pc +1 -1
- package/lib/pkgconfig/gobject-2.0.pc +1 -1
- package/lib/pkgconfig/gthread-2.0.pc +1 -1
- package/lib/pkgconfig/lcms2.pc +1 -1
- package/lib/pkgconfig/libexif.pc +1 -1
- package/lib/pkgconfig/libheif.pc +1 -1
- package/lib/pkgconfig/libhwy.pc +3 -4
- package/lib/pkgconfig/libpng.pc +1 -1
- package/lib/pkgconfig/libpng16.pc +1 -1
- package/lib/pkgconfig/libsharpyuv.pc +1 -1
- package/lib/pkgconfig/libtiff-4.pc +2 -2
- package/lib/pkgconfig/libwebp.pc +1 -1
- package/lib/pkgconfig/libwebpdecoder.pc +11 -0
- package/lib/pkgconfig/libwebpmux.pc +1 -1
- package/lib/pkgconfig/vips-cpp.pc +1 -1
- package/lib/pkgconfig/vips.pc +1 -1
- package/package.json +1 -1
- package/versions.json +15 -15
- package/lib/libsharpyuv.la +0 -41
- package/lib/libtiff.la +0 -41
- package/lib/libwebp.la +0 -41
- package/lib/libwebpdemux.la +0 -41
- package/lib/libwebpmux.la +0 -41
package/include/hwy/base.h
CHANGED
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
#include <stddef.h>
|
|
23
23
|
#include <stdint.h>
|
|
24
24
|
#if defined(HWY_HEADER_ONLY)
|
|
25
|
-
#include <
|
|
26
|
-
#include <
|
|
25
|
+
#include <stdarg.h>
|
|
26
|
+
#include <stdio.h>
|
|
27
27
|
#endif
|
|
28
28
|
|
|
29
29
|
#if !defined(HWY_NO_LIBCXX)
|
|
@@ -33,9 +33,10 @@
|
|
|
33
33
|
#include "hwy/detect_compiler_arch.h"
|
|
34
34
|
#include "hwy/highway_export.h"
|
|
35
35
|
|
|
36
|
-
// API version (https://semver.org/); keep in sync with CMakeLists.txt
|
|
36
|
+
// API version (https://semver.org/); keep in sync with CMakeLists.txt and
|
|
37
|
+
// meson.build.
|
|
37
38
|
#define HWY_MAJOR 1
|
|
38
|
-
#define HWY_MINOR
|
|
39
|
+
#define HWY_MINOR 4
|
|
39
40
|
#define HWY_PATCH 0
|
|
40
41
|
|
|
41
42
|
// True if the Highway version >= major.minor.0. Added in 1.2.0.
|
|
@@ -57,7 +58,7 @@
|
|
|
57
58
|
|
|
58
59
|
#endif // !HWY_IDE
|
|
59
60
|
|
|
60
|
-
#if
|
|
61
|
+
#if !defined(HWY_NO_LIBCXX) || HWY_COMPILER_MSVC
|
|
61
62
|
#include <atomic>
|
|
62
63
|
#endif
|
|
63
64
|
|
|
@@ -148,6 +149,21 @@
|
|
|
148
149
|
|
|
149
150
|
#endif // !HWY_COMPILER_MSVC
|
|
150
151
|
|
|
152
|
+
#if (HWY_COMPILER_GCC_ACTUAL && HWY_COMPILER_GCC_ACTUAL < 1200) || \
|
|
153
|
+
(HWY_COMPILER_ICC && !HWY_COMPILER_ICX)
|
|
154
|
+
// The use of __attribute__((unused)) in private class member variables triggers
|
|
155
|
+
// a compiler warning with GCC 11 and earlier and ICC
|
|
156
|
+
|
|
157
|
+
// GCC 11 and earlier and ICC also do not emit -Wunused-private-field warnings
|
|
158
|
+
// for unused private class member variables
|
|
159
|
+
#define HWY_MEMBER_VAR_MAYBE_UNUSED
|
|
160
|
+
#else
|
|
161
|
+
// Clang and ICX need __attribute__((unused)) in unused private class member
|
|
162
|
+
// variables to suppress -Wunused-private-field warnings unless this warning is
|
|
163
|
+
// ignored by using HWY_DIAGNOSTICS_OFF
|
|
164
|
+
#define HWY_MEMBER_VAR_MAYBE_UNUSED HWY_MAYBE_UNUSED
|
|
165
|
+
#endif
|
|
166
|
+
|
|
151
167
|
//------------------------------------------------------------------------------
|
|
152
168
|
// Builtin/attributes (no more #include after this point due to namespace!)
|
|
153
169
|
|
|
@@ -202,7 +218,9 @@ namespace hwy {
|
|
|
202
218
|
//------------------------------------------------------------------------------
|
|
203
219
|
// Macros
|
|
204
220
|
|
|
205
|
-
|
|
221
|
+
// Note: it is safe to remove `static` for users who want to use modules, but
|
|
222
|
+
// that might be a breaking change for some users, hence we do not by default.
|
|
223
|
+
#define HWY_API static HWY_INLINE HWY_FLATTEN
|
|
206
224
|
|
|
207
225
|
#define HWY_CONCAT_IMPL(a, b) a##b
|
|
208
226
|
#define HWY_CONCAT(a, b) HWY_CONCAT_IMPL(a, b)
|
|
@@ -349,60 +367,20 @@ HWY_DLLEXPORT HWY_NORETURN void HWY_FORMAT(3, 4)
|
|
|
349
367
|
} while (0)
|
|
350
368
|
#define HWY_ASSERT(condition) HWY_ASSERT_M(condition, "")
|
|
351
369
|
|
|
352
|
-
#if HWY_HAS_FEATURE(memory_sanitizer) || defined(MEMORY_SANITIZER) || \
|
|
353
|
-
defined(__SANITIZE_MEMORY__)
|
|
354
|
-
#define HWY_IS_MSAN 1
|
|
355
|
-
#else
|
|
356
|
-
#define HWY_IS_MSAN 0
|
|
357
|
-
#endif
|
|
358
|
-
|
|
359
|
-
#if HWY_HAS_FEATURE(address_sanitizer) || defined(ADDRESS_SANITIZER) || \
|
|
360
|
-
defined(__SANITIZE_ADDRESS__)
|
|
361
|
-
#define HWY_IS_ASAN 1
|
|
362
|
-
#else
|
|
363
|
-
#define HWY_IS_ASAN 0
|
|
364
|
-
#endif
|
|
365
|
-
|
|
366
|
-
#if HWY_HAS_FEATURE(hwaddress_sanitizer) || defined(HWADDRESS_SANITIZER) || \
|
|
367
|
-
defined(__SANITIZE_HWADDRESS__)
|
|
368
|
-
#define HWY_IS_HWASAN 1
|
|
369
|
-
#else
|
|
370
|
-
#define HWY_IS_HWASAN 0
|
|
371
|
-
#endif
|
|
372
|
-
|
|
373
|
-
#if HWY_HAS_FEATURE(thread_sanitizer) || defined(THREAD_SANITIZER) || \
|
|
374
|
-
defined(__SANITIZE_THREAD__)
|
|
375
|
-
#define HWY_IS_TSAN 1
|
|
376
|
-
#else
|
|
377
|
-
#define HWY_IS_TSAN 0
|
|
378
|
-
#endif
|
|
379
|
-
|
|
380
|
-
#if HWY_HAS_FEATURE(undefined_behavior_sanitizer) || \
|
|
381
|
-
defined(UNDEFINED_BEHAVIOR_SANITIZER)
|
|
382
|
-
#define HWY_IS_UBSAN 1
|
|
383
|
-
#else
|
|
384
|
-
#define HWY_IS_UBSAN 0
|
|
385
|
-
#endif
|
|
386
|
-
|
|
387
|
-
// MSAN may cause lengthy build times or false positives e.g. in AVX3 DemoteTo.
|
|
388
|
-
// You can disable MSAN by adding this attribute to the function that fails.
|
|
389
|
-
#if HWY_IS_MSAN
|
|
390
|
-
#define HWY_ATTR_NO_MSAN __attribute__((no_sanitize_memory))
|
|
391
|
-
#else
|
|
392
|
-
#define HWY_ATTR_NO_MSAN
|
|
393
|
-
#endif
|
|
394
|
-
|
|
395
|
-
#if HWY_IS_ASAN || HWY_IS_HWASAN || HWY_IS_MSAN || HWY_IS_TSAN || HWY_IS_UBSAN
|
|
396
|
-
#define HWY_IS_SANITIZER 1
|
|
397
|
-
#else
|
|
398
|
-
#define HWY_IS_SANITIZER 0
|
|
399
|
-
#endif
|
|
400
|
-
|
|
401
370
|
// For enabling HWY_DASSERT and shortening tests in slower debug builds
|
|
371
|
+
//
|
|
372
|
+
// Note: `HWY_IS_UBSAN` is specifically excluded from engaging debug
|
|
373
|
+
// builds. This is in service of Chromium's `-fsanitize=array-bounds` by
|
|
374
|
+
// default, where we don't want Highway to unconditionally build in
|
|
375
|
+
// debug mode.
|
|
376
|
+
//
|
|
377
|
+
// See also:
|
|
378
|
+
// https://docs.google.com/document/d/1eCtY4AZF-SiFHxhIYWzEytdIx3C24de7ccD6Y5Gn2H8/edit?tab=t.9zkn85hr82ms#heading=h.efcshvfql42c
|
|
402
379
|
#if !defined(HWY_IS_DEBUG_BUILD)
|
|
403
380
|
// Clang does not define NDEBUG, but it and GCC define __OPTIMIZE__, and recent
|
|
404
381
|
// MSVC defines NDEBUG (if not, could instead check _DEBUG).
|
|
405
|
-
#if (!defined(__OPTIMIZE__) && !defined(NDEBUG)) ||
|
|
382
|
+
#if (!defined(__OPTIMIZE__) && !defined(NDEBUG)) || \
|
|
383
|
+
(HWY_IS_ASAN || (HWY_IS_SANITIZER && !HWY_IS_UBSAN)) || \
|
|
406
384
|
defined(__clang_analyzer__)
|
|
407
385
|
#define HWY_IS_DEBUG_BUILD 1
|
|
408
386
|
#else
|
|
@@ -455,21 +433,22 @@ HWY_API void CopySameSize(const From* HWY_RESTRICT from, To* HWY_RESTRICT to) {
|
|
|
455
433
|
CopyBytes<sizeof(From)>(from, to);
|
|
456
434
|
}
|
|
457
435
|
|
|
458
|
-
|
|
459
|
-
HWY_API void
|
|
436
|
+
// Sets each byte to `byte_value`, which must be between 0 and 255.
|
|
437
|
+
HWY_API void FillBytes(void* to, int byte_value, size_t num_bytes) {
|
|
460
438
|
#if HWY_COMPILER_MSVC
|
|
461
|
-
memset(to,
|
|
439
|
+
memset(to, byte_value, num_bytes);
|
|
462
440
|
#else
|
|
463
|
-
__builtin_memset(to,
|
|
441
|
+
__builtin_memset(to, byte_value, num_bytes);
|
|
464
442
|
#endif
|
|
465
443
|
}
|
|
466
444
|
|
|
467
445
|
HWY_API void ZeroBytes(void* to, size_t num_bytes) {
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
446
|
+
FillBytes(to, 0, num_bytes);
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
template <size_t kBytes, typename To>
|
|
450
|
+
HWY_API void ZeroBytes(To* to) {
|
|
451
|
+
ZeroBytes(to, kBytes);
|
|
473
452
|
}
|
|
474
453
|
|
|
475
454
|
//------------------------------------------------------------------------------
|
|
@@ -1699,28 +1678,14 @@ HWY_F16_CONSTEXPR inline std::partial_ordering operator<=>(
|
|
|
1699
1678
|
//------------------------------------------------------------------------------
|
|
1700
1679
|
// BF16 lane type
|
|
1701
1680
|
|
|
1702
|
-
// Compiler supports ACLE __bf16, not necessarily with operators.
|
|
1703
|
-
|
|
1704
|
-
// Disable the __bf16 type on AArch64 with GCC 13 or earlier as there is a bug
|
|
1705
|
-
// in GCC 13 and earlier that sometimes causes BF16 constant values to be
|
|
1706
|
-
// incorrectly loaded on AArch64, and this GCC bug on AArch64 is
|
|
1707
|
-
// described at https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111867.
|
|
1708
|
-
|
|
1709
|
-
#if HWY_ARCH_ARM_A64 && \
|
|
1710
|
-
(HWY_COMPILER_CLANG >= 1700 || HWY_COMPILER_GCC_ACTUAL >= 1400)
|
|
1711
|
-
#define HWY_ARM_HAVE_SCALAR_BF16_TYPE 1
|
|
1712
|
-
#else
|
|
1713
|
-
#define HWY_ARM_HAVE_SCALAR_BF16_TYPE 0
|
|
1714
|
-
#endif
|
|
1715
|
-
|
|
1716
1681
|
// x86 compiler supports __bf16, not necessarily with operators.
|
|
1717
1682
|
// Disable in debug builds due to clang miscompiles as of 2025-07-22: casting
|
|
1718
1683
|
// bf16 <-> f32 in convert_test results in 0x2525 for 1.0 instead of 0x3f80.
|
|
1719
1684
|
// Reported at https://github.com/llvm/llvm-project/issues/151692.
|
|
1720
1685
|
#ifndef HWY_SSE2_HAVE_SCALAR_BF16_TYPE
|
|
1721
|
-
#if HWY_ARCH_X86 && defined(__SSE2__) &&
|
|
1722
|
-
((HWY_COMPILER_CLANG >= 1700 && !HWY_COMPILER_CLANGCL &&
|
|
1723
|
-
!HWY_IS_DEBUG_BUILD) ||
|
|
1686
|
+
#if HWY_ARCH_X86 && defined(__SSE2__) && \
|
|
1687
|
+
((HWY_COMPILER_CLANG >= 1700 && !HWY_COMPILER_CLANGCL && \
|
|
1688
|
+
(!HWY_IS_DEBUG_BUILD || HWY_COMPILER3_CLANG >= 220101)) || \
|
|
1724
1689
|
HWY_COMPILER_GCC_ACTUAL >= 1300)
|
|
1725
1690
|
#define HWY_SSE2_HAVE_SCALAR_BF16_TYPE 1
|
|
1726
1691
|
#else
|
|
@@ -1738,7 +1703,11 @@ HWY_F16_CONSTEXPR inline std::partial_ordering operator<=>(
|
|
|
1738
1703
|
#ifndef HWY_HAVE_SCALAR_BF16_OPERATORS
|
|
1739
1704
|
// Recent enough compiler also has operators. aarch64 clang 18 hits internal
|
|
1740
1705
|
// compiler errors on bf16 ToString, hence only enable on GCC for now.
|
|
1741
|
-
|
|
1706
|
+
// GCC >= 13 will insert a function call to the __extendbfsf2 helper function
|
|
1707
|
+
// for scalar conversions from __bf16 to float. This is prohibitively expensive,
|
|
1708
|
+
// so refrain from using scalar BF16 operators on these compiler versions.
|
|
1709
|
+
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121853
|
|
1710
|
+
#if HWY_HAVE_SCALAR_BF16_TYPE && (HWY_COMPILER_GCC_ACTUAL >= 1700)
|
|
1742
1711
|
#define HWY_HAVE_SCALAR_BF16_OPERATORS 1
|
|
1743
1712
|
#else
|
|
1744
1713
|
#define HWY_HAVE_SCALAR_BF16_OPERATORS 0
|
|
@@ -2734,7 +2703,7 @@ HWY_API constexpr TTo ConvertScalarTo(TFrom in) {
|
|
|
2734
2703
|
template <typename T1, typename T2>
|
|
2735
2704
|
constexpr inline T1 DivCeil(T1 a, T2 b) {
|
|
2736
2705
|
#if HWY_CXX_LANG >= 201703L
|
|
2737
|
-
HWY_DASSERT(b != 0);
|
|
2706
|
+
HWY_DASSERT(b != T2{0});
|
|
2738
2707
|
#endif
|
|
2739
2708
|
return (a + b - 1) / b;
|
|
2740
2709
|
}
|
|
@@ -2957,9 +2926,10 @@ HWY_INLINE constexpr T AddWithWraparound(T t, T2 n) {
|
|
|
2957
2926
|
// 64 x 64 = 128 bit multiplication
|
|
2958
2927
|
HWY_API uint64_t Mul128(uint64_t a, uint64_t b, uint64_t* HWY_RESTRICT upper) {
|
|
2959
2928
|
#if defined(__SIZEOF_INT128__)
|
|
2960
|
-
__uint128_t product =
|
|
2961
|
-
|
|
2962
|
-
|
|
2929
|
+
__uint128_t product =
|
|
2930
|
+
static_cast<__uint128_t>(a) * static_cast<__uint128_t>(b);
|
|
2931
|
+
*upper = static_cast<uint64_t>(product >> 64);
|
|
2932
|
+
return static_cast<uint64_t>(product & 0xFFFFFFFFFFFFFFFFULL);
|
|
2963
2933
|
#elif HWY_COMPILER_MSVC && HWY_ARCH_X86_64
|
|
2964
2934
|
return _umul128(a, b, upper);
|
|
2965
2935
|
#else
|
|
@@ -2976,9 +2946,9 @@ HWY_API uint64_t Mul128(uint64_t a, uint64_t b, uint64_t* HWY_RESTRICT upper) {
|
|
|
2976
2946
|
|
|
2977
2947
|
HWY_API int64_t Mul128(int64_t a, int64_t b, int64_t* HWY_RESTRICT upper) {
|
|
2978
2948
|
#if defined(__SIZEOF_INT128__)
|
|
2979
|
-
__int128_t product = (
|
|
2980
|
-
*upper =
|
|
2981
|
-
return
|
|
2949
|
+
__int128_t product = static_cast<__int128_t>(a) * static_cast<__int128_t>(b);
|
|
2950
|
+
*upper = static_cast<int64_t>(product >> 64);
|
|
2951
|
+
return static_cast<int64_t>(product & 0xFFFFFFFFFFFFFFFFULL);
|
|
2982
2952
|
#elif HWY_COMPILER_MSVC && HWY_ARCH_X86_64
|
|
2983
2953
|
return _mul128(a, b, upper);
|
|
2984
2954
|
#else
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
// Copyright 2024 Google LLC
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
//
|
|
4
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
// you may not use this file except in compliance with the License.
|
|
6
|
+
// You may obtain a copy of the License at
|
|
7
|
+
//
|
|
8
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
//
|
|
10
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
// See the License for the specific language governing permissions and
|
|
14
|
+
// limitations under the License.
|
|
15
|
+
|
|
16
|
+
#ifndef HIGHWAY_HWY_BIT_SET_H_
|
|
17
|
+
#define HIGHWAY_HWY_BIT_SET_H_
|
|
18
|
+
|
|
19
|
+
// Various BitSet for 64, up to 4096, or any number of bits.
|
|
20
|
+
|
|
21
|
+
#include <stddef.h>
|
|
22
|
+
|
|
23
|
+
#include <atomic>
|
|
24
|
+
|
|
25
|
+
#include "hwy/base.h"
|
|
26
|
+
|
|
27
|
+
namespace hwy {
|
|
28
|
+
|
|
29
|
+
// 64-bit specialization of `std::bitset`, which lacks `Foreach`.
|
|
30
|
+
class BitSet64 {
|
|
31
|
+
public:
|
|
32
|
+
constexpr size_t MaxSize() const { return 64; }
|
|
33
|
+
|
|
34
|
+
// No harm if `i` is already set.
|
|
35
|
+
void Set(size_t i) {
|
|
36
|
+
HWY_DASSERT(i < 64);
|
|
37
|
+
bits_ |= (1ULL << i);
|
|
38
|
+
HWY_DASSERT(Get(i));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Equivalent to Set(i) for i in [0, 64) where (bits >> i) & 1. This does
|
|
42
|
+
// not clear any existing bits.
|
|
43
|
+
void SetNonzeroBitsFrom64(uint64_t bits) { bits_ |= bits; }
|
|
44
|
+
|
|
45
|
+
void Clear(size_t i) {
|
|
46
|
+
HWY_DASSERT(i < 64);
|
|
47
|
+
bits_ &= ~(1ULL << i);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
bool Get(size_t i) const {
|
|
51
|
+
HWY_DASSERT(i < 64);
|
|
52
|
+
return (bits_ & (1ULL << i)) != 0;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Returns true if Get(i) would return true for any i in [0, 64).
|
|
56
|
+
bool Any() const { return bits_ != 0; }
|
|
57
|
+
|
|
58
|
+
// Returns true if Get(i) would return true for all i in [0, 64).
|
|
59
|
+
bool All() const { return bits_ == ~uint64_t{0}; }
|
|
60
|
+
|
|
61
|
+
// Returns lowest i such that `Get(i)`. Caller must first ensure `Any()`!
|
|
62
|
+
size_t First() const {
|
|
63
|
+
HWY_DASSERT(Any());
|
|
64
|
+
return Num0BitsBelowLS1Bit_Nonzero64(bits_);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Returns lowest i such that `!Get(i)`. Caller must first ensure `!All()`!
|
|
68
|
+
size_t First0() const {
|
|
69
|
+
HWY_DASSERT(!All());
|
|
70
|
+
return Num0BitsBelowLS1Bit_Nonzero64(~bits_);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Returns uint64_t(Get(i)) << i for i in [0, 64).
|
|
74
|
+
uint64_t Get64() const { return bits_; }
|
|
75
|
+
|
|
76
|
+
// Calls `func(i)` for each `i` in the set. It is safe for `func` to modify
|
|
77
|
+
// the set, but the current Foreach call is unaffected.
|
|
78
|
+
template <class Func>
|
|
79
|
+
void Foreach(const Func& func) const {
|
|
80
|
+
uint64_t remaining_bits = bits_;
|
|
81
|
+
while (remaining_bits != 0) {
|
|
82
|
+
const size_t i = Num0BitsBelowLS1Bit_Nonzero64(remaining_bits);
|
|
83
|
+
remaining_bits &= remaining_bits - 1; // clear LSB
|
|
84
|
+
func(i);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
size_t Count() const { return PopCount(bits_); }
|
|
89
|
+
|
|
90
|
+
private:
|
|
91
|
+
uint64_t bits_ = 0;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
// Any number of bits, flat array.
|
|
95
|
+
template <size_t kMaxSize>
|
|
96
|
+
class BitSet {
|
|
97
|
+
static_assert(kMaxSize != 0, "BitSet requires non-zero size");
|
|
98
|
+
|
|
99
|
+
public:
|
|
100
|
+
constexpr size_t MaxSize() const { return kMaxSize; }
|
|
101
|
+
|
|
102
|
+
// No harm if `i` is already set.
|
|
103
|
+
void Set(size_t i) {
|
|
104
|
+
HWY_DASSERT(i < kMaxSize);
|
|
105
|
+
const size_t idx = i / 64;
|
|
106
|
+
const size_t mod = i % 64;
|
|
107
|
+
bits_[idx].Set(mod);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
void Clear(size_t i) {
|
|
111
|
+
HWY_DASSERT(i < kMaxSize);
|
|
112
|
+
const size_t idx = i / 64;
|
|
113
|
+
const size_t mod = i % 64;
|
|
114
|
+
bits_[idx].Clear(mod);
|
|
115
|
+
HWY_DASSERT(!Get(i));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
bool Get(size_t i) const {
|
|
119
|
+
HWY_DASSERT(i < kMaxSize);
|
|
120
|
+
const size_t idx = i / 64;
|
|
121
|
+
const size_t mod = i % 64;
|
|
122
|
+
return bits_[idx].Get(mod);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Returns true if Get(i) would return true for any i in [0, kMaxSize).
|
|
126
|
+
bool Any() const {
|
|
127
|
+
for (const BitSet64& bits : bits_) {
|
|
128
|
+
if (bits.Any()) return true;
|
|
129
|
+
}
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Returns true if Get(i) would return true for all i in [0, kMaxSize).
|
|
134
|
+
bool All() const {
|
|
135
|
+
for (size_t idx = 0; idx < kNum64 - 1; ++idx) {
|
|
136
|
+
if (!bits_[idx].All()) return false;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
constexpr size_t kRemainder = kMaxSize % 64;
|
|
140
|
+
if (kRemainder == 0) {
|
|
141
|
+
return bits_[kNum64 - 1].All();
|
|
142
|
+
}
|
|
143
|
+
return bits_[kNum64 - 1].Count() == kRemainder;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Returns lowest i such that `Get(i)`. Caller must first ensure `Any()`!
|
|
147
|
+
size_t First() const {
|
|
148
|
+
HWY_DASSERT(Any());
|
|
149
|
+
for (size_t idx = 0;; ++idx) {
|
|
150
|
+
HWY_DASSERT(idx < kNum64);
|
|
151
|
+
if (bits_[idx].Any()) return idx * 64 + bits_[idx].First();
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Returns lowest i such that `!Get(i)`. Caller must first ensure `All()`!
|
|
156
|
+
size_t First0() const {
|
|
157
|
+
HWY_DASSERT(!All());
|
|
158
|
+
for (size_t idx = 0;; ++idx) {
|
|
159
|
+
HWY_DASSERT(idx < kNum64);
|
|
160
|
+
if (!bits_[idx].All()) {
|
|
161
|
+
const size_t first0 = idx * 64 + bits_[idx].First0();
|
|
162
|
+
HWY_DASSERT(first0 < kMaxSize);
|
|
163
|
+
return first0;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Calls `func(i)` for each `i` in the set. It is safe for `func` to modify
|
|
169
|
+
// the set, but the current Foreach call is only affected if changing one of
|
|
170
|
+
// the not yet visited BitSet64.
|
|
171
|
+
template <class Func>
|
|
172
|
+
void Foreach(const Func& func) const {
|
|
173
|
+
for (size_t idx = 0; idx < kNum64; ++idx) {
|
|
174
|
+
bits_[idx].Foreach([idx, &func](size_t mod) { func(idx * 64 + mod); });
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
size_t Count() const {
|
|
179
|
+
size_t total = 0;
|
|
180
|
+
for (const BitSet64& bits : bits_) {
|
|
181
|
+
total += bits.Count();
|
|
182
|
+
}
|
|
183
|
+
return total;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private:
|
|
187
|
+
static constexpr size_t kNum64 = DivCeil(kMaxSize, size_t{64});
|
|
188
|
+
BitSet64 bits_[kNum64];
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
// Any number of bits, flat array, atomic updates to the u64.
|
|
192
|
+
template <size_t kMaxSize>
|
|
193
|
+
class AtomicBitSet {
|
|
194
|
+
static_assert(kMaxSize != 0, "AtomicBitSet requires non-zero size");
|
|
195
|
+
|
|
196
|
+
// Bits may signal something to other threads, hence relaxed is insufficient.
|
|
197
|
+
// Acq/Rel ensures a happens-before relationship.
|
|
198
|
+
static constexpr auto kAcq = std::memory_order_acquire;
|
|
199
|
+
static constexpr auto kRel = std::memory_order_release;
|
|
200
|
+
|
|
201
|
+
public:
|
|
202
|
+
constexpr size_t MaxSize() const { return kMaxSize; }
|
|
203
|
+
|
|
204
|
+
// No harm if `i` is already set.
|
|
205
|
+
void Set(size_t i) {
|
|
206
|
+
HWY_DASSERT(i < kMaxSize);
|
|
207
|
+
const size_t idx = i / 64;
|
|
208
|
+
const size_t mod = i % 64;
|
|
209
|
+
bits_[idx].fetch_or(1ULL << mod, kRel);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
void Clear(size_t i) {
|
|
213
|
+
HWY_DASSERT(i < kMaxSize);
|
|
214
|
+
const size_t idx = i / 64;
|
|
215
|
+
const size_t mod = i % 64;
|
|
216
|
+
bits_[idx].fetch_and(~(1ULL << mod), kRel);
|
|
217
|
+
HWY_DASSERT(!Get(i));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
bool Get(size_t i) const {
|
|
221
|
+
HWY_DASSERT(i < kMaxSize);
|
|
222
|
+
const size_t idx = i / 64;
|
|
223
|
+
const size_t mod = i % 64;
|
|
224
|
+
return ((bits_[idx].load(kAcq) & (1ULL << mod))) != 0;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Returns true if Get(i) would return true for any i in [0, kMaxSize).
|
|
228
|
+
bool Any() const {
|
|
229
|
+
for (const std::atomic<uint64_t>& bits : bits_) {
|
|
230
|
+
if (bits.load(kAcq)) return true;
|
|
231
|
+
}
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Returns true if Get(i) would return true for all i in [0, kMaxSize).
|
|
236
|
+
bool All() const {
|
|
237
|
+
for (size_t idx = 0; idx < kNum64 - 1; ++idx) {
|
|
238
|
+
if (bits_[idx].load(kAcq) != ~uint64_t{0}) return false;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
constexpr size_t kRemainder = kMaxSize % 64;
|
|
242
|
+
const uint64_t last_bits = bits_[kNum64 - 1].load(kAcq);
|
|
243
|
+
if (kRemainder == 0) {
|
|
244
|
+
return last_bits == ~uint64_t{0};
|
|
245
|
+
}
|
|
246
|
+
return PopCount(last_bits) == kRemainder;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Returns lowest i such that `Get(i)`. Caller must first ensure `Any()`!
|
|
250
|
+
size_t First() const {
|
|
251
|
+
HWY_DASSERT(Any());
|
|
252
|
+
for (size_t idx = 0;; ++idx) {
|
|
253
|
+
HWY_DASSERT(idx < kNum64);
|
|
254
|
+
const uint64_t bits = bits_[idx].load(kAcq);
|
|
255
|
+
if (bits != 0) {
|
|
256
|
+
return idx * 64 + Num0BitsBelowLS1Bit_Nonzero64(bits);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Returns lowest i such that `!Get(i)`. Caller must first ensure `!All()`!
|
|
262
|
+
size_t First0() const {
|
|
263
|
+
HWY_DASSERT(!All());
|
|
264
|
+
for (size_t idx = 0;; ++idx) {
|
|
265
|
+
HWY_DASSERT(idx < kNum64);
|
|
266
|
+
const uint64_t inv_bits = ~bits_[idx].load(kAcq);
|
|
267
|
+
if (inv_bits != 0) {
|
|
268
|
+
const size_t first0 =
|
|
269
|
+
idx * 64 + Num0BitsBelowLS1Bit_Nonzero64(inv_bits);
|
|
270
|
+
HWY_DASSERT(first0 < kMaxSize);
|
|
271
|
+
return first0;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Calls `func(i)` for each `i` in the set. It is safe for `func` to modify
|
|
277
|
+
// the set, but the current Foreach call is only affected if changing one of
|
|
278
|
+
// the not yet visited uint64_t.
|
|
279
|
+
template <class Func>
|
|
280
|
+
void Foreach(const Func& func) const {
|
|
281
|
+
for (size_t idx = 0; idx < kNum64; ++idx) {
|
|
282
|
+
uint64_t remaining_bits = bits_[idx].load(kAcq);
|
|
283
|
+
while (remaining_bits != 0) {
|
|
284
|
+
const size_t i = Num0BitsBelowLS1Bit_Nonzero64(remaining_bits);
|
|
285
|
+
remaining_bits &= remaining_bits - 1; // clear LSB
|
|
286
|
+
func(idx * 64 + i);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
size_t Count() const {
|
|
292
|
+
size_t total = 0;
|
|
293
|
+
for (const std::atomic<uint64_t>& bits : bits_) {
|
|
294
|
+
total += PopCount(bits.load(kAcq));
|
|
295
|
+
}
|
|
296
|
+
return total;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
private:
|
|
300
|
+
static constexpr size_t kNum64 = DivCeil(kMaxSize, size_t{64});
|
|
301
|
+
std::atomic<uint64_t> bits_[kNum64] = {};
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
// Two-level bitset for up to `kMaxSize` <= 4096 values. The iterators
|
|
305
|
+
// (`Any/First/Foreach/Count`) are more efficient than `BitSet` for sparse sets.
|
|
306
|
+
// This comes at the cost of slightly slower mutators (`Set/Clear`).
|
|
307
|
+
template <size_t kMaxSize = 4096>
|
|
308
|
+
class BitSet4096 {
|
|
309
|
+
static_assert(kMaxSize != 0, "BitSet4096 requires non-zero size");
|
|
310
|
+
|
|
311
|
+
public:
|
|
312
|
+
constexpr size_t MaxSize() const { return kMaxSize; }
|
|
313
|
+
|
|
314
|
+
// No harm if `i` is already set.
|
|
315
|
+
void Set(size_t i) {
|
|
316
|
+
HWY_DASSERT(i < kMaxSize);
|
|
317
|
+
const size_t idx = i / 64;
|
|
318
|
+
const size_t mod = i % 64;
|
|
319
|
+
bits_[idx].Set(mod);
|
|
320
|
+
nonzero_.Set(idx);
|
|
321
|
+
HWY_DASSERT(Get(i));
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Equivalent to Set(i) for i in [0, 64) where (bits >> i) & 1. This does
|
|
325
|
+
// not clear any existing bits.
|
|
326
|
+
void SetNonzeroBitsFrom64(uint64_t bits) {
|
|
327
|
+
bits_[0].SetNonzeroBitsFrom64(bits);
|
|
328
|
+
if (bits) nonzero_.Set(0);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
void Clear(size_t i) {
|
|
332
|
+
HWY_DASSERT(i < kMaxSize);
|
|
333
|
+
const size_t idx = i / 64;
|
|
334
|
+
const size_t mod = i % 64;
|
|
335
|
+
bits_[idx].Clear(mod);
|
|
336
|
+
if (!bits_[idx].Any()) {
|
|
337
|
+
nonzero_.Clear(idx);
|
|
338
|
+
}
|
|
339
|
+
HWY_DASSERT(!Get(i));
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
bool Get(size_t i) const {
|
|
343
|
+
HWY_DASSERT(i < kMaxSize);
|
|
344
|
+
const size_t idx = i / 64;
|
|
345
|
+
const size_t mod = i % 64;
|
|
346
|
+
return bits_[idx].Get(mod);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Returns true if `Get(i)` would return true for any i in [0, kMaxSize).
|
|
350
|
+
bool Any() const { return nonzero_.Any(); }
|
|
351
|
+
|
|
352
|
+
// Returns true if `Get(i)` would return true for all i in [0, kMaxSize).
|
|
353
|
+
bool All() const {
|
|
354
|
+
// Do not check `nonzero_.All()` - that only works if `kMaxSize` is 4096.
|
|
355
|
+
if (nonzero_.Count() != kNum64) return false;
|
|
356
|
+
return Count() == kMaxSize;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Returns lowest i such that `Get(i)`. Caller must first ensure `Any()`!
|
|
360
|
+
size_t First() const {
|
|
361
|
+
HWY_DASSERT(Any());
|
|
362
|
+
const size_t idx = nonzero_.First();
|
|
363
|
+
return idx * 64 + bits_[idx].First();
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Returns lowest i such that `!Get(i)`. Caller must first ensure `!All()`!
|
|
367
|
+
size_t First0() const {
|
|
368
|
+
HWY_DASSERT(!All());
|
|
369
|
+
// It is likely not worthwhile to have a separate `BitSet64` for `not_all_`,
|
|
370
|
+
// hence iterate over all u64.
|
|
371
|
+
for (size_t idx = 0;; ++idx) {
|
|
372
|
+
HWY_DASSERT(idx < kNum64);
|
|
373
|
+
if (!bits_[idx].All()) {
|
|
374
|
+
const size_t first0 = idx * 64 + bits_[idx].First0();
|
|
375
|
+
HWY_DASSERT(first0 < kMaxSize);
|
|
376
|
+
return first0;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// Returns uint64_t(Get(i)) << i for i in [0, 64).
|
|
382
|
+
uint64_t Get64() const { return bits_[0].Get64(); }
|
|
383
|
+
|
|
384
|
+
// Calls `func(i)` for each `i` in the set. It is safe for `func` to modify
|
|
385
|
+
// the set, but the current Foreach call is only affected if changing one of
|
|
386
|
+
// the not yet visited BitSet64 for which Any() is true.
|
|
387
|
+
template <class Func>
|
|
388
|
+
void Foreach(const Func& func) const {
|
|
389
|
+
nonzero_.Foreach([&func, this](size_t idx) {
|
|
390
|
+
bits_[idx].Foreach([idx, &func](size_t mod) { func(idx * 64 + mod); });
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
size_t Count() const {
|
|
395
|
+
size_t total = 0;
|
|
396
|
+
nonzero_.Foreach(
|
|
397
|
+
[&total, this](size_t idx) { total += bits_[idx].Count(); });
|
|
398
|
+
return total;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
private:
|
|
402
|
+
static_assert(kMaxSize <= 64 * 64, "One BitSet64 insufficient");
|
|
403
|
+
static constexpr size_t kNum64 = DivCeil(kMaxSize, size_t{64});
|
|
404
|
+
BitSet64 nonzero_;
|
|
405
|
+
BitSet64 bits_[kNum64];
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
} // namespace hwy
|
|
409
|
+
|
|
410
|
+
#endif // HIGHWAY_HWY_BIT_SET_H_
|
|
@@ -98,9 +98,10 @@ template <typename T>
|
|
|
98
98
|
HWY_INLINE HWY_ATTR_CACHE void Prefetch(const T* p) {
|
|
99
99
|
(void)p;
|
|
100
100
|
#ifndef HWY_DISABLE_CACHE_CONTROL
|
|
101
|
-
|
|
101
|
+
// Use _mm_prefetch on x86/x64, except when clang-cl is compiled with -mno-mmx.
|
|
102
|
+
#if HWY_ARCH_X86 && !(HWY_COMPILER_CLANGCL && !defined(__MMX__))
|
|
102
103
|
_mm_prefetch(reinterpret_cast<const char*>(p), _MM_HINT_T0);
|
|
103
|
-
#elif HWY_COMPILER_GCC // includes clang
|
|
104
|
+
#elif HWY_COMPILER_GCC || HWY_COMPILER_CLANGCL // includes clang
|
|
104
105
|
// Hint=0 (NTA) behavior differs, but skipping outer caches is probably not
|
|
105
106
|
// desirable, so use the default 3 (keep in caches).
|
|
106
107
|
__builtin_prefetch(p, /*write=*/0, /*hint=*/3);
|