// engine/vector-store/similarity.ts — Similarity metrics for vector comparison.
// SPEC-075: cosine, jaccard, combined similarity functions.
/**
 * Compute cosine similarity between two vectors.
 * Returns a value in [0, 1] where 1 means identical direction.
 */
export function cosineSimilarity(a, b) {
    if (a.length === 0 || b.length === 0) {
        return 0;
    }
    if (a.length !== b.length) {
        return 0;
    }
    let dot = 0;
    let normA = 0;
    let normB = 0;
    for (let i = 0; i < a.length; i++) {
        /* v8 ignore start -- noUncheckedIndexedAccess: i always within bounds */
        const ai = a[i] ?? 0;
        const bi = b[i] ?? 0;
        /* v8 ignore stop */
        dot += ai * bi;
        normA += ai * ai;
        normB += bi * bi;
    }
    const denom = Math.sqrt(normA) * Math.sqrt(normB);
    if (denom === 0) {
        return 0;
    }
    return dot / denom;
}
/**
 * Compute Jaccard similarity between two binary-ish vectors.
 * Treats non-zero values as "present". Returns value in [0, 1].
 */
export function jaccardSimilarity(a, b) {
    if (a.length === 0 || b.length === 0) {
        return 0;
    }
    if (a.length !== b.length) {
        return 0;
    }
    let intersection = 0;
    let union = 0;
    for (let i = 0; i < a.length; i++) {
        /* v8 ignore start -- noUncheckedIndexedAccess: i always within bounds */
        const aPresent = (a[i] ?? 0) !== 0;
        const bPresent = (b[i] ?? 0) !== 0;
        /* v8 ignore stop */
        if (aPresent || bPresent) {
            union++;
            if (aPresent && bPresent) {
                intersection++;
            }
        }
    }
    if (union === 0) {
        return 0;
    }
    return intersection / union;
}
/**
 * Combined similarity: weighted average of cosine and jaccard.
 * Default weights: 0.8 cosine + 0.2 jaccard.
 */
export function combinedSimilarity(a, b, cosineWeight = 0.8) {
    const cos = cosineSimilarity(a, b);
    const jac = jaccardSimilarity(a, b);
    return cos * cosineWeight + jac * (1 - cosineWeight);
}
/**
 * Normalize a vector to unit length (L2 norm).
 * Returns a new array. If the vector is zero, returns a zero vector.
 */
export function normalizeVector(v) {
    let norm = 0;
    for (const val of v) {
        norm += val * val;
    }
    norm = Math.sqrt(norm);
    if (norm === 0) {
        return v.map(() => 0);
    }
    return v.map((val) => val / norm);
}
//# sourceMappingURL=similarity.js.map