ngt 0.4.0 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +9 -0
- data/lib/ngt/ffi.rb +12 -0
- data/lib/ngt/index.rb +37 -17
- data/lib/ngt/optimizer.rb +3 -10
- data/lib/ngt/utils.rb +4 -1
- data/lib/ngt/version.rb +1 -1
- data/lib/ngt.rb +4 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a8a99eccfae3fd0f09f5566ec99d240049e34a4a5ddff73ef26333bad6070932
|
4
|
+
data.tar.gz: ea4dae9eee921e69078ca04eb76c67ceb8c3f00ba368b6c76809a8f98b39478e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 67f096ab1115949bba0606db499790ee6168fada1f06f7b9b46a1631c3f7f2311f9babbdd374afc0dea5dbba5d9a44721f7d8d8a61882c73bc44c043c3f5c258
|
7
|
+
data.tar.gz: 4b44ba3724255e3deb15a52be30a7856ef76f2c47ad5be75a2f9535561058f3dc3dc12a682063054d812f581a266ae423f819ded4fd7c6d1e827c27ca4006595
|
data/CHANGELOG.md
CHANGED
data/lib/ngt/ffi.rb
CHANGED
@@ -36,8 +36,10 @@ module Ngt
|
|
36
36
|
attach_function :ngt_set_property_edge_size_for_creation, %i[pointer int16_t pointer], :bool
|
37
37
|
attach_function :ngt_set_property_edge_size_for_search, %i[pointer int16_t pointer], :bool
|
38
38
|
attach_function :ngt_is_property_object_type_float, %i[int32_t], :bool
|
39
|
+
attach_function :ngt_is_property_object_type_float16, %i[int32_t], :bool
|
39
40
|
attach_function :ngt_get_property_object_type, %i[pointer pointer], :int32_t
|
40
41
|
attach_function :ngt_set_property_object_type_float, %i[pointer pointer], :bool
|
42
|
+
attach_function :ngt_set_property_object_type_float16, %i[pointer pointer], :bool
|
41
43
|
attach_function :ngt_set_property_object_type_integer, %i[pointer pointer], :bool
|
42
44
|
attach_function :ngt_set_property_distance_type_l1, %i[pointer pointer], :bool
|
43
45
|
attach_function :ngt_set_property_distance_type_l2, %i[pointer pointer], :bool
|
@@ -67,11 +69,21 @@ module Ngt
|
|
67
69
|
attach_function :ngt_get_property_distance_type, %i[pointer pointer], :distance_type
|
68
70
|
attach_function :ngt_create_error_object, %i[], :pointer
|
69
71
|
attach_function :ngt_get_error_string, %i[pointer], :string
|
72
|
+
attach_function :ngt_clear_error_string, %i[pointer], :void
|
70
73
|
attach_function :ngt_destroy_error_object, %i[pointer], :void
|
71
74
|
attach_function :ngt_create_optimizer, %i[bool pointer], :pointer
|
72
75
|
attach_function :ngt_optimizer_adjust_search_coefficients, %i[pointer string pointer], :bool
|
73
76
|
attach_function :ngt_optimizer_execute, %i[pointer string string pointer], :bool
|
74
77
|
attach_function :ngt_optimizer_set, %i[pointer int int int float float float float double double pointer], :bool
|
75
78
|
attach_function :ngt_destroy_optimizer, %i[pointer], :void
|
79
|
+
|
80
|
+
def self.add_finalizer(pointer, method)
|
81
|
+
ObjectSpace.define_finalizer(pointer, finalize(pointer.to_i, method))
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.finalize(addr, method)
|
85
|
+
# must use proc instead of stabby lambda
|
86
|
+
proc { FFI.send(method, ::FFI::Pointer.new(:pointer, addr)) }
|
87
|
+
end
|
76
88
|
end
|
77
89
|
end
|
data/lib/ngt/index.rb
CHANGED
@@ -9,10 +9,11 @@ module Ngt
|
|
9
9
|
@path = path
|
10
10
|
|
11
11
|
@error = FFI.ngt_create_error_object
|
12
|
+
FFI.add_finalizer(@error, :ngt_destroy_error_object)
|
13
|
+
|
12
14
|
@property = ffi(:ngt_create_property)
|
15
|
+
FFI.add_finalizer(@property, :ngt_destroy_property)
|
13
16
|
ffi(:ngt_get_property, @index, @property)
|
14
|
-
|
15
|
-
ObjectSpace.define_finalizer(self, self.class.finalize(@error, @index, @property))
|
16
17
|
end
|
17
18
|
|
18
19
|
def dimensions
|
@@ -34,22 +35,34 @@ module Ngt
|
|
34
35
|
def object_type
|
35
36
|
@object_type ||= begin
|
36
37
|
object_type = ffi(:ngt_get_property_object_type, @property)
|
37
|
-
FFI.ngt_is_property_object_type_float(object_type)
|
38
|
+
if FFI.ngt_is_property_object_type_float(object_type)
|
39
|
+
:float
|
40
|
+
elsif FFI.ngt_is_property_object_type_float16(object_type)
|
41
|
+
:float16
|
42
|
+
else
|
43
|
+
:integer
|
44
|
+
end
|
38
45
|
end
|
39
46
|
end
|
40
47
|
|
41
48
|
def insert(object)
|
42
|
-
|
49
|
+
object = object.to_a
|
50
|
+
ffi(:ngt_insert_index, @index, c_object(object), object.size)
|
43
51
|
end
|
44
52
|
|
45
53
|
def batch_insert(objects, num_threads: 8)
|
46
54
|
if narray?(objects)
|
55
|
+
check_dimensions(objects.shape[1])
|
56
|
+
|
47
57
|
objects = objects.cast_to(Numo::SFloat) unless objects.is_a?(Numo::SFloat)
|
48
58
|
count = objects.shape[0]
|
49
59
|
obj = ::FFI::MemoryPointer.new(:char, objects.byte_size)
|
50
60
|
obj.write_bytes(objects.to_binary)
|
51
61
|
else
|
52
62
|
objects = objects.to_a
|
63
|
+
objects.each do |object|
|
64
|
+
check_dimensions(object.size)
|
65
|
+
end
|
53
66
|
count = objects.size
|
54
67
|
flat_objects = objects.flatten
|
55
68
|
obj = ::FFI::MemoryPointer.new(:float, flat_objects.size)
|
@@ -70,11 +83,13 @@ module Ngt
|
|
70
83
|
|
71
84
|
def object(id)
|
72
85
|
if object_type == :float
|
73
|
-
res = ffi(:ngt_get_object_as_float,
|
86
|
+
res = ffi(:ngt_get_object_as_float, object_space, id)
|
74
87
|
res.read_array_of_float(dimensions)
|
75
|
-
|
76
|
-
res = ffi(:ngt_get_object_as_integer,
|
88
|
+
elsif object_type == :integer
|
89
|
+
res = ffi(:ngt_get_object_as_integer, object_space, id)
|
77
90
|
res.read_array_of_uint8(dimensions)
|
91
|
+
else
|
92
|
+
raise Error, "Method not supported for this object type"
|
78
93
|
end
|
79
94
|
end
|
80
95
|
|
@@ -85,7 +100,8 @@ module Ngt
|
|
85
100
|
def search(query, size: 20, epsilon: 0.1, radius: nil)
|
86
101
|
radius ||= -1.0
|
87
102
|
results = ffi(:ngt_create_empty_results)
|
88
|
-
|
103
|
+
query = query.to_a
|
104
|
+
ffi(:ngt_search_index, @index, c_object(query), query.size, size, epsilon, radius, results)
|
89
105
|
result_size = ffi(:ngt_get_result_size, results)
|
90
106
|
ret = []
|
91
107
|
result_size.times do |i|
|
@@ -125,6 +141,8 @@ module Ngt
|
|
125
141
|
case object_type.to_s.downcase
|
126
142
|
when "float"
|
127
143
|
ffi(:ngt_set_property_object_type_float, property, error)
|
144
|
+
when "float16"
|
145
|
+
ffi(:ngt_set_property_object_type_float16, property, error)
|
128
146
|
when "integer"
|
129
147
|
ffi(:ngt_set_property_object_type_integer, property, error)
|
130
148
|
else
|
@@ -160,6 +178,8 @@ module Ngt
|
|
160
178
|
end
|
161
179
|
end
|
162
180
|
|
181
|
+
FFI.add_finalizer(index, :ngt_close_index)
|
182
|
+
|
163
183
|
super(index, path)
|
164
184
|
ensure
|
165
185
|
FFI.ngt_destroy_error_object(error) if error
|
@@ -180,15 +200,6 @@ module Ngt
|
|
180
200
|
Utils.ffi(*args)
|
181
201
|
end
|
182
202
|
|
183
|
-
def self.finalize(error, index, property)
|
184
|
-
# must use proc instead of stabby lambda
|
185
|
-
proc do
|
186
|
-
FFI.ngt_destroy_error_object(error)
|
187
|
-
FFI.ngt_close_index(index)
|
188
|
-
FFI.ngt_destroy_property(property)
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
203
|
private
|
193
204
|
|
194
205
|
def narray?(data)
|
@@ -196,9 +207,18 @@ module Ngt
|
|
196
207
|
end
|
197
208
|
|
198
209
|
def c_object(object)
|
210
|
+
check_dimensions(object.size)
|
199
211
|
c_object = ::FFI::MemoryPointer.new(:double, object.size)
|
200
212
|
c_object.write_array_of_double(object)
|
201
213
|
c_object
|
202
214
|
end
|
215
|
+
|
216
|
+
def check_dimensions(d)
|
217
|
+
raise ArgumentError, "Bad dimensions" if d != dimensions
|
218
|
+
end
|
219
|
+
|
220
|
+
def object_space
|
221
|
+
@object_space ||= ffi(:ngt_get_object_space, @index)
|
222
|
+
end
|
203
223
|
end
|
204
224
|
end
|
data/lib/ngt/optimizer.rb
CHANGED
@@ -4,12 +4,13 @@ module Ngt
|
|
4
4
|
|
5
5
|
def initialize(outgoing: 10, incoming: 120, queries: 100, low_accuracy_from: 0.3, low_accuracy_to: 0.5, high_accuracy_from: 0.8, high_accuracy_to: 0.9, gt_epsilon: 0.1, merge: 0.2)
|
6
6
|
@error = FFI.ngt_create_error_object
|
7
|
+
FFI.add_finalizer(@error, :ngt_destroy_error_object)
|
8
|
+
|
7
9
|
@optimizer = ffi(:ngt_create_optimizer, true)
|
10
|
+
FFI.add_finalizer(@optimizer, :ngt_destroy_optimizer)
|
8
11
|
|
9
12
|
ffi(:ngt_optimizer_set, @optimizer, outgoing, incoming, queries, low_accuracy_from,
|
10
13
|
low_accuracy_to, high_accuracy_from, high_accuracy_to, gt_epsilon, merge)
|
11
|
-
|
12
|
-
ObjectSpace.define_finalizer(self, self.class.finalize(@optimizer, @error))
|
13
14
|
end
|
14
15
|
|
15
16
|
def execute(in_index_path, out_index_path)
|
@@ -20,14 +21,6 @@ module Ngt
|
|
20
21
|
ffi(:ngt_optimizer_adjust_search_coefficients, @optimizer, path(index_path))
|
21
22
|
end
|
22
23
|
|
23
|
-
def self.finalize(optimizer, error)
|
24
|
-
# must use proc instead of stabby lambda
|
25
|
-
proc do
|
26
|
-
FFI.ngt_destroy_optimizer(optimizer)
|
27
|
-
FFI.ngt_destroy_error_object(error)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
24
|
private
|
32
25
|
|
33
26
|
def path(obj)
|
data/lib/ngt/utils.rb
CHANGED
@@ -4,7 +4,10 @@ module Ngt
|
|
4
4
|
def self.ffi(method, *args)
|
5
5
|
res = FFI.send(method, *args)
|
6
6
|
message = FFI.ngt_get_error_string(args.last)
|
7
|
-
|
7
|
+
unless message.empty?
|
8
|
+
FFI.ngt_clear_error_string(args.last)
|
9
|
+
raise Error, message
|
10
|
+
end
|
8
11
|
res
|
9
12
|
end
|
10
13
|
|
data/lib/ngt/version.rb
CHANGED
data/lib/ngt.rb
CHANGED
@@ -5,10 +5,10 @@ require "ffi"
|
|
5
5
|
require "tmpdir"
|
6
6
|
|
7
7
|
# modules
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
8
|
+
require_relative "ngt/utils"
|
9
|
+
require_relative "ngt/index"
|
10
|
+
require_relative "ngt/optimizer"
|
11
|
+
require_relative "ngt/version"
|
12
12
|
|
13
13
|
module Ngt
|
14
14
|
class Error < StandardError; end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ngt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kane
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-07-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ffi
|
@@ -71,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
71
|
- !ruby/object:Gem::Version
|
72
72
|
version: '0'
|
73
73
|
requirements: []
|
74
|
-
rubygems_version: 3.
|
74
|
+
rubygems_version: 3.4.10
|
75
75
|
signing_key:
|
76
76
|
specification_version: 4
|
77
77
|
summary: High-speed approximate nearest neighbors for Ruby
|