faiss 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 47b973803ea179379ab292d5d7b8350c12a383387e90b96f38eae4e90e20dad3
4
+ data.tar.gz: 5697b1ec26dbbb0794e6c11563b0cf76d564391882e7c0c0148f3893e1bf6b59
5
+ SHA512:
6
+ metadata.gz: dccf5a8ddfd4030e70308c3e71b16bb6742839b8b1a263d3a010a381729af869c1755164e25a3941a3f475376e783ec42b43409fede77010e97949092a424e18
7
+ data.tar.gz: 57c933bc9d3ffbec37be0edbf641bd004e8dbfa13c04d52ca970e8ff03f719f65f27016892b06cd66755f36afc8d3ff505e6062656f2c48fa20d58cf64c2b6fd
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## 0.1.0 (2020-03-08)
2
+
3
+ - First release
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2020 Andrew Kane
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,130 @@
1
+ # Faiss
2
+
3
+ [Faiss](https://github.com/facebookresearch/faiss) - efficient similarity search and clustering - for Ruby
4
+
5
+ ## Installation
6
+
7
+ First, install the [Faiss C++ library](https://github.com/facebookresearch/faiss/blob/master/INSTALL.md). For Homebrew, use:
8
+
9
+ ```sh
10
+ brew install faiss
11
+ ```
12
+
13
+ Add this line to your application’s Gemfile:
14
+
15
+ ```ruby
16
+ gem 'faiss'
17
+ ```
18
+
19
+ ## Getting Started
20
+
21
+ Prep your data
22
+
23
+ ```ruby
24
+ objects = [
25
+ [1, 1, 2, 1],
26
+ [5, 4, 6, 5],
27
+ [1, 2, 1, 2]
28
+ ]
29
+ ```
30
+
31
+ Build an index
32
+
33
+ ```ruby
34
+ index = Faiss::IndexFlatL2.new(4)
35
+ index.add(objects)
36
+ ```
37
+
38
+ Search
39
+
40
+ ```ruby
41
+ distances, ids = index.search(objects, 3)
42
+ ```
43
+
44
+ ## K-means Clustering
45
+
46
+ Train
47
+
48
+ ```ruby
49
+ kmeans = Faiss::Kmeans.new(4, 2)
50
+ kmeans.train(objects)
51
+ ```
52
+
53
+ Get the centroids
54
+
55
+ ```ruby
56
+ kmeans.centroids
57
+ ```
58
+
59
+ ## PCA
60
+
61
+ Train
62
+
63
+ ```ruby
64
+ mat = Faiss::PCAMatrix.new(40, 10)
65
+ mat.train(objects)
66
+ ```
67
+
68
+ Apply
69
+
70
+ ```ruby
71
+ mat.apply(mt)
72
+ ```
73
+
74
+ ## Product Quantizer
75
+
76
+ Train
77
+
78
+ ```ruby
79
+ pq = Faiss::ProductQuantizer.new(32, 4, 8)
80
+ pq.train(objects)
81
+ ```
82
+
83
+ Encode
84
+
85
+ ```ruby
86
+ pq.compute_codes(objects)
87
+ ```
88
+
89
+ Decode
90
+
91
+ ```ruby
92
+ pq.decode(codes)
93
+ ```
94
+
95
+ ## Data
96
+
97
+ Data can be an array of arrays
98
+
99
+ ```ruby
100
+ [[1, 2, 3], [4, 5, 6]]
101
+ ```
102
+
103
+ Or a Numo NArray
104
+
105
+ ```ruby
106
+ Numo::SFloat.new(3, 2).seq
107
+ ```
108
+
109
+ ## History
110
+
111
+ View the [changelog](https://github.com/ankane/faiss/blob/master/CHANGELOG.md)
112
+
113
+ ## Contributing
114
+
115
+ Everyone is encouraged to help improve this project. Here are a few ways you can help:
116
+
117
+ - [Report bugs](https://github.com/ankane/faiss/issues)
118
+ - Fix bugs and [submit pull requests](https://github.com/ankane/faiss/pulls)
119
+ - Write, clarify, or fix documentation
120
+ - Suggest or add new features
121
+
122
+ To get started with development:
123
+
124
+ ```sh
125
+ git clone https://github.com/ankane/faiss.git
126
+ cd faiss
127
+ bundle install
128
+ bundle exec rake compile
129
+ bundle exec rake test
130
+ ```
data/ext/faiss/ext.cpp ADDED
@@ -0,0 +1,248 @@
1
+ #include <faiss/IndexFlat.h>
2
+ #include <faiss/IndexHNSW.h>
3
+ #include <faiss/IndexIVFFlat.h>
4
+ #include <faiss/IndexLSH.h>
5
+ #include <faiss/IndexScalarQuantizer.h>
6
+ #include <faiss/IndexPQ.h>
7
+ #include <faiss/IndexIVFPQ.h>
8
+ #include <faiss/IndexIVFPQR.h>
9
+
10
+ #include <faiss/IndexBinaryFlat.h>
11
+ #include <faiss/IndexBinaryIVF.h>
12
+ #include <faiss/index_factory.h>
13
+
14
+ #include <faiss/Clustering.h>
15
+ #include <faiss/VectorTransform.h>
16
+
17
+ #include <rice/Array.hpp>
18
+ #include <rice/Class.hpp>
19
+ #include <rice/Constructor.hpp>
20
+ #include <rice/Module.hpp>
21
+
22
+ extern "C"
23
+ void Init_ext()
24
+ {
25
+ Rice::Module rb_mFaiss = Rice::define_module("Faiss")
26
+ .define_singleton_method(
27
+ "index_binary_factory",
28
+ *[](int d, const char *description) {
29
+ return faiss::index_binary_factory(d, description);
30
+ });
31
+
32
+ Rice::define_class_under<faiss::Index>(rb_mFaiss, "Index")
33
+ .define_method(
34
+ "d",
35
+ *[](faiss::Index &self) {
36
+ return self.d;
37
+ })
38
+ .define_method(
39
+ "trained?",
40
+ *[](faiss::Index &self) {
41
+ return self.is_trained;
42
+ })
43
+ .define_method(
44
+ "ntotal",
45
+ *[](faiss::Index &self) {
46
+ return self.ntotal;
47
+ })
48
+ .define_method(
49
+ "_train",
50
+ *[](faiss::Index &self, int64_t n, Rice::String s) {
51
+ const float *x = (float*) s.c_str();
52
+ self.train(n, x);
53
+ })
54
+ .define_method(
55
+ "_add",
56
+ *[](faiss::Index &self, int64_t n, Rice::String s) {
57
+ const float *x = (float*) s.c_str();
58
+ self.add(n, x);
59
+ })
60
+ .define_method(
61
+ "_search",
62
+ *[](faiss::Index &self, int64_t n, Rice::String s, int64_t k) {
63
+ const float *x = (float*) s.c_str();
64
+ float *distances = new float[k * n];
65
+ int64_t *labels = new int64_t[k * n];
66
+
67
+ self.search(n, x, k, distances, labels);
68
+
69
+ auto dstr = std::string((char*) distances, k * n * sizeof(float));
70
+ auto lstr = std::string((char*) labels, k * n * sizeof(int64_t));
71
+
72
+ Rice::Array ret;
73
+ ret.push(dstr);
74
+ ret.push(lstr);
75
+ return ret;
76
+ });
77
+
78
+ Rice::define_class_under<faiss::IndexBinary>(rb_mFaiss, "IndexBinary")
79
+ .define_method(
80
+ "d",
81
+ *[](faiss::Index &self) {
82
+ return self.d;
83
+ })
84
+ .define_method(
85
+ "trained?",
86
+ *[](faiss::IndexBinary &self) {
87
+ return self.is_trained;
88
+ })
89
+ .define_method(
90
+ "ntotal",
91
+ *[](faiss::IndexBinary &self) {
92
+ return self.ntotal;
93
+ })
94
+ .define_method(
95
+ "_train",
96
+ *[](faiss::IndexBinary &self, int64_t n, Rice::String s) {
97
+ const uint8_t *x = (uint8_t*) s.c_str();
98
+ self.train(n, x);
99
+ })
100
+ .define_method(
101
+ "_add",
102
+ *[](faiss::IndexBinary &self, int64_t n, Rice::String s) {
103
+ const uint8_t *x = (uint8_t*) s.c_str();
104
+ self.add(n, x);
105
+ })
106
+ .define_method(
107
+ "_search",
108
+ *[](faiss::IndexBinary &self, int64_t n, Rice::String s, int64_t k) {
109
+ const uint8_t *x = (uint8_t*) s.c_str();
110
+ int32_t *distances = new int32_t[k * n];
111
+ int64_t *labels = new int64_t[k * n];
112
+
113
+ self.search(n, x, k, distances, labels);
114
+
115
+ auto dstr = std::string((char*) distances, k * n * sizeof(int32_t));
116
+ auto lstr = std::string((char*) labels, k * n * sizeof(int64_t));
117
+
118
+ Rice::Array ret;
119
+ ret.push(dstr);
120
+ ret.push(lstr);
121
+ return ret;
122
+ });
123
+
124
+ Rice::define_class_under<faiss::IndexFlatL2, faiss::Index>(rb_mFaiss, "IndexFlatL2")
125
+ .define_constructor(Rice::Constructor<faiss::IndexFlatL2, int64_t>());
126
+
127
+ Rice::define_class_under<faiss::IndexFlatIP, faiss::Index>(rb_mFaiss, "IndexFlatIP")
128
+ .define_constructor(Rice::Constructor<faiss::IndexFlatIP, int64_t>());
129
+
130
+ Rice::define_class_under<faiss::IndexHNSWFlat, faiss::Index>(rb_mFaiss, "IndexHNSWFlat")
131
+ .define_constructor(Rice::Constructor<faiss::IndexHNSWFlat, int, int>());
132
+
133
+ Rice::define_class_under<faiss::IndexIVFFlat, faiss::Index>(rb_mFaiss, "IndexIVFFlat")
134
+ .define_constructor(Rice::Constructor<faiss::IndexIVFFlat, faiss::Index*, size_t, size_t>());
135
+
136
+ Rice::define_class_under<faiss::IndexLSH, faiss::Index>(rb_mFaiss, "IndexLSH")
137
+ .define_constructor(Rice::Constructor<faiss::IndexLSH, int64_t, int>());
138
+
139
+ Rice::define_class_under<faiss::IndexScalarQuantizer, faiss::Index>(rb_mFaiss, "IndexScalarQuantizer")
140
+ .define_constructor(Rice::Constructor<faiss::IndexScalarQuantizer, int, faiss::ScalarQuantizer::QuantizerType>());
141
+
142
+ Rice::define_class_under<faiss::IndexPQ, faiss::Index>(rb_mFaiss, "IndexPQ")
143
+ .define_constructor(Rice::Constructor<faiss::IndexPQ, int, size_t, size_t>());
144
+
145
+ Rice::define_class_under<faiss::IndexIVFScalarQuantizer, faiss::Index>(rb_mFaiss, "IndexIVFScalarQuantizer")
146
+ .define_constructor(Rice::Constructor<faiss::IndexIVFScalarQuantizer, faiss::Index*, size_t, size_t, faiss::ScalarQuantizer::QuantizerType>());
147
+
148
+ Rice::define_class_under<faiss::IndexIVFPQ, faiss::Index>(rb_mFaiss, "IndexIVFPQ")
149
+ .define_constructor(Rice::Constructor<faiss::IndexIVFPQ, faiss::Index*, size_t, size_t, size_t, size_t>());
150
+
151
+ Rice::define_class_under<faiss::IndexIVFPQR, faiss::Index>(rb_mFaiss, "IndexIVFPQR")
152
+ .define_constructor(Rice::Constructor<faiss::IndexIVFPQR, faiss::Index*, size_t, size_t, size_t, size_t, size_t, size_t>());
153
+
154
+ Rice::define_class_under<faiss::IndexBinaryFlat, faiss::IndexBinary>(rb_mFaiss, "IndexBinaryFlat")
155
+ .define_constructor(Rice::Constructor<faiss::IndexBinaryFlat, int64_t>());
156
+
157
+ Rice::define_class_under<faiss::IndexBinaryIVF, faiss::IndexBinary>(rb_mFaiss, "IndexBinaryIVF")
158
+ .define_constructor(Rice::Constructor<faiss::IndexBinaryIVF, faiss::IndexBinary*, size_t, size_t>());
159
+
160
+ Rice::define_class_under<faiss::Clustering>(rb_mFaiss, "Kmeans")
161
+ .define_constructor(Rice::Constructor<faiss::Clustering, int, int>())
162
+ .define_method(
163
+ "d",
164
+ *[](faiss::Clustering &self) {
165
+ return self.d;
166
+ })
167
+ .define_method(
168
+ "k",
169
+ *[](faiss::Clustering &self) {
170
+ return self.k;
171
+ })
172
+ .define_method(
173
+ "_centroids",
174
+ *[](faiss::Clustering &self) {
175
+ float *centroids = new float[self.k * self.d];
176
+ for (size_t i = 0; i < self.centroids.size(); i++) {
177
+ centroids[i] = self.centroids[i];
178
+ }
179
+ return std::string((char*) centroids, self.k * self.d * sizeof(float));
180
+ })
181
+ .define_method(
182
+ "_train",
183
+ *[](faiss::Clustering &self, int64_t n, Rice::String s, faiss::Index & index) {
184
+ const float *x = (float*) s.c_str();
185
+ self.train(n, x, index);
186
+ });
187
+
188
+ Rice::define_class_under<faiss::PCAMatrix>(rb_mFaiss, "PCAMatrix")
189
+ .define_constructor(Rice::Constructor<faiss::PCAMatrix, int, int>())
190
+ .define_method(
191
+ "d_in",
192
+ *[](faiss::PCAMatrix &self) {
193
+ return self.d_in;
194
+ })
195
+ .define_method(
196
+ "d_out",
197
+ *[](faiss::PCAMatrix &self) {
198
+ return self.d_out;
199
+ })
200
+ .define_method(
201
+ "_train",
202
+ *[](faiss::PCAMatrix &self, int64_t n, Rice::String s) {
203
+ const float *x = (float*) s.c_str();
204
+ self.train(n, x);
205
+ })
206
+ .define_method(
207
+ "_apply",
208
+ *[](faiss::PCAMatrix &self, int64_t n, Rice::String s) {
209
+ const float *x = (float*) s.c_str();
210
+ float* res = self.apply(n, x);
211
+ return std::string((char*) res, n * self.d_out * sizeof(float));
212
+ });
213
+
214
+ Rice::define_class_under<faiss::ProductQuantizer>(rb_mFaiss, "ProductQuantizer")
215
+ .define_constructor(Rice::Constructor<faiss::ProductQuantizer, size_t, size_t, size_t>())
216
+ .define_method(
217
+ "d",
218
+ *[](faiss::ProductQuantizer &self) {
219
+ return self.d;
220
+ })
221
+ .define_method(
222
+ "m",
223
+ *[](faiss::ProductQuantizer &self) {
224
+ return self.M;
225
+ })
226
+ .define_method(
227
+ "_train",
228
+ *[](faiss::ProductQuantizer &self, int n, Rice::String s) {
229
+ const float *x = (float*) s.c_str();
230
+ self.train(n, x);
231
+ })
232
+ .define_method(
233
+ "_compute_codes",
234
+ *[](faiss::ProductQuantizer &self, int n, Rice::String s) {
235
+ const float *x = (float*) s.c_str();
236
+ uint8_t *codes = new uint8_t[n * self.M];
237
+ self.compute_codes(x, codes, n);
238
+ return std::string((char*) codes, n * self.M * sizeof(uint8_t));
239
+ })
240
+ .define_method(
241
+ "_decode",
242
+ *[](faiss::ProductQuantizer &self, int n, Rice::String s) {
243
+ const uint8_t *codes = (uint8_t*) s.c_str();
244
+ float *x = new float[n * self.d];
245
+ self.decode(codes, x, n);
246
+ return std::string((char*) x, n * self.d * sizeof(float));
247
+ });
248
+ }
@@ -0,0 +1,7 @@
1
+ require "mkmf-rice"
2
+
3
+ abort "Missing faiss" unless have_library("faiss")
4
+
5
+ $CXXFLAGS << " -std=c++11"
6
+
7
+ create_makefile("faiss/ext")
@@ -0,0 +1,20 @@
1
+ module Faiss
2
+ class Index
3
+ def train(objects)
4
+ objects = Numo::SFloat.cast(objects) unless objects.is_a?(Numo::SFloat)
5
+ _train(objects.shape[0], objects.to_binary)
6
+ end
7
+
8
+ def add(objects)
9
+ objects = Numo::SFloat.cast(objects) unless objects.is_a?(Numo::SFloat)
10
+ _add(objects.shape[0], objects.to_binary)
11
+ end
12
+
13
+ def search(objects, k)
14
+ objects = Numo::SFloat.cast(objects) unless objects.is_a?(Numo::SFloat)
15
+ n = objects.shape[0]
16
+ distances, labels = _search(n, objects.to_binary, k)
17
+ [Numo::SFloat.from_binary(distances).reshape(n, k), Numo::Int64.from_binary(labels).reshape(n, k)]
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ module Faiss
2
+ class IndexBinary
3
+ def train(objects)
4
+ objects = Numo::UInt8.cast(objects) unless objects.is_a?(Numo::UInt8)
5
+ _train(objects.shape[0], objects.to_binary)
6
+ end
7
+
8
+ def add(objects)
9
+ objects = Numo::UInt8.cast(objects) unless objects.is_a?(Numo::UInt8)
10
+ _add(objects.shape[0], objects.to_binary)
11
+ end
12
+
13
+ def search(objects, k)
14
+ objects = Numo::UInt8.cast(objects) unless objects.is_a?(Numo::UInt8)
15
+ n = objects.shape[0]
16
+ distances, labels = _search(n, objects.to_binary, k)
17
+ [Numo::UInt32.from_binary(distances).reshape(n, k), Numo::Int64.from_binary(labels).reshape(n, k)]
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,15 @@
1
+ module Faiss
2
+ class Kmeans
3
+ attr_reader :index
4
+
5
+ def train(objects)
6
+ objects = Numo::SFloat.cast(objects) unless objects.is_a?(Numo::SFloat)
7
+ @index = IndexFlatL2.new(d)
8
+ _train(objects.shape[0], objects.to_binary, @index)
9
+ end
10
+
11
+ def centroids
12
+ Numo::SFloat.from_binary(_centroids).reshape(k, d)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Faiss
2
+ class PCAMatrix
3
+ def train(objects)
4
+ objects = Numo::SFloat.cast(objects) unless objects.is_a?(Numo::SFloat)
5
+ _train(objects.shape[0], objects.to_binary)
6
+ end
7
+
8
+ def apply(objects)
9
+ objects = Numo::SFloat.cast(objects) unless objects.is_a?(Numo::SFloat)
10
+ n = objects.shape[0]
11
+ res = _apply(n, objects.to_binary)
12
+ Numo::SFloat.from_binary(res).reshape(n, d_out)
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ module Faiss
2
+ class ProductQuantizer
3
+ def train(objects)
4
+ objects = Numo::SFloat.cast(objects) unless objects.is_a?(Numo::SFloat)
5
+ _train(objects.shape[0], objects.to_binary)
6
+ end
7
+
8
+ def compute_codes(objects)
9
+ objects = Numo::SFloat.cast(objects) unless objects.is_a?(Numo::SFloat)
10
+ n = objects.shape[0]
11
+ res = _compute_codes(n, objects.to_binary)
12
+ Numo::UInt8.from_binary(res).reshape(n, m)
13
+ end
14
+
15
+ def decode(objects)
16
+ objects = Numo::UInt8.cast(objects) unless objects.is_a?(Numo::UInt8)
17
+ n = objects.shape[0]
18
+ res = _decode(n, objects.to_binary)
19
+ Numo::SFloat.from_binary(res).reshape(n, d)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module Faiss
2
+ VERSION = "0.1.0"
3
+ end
data/lib/faiss.rb ADDED
@@ -0,0 +1,13 @@
1
+ # dependencies
2
+ require "numo/narray"
3
+
4
+ # ext
5
+ require "faiss/ext"
6
+
7
+ # modules
8
+ require "faiss/index"
9
+ require "faiss/index_binary"
10
+ require "faiss/kmeans"
11
+ require "faiss/pca_matrix"
12
+ require "faiss/product_quantizer"
13
+ require "faiss/version"
metadata ADDED
@@ -0,0 +1,139 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: faiss
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Kane
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-03-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rice
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '2.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '2.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: numo-narray
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake-compiler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '5'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '5'
97
+ description:
98
+ email: andrew@chartkick.com
99
+ executables: []
100
+ extensions:
101
+ - ext/faiss/extconf.rb
102
+ extra_rdoc_files: []
103
+ files:
104
+ - CHANGELOG.md
105
+ - LICENSE.txt
106
+ - README.md
107
+ - ext/faiss/ext.cpp
108
+ - ext/faiss/extconf.rb
109
+ - lib/faiss.rb
110
+ - lib/faiss/index.rb
111
+ - lib/faiss/index_binary.rb
112
+ - lib/faiss/kmeans.rb
113
+ - lib/faiss/pca_matrix.rb
114
+ - lib/faiss/product_quantizer.rb
115
+ - lib/faiss/version.rb
116
+ homepage: https://github.com/ankane/faiss
117
+ licenses:
118
+ - MIT
119
+ metadata: {}
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '2.4'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubygems_version: 3.1.2
136
+ signing_key:
137
+ specification_version: 4
138
+ summary: Efficient similarity search and clustering for Ruby
139
+ test_files: []