usearch 0.14.0 → 0.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.
Files changed (64) hide show
  1. package/.github/workflows/release.yml +56 -4
  2. package/.github/workflows/update_version.sh +6 -1
  3. package/.vscode/launch.json +21 -22
  4. package/.vscode/settings.json +7 -1
  5. package/CITATION.cff +4 -4
  6. package/CMakeLists.txt +1 -1
  7. package/Cargo.toml +1 -1
  8. package/Package.swift +0 -1
  9. package/README.md +100 -27
  10. package/binding.gyp +0 -1
  11. package/build.gradle +1 -1
  12. package/build.rs +3 -3
  13. package/c/lib.cpp +32 -9
  14. package/c/usearch.h +67 -36
  15. package/conanfile.py +1 -1
  16. package/{src → cpp}/bench.cpp +52 -36
  17. package/{src → cpp}/test.cpp +17 -7
  18. package/docs/benchmarks.md +33 -10
  19. package/docs/c/index.rst +11 -0
  20. package/docs/c/reference.rst +7 -0
  21. package/docs/compilation.md +24 -9
  22. package/docs/conf.dox +6 -6
  23. package/docs/conf.py +3 -1
  24. package/docs/cpp/index.rst +11 -0
  25. package/docs/cpp/reference.rst +7 -0
  26. package/docs/index.rst +10 -0
  27. package/docs/java/index.rst +11 -0
  28. package/docs/java/reference.rst +7 -0
  29. package/docs/javascript/index.rst +11 -0
  30. package/docs/javascript/reference.rst +9 -0
  31. package/docs/python/index.rst +11 -0
  32. package/docs/python/reference.rst +35 -0
  33. package/golang/lib.go +1 -1
  34. package/include/usearch/{usearch.hpp → index.hpp} +152 -148
  35. package/include/usearch/index_punned_dense.hpp +633 -0
  36. package/include/usearch/index_punned_helpers.hpp +528 -0
  37. package/java/cloud/unum/usearch/cloud_unum_usearch_Index.cpp +8 -7
  38. package/javascript/lib.cpp +26 -50
  39. package/javascript/usearch.js +117 -2
  40. package/objc/USearchObjective.mm +145 -49
  41. package/objc/include/USearchObjective.h +106 -30
  42. package/package.json +2 -2
  43. package/python/lib.cpp +134 -331
  44. package/python/scripts/bench.ipynb +170 -0
  45. package/python/scripts/bench.py +87 -175
  46. package/python/scripts/index_faiss.py +100 -0
  47. package/python/scripts/test.py +41 -37
  48. package/python/usearch/eval.py +353 -0
  49. package/python/usearch/index.py +117 -113
  50. package/python/usearch/io.py +7 -2
  51. package/python/usearch/join.py +100 -0
  52. package/python/usearch/numba.py +101 -0
  53. package/rust/lib.cpp +27 -14
  54. package/rust/lib.hpp +4 -10
  55. package/rust/lib.rs +50 -17
  56. package/setup.py +12 -2
  57. package/simsimd/include/simsimd/simsimd.h +32 -3
  58. package/swift/Index+Sugar.swift +55 -29
  59. package/swift/Test.swift +1 -1
  60. package/wolfram/lib.cpp +4 -4
  61. package/python/scripts/bench_params.py +0 -201
  62. package/python/usearch/synthetic.py +0 -31
  63. package/src/punned.hpp +0 -906
  64. /package/{src → cpp}/CMakeLists.txt +0 -0
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.14.0'
7
+ version = '0.15.0'
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'
@@ -38,7 +38,7 @@
38
38
 
39
39
  #include <simsimd/simsimd.h>
40
40
 
41
- #include "punned.hpp"
41
+ #include <usearch/index_punned_dense.hpp>
42
42
 
43
43
  using namespace unum::usearch;
44
44
  using namespace unum;
@@ -432,46 +432,58 @@ struct args_t {
432
432
 
433
433
  bool big = false;
434
434
  bool native = false;
435
+
435
436
  bool quantize_f16 = false;
436
437
  bool quantize_f8 = false;
438
+ bool quantize_b1 = false;
437
439
 
438
440
  bool metric_ip = false;
439
441
  bool metric_l2 = false;
440
442
  bool metric_cos = false;
441
443
  bool metric_haversine = false;
442
- };
444
+ bool metric_hamming = false;
445
+ bool metric_tanimoto = false;
446
+ bool metric_sorensen = false;
447
+
448
+ metric_kind_t metric() const noexcept {
449
+ if (metric_l2)
450
+ return metric_kind_t::l2sq_k;
451
+ if (metric_cos)
452
+ return metric_kind_t::cos_k;
453
+ if (metric_haversine)
454
+ return metric_kind_t::haversine_k;
455
+ if (metric_hamming)
456
+ return metric_kind_t::hamming_k;
457
+ if (metric_tanimoto)
458
+ return metric_kind_t::tanimoto_k;
459
+ if (metric_sorensen)
460
+ return metric_kind_t::sorensen_k;
461
+ return metric_kind_t::ip_k;
462
+ }
443
463
 
444
- template <typename index_at, typename dataset_at> //
445
- index_at punned_index_for_metric(dataset_at& dataset, args_t const& args, index_config_t config, accuracy_t accuracy) {
446
- if (args.metric_l2) {
447
- std::printf("-- Metric: Euclidean\n");
448
- return index_at::l2sq(dataset.dimensions(), accuracy, config);
449
- } else if (args.metric_cos) {
450
- std::printf("-- Metric: Angular\n");
451
- return index_at::cos(dataset.dimensions(), accuracy, config);
452
- } else if (args.metric_haversine) {
453
- std::printf("-- Metric: Haversine\n");
454
- return index_at::haversine(accuracy, config);
455
- } else {
456
- std::printf("-- Metric: Inner Product\n");
457
- return index_at::ip(dataset.dimensions(), accuracy, config);
464
+ scalar_kind_t accuracy() const noexcept {
465
+ if (quantize_f16)
466
+ return scalar_kind_t::f16_k;
467
+ if (quantize_f8)
468
+ return scalar_kind_t::f8_k;
469
+ if (quantize_b1)
470
+ return scalar_kind_t::b1x8_k;
471
+ return scalar_kind_t::f32_k;
458
472
  }
459
- }
473
+ };
460
474
 
461
475
  template <typename index_at, typename dataset_at> //
462
476
  void run_punned(dataset_at& dataset, args_t const& args, index_config_t config, index_limits_t limits) {
463
477
 
464
- accuracy_t accuracy = accuracy_t::f32_k;
465
- if (args.quantize_f16)
466
- accuracy = accuracy_t::f16_k;
467
- if (args.quantize_f8)
468
- accuracy = accuracy_t::f8_k;
478
+ scalar_kind_t accuracy = args.accuracy();
479
+ std::printf("-- Accuracy: %s\n", scalar_kind_name(accuracy));
469
480
 
470
- std::printf("-- Accuracy: %s\n", accuracy_name(accuracy));
481
+ metric_kind_t kind = args.metric();
482
+ std::printf("-- Metric: %s\n", metric_kind_name(kind));
471
483
 
472
- index_at index{punned_index_for_metric<index_at>(dataset, args, config, accuracy)};
484
+ index_at index = index_at::make(dataset.dimensions(), kind, config, accuracy);
473
485
  index.reserve(limits);
474
- std::printf("-- Hardware acceleration: %s\n", isa_name(index.acceleration()));
486
+ std::printf("-- Hardware acceleration: %s\n", isa_name(index.isa()));
475
487
  std::printf("Will benchmark in-memory\n");
476
488
 
477
489
  single_shot(dataset, index, true);
@@ -518,7 +530,7 @@ void run_big_or_small(dataset_at& dataset, args_t const& args, index_config_t co
518
530
  run_typed<index_gt<ip_gt<float>, std::size_t, neighbor_id_at>>(dataset, args, config, limits);
519
531
  }
520
532
  } else
521
- run_punned<punned_gt<std::size_t, neighbor_id_at>>(dataset, args, config, limits);
533
+ run_punned<index_punned_dense_gt<std::size_t, neighbor_id_at>>(dataset, args, config, limits);
522
534
  }
523
535
 
524
536
  void report_alternative_setups() {
@@ -537,8 +549,8 @@ void report_expected_losses(persisted_dataset_gt<float, vector_id_t> const& data
537
549
 
538
550
  auto vec1 = dataset.vector(0);
539
551
  auto vec2 = dataset.query(0);
540
- std::vector<f16_bits_t> vec1f16(dataset.dimensions());
541
- std::vector<f16_bits_t> vec2f16(dataset.dimensions());
552
+ std::vector<f16_t> vec1f16(dataset.dimensions());
553
+ std::vector<f16_t> vec2f16(dataset.dimensions());
542
554
  std::transform(vec1, vec1 + dataset.dimensions(), vec1f16.data(), [](float v) { return v; });
543
555
  std::transform(vec2, vec2 + dataset.dimensions(), vec2f16.data(), [](float v) { return v; });
544
556
  std::vector<f8_bits_t> vec1f8(dataset.dimensions());
@@ -548,7 +560,7 @@ void report_expected_losses(persisted_dataset_gt<float, vector_id_t> const& data
548
560
 
549
561
  #if 0
550
562
  auto ip_default = ip_gt<float>{}(vec1, vec2, dataset.dimensions());
551
- auto ip_f16 = ip_gt<f16_bits_t, float>{}(vec1f16.data(), vec2f16.data(), dataset.dimensions());
563
+ auto ip_f16 = ip_gt<f16_t, float>{}(vec1f16.data(), vec2f16.data(), dataset.dimensions());
552
564
  auto ip_f8 = ip_gt<f8_bits_t, float>{}(vec1f8.data(), vec2f8.data(), dataset.dimensions());
553
565
 
554
566
  #if defined(__AVX512F__)
@@ -591,12 +603,16 @@ int main(int argc, char** argv) {
591
603
  (option("--rows-take") & value("integer", args.vectors_to_take)).doc("Number of vectors to take"),
592
604
  ( //
593
605
  option("--native").set(args.native).doc("Use raw templates instead of type-punned classes") |
594
- option("--f16quant").set(args.quantize_f16).doc("Enable `f16_t` quantization") |
595
- option("--f8quant").set(args.quantize_f8).doc("Enable `f8_t` quantization")),
606
+ option("-f16", "--f16quant").set(args.quantize_f16).doc("Enable `f16_t` quantization") |
607
+ option("-f8", "--f8quant").set(args.quantize_f8).doc("Enable `f8_t` quantization") |
608
+ option("-b1", "--b1quant").set(args.quantize_b1).doc("Enable `b1x8_t` quantization")),
596
609
  ( //
597
610
  option("--ip").set(args.metric_ip).doc("Choose Inner Product metric") |
598
611
  option("--l2sq").set(args.metric_l2).doc("Choose L2 Euclidean metric") |
599
612
  option("--cos").set(args.metric_cos).doc("Choose Angular metric") |
613
+ option("--hamming").set(args.metric_hamming).doc("Choose Hamming metric") |
614
+ option("--tanimoto").set(args.metric_tanimoto).doc("Choose Tanimoto metric") |
615
+ option("--sorensen").set(args.metric_sorensen).doc("Choose Sorensen metric") |
600
616
  option("--haversine").set(args.metric_haversine).doc("Choose Haversine metric")),
601
617
  option("-h", "--help").set(args.help).doc("Print this help information on this tool and exit"));
602
618
 
@@ -609,7 +625,7 @@ int main(int argc, char** argv) {
609
625
  exit(0);
610
626
  }
611
627
 
612
- // Instead of relying on `multithreaded` from "punned.hpp" we will use OpenMP
628
+ // Instead of relying on `multithreaded` from "index_punned_dense.hpp" we will use OpenMP
613
629
  // to better estimate statistics between tasks batches, without having to recreate
614
630
  // the threads.
615
631
  omp_set_dynamic(true);
@@ -638,16 +654,16 @@ int main(int argc, char** argv) {
638
654
 
639
655
  index_config_t config;
640
656
  config.connectivity = args.connectivity;
641
- config.expansion_add = args.expansion_add;
642
- config.expansion_search = args.expansion_search;
657
+ // config.expansion_add = args.expansion_add;
658
+ // config.expansion_search = args.expansion_search;
643
659
  index_limits_t limits;
644
660
  limits.threads_add = limits.threads_search = args.threads;
645
661
  limits.elements = dataset.vectors_count();
646
662
 
647
663
  std::printf("- Index: \n");
648
664
  std::printf("-- Connectivity: %zu\n", config.connectivity);
649
- std::printf("-- Expansion @ Add: %zu\n", config.expansion_add);
650
- std::printf("-- Expansion @ Search: %zu\n", config.expansion_search);
665
+ // std::printf("-- Expansion @ Add: %zu\n", config.expansion_add);
666
+ // std::printf("-- Expansion @ Search: %zu\n", config.expansion_search);
651
667
 
652
668
  if (args.big)
653
669
  run_big_or_small<uint40_t>(dataset, args, config, limits);
@@ -4,7 +4,7 @@
4
4
  #include <algorithm>
5
5
  #include <stdexcept>
6
6
 
7
- #include "punned.hpp"
7
+ #include <usearch/index_punned_dense.hpp>
8
8
 
9
9
  using namespace unum::usearch;
10
10
  using namespace unum;
@@ -134,20 +134,30 @@ template <typename index_at> void test_sets_moved() {
134
134
 
135
135
  int main(int, char**) {
136
136
 
137
+ static_assert(!std::is_same<index_gt<ip_gt<>>::value_type, std::true_type>());
138
+ static_assert(!std::is_same<index_gt<cos_gt<>>::value_type, std::true_type>());
139
+ static_assert(!std::is_same<index_gt<l2sq_gt<>>::value_type, std::true_type>());
140
+ // static_assert(!std::is_same<index_gt<hamming_gt<>>::value_type, std::true_type>());
141
+ // static_assert(!std::is_same<index_gt<tanimoto_gt<>>::value_type, std::true_type>());
142
+ // static_assert(!std::is_same<index_gt<sorensen_gt<>>::value_type, std::true_type>());
143
+ // static_assert(!std::is_same<index_gt<jaccard_gt<>>::value_type, std::true_type>());
144
+ // static_assert(!std::is_same<index_gt<pearson_correlation_gt<>>::value_type, std::true_type>());
145
+ // static_assert(!std::is_same<index_gt<haversine_gt<>>::value_type, std::true_type>());
146
+
137
147
  test3d<float>(index_gt<cos_gt<float>, point_id_t, std::uint32_t, float>{});
138
148
  test3d<float>(index_gt<l2sq_gt<float>, point_id_t, std::uint32_t, float>{});
139
149
 
140
150
  test3d<double>(index_gt<cos_gt<double>, point_id_t, std::uint32_t, double>{});
141
151
  test3d<double>(index_gt<l2sq_gt<double>, point_id_t, std::uint32_t, double>{});
142
152
 
143
- test3d<float>(punned_small_t::cos(3));
144
- test3d<float>(punned_small_t::l2sq(3));
153
+ test3d<float>(punned_small_t::make(3, metric_kind_t::cos_k));
154
+ test3d<float>(punned_small_t::make(3, metric_kind_t::l2sq_k));
145
155
 
146
- test3d<double>(punned_small_t::cos(3));
147
- test3d<double>(punned_small_t::l2sq(3));
156
+ test3d<double>(punned_small_t::make(3, metric_kind_t::cos_k));
157
+ test3d<double>(punned_small_t::make(3, metric_kind_t::l2sq_k));
148
158
 
149
- test3d_punned<float>(punned_small_t::cos(3));
150
- test3d_punned<float>(punned_small_t::l2sq(3));
159
+ test3d_punned<float>(punned_small_t::make(3, metric_kind_t::cos_k));
160
+ test3d_punned<float>(punned_small_t::make(3, metric_kind_t::l2sq_k));
151
161
 
152
162
  test_sets(index_gt<jaccard_gt<std::int32_t, float>, point_id_t, std::uint32_t, std::int32_t>{});
153
163
  test_sets(index_gt<jaccard_gt<std::int64_t, float>, point_id_t, std::uint32_t, std::int64_t>{});
@@ -55,7 +55,7 @@ Also worth noting, 8-bit quantization results in almost no accuracy loss and may
55
55
 
56
56
  Within this repository you will find two commonly used utilities:
57
57
 
58
- - `src/bench.cpp` the produces the `bench` binary for broad USearch benchmarks.
58
+ - `cpp/bench.cpp` the produces the `bench` binary for broad USearch benchmarks.
59
59
  - `python/bench.py` for simple benchmarks against FAISS.
60
60
 
61
61
  To achieve best highest results we suggest compiling locally for the target architecture.
@@ -170,15 +170,6 @@ mkdir -p datasets/deep_1B/ && \
170
170
 
171
171
  ## Profiling
172
172
 
173
- Enabling Huge Pages:
174
-
175
- ```sh
176
- sudo cat /proc/sys/vm/nr_hugepages
177
- sudo sysctl -w vm.nr_hugepages=2048
178
- sudo reboot
179
- sudo cat /proc/sys/vm/nr_hugepages
180
- ```
181
-
182
173
  With `perf`:
183
174
 
184
175
  ```sh
@@ -189,3 +180,35 @@ sudo -E perf mem -d ./build_release/bench ...
189
180
  sudo -E perf record -F 1000 ./build_release/bench ...
190
181
  perf record -d -e arm_spe// -- ./build_release/bench ..
191
182
  ```
183
+
184
+ ### Caches
185
+
186
+ ```sh
187
+ sudo perf stat -e 'faults,dTLB-loads,dTLB-load-misses,cache-misses,cache-references' ./build_release/bench ...
188
+ ```
189
+
190
+ Typical output on a 1M vectors dataset is:
191
+
192
+ ```txt
193
+ 255426 faults
194
+ 305988813388 dTLB-loads
195
+ 8845723783 dTLB-load-misses # 2.89% of all dTLB cache accesses
196
+ 20094264206 cache-misses # 6.567 % of all cache refs
197
+ 305988812745 cache-references
198
+
199
+ 8.285148010 seconds time elapsed
200
+
201
+ 500.705967000 seconds user
202
+ 1.371118000 seconds sys
203
+ ```
204
+
205
+ If you notice problems and the stalls are closer to 90%, it might be a good reason to consider enabling Huge Pages and tuning allocations alignment.
206
+ To enable Huge Pages:
207
+
208
+ ```sh
209
+ sudo cat /proc/sys/vm/nr_hugepages
210
+ sudo sysctl -w vm.nr_hugepages=2048
211
+ sudo reboot
212
+ sudo cat /proc/sys/vm/nr_hugepages
213
+ ```
214
+
@@ -0,0 +1,11 @@
1
+ =======
2
+ C SDK
3
+ =======
4
+
5
+
6
+ .. mdinclude:: ../../c/README.md
7
+
8
+ .. toctree::
9
+ :hidden:
10
+
11
+ reference
@@ -0,0 +1,7 @@
1
+ API Reference
2
+ ===============
3
+
4
+ ===============
5
+ usearch
6
+ ===============
7
+ .. doxygenfile:: usearch.h
@@ -41,7 +41,10 @@ cmake -B ./build_release \
41
41
  Linting:
42
42
 
43
43
  ```sh
44
- cppcheck --enable=all --suppress=cstyleCast --suppress=unusedFunction include/usearch/usearch.hpp src/punned.hpp
44
+ cppcheck --enable=all --suppress=cstyleCast --suppress=unusedFunction \
45
+ include/usearch/index.hpp \
46
+ include/index_punned_dense.hpp \
47
+ include/index_punned_helpers.hpp
45
48
  ```
46
49
 
47
50
  Benchmarking:
@@ -81,7 +84,7 @@ Benchmarking:
81
84
 
82
85
  ```sh
83
86
  pip install faiss-cpu
84
- python python/scripts/bench.py \
87
+ python python/scripts/bench.py speed \
85
88
  --vectors datasets/wiki_1M/base.1M.fbin \
86
89
  --queries datasets/wiki_1M/query.public.100K.fbin \
87
90
  --neighbors datasets/wiki_1M/groundtruth.public.100K.ibin
@@ -92,9 +95,8 @@ python python/scripts/bench.py \
92
95
  Checking the effect of different embedding dimensions on construction speed:
93
96
 
94
97
  ```sh
95
- python python/scripts/bench_params.py dimensions
96
- python python/scripts/bench_params.py connectivity
97
- python python/scripts/bench_params.py robustness
98
+ python python/scripts/bench.py dimensions ...
99
+ python python/scripts/bench.py connectivity ...
98
100
  ```
99
101
 
100
102
  ## JavaScript
@@ -115,7 +117,7 @@ cargo publish
115
117
 
116
118
  ```sh
117
119
  gradle clean build
118
- java -cp . -Djava.library.path=/Users/av/github/usearch/build/libs/usearch/shared java/cloud/unum/usearch/Index.java
120
+ java -cp . -Djava.library.path="$(pwd)/build/libs/usearch/shared" java/cloud/unum/usearch/Index.java
119
121
  ```
120
122
 
121
123
  Or step by-step:
@@ -135,15 +137,14 @@ g++ -shared -o USearchJNI.dll cloud_unum_usearch_Index.o -Wl,--add-stdcall-alias
135
137
  # MacOS
136
138
  g++ -std=c++11 -c -fPIC \
137
139
  -I../../../../include \
138
- -I../../../../src \
139
140
  -I../../../../fp16/include \
140
141
  -I../../../../robin-map/include \
141
142
  -I../../../../simsimd/include \
142
143
  -I${JAVA_HOME}/include -I${JAVA_HOME}/include/darwin cloud_unum_usearch_Index.cpp -o cloud_unum_usearch_Index.o
143
144
  g++ -dynamiclib -o libusearch.dylib cloud_unum_usearch_Index.o -lc
144
145
  # Run linking to that directory
145
- java -cp . -Djava.library.path=/Users/av/github/usearch/java/cloud/unum/usearch/ Index.java
146
- java -cp . -Djava.library.path=/Users/av/github/usearch/java cloud.unum.usearch.Index
146
+ java -cp . -Djava.library.path="$(pwd)/java/cloud/unum/usearch/" Index.java
147
+ java -cp . -Djava.library.path="$(pwd)/java" cloud.unum.usearch.Index
147
148
  ```
148
149
 
149
150
  ## Wolfram
@@ -159,6 +160,12 @@ cd golang
159
160
  go test -v
160
161
  ```
161
162
 
163
+ ## Objective-C and Swift
164
+
165
+ ```sh
166
+ swift build
167
+ ```
168
+
162
169
  ## C
163
170
 
164
171
  ### Linux
@@ -186,4 +193,12 @@ docker buildx create --use &&
186
193
  --tag unum/usearch:$version \
187
194
  --tag unum/usearch:latest \
188
195
  --push .
196
+ ```
197
+
198
+ ---
199
+
200
+ Extending metrics in SimSIMD:
201
+
202
+ ```
203
+ git push --set-upstream https://github.com/ashvardanian/simsimd.git HEAD:main
189
204
  ```
package/docs/conf.dox CHANGED
@@ -872,7 +872,7 @@ WARN_LOGFILE =
872
872
  # - Testing
873
873
  # - Benchmarks
874
874
 
875
- INPUT = ../include/usearch
875
+ INPUT = ../include/usearch ../c/usearch.h ../java/cloud/unum/usearch/Index.java
876
876
 
877
877
  # This tag can be used to specify the character encoding of the source files
878
878
  # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -1290,9 +1290,9 @@ HTML_STYLESHEET =
1290
1290
  # list). For an example see the documentation.
1291
1291
  # This tag requires that the tag GENERATE_HTML is set to YES.
1292
1292
 
1293
- HTML_EXTRA_STYLESHEET = doxygen-awesome-css/doxygen-awesome.css \
1294
- doxygen-awesome-css/doxygen-awesome-sidebar-only.css \
1295
- doxygen-awesome-css/doxygen-awesome-sidebar-only-darkmode-toggle.css
1293
+ HTML_EXTRA_STYLESHEET =
1294
+
1295
+
1296
1296
 
1297
1297
  # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
1298
1298
  # other source files which should be copied to the HTML output directory. Note
@@ -1302,8 +1302,8 @@ HTML_EXTRA_STYLESHEET = doxygen-awesome-css/doxygen-awesome.css \
1302
1302
  # files will be copied as-is; there are no commands or markers available.
1303
1303
  # This tag requires that the tag GENERATE_HTML is set to YES.
1304
1304
 
1305
- HTML_EXTRA_FILES = doxygen-awesome-css/doxygen-awesome-darkmode-toggle.js \
1306
- doxygen-awesome-css/doxygen-awesome-interactive-toc.js
1305
+ HTML_EXTRA_FILES =
1306
+
1307
1307
 
1308
1308
  # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
1309
1309
  # will adjust the colors in the style sheet and background images according to
package/docs/conf.py CHANGED
@@ -21,7 +21,7 @@ with open('_static/custom.js', 'r+') as js:
21
21
 
22
22
  extensions = [
23
23
  'breathe', 'm2r2',
24
- 'sphinx.ext.autodoc',
24
+ 'sphinx.ext.autodoc', 'sphinx_js',
25
25
  'sphinx.ext.autosummary',
26
26
  'sphinx.ext.intersphinx',
27
27
  'sphinx.ext.napoleon',
@@ -46,3 +46,5 @@ html_baseurl = '/docs/usearch/'
46
46
 
47
47
  breathe_projects = {'USearch': '../build/xml'}
48
48
  breathe_default_project = 'USearch'
49
+
50
+ js_source_path = '../javascript/usearch.js'
@@ -0,0 +1,11 @@
1
+ =======
2
+ C++ SDK
3
+ =======
4
+
5
+
6
+ .. mdinclude:: ../../cpp/README.md
7
+
8
+ .. toctree::
9
+ :hidden:
10
+
11
+ reference
@@ -0,0 +1,7 @@
1
+ API Reference
2
+ ===============
3
+
4
+ ===============
5
+ usearch
6
+ ===============
7
+ .. doxygenfile:: index.hpp
package/docs/index.rst CHANGED
@@ -10,6 +10,16 @@ Overview
10
10
  benchmarks
11
11
  compilation
12
12
 
13
+ .. toctree::
14
+ :hidden:
15
+ :caption: �
16
+
17
+ c/index
18
+ cpp/index
19
+ java/index
20
+ python/index
21
+ javascript/index
22
+
13
23
  .. toctree::
14
24
  :hidden:
15
25
  :caption: �
@@ -0,0 +1,11 @@
1
+ ================
2
+ Java SDK
3
+ ================
4
+
5
+
6
+ .. mdinclude:: ../../java/README.md
7
+
8
+ .. toctree::
9
+ :hidden:
10
+
11
+ reference
@@ -0,0 +1,7 @@
1
+ API Reference
2
+ ===============
3
+
4
+ ===============
5
+ usearch
6
+ ===============
7
+ .. doxygenfile:: Index.java
@@ -0,0 +1,11 @@
1
+ ==============
2
+ JavaScript SDK
3
+ ==============
4
+
5
+
6
+ .. mdinclude:: ../javascript/README.md
7
+
8
+ .. toctree::
9
+ :hidden:
10
+
11
+ reference
@@ -0,0 +1,9 @@
1
+ API Reference
2
+ ===============
3
+
4
+ ==================
5
+ usearch.Index
6
+ ==================
7
+
8
+ .. js:autoclass:: Index
9
+ :members:
@@ -0,0 +1,11 @@
1
+ ==============
2
+ Python SDK
3
+ ==============
4
+
5
+
6
+ .. mdinclude:: ../python/README.md
7
+
8
+ .. toctree::
9
+ :hidden:
10
+
11
+ reference
@@ -0,0 +1,35 @@
1
+ API Reference
2
+ ===============
3
+
4
+ ======
5
+ Index
6
+ ======
7
+
8
+ .. automodule:: usearch.index
9
+ :members:
10
+ :undoc-members:
11
+
12
+ ======
13
+ IO
14
+ ======
15
+
16
+ .. automodule:: usearch.io
17
+ :members:
18
+ :undoc-members:
19
+
20
+ ======
21
+ Client
22
+ ======
23
+
24
+ .. automodule:: usearch.client
25
+ :members:
26
+ :undoc-members:
27
+
28
+
29
+ ======
30
+ Server
31
+ ======
32
+
33
+ .. automodule:: usearch.server
34
+ :members:
35
+ :undoc-members:
package/golang/lib.go CHANGED
@@ -118,7 +118,7 @@ func (ind *Index) Destroy() {
118
118
  if ind.opaque_handle == nil {
119
119
  panic("index not initialized")
120
120
  }
121
- C.usearch_destroy(unsafe.Pointer(ind.opaque_handle))
121
+ C.usearch_free(unsafe.Pointer(ind.opaque_handle))
122
122
  ind.opaque_handle = nil
123
123
  ind.config = IndexConfig{}
124
124
  }