usearch 2.14.0 → 2.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -544,7 +544,7 @@ doi = {10.5281/zenodo.7949416},
544
544
  author = {Vardanian, Ash},
545
545
  title = {{USearch by Unum Cloud}},
546
546
  url = {https://github.com/unum-cloud/usearch},
547
- version = {2.14.0},
547
+ version = {2.15.0},
548
548
  year = {2023},
549
549
  month = oct,
550
550
  }
package/cpp/bench.cpp CHANGED
@@ -468,6 +468,7 @@ struct args_t {
468
468
 
469
469
  bool big = false;
470
470
 
471
+ bool quantize_bf16 = false;
471
472
  bool quantize_f16 = false;
472
473
  bool quantize_i8 = false;
473
474
  bool quantize_b1 = false;
@@ -500,6 +501,8 @@ struct args_t {
500
501
  }
501
502
 
502
503
  scalar_kind_t quantization() const noexcept {
504
+ if (quantize_bf16)
505
+ return scalar_kind_t::bf16_k;
503
506
  if (quantize_f16)
504
507
  return scalar_kind_t::f16_k;
505
508
  if (quantize_i8)
@@ -611,6 +614,7 @@ int main(int argc, char** argv) {
611
614
  (option("--rows-skip") & value("integer", args.vectors_to_skip)).doc("Number of vectors to skip"),
612
615
  (option("--rows-take") & value("integer", args.vectors_to_take)).doc("Number of vectors to take"),
613
616
  ( //
617
+ option("-bf16", "--bf16quant").set(args.quantize_bf16).doc("Enable `bf16_t` quantization") |
614
618
  option("-f16", "--f16quant").set(args.quantize_f16).doc("Enable `f16_t` quantization") |
615
619
  option("-i8", "--i8quant").set(args.quantize_i8).doc("Enable `i8_t` quantization") |
616
620
  option("-b1", "--b1quant").set(args.quantize_b1).doc("Enable `b1x8_t` quantization")),
@@ -8,7 +8,7 @@
8
8
  #define UNUM_USEARCH_HPP
9
9
 
10
10
  #define USEARCH_VERSION_MAJOR 2
11
- #define USEARCH_VERSION_MINOR 14
11
+ #define USEARCH_VERSION_MINOR 15
12
12
  #define USEARCH_VERSION_PATCH 0
13
13
 
14
14
  // Inferring C++ version
@@ -950,7 +950,7 @@ class index_dense_gt {
950
950
 
951
951
  void reserve(index_limits_t limits) {
952
952
  if (!try_reserve(limits))
953
- throw std::bad_alloc();
953
+ __usearch_raise_runtime_error("failed to reserve memory");
954
954
  }
955
955
 
956
956
  /**
@@ -72,25 +72,8 @@ struct uuid_t {
72
72
  class f16_bits_t;
73
73
  class bf16_bits_t;
74
74
 
75
- #if !USEARCH_USE_FP16LIB
76
- #if USEARCH_USE_SIMSIMD
77
- using f16_native_t = simsimd_f16_t;
78
- using bf16_native_t = simsimd_bf16_t;
79
- #elif defined(USEARCH_DEFINED_ARM)
80
- using f16_native_t = __fp16;
81
- using bf16_native_t = __fp16; // No better choice on most compilers!
82
- #else
83
- using f16_native_t = _Float16;
84
- using bf16_native_t = _Float16; // No better choice on most compilers!
85
- #endif
86
- using f16_t = f16_native_t;
87
- using bf16_t = bf16_native_t;
88
- #else
89
- using f16_native_t = void;
90
- using bf16_native_t = void;
91
75
  using f16_t = f16_bits_t;
92
76
  using bf16_t = bf16_bits_t;
93
- #endif
94
77
 
95
78
  using f64_t = double;
96
79
  using f32_t = float;
@@ -156,12 +139,6 @@ enum class scalar_kind_t : std::uint8_t {
156
139
  i8_k = 23,
157
140
  };
158
141
 
159
- enum class prefetching_kind_t {
160
- none_k,
161
- cpu_k,
162
- io_uring_k,
163
- };
164
-
165
142
  template <typename scalar_at> scalar_kind_t scalar_kind() noexcept {
166
143
  if (std::is_same<scalar_at, b1x8_t>())
167
144
  return scalar_kind_t::b1x8_k;
@@ -352,12 +329,14 @@ inline expected_gt<metric_kind_t> metric_from_name(char const* name) {
352
329
  * @brief Convenience function to upcast a half-precision floating point number to a single-precision one.
353
330
  */
354
331
  inline float f16_to_f32(std::uint16_t u16) noexcept {
355
- #if !USEARCH_USE_FP16LIB
332
+ #if USEARCH_USE_FP16LIB
333
+ return fp16_ieee_to_fp32_value(u16);
334
+ #elif USEARCH_USE_SIMSIMD
335
+ return simsimd_uncompress_f16(u16);
336
+ #else
356
337
  f16_native_t f16;
357
338
  std::memcpy(&f16, &u16, sizeof(std::uint16_t));
358
339
  return float(f16);
359
- #else
360
- return fp16_ieee_to_fp32_value(u16);
361
340
  #endif
362
341
  }
363
342
 
@@ -365,13 +344,15 @@ inline float f16_to_f32(std::uint16_t u16) noexcept {
365
344
  * @brief Convenience function to downcast a single-precision floating point number to a half-precision one.
366
345
  */
367
346
  inline std::uint16_t f32_to_f16(float f32) noexcept {
368
- #if !USEARCH_USE_FP16LIB
347
+ #if USEARCH_USE_FP16LIB
348
+ return fp16_ieee_from_fp32_value(f32);
349
+ #elif USEARCH_USE_SIMSIMD
350
+ return simsimd_compress_f16(f32);
351
+ #else
369
352
  f16_native_t f16 = f16_native_t(f32);
370
353
  std::uint16_t u16;
371
354
  std::memcpy(&u16, &f16, sizeof(std::uint16_t));
372
355
  return u16;
373
- #else
374
- return fp16_ieee_from_fp32_value(f32);
375
356
  #endif
376
357
  }
377
358
 
@@ -380,6 +361,9 @@ inline std::uint16_t f32_to_f16(float f32) noexcept {
380
361
  * https://github.com/ashvardanian/SimSIMD/blob/ff51434d90c66f916e94ff05b24530b127aa4cff/include/simsimd/types.h#L395-L410
381
362
  */
382
363
  inline float bf16_to_f32(std::uint16_t u16) noexcept {
364
+ #if USEARCH_USE_SIMSIMD
365
+ return simsimd_uncompress_bf16(u16);
366
+ #else
383
367
  union float_or_unsigned_int_t {
384
368
  float f;
385
369
  unsigned int i;
@@ -387,6 +371,7 @@ inline float bf16_to_f32(std::uint16_t u16) noexcept {
387
371
  union float_or_unsigned_int_t result_union;
388
372
  result_union.i = u16 << 16; // Zero extends the mantissa
389
373
  return result_union.f;
374
+ #endif
390
375
  }
391
376
 
392
377
  /**
@@ -394,6 +379,9 @@ inline float bf16_to_f32(std::uint16_t u16) noexcept {
394
379
  * https://github.com/ashvardanian/SimSIMD/blob/ff51434d90c66f916e94ff05b24530b127aa4cff/include/simsimd/types.h#L412-L425
395
380
  */
396
381
  inline std::uint16_t f32_to_bf16(float f32) noexcept {
382
+ #if USEARCH_USE_SIMSIMD
383
+ return simsimd_compress_bf16(f32);
384
+ #else
397
385
  union float_or_unsigned_int_t {
398
386
  float f;
399
387
  unsigned int i;
@@ -403,6 +391,7 @@ inline std::uint16_t f32_to_bf16(float f32) noexcept {
403
391
  value.i >>= 16;
404
392
  value.i &= 0xFFFF;
405
393
  return (unsigned short)value.i;
394
+ #endif
406
395
  }
407
396
 
408
397
  /**
@@ -1047,6 +1036,10 @@ template <> struct cast_gt<f16_bits_t, f16_bits_t> {
1047
1036
  static bool try_(byte_t const*, std::size_t, byte_t*) noexcept { return false; }
1048
1037
  };
1049
1038
 
1039
+ template <> struct cast_gt<bf16_bits_t, bf16_bits_t> {
1040
+ static bool try_(byte_t const*, std::size_t, byte_t*) noexcept { return false; }
1041
+ };
1042
+
1050
1043
  template <> struct cast_gt<i8_t, i8_t> {
1051
1044
  static bool try_(byte_t const*, std::size_t, byte_t*) noexcept { return false; }
1052
1045
  };
@@ -1119,23 +1112,23 @@ template <typename to_scalar_at> struct cast_from_i8_gt {
1119
1112
  }
1120
1113
  };
1121
1114
 
1122
- template <> struct cast_gt<i8_t, f16_t> : public cast_from_i8_gt<f16_t> {};
1123
- template <> struct cast_gt<i8_t, bf16_t> : public cast_from_i8_gt<bf16_t> {};
1115
+ template <> struct cast_gt<i8_t, f16_bits_t> : public cast_from_i8_gt<f16_t> {};
1116
+ template <> struct cast_gt<i8_t, bf16_bits_t> : public cast_from_i8_gt<bf16_t> {};
1124
1117
  template <> struct cast_gt<i8_t, f32_t> : public cast_from_i8_gt<f32_t> {};
1125
1118
  template <> struct cast_gt<i8_t, f64_t> : public cast_from_i8_gt<f64_t> {};
1126
1119
 
1127
- template <> struct cast_gt<f16_t, i8_t> : public cast_to_i8_gt<f16_t> {};
1128
- template <> struct cast_gt<bf16_t, i8_t> : public cast_to_i8_gt<bf16_t> {};
1120
+ template <> struct cast_gt<f16_bits_t, i8_t> : public cast_to_i8_gt<f16_t> {};
1121
+ template <> struct cast_gt<bf16_bits_t, i8_t> : public cast_to_i8_gt<bf16_t> {};
1129
1122
  template <> struct cast_gt<f32_t, i8_t> : public cast_to_i8_gt<f32_t> {};
1130
1123
  template <> struct cast_gt<f64_t, i8_t> : public cast_to_i8_gt<f64_t> {};
1131
1124
 
1132
- template <> struct cast_gt<b1x8_t, f16_t> : public cast_from_b1x8_gt<f16_t> {};
1133
- template <> struct cast_gt<b1x8_t, bf16_t> : public cast_from_b1x8_gt<bf16_t> {};
1125
+ template <> struct cast_gt<b1x8_t, f16_bits_t> : public cast_from_b1x8_gt<f16_t> {};
1126
+ template <> struct cast_gt<b1x8_t, bf16_bits_t> : public cast_from_b1x8_gt<bf16_t> {};
1134
1127
  template <> struct cast_gt<b1x8_t, f32_t> : public cast_from_b1x8_gt<f32_t> {};
1135
1128
  template <> struct cast_gt<b1x8_t, f64_t> : public cast_from_b1x8_gt<f64_t> {};
1136
1129
 
1137
- template <> struct cast_gt<f16_t, b1x8_t> : public cast_to_b1x8_gt<f16_t> {};
1138
- template <> struct cast_gt<bf16_t, b1x8_t> : public cast_to_b1x8_gt<bf16_t> {};
1130
+ template <> struct cast_gt<f16_bits_t, b1x8_t> : public cast_to_b1x8_gt<f16_t> {};
1131
+ template <> struct cast_gt<bf16_bits_t, b1x8_t> : public cast_to_b1x8_gt<bf16_t> {};
1139
1132
  template <> struct cast_gt<f32_t, b1x8_t> : public cast_to_b1x8_gt<f32_t> {};
1140
1133
  template <> struct cast_gt<f64_t, b1x8_t> : public cast_to_b1x8_gt<f64_t> {};
1141
1134
 
@@ -2088,7 +2081,7 @@ class flat_hash_multi_set_gt {
2088
2081
  // Allocate new memory
2089
2082
  data_ = (char*)allocator_t{}.allocate(other.buckets_ * bytes_per_bucket());
2090
2083
  if (!data_)
2091
- throw std::bad_alloc();
2084
+ __usearch_raise_runtime_error("failed memory allocation");
2092
2085
 
2093
2086
  // Copy metadata
2094
2087
  buckets_ = other.buckets_;
@@ -2128,7 +2121,7 @@ class flat_hash_multi_set_gt {
2128
2121
  // Allocate new memory
2129
2122
  data_ = (char*)allocator_t{}.allocate(other.buckets_ * bytes_per_bucket());
2130
2123
  if (!data_)
2131
- throw std::bad_alloc();
2124
+ __usearch_raise_runtime_error("failed memory allocation");
2132
2125
 
2133
2126
  // Copy metadata
2134
2127
  buckets_ = other.buckets_;
@@ -2501,7 +2494,7 @@ class flat_hash_multi_set_gt {
2501
2494
 
2502
2495
  void reserve(std::size_t capacity) {
2503
2496
  if (!try_reserve(capacity))
2504
- throw std::bad_alloc();
2497
+ __usearch_raise_runtime_error("failed to reserve memory");
2505
2498
  }
2506
2499
 
2507
2500
  bool try_emplace(element_t const& element) noexcept {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usearch",
3
- "version": "2.14.0",
3
+ "version": "2.15.0",
4
4
  "description": "Smaller & Faster Single-File Vector Search Engine from Unum",
5
5
  "author": "Ash Vardanian (https://ashvardanian.com/)",
6
6
  "license": "Apache 2.0",
Binary file
Binary file