/**
* Cosine similarity between two Float32Arrays.
* Returns value in [-1, 1]. Higher = more similar.
*/
export function cosineSimilarity(a: Float32Array, b: Float32Array): number {
if (a.length !== b.length) {
throw new Error(`Dimension mismatch: ${a.length} vs ${b.length}`);
}
let dot = 0;
let normA = 0;
let normB = 0;
for (let i = 0; i < a.length; i++) {
dot += a[i] * b[i];
normA += a[i] * a[i];
normB += b[i] * b[i];
}
const denom = Math.sqrt(normA) * Math.sqrt(normB);
if (denom === 0) return 0;
return dot / denom;
}
/** Convert Float32Array to Buffer for SQLite BLOB storage */
export function embeddingToBuffer(embedding: Float32Array): Buffer {
return Buffer.from(embedding.buffer, embedding.byteOffset, embedding.byteLength);
}
/** Convert SQLite BLOB Buffer back to Float32Array */
export function bufferToEmbedding(buf: Buffer): Float32Array {
const ab = new ArrayBuffer(buf.length);
const view = new Uint8Array(ab);
for (let i = 0; i < buf.length; i++) {
view[i] = buf[i];
}
return new Float32Array(ab);
}