usearch 0.18.4 → 0.18.5

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/Cargo.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "usearch"
3
- version = "0.18.4"
3
+ version = "0.18.5"
4
4
  authors = ["Ashot Vardanian <1983160+ashvardanian@users.noreply.github.com>"]
5
5
  description = "Smaller & Faster Single-File Vector Search Engine from Unum"
6
6
  edition = "2021"
package/conanfile.py CHANGED
@@ -4,7 +4,7 @@ from conans import ConanFile
4
4
  class USearchConan(ConanFile):
5
5
 
6
6
  name = 'USearch'
7
- version = '0.18.4'
7
+ version = '0.18.5'
8
8
  license = 'Apache 2.0'
9
9
  url = 'https://github.com/unum-cloud/usearch'
10
10
  description = 'Smaller & Faster Single-File Vector Search Engine from Unum'
@@ -328,7 +328,7 @@ class index_punned_dense_gt {
328
328
  std::size_t vector_bytes = dimensions_ * sizeof(scalar_at);
329
329
 
330
330
  byte_t* casted_data = cast_buffer_.data() + casted_vector_bytes_ * config.thread;
331
- bool casted = cast(vector_data, vector_bytes, casted_data);
331
+ bool casted = cast(vector_data, dimensions_, casted_data);
332
332
  if (casted)
333
333
  vector_data = casted_data, vector_bytes = casted_vector_bytes_, config.store_vector = true;
334
334
 
@@ -349,7 +349,7 @@ class index_punned_dense_gt {
349
349
  std::size_t vector_bytes = dimensions_ * sizeof(scalar_at);
350
350
 
351
351
  byte_t* casted_data = cast_buffer_.data() + casted_vector_bytes_ * config.thread;
352
- bool casted = cast(vector_data, vector_bytes, casted_data);
352
+ bool casted = cast(vector_data, dimensions_, casted_data);
353
353
  if (casted)
354
354
  vector_data = casted_data, vector_bytes = casted_vector_bytes_;
355
355
 
@@ -365,7 +365,7 @@ class index_punned_dense_gt {
365
365
  std::size_t vector_bytes = dimensions_ * sizeof(scalar_at);
366
366
 
367
367
  byte_t* casted_data = cast_buffer_.data() + casted_vector_bytes_ * config.thread;
368
- bool casted = cast(vector_data, vector_bytes, casted_data);
368
+ bool casted = cast(vector_data, dimensions_, casted_data);
369
369
  if (casted)
370
370
  vector_data = casted_data, vector_bytes = casted_vector_bytes_;
371
371
 
@@ -388,10 +388,10 @@ class index_punned_dense_gt {
388
388
  }
389
389
  member_citerator_t iterator = typed_->cbegin() + id;
390
390
  member_cref_t member = *iterator;
391
- byte_t const* casted_vector = reinterpret_cast<byte_t const*>(member.vector.data());
392
- bool casted = cast(casted_vector, casted_vector_bytes_, (byte_t*)reconstructed);
391
+ byte_t const* punned_vector = reinterpret_cast<byte_t const*>(member.vector.data());
392
+ bool casted = cast(punned_vector, dimensions_, (byte_t*)reconstructed);
393
393
  if (!casted)
394
- std::memcpy(reconstructed, casted_vector, casted_vector_bytes_);
394
+ std::memcpy(reconstructed, punned_vector, casted_vector_bytes_);
395
395
  return true;
396
396
  }
397
397
 
@@ -492,12 +492,11 @@ using memory_mapping_allocator_t = aligned_allocator_t;
492
492
  #endif
493
493
 
494
494
  template <typename from_scalar_at, typename to_scalar_at> struct cast_gt {
495
- inline bool operator()(byte_t const* input, std::size_t bytes_in_input, byte_t* output) const {
495
+ inline bool operator()(byte_t const* input, std::size_t dimensions, byte_t* output) const {
496
496
  from_scalar_at const* typed_input = reinterpret_cast<from_scalar_at const*>(input);
497
497
  to_scalar_at* typed_output = reinterpret_cast<to_scalar_at*>(output);
498
- std::size_t size_input = bytes_in_input / sizeof(from_scalar_at);
499
498
  auto converter = [](from_scalar_at from) { return to_scalar_at(from); };
500
- std::transform(typed_input, typed_input + size_input, typed_output, converter);
499
+ std::transform(typed_input, typed_input + dimensions, typed_output, converter);
501
500
  return true;
502
501
  }
503
502
  };
@@ -523,23 +522,21 @@ template <> struct cast_gt<b1x8_t, b1x8_t> {
523
522
  };
524
523
 
525
524
  template <typename from_scalar_at> struct cast_gt<from_scalar_at, b1x8_t> {
526
- inline bool operator()(byte_t const* input, std::size_t bytes_in_input, byte_t* output) const {
525
+ inline bool operator()(byte_t const* input, std::size_t dimensions, byte_t* output) const {
527
526
  from_scalar_at const* typed_input = reinterpret_cast<from_scalar_at const*>(input);
528
527
  unsigned char* typed_output = reinterpret_cast<unsigned char*>(output);
529
- std::size_t size_input = bytes_in_input / sizeof(from_scalar_at);
530
- for (std::size_t i = 0; i != size_input; ++i)
531
- typed_output[i / CHAR_BIT] |= bool(typed_input[i]) ? (1 << (i & (CHAR_BIT - 1))) : 0;
528
+ for (std::size_t i = 0; i != dimensions; ++i)
529
+ typed_output[i / CHAR_BIT] |= bool(typed_input[i]) ? (128 >> (i & (CHAR_BIT - 1))) : 0;
532
530
  return true;
533
531
  }
534
532
  };
535
533
 
536
534
  template <typename to_scalar_at> struct cast_gt<b1x8_t, to_scalar_at> {
537
- inline bool operator()(byte_t const* input, std::size_t bytes_in_input, byte_t* output) const {
535
+ inline bool operator()(byte_t const* input, std::size_t dimensions, byte_t* output) const {
538
536
  unsigned char const* typed_input = reinterpret_cast<unsigned char const*>(input);
539
537
  to_scalar_at* typed_output = reinterpret_cast<to_scalar_at*>(output);
540
- std::size_t size_input = bytes_in_input * CHAR_BIT;
541
- for (std::size_t i = 0; i != size_input; ++i)
542
- typed_output[i] = bool(typed_input[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))));
538
+ for (std::size_t i = 0; i != dimensions; ++i)
539
+ typed_output[i] = bool(typed_input[i / CHAR_BIT] & (128 >> (i & (CHAR_BIT - 1))));
543
540
  return true;
544
541
  }
545
542
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "usearch",
3
- "version": "0.18.4",
3
+ "version": "0.18.5",
4
4
  "description": "Smaller & Faster Single-File Vector Search Engine from Unum",
5
5
  "author": "Ashot Vardanian",
6
6
  "license": "Apache 2.0",
package/python/lib.cpp CHANGED
@@ -394,7 +394,8 @@ template <typename index_at> void view_index(index_at& index, std::string const&
394
394
 
395
395
  template <typename internal_at, typename external_at = internal_at, typename index_at = void>
396
396
  py::object get_typed_member(index_at const& index, label_t label) {
397
- py::array_t<external_at> result_py(static_cast<Py_ssize_t>(index.scalar_words()));
397
+ std::size_t result_slots = std::is_same<internal_at, b1x8_t>() ? index.scalar_words() : index.dimensions();
398
+ py::array_t<external_at> result_py(static_cast<Py_ssize_t>(result_slots));
398
399
  auto result_py1d = result_py.template mutable_unchecked<1>();
399
400
  if (!index.get(label, (internal_at*)&result_py1d(0)))
400
401
  return py::none();
@@ -4,7 +4,6 @@ import itertools
4
4
  from typing import List, Optional, Iterable
5
5
  from dataclasses import asdict
6
6
 
7
- import fire
8
7
  import numpy as np
9
8
  import pandas as pd
10
9
 
@@ -5,7 +5,7 @@ import numpy as np
5
5
  from usearch.io import load_matrix, save_matrix
6
6
  from usearch.eval import recall_members, random_vectors
7
7
 
8
- from usearch.index import Index, SparseIndex, MetricKind, ScalarKind, Matches
8
+ from usearch.index import Index, SparseIndex, MetricKind, ScalarKind, Matches, MetricKindBitwise
9
9
  from usearch.index import _normalize_dtype
10
10
  from usearch.index import (
11
11
  DEFAULT_CONNECTIVITY,
@@ -181,10 +181,13 @@ def test_bitwise_index(bits: int, metric: MetricKind, connectivity: int, batch_s
181
181
  index = Index(ndim=bits, metric=metric, connectivity=connectivity)
182
182
 
183
183
  labels = np.arange(batch_size)
184
- bit_vectors = np.random.randint(2, size=(batch_size, bits))
185
- bit_vectors = np.packbits(bit_vectors, axis=1)
184
+ byte_vectors = np.random.randint(2, size=(batch_size, bits))
185
+ bit_vectors = np.packbits(byte_vectors, axis=1)
186
186
 
187
187
  index.add(labels, bit_vectors)
188
+ assert np.allclose(index.get_vectors(labels), byte_vectors, atol=0.1)
189
+ assert np.alltrue(index.get_vectors(labels, ScalarKind.B1) == bit_vectors)
190
+
188
191
  index.search(bit_vectors, 10)
189
192
 
190
193