eigen-db 4.1.0 → 4.3.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.
- package/CHANGELOG.md +8 -0
- package/README.md +79 -27
- package/dist/eigen-db.js +317 -195
- package/dist/eigen-db.js.map +1 -1
- package/dist/eigen-db.umd.cjs +1 -1
- package/dist/eigen-db.umd.cjs.map +1 -1
- package/package.json +1 -1
- package/src/lib/__tests__/result-set.test.ts +19 -19
- package/src/lib/__tests__/vector-db.test.ts +429 -16
- package/src/lib/memory-manager.ts +8 -0
- package/src/lib/result-set.ts +16 -15
- package/src/lib/simd-binary.ts +1 -1
- package/src/lib/simd-optimized.wat +362 -0
- package/src/lib/simd.wat +42 -248
- package/src/lib/types.ts +4 -6
- package/src/lib/vector-db.ts +241 -9
package/src/lib/simd.wat
CHANGED
|
@@ -4,70 +4,38 @@
|
|
|
4
4
|
|
|
5
5
|
;; normalize(ptr: i32, dimensions: i32)
|
|
6
6
|
;; Normalizes a vector in-place to unit length using SIMD.
|
|
7
|
-
;; Optimized with 4x loop unrolling (16 floats/iteration) and multiple accumulators.
|
|
8
7
|
(func (export "normalize") (param $ptr i32) (param $dim i32)
|
|
9
8
|
(local $i i32)
|
|
10
|
-
(local $
|
|
11
|
-
(local $acc1 v128)
|
|
12
|
-
(local $acc2 v128)
|
|
13
|
-
(local $acc3 v128)
|
|
9
|
+
(local $acc v128)
|
|
14
10
|
(local $sum f32)
|
|
15
11
|
(local $mag f32)
|
|
16
12
|
(local $inv_mag f32)
|
|
17
13
|
(local $inv_vec v128)
|
|
18
|
-
(local $unroll_end i32)
|
|
19
14
|
(local $simd_end i32)
|
|
20
15
|
(local $offset i32)
|
|
21
16
|
|
|
22
|
-
;; Phase 1: Sum of squares
|
|
23
|
-
(local.set $
|
|
24
|
-
(local.set $acc1 (v128.const f32x4 0 0 0 0))
|
|
25
|
-
(local.set $acc2 (v128.const f32x4 0 0 0 0))
|
|
26
|
-
(local.set $acc3 (v128.const f32x4 0 0 0 0))
|
|
27
|
-
(local.set $unroll_end (i32.and (local.get $dim) (i32.const -16)))
|
|
17
|
+
;; Phase 1: Sum of squares
|
|
18
|
+
(local.set $acc (v128.const f32x4 0 0 0 0))
|
|
28
19
|
(local.set $simd_end (i32.and (local.get $dim) (i32.const -4)))
|
|
29
20
|
(local.set $i (i32.const 0))
|
|
30
21
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
22
|
+
;; SIMD loop: 4 floats per iteration
|
|
23
|
+
(block $break_sum
|
|
24
|
+
(loop $loop_sum
|
|
25
|
+
(br_if $break_sum (i32.ge_u (local.get $i) (local.get $simd_end)))
|
|
34
26
|
(local.set $offset (i32.add (local.get $ptr) (i32.shl (local.get $i) (i32.const 2))))
|
|
35
|
-
|
|
36
|
-
(local.set $acc0 (f32x4.add (local.get $acc0)
|
|
37
|
-
(f32x4.mul (v128.load (local.get $offset)) (v128.load (local.get $offset)))))
|
|
38
|
-
(local.set $acc1 (f32x4.add (local.get $acc1)
|
|
39
|
-
(f32x4.mul (v128.load offset=16 (local.get $offset)) (v128.load offset=16 (local.get $offset)))))
|
|
40
|
-
(local.set $acc2 (f32x4.add (local.get $acc2)
|
|
41
|
-
(f32x4.mul (v128.load offset=32 (local.get $offset)) (v128.load offset=32 (local.get $offset)))))
|
|
42
|
-
(local.set $acc3 (f32x4.add (local.get $acc3)
|
|
43
|
-
(f32x4.mul (v128.load offset=48 (local.get $offset)) (v128.load offset=48 (local.get $offset)))))
|
|
44
|
-
|
|
45
|
-
(local.set $i (i32.add (local.get $i) (i32.const 16)))
|
|
46
|
-
(br $loop_sum_u)
|
|
47
|
-
)
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
;; Merge 4 accumulators
|
|
51
|
-
(local.set $acc0 (f32x4.add (f32x4.add (local.get $acc0) (local.get $acc1))
|
|
52
|
-
(f32x4.add (local.get $acc2) (local.get $acc3))))
|
|
53
|
-
|
|
54
|
-
;; Remaining 4-wide chunks
|
|
55
|
-
(block $break_sum4
|
|
56
|
-
(loop $loop_sum4
|
|
57
|
-
(br_if $break_sum4 (i32.ge_u (local.get $i) (local.get $simd_end)))
|
|
58
|
-
(local.set $offset (i32.add (local.get $ptr) (i32.shl (local.get $i) (i32.const 2))))
|
|
59
|
-
(local.set $acc0 (f32x4.add (local.get $acc0)
|
|
27
|
+
(local.set $acc (f32x4.add (local.get $acc)
|
|
60
28
|
(f32x4.mul (v128.load (local.get $offset)) (v128.load (local.get $offset)))))
|
|
61
29
|
(local.set $i (i32.add (local.get $i) (i32.const 4)))
|
|
62
|
-
(br $
|
|
30
|
+
(br $loop_sum)
|
|
63
31
|
)
|
|
64
32
|
)
|
|
65
33
|
|
|
66
34
|
;; Horizontal sum
|
|
67
35
|
(local.set $sum
|
|
68
36
|
(f32.add
|
|
69
|
-
(f32.add (f32x4.extract_lane 0 (local.get $
|
|
70
|
-
(f32.add (f32x4.extract_lane 2 (local.get $
|
|
37
|
+
(f32.add (f32x4.extract_lane 0 (local.get $acc)) (f32x4.extract_lane 1 (local.get $acc)))
|
|
38
|
+
(f32.add (f32x4.extract_lane 2 (local.get $acc)) (f32x4.extract_lane 3 (local.get $acc)))))
|
|
71
39
|
|
|
72
40
|
;; Scalar remainder
|
|
73
41
|
(block $break_rem_sum
|
|
@@ -86,39 +54,20 @@
|
|
|
86
54
|
(if (f32.eq (local.get $mag) (f32.const 0))
|
|
87
55
|
(then (return)))
|
|
88
56
|
|
|
89
|
-
;; Phase 2: Scale by inverse magnitude
|
|
57
|
+
;; Phase 2: Scale by inverse magnitude
|
|
90
58
|
(local.set $inv_mag (f32.div (f32.const 1) (local.get $mag)))
|
|
91
59
|
(local.set $inv_vec (f32x4.splat (local.get $inv_mag)))
|
|
92
60
|
(local.set $i (i32.const 0))
|
|
93
61
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
(
|
|
98
|
-
|
|
99
|
-
(v128.store (local.get $offset)
|
|
100
|
-
(f32x4.mul (v128.load (local.get $offset)) (local.get $inv_vec)))
|
|
101
|
-
(v128.store offset=16 (local.get $offset)
|
|
102
|
-
(f32x4.mul (v128.load offset=16 (local.get $offset)) (local.get $inv_vec)))
|
|
103
|
-
(v128.store offset=32 (local.get $offset)
|
|
104
|
-
(f32x4.mul (v128.load offset=32 (local.get $offset)) (local.get $inv_vec)))
|
|
105
|
-
(v128.store offset=48 (local.get $offset)
|
|
106
|
-
(f32x4.mul (v128.load offset=48 (local.get $offset)) (local.get $inv_vec)))
|
|
107
|
-
|
|
108
|
-
(local.set $i (i32.add (local.get $i) (i32.const 16)))
|
|
109
|
-
(br $loop_norm_u)
|
|
110
|
-
)
|
|
111
|
-
)
|
|
112
|
-
|
|
113
|
-
;; Remaining 4-wide chunks
|
|
114
|
-
(block $break_norm4
|
|
115
|
-
(loop $loop_norm4
|
|
116
|
-
(br_if $break_norm4 (i32.ge_u (local.get $i) (local.get $simd_end)))
|
|
62
|
+
;; SIMD loop
|
|
63
|
+
(block $break_norm
|
|
64
|
+
(loop $loop_norm
|
|
65
|
+
(br_if $break_norm (i32.ge_u (local.get $i) (local.get $simd_end)))
|
|
117
66
|
(local.set $offset (i32.add (local.get $ptr) (i32.shl (local.get $i) (i32.const 2))))
|
|
118
67
|
(v128.store (local.get $offset)
|
|
119
68
|
(f32x4.mul (v128.load (local.get $offset)) (local.get $inv_vec)))
|
|
120
69
|
(local.set $i (i32.add (local.get $i) (i32.const 4)))
|
|
121
|
-
(br $
|
|
70
|
+
(br $loop_norm)
|
|
122
71
|
)
|
|
123
72
|
)
|
|
124
73
|
|
|
@@ -137,226 +86,71 @@
|
|
|
137
86
|
|
|
138
87
|
;; search_all(query_ptr, db_ptr, scores_ptr, db_size, dimensions)
|
|
139
88
|
;; Computes dot products of query against every vector in the database.
|
|
140
|
-
;; Optimized with:
|
|
141
|
-
;; - 2-vector outer loop unrolling (halves query memory reads)
|
|
142
|
-
;; - 4x inner loop unrolling (16 floats/iteration, 4 accumulators per vector)
|
|
143
89
|
(func (export "search_all") (param $query_ptr i32) (param $db_ptr i32) (param $scores_ptr i32) (param $db_size i32) (param $dim i32)
|
|
144
90
|
(local $i i32)
|
|
145
91
|
(local $j i32)
|
|
146
|
-
(local $
|
|
147
|
-
(local $
|
|
148
|
-
(local $
|
|
149
|
-
(local $accA3 v128)
|
|
150
|
-
(local $accB0 v128)
|
|
151
|
-
(local $accB1 v128)
|
|
152
|
-
(local $accB2 v128)
|
|
153
|
-
(local $accB3 v128)
|
|
154
|
-
(local $q0 v128)
|
|
155
|
-
(local $q1 v128)
|
|
156
|
-
(local $q2 v128)
|
|
157
|
-
(local $q3 v128)
|
|
158
|
-
(local $dotA f32)
|
|
159
|
-
(local $dotB f32)
|
|
160
|
-
(local $vec_ptrA i32)
|
|
161
|
-
(local $vec_ptrB i32)
|
|
162
|
-
(local $unroll_end i32)
|
|
92
|
+
(local $acc v128)
|
|
93
|
+
(local $dot f32)
|
|
94
|
+
(local $vec_ptr i32)
|
|
163
95
|
(local $simd_end i32)
|
|
164
96
|
(local $q_offset i32)
|
|
165
|
-
(local $
|
|
166
|
-
(local $vB_offset i32)
|
|
97
|
+
(local $v_offset i32)
|
|
167
98
|
(local $bytes_per_vec i32)
|
|
168
|
-
(local $pair_end i32)
|
|
169
99
|
|
|
170
|
-
(local.set $unroll_end (i32.and (local.get $dim) (i32.const -16)))
|
|
171
100
|
(local.set $simd_end (i32.and (local.get $dim) (i32.const -4)))
|
|
172
101
|
(local.set $bytes_per_vec (i32.shl (local.get $dim) (i32.const 2)))
|
|
173
|
-
(local.set $pair_end (i32.and (local.get $db_size) (i32.const -2)))
|
|
174
102
|
(local.set $i (i32.const 0))
|
|
175
103
|
|
|
176
|
-
;;
|
|
104
|
+
;; Outer loop: one database vector per iteration
|
|
177
105
|
(block $break_outer
|
|
178
106
|
(loop $loop_outer
|
|
179
|
-
(br_if $break_outer (i32.ge_u (local.get $i) (local.get $
|
|
107
|
+
(br_if $break_outer (i32.ge_u (local.get $i) (local.get $db_size)))
|
|
180
108
|
|
|
181
|
-
(local.set $
|
|
109
|
+
(local.set $vec_ptr
|
|
182
110
|
(i32.add (local.get $db_ptr) (i32.mul (local.get $i) (local.get $bytes_per_vec))))
|
|
183
|
-
(local.set $
|
|
184
|
-
(i32.add (local.get $vec_ptrA) (local.get $bytes_per_vec)))
|
|
185
|
-
|
|
186
|
-
(local.set $accA0 (v128.const f32x4 0 0 0 0))
|
|
187
|
-
(local.set $accA1 (v128.const f32x4 0 0 0 0))
|
|
188
|
-
(local.set $accA2 (v128.const f32x4 0 0 0 0))
|
|
189
|
-
(local.set $accA3 (v128.const f32x4 0 0 0 0))
|
|
190
|
-
(local.set $accB0 (v128.const f32x4 0 0 0 0))
|
|
191
|
-
(local.set $accB1 (v128.const f32x4 0 0 0 0))
|
|
192
|
-
(local.set $accB2 (v128.const f32x4 0 0 0 0))
|
|
193
|
-
(local.set $accB3 (v128.const f32x4 0 0 0 0))
|
|
111
|
+
(local.set $acc (v128.const f32x4 0 0 0 0))
|
|
194
112
|
(local.set $j (i32.const 0))
|
|
195
113
|
|
|
196
|
-
;;
|
|
114
|
+
;; SIMD inner loop: dot product, 4 floats per iteration
|
|
197
115
|
(block $break_inner
|
|
198
116
|
(loop $loop_inner
|
|
199
|
-
(br_if $break_inner (i32.ge_u (local.get $j) (local.get $
|
|
200
|
-
(local.set $q_offset (i32.add (local.get $query_ptr) (i32.shl (local.get $j) (i32.const 2))))
|
|
201
|
-
(local.set $vA_offset (i32.add (local.get $vec_ptrA) (i32.shl (local.get $j) (i32.const 2))))
|
|
202
|
-
(local.set $vB_offset (i32.add (local.get $vec_ptrB) (i32.shl (local.get $j) (i32.const 2))))
|
|
203
|
-
|
|
204
|
-
;; Load query chunk (shared between both vectors)
|
|
205
|
-
(local.set $q0 (v128.load (local.get $q_offset)))
|
|
206
|
-
(local.set $q1 (v128.load offset=16 (local.get $q_offset)))
|
|
207
|
-
(local.set $q2 (v128.load offset=32 (local.get $q_offset)))
|
|
208
|
-
(local.set $q3 (v128.load offset=48 (local.get $q_offset)))
|
|
209
|
-
|
|
210
|
-
;; Vector A
|
|
211
|
-
(local.set $accA0 (f32x4.add (local.get $accA0)
|
|
212
|
-
(f32x4.mul (local.get $q0) (v128.load (local.get $vA_offset)))))
|
|
213
|
-
(local.set $accA1 (f32x4.add (local.get $accA1)
|
|
214
|
-
(f32x4.mul (local.get $q1) (v128.load offset=16 (local.get $vA_offset)))))
|
|
215
|
-
(local.set $accA2 (f32x4.add (local.get $accA2)
|
|
216
|
-
(f32x4.mul (local.get $q2) (v128.load offset=32 (local.get $vA_offset)))))
|
|
217
|
-
(local.set $accA3 (f32x4.add (local.get $accA3)
|
|
218
|
-
(f32x4.mul (local.get $q3) (v128.load offset=48 (local.get $vA_offset)))))
|
|
219
|
-
|
|
220
|
-
;; Vector B (reuses query loads)
|
|
221
|
-
(local.set $accB0 (f32x4.add (local.get $accB0)
|
|
222
|
-
(f32x4.mul (local.get $q0) (v128.load (local.get $vB_offset)))))
|
|
223
|
-
(local.set $accB1 (f32x4.add (local.get $accB1)
|
|
224
|
-
(f32x4.mul (local.get $q1) (v128.load offset=16 (local.get $vB_offset)))))
|
|
225
|
-
(local.set $accB2 (f32x4.add (local.get $accB2)
|
|
226
|
-
(f32x4.mul (local.get $q2) (v128.load offset=32 (local.get $vB_offset)))))
|
|
227
|
-
(local.set $accB3 (f32x4.add (local.get $accB3)
|
|
228
|
-
(f32x4.mul (local.get $q3) (v128.load offset=48 (local.get $vB_offset)))))
|
|
229
|
-
|
|
230
|
-
(local.set $j (i32.add (local.get $j) (i32.const 16)))
|
|
231
|
-
(br $loop_inner)
|
|
232
|
-
)
|
|
233
|
-
)
|
|
234
|
-
|
|
235
|
-
;; Merge accumulators
|
|
236
|
-
(local.set $accA0 (f32x4.add (f32x4.add (local.get $accA0) (local.get $accA1))
|
|
237
|
-
(f32x4.add (local.get $accA2) (local.get $accA3))))
|
|
238
|
-
(local.set $accB0 (f32x4.add (f32x4.add (local.get $accB0) (local.get $accB1))
|
|
239
|
-
(f32x4.add (local.get $accB2) (local.get $accB3))))
|
|
240
|
-
|
|
241
|
-
;; 4-wide cleanup (both vectors)
|
|
242
|
-
(block $break_inner4
|
|
243
|
-
(loop $loop_inner4
|
|
244
|
-
(br_if $break_inner4 (i32.ge_u (local.get $j) (local.get $simd_end)))
|
|
117
|
+
(br_if $break_inner (i32.ge_u (local.get $j) (local.get $simd_end)))
|
|
245
118
|
(local.set $q_offset (i32.add (local.get $query_ptr) (i32.shl (local.get $j) (i32.const 2))))
|
|
246
|
-
(local.set $
|
|
247
|
-
(local.set $
|
|
248
|
-
|
|
249
|
-
(local.set $accA0 (f32x4.add (local.get $accA0) (f32x4.mul (local.get $q0) (v128.load (local.get $vA_offset)))))
|
|
250
|
-
(local.set $accB0 (f32x4.add (local.get $accB0) (f32x4.mul (local.get $q0) (v128.load (local.get $vB_offset)))))
|
|
119
|
+
(local.set $v_offset (i32.add (local.get $vec_ptr) (i32.shl (local.get $j) (i32.const 2))))
|
|
120
|
+
(local.set $acc (f32x4.add (local.get $acc)
|
|
121
|
+
(f32x4.mul (v128.load (local.get $q_offset)) (v128.load (local.get $v_offset)))))
|
|
251
122
|
(local.set $j (i32.add (local.get $j) (i32.const 4)))
|
|
252
|
-
(br $
|
|
123
|
+
(br $loop_inner)
|
|
253
124
|
)
|
|
254
125
|
)
|
|
255
126
|
|
|
256
|
-
;; Horizontal
|
|
257
|
-
(local.set $
|
|
127
|
+
;; Horizontal sum
|
|
128
|
+
(local.set $dot
|
|
258
129
|
(f32.add
|
|
259
|
-
(f32.add (f32x4.extract_lane 0 (local.get $
|
|
260
|
-
(f32.add (f32x4.extract_lane 2 (local.get $
|
|
261
|
-
(local.set $dotB
|
|
262
|
-
(f32.add
|
|
263
|
-
(f32.add (f32x4.extract_lane 0 (local.get $accB0)) (f32x4.extract_lane 1 (local.get $accB0)))
|
|
264
|
-
(f32.add (f32x4.extract_lane 2 (local.get $accB0)) (f32x4.extract_lane 3 (local.get $accB0)))))
|
|
130
|
+
(f32.add (f32x4.extract_lane 0 (local.get $acc)) (f32x4.extract_lane 1 (local.get $acc)))
|
|
131
|
+
(f32.add (f32x4.extract_lane 2 (local.get $acc)) (f32x4.extract_lane 3 (local.get $acc)))))
|
|
265
132
|
|
|
266
|
-
;; Scalar remainder
|
|
133
|
+
;; Scalar remainder
|
|
267
134
|
(block $break_rem
|
|
268
135
|
(loop $loop_rem
|
|
269
136
|
(br_if $break_rem (i32.ge_u (local.get $j) (local.get $dim)))
|
|
270
137
|
(local.set $q_offset (i32.add (local.get $query_ptr) (i32.shl (local.get $j) (i32.const 2))))
|
|
271
|
-
(local.set $
|
|
272
|
-
(local.set $
|
|
273
|
-
|
|
274
|
-
(f32.mul (f32.load (local.get $q_offset)) (f32.load (local.get $vA_offset)))))
|
|
275
|
-
(local.set $dotB (f32.add (local.get $dotB)
|
|
276
|
-
(f32.mul (f32.load (local.get $q_offset)) (f32.load (local.get $vB_offset)))))
|
|
138
|
+
(local.set $v_offset (i32.add (local.get $vec_ptr) (i32.shl (local.get $j) (i32.const 2))))
|
|
139
|
+
(local.set $dot (f32.add (local.get $dot)
|
|
140
|
+
(f32.mul (f32.load (local.get $q_offset)) (f32.load (local.get $v_offset)))))
|
|
277
141
|
(local.set $j (i32.add (local.get $j) (i32.const 1)))
|
|
278
142
|
(br $loop_rem)
|
|
279
143
|
)
|
|
280
144
|
)
|
|
281
145
|
|
|
282
|
-
;; Store
|
|
146
|
+
;; Store score
|
|
283
147
|
(f32.store
|
|
284
148
|
(i32.add (local.get $scores_ptr) (i32.shl (local.get $i) (i32.const 2)))
|
|
285
|
-
(local.get $
|
|
286
|
-
(f32.store
|
|
287
|
-
(i32.add (local.get $scores_ptr) (i32.shl (i32.add (local.get $i) (i32.const 1)) (i32.const 2)))
|
|
288
|
-
(local.get $dotB))
|
|
149
|
+
(local.get $dot))
|
|
289
150
|
|
|
290
|
-
(local.set $i (i32.add (local.get $i) (i32.const
|
|
151
|
+
(local.set $i (i32.add (local.get $i) (i32.const 1)))
|
|
291
152
|
(br $loop_outer)
|
|
292
153
|
)
|
|
293
154
|
)
|
|
294
|
-
|
|
295
|
-
;; Handle last vector if db_size is odd
|
|
296
|
-
(if (i32.lt_u (local.get $i) (local.get $db_size))
|
|
297
|
-
(then
|
|
298
|
-
(local.set $vec_ptrA
|
|
299
|
-
(i32.add (local.get $db_ptr) (i32.mul (local.get $i) (local.get $bytes_per_vec))))
|
|
300
|
-
(local.set $accA0 (v128.const f32x4 0 0 0 0))
|
|
301
|
-
(local.set $accA1 (v128.const f32x4 0 0 0 0))
|
|
302
|
-
(local.set $accA2 (v128.const f32x4 0 0 0 0))
|
|
303
|
-
(local.set $accA3 (v128.const f32x4 0 0 0 0))
|
|
304
|
-
(local.set $j (i32.const 0))
|
|
305
|
-
|
|
306
|
-
(block $break_last
|
|
307
|
-
(loop $loop_last
|
|
308
|
-
(br_if $break_last (i32.ge_u (local.get $j) (local.get $unroll_end)))
|
|
309
|
-
(local.set $q_offset (i32.add (local.get $query_ptr) (i32.shl (local.get $j) (i32.const 2))))
|
|
310
|
-
(local.set $vA_offset (i32.add (local.get $vec_ptrA) (i32.shl (local.get $j) (i32.const 2))))
|
|
311
|
-
(local.set $accA0 (f32x4.add (local.get $accA0)
|
|
312
|
-
(f32x4.mul (v128.load (local.get $q_offset)) (v128.load (local.get $vA_offset)))))
|
|
313
|
-
(local.set $accA1 (f32x4.add (local.get $accA1)
|
|
314
|
-
(f32x4.mul (v128.load offset=16 (local.get $q_offset)) (v128.load offset=16 (local.get $vA_offset)))))
|
|
315
|
-
(local.set $accA2 (f32x4.add (local.get $accA2)
|
|
316
|
-
(f32x4.mul (v128.load offset=32 (local.get $q_offset)) (v128.load offset=32 (local.get $vA_offset)))))
|
|
317
|
-
(local.set $accA3 (f32x4.add (local.get $accA3)
|
|
318
|
-
(f32x4.mul (v128.load offset=48 (local.get $q_offset)) (v128.load offset=48 (local.get $vA_offset)))))
|
|
319
|
-
(local.set $j (i32.add (local.get $j) (i32.const 16)))
|
|
320
|
-
(br $loop_last)
|
|
321
|
-
)
|
|
322
|
-
)
|
|
323
|
-
|
|
324
|
-
(local.set $accA0 (f32x4.add (f32x4.add (local.get $accA0) (local.get $accA1))
|
|
325
|
-
(f32x4.add (local.get $accA2) (local.get $accA3))))
|
|
326
|
-
|
|
327
|
-
(block $break_last4
|
|
328
|
-
(loop $loop_last4
|
|
329
|
-
(br_if $break_last4 (i32.ge_u (local.get $j) (local.get $simd_end)))
|
|
330
|
-
(local.set $q_offset (i32.add (local.get $query_ptr) (i32.shl (local.get $j) (i32.const 2))))
|
|
331
|
-
(local.set $vA_offset (i32.add (local.get $vec_ptrA) (i32.shl (local.get $j) (i32.const 2))))
|
|
332
|
-
(local.set $accA0 (f32x4.add (local.get $accA0)
|
|
333
|
-
(f32x4.mul (v128.load (local.get $q_offset)) (v128.load (local.get $vA_offset)))))
|
|
334
|
-
(local.set $j (i32.add (local.get $j) (i32.const 4)))
|
|
335
|
-
(br $loop_last4)
|
|
336
|
-
)
|
|
337
|
-
)
|
|
338
|
-
|
|
339
|
-
(local.set $dotA
|
|
340
|
-
(f32.add
|
|
341
|
-
(f32.add (f32x4.extract_lane 0 (local.get $accA0)) (f32x4.extract_lane 1 (local.get $accA0)))
|
|
342
|
-
(f32.add (f32x4.extract_lane 2 (local.get $accA0)) (f32x4.extract_lane 3 (local.get $accA0)))))
|
|
343
|
-
|
|
344
|
-
(block $break_last_rem
|
|
345
|
-
(loop $loop_last_rem
|
|
346
|
-
(br_if $break_last_rem (i32.ge_u (local.get $j) (local.get $dim)))
|
|
347
|
-
(local.set $q_offset (i32.add (local.get $query_ptr) (i32.shl (local.get $j) (i32.const 2))))
|
|
348
|
-
(local.set $vA_offset (i32.add (local.get $vec_ptrA) (i32.shl (local.get $j) (i32.const 2))))
|
|
349
|
-
(local.set $dotA (f32.add (local.get $dotA)
|
|
350
|
-
(f32.mul (f32.load (local.get $q_offset)) (f32.load (local.get $vA_offset)))))
|
|
351
|
-
(local.set $j (i32.add (local.get $j) (i32.const 1)))
|
|
352
|
-
(br $loop_last_rem)
|
|
353
|
-
)
|
|
354
|
-
)
|
|
355
|
-
|
|
356
|
-
(f32.store
|
|
357
|
-
(i32.add (local.get $scores_ptr) (i32.shl (local.get $i) (i32.const 2)))
|
|
358
|
-
(local.get $dotA))
|
|
359
|
-
)
|
|
360
|
-
)
|
|
361
155
|
)
|
|
362
156
|
)
|
package/src/lib/types.ts
CHANGED
|
@@ -2,20 +2,18 @@
|
|
|
2
2
|
* Options for opening a VectorDB instance.
|
|
3
3
|
*/
|
|
4
4
|
export interface OpenOptions {
|
|
5
|
-
/** Name of the OPFS directory. Defaults to "default". */
|
|
6
|
-
name?: string;
|
|
7
5
|
/** Vector dimensions (e.g., 1536 for OpenAI text-embedding-3-small) */
|
|
8
6
|
dimensions: number;
|
|
9
7
|
/** Whether to normalize vectors on set/query (default: true). */
|
|
10
8
|
normalize?: boolean;
|
|
9
|
+
/** Storage provider for persistence. Defaults to InMemoryStorageProvider. Use OPFSStorageProvider for browser persistence. */
|
|
10
|
+
storage?: import("./storage").StorageProvider;
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
* Extended options including internal overrides for testing/advanced use.
|
|
15
15
|
*/
|
|
16
16
|
export interface OpenOptionsInternal extends OpenOptions {
|
|
17
|
-
/** Override the storage provider (default: OPFS). Useful for testing. */
|
|
18
|
-
storage?: import("./storage").StorageProvider;
|
|
19
17
|
/** Pre-compiled WASM binary. If not provided, uses the embedded SIMD binary. Set to null to force JS-only mode. */
|
|
20
18
|
wasmBinary?: Uint8Array | null;
|
|
21
19
|
}
|
|
@@ -41,8 +39,8 @@ export interface SetOptions {
|
|
|
41
39
|
export interface QueryOptions {
|
|
42
40
|
/** Maximum number of results to return. Defaults to Infinity (all results). */
|
|
43
41
|
topK?: number;
|
|
44
|
-
/**
|
|
45
|
-
|
|
42
|
+
/** Minimum similarity threshold (inclusive). Results with similarity < minSimilarity are excluded. */
|
|
43
|
+
minSimilarity?: number;
|
|
46
44
|
/** Override normalization for this call. */
|
|
47
45
|
normalize?: boolean;
|
|
48
46
|
/** When true, returns an Iterable<ResultItem> instead of ResultItem[]. */
|