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 },