diff --git a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3.c b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3.c index daad6d309d..c0bc2492da 100644 --- a/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3.c +++ b/libsql-ffi/bundled/SQLite3MultipleCiphers/src/sqlite3.c @@ -85273,6 +85273,7 @@ typedef u32 VectorDims; #define VECTOR_TYPE_FLOAT1BIT 3 #define VECTOR_TYPE_FLOAT8 4 #define VECTOR_TYPE_FLOAT16 5 +#define VECTOR_TYPE_FLOATB16 6 #define VECTOR_FLAGS_STATIC 1 @@ -85301,6 +85302,7 @@ void vectorInit(Vector *, VectorType, VectorDims, void *); void vectorDump (const Vector *v); void vectorF8Dump (const Vector *v); void vectorF16Dump (const Vector *v); +void vectorFB16Dump(const Vector *v); void vectorF32Dump (const Vector *v); void vectorF64Dump (const Vector *v); void vector1BitDump(const Vector *v); @@ -85321,6 +85323,7 @@ void vectorF64MarshalToText(sqlite3_context *, const Vector *); void vectorSerializeToBlob (const Vector *, unsigned char *, size_t); void vectorF8SerializeToBlob (const Vector *, unsigned char *, size_t); void vectorF16SerializeToBlob (const Vector *, unsigned char *, size_t); +void vectorFB16SerializeToBlob(const Vector *, unsigned char *, size_t); void vectorF32SerializeToBlob (const Vector *, unsigned char *, size_t); void vectorF64SerializeToBlob (const Vector *, unsigned char *, size_t); void vector1BitSerializeToBlob(const Vector *, unsigned char *, size_t); @@ -85331,6 +85334,7 @@ void vector1BitSerializeToBlob(const Vector *, unsigned char *, size_t); float vectorDistanceCos (const Vector *, const Vector *); float vectorF8DistanceCos (const Vector *, const Vector *); float vectorF16DistanceCos (const Vector *, const Vector *); +float vectorFB16DistanceCos(const Vector *, const Vector *); float vectorF32DistanceCos (const Vector *, const Vector *); double vectorF64DistanceCos(const Vector *, const Vector *); @@ -85345,6 +85349,7 @@ int vector1BitDistanceHamming(const Vector *, const Vector *); float vectorDistanceL2 (const Vector *, const Vector *); float vectorF8DistanceL2 (const Vector *, const Vector *); float vectorF16DistanceL2 (const Vector *, const Vector *); +float vectorFB16DistanceL2(const Vector *, const Vector *); float vectorF32DistanceL2 (const Vector *, const Vector *); double vectorF64DistanceL2(const Vector *, const Vector *); @@ -85362,6 +85367,7 @@ int vectorParseSqliteBlobWithType(sqlite3_value *, Vector *, char **); void vectorF8DeserializeFromBlob (Vector *, const unsigned char *, size_t); void vectorF16DeserializeFromBlob (Vector *, const unsigned char *, size_t); +void vectorFB16DeserializeFromBlob(Vector *, const unsigned char *, size_t); void vectorF32DeserializeFromBlob (Vector *, const unsigned char *, size_t); void vectorF64DeserializeFromBlob (Vector *, const unsigned char *, size_t); void vector1BitDeserializeFromBlob(Vector *, const unsigned char *, size_t); @@ -85372,6 +85378,9 @@ void vectorInitFromBlob(Vector *, const unsigned char *, size_t); u16 vectorF16FromFloat(float); float vectorF16ToFloat(u16); +u16 vectorFB16FromFloat(float); +float vectorFB16ToFloat(u16); + void vectorConvert(const Vector *, Vector *); /* Detect type and dimension of vector provided with first parameter of sqlite3_value * type */ @@ -211050,6 +211059,8 @@ size_t vectorDataSize(VectorType type, VectorDims dims){ return ALIGN(dims, sizeof(float)) + sizeof(float) /* alpha */ + sizeof(float) /* shift */; case VECTOR_TYPE_FLOAT16: return dims * sizeof(u16); + case VECTOR_TYPE_FLOATB16: + return dims * sizeof(u16); default: assert(0); } @@ -211127,6 +211138,8 @@ float vectorDistanceCos(const Vector *pVector1, const Vector *pVector2){ return vectorF8DistanceCos(pVector1, pVector2); case VECTOR_TYPE_FLOAT16: return vectorF16DistanceCos(pVector1, pVector2); + case VECTOR_TYPE_FLOATB16: + return vectorFB16DistanceCos(pVector1, pVector2); default: assert(0); } @@ -211144,6 +211157,8 @@ float vectorDistanceL2(const Vector *pVector1, const Vector *pVector2){ return vectorF8DistanceL2(pVector1, pVector2); case VECTOR_TYPE_FLOAT16: return vectorF16DistanceL2(pVector1, pVector2); + case VECTOR_TYPE_FLOATB16: + return vectorFB16DistanceL2(pVector1, pVector2); default: assert(0); } @@ -211317,6 +211332,13 @@ static int vectorParseMeta(const unsigned char *pBlob, size_t nBlobSize, int *pT } *pDims = nBlobSize / sizeof(u16); *pDataSize = nBlobSize; + }else if( *pType == VECTOR_TYPE_FLOATB16 ){ + if( nBlobSize % 2 != 0 ){ + *pzErrMsg = sqlite3_mprintf("vector: floatb16 vector blob length must be divisible by 2 (excluding 'type'-byte): length=%d", nBlobSize); + return SQLITE_ERROR; + } + *pDims = nBlobSize / sizeof(u16); + *pDataSize = nBlobSize; }else{ *pzErrMsg = sqlite3_mprintf("vector: unexpected binary type: %d", *pType); return SQLITE_ERROR; @@ -211368,6 +211390,9 @@ int vectorParseSqliteBlobWithType( case VECTOR_TYPE_FLOAT16: vectorF16DeserializeFromBlob(pVector, pBlob, nDataSize); return 0; + case VECTOR_TYPE_FLOATB16: + vectorFB16DeserializeFromBlob(pVector, pBlob, nDataSize); + return 0; default: assert(0); } @@ -211472,6 +211497,9 @@ void vectorDump(const Vector *pVector){ case VECTOR_TYPE_FLOAT16: vectorF16Dump(pVector); break; + case VECTOR_TYPE_FLOATB16: + vectorFB16Dump(pVector); + break; default: assert(0); } @@ -211497,7 +211525,7 @@ static int vectorMetaSize(VectorType type, VectorDims dims){ int nDataSize; if( type == VECTOR_TYPE_FLOAT32 ){ return 0; - }else if( type == VECTOR_TYPE_FLOAT64 || type == VECTOR_TYPE_FLOAT16 ){ + }else if( type == VECTOR_TYPE_FLOAT64 || type == VECTOR_TYPE_FLOAT16 || type == VECTOR_TYPE_FLOATB16 ){ return 1; }else if( type == VECTOR_TYPE_FLOAT1BIT ){ nDataSize = vectorDataSize(type, dims); @@ -211516,7 +211544,7 @@ static int vectorMetaSize(VectorType type, VectorDims dims){ static void vectorSerializeMeta(const Vector *pVector, size_t nDataSize, unsigned char *pBlob, size_t nBlobSize){ if( pVector->type == VECTOR_TYPE_FLOAT32 ){ // no meta for f32 type as this is "default" vector type - }else if( pVector->type == VECTOR_TYPE_FLOAT64 || pVector->type == VECTOR_TYPE_FLOAT16 ){ + }else if( pVector->type == VECTOR_TYPE_FLOAT64 || pVector->type == VECTOR_TYPE_FLOAT16 || pVector->type == VECTOR_TYPE_FLOATB16 ){ assert( nDataSize % 2 == 0 ); assert( nBlobSize == nDataSize + 1 ); pBlob[nBlobSize - 1] = pVector->type; @@ -211585,6 +211613,9 @@ void vectorSerializeToBlob(const Vector *pVector, unsigned char *pBlob, size_t n case VECTOR_TYPE_FLOAT16: vectorF16SerializeToBlob(pVector, pBlob, nBlobSize); break; + case VECTOR_TYPE_FLOATB16: + vectorFB16SerializeToBlob(pVector, pBlob, nBlobSize); + break; default: assert(0); } @@ -211627,6 +211658,11 @@ static void vectorConvertFromF32(const Vector *pFrom, Vector *pTo){ for(i = 0; i < pFrom->dims; i++){ dstF16[i] = vectorF16FromFloat(src[i]); } + }else if( pTo->type == VECTOR_TYPE_FLOATB16 ){ + dstF16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstF16[i] = vectorFB16FromFloat(src[i]); + } }else{ assert( 0 ); } @@ -211665,6 +211701,11 @@ static void vectorConvertFromF64(const Vector *pFrom, Vector *pTo){ for(i = 0; i < pFrom->dims; i++){ dstF16[i] = vectorF16FromFloat(src[i]); } + }else if( pTo->type == VECTOR_TYPE_FLOATB16 ){ + dstF16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstF16[i] = vectorFB16FromFloat(src[i]); + } }else{ assert( 0 ); } @@ -211676,7 +211717,7 @@ static void vectorConvertFrom1Bit(const Vector *pFrom, Vector *pTo){ float *dstF32; double *dstF64; - u16 *dstF16; + u16 *dstU16; assert( pFrom->dims == pTo->dims ); assert( pFrom->type != pTo->type ); @@ -211704,12 +211745,23 @@ static void vectorConvertFrom1Bit(const Vector *pFrom, Vector *pTo){ }else if( pTo->type == VECTOR_TYPE_FLOAT16 ){ u16 positive = vectorF16FromFloat(+1); u16 negative = vectorF16FromFloat(-1); - dstF16 = pTo->data; + dstU16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + if( ((src[i / 8] >> (i & 7)) & 1) == 1 ){ + dstU16[i] = positive; + }else{ + dstU16[i] = negative; + } + } + }else if( pTo->type == VECTOR_TYPE_FLOATB16 ){ + u16 positive = vectorFB16FromFloat(+1); + u16 negative = vectorFB16FromFloat(-1); + dstU16 = pTo->data; for(i = 0; i < pFrom->dims; i++){ if( ((src[i / 8] >> (i & 7)) & 1) == 1 ){ - dstF16[i] = positive; + dstU16[i] = positive; }else{ - dstF16[i] = negative; + dstU16[i] = negative; } } }else{ @@ -211759,6 +211811,11 @@ static void vectorConvertFromF8(const Vector *pFrom, Vector *pTo){ for(i = 0; i < pFrom->dims; i++){ dstF16[i] = vectorF16FromFloat(alpha * src[i] + shift); } + }else if( pTo->type == VECTOR_TYPE_FLOATB16 ){ + dstF16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstF16[i] = vectorFB16FromFloat(alpha * src[i] + shift); + } }else{ assert( 0 ); } @@ -211771,6 +211828,7 @@ static void vectorConvertFromF16(const Vector *pFrom, Vector *pTo){ float *dstF32; double *dstF64; u8 *dst1Bit; + u16 *dstU16; assert( pFrom->dims == pTo->dims ); assert( pFrom->type != pTo->type ); @@ -211787,6 +211845,11 @@ static void vectorConvertFromF16(const Vector *pFrom, Vector *pTo){ for(i = 0; i < pFrom->dims; i++){ dstF64[i] = vectorF16ToFloat(src[i]); } + }else if( pTo->type == VECTOR_TYPE_FLOATB16 ){ + dstU16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstU16[i] = vectorFB16FromFloat(vectorF16ToFloat(src[i])); + } }else if( pTo->type == VECTOR_TYPE_FLOAT1BIT ){ dst1Bit = pTo->data; for(i = 0; i < pFrom->dims; i += 8){ @@ -211802,6 +211865,50 @@ static void vectorConvertFromF16(const Vector *pFrom, Vector *pTo){ } } +static void vectorConvertFromFB16(const Vector *pFrom, Vector *pTo){ + int i; + u16 *src; + + float *dstF32; + double *dstF64; + u8 *dst1Bit; + u16 *dstU16; + + assert( pFrom->dims == pTo->dims ); + assert( pFrom->type != pTo->type ); + assert( pFrom->type == VECTOR_TYPE_FLOATB16 ); + + src = pFrom->data; + if( pTo->type == VECTOR_TYPE_FLOAT32 ){ + dstF32 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstF32[i] = vectorFB16ToFloat(src[i]); + } + }else if( pTo->type == VECTOR_TYPE_FLOAT64 ){ + dstF64 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstF64[i] = vectorFB16ToFloat(src[i]); + } + }else if( pTo->type == VECTOR_TYPE_FLOAT16 ){ + dstU16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstU16[i] = vectorF16FromFloat(vectorFB16ToFloat(src[i])); + } + }else if( pTo->type == VECTOR_TYPE_FLOAT1BIT ){ + dst1Bit = pTo->data; + for(i = 0; i < pFrom->dims; i += 8){ + dst1Bit[i / 8] = 0; + } + for(i = 0; i < pFrom->dims; i++){ + if( vectorFB16ToFloat(src[i]) > 0 ){ + dst1Bit[i / 8] |= (1 << (i & 7)); + } + } + }else{ + assert( 0 ); + } +} + static inline int clip(float f, int minF, int maxF){ if( f < minF ){ return minF; @@ -211822,7 +211929,7 @@ static void vectorConvertToF8(const Vector *pFrom, Vector *pTo){ float *srcF32; double *srcF64; u8 *src1Bit; - u16 *srcF16; + u16 *srcU16; assert( pFrom->dims == pTo->dims ); assert( pFrom->type != pTo->type ); @@ -211860,14 +211967,24 @@ static void vectorConvertToF8(const Vector *pFrom, Vector *pTo){ dst[i] = clip(((((src1Bit[i / 8] >> (i & 7)) & 1) ? +1 : -1) - shift) / alpha, 0, 255); } }else if( pFrom->type == VECTOR_TYPE_FLOAT16 ){ - srcF16 = pFrom->data; + srcU16 = pFrom->data; for(i = 0; i < pFrom->dims; i++){ - MINMAX(i, vectorF16ToFloat(srcF16[i]), minF, maxF); + MINMAX(i, vectorF16ToFloat(srcU16[i]), minF, maxF); } shift = minF; alpha = (maxF - minF) / 255; for(i = 0; i < pFrom->dims; i++){ - dst[i] = clip((vectorF16ToFloat(srcF16[i]) - shift) / alpha, 0, 255); + dst[i] = clip((vectorF16ToFloat(srcU16[i]) - shift) / alpha, 0, 255); + } + }else if( pFrom->type == VECTOR_TYPE_FLOATB16 ){ + srcU16 = pFrom->data; + for(i = 0; i < pFrom->dims; i++){ + MINMAX(i, vectorFB16ToFloat(srcU16[i]), minF, maxF); + } + shift = minF; + alpha = (maxF - minF) / 255; + for(i = 0; i < pFrom->dims; i++){ + dst[i] = clip((vectorFB16ToFloat(srcU16[i]) - shift) / alpha, 0, 255); } }else{ assert( 0 ); @@ -211896,6 +212013,8 @@ void vectorConvert(const Vector *pFrom, Vector *pTo){ vectorConvertFromF8(pFrom, pTo); }else if( pFrom->type == VECTOR_TYPE_FLOAT16 ){ vectorConvertFromF16(pFrom, pTo); + }else if( pFrom->type == VECTOR_TYPE_FLOATB16 ){ + vectorConvertFromFB16(pFrom, pTo); }else{ assert( 0 ); } @@ -211988,6 +212107,14 @@ static void vector16Func( vectorFuncHintedType(context, argc, argv, VECTOR_TYPE_FLOAT16); } +static void vectorb16Func( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + vectorFuncHintedType(context, argc, argv, VECTOR_TYPE_FLOATB16); +} + static void vector1BitFunc( sqlite3_context *context, int argc, @@ -212147,6 +212274,7 @@ SQLITE_PRIVATE void sqlite3RegisterVectorFunctions(void){ FUNCTION(vector1bit, 1, 0, 0, vector1BitFunc), FUNCTION(vector8, 1, 0, 0, vector8Func), FUNCTION(vector16, 1, 0, 0, vector16Func), + FUNCTION(vectorb16, 1, 0, 0, vectorb16Func), FUNCTION(vector_extract, 1, 0, 0, vectorExtractFunc), FUNCTION(vector_distance_cos, 2, 0, 0, vectorDistanceCosFunc), FUNCTION(vector_distance_l2, 2, 0, 0, vectorDistanceL2Func), @@ -214751,8 +214879,6 @@ void vectorF16SerializeToBlob( unsigned char *pBlob, size_t nBlobSize ){ - float alpha, shift; - assert( pVector->type == VECTOR_TYPE_FLOAT16 ); assert( pVector->dims <= MAX_VECTOR_SZ ); assert( nBlobSize >= vectorDataSize(pVector->type, pVector->dims) ); @@ -214815,6 +214941,137 @@ void vectorF16DeserializeFromBlob( #endif /* !defined(SQLITE_OMIT_VECTOR) */ /************** End of vectorfloat16.c ***************************************/ +/************** Begin file vectorfloatb16.c **********************************/ +/* +** 2024-07-04 +** +** Copyright 2024 the libSQL authors +** +** Permission is hereby granted, free of charge, to any person obtaining a copy of +** this software and associated documentation files (the "Software"), to deal in +** the Software without restriction, including without limitation the rights to +** use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +** the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in all +** copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +** FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +** COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +** IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************** +** +** 16-bit brain floating point vector format utilities. +** +** See https://en.wikipedia.org/wiki/Bfloat16_floating-point_format +*/ +#ifndef SQLITE_OMIT_VECTOR +/* #include "sqliteInt.h" */ + +/* #include "vectorInt.h" */ + +/* #include */ + +/************************************************************************** +** Utility routines for vector serialization and deserialization +**************************************************************************/ + +float vectorFB16ToFloat(u16 f16){ + u32 f32 = (u32)f16 << 16; + return *((float*)&f32); +} + +u16 vectorFB16FromFloat(float f){ + u32 f32 = *((u32*)&f); + return (u16)(f32 >> 16); +} + +void vectorFB16Dump(const Vector *pVec){ + u16 *elems = pVec->data; + unsigned i; + + assert( pVec->type == VECTOR_TYPE_FLOATB16 ); + + printf("fb16: ["); + for(i = 0; i < pVec->dims; i++){ + printf("%s%f", i == 0 ? "" : ", ", vectorFB16ToFloat(elems[i])); + } + printf("]\n"); +} + +void vectorFB16SerializeToBlob( + const Vector *pVector, + unsigned char *pBlob, + size_t nBlobSize +){ + assert( pVector->type == VECTOR_TYPE_FLOATB16 ); + assert( pVector->dims <= MAX_VECTOR_SZ ); + assert( nBlobSize >= vectorDataSize(pVector->type, pVector->dims) ); + + memcpy(pBlob, pVector->data, pVector->dims * sizeof(u16)); +} + +float vectorFB16DistanceCos(const Vector *v1, const Vector *v2){ + int i; + float dot = 0, norm1 = 0, norm2 = 0; + float value1, value2; + u16 *data1 = v1->data, *data2 = v2->data; + + assert( v1->dims == v2->dims ); + assert( v1->type == VECTOR_TYPE_FLOATB16 ); + assert( v2->type == VECTOR_TYPE_FLOATB16 ); + + for(i = 0; i < v1->dims; i++){ + value1 = vectorFB16ToFloat(data1[i]); + value2 = vectorFB16ToFloat(data2[i]); + dot += value1*value2; + norm1 += value1*value1; + norm2 += value2*value2; + } + + return 1.0 - (dot / sqrt(norm1 * norm2)); +} + +float vectorFB16DistanceL2(const Vector *v1, const Vector *v2){ + int i; + float sum = 0; + float value1, value2; + u16 *data1 = v1->data, *data2 = v2->data; + + assert( v1->dims == v2->dims ); + assert( v1->type == VECTOR_TYPE_FLOATB16 ); + assert( v2->type == VECTOR_TYPE_FLOATB16 ); + + for(i = 0; i < v1->dims; i++){ + value1 = vectorFB16ToFloat(data1[i]); + value2 = vectorFB16ToFloat(data2[i]); + float d = (value1 - value2); + sum += d*d; + } + return sqrt(sum); +} + +void vectorFB16DeserializeFromBlob( + Vector *pVector, + const unsigned char *pBlob, + size_t nBlobSize +){ + assert( pVector->type == VECTOR_TYPE_FLOATB16 ); + assert( 0 <= pVector->dims && pVector->dims <= MAX_VECTOR_SZ ); + assert( nBlobSize >= vectorDataSize(pVector->type, pVector->dims) ); + + memcpy((u8*)pVector->data, (u8*)pBlob, pVector->dims * sizeof(u16)); +} + +#endif /* !defined(SQLITE_OMIT_VECTOR) */ + + +/************** End of vectorfloatb16.c **************************************/ /************** Begin file vectorIndex.c *************************************/ /* ** 2024-03-18 @@ -215205,6 +215462,8 @@ static struct VectorColumnType VECTOR_COLUMN_TYPES[] = { { "F8_BLOB", VECTOR_TYPE_FLOAT8 }, { "FLOAT16", VECTOR_TYPE_FLOAT16 }, { "F16_BLOB", VECTOR_TYPE_FLOAT16 }, + { "FLOATB16", VECTOR_TYPE_FLOATB16 }, + { "FB16_BLOB", VECTOR_TYPE_FLOATB16 }, }; /* @@ -215226,6 +215485,7 @@ static struct VectorParamName VECTOR_PARAM_NAMES[] = { { "compress_neighbors", VECTOR_COMPRESS_NEIGHBORS_PARAM_ID, 0, "float1bit", VECTOR_TYPE_FLOAT1BIT }, { "compress_neighbors", VECTOR_COMPRESS_NEIGHBORS_PARAM_ID, 0, "float8", VECTOR_TYPE_FLOAT8 }, { "compress_neighbors", VECTOR_COMPRESS_NEIGHBORS_PARAM_ID, 0, "float16", VECTOR_TYPE_FLOAT16 }, + { "compress_neighbors", VECTOR_COMPRESS_NEIGHBORS_PARAM_ID, 0, "floatb16", VECTOR_TYPE_FLOATB16 }, { "compress_neighbors", VECTOR_COMPRESS_NEIGHBORS_PARAM_ID, 0, "float32", VECTOR_TYPE_FLOAT32 }, { "alpha", VECTOR_PRUNING_ALPHA_PARAM_ID, 2, 0, 0 }, { "search_l", VECTOR_SEARCH_L_PARAM_ID, 1, 0, 0 }, diff --git a/libsql-ffi/bundled/src/sqlite3.c b/libsql-ffi/bundled/src/sqlite3.c index daad6d309d..c0bc2492da 100644 --- a/libsql-ffi/bundled/src/sqlite3.c +++ b/libsql-ffi/bundled/src/sqlite3.c @@ -85273,6 +85273,7 @@ typedef u32 VectorDims; #define VECTOR_TYPE_FLOAT1BIT 3 #define VECTOR_TYPE_FLOAT8 4 #define VECTOR_TYPE_FLOAT16 5 +#define VECTOR_TYPE_FLOATB16 6 #define VECTOR_FLAGS_STATIC 1 @@ -85301,6 +85302,7 @@ void vectorInit(Vector *, VectorType, VectorDims, void *); void vectorDump (const Vector *v); void vectorF8Dump (const Vector *v); void vectorF16Dump (const Vector *v); +void vectorFB16Dump(const Vector *v); void vectorF32Dump (const Vector *v); void vectorF64Dump (const Vector *v); void vector1BitDump(const Vector *v); @@ -85321,6 +85323,7 @@ void vectorF64MarshalToText(sqlite3_context *, const Vector *); void vectorSerializeToBlob (const Vector *, unsigned char *, size_t); void vectorF8SerializeToBlob (const Vector *, unsigned char *, size_t); void vectorF16SerializeToBlob (const Vector *, unsigned char *, size_t); +void vectorFB16SerializeToBlob(const Vector *, unsigned char *, size_t); void vectorF32SerializeToBlob (const Vector *, unsigned char *, size_t); void vectorF64SerializeToBlob (const Vector *, unsigned char *, size_t); void vector1BitSerializeToBlob(const Vector *, unsigned char *, size_t); @@ -85331,6 +85334,7 @@ void vector1BitSerializeToBlob(const Vector *, unsigned char *, size_t); float vectorDistanceCos (const Vector *, const Vector *); float vectorF8DistanceCos (const Vector *, const Vector *); float vectorF16DistanceCos (const Vector *, const Vector *); +float vectorFB16DistanceCos(const Vector *, const Vector *); float vectorF32DistanceCos (const Vector *, const Vector *); double vectorF64DistanceCos(const Vector *, const Vector *); @@ -85345,6 +85349,7 @@ int vector1BitDistanceHamming(const Vector *, const Vector *); float vectorDistanceL2 (const Vector *, const Vector *); float vectorF8DistanceL2 (const Vector *, const Vector *); float vectorF16DistanceL2 (const Vector *, const Vector *); +float vectorFB16DistanceL2(const Vector *, const Vector *); float vectorF32DistanceL2 (const Vector *, const Vector *); double vectorF64DistanceL2(const Vector *, const Vector *); @@ -85362,6 +85367,7 @@ int vectorParseSqliteBlobWithType(sqlite3_value *, Vector *, char **); void vectorF8DeserializeFromBlob (Vector *, const unsigned char *, size_t); void vectorF16DeserializeFromBlob (Vector *, const unsigned char *, size_t); +void vectorFB16DeserializeFromBlob(Vector *, const unsigned char *, size_t); void vectorF32DeserializeFromBlob (Vector *, const unsigned char *, size_t); void vectorF64DeserializeFromBlob (Vector *, const unsigned char *, size_t); void vector1BitDeserializeFromBlob(Vector *, const unsigned char *, size_t); @@ -85372,6 +85378,9 @@ void vectorInitFromBlob(Vector *, const unsigned char *, size_t); u16 vectorF16FromFloat(float); float vectorF16ToFloat(u16); +u16 vectorFB16FromFloat(float); +float vectorFB16ToFloat(u16); + void vectorConvert(const Vector *, Vector *); /* Detect type and dimension of vector provided with first parameter of sqlite3_value * type */ @@ -211050,6 +211059,8 @@ size_t vectorDataSize(VectorType type, VectorDims dims){ return ALIGN(dims, sizeof(float)) + sizeof(float) /* alpha */ + sizeof(float) /* shift */; case VECTOR_TYPE_FLOAT16: return dims * sizeof(u16); + case VECTOR_TYPE_FLOATB16: + return dims * sizeof(u16); default: assert(0); } @@ -211127,6 +211138,8 @@ float vectorDistanceCos(const Vector *pVector1, const Vector *pVector2){ return vectorF8DistanceCos(pVector1, pVector2); case VECTOR_TYPE_FLOAT16: return vectorF16DistanceCos(pVector1, pVector2); + case VECTOR_TYPE_FLOATB16: + return vectorFB16DistanceCos(pVector1, pVector2); default: assert(0); } @@ -211144,6 +211157,8 @@ float vectorDistanceL2(const Vector *pVector1, const Vector *pVector2){ return vectorF8DistanceL2(pVector1, pVector2); case VECTOR_TYPE_FLOAT16: return vectorF16DistanceL2(pVector1, pVector2); + case VECTOR_TYPE_FLOATB16: + return vectorFB16DistanceL2(pVector1, pVector2); default: assert(0); } @@ -211317,6 +211332,13 @@ static int vectorParseMeta(const unsigned char *pBlob, size_t nBlobSize, int *pT } *pDims = nBlobSize / sizeof(u16); *pDataSize = nBlobSize; + }else if( *pType == VECTOR_TYPE_FLOATB16 ){ + if( nBlobSize % 2 != 0 ){ + *pzErrMsg = sqlite3_mprintf("vector: floatb16 vector blob length must be divisible by 2 (excluding 'type'-byte): length=%d", nBlobSize); + return SQLITE_ERROR; + } + *pDims = nBlobSize / sizeof(u16); + *pDataSize = nBlobSize; }else{ *pzErrMsg = sqlite3_mprintf("vector: unexpected binary type: %d", *pType); return SQLITE_ERROR; @@ -211368,6 +211390,9 @@ int vectorParseSqliteBlobWithType( case VECTOR_TYPE_FLOAT16: vectorF16DeserializeFromBlob(pVector, pBlob, nDataSize); return 0; + case VECTOR_TYPE_FLOATB16: + vectorFB16DeserializeFromBlob(pVector, pBlob, nDataSize); + return 0; default: assert(0); } @@ -211472,6 +211497,9 @@ void vectorDump(const Vector *pVector){ case VECTOR_TYPE_FLOAT16: vectorF16Dump(pVector); break; + case VECTOR_TYPE_FLOATB16: + vectorFB16Dump(pVector); + break; default: assert(0); } @@ -211497,7 +211525,7 @@ static int vectorMetaSize(VectorType type, VectorDims dims){ int nDataSize; if( type == VECTOR_TYPE_FLOAT32 ){ return 0; - }else if( type == VECTOR_TYPE_FLOAT64 || type == VECTOR_TYPE_FLOAT16 ){ + }else if( type == VECTOR_TYPE_FLOAT64 || type == VECTOR_TYPE_FLOAT16 || type == VECTOR_TYPE_FLOATB16 ){ return 1; }else if( type == VECTOR_TYPE_FLOAT1BIT ){ nDataSize = vectorDataSize(type, dims); @@ -211516,7 +211544,7 @@ static int vectorMetaSize(VectorType type, VectorDims dims){ static void vectorSerializeMeta(const Vector *pVector, size_t nDataSize, unsigned char *pBlob, size_t nBlobSize){ if( pVector->type == VECTOR_TYPE_FLOAT32 ){ // no meta for f32 type as this is "default" vector type - }else if( pVector->type == VECTOR_TYPE_FLOAT64 || pVector->type == VECTOR_TYPE_FLOAT16 ){ + }else if( pVector->type == VECTOR_TYPE_FLOAT64 || pVector->type == VECTOR_TYPE_FLOAT16 || pVector->type == VECTOR_TYPE_FLOATB16 ){ assert( nDataSize % 2 == 0 ); assert( nBlobSize == nDataSize + 1 ); pBlob[nBlobSize - 1] = pVector->type; @@ -211585,6 +211613,9 @@ void vectorSerializeToBlob(const Vector *pVector, unsigned char *pBlob, size_t n case VECTOR_TYPE_FLOAT16: vectorF16SerializeToBlob(pVector, pBlob, nBlobSize); break; + case VECTOR_TYPE_FLOATB16: + vectorFB16SerializeToBlob(pVector, pBlob, nBlobSize); + break; default: assert(0); } @@ -211627,6 +211658,11 @@ static void vectorConvertFromF32(const Vector *pFrom, Vector *pTo){ for(i = 0; i < pFrom->dims; i++){ dstF16[i] = vectorF16FromFloat(src[i]); } + }else if( pTo->type == VECTOR_TYPE_FLOATB16 ){ + dstF16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstF16[i] = vectorFB16FromFloat(src[i]); + } }else{ assert( 0 ); } @@ -211665,6 +211701,11 @@ static void vectorConvertFromF64(const Vector *pFrom, Vector *pTo){ for(i = 0; i < pFrom->dims; i++){ dstF16[i] = vectorF16FromFloat(src[i]); } + }else if( pTo->type == VECTOR_TYPE_FLOATB16 ){ + dstF16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstF16[i] = vectorFB16FromFloat(src[i]); + } }else{ assert( 0 ); } @@ -211676,7 +211717,7 @@ static void vectorConvertFrom1Bit(const Vector *pFrom, Vector *pTo){ float *dstF32; double *dstF64; - u16 *dstF16; + u16 *dstU16; assert( pFrom->dims == pTo->dims ); assert( pFrom->type != pTo->type ); @@ -211704,12 +211745,23 @@ static void vectorConvertFrom1Bit(const Vector *pFrom, Vector *pTo){ }else if( pTo->type == VECTOR_TYPE_FLOAT16 ){ u16 positive = vectorF16FromFloat(+1); u16 negative = vectorF16FromFloat(-1); - dstF16 = pTo->data; + dstU16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + if( ((src[i / 8] >> (i & 7)) & 1) == 1 ){ + dstU16[i] = positive; + }else{ + dstU16[i] = negative; + } + } + }else if( pTo->type == VECTOR_TYPE_FLOATB16 ){ + u16 positive = vectorFB16FromFloat(+1); + u16 negative = vectorFB16FromFloat(-1); + dstU16 = pTo->data; for(i = 0; i < pFrom->dims; i++){ if( ((src[i / 8] >> (i & 7)) & 1) == 1 ){ - dstF16[i] = positive; + dstU16[i] = positive; }else{ - dstF16[i] = negative; + dstU16[i] = negative; } } }else{ @@ -211759,6 +211811,11 @@ static void vectorConvertFromF8(const Vector *pFrom, Vector *pTo){ for(i = 0; i < pFrom->dims; i++){ dstF16[i] = vectorF16FromFloat(alpha * src[i] + shift); } + }else if( pTo->type == VECTOR_TYPE_FLOATB16 ){ + dstF16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstF16[i] = vectorFB16FromFloat(alpha * src[i] + shift); + } }else{ assert( 0 ); } @@ -211771,6 +211828,7 @@ static void vectorConvertFromF16(const Vector *pFrom, Vector *pTo){ float *dstF32; double *dstF64; u8 *dst1Bit; + u16 *dstU16; assert( pFrom->dims == pTo->dims ); assert( pFrom->type != pTo->type ); @@ -211787,6 +211845,11 @@ static void vectorConvertFromF16(const Vector *pFrom, Vector *pTo){ for(i = 0; i < pFrom->dims; i++){ dstF64[i] = vectorF16ToFloat(src[i]); } + }else if( pTo->type == VECTOR_TYPE_FLOATB16 ){ + dstU16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstU16[i] = vectorFB16FromFloat(vectorF16ToFloat(src[i])); + } }else if( pTo->type == VECTOR_TYPE_FLOAT1BIT ){ dst1Bit = pTo->data; for(i = 0; i < pFrom->dims; i += 8){ @@ -211802,6 +211865,50 @@ static void vectorConvertFromF16(const Vector *pFrom, Vector *pTo){ } } +static void vectorConvertFromFB16(const Vector *pFrom, Vector *pTo){ + int i; + u16 *src; + + float *dstF32; + double *dstF64; + u8 *dst1Bit; + u16 *dstU16; + + assert( pFrom->dims == pTo->dims ); + assert( pFrom->type != pTo->type ); + assert( pFrom->type == VECTOR_TYPE_FLOATB16 ); + + src = pFrom->data; + if( pTo->type == VECTOR_TYPE_FLOAT32 ){ + dstF32 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstF32[i] = vectorFB16ToFloat(src[i]); + } + }else if( pTo->type == VECTOR_TYPE_FLOAT64 ){ + dstF64 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstF64[i] = vectorFB16ToFloat(src[i]); + } + }else if( pTo->type == VECTOR_TYPE_FLOAT16 ){ + dstU16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstU16[i] = vectorF16FromFloat(vectorFB16ToFloat(src[i])); + } + }else if( pTo->type == VECTOR_TYPE_FLOAT1BIT ){ + dst1Bit = pTo->data; + for(i = 0; i < pFrom->dims; i += 8){ + dst1Bit[i / 8] = 0; + } + for(i = 0; i < pFrom->dims; i++){ + if( vectorFB16ToFloat(src[i]) > 0 ){ + dst1Bit[i / 8] |= (1 << (i & 7)); + } + } + }else{ + assert( 0 ); + } +} + static inline int clip(float f, int minF, int maxF){ if( f < minF ){ return minF; @@ -211822,7 +211929,7 @@ static void vectorConvertToF8(const Vector *pFrom, Vector *pTo){ float *srcF32; double *srcF64; u8 *src1Bit; - u16 *srcF16; + u16 *srcU16; assert( pFrom->dims == pTo->dims ); assert( pFrom->type != pTo->type ); @@ -211860,14 +211967,24 @@ static void vectorConvertToF8(const Vector *pFrom, Vector *pTo){ dst[i] = clip(((((src1Bit[i / 8] >> (i & 7)) & 1) ? +1 : -1) - shift) / alpha, 0, 255); } }else if( pFrom->type == VECTOR_TYPE_FLOAT16 ){ - srcF16 = pFrom->data; + srcU16 = pFrom->data; for(i = 0; i < pFrom->dims; i++){ - MINMAX(i, vectorF16ToFloat(srcF16[i]), minF, maxF); + MINMAX(i, vectorF16ToFloat(srcU16[i]), minF, maxF); } shift = minF; alpha = (maxF - minF) / 255; for(i = 0; i < pFrom->dims; i++){ - dst[i] = clip((vectorF16ToFloat(srcF16[i]) - shift) / alpha, 0, 255); + dst[i] = clip((vectorF16ToFloat(srcU16[i]) - shift) / alpha, 0, 255); + } + }else if( pFrom->type == VECTOR_TYPE_FLOATB16 ){ + srcU16 = pFrom->data; + for(i = 0; i < pFrom->dims; i++){ + MINMAX(i, vectorFB16ToFloat(srcU16[i]), minF, maxF); + } + shift = minF; + alpha = (maxF - minF) / 255; + for(i = 0; i < pFrom->dims; i++){ + dst[i] = clip((vectorFB16ToFloat(srcU16[i]) - shift) / alpha, 0, 255); } }else{ assert( 0 ); @@ -211896,6 +212013,8 @@ void vectorConvert(const Vector *pFrom, Vector *pTo){ vectorConvertFromF8(pFrom, pTo); }else if( pFrom->type == VECTOR_TYPE_FLOAT16 ){ vectorConvertFromF16(pFrom, pTo); + }else if( pFrom->type == VECTOR_TYPE_FLOATB16 ){ + vectorConvertFromFB16(pFrom, pTo); }else{ assert( 0 ); } @@ -211988,6 +212107,14 @@ static void vector16Func( vectorFuncHintedType(context, argc, argv, VECTOR_TYPE_FLOAT16); } +static void vectorb16Func( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + vectorFuncHintedType(context, argc, argv, VECTOR_TYPE_FLOATB16); +} + static void vector1BitFunc( sqlite3_context *context, int argc, @@ -212147,6 +212274,7 @@ SQLITE_PRIVATE void sqlite3RegisterVectorFunctions(void){ FUNCTION(vector1bit, 1, 0, 0, vector1BitFunc), FUNCTION(vector8, 1, 0, 0, vector8Func), FUNCTION(vector16, 1, 0, 0, vector16Func), + FUNCTION(vectorb16, 1, 0, 0, vectorb16Func), FUNCTION(vector_extract, 1, 0, 0, vectorExtractFunc), FUNCTION(vector_distance_cos, 2, 0, 0, vectorDistanceCosFunc), FUNCTION(vector_distance_l2, 2, 0, 0, vectorDistanceL2Func), @@ -214751,8 +214879,6 @@ void vectorF16SerializeToBlob( unsigned char *pBlob, size_t nBlobSize ){ - float alpha, shift; - assert( pVector->type == VECTOR_TYPE_FLOAT16 ); assert( pVector->dims <= MAX_VECTOR_SZ ); assert( nBlobSize >= vectorDataSize(pVector->type, pVector->dims) ); @@ -214815,6 +214941,137 @@ void vectorF16DeserializeFromBlob( #endif /* !defined(SQLITE_OMIT_VECTOR) */ /************** End of vectorfloat16.c ***************************************/ +/************** Begin file vectorfloatb16.c **********************************/ +/* +** 2024-07-04 +** +** Copyright 2024 the libSQL authors +** +** Permission is hereby granted, free of charge, to any person obtaining a copy of +** this software and associated documentation files (the "Software"), to deal in +** the Software without restriction, including without limitation the rights to +** use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +** the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in all +** copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +** FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +** COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +** IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************** +** +** 16-bit brain floating point vector format utilities. +** +** See https://en.wikipedia.org/wiki/Bfloat16_floating-point_format +*/ +#ifndef SQLITE_OMIT_VECTOR +/* #include "sqliteInt.h" */ + +/* #include "vectorInt.h" */ + +/* #include */ + +/************************************************************************** +** Utility routines for vector serialization and deserialization +**************************************************************************/ + +float vectorFB16ToFloat(u16 f16){ + u32 f32 = (u32)f16 << 16; + return *((float*)&f32); +} + +u16 vectorFB16FromFloat(float f){ + u32 f32 = *((u32*)&f); + return (u16)(f32 >> 16); +} + +void vectorFB16Dump(const Vector *pVec){ + u16 *elems = pVec->data; + unsigned i; + + assert( pVec->type == VECTOR_TYPE_FLOATB16 ); + + printf("fb16: ["); + for(i = 0; i < pVec->dims; i++){ + printf("%s%f", i == 0 ? "" : ", ", vectorFB16ToFloat(elems[i])); + } + printf("]\n"); +} + +void vectorFB16SerializeToBlob( + const Vector *pVector, + unsigned char *pBlob, + size_t nBlobSize +){ + assert( pVector->type == VECTOR_TYPE_FLOATB16 ); + assert( pVector->dims <= MAX_VECTOR_SZ ); + assert( nBlobSize >= vectorDataSize(pVector->type, pVector->dims) ); + + memcpy(pBlob, pVector->data, pVector->dims * sizeof(u16)); +} + +float vectorFB16DistanceCos(const Vector *v1, const Vector *v2){ + int i; + float dot = 0, norm1 = 0, norm2 = 0; + float value1, value2; + u16 *data1 = v1->data, *data2 = v2->data; + + assert( v1->dims == v2->dims ); + assert( v1->type == VECTOR_TYPE_FLOATB16 ); + assert( v2->type == VECTOR_TYPE_FLOATB16 ); + + for(i = 0; i < v1->dims; i++){ + value1 = vectorFB16ToFloat(data1[i]); + value2 = vectorFB16ToFloat(data2[i]); + dot += value1*value2; + norm1 += value1*value1; + norm2 += value2*value2; + } + + return 1.0 - (dot / sqrt(norm1 * norm2)); +} + +float vectorFB16DistanceL2(const Vector *v1, const Vector *v2){ + int i; + float sum = 0; + float value1, value2; + u16 *data1 = v1->data, *data2 = v2->data; + + assert( v1->dims == v2->dims ); + assert( v1->type == VECTOR_TYPE_FLOATB16 ); + assert( v2->type == VECTOR_TYPE_FLOATB16 ); + + for(i = 0; i < v1->dims; i++){ + value1 = vectorFB16ToFloat(data1[i]); + value2 = vectorFB16ToFloat(data2[i]); + float d = (value1 - value2); + sum += d*d; + } + return sqrt(sum); +} + +void vectorFB16DeserializeFromBlob( + Vector *pVector, + const unsigned char *pBlob, + size_t nBlobSize +){ + assert( pVector->type == VECTOR_TYPE_FLOATB16 ); + assert( 0 <= pVector->dims && pVector->dims <= MAX_VECTOR_SZ ); + assert( nBlobSize >= vectorDataSize(pVector->type, pVector->dims) ); + + memcpy((u8*)pVector->data, (u8*)pBlob, pVector->dims * sizeof(u16)); +} + +#endif /* !defined(SQLITE_OMIT_VECTOR) */ + + +/************** End of vectorfloatb16.c **************************************/ /************** Begin file vectorIndex.c *************************************/ /* ** 2024-03-18 @@ -215205,6 +215462,8 @@ static struct VectorColumnType VECTOR_COLUMN_TYPES[] = { { "F8_BLOB", VECTOR_TYPE_FLOAT8 }, { "FLOAT16", VECTOR_TYPE_FLOAT16 }, { "F16_BLOB", VECTOR_TYPE_FLOAT16 }, + { "FLOATB16", VECTOR_TYPE_FLOATB16 }, + { "FB16_BLOB", VECTOR_TYPE_FLOATB16 }, }; /* @@ -215226,6 +215485,7 @@ static struct VectorParamName VECTOR_PARAM_NAMES[] = { { "compress_neighbors", VECTOR_COMPRESS_NEIGHBORS_PARAM_ID, 0, "float1bit", VECTOR_TYPE_FLOAT1BIT }, { "compress_neighbors", VECTOR_COMPRESS_NEIGHBORS_PARAM_ID, 0, "float8", VECTOR_TYPE_FLOAT8 }, { "compress_neighbors", VECTOR_COMPRESS_NEIGHBORS_PARAM_ID, 0, "float16", VECTOR_TYPE_FLOAT16 }, + { "compress_neighbors", VECTOR_COMPRESS_NEIGHBORS_PARAM_ID, 0, "floatb16", VECTOR_TYPE_FLOATB16 }, { "compress_neighbors", VECTOR_COMPRESS_NEIGHBORS_PARAM_ID, 0, "float32", VECTOR_TYPE_FLOAT32 }, { "alpha", VECTOR_PRUNING_ALPHA_PARAM_ID, 2, 0, 0 }, { "search_l", VECTOR_SEARCH_L_PARAM_ID, 1, 0, 0 }, diff --git a/libsql-sqlite3/Makefile.in b/libsql-sqlite3/Makefile.in index 9ebc16d5c6..0896f28b95 100644 --- a/libsql-sqlite3/Makefile.in +++ b/libsql-sqlite3/Makefile.in @@ -195,7 +195,7 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \ sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \ table.lo threads.lo tokenize.lo treeview.lo trigger.lo \ update.lo userauth.lo upsert.lo util.lo vacuum.lo \ - vector.lo vectorfloat32.lo vectorfloat64.lo vectorfloat1bit.lo vectorfloat8.lo vectorfloat16.lo \ + vector.lo vectorfloat32.lo vectorfloat64.lo vectorfloat1bit.lo vectorfloat8.lo vectorfloat16.lo vectorfloatb16.lo \ vectorIndex.lo vectordiskann.lo vectorvtab.lo \ vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \ vdbetrace.lo vdbevtab.lo \ @@ -304,10 +304,12 @@ SRC = \ $(TOP)/src/vector.c \ $(TOP)/src/vectorInt.h \ $(TOP)/src/vectorfloat1bit.c \ + $(TOP)/src/vectorfloat1bit.c \ $(TOP)/src/vectorfloat16.c \ $(TOP)/src/vectorfloat32.c \ $(TOP)/src/vectorfloat64.c \ $(TOP)/src/vectorfloat8.c \ + $(TOP)/src/vectorfloatb16.c \ $(TOP)/src/vectorIndexInt.h \ $(TOP)/src/vectorIndex.c \ $(TOP)/src/vectordiskann.c \ @@ -1147,6 +1149,9 @@ vectorfloat1bit.lo: $(TOP)/src/vectorfloat1bit.c $(HDR) vectorfloat16.lo: $(TOP)/src/vectorfloat16.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vectorfloat16.c +vectorfloatb16.lo: $(TOP)/src/vectorfloatb16.c $(HDR) + $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vectorfloatb16.c + vectorfloat32.lo: $(TOP)/src/vectorfloat32.c $(HDR) $(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/vectorfloat32.c diff --git a/libsql-sqlite3/src/vector.c b/libsql-sqlite3/src/vector.c index 5daa9af07d..51f8af5d05 100644 --- a/libsql-sqlite3/src/vector.c +++ b/libsql-sqlite3/src/vector.c @@ -47,6 +47,8 @@ size_t vectorDataSize(VectorType type, VectorDims dims){ return ALIGN(dims, sizeof(float)) + sizeof(float) /* alpha */ + sizeof(float) /* shift */; case VECTOR_TYPE_FLOAT16: return dims * sizeof(u16); + case VECTOR_TYPE_FLOATB16: + return dims * sizeof(u16); default: assert(0); } @@ -124,6 +126,8 @@ float vectorDistanceCos(const Vector *pVector1, const Vector *pVector2){ return vectorF8DistanceCos(pVector1, pVector2); case VECTOR_TYPE_FLOAT16: return vectorF16DistanceCos(pVector1, pVector2); + case VECTOR_TYPE_FLOATB16: + return vectorFB16DistanceCos(pVector1, pVector2); default: assert(0); } @@ -141,6 +145,8 @@ float vectorDistanceL2(const Vector *pVector1, const Vector *pVector2){ return vectorF8DistanceL2(pVector1, pVector2); case VECTOR_TYPE_FLOAT16: return vectorF16DistanceL2(pVector1, pVector2); + case VECTOR_TYPE_FLOATB16: + return vectorFB16DistanceL2(pVector1, pVector2); default: assert(0); } @@ -314,6 +320,13 @@ static int vectorParseMeta(const unsigned char *pBlob, size_t nBlobSize, int *pT } *pDims = nBlobSize / sizeof(u16); *pDataSize = nBlobSize; + }else if( *pType == VECTOR_TYPE_FLOATB16 ){ + if( nBlobSize % 2 != 0 ){ + *pzErrMsg = sqlite3_mprintf("vector: floatb16 vector blob length must be divisible by 2 (excluding 'type'-byte): length=%d", nBlobSize); + return SQLITE_ERROR; + } + *pDims = nBlobSize / sizeof(u16); + *pDataSize = nBlobSize; }else{ *pzErrMsg = sqlite3_mprintf("vector: unexpected binary type: %d", *pType); return SQLITE_ERROR; @@ -365,6 +378,9 @@ int vectorParseSqliteBlobWithType( case VECTOR_TYPE_FLOAT16: vectorF16DeserializeFromBlob(pVector, pBlob, nDataSize); return 0; + case VECTOR_TYPE_FLOATB16: + vectorFB16DeserializeFromBlob(pVector, pBlob, nDataSize); + return 0; default: assert(0); } @@ -469,6 +485,9 @@ void vectorDump(const Vector *pVector){ case VECTOR_TYPE_FLOAT16: vectorF16Dump(pVector); break; + case VECTOR_TYPE_FLOATB16: + vectorFB16Dump(pVector); + break; default: assert(0); } @@ -494,7 +513,7 @@ static int vectorMetaSize(VectorType type, VectorDims dims){ int nDataSize; if( type == VECTOR_TYPE_FLOAT32 ){ return 0; - }else if( type == VECTOR_TYPE_FLOAT64 || type == VECTOR_TYPE_FLOAT16 ){ + }else if( type == VECTOR_TYPE_FLOAT64 || type == VECTOR_TYPE_FLOAT16 || type == VECTOR_TYPE_FLOATB16 ){ return 1; }else if( type == VECTOR_TYPE_FLOAT1BIT ){ nDataSize = vectorDataSize(type, dims); @@ -513,7 +532,7 @@ static int vectorMetaSize(VectorType type, VectorDims dims){ static void vectorSerializeMeta(const Vector *pVector, size_t nDataSize, unsigned char *pBlob, size_t nBlobSize){ if( pVector->type == VECTOR_TYPE_FLOAT32 ){ // no meta for f32 type as this is "default" vector type - }else if( pVector->type == VECTOR_TYPE_FLOAT64 || pVector->type == VECTOR_TYPE_FLOAT16 ){ + }else if( pVector->type == VECTOR_TYPE_FLOAT64 || pVector->type == VECTOR_TYPE_FLOAT16 || pVector->type == VECTOR_TYPE_FLOATB16 ){ assert( nDataSize % 2 == 0 ); assert( nBlobSize == nDataSize + 1 ); pBlob[nBlobSize - 1] = pVector->type; @@ -582,6 +601,9 @@ void vectorSerializeToBlob(const Vector *pVector, unsigned char *pBlob, size_t n case VECTOR_TYPE_FLOAT16: vectorF16SerializeToBlob(pVector, pBlob, nBlobSize); break; + case VECTOR_TYPE_FLOATB16: + vectorFB16SerializeToBlob(pVector, pBlob, nBlobSize); + break; default: assert(0); } @@ -624,6 +646,11 @@ static void vectorConvertFromF32(const Vector *pFrom, Vector *pTo){ for(i = 0; i < pFrom->dims; i++){ dstF16[i] = vectorF16FromFloat(src[i]); } + }else if( pTo->type == VECTOR_TYPE_FLOATB16 ){ + dstF16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstF16[i] = vectorFB16FromFloat(src[i]); + } }else{ assert( 0 ); } @@ -662,6 +689,11 @@ static void vectorConvertFromF64(const Vector *pFrom, Vector *pTo){ for(i = 0; i < pFrom->dims; i++){ dstF16[i] = vectorF16FromFloat(src[i]); } + }else if( pTo->type == VECTOR_TYPE_FLOATB16 ){ + dstF16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstF16[i] = vectorFB16FromFloat(src[i]); + } }else{ assert( 0 ); } @@ -673,7 +705,7 @@ static void vectorConvertFrom1Bit(const Vector *pFrom, Vector *pTo){ float *dstF32; double *dstF64; - u16 *dstF16; + u16 *dstU16; assert( pFrom->dims == pTo->dims ); assert( pFrom->type != pTo->type ); @@ -701,12 +733,23 @@ static void vectorConvertFrom1Bit(const Vector *pFrom, Vector *pTo){ }else if( pTo->type == VECTOR_TYPE_FLOAT16 ){ u16 positive = vectorF16FromFloat(+1); u16 negative = vectorF16FromFloat(-1); - dstF16 = pTo->data; + dstU16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + if( ((src[i / 8] >> (i & 7)) & 1) == 1 ){ + dstU16[i] = positive; + }else{ + dstU16[i] = negative; + } + } + }else if( pTo->type == VECTOR_TYPE_FLOATB16 ){ + u16 positive = vectorFB16FromFloat(+1); + u16 negative = vectorFB16FromFloat(-1); + dstU16 = pTo->data; for(i = 0; i < pFrom->dims; i++){ if( ((src[i / 8] >> (i & 7)) & 1) == 1 ){ - dstF16[i] = positive; + dstU16[i] = positive; }else{ - dstF16[i] = negative; + dstU16[i] = negative; } } }else{ @@ -756,6 +799,11 @@ static void vectorConvertFromF8(const Vector *pFrom, Vector *pTo){ for(i = 0; i < pFrom->dims; i++){ dstF16[i] = vectorF16FromFloat(alpha * src[i] + shift); } + }else if( pTo->type == VECTOR_TYPE_FLOATB16 ){ + dstF16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstF16[i] = vectorFB16FromFloat(alpha * src[i] + shift); + } }else{ assert( 0 ); } @@ -768,6 +816,7 @@ static void vectorConvertFromF16(const Vector *pFrom, Vector *pTo){ float *dstF32; double *dstF64; u8 *dst1Bit; + u16 *dstU16; assert( pFrom->dims == pTo->dims ); assert( pFrom->type != pTo->type ); @@ -784,6 +833,11 @@ static void vectorConvertFromF16(const Vector *pFrom, Vector *pTo){ for(i = 0; i < pFrom->dims; i++){ dstF64[i] = vectorF16ToFloat(src[i]); } + }else if( pTo->type == VECTOR_TYPE_FLOATB16 ){ + dstU16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstU16[i] = vectorFB16FromFloat(vectorF16ToFloat(src[i])); + } }else if( pTo->type == VECTOR_TYPE_FLOAT1BIT ){ dst1Bit = pTo->data; for(i = 0; i < pFrom->dims; i += 8){ @@ -799,6 +853,50 @@ static void vectorConvertFromF16(const Vector *pFrom, Vector *pTo){ } } +static void vectorConvertFromFB16(const Vector *pFrom, Vector *pTo){ + int i; + u16 *src; + + float *dstF32; + double *dstF64; + u8 *dst1Bit; + u16 *dstU16; + + assert( pFrom->dims == pTo->dims ); + assert( pFrom->type != pTo->type ); + assert( pFrom->type == VECTOR_TYPE_FLOATB16 ); + + src = pFrom->data; + if( pTo->type == VECTOR_TYPE_FLOAT32 ){ + dstF32 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstF32[i] = vectorFB16ToFloat(src[i]); + } + }else if( pTo->type == VECTOR_TYPE_FLOAT64 ){ + dstF64 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstF64[i] = vectorFB16ToFloat(src[i]); + } + }else if( pTo->type == VECTOR_TYPE_FLOAT16 ){ + dstU16 = pTo->data; + for(i = 0; i < pFrom->dims; i++){ + dstU16[i] = vectorF16FromFloat(vectorFB16ToFloat(src[i])); + } + }else if( pTo->type == VECTOR_TYPE_FLOAT1BIT ){ + dst1Bit = pTo->data; + for(i = 0; i < pFrom->dims; i += 8){ + dst1Bit[i / 8] = 0; + } + for(i = 0; i < pFrom->dims; i++){ + if( vectorFB16ToFloat(src[i]) > 0 ){ + dst1Bit[i / 8] |= (1 << (i & 7)); + } + } + }else{ + assert( 0 ); + } +} + static inline int clip(float f, int minF, int maxF){ if( f < minF ){ return minF; @@ -819,7 +917,7 @@ static void vectorConvertToF8(const Vector *pFrom, Vector *pTo){ float *srcF32; double *srcF64; u8 *src1Bit; - u16 *srcF16; + u16 *srcU16; assert( pFrom->dims == pTo->dims ); assert( pFrom->type != pTo->type ); @@ -857,14 +955,24 @@ static void vectorConvertToF8(const Vector *pFrom, Vector *pTo){ dst[i] = clip(((((src1Bit[i / 8] >> (i & 7)) & 1) ? +1 : -1) - shift) / alpha, 0, 255); } }else if( pFrom->type == VECTOR_TYPE_FLOAT16 ){ - srcF16 = pFrom->data; + srcU16 = pFrom->data; + for(i = 0; i < pFrom->dims; i++){ + MINMAX(i, vectorF16ToFloat(srcU16[i]), minF, maxF); + } + shift = minF; + alpha = (maxF - minF) / 255; + for(i = 0; i < pFrom->dims; i++){ + dst[i] = clip((vectorF16ToFloat(srcU16[i]) - shift) / alpha, 0, 255); + } + }else if( pFrom->type == VECTOR_TYPE_FLOATB16 ){ + srcU16 = pFrom->data; for(i = 0; i < pFrom->dims; i++){ - MINMAX(i, vectorF16ToFloat(srcF16[i]), minF, maxF); + MINMAX(i, vectorFB16ToFloat(srcU16[i]), minF, maxF); } shift = minF; alpha = (maxF - minF) / 255; for(i = 0; i < pFrom->dims; i++){ - dst[i] = clip((vectorF16ToFloat(srcF16[i]) - shift) / alpha, 0, 255); + dst[i] = clip((vectorFB16ToFloat(srcU16[i]) - shift) / alpha, 0, 255); } }else{ assert( 0 ); @@ -893,6 +1001,8 @@ void vectorConvert(const Vector *pFrom, Vector *pTo){ vectorConvertFromF8(pFrom, pTo); }else if( pFrom->type == VECTOR_TYPE_FLOAT16 ){ vectorConvertFromF16(pFrom, pTo); + }else if( pFrom->type == VECTOR_TYPE_FLOATB16 ){ + vectorConvertFromFB16(pFrom, pTo); }else{ assert( 0 ); } @@ -985,6 +1095,14 @@ static void vector16Func( vectorFuncHintedType(context, argc, argv, VECTOR_TYPE_FLOAT16); } +static void vectorb16Func( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + vectorFuncHintedType(context, argc, argv, VECTOR_TYPE_FLOATB16); +} + static void vector1BitFunc( sqlite3_context *context, int argc, @@ -1144,6 +1262,7 @@ void sqlite3RegisterVectorFunctions(void){ FUNCTION(vector1bit, 1, 0, 0, vector1BitFunc), FUNCTION(vector8, 1, 0, 0, vector8Func), FUNCTION(vector16, 1, 0, 0, vector16Func), + FUNCTION(vectorb16, 1, 0, 0, vectorb16Func), FUNCTION(vector_extract, 1, 0, 0, vectorExtractFunc), FUNCTION(vector_distance_cos, 2, 0, 0, vectorDistanceCosFunc), FUNCTION(vector_distance_l2, 2, 0, 0, vectorDistanceL2Func), diff --git a/libsql-sqlite3/src/vectorIndex.c b/libsql-sqlite3/src/vectorIndex.c index f1af0726ee..5bf912af1d 100644 --- a/libsql-sqlite3/src/vectorIndex.c +++ b/libsql-sqlite3/src/vectorIndex.c @@ -387,6 +387,8 @@ static struct VectorColumnType VECTOR_COLUMN_TYPES[] = { { "F8_BLOB", VECTOR_TYPE_FLOAT8 }, { "FLOAT16", VECTOR_TYPE_FLOAT16 }, { "F16_BLOB", VECTOR_TYPE_FLOAT16 }, + { "FLOATB16", VECTOR_TYPE_FLOATB16 }, + { "FB16_BLOB", VECTOR_TYPE_FLOATB16 }, }; /* @@ -408,6 +410,7 @@ static struct VectorParamName VECTOR_PARAM_NAMES[] = { { "compress_neighbors", VECTOR_COMPRESS_NEIGHBORS_PARAM_ID, 0, "float1bit", VECTOR_TYPE_FLOAT1BIT }, { "compress_neighbors", VECTOR_COMPRESS_NEIGHBORS_PARAM_ID, 0, "float8", VECTOR_TYPE_FLOAT8 }, { "compress_neighbors", VECTOR_COMPRESS_NEIGHBORS_PARAM_ID, 0, "float16", VECTOR_TYPE_FLOAT16 }, + { "compress_neighbors", VECTOR_COMPRESS_NEIGHBORS_PARAM_ID, 0, "floatb16", VECTOR_TYPE_FLOATB16 }, { "compress_neighbors", VECTOR_COMPRESS_NEIGHBORS_PARAM_ID, 0, "float32", VECTOR_TYPE_FLOAT32 }, { "alpha", VECTOR_PRUNING_ALPHA_PARAM_ID, 2, 0, 0 }, { "search_l", VECTOR_SEARCH_L_PARAM_ID, 1, 0, 0 }, diff --git a/libsql-sqlite3/src/vectorInt.h b/libsql-sqlite3/src/vectorInt.h index 7d3b3e79e8..81811e9faa 100644 --- a/libsql-sqlite3/src/vectorInt.h +++ b/libsql-sqlite3/src/vectorInt.h @@ -54,6 +54,7 @@ typedef u32 VectorDims; #define VECTOR_TYPE_FLOAT1BIT 3 #define VECTOR_TYPE_FLOAT8 4 #define VECTOR_TYPE_FLOAT16 5 +#define VECTOR_TYPE_FLOATB16 6 #define VECTOR_FLAGS_STATIC 1 @@ -82,6 +83,7 @@ void vectorInit(Vector *, VectorType, VectorDims, void *); void vectorDump (const Vector *v); void vectorF8Dump (const Vector *v); void vectorF16Dump (const Vector *v); +void vectorFB16Dump(const Vector *v); void vectorF32Dump (const Vector *v); void vectorF64Dump (const Vector *v); void vector1BitDump(const Vector *v); @@ -102,6 +104,7 @@ void vectorF64MarshalToText(sqlite3_context *, const Vector *); void vectorSerializeToBlob (const Vector *, unsigned char *, size_t); void vectorF8SerializeToBlob (const Vector *, unsigned char *, size_t); void vectorF16SerializeToBlob (const Vector *, unsigned char *, size_t); +void vectorFB16SerializeToBlob(const Vector *, unsigned char *, size_t); void vectorF32SerializeToBlob (const Vector *, unsigned char *, size_t); void vectorF64SerializeToBlob (const Vector *, unsigned char *, size_t); void vector1BitSerializeToBlob(const Vector *, unsigned char *, size_t); @@ -112,6 +115,7 @@ void vector1BitSerializeToBlob(const Vector *, unsigned char *, size_t); float vectorDistanceCos (const Vector *, const Vector *); float vectorF8DistanceCos (const Vector *, const Vector *); float vectorF16DistanceCos (const Vector *, const Vector *); +float vectorFB16DistanceCos(const Vector *, const Vector *); float vectorF32DistanceCos (const Vector *, const Vector *); double vectorF64DistanceCos(const Vector *, const Vector *); @@ -126,6 +130,7 @@ int vector1BitDistanceHamming(const Vector *, const Vector *); float vectorDistanceL2 (const Vector *, const Vector *); float vectorF8DistanceL2 (const Vector *, const Vector *); float vectorF16DistanceL2 (const Vector *, const Vector *); +float vectorFB16DistanceL2(const Vector *, const Vector *); float vectorF32DistanceL2 (const Vector *, const Vector *); double vectorF64DistanceL2(const Vector *, const Vector *); @@ -143,6 +148,7 @@ int vectorParseSqliteBlobWithType(sqlite3_value *, Vector *, char **); void vectorF8DeserializeFromBlob (Vector *, const unsigned char *, size_t); void vectorF16DeserializeFromBlob (Vector *, const unsigned char *, size_t); +void vectorFB16DeserializeFromBlob(Vector *, const unsigned char *, size_t); void vectorF32DeserializeFromBlob (Vector *, const unsigned char *, size_t); void vectorF64DeserializeFromBlob (Vector *, const unsigned char *, size_t); void vector1BitDeserializeFromBlob(Vector *, const unsigned char *, size_t); @@ -153,6 +159,9 @@ void vectorInitFromBlob(Vector *, const unsigned char *, size_t); u16 vectorF16FromFloat(float); float vectorF16ToFloat(u16); +u16 vectorFB16FromFloat(float); +float vectorFB16ToFloat(u16); + void vectorConvert(const Vector *, Vector *); /* Detect type and dimension of vector provided with first parameter of sqlite3_value * type */ diff --git a/libsql-sqlite3/src/vectorfloat16.c b/libsql-sqlite3/src/vectorfloat16.c index cde769b11a..f0d2d35511 100644 --- a/libsql-sqlite3/src/vectorfloat16.c +++ b/libsql-sqlite3/src/vectorfloat16.c @@ -128,8 +128,6 @@ void vectorF16SerializeToBlob( unsigned char *pBlob, size_t nBlobSize ){ - float alpha, shift; - assert( pVector->type == VECTOR_TYPE_FLOAT16 ); assert( pVector->dims <= MAX_VECTOR_SZ ); assert( nBlobSize >= vectorDataSize(pVector->type, pVector->dims) ); diff --git a/libsql-sqlite3/src/vectorfloatb16.c b/libsql-sqlite3/src/vectorfloatb16.c new file mode 100644 index 0000000000..41b0bff557 --- /dev/null +++ b/libsql-sqlite3/src/vectorfloatb16.c @@ -0,0 +1,128 @@ +/* +** 2024-07-04 +** +** Copyright 2024 the libSQL authors +** +** Permission is hereby granted, free of charge, to any person obtaining a copy of +** this software and associated documentation files (the "Software"), to deal in +** the Software without restriction, including without limitation the rights to +** use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +** the Software, and to permit persons to whom the Software is furnished to do so, +** subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in all +** copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +** FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +** COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +** IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +** CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +** +****************************************************************************** +** +** 16-bit brain floating point vector format utilities. +** +** See https://en.wikipedia.org/wiki/Bfloat16_floating-point_format +*/ +#ifndef SQLITE_OMIT_VECTOR +#include "sqliteInt.h" + +#include "vectorInt.h" + +#include + +/************************************************************************** +** Utility routines for vector serialization and deserialization +**************************************************************************/ + +float vectorFB16ToFloat(u16 f16){ + u32 f32 = (u32)f16 << 16; + return *((float*)&f32); +} + +u16 vectorFB16FromFloat(float f){ + u32 f32 = *((u32*)&f); + return (u16)(f32 >> 16); +} + +void vectorFB16Dump(const Vector *pVec){ + u16 *elems = pVec->data; + unsigned i; + + assert( pVec->type == VECTOR_TYPE_FLOATB16 ); + + printf("fb16: ["); + for(i = 0; i < pVec->dims; i++){ + printf("%s%f", i == 0 ? "" : ", ", vectorFB16ToFloat(elems[i])); + } + printf("]\n"); +} + +void vectorFB16SerializeToBlob( + const Vector *pVector, + unsigned char *pBlob, + size_t nBlobSize +){ + assert( pVector->type == VECTOR_TYPE_FLOATB16 ); + assert( pVector->dims <= MAX_VECTOR_SZ ); + assert( nBlobSize >= vectorDataSize(pVector->type, pVector->dims) ); + + memcpy(pBlob, pVector->data, pVector->dims * sizeof(u16)); +} + +float vectorFB16DistanceCos(const Vector *v1, const Vector *v2){ + int i; + float dot = 0, norm1 = 0, norm2 = 0; + float value1, value2; + u16 *data1 = v1->data, *data2 = v2->data; + + assert( v1->dims == v2->dims ); + assert( v1->type == VECTOR_TYPE_FLOATB16 ); + assert( v2->type == VECTOR_TYPE_FLOATB16 ); + + for(i = 0; i < v1->dims; i++){ + value1 = vectorFB16ToFloat(data1[i]); + value2 = vectorFB16ToFloat(data2[i]); + dot += value1*value2; + norm1 += value1*value1; + norm2 += value2*value2; + } + + return 1.0 - (dot / sqrt(norm1 * norm2)); +} + +float vectorFB16DistanceL2(const Vector *v1, const Vector *v2){ + int i; + float sum = 0; + float value1, value2; + u16 *data1 = v1->data, *data2 = v2->data; + + assert( v1->dims == v2->dims ); + assert( v1->type == VECTOR_TYPE_FLOATB16 ); + assert( v2->type == VECTOR_TYPE_FLOATB16 ); + + for(i = 0; i < v1->dims; i++){ + value1 = vectorFB16ToFloat(data1[i]); + value2 = vectorFB16ToFloat(data2[i]); + float d = (value1 - value2); + sum += d*d; + } + return sqrt(sum); +} + +void vectorFB16DeserializeFromBlob( + Vector *pVector, + const unsigned char *pBlob, + size_t nBlobSize +){ + assert( pVector->type == VECTOR_TYPE_FLOATB16 ); + assert( 0 <= pVector->dims && pVector->dims <= MAX_VECTOR_SZ ); + assert( nBlobSize >= vectorDataSize(pVector->type, pVector->dims) ); + + memcpy((u8*)pVector->data, (u8*)pBlob, pVector->dims * sizeof(u16)); +} + +#endif /* !defined(SQLITE_OMIT_VECTOR) */ + diff --git a/libsql-sqlite3/test/libsql_vector.test b/libsql-sqlite3/test/libsql_vector.test index 689310af39..793358e068 100644 --- a/libsql-sqlite3/test/libsql_vector.test +++ b/libsql-sqlite3/test/libsql_vector.test @@ -55,23 +55,29 @@ do_execsql_test vector-1-func-valid { SELECT vector_distance_cos(vector1bit('[10,-10]'), vector1bit('[20,-2]')); SELECT vector_distance_cos(vector8('[10,-10]'), vector8('[10,-10]')); + SELECT vector_distance_cos(vector16('[10,-10]'), vector16('[10,-10]')); + SELECT vector_distance_cos(vectorb16('[10,-10]'), vectorb16('[10,-10]')); SELECT vector_distance_cos(vector32('[10,-10]'), vector32('[10,-10]')); SELECT vector_distance_cos(vector8('[-21,-31,0,2,2.1,2.2,105]'), vector8('[-20,-30,0,1,1.1,1.2,100]')); SELECT vector_distance_cos(vector16('[-21,-31,0,2,2.1,2.2,105]'), vector16('[-20,-30,0,1,1.1,1.2,100]')); + SELECT vector_distance_cos(vectorb16('[-21,-31,0,2,2.1,2.2,105]'), vectorb16('[-20,-30,0,1,1.1,1.2,100]')); SELECT vector_distance_cos(vector32('[-21,-31,0,2,2.1,2.2,105]'), vector32('[-20,-30,0,1,1.1,1.2,100]')); SELECT vector_distance_cos(vector8('[-20,-30,0,1,1.1,1.2,100]'), vector8('[-20,-30,0,1,1.1,1.2,10000]')); SELECT vector_distance_cos(vector16('[-20,-30,0,1,1.1,1.2,100]'), vector16('[-20,-30,0,1,1.1,1.2,10000]')); + SELECT vector_distance_cos(vectorb16('[-20,-30,0,1,1.1,1.2,100]'), vectorb16('[-20,-30,0,1,1.1,1.2,10000]')); SELECT vector_distance_cos(vector32('[-20,-30,0,1,1.1,1.2,100]'), vector32('[-20,-30,0,1,1.1,1.2,10000]')); SELECT vector_distance_cos(vector8('[-1000000,1000000]'), vector8('[1000000,-1000000]')); SELECT vector_distance_cos(vector16('[-1000000,1000000]'), vector16('[1000000,-1000000]')); + SELECT vector_distance_cos(vectorb16('[-1000000,1000000]'), vectorb16('[1000000,-1000000]')); SELECT vector_distance_cos(vector32('[-1000000,1000000]'), vector32('[1000000,-1000000]')); SELECT vector_distance_l2(vector('[1,2,2,3,4,1,5]'), vector('[2,3,1,-1,2,4,5]')); SELECT vector_distance_l2(vector8('[1,2,2,3,4,1,5]'), vector8('[2,3,1,-1,2,4,5]')); SELECT vector_distance_l2(vector16('[1,2,2,3,4,1,5]'), vector16('[2,3,1,-1,2,4,5]')); + SELECT vector_distance_l2(vectorb16('[1,2,2,3,4,1,5]'), vectorb16('[2,3,1,-1,2,4,5]')); } { {[]} {[]} @@ -91,12 +97,12 @@ do_execsql_test vector-1-func-valid { {1.0} {0.0} - {-6.10352568486405e-09} {0.0} - {0.000111237335659098} {0.000117182018584572} {0.000117244853754528} - {0.0576796568930149} {0.0582110174000263} {0.0582110174000263} - {2.0} {} {2.0} + {-6.10352568486405e-09} {0.0} {0.0} {0.0} + {0.000111237335659098} {0.000117182018584572} {0.000116735325718764} {0.000117244853754528} + {0.0576796568930149} {0.0582110174000263} {0.0582080148160458} {0.0582110174000263} + {2.0} {} {2.0} {2.0} - {5.65685415267944} {5.65413522720337} {5.65685415267944} + {5.65685415267944} {5.65413522720337} {5.65685415267944} {5.65685415267944} } do_execsql_test vector-1-conversion-simple { @@ -112,11 +118,13 @@ do_execsql_test vector-1-conversion-to-f32 { SELECT vector_extract(vector32(vector32('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))), hex(vector32(vector32('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))); SELECT vector_extract(vector32(vector64('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))), hex(vector32(vector64('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))); SELECT vector_extract(vector32(vector16('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))), hex(vector32(vector16('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))); + SELECT vector_extract(vector32(vectorb16('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))), hex(vector32(vectorb16('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))); } { {[-1,-1,1,-1,1,-1,1]} 000080BF000080BF0000803F000080BF0000803F000080BF0000803F {[-1e-06,0,Inf,-1e+10,1e-10,0,1.5]} BD3786B5000000000000807FF90215D0FFE6DB2E000000000000C03F {[-1e-06,0,Inf,-1e+10,1e-10,0,1.5]} BD3786B5000000000000807FF90215D0FFE6DB2E000000000000C03F {[-1.01328e-06,0,Inf,-Inf,0,0,1.5]} 000088B5000000000000807F000080FF00000000000000000000C03F + {[-9.98378e-07,0,Inf,-9.99922e+09,9.95897e-11,0,1.5]} 000086B5000000000000807F000015D00000DB2E000000000000C03F } do_execsql_test vector-1-conversion-to-f64 { @@ -124,11 +132,13 @@ do_execsql_test vector-1-conversion-to-f64 { SELECT vector_extract(vector64(vector32('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))), hex(vector64(vector32('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))); SELECT vector_extract(vector64(vector64('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))), hex(vector64(vector64('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))); SELECT vector_extract(vector64(vector16('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))), hex(vector64(vector16('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))); + SELECT vector_extract(vector64(vectorb16('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))), hex(vector64(vectorb16('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))); } { {[-1,-1,1,-1,1,-1,1]} 000000000000F0BF000000000000F0BF000000000000F03F000000000000F0BF000000000000F03F000000000000F0BF000000000000F03F02 {[-1e-06,0,Inf,-1e+10,1e-10,0,1.5]} 000000A0F7C6B0BE0000000000000000000000000000F07F000000205FA002C2000000E0DF7CDB3D0000000000000000000000000000F83F02 {[-1e-06,1e-100,1e+100,-1e+10,1e-10,0,1.5]} 8DEDB5A0F7C6B0BE30058EE42EFF2B2B7DC39425AD49B254000000205FA002C2BBBDD7D9DF7CDB3D0000000000000000000000000000F83F02 {[-1.01328e-06,0,Inf,-Inf,0,0,1.5]} 000000000000B1BE0000000000000000000000000000F07F000000000000F0FF00000000000000000000000000000000000000000000F83F02 + {[-9.98378e-07,0,Inf,-9.99922e+09,9.95897e-11,0,1.5]} 0000000000C0B0BE0000000000000000000000000000F07F0000000000A002C2000000000060DB3D0000000000000000000000000000F83F02 } do_execsql_test vector-1-conversion-to-f1bit { @@ -136,11 +146,13 @@ do_execsql_test vector-1-conversion-to-f1bit { SELECT vector_extract(vector1bit(vector32('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))), hex(vector1bit(vector32('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))); SELECT vector_extract(vector1bit(vector64('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))), hex(vector1bit(vector64('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))); SELECT vector_extract(vector1bit(vector16('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))), hex(vector1bit(vector16('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))); + SELECT vector_extract(vector1bit(vectorb16('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))), hex(vector1bit(vectorb16('[-0.000001,1e-100,1e100,-1e10,1e-10,0,1.5]'))); } { {[-1,-1,1,-1,1,-1,1]} 540903 {[-1,-1,1,-1,1,-1,1]} 540903 {[-1,1,1,-1,1,-1,1]} 560903 {[-1,-1,1,-1,-1,-1,1]} 440903 + {[-1,-1,1,-1,1,-1,1]} 540903 } do_execsql_test vector-1-conversion-to-f16 { @@ -148,11 +160,13 @@ do_execsql_test vector-1-conversion-to-f16 { SELECT vector_extract(vector16(vector32('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))), hex(vector16(vector32('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))); SELECT vector_extract(vector16(vector64('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))), hex(vector16(vector64('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))); SELECT vector_extract(vector16(vector16('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))), hex(vector16(vector16('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))); + SELECT vector_extract(vector16(vectorb16('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))), hex(vector16(vectorb16('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))); } { {[-1,-1,1,1,1,1,1,1,1,1]} 00BC00BC003C003C003C003C003C003C003C003C05 {[-20,-35.4375,1,1.5,2,3,10,100,105,110]} 00CD6ED0003C003E00400042004940569056E05605 {[-20,-35.4375,1,1.5,2,3,10,100,105,110]} 00CD6ED0003C003E00400042004940569056E05605 {[-20,-35.4375,1,1.5,2,3,10,100,105,110]} 00CD6ED0003C003E00400042004940569056E05605 + {[-20,-35.25,1,1.5,2,3,10,100,105,110]} 00CD68D0003C003E00400042004940569056E05605 } do_execsql_test vector-1-conversion-f8 { @@ -163,11 +177,13 @@ do_execsql_test vector-1-conversion-f8 { SELECT vector_extract(vector8(vector32('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))), hex(vector8(vector32('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))); SELECT vector_extract(vector8(vector64('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))), hex(vector8(vector64('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))); SELECT vector_extract(vector8(vector16('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))), hex(vector8(vector16('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))); + SELECT vector_extract(vector8(vectorb16('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))), hex(vector8(vectorb16('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))); SELECT vector_extract(vector1bit(vector8('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))), hex(vector1bit(vector8('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))); SELECT vector_extract(vector32(vector8('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))), hex(vector32(vector8('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))); SELECT vector_extract(vector64(vector8('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))), hex(vector64(vector8('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))); SELECT vector_extract(vector16(vector8('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))), hex(vector16(vector8('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))); + SELECT vector_extract(vectorb16(vector8('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))), hex(vectorb16(vector8('[-20,-35.44,1,1.5,2,3,10,100,105,110]'))); } { {[-20.0405,-35.44,1.06259,1.63295,2.2033,2.77365,10.1882,99.7337,104.867,110]} 1B004041424350EDF6FF0000A702123F8FC20DC2000204 @@ -176,11 +192,13 @@ do_execsql_test vector-1-conversion-f8 { {[-20.0405,-35.44,1.06259,1.63295,2.2033,2.77365,10.1882,99.7337,104.867,110]} 1B004041424350EDF6FF0000A702123F8FC20DC2000204 {[-20.0405,-35.44,1.06259,1.63295,2.2033,2.77365,10.1882,99.7337,104.867,110]} 1B004041424350EDF6FF0000A702123F8FC20DC2000204 {[-20.0382,-35.4375,1.06446,1.6348,2.20515,2.77549,10.1899,99.7338,104.867,110]} 1B004041424350EDF6FF00000202123F00C00DC2000204 + {[-19.8706,-35.25,1.2049,1.77451,1.77451,2.91373,9.74902,99.7471,104.874,110]} 1B00404141434FEDF6FF0000D2D1113F00000DC2000204 {[-1,-1,1,1,1,1,1,1,1,1]} FC03001603 {[-20.0405,-35.44,1.06259,1.63295,2.2033,2.77365,10.1882,99.7337,104.867,110]} E152A0C18FC20DC20003883F6004D13FD0020D408083314008032341A277C742D0BBD1420000DC42 {[-20.0405,-35.44,1.06259,1.63295,2.2033,2.77365,10.1882,99.7337,104.867,110]} 000000205C0A34C0000000E051B841C0000000006000F13F000000008C20FA3F000000005AA001400000000070300640000000006160244000000040F4EE5840000000007A375A400000000000805B4002 {[-20.0469,-35.4375,1.0625,1.63281,2.20313,2.77344,10.1875,99.75,104.875,110]} 03CD6ED0403C883E68408C4118493C568E56E05605 + {[-20,-35.25,1.0625,1.63281,2.20313,2.76563,10.1875,99.5,104.5,110]} A0C10DC2883FD13F0D4031402341C742D142DC4206 } proc error_messages {sql} { diff --git a/libsql-sqlite3/test/libsql_vector_index.test b/libsql-sqlite3/test/libsql_vector_index.test index 0b72d1ec46..95a26b3d0a 100644 --- a/libsql-sqlite3/test/libsql_vector_index.test +++ b/libsql-sqlite3/test/libsql_vector_index.test @@ -375,6 +375,15 @@ do_execsql_test vector-f32-compress-f16 { SELECT * FROM vector_top_k('t_f32_f16_idx', vector('[10,-10,-20,20]'), 4); } {3 1 2} +do_execsql_test vector-f32-compress-bf16 { + CREATE TABLE t_f32_bf16( v FLOAT32(4) ); + CREATE INDEX t_f32_bf16_idx ON t_f32_bf16( libsql_vector_idx(v, 'compress_neighbors=floatb16') ); + INSERT INTO t_f32_bf16 VALUES ( vector('[1,-1,1,-1]') ); + INSERT INTO t_f32_bf16 VALUES ( vector('[-1,1,1,-1]') ); + INSERT INTO t_f32_bf16 VALUES ( vector('[1,-1,-1,1]') ); + SELECT * FROM vector_top_k('t_f32_bf16_idx', vector('[10,-10,-20,20]'), 4); +} {3 1 2} + do_execsql_test vector-f8 { CREATE TABLE t_f8( v FLOAT8(4) ); CREATE INDEX t_f8_idx ON t_f8( libsql_vector_idx(v) ); @@ -393,6 +402,15 @@ do_execsql_test vector-f16 { SELECT * FROM vector_top_k('t_f16_idx', vector16('[10,-10,-20,20]'), 4); } {3 1 2} +do_execsql_test vector-bf16 { + CREATE TABLE t_bf16( v FLOATB16(4) ); + CREATE INDEX t_bf16_idx ON t_bf16( libsql_vector_idx(v) ); + INSERT INTO t_bf16 VALUES ( vectorb16('[1,-1,1,-1]') ); + INSERT INTO t_bf16 VALUES ( vectorb16('[-1,1,1,-1]') ); + INSERT INTO t_bf16 VALUES ( vectorb16('[1,-1,-1,1]') ); + SELECT * FROM vector_top_k('t_bf16_idx', vectorb16('[10,-10,-20,20]'), 4); +} {3 1 2} + do_execsql_test vector-f8-compress-1bit { CREATE TABLE t_f8_1bit( v FLOAT8(4) ); CREATE INDEX t_f8_1bit_idx ON t_f8_1bit( libsql_vector_idx(v, 'compress_neighbors=float1bit') ); @@ -404,13 +422,22 @@ do_execsql_test vector-f8-compress-1bit { do_execsql_test vector-f16-compress-1bit { CREATE TABLE t_f16_1bit( v FLOAT16(4) ); - CREATE INDEX t_f16_1bit_idx ON t_f16_1bit( libsql_vector_idx(v, 'compress_neighbors=float16') ); + CREATE INDEX t_f16_1bit_idx ON t_f16_1bit( libsql_vector_idx(v, 'compress_neighbors=float1bit') ); INSERT INTO t_f16_1bit VALUES ( vector16('[1,-1,1,-1]') ); INSERT INTO t_f16_1bit VALUES ( vector16('[-1,1,1,-1]') ); INSERT INTO t_f16_1bit VALUES ( vector16('[1,-1,-1,1]') ); SELECT * FROM vector_top_k('t_f16_1bit_idx', vector16('[10,-10,-20,20]'), 4); } {3 1 2} +do_execsql_test vector-bf16-compress-1bit { + CREATE TABLE t_bf16_1bit( v FLOATB16(4) ); + CREATE INDEX t_bf16_1bit_idx ON t_bf16_1bit( libsql_vector_idx(v, 'compress_neighbors=float1bit') ); + INSERT INTO t_bf16_1bit VALUES ( vectorb16('[1,-1,1,-1]') ); + INSERT INTO t_bf16_1bit VALUES ( vectorb16('[-1,1,1,-1]') ); + INSERT INTO t_bf16_1bit VALUES ( vectorb16('[1,-1,-1,1]') ); + SELECT * FROM vector_top_k('t_bf16_1bit_idx', vectorb16('[10,-10,-20,20]'), 4); +} {3 1 2} + proc error_messages {sql} { set ret "" catch { diff --git a/libsql-sqlite3/tool/mksqlite3c.tcl b/libsql-sqlite3/tool/mksqlite3c.tcl index 33a7708e92..38aa671356 100644 --- a/libsql-sqlite3/tool/mksqlite3c.tcl +++ b/libsql-sqlite3/tool/mksqlite3c.tcl @@ -474,6 +474,7 @@ set flist { vectorfloat64.c vectorfloat8.c vectorfloat16.c + vectorfloatb16.c vectorIndex.c vectorvtab.c rtree.c