usearch 0.18.4 → 0.18.6
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
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.
|
|
7
|
+
version = '0.18.6'
|
|
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,
|
|
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,
|
|
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,
|
|
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*
|
|
392
|
-
bool casted = cast(
|
|
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,
|
|
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
|
|
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 +
|
|
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
|
|
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
|
|
530
|
-
|
|
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
|
|
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
|
|
541
|
-
|
|
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
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
|
-
|
|
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();
|
package/python/scripts/bench.py
CHANGED
package/python/scripts/test.py
CHANGED
|
@@ -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
|
-
|
|
185
|
-
bit_vectors = np.packbits(
|
|
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.all(index.get_vectors(labels, ScalarKind.B1) == bit_vectors)
|
|
190
|
+
|
|
188
191
|
index.search(bit_vectors, 10)
|
|
189
192
|
|
|
190
193
|
|