digest-xxhash 0.2.6 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0d340515d2a46b42bc5c332465a18de3bac90949c8e4d694a040b537d47bf742
4
- data.tar.gz: 347fd239d94cb06cef8760e6f9146b4c7aaa70032ae74005cb2f81ba703e3217
3
+ metadata.gz: dd4724a81a8591422e26de9b1374b843cd6658c9b489d30e8aa1cb1079d85da6
4
+ data.tar.gz: 430d6b738c1e4ccbfa9d876de7c797b364c3a8ed8c7a027a361aca87c149c2a2
5
5
  SHA512:
6
- metadata.gz: e15847af311052541303513833fb79881e4798a3fac0127b26a41bce200e6f8c141dae525c93746710da1d0b5977e7fbce03302f74c8d88181a0d24215c3fa71
7
- data.tar.gz: 361d7b1e29837803ade9545a4c9f86f01275d4b21680a69a3f154d1849b6d31bd5d80f4ff3c291e1d74bab0b1be28e66ee1f9380f040b7570e85124744d6548b
6
+ metadata.gz: 1a632aa6781227200270fdcf82afe3df388ef409e157e19e7a86d71b3c627d193e46a8f86a343deb864ae1463f2300735fd42d8e53b3c9f0af78cddb8f528ee7
7
+ data.tar.gz: eb4cf2422fc4e74034599ebf7012aef294230469de57cfab9105061480113ed4b74b799815de8bd2b1d1d3eafc5fdb2cbe0478c220565e6bda0479015dd7b7c7
@@ -43,7 +43,7 @@ Gem::Specification.new do |spec|
43
43
  spec.require_paths = ["lib"]
44
44
 
45
45
  spec.add_development_dependency "rake"
46
- spec.add_development_dependency "rake-compiler", "~> 1.0", "!= 1.1.3", "!= 1.1.4", "!= 1.1.5"
46
+ spec.add_development_dependency "rake-compiler", "~> 1.2", ">= 1.2.3"
47
47
  spec.add_development_dependency "minitest", "~> 5.8"
48
48
 
49
49
  spec.extensions = %w[ext/digest/xxhash/extconf.rb]
@@ -182,6 +182,33 @@ extern "C" {
182
182
  * @{
183
183
  */
184
184
  #ifdef XXH_DOXYGEN
185
+ /*!
186
+ * @brief Gives access to internal state declaration, required for static allocation.
187
+ *
188
+ * Incompatible with dynamic linking, due to risks of ABI changes.
189
+ *
190
+ * Usage:
191
+ * @code{.c}
192
+ * #define XXH_STATIC_LINKING_ONLY
193
+ * #include "xxhash.h"
194
+ * @endcode
195
+ */
196
+ # define XXH_STATIC_LINKING_ONLY
197
+ /* Do not undef XXH_STATIC_LINKING_ONLY for Doxygen */
198
+
199
+ /*!
200
+ * @brief Gives access to internal definitions.
201
+ *
202
+ * Usage:
203
+ * @code{.c}
204
+ * #define XXH_STATIC_LINKING_ONLY
205
+ * #define XXH_IMPLEMENTATION
206
+ * #include "xxhash.h"
207
+ * @endcode
208
+ */
209
+ # define XXH_IMPLEMENTATION
210
+ /* Do not undef XXH_IMPLEMENTATION for Doxygen */
211
+
185
212
  /*!
186
213
  * @brief Exposes the implementation and marks all functions as `inline`.
187
214
  *
@@ -448,7 +475,7 @@ extern "C" {
448
475
  ***************************************/
449
476
  #define XXH_VERSION_MAJOR 0
450
477
  #define XXH_VERSION_MINOR 8
451
- #define XXH_VERSION_RELEASE 1
478
+ #define XXH_VERSION_RELEASE 2
452
479
  /*! @brief Version number, encoded as two digits each */
453
480
  #define XXH_VERSION_NUMBER (XXH_VERSION_MAJOR *100*100 + XXH_VERSION_MINOR *100 + XXH_VERSION_RELEASE)
454
481
 
@@ -710,32 +737,41 @@ XXH_PUBLIC_API void XXH32_canonicalFromHash(XXH32_canonical_t* dst, XXH32_hash_t
710
737
  XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canonical_t* src);
711
738
 
712
739
 
740
+ /*! @cond Doxygen ignores this part */
713
741
  #ifdef __has_attribute
714
742
  # define XXH_HAS_ATTRIBUTE(x) __has_attribute(x)
715
743
  #else
716
744
  # define XXH_HAS_ATTRIBUTE(x) 0
717
745
  #endif
746
+ /*! @endcond */
718
747
 
748
+ /*! @cond Doxygen ignores this part */
719
749
  /*
720
750
  * C23 __STDC_VERSION__ number hasn't been specified yet. For now
721
751
  * leave as `201711L` (C17 + 1).
722
752
  * TODO: Update to correct value when its been specified.
723
753
  */
724
754
  #define XXH_C23_VN 201711L
755
+ /*! @endcond */
725
756
 
757
+ /*! @cond Doxygen ignores this part */
726
758
  /* C-language Attributes are added in C23. */
727
759
  #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= XXH_C23_VN) && defined(__has_c_attribute)
728
760
  # define XXH_HAS_C_ATTRIBUTE(x) __has_c_attribute(x)
729
761
  #else
730
762
  # define XXH_HAS_C_ATTRIBUTE(x) 0
731
763
  #endif
764
+ /*! @endcond */
732
765
 
766
+ /*! @cond Doxygen ignores this part */
733
767
  #if defined(__cplusplus) && defined(__has_cpp_attribute)
734
768
  # define XXH_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
735
769
  #else
736
770
  # define XXH_HAS_CPP_ATTRIBUTE(x) 0
737
771
  #endif
772
+ /*! @endcond */
738
773
 
774
+ /*! @cond Doxygen ignores this part */
739
775
  /*
740
776
  * Define XXH_FALLTHROUGH macro for annotating switch case with the 'fallthrough' attribute
741
777
  * introduced in CPP17 and C23.
@@ -749,7 +785,9 @@ XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canoni
749
785
  #else
750
786
  # define XXH_FALLTHROUGH /* fallthrough */
751
787
  #endif
788
+ /*! @endcond */
752
789
 
790
+ /*! @cond Doxygen ignores this part */
753
791
  /*
754
792
  * Define XXH_NOESCAPE for annotated pointers in public API.
755
793
  * https://clang.llvm.org/docs/AttributeReference.html#noescape
@@ -760,6 +798,7 @@ XXH_PUBLIC_API XXH_PUREF XXH32_hash_t XXH32_hashFromCanonical(const XXH32_canoni
760
798
  #else
761
799
  # define XXH_NOESCAPE
762
800
  #endif
801
+ /*! @endcond */
763
802
 
764
803
 
765
804
  /*!
@@ -842,17 +881,113 @@ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64(XXH_NOESCAPE const void* input, size
842
881
  * @see XXH64_state_s for details.
843
882
  */
844
883
  typedef struct XXH64_state_s XXH64_state_t; /* incomplete type */
884
+
885
+ /*!
886
+ * @brief Allocates an @ref XXH64_state_t.
887
+ *
888
+ * Must be freed with XXH64_freeState().
889
+ * @return An allocated XXH64_state_t on success, `NULL` on failure.
890
+ */
845
891
  XXH_PUBLIC_API XXH_MALLOCF XXH64_state_t* XXH64_createState(void);
892
+
893
+ /*!
894
+ * @brief Frees an @ref XXH64_state_t.
895
+ *
896
+ * Must be allocated with XXH64_createState().
897
+ * @param statePtr A pointer to an @ref XXH64_state_t allocated with @ref XXH64_createState().
898
+ * @return XXH_OK.
899
+ */
846
900
  XXH_PUBLIC_API XXH_errorcode XXH64_freeState(XXH64_state_t* statePtr);
901
+
902
+ /*!
903
+ * @brief Copies one @ref XXH64_state_t to another.
904
+ *
905
+ * @param dst_state The state to copy to.
906
+ * @param src_state The state to copy from.
907
+ * @pre
908
+ * @p dst_state and @p src_state must not be `NULL` and must not overlap.
909
+ */
847
910
  XXH_PUBLIC_API void XXH64_copyState(XXH_NOESCAPE XXH64_state_t* dst_state, const XXH64_state_t* src_state);
848
911
 
912
+ /*!
913
+ * @brief Resets an @ref XXH64_state_t to begin a new hash.
914
+ *
915
+ * This function resets and seeds a state. Call it before @ref XXH64_update().
916
+ *
917
+ * @param statePtr The state struct to reset.
918
+ * @param seed The 64-bit seed to alter the hash result predictably.
919
+ *
920
+ * @pre
921
+ * @p statePtr must not be `NULL`.
922
+ *
923
+ * @return @ref XXH_OK on success, @ref XXH_ERROR on failure.
924
+ */
849
925
  XXH_PUBLIC_API XXH_errorcode XXH64_reset (XXH_NOESCAPE XXH64_state_t* statePtr, XXH64_hash_t seed);
926
+
927
+ /*!
928
+ * @brief Consumes a block of @p input to an @ref XXH64_state_t.
929
+ *
930
+ * Call this to incrementally consume blocks of data.
931
+ *
932
+ * @param statePtr The state struct to update.
933
+ * @param input The block of data to be hashed, at least @p length bytes in size.
934
+ * @param length The length of @p input, in bytes.
935
+ *
936
+ * @pre
937
+ * @p statePtr must not be `NULL`.
938
+ * @pre
939
+ * The memory between @p input and @p input + @p length must be valid,
940
+ * readable, contiguous memory. However, if @p length is `0`, @p input may be
941
+ * `NULL`. In C++, this also must be *TriviallyCopyable*.
942
+ *
943
+ * @return @ref XXH_OK on success, @ref XXH_ERROR on failure.
944
+ */
850
945
  XXH_PUBLIC_API XXH_errorcode XXH64_update (XXH_NOESCAPE XXH64_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length);
946
+
947
+ /*!
948
+ * @brief Returns the calculated hash value from an @ref XXH64_state_t.
949
+ *
950
+ * @note
951
+ * Calling XXH64_digest() will not affect @p statePtr, so you can update,
952
+ * digest, and update again.
953
+ *
954
+ * @param statePtr The state struct to calculate the hash from.
955
+ *
956
+ * @pre
957
+ * @p statePtr must not be `NULL`.
958
+ *
959
+ * @return The calculated xxHash64 value from that state.
960
+ */
851
961
  XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_digest (XXH_NOESCAPE const XXH64_state_t* statePtr);
852
962
  #endif /* !XXH_NO_STREAM */
853
963
  /******* Canonical representation *******/
964
+
965
+ /*!
966
+ * @brief Canonical (big endian) representation of @ref XXH64_hash_t.
967
+ */
854
968
  typedef struct { unsigned char digest[sizeof(XXH64_hash_t)]; } XXH64_canonical_t;
969
+
970
+ /*!
971
+ * @brief Converts an @ref XXH64_hash_t to a big endian @ref XXH64_canonical_t.
972
+ *
973
+ * @param dst The @ref XXH64_canonical_t pointer to be stored to.
974
+ * @param hash The @ref XXH64_hash_t to be converted.
975
+ *
976
+ * @pre
977
+ * @p dst must not be `NULL`.
978
+ */
855
979
  XXH_PUBLIC_API void XXH64_canonicalFromHash(XXH_NOESCAPE XXH64_canonical_t* dst, XXH64_hash_t hash);
980
+
981
+ /*!
982
+ * @brief Converts an @ref XXH64_canonical_t to a native @ref XXH64_hash_t.
983
+ *
984
+ * @param src The @ref XXH64_canonical_t to convert.
985
+ *
986
+ * @pre
987
+ * @p src must not be `NULL`.
988
+ *
989
+ * @return The converted hash.
990
+ */
856
991
  XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_canonical_t* src);
857
992
 
858
993
  #ifndef XXH_NO_XXH3
@@ -884,10 +1019,18 @@ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const
884
1019
  * at competitive speeds, even without vector support. Further details are
885
1020
  * explained in the implementation.
886
1021
  *
887
- * Optimized implementations are provided for AVX512, AVX2, SSE2, NEON, POWER8,
888
- * ZVector and scalar targets. This can be controlled via the @ref XXH_VECTOR
889
- * macro. For the x86 family, an automatic dispatcher is included separately
890
- * in @ref xxh_x86dispatch.c.
1022
+ * XXH3 has a fast scalar implementation, but it also includes accelerated SIMD
1023
+ * implementations for many common platforms:
1024
+ * - AVX512
1025
+ * - AVX2
1026
+ * - SSE2
1027
+ * - ARM NEON
1028
+ * - WebAssembly SIMD128
1029
+ * - POWER8 VSX
1030
+ * - s390x ZVector
1031
+ * This can be controlled via the @ref XXH_VECTOR macro, but it automatically
1032
+ * selects the best version according to predefined macros. For the x86 family, an
1033
+ * automatic runtime dispatcher is included separately in @ref xxh_x86dispatch.c.
891
1034
  *
892
1035
  * XXH3 implementation is portable:
893
1036
  * it has a generic C90 formulation that can be compiled on any platform,
@@ -987,20 +1130,50 @@ XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_withSecret(XXH_NOESCAPE const
987
1130
  typedef struct XXH3_state_s XXH3_state_t;
988
1131
  XXH_PUBLIC_API XXH_MALLOCF XXH3_state_t* XXH3_createState(void);
989
1132
  XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr);
1133
+
1134
+ /*!
1135
+ * @brief Copies one @ref XXH3_state_t to another.
1136
+ *
1137
+ * @param dst_state The state to copy to.
1138
+ * @param src_state The state to copy from.
1139
+ * @pre
1140
+ * @p dst_state and @p src_state must not be `NULL` and must not overlap.
1141
+ */
990
1142
  XXH_PUBLIC_API void XXH3_copyState(XXH_NOESCAPE XXH3_state_t* dst_state, XXH_NOESCAPE const XXH3_state_t* src_state);
991
1143
 
992
- /*
993
- * XXH3_64bits_reset():
994
- * Initialize with default parameters.
995
- * digest will be equivalent to `XXH3_64bits()`.
1144
+ /*!
1145
+ * @brief Resets an @ref XXH3_state_t to begin a new hash.
1146
+ *
1147
+ * This function resets `statePtr` and generate a secret with default parameters. Call it before @ref XXH3_64bits_update().
1148
+ * Digest will be equivalent to `XXH3_64bits()`.
1149
+ *
1150
+ * @param statePtr The state struct to reset.
1151
+ *
1152
+ * @pre
1153
+ * @p statePtr must not be `NULL`.
1154
+ *
1155
+ * @return @ref XXH_OK on success, @ref XXH_ERROR on failure.
1156
+ *
996
1157
  */
997
1158
  XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr);
998
- /*
999
- * XXH3_64bits_reset_withSeed():
1000
- * Generate a custom secret from `seed`, and store it into `statePtr`.
1001
- * digest will be equivalent to `XXH3_64bits_withSeed()`.
1159
+
1160
+ /*!
1161
+ * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash.
1162
+ *
1163
+ * This function resets `statePtr` and generate a secret from `seed`. Call it before @ref XXH3_64bits_update().
1164
+ * Digest will be equivalent to `XXH3_64bits_withSeed()`.
1165
+ *
1166
+ * @param statePtr The state struct to reset.
1167
+ * @param seed The 64-bit seed to alter the state.
1168
+ *
1169
+ * @pre
1170
+ * @p statePtr must not be `NULL`.
1171
+ *
1172
+ * @return @ref XXH_OK on success, @ref XXH_ERROR on failure.
1173
+ *
1002
1174
  */
1003
1175
  XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed);
1176
+
1004
1177
  /*!
1005
1178
  * XXH3_64bits_reset_withSecret():
1006
1179
  * `secret` is referenced, it _must outlive_ the hash streaming session.
@@ -1012,7 +1185,40 @@ XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSeed(XXH_NOESCAPE XXH3_state_
1012
1185
  */
1013
1186
  XXH_PUBLIC_API XXH_errorcode XXH3_64bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize);
1014
1187
 
1188
+ /*!
1189
+ * @brief Consumes a block of @p input to an @ref XXH3_state_t.
1190
+ *
1191
+ * Call this to incrementally consume blocks of data.
1192
+ *
1193
+ * @param statePtr The state struct to update.
1194
+ * @param input The block of data to be hashed, at least @p length bytes in size.
1195
+ * @param length The length of @p input, in bytes.
1196
+ *
1197
+ * @pre
1198
+ * @p statePtr must not be `NULL`.
1199
+ * @pre
1200
+ * The memory between @p input and @p input + @p length must be valid,
1201
+ * readable, contiguous memory. However, if @p length is `0`, @p input may be
1202
+ * `NULL`. In C++, this also must be *TriviallyCopyable*.
1203
+ *
1204
+ * @return @ref XXH_OK on success, @ref XXH_ERROR on failure.
1205
+ */
1015
1206
  XXH_PUBLIC_API XXH_errorcode XXH3_64bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length);
1207
+
1208
+ /*!
1209
+ * @brief Returns the calculated XXH3 64-bit hash value from an @ref XXH3_state_t.
1210
+ *
1211
+ * @note
1212
+ * Calling XXH3_64bits_digest() will not affect @p statePtr, so you can update,
1213
+ * digest, and update again.
1214
+ *
1215
+ * @param statePtr The state struct to calculate the hash from.
1216
+ *
1217
+ * @pre
1218
+ * @p statePtr must not be `NULL`.
1219
+ *
1220
+ * @return The calculated XXH3 64-bit hash value from that state.
1221
+ */
1016
1222
  XXH_PUBLIC_API XXH_PUREF XXH64_hash_t XXH3_64bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr);
1017
1223
  #endif /* !XXH_NO_STREAM */
1018
1224
 
@@ -1072,11 +1278,75 @@ XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_withSecret(XXH_NOESCAPE cons
1072
1278
  * All reset and streaming functions have same meaning as their 64-bit counterpart.
1073
1279
  */
1074
1280
 
1281
+ /*!
1282
+ * @brief Resets an @ref XXH3_state_t to begin a new hash.
1283
+ *
1284
+ * This function resets `statePtr` and generate a secret with default parameters. Call it before @ref XXH3_128bits_update().
1285
+ * Digest will be equivalent to `XXH3_128bits()`.
1286
+ *
1287
+ * @param statePtr The state struct to reset.
1288
+ *
1289
+ * @pre
1290
+ * @p statePtr must not be `NULL`.
1291
+ *
1292
+ * @return @ref XXH_OK on success, @ref XXH_ERROR on failure.
1293
+ *
1294
+ */
1075
1295
  XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset(XXH_NOESCAPE XXH3_state_t* statePtr);
1296
+
1297
+ /*!
1298
+ * @brief Resets an @ref XXH3_state_t with 64-bit seed to begin a new hash.
1299
+ *
1300
+ * This function resets `statePtr` and generate a secret from `seed`. Call it before @ref XXH3_128bits_update().
1301
+ * Digest will be equivalent to `XXH3_128bits_withSeed()`.
1302
+ *
1303
+ * @param statePtr The state struct to reset.
1304
+ * @param seed The 64-bit seed to alter the state.
1305
+ *
1306
+ * @pre
1307
+ * @p statePtr must not be `NULL`.
1308
+ *
1309
+ * @return @ref XXH_OK on success, @ref XXH_ERROR on failure.
1310
+ *
1311
+ */
1076
1312
  XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSeed(XXH_NOESCAPE XXH3_state_t* statePtr, XXH64_hash_t seed);
1313
+ /*! @brief Custom secret 128-bit variant of XXH3. @see XXH_64bits_reset_withSecret(). */
1077
1314
  XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecret(XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* secret, size_t secretSize);
1078
1315
 
1316
+ /*!
1317
+ * @brief Consumes a block of @p input to an @ref XXH3_state_t.
1318
+ *
1319
+ * Call this to incrementally consume blocks of data.
1320
+ *
1321
+ * @param statePtr The state struct to update.
1322
+ * @param input The block of data to be hashed, at least @p length bytes in size.
1323
+ * @param length The length of @p input, in bytes.
1324
+ *
1325
+ * @pre
1326
+ * @p statePtr must not be `NULL`.
1327
+ * @pre
1328
+ * The memory between @p input and @p input + @p length must be valid,
1329
+ * readable, contiguous memory. However, if @p length is `0`, @p input may be
1330
+ * `NULL`. In C++, this also must be *TriviallyCopyable*.
1331
+ *
1332
+ * @return @ref XXH_OK on success, @ref XXH_ERROR on failure.
1333
+ */
1079
1334
  XXH_PUBLIC_API XXH_errorcode XXH3_128bits_update (XXH_NOESCAPE XXH3_state_t* statePtr, XXH_NOESCAPE const void* input, size_t length);
1335
+
1336
+ /*!
1337
+ * @brief Returns the calculated XXH3 128-bit hash value from an @ref XXH3_state_t.
1338
+ *
1339
+ * @note
1340
+ * Calling XXH3_128bits_digest() will not affect @p statePtr, so you can update,
1341
+ * digest, and update again.
1342
+ *
1343
+ * @param statePtr The state struct to calculate the hash from.
1344
+ *
1345
+ * @pre
1346
+ * @p statePtr must not be `NULL`.
1347
+ *
1348
+ * @return The calculated XXH3 128-bit hash value from that state.
1349
+ */
1080
1350
  XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH3_128bits_digest (XXH_NOESCAPE const XXH3_state_t* statePtr);
1081
1351
  #endif /* !XXH_NO_STREAM */
1082
1352
 
@@ -1103,7 +1373,29 @@ XXH_PUBLIC_API XXH_PUREF int XXH128_cmp(XXH_NOESCAPE const void* h128_1, XXH_NOE
1103
1373
 
1104
1374
  /******* Canonical representation *******/
1105
1375
  typedef struct { unsigned char digest[sizeof(XXH128_hash_t)]; } XXH128_canonical_t;
1376
+
1377
+
1378
+ /*!
1379
+ * @brief Converts an @ref XXH128_hash_t to a big endian @ref XXH128_canonical_t.
1380
+ *
1381
+ * @param dst The @ref XXH128_canonical_t pointer to be stored to.
1382
+ * @param hash The @ref XXH128_hash_t to be converted.
1383
+ *
1384
+ * @pre
1385
+ * @p dst must not be `NULL`.
1386
+ */
1106
1387
  XXH_PUBLIC_API void XXH128_canonicalFromHash(XXH_NOESCAPE XXH128_canonical_t* dst, XXH128_hash_t hash);
1388
+
1389
+ /*!
1390
+ * @brief Converts an @ref XXH128_canonical_t to a native @ref XXH128_hash_t.
1391
+ *
1392
+ * @param src The @ref XXH128_canonical_t to convert.
1393
+ *
1394
+ * @pre
1395
+ * @p src must not be `NULL`.
1396
+ *
1397
+ * @return The converted hash.
1398
+ */
1107
1399
  XXH_PUBLIC_API XXH_PUREF XXH128_hash_t XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t* src);
1108
1400
 
1109
1401
 
@@ -1213,6 +1505,7 @@ struct XXH64_state_s {
1213
1505
  #define XXH3_INTERNALBUFFER_SIZE 256
1214
1506
 
1215
1507
  /*!
1508
+ * @internal
1216
1509
  * @brief Default size of the secret buffer (and @ref XXH3_kSecret).
1217
1510
  *
1218
1511
  * This is the size used in @ref XXH3_kSecret and the seeded functions.
@@ -1539,7 +1832,7 @@ XXH3_128bits_reset_withSecretandSeed(XXH_NOESCAPE XXH3_state_t* statePtr,
1539
1832
  * inline small `memcpy()` calls, and it might also be faster on big-endian
1540
1833
  * systems which lack a native byteswap instruction. However, some compilers
1541
1834
  * will emit literal byteshifts even if the target supports unaligned access.
1542
- * .
1835
+ *
1543
1836
  *
1544
1837
  * @warning
1545
1838
  * Methods 1 and 2 rely on implementation-defined behavior. Use these with
@@ -1858,7 +2151,11 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size)
1858
2151
  # include <assert.h> /* note: can still be disabled with NDEBUG */
1859
2152
  # define XXH_ASSERT(c) assert(c)
1860
2153
  #else
1861
- # define XXH_ASSERT(c) XXH_ASSUME(c)
2154
+ # if defined(__INTEL_COMPILER)
2155
+ # define XXH_ASSERT(c) XXH_ASSUME((unsigned char) (c))
2156
+ # else
2157
+ # define XXH_ASSERT(c) XXH_ASSUME(c)
2158
+ # endif
1862
2159
  #endif
1863
2160
 
1864
2161
  /* note: use after variable declarations */
@@ -1895,10 +2192,12 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size)
1895
2192
  # define XXH_COMPILER_GUARD(var) ((void)0)
1896
2193
  #endif
1897
2194
 
1898
- #if defined(__clang__)
1899
- # define XXH_COMPILER_GUARD_W(var) __asm__("" : "+w" (var))
2195
+ /* Specifically for NEON vectors which use the "w" constraint, on
2196
+ * Clang. */
2197
+ #if defined(__clang__) && defined(__ARM_ARCH) && !defined(__wasm__)
2198
+ # define XXH_COMPILER_GUARD_CLANG_NEON(var) __asm__("" : "+w" (var))
1900
2199
  #else
1901
- # define XXH_COMPILER_GUARD_W(var) ((void)0)
2200
+ # define XXH_COMPILER_GUARD_CLANG_NEON(var) ((void)0)
1902
2201
  #endif
1903
2202
 
1904
2203
  /* *************************************
@@ -1915,6 +2214,7 @@ static void* XXH_memcpy(void* dest, const void* src, size_t size)
1915
2214
  typedef XXH32_hash_t xxh_u32;
1916
2215
 
1917
2216
  #ifdef XXH_OLD_NAMES
2217
+ # warning "XXH_OLD_NAMES is planned to be removed starting v0.9. If the program depends on it, consider moving away from it by employing newer type names directly"
1918
2218
  # define BYTE xxh_u8
1919
2219
  # define U8 xxh_u8
1920
2220
  # define U32 xxh_u32
@@ -2287,7 +2587,7 @@ static xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input)
2287
2587
  acc += input * XXH_PRIME32_2;
2288
2588
  acc = XXH_rotl32(acc, 13);
2289
2589
  acc *= XXH_PRIME32_1;
2290
- #if (defined(__SSE4_1__) || defined(__aarch64__)) && !defined(XXH_ENABLE_AUTOVECTORIZE)
2590
+ #if (defined(__SSE4_1__) || defined(__aarch64__) || defined(__wasm_simd128__)) && !defined(XXH_ENABLE_AUTOVECTORIZE)
2291
2591
  /*
2292
2592
  * UGLY HACK:
2293
2593
  * A compiler fence is the only thing that prevents GCC and Clang from
@@ -2320,6 +2620,9 @@ static xxh_u32 XXH32_round(xxh_u32 acc, xxh_u32 input)
2320
2620
  * This is also enabled on AArch64, as Clang is *very aggressive* in vectorizing
2321
2621
  * the loop. NEON is only faster on the A53, and with the newer cores, it is less
2322
2622
  * than half the speed.
2623
+ *
2624
+ * Additionally, this is used on WASM SIMD128 because it JITs to the same
2625
+ * SIMD instructions and has the same issue.
2323
2626
  */
2324
2627
  XXH_COMPILER_GUARD(acc);
2325
2628
  #endif
@@ -3111,13 +3414,22 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_can
3111
3414
  # define XXH_unlikely(x) (x)
3112
3415
  #endif
3113
3416
 
3417
+ #ifndef XXH_HAS_INCLUDE
3418
+ # ifdef __has_include
3419
+ # define XXH_HAS_INCLUDE(x) __has_include(x)
3420
+ # else
3421
+ # define XXH_HAS_INCLUDE(x) 0
3422
+ # endif
3423
+ #endif
3424
+
3114
3425
  #if defined(__GNUC__) || defined(__clang__)
3115
3426
  # if defined(__ARM_FEATURE_SVE)
3116
3427
  # include <arm_sve.h>
3117
3428
  # endif
3118
3429
  # if defined(__ARM_NEON__) || defined(__ARM_NEON) \
3119
3430
  || (defined(_M_ARM) && _M_ARM >= 7) \
3120
- || defined(_M_ARM64) || defined(_M_ARM64EC)
3431
+ || defined(_M_ARM64) || defined(_M_ARM64EC) \
3432
+ || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE(<arm_neon.h>)) /* WASM SIMD128 via SIMDe */
3121
3433
  # define inline __inline__ /* circumvent a clang bug */
3122
3434
  # include <arm_neon.h>
3123
3435
  # undef inline
@@ -3228,7 +3540,7 @@ XXH_PUBLIC_API XXH64_hash_t XXH64_hashFromCanonical(XXH_NOESCAPE const XXH64_can
3228
3540
  * Note that these are actually implemented as macros.
3229
3541
  *
3230
3542
  * If this is not defined, it is detected automatically.
3231
- * @ref XXH_X86DISPATCH overrides this.
3543
+ * internal macro XXH_X86DISPATCH overrides this.
3232
3544
  */
3233
3545
  enum XXH_VECTOR_TYPE /* fake enum */ {
3234
3546
  XXH_SCALAR = 0, /*!< Portable scalar version */
@@ -3240,7 +3552,11 @@ enum XXH_VECTOR_TYPE /* fake enum */ {
3240
3552
  */
3241
3553
  XXH_AVX2 = 2, /*!< AVX2 for Haswell and Bulldozer */
3242
3554
  XXH_AVX512 = 3, /*!< AVX512 for Skylake and Icelake */
3243
- XXH_NEON = 4, /*!< NEON for most ARMv7-A and all AArch64 */
3555
+ XXH_NEON = 4, /*!<
3556
+ * NEON for most ARMv7-A, all AArch64, and WASM SIMD128
3557
+ * via the SIMDeverywhere polyfill provided with the
3558
+ * Emscripten SDK.
3559
+ */
3244
3560
  XXH_VSX = 5, /*!< VSX and ZVector for POWER8/z13 (64-bit) */
3245
3561
  XXH_SVE = 6, /*!< SVE for some ARMv8-A and ARMv9-A */
3246
3562
  };
@@ -3273,6 +3589,7 @@ enum XXH_VECTOR_TYPE /* fake enum */ {
3273
3589
  # elif ( \
3274
3590
  defined(__ARM_NEON__) || defined(__ARM_NEON) /* gcc */ \
3275
3591
  || defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC) /* msvc */ \
3592
+ || (defined(__wasm_simd128__) && XXH_HAS_INCLUDE(<arm_neon.h>)) /* wasm simd128 via SIMDe */ \
3276
3593
  ) && ( \
3277
3594
  defined(_WIN32) || defined(__LITTLE_ENDIAN__) /* little endian only */ \
3278
3595
  || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) \
@@ -3478,6 +3795,9 @@ XXH_vmlal_high_u32(uint64x2_t acc, uint32x4_t lhs, uint32x4_t rhs)
3478
3795
  *
3479
3796
  * It also seems to fix some bad codegen on GCC, making it almost as fast as clang.
3480
3797
  *
3798
+ * When using WASM SIMD128, if this is 2 or 6, SIMDe will scalarize 2 of the lanes meaning
3799
+ * it effectively becomes worse 4.
3800
+ *
3481
3801
  * @see XXH3_accumulate_512_neon()
3482
3802
  */
3483
3803
  # ifndef XXH3_NEON_LANES
@@ -3623,7 +3943,6 @@ do { \
3623
3943
  } while (0)
3624
3944
  #endif /* XXH_VECTOR == XXH_SVE */
3625
3945
 
3626
-
3627
3946
  /* prefetch
3628
3947
  * can be disabled, by declaring XXH_NO_PREFETCH build macro */
3629
3948
  #if defined(XXH_NO_PREFETCH)
@@ -3668,6 +3987,8 @@ XXH_ALIGN(64) static const xxh_u8 XXH3_kSecret[XXH_SECRET_DEFAULT_SIZE] = {
3668
3987
  0x45, 0xcb, 0x3a, 0x8f, 0x95, 0x16, 0x04, 0x28, 0xaf, 0xd7, 0xfb, 0xca, 0xbb, 0x4b, 0x40, 0x7e,
3669
3988
  };
3670
3989
 
3990
+ static const xxh_u64 PRIME_MX1 = 0x165667919E3779F9ULL; /*!< 0b0001011001010110011001111001000110011110001101110111100111111001 */
3991
+ static const xxh_u64 PRIME_MX2 = 0x9FB21C651E98DF25ULL; /*!< 0b1001111110110010000111000110010100011110100110001101111100100101 */
3671
3992
 
3672
3993
  #ifdef XXH_OLD_NAMES
3673
3994
  # define kSecret XXH3_kSecret
@@ -3872,7 +4193,7 @@ XXH_FORCE_INLINE XXH_CONSTF xxh_u64 XXH_xorshift64(xxh_u64 v64, int shift)
3872
4193
  static XXH64_hash_t XXH3_avalanche(xxh_u64 h64)
3873
4194
  {
3874
4195
  h64 = XXH_xorshift64(h64, 37);
3875
- h64 *= 0x165667919E3779F9ULL;
4196
+ h64 *= PRIME_MX1;
3876
4197
  h64 = XXH_xorshift64(h64, 32);
3877
4198
  return h64;
3878
4199
  }
@@ -3886,9 +4207,9 @@ static XXH64_hash_t XXH3_rrmxmx(xxh_u64 h64, xxh_u64 len)
3886
4207
  {
3887
4208
  /* this mix is inspired by Pelle Evensen's rrmxmx */
3888
4209
  h64 ^= XXH_rotl64(h64, 49) ^ XXH_rotl64(h64, 24);
3889
- h64 *= 0x9FB21C651E98DF25ULL;
4210
+ h64 *= PRIME_MX2;
3890
4211
  h64 ^= (h64 >> 35) + len ;
3891
- h64 *= 0x9FB21C651E98DF25ULL;
4212
+ h64 *= PRIME_MX2;
3892
4213
  return XXH_xorshift64(h64, 28);
3893
4214
  }
3894
4215
 
@@ -4059,7 +4380,7 @@ XXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len,
4059
4380
  XXH_ASSERT(secretSize >= XXH3_SECRET_SIZE_MIN); (void)secretSize;
4060
4381
  XXH_ASSERT(16 < len && len <= 128);
4061
4382
 
4062
- { xxh_u64 acc = len * XXH_PRIME64_1, acc_end;
4383
+ { xxh_u64 acc = len * XXH_PRIME64_1;
4063
4384
  #if XXH_SIZE_OPT >= 1
4064
4385
  /* Smaller and cleaner, but slightly slower. */
4065
4386
  unsigned int i = (unsigned int)(len - 1) / 32;
@@ -4067,25 +4388,23 @@ XXH3_len_17to128_64b(const xxh_u8* XXH_RESTRICT input, size_t len,
4067
4388
  acc += XXH3_mix16B(input+16 * i, secret+32*i, seed);
4068
4389
  acc += XXH3_mix16B(input+len-16*(i+1), secret+32*i+16, seed);
4069
4390
  } while (i-- != 0);
4070
- acc_end = 0;
4071
4391
  #else
4072
- acc += XXH3_mix16B(input+0, secret+0, seed);
4073
- acc_end = XXH3_mix16B(input+len-16, secret+16, seed);
4074
4392
  if (len > 32) {
4075
- acc += XXH3_mix16B(input+16, secret+32, seed);
4076
- acc_end += XXH3_mix16B(input+len-32, secret+48, seed);
4077
4393
  if (len > 64) {
4078
- acc += XXH3_mix16B(input+32, secret+64, seed);
4079
- acc_end += XXH3_mix16B(input+len-48, secret+80, seed);
4080
-
4081
4394
  if (len > 96) {
4082
4395
  acc += XXH3_mix16B(input+48, secret+96, seed);
4083
- acc_end += XXH3_mix16B(input+len-64, secret+112, seed);
4396
+ acc += XXH3_mix16B(input+len-64, secret+112, seed);
4084
4397
  }
4398
+ acc += XXH3_mix16B(input+32, secret+64, seed);
4399
+ acc += XXH3_mix16B(input+len-48, secret+80, seed);
4085
4400
  }
4401
+ acc += XXH3_mix16B(input+16, secret+32, seed);
4402
+ acc += XXH3_mix16B(input+len-32, secret+48, seed);
4086
4403
  }
4404
+ acc += XXH3_mix16B(input+0, secret+0, seed);
4405
+ acc += XXH3_mix16B(input+len-16, secret+16, seed);
4087
4406
  #endif
4088
- return XXH3_avalanche(acc + acc_end);
4407
+ return XXH3_avalanche(acc);
4089
4408
  }
4090
4409
  }
4091
4410
 
@@ -4576,7 +4895,7 @@ XXH3_scalarScrambleRound(void* XXH_RESTRICT acc,
4576
4895
 
4577
4896
  /*!
4578
4897
  * @internal
4579
- * @brief The bulk processing loop for NEON.
4898
+ * @brief The bulk processing loop for NEON and WASM SIMD128.
4580
4899
  *
4581
4900
  * The NEON code path is actually partially scalar when running on AArch64. This
4582
4901
  * is to optimize the pipelining and can have up to 15% speedup depending on the
@@ -4593,7 +4912,11 @@ XXH3_scalarScrambleRound(void* XXH_RESTRICT acc,
4593
4912
  * Since, as stated, the most optimal amount of lanes for Cortexes is 6,
4594
4913
  * there needs to be *three* versions of the accumulate operation used
4595
4914
  * for the remaining 2 lanes.
4915
+ *
4916
+ * WASM's SIMD128 uses SIMDe's arm_neon.h polyfill because the intrinsics overlap
4917
+ * nearly perfectly.
4596
4918
  */
4919
+
4597
4920
  XXH_FORCE_INLINE void
4598
4921
  XXH3_accumulate_512_neon( void* XXH_RESTRICT acc,
4599
4922
  const void* XXH_RESTRICT input,
@@ -4604,10 +4927,30 @@ XXH3_accumulate_512_neon( void* XXH_RESTRICT acc,
4604
4927
  { /* GCC for darwin arm64 does not like aliasing here */
4605
4928
  xxh_aliasing_uint64x2_t* const xacc = (xxh_aliasing_uint64x2_t*) acc;
4606
4929
  /* We don't use a uint32x4_t pointer because it causes bus errors on ARMv7. */
4607
- uint8_t const* const xinput = (const uint8_t *) input;
4608
- uint8_t const* const xsecret = (const uint8_t *) secret;
4930
+ uint8_t const* xinput = (const uint8_t *) input;
4931
+ uint8_t const* xsecret = (const uint8_t *) secret;
4609
4932
 
4610
4933
  size_t i;
4934
+ #ifdef __wasm_simd128__
4935
+ /*
4936
+ * On WASM SIMD128, Clang emits direct address loads when XXH3_kSecret
4937
+ * is constant propagated, which results in it converting it to this
4938
+ * inside the loop:
4939
+ *
4940
+ * a = v128.load(XXH3_kSecret + 0 + $secret_offset, offset = 0)
4941
+ * b = v128.load(XXH3_kSecret + 16 + $secret_offset, offset = 0)
4942
+ * ...
4943
+ *
4944
+ * This requires a full 32-bit address immediate (and therefore a 6 byte
4945
+ * instruction) as well as an add for each offset.
4946
+ *
4947
+ * Putting an asm guard prevents it from folding (at the cost of losing
4948
+ * the alignment hint), and uses the free offset in `v128.load` instead
4949
+ * of adding secret_offset each time which overall reduces code size by
4950
+ * about a kilobyte and improves performance.
4951
+ */
4952
+ XXH_COMPILER_GUARD(xsecret);
4953
+ #endif
4611
4954
  /* Scalar lanes use the normal scalarRound routine */
4612
4955
  for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) {
4613
4956
  XXH3_scalarRound(acc, input, secret, i);
@@ -4634,9 +4977,9 @@ XXH3_accumulate_512_neon( void* XXH_RESTRICT acc,
4634
4977
  * get one vector with the low 32 bits of each lane, and one vector
4635
4978
  * with the high 32 bits of each lane.
4636
4979
  *
4637
- * This compiles to two instructions on AArch64 and has a paired vector
4638
- * result, which is an artifact from ARMv7a's version which modified both
4639
- * vectors in place.
4980
+ * The intrinsic returns a double vector because the original ARMv7-a
4981
+ * instruction modified both arguments in place. AArch64 and SIMD128 emit
4982
+ * two instructions from this intrinsic.
4640
4983
  *
4641
4984
  * [ dk11L | dk11H | dk12L | dk12H ] -> [ dk11L | dk12L | dk21L | dk22L ]
4642
4985
  * [ dk21L | dk21H | dk22L | dk22H ] -> [ dk11H | dk12H | dk21H | dk22H ]
@@ -4652,7 +4995,7 @@ XXH3_accumulate_512_neon( void* XXH_RESTRICT acc,
4652
4995
  /*
4653
4996
  * Then, we can split the vectors horizontally and multiply which, as for most
4654
4997
  * widening intrinsics, have a variant that works on both high half vectors
4655
- * for free on AArch64.
4998
+ * for free on AArch64. A similar instruction is available on SIMD128.
4656
4999
  *
4657
5000
  * sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi
4658
5001
  */
@@ -4670,8 +5013,8 @@ XXH3_accumulate_512_neon( void* XXH_RESTRICT acc,
4670
5013
  * for reasons likely related to umlal being limited to certain NEON
4671
5014
  * pipelines, this is worse. A compiler guard fixes this.
4672
5015
  */
4673
- XXH_COMPILER_GUARD_W(sum_1);
4674
- XXH_COMPILER_GUARD_W(sum_2);
5016
+ XXH_COMPILER_GUARD_CLANG_NEON(sum_1);
5017
+ XXH_COMPILER_GUARD_CLANG_NEON(sum_2);
4675
5018
  /* xacc[i] = acc_vec + sum; */
4676
5019
  xacc[i] = vaddq_u64(xacc[i], sum_1);
4677
5020
  xacc[i+1] = vaddq_u64(xacc[i+1], sum_2);
@@ -4694,7 +5037,7 @@ XXH3_accumulate_512_neon( void* XXH_RESTRICT acc,
4694
5037
  /* sum = data_swap + (u64x2) data_key_lo * (u64x2) data_key_hi; */
4695
5038
  uint64x2_t sum = vmlal_u32(data_swap, data_key_lo, data_key_hi);
4696
5039
  /* Same Clang workaround as before */
4697
- XXH_COMPILER_GUARD_W(sum);
5040
+ XXH_COMPILER_GUARD_CLANG_NEON(sum);
4698
5041
  /* xacc[i] = acc_vec + sum; */
4699
5042
  xacc[i] = vaddq_u64 (xacc[i], sum);
4700
5043
  }
@@ -4709,9 +5052,16 @@ XXH3_scrambleAcc_neon(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
4709
5052
 
4710
5053
  { xxh_aliasing_uint64x2_t* xacc = (xxh_aliasing_uint64x2_t*) acc;
4711
5054
  uint8_t const* xsecret = (uint8_t const*) secret;
4712
- uint32x2_t prime = vdup_n_u32 (XXH_PRIME32_1);
4713
5055
 
4714
5056
  size_t i;
5057
+ /* WASM uses operator overloads and doesn't need these. */
5058
+ #ifndef __wasm_simd128__
5059
+ /* { prime32_1, prime32_1 } */
5060
+ uint32x2_t const kPrimeLo = vdup_n_u32(XXH_PRIME32_1);
5061
+ /* { 0, prime32_1, 0, prime32_1 } */
5062
+ uint32x4_t const kPrimeHi = vreinterpretq_u32_u64(vdupq_n_u64((xxh_u64)XXH_PRIME32_1 << 32));
5063
+ #endif
5064
+
4715
5065
  /* AArch64 uses both scalar and neon at the same time */
4716
5066
  for (i = XXH3_NEON_LANES; i < XXH_ACC_NB; i++) {
4717
5067
  XXH3_scalarScrambleRound(acc, secret, i);
@@ -4725,33 +5075,28 @@ XXH3_scrambleAcc_neon(void* XXH_RESTRICT acc, const void* XXH_RESTRICT secret)
4725
5075
  /* xacc[i] ^= xsecret[i]; */
4726
5076
  uint64x2_t key_vec = XXH_vld1q_u64(xsecret + (i * 16));
4727
5077
  uint64x2_t data_key = veorq_u64(data_vec, key_vec);
4728
-
4729
5078
  /* xacc[i] *= XXH_PRIME32_1 */
4730
- uint32x2_t data_key_lo = vmovn_u64(data_key);
4731
- uint32x2_t data_key_hi = vshrn_n_u64(data_key, 32);
5079
+ #ifdef __wasm_simd128__
5080
+ /* SIMD128 has multiply by u64x2, use it instead of expanding and scalarizing */
5081
+ xacc[i] = data_key * XXH_PRIME32_1;
5082
+ #else
4732
5083
  /*
4733
- * prod_hi = (data_key >> 32) * XXH_PRIME32_1;
5084
+ * Expanded version with portable NEON intrinsics
4734
5085
  *
4735
- * Avoid vmul_u32 + vshll_n_u32 since Clang 6 and 7 will
4736
- * incorrectly "optimize" this:
4737
- * tmp = vmul_u32(vmovn_u64(a), vmovn_u64(b));
4738
- * shifted = vshll_n_u32(tmp, 32);
4739
- * to this:
4740
- * tmp = "vmulq_u64"(a, b); // no such thing!
4741
- * shifted = vshlq_n_u64(tmp, 32);
5086
+ * lo(x) * lo(y) + (hi(x) * lo(y) << 32)
4742
5087
  *
4743
- * However, unlike SSE, Clang lacks a 64-bit multiply routine
4744
- * for NEON, and it scalarizes two 64-bit multiplies instead.
5088
+ * prod_hi = hi(data_key) * lo(prime) << 32
4745
5089
  *
4746
- * vmull_u32 has the same timing as vmul_u32, and it avoids
4747
- * this bug completely.
4748
- * See https://bugs.llvm.org/show_bug.cgi?id=39967
5090
+ * Since we only need 32 bits of this multiply a trick can be used, reinterpreting the vector
5091
+ * as a uint32x4_t and multiplying by { 0, prime, 0, prime } to cancel out the unwanted bits
5092
+ * and avoid the shift.
4749
5093
  */
4750
- uint64x2_t prod_hi = vmull_u32 (data_key_hi, prime);
4751
- /* xacc[i] = prod_hi << 32; */
4752
- prod_hi = vshlq_n_u64(prod_hi, 32);
4753
- /* xacc[i] += (prod_hi & 0xFFFFFFFF) * XXH_PRIME32_1; */
4754
- xacc[i] = vmlal_u32(prod_hi, data_key_lo, prime);
5094
+ uint32x4_t prod_hi = vmulq_u32 (vreinterpretq_u32_u64(data_key), kPrimeHi);
5095
+ /* Extract low bits for vmlal_u32 */
5096
+ uint32x2_t data_key_lo = vmovn_u64(data_key);
5097
+ /* xacc[i] = prod_hi + lo(data_key) * XXH_PRIME32_1; */
5098
+ xacc[i] = vmlal_u32(vreinterpretq_u64_u32(prod_hi), data_key_lo, kPrimeLo);
5099
+ #endif
4755
5100
  }
4756
5101
  }
4757
5102
  }
@@ -5467,6 +5812,12 @@ static void XXH_alignedFree(void* p)
5467
5812
  }
5468
5813
  }
5469
5814
  /*! @ingroup XXH3_family */
5815
+ /*!
5816
+ * @brief Allocate an @ref XXH3_state_t.
5817
+ *
5818
+ * Must be freed with XXH3_freeState().
5819
+ * @return An allocated XXH3_state_t on success, `NULL` on failure.
5820
+ */
5470
5821
  XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void)
5471
5822
  {
5472
5823
  XXH3_state_t* const state = (XXH3_state_t*)XXH_alignedMalloc(sizeof(XXH3_state_t), 64);
@@ -5476,6 +5827,13 @@ XXH_PUBLIC_API XXH3_state_t* XXH3_createState(void)
5476
5827
  }
5477
5828
 
5478
5829
  /*! @ingroup XXH3_family */
5830
+ /*!
5831
+ * @brief Frees an @ref XXH3_state_t.
5832
+ *
5833
+ * Must be allocated with XXH3_createState().
5834
+ * @param statePtr A pointer to an @ref XXH3_state_t allocated with @ref XXH3_createState().
5835
+ * @return XXH_OK.
5836
+ */
5479
5837
  XXH_PUBLIC_API XXH_errorcode XXH3_freeState(XXH3_state_t* statePtr)
5480
5838
  {
5481
5839
  XXH_alignedFree(statePtr);
@@ -5832,7 +6190,7 @@ XXH3_len_4to8_128b(const xxh_u8* input, size_t len, const xxh_u8* secret, XXH64_
5832
6190
  m128.low64 ^= (m128.high64 >> 3);
5833
6191
 
5834
6192
  m128.low64 = XXH_xorshift64(m128.low64, 35);
5835
- m128.low64 *= 0x9FB21C651E98DF25ULL;
6193
+ m128.low64 *= PRIME_MX2;
5836
6194
  m128.low64 = XXH_xorshift64(m128.low64, 28);
5837
6195
  m128.high64 = XXH3_avalanche(m128.high64);
5838
6196
  return m128;
@@ -2,6 +2,6 @@ require 'digest'
2
2
 
3
3
  module Digest
4
4
  class XXHash < Digest::Class
5
- VERSION = "0.2.6"
5
+ VERSION = "0.2.7"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: digest-xxhash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - konsolebox
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-22 00:00:00.000000000 Z
11
+ date: 2023-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -30,32 +30,20 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.0'
34
- - - "!="
35
- - !ruby/object:Gem::Version
36
- version: 1.1.3
37
- - - "!="
38
- - !ruby/object:Gem::Version
39
- version: 1.1.4
40
- - - "!="
33
+ version: '1.2'
34
+ - - ">="
41
35
  - !ruby/object:Gem::Version
42
- version: 1.1.5
36
+ version: 1.2.3
43
37
  type: :development
44
38
  prerelease: false
45
39
  version_requirements: !ruby/object:Gem::Requirement
46
40
  requirements:
47
41
  - - "~>"
48
42
  - !ruby/object:Gem::Version
49
- version: '1.0'
50
- - - "!="
51
- - !ruby/object:Gem::Version
52
- version: 1.1.3
53
- - - "!="
54
- - !ruby/object:Gem::Version
55
- version: 1.1.4
56
- - - "!="
43
+ version: '1.2'
44
+ - - ">="
57
45
  - !ruby/object:Gem::Version
58
- version: 1.1.5
46
+ version: 1.2.3
59
47
  - !ruby/object:Gem::Dependency
60
48
  name: minitest
61
49
  requirement: !ruby/object:Gem::Requirement
@@ -117,7 +105,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
117
105
  - !ruby/object:Gem::Version
118
106
  version: '0'
119
107
  requirements: []
120
- rubygems_version: 3.4.10
108
+ rubygems_version: 3.4.14
121
109
  signing_key:
122
110
  specification_version: 4
123
111
  summary: A Digest framework based XXHash library for Ruby