@@ -208,7 +208,7 @@ func DefaultConfig(dimensions uint) IndexConfig {
208208 return c
209209}
210210
211- // FilteredSearchHandler include the callback functiona and user data
211+ // FilteredSearchHandler includes the callback function and user data.
212212type FilteredSearchHandler struct {
213213 Callback func (key Key , handler * FilteredSearchHandler ) int
214214 Data any
@@ -246,15 +246,15 @@ func NewIndex(conf IndexConfig) (index *Index, err error) {
246246 conf = index .config
247247 dimensions := C .size_t (conf .Dimensions )
248248 connectivity := C .size_t (conf .Connectivity )
249- expansion_add := C .size_t (conf .ExpansionAdd )
250- expansion_search := C .size_t (conf .ExpansionSearch )
249+ expansionAdd := C .size_t (conf .ExpansionAdd )
250+ expansionSearch := C .size_t (conf .ExpansionSearch )
251251 multi := C .bool (conf .Multi )
252252
253253 options := C.struct_usearch_init_options_t {}
254254 options .dimensions = dimensions
255255 options .connectivity = connectivity
256- options .expansion_add = expansion_add
257- options .expansion_search = expansion_search
256+ options .expansion_add = expansionAdd
257+ options .expansion_search = expansionSearch
258258 options .multi = multi
259259 options .metric_kind = conf .Metric .CValue ()
260260
@@ -271,6 +271,11 @@ func NewIndex(conf IndexConfig) (index *Index, err error) {
271271 return index , nil
272272}
273273
274+ // Version returns the USearch library version string.
275+ func Version () string {
276+ return C .GoString (C .usearch_version ())
277+ }
278+
274279// Len returns the number of vectors in the index.
275280func (index * Index ) Len () (len uint , err error ) {
276281 var errorMessage * C.char
@@ -393,13 +398,13 @@ func (index *Index) Capacity() (cap uint, err error) {
393398 return cap , err
394399}
395400
396- // HardwareAcceleration returns a string showing the SIMD capability for the index
401+ // HardwareAcceleration returns a string showing the SIMD capability for the index.
397402func (index * Index ) HardwareAcceleration () (string , error ) {
398403 var str * C.char
399404 var errorMessage * C.char
400405 str = C .usearch_hardware_acceleration (index .handle , (* C .usearch_error_t )(& errorMessage ))
401406 if errorMessage != nil {
402- return C . GoString ( nil ) , errors .New (C .GoString (errorMessage ))
407+ return "" , errors .New (C .GoString (errorMessage ))
403408 }
404409 return C .GoString (str ), nil
405410}
@@ -512,6 +517,20 @@ func (index *Index) Remove(key Key) error {
512517 return nil
513518}
514519
520+ // Clear removes all vectors from the index while preserving its structure.
521+ func (index * Index ) Clear () error {
522+ if index .handle == nil {
523+ panic ("index is uninitialized" )
524+ }
525+
526+ var errorMessage * C.char
527+ C .usearch_clear (index .handle , (* C .usearch_error_t )(& errorMessage ))
528+ if errorMessage != nil {
529+ return errors .New (C .GoString (errorMessage ))
530+ }
531+ return nil
532+ }
533+
515534// Contains checks if the index contains a vector with a specific key.
516535func (index * Index ) Contains (key Key ) (found bool , err error ) {
517536 if index .handle == nil {
@@ -526,6 +545,21 @@ func (index *Index) Contains(key Key) (found bool, err error) {
526545 return found , nil
527546}
528547
548+ // Count returns the number of vectors stored under the given key.
549+ // Useful for multi-vector indexes where multiple vectors can share a key.
550+ func (index * Index ) Count (key Key ) (count uint , err error ) {
551+ if index .handle == nil {
552+ panic ("index is uninitialized" )
553+ }
554+
555+ var errorMessage * C.char
556+ count = uint (C .usearch_count (index .handle , (C .usearch_key_t )(key ), (* C .usearch_error_t )(& errorMessage )))
557+ if errorMessage != nil {
558+ return 0 , errors .New (C .GoString (errorMessage ))
559+ }
560+ return count , nil
561+ }
562+
529563// Get retrieves the vectors associated with the given key from the index.
530564// Returns nil if the key is not found.
531565func (index * Index ) Get (key Key , maxCount uint ) (vectors []float32 , err error ) {
@@ -550,7 +584,7 @@ func (index *Index) Get(key Key, maxCount uint) (vectors []float32, err error) {
550584 return vectors , nil
551585}
552586
553- // Rename the vector at key from to key to
587+ // Rename changes the key of a vector from one value to another.
554588func (index * Index ) Rename (from Key , to Key ) error {
555589 var errorMessage * C.char
556590 C .usearch_rename (index .handle , C .usearch_key_t (from ), C .usearch_key_t (to ), (* C .usearch_error_t )(& errorMessage ))
@@ -649,19 +683,19 @@ func (index *Index) Search(query []float32, limit uint) (keys []Key, distances [
649683 return keys , distances , nil
650684}
651685
652- // Search finds the k nearest neighbors to the query vector.
686+ // FilteredSearch finds the k nearest neighbors to the query vector, applying a filter .
653687//
654688// Parameters:
655689// - query: Must have exactly Dimensions() elements
656690// - limit: Maximum number of results to return
691+ // - handler: Filter callback that returns non-zero to accept a candidate, zero to reject
657692//
658693// Returns:
659- // - keys: IDs of the nearest vectors (up to limit)
694+ // - keys: IDs of the nearest vectors that passed the filter (up to limit)
660695// - distances: Distance to each result (same length as keys)
661- // - err: Error if query is invalid or search fails
696+ // - err: Error if query is invalid, handler is nil, or search fails
662697//
663- // The actual number of results may be less than limit if the index
664- // contains fewer vectors.
698+ // The actual number of results may be less than limit if fewer vectors pass the filter.
665699func (index * Index ) FilteredSearch (query []float32 , limit uint , handler * FilteredSearchHandler ) (keys []Key , distances []float32 , err error ) {
666700 if index .handle == nil {
667701 panic ("index is uninitialized" )
@@ -743,7 +777,13 @@ func goFilteredSearchCallback(key C.usearch_key_t, ptr unsafe.Pointer) C.int {
743777 return C .int (handler .Callback (Key (key ), handler ))
744778}
745779
746- // Filtred Search performs k-Approximate Nearest Neighbors Search for the closest vectors to the query vector with filtering.
780+ // FilteredSearchUnsafe performs filtered k-ANN search using an unsafe pointer.
781+ //
782+ // SAFETY REQUIREMENTS:
783+ // - query must not be nil
784+ // - Memory at query must contain exactly Dimensions() scalars
785+ // - Scalar type must match index.config.Quantization
786+ // - Memory must remain valid for the duration of the call
747787func (index * Index ) FilteredSearchUnsafe (query unsafe.Pointer , limit uint , handler * FilteredSearchHandler ) (keys []Key , distances []float32 , err error ) {
748788 if index .handle == nil {
749789 panic ("index is uninitialized" )
@@ -1028,20 +1068,20 @@ func ExactSearchI8(dataset []int8, queries []int8, datasetSize uint, queryCount
10281068// SaveBuffer serializes the index into a byte buffer.
10291069// The buffer must be large enough to hold the serialized index.
10301070// Use SerializedLength() to determine the required buffer size.
1031- func (index * Index ) SaveBuffer (buf []byte , buffer_size uint ) error {
1071+ func (index * Index ) SaveBuffer (buf []byte , bufferSize uint ) error {
10321072 if index .handle == nil {
10331073 panic ("index is uninitialized" )
10341074 }
10351075
10361076 if len (buf ) == 0 {
10371077 return errors .New ("buffer cannot be empty" )
10381078 }
1039- if uint (len (buf )) < buffer_size {
1040- return fmt .Errorf ("buffer too small: has %d bytes, need %d" , len (buf ), buffer_size )
1079+ if uint (len (buf )) < bufferSize {
1080+ return fmt .Errorf ("buffer too small: has %d bytes, need %d" , len (buf ), bufferSize )
10411081 }
10421082
10431083 var errorMessage * C.char
1044- C .usearch_save_buffer (index .handle , unsafe .Pointer (& buf [0 ]), C .size_t (buffer_size ), (* C .usearch_error_t )(& errorMessage ))
1084+ C .usearch_save_buffer (index .handle , unsafe .Pointer (& buf [0 ]), C .size_t (bufferSize ), (* C .usearch_error_t )(& errorMessage ))
10451085 runtime .KeepAlive (buf )
10461086 if errorMessage != nil {
10471087 return errors .New (C .GoString (errorMessage ))
@@ -1051,20 +1091,20 @@ func (index *Index) SaveBuffer(buf []byte, buffer_size uint) error {
10511091
10521092// LoadBuffer loads a serialized index from a byte buffer.
10531093// The buffer must contain a valid serialized index.
1054- func (index * Index ) LoadBuffer (buf []byte , buffer_size uint ) error {
1094+ func (index * Index ) LoadBuffer (buf []byte , bufferSize uint ) error {
10551095 if index .handle == nil {
10561096 panic ("index is uninitialized" )
10571097 }
10581098
10591099 if len (buf ) == 0 {
10601100 return errors .New ("buffer cannot be empty" )
10611101 }
1062- if uint (len (buf )) < buffer_size {
1063- return fmt .Errorf ("buffer too small: has %d bytes, need %d" , len (buf ), buffer_size )
1102+ if uint (len (buf )) < bufferSize {
1103+ return fmt .Errorf ("buffer too small: has %d bytes, need %d" , len (buf ), bufferSize )
10641104 }
10651105
10661106 var errorMessage * C.char
1067- C .usearch_load_buffer (index .handle , unsafe .Pointer (& buf [0 ]), C .size_t (buffer_size ), (* C .usearch_error_t )(& errorMessage ))
1107+ C .usearch_load_buffer (index .handle , unsafe .Pointer (& buf [0 ]), C .size_t (bufferSize ), (* C .usearch_error_t )(& errorMessage ))
10681108 runtime .KeepAlive (buf )
10691109 if errorMessage != nil {
10701110 return errors .New (C .GoString (errorMessage ))
@@ -1075,20 +1115,20 @@ func (index *Index) LoadBuffer(buf []byte, buffer_size uint) error {
10751115// ViewBuffer creates a view of a serialized index without copying the data.
10761116// The buffer must remain valid for the lifetime of the index.
10771117// Changes to the buffer will affect the index.
1078- func (index * Index ) ViewBuffer (buf []byte , buffer_size uint ) error {
1118+ func (index * Index ) ViewBuffer (buf []byte , bufferSize uint ) error {
10791119 if index .handle == nil {
10801120 panic ("index is uninitialized" )
10811121 }
10821122
10831123 if len (buf ) == 0 {
10841124 return errors .New ("buffer cannot be empty" )
10851125 }
1086- if uint (len (buf )) < buffer_size {
1087- return fmt .Errorf ("buffer too small: has %d bytes, need %d" , len (buf ), buffer_size )
1126+ if uint (len (buf )) < bufferSize {
1127+ return fmt .Errorf ("buffer too small: has %d bytes, need %d" , len (buf ), bufferSize )
10881128 }
10891129
10901130 var errorMessage * C.char
1091- C .usearch_view_buffer (index .handle , unsafe .Pointer (& buf [0 ]), C .size_t (buffer_size ), (* C .usearch_error_t )(& errorMessage ))
1131+ C .usearch_view_buffer (index .handle , unsafe .Pointer (& buf [0 ]), C .size_t (bufferSize ), (* C .usearch_error_t )(& errorMessage ))
10921132 runtime .KeepAlive (buf )
10931133 if errorMessage != nil {
10941134 return errors .New (C .GoString (errorMessage ))
@@ -1098,19 +1138,19 @@ func (index *Index) ViewBuffer(buf []byte, buffer_size uint) error {
10981138
10991139// MetadataBuffer extracts index configuration metadata from a serialized buffer.
11001140// This can be used to inspect an index before loading it.
1101- func MetadataBuffer (buf []byte , buffer_size uint ) (c IndexConfig , err error ) {
1141+ func MetadataBuffer (buf []byte , bufferSize uint ) (c IndexConfig , err error ) {
11021142 if len (buf ) == 0 {
11031143 return c , errors .New ("buffer cannot be empty" )
11041144 }
1105- if uint (len (buf )) < buffer_size {
1106- return c , fmt .Errorf ("buffer too small: has %d bytes, need %d" , len (buf ), buffer_size )
1145+ if uint (len (buf )) < bufferSize {
1146+ return c , fmt .Errorf ("buffer too small: has %d bytes, need %d" , len (buf ), bufferSize )
11071147 }
11081148 c = IndexConfig {}
11091149
11101150 options := C.struct_usearch_init_options_t {}
11111151
11121152 var errorMessage * C.char
1113- C .usearch_metadata_buffer (unsafe .Pointer (& buf [0 ]), C .size_t (buffer_size ), & options , (* C .usearch_error_t )(& errorMessage ))
1153+ C .usearch_metadata_buffer (unsafe .Pointer (& buf [0 ]), C .size_t (bufferSize ), & options , (* C .usearch_error_t )(& errorMessage ))
11141154 runtime .KeepAlive (buf )
11151155 if errorMessage != nil {
11161156 return c , errors .New (C .GoString (errorMessage ))
@@ -1154,6 +1194,8 @@ func MetadataBuffer(buf []byte, buffer_size uint) (c IndexConfig, err error) {
11541194 c .Quantization = I8
11551195 case C .usearch_scalar_b1_k :
11561196 c .Quantization = B1
1197+ case C .usearch_scalar_bf16_k :
1198+ c .Quantization = BF16
11571199 }
11581200
11591201 return c , nil
@@ -1166,13 +1208,13 @@ func Metadata(path string) (c IndexConfig, err error) {
11661208 return c , errors .New ("path cannot be empty" )
11671209 }
11681210
1169- c_path := C .CString (path )
1170- defer C .free (unsafe .Pointer (c_path ))
1211+ cPath := C .CString (path )
1212+ defer C .free (unsafe .Pointer (cPath ))
11711213
11721214 options := C.struct_usearch_init_options_t {}
11731215
11741216 var errorMessage * C.char
1175- C .usearch_metadata (c_path , & options , (* C .usearch_error_t )(& errorMessage ))
1217+ C .usearch_metadata (cPath , & options , (* C .usearch_error_t )(& errorMessage ))
11761218 if errorMessage != nil {
11771219 return c , errors .New (C .GoString (errorMessage ))
11781220 }
@@ -1228,11 +1270,11 @@ func (index *Index) Save(path string) error {
12281270 panic ("index is uninitialized" )
12291271 }
12301272
1231- c_path := C .CString (path )
1232- defer C .free (unsafe .Pointer (c_path ))
1273+ cPath := C .CString (path )
1274+ defer C .free (unsafe .Pointer (cPath ))
12331275
12341276 var errorMessage * C.char
1235- C .usearch_save (( C . usearch_index_t )( unsafe . Pointer ( index .handle )), c_path , (* C .usearch_error_t )(& errorMessage ))
1277+ C .usearch_save (index .handle , cPath , (* C .usearch_error_t )(& errorMessage ))
12361278 if errorMessage != nil {
12371279 return errors .New (C .GoString (errorMessage ))
12381280 }
@@ -1245,11 +1287,11 @@ func (index *Index) Load(path string) error {
12451287 panic ("index is uninitialized" )
12461288 }
12471289
1248- c_path := C .CString (path )
1249- defer C .free (unsafe .Pointer (c_path ))
1290+ cPath := C .CString (path )
1291+ defer C .free (unsafe .Pointer (cPath ))
12501292
12511293 var errorMessage * C.char
1252- C .usearch_load (( C . usearch_index_t )( unsafe . Pointer ( index .handle )), c_path , (* C .usearch_error_t )(& errorMessage ))
1294+ C .usearch_load (index .handle , cPath , (* C .usearch_error_t )(& errorMessage ))
12531295 if errorMessage != nil {
12541296 return errors .New (C .GoString (errorMessage ))
12551297 }
@@ -1262,11 +1304,11 @@ func (index *Index) View(path string) error {
12621304 panic ("index is uninitialized" )
12631305 }
12641306
1265- c_path := C .CString (path )
1266- defer C .free (unsafe .Pointer (c_path ))
1307+ cPath := C .CString (path )
1308+ defer C .free (unsafe .Pointer (cPath ))
12671309
12681310 var errorMessage * C.char
1269- C .usearch_view (( C . usearch_index_t )( unsafe . Pointer ( index .handle )), c_path , (* C .usearch_error_t )(& errorMessage ))
1311+ C .usearch_view (index .handle , cPath , (* C .usearch_error_t )(& errorMessage ))
12701312 if errorMessage != nil {
12711313 return errors .New (C .GoString (errorMessage ))
12721314 }
0 commit comments