/**
 * Embedding quantization — ADR-121 Phase 3.
 *
 * Two opt-in quantization paths:
 *
 *   1. **int8** — per-vector linear quantization. 4× memory
 *      reduction (float32 → int8). Works with streaming inserts
 *      because each vector encodes independently. Used by
 *      `SearchableEmbeddingCache` when `quantize: 'int8'` is set.
 *
 *   2. **RaBitQ** — 1-bit-per-dimension quantization via
 *      `@ruvector/rabitq-wasm`. 32× memory reduction. Build-once
 *      batch API (not streaming) — exposed here as the
 *      `RabitqSnapshot` class for callers that want to compress
 *      a fixed corpus and query it. Recall recovered via an
 *      exact-L2² rerank pool (default 20× the requested k).
 *
 * Each path is opt-in + has a measurable acceptance gate:
 *   int8     → ≥0.98 cosine-similarity recall after dequantize
 *   RaBitQ   → ≥0.95 recall after rerank, 32× memory reduction
 *
 * For int8 the recall acceptance is measured per-vector
 * (cosine(original, dequant(quant(original)))). For RaBitQ
 * recall is measured against the top-k from a brute-force baseline.
 */
import type { CacheSearchHit } from './searchable-embedding-cache.js';
/**
 * Encoded int8 vector: the int8 buffer + the scale factor needed to
 * dequantize. Scale is per-vector (each vector's max-abs sets its own
 * scale) — that's the standard approach for embedding quantization
 * and preserves recall best for unit-normalized vectors.
 */
export interface Int8EncodedVector {
    /** Int8 buffer, same length as the source float32 vector. */
    readonly bytes: Int8Array;
    /** Scale factor: float32 ≈ int8 * scale. */
    readonly scale: number;
}
/**
 * Encode a float32 vector as int8. Returns the byte buffer + a per-vector
 * scale that maps int8 back to ~float32 on decode.
 *
 * Algorithm: find max-abs value, scale so max-abs maps to 127, round
 * to nearest int8. This is min-max scaling clamped to [-127, 127] and
 * is the cheapest path that preserves direction (which is what cosine
 * similarity cares about for unit-normalized embeddings).
 */
export declare function int8Encode(vec: Float32Array): Int8EncodedVector;
/**
 * Decode an int8-encoded vector back to float32. Round-trips with
 * recall ≥0.98 on unit-normalized vectors (the ADR-121 Phase 3 gate).
 */
export declare function int8Decode(encoded: Int8EncodedVector): Float32Array;
/**
 * Measure round-trip recall for int8 encoding on a corpus.
 * Recall here = mean cosine similarity between `vec` and
 * `int8Decode(int8Encode(vec))` across all corpus vectors.
 *
 * Used by the CI benchmark to assert the ADR-121 Phase 3 acceptance
 * gate (≥0.98 recall for int8).
 */
export declare function measureInt8RoundTripRecall(corpus: Float32Array[]): {
    meanRecall: number;
    minRecall: number;
    maxRecall: number;
    count: number;
};
export interface RabitqSnapshotOptions {
    /** Embedding dimension. Required. */
    readonly dimension: number;
    /** Random rotation seed (default 0n) — same seed = bit-identical codes. */
    readonly seed?: bigint;
    /** Multiplier on `k` for the exact-L2² rerank pool (default 20). */
    readonly rerankFactor?: number;
}
/**
 * Snapshot result — what callers get back from `search`. `id` is the
 * caller-supplied key (string), preserved through the build/search
 * round-trip via the snapshot's internal id-map.
 */
export interface RabitqSnapshotHit {
    readonly id: string;
    /** Approximate L2² distance after RaBitQ rerank. */
    readonly distance: number;
    /** Original vector (preserved by the snapshot for downstream use). */
    readonly vector: Float32Array;
}
/**
 * Batch RaBitQ snapshot — compress a corpus of vectors once, then
 * query against the 1-bit index with exact-L2² rerank for recall.
 *
 * Lifecycle:
 *   const snap = await RabitqSnapshot.build(entries, { dimension: 384 });
 *   const hits = await snap.search(queryVec, 10);
 *   snap.dispose();
 *
 * Memory profile:
 *   raw  = N × dim × 4 bytes (float32)
 *   rabitq = N × dim / 8 bytes (1 bit per dim) → 32× smaller
 * (Plus a per-snapshot id-map for string → numeric position; small.)
 *
 * If `@ruvector/rabitq-wasm` isn't installed, `build` throws a
 * clear named error so callers know which optional peer to install.
 */
export declare class RabitqSnapshot {
    private readonly index;
    private readonly idMap;
    private readonly vectors;
    private disposed;
    private constructor();
    static build(entries: Array<{
        id: string;
        vector: Float32Array;
    }>, options: RabitqSnapshotOptions): Promise<RabitqSnapshot>;
    /** Query the snapshot for the `k` nearest neighbors of `query`. */
    search(query: Float32Array, k: number): Promise<RabitqSnapshotHit[]>;
    /** Number of vectors in the snapshot. */
    get size(): number;
    /**
     * Release the WASM index. Idempotent. Memory held by the JS-side
     * id-map and vectors is GC'd normally.
     */
    dispose(): void;
}
/**
 * Measure the *theoretical* memory reduction for a corpus when
 * encoded with RaBitQ vs raw float32. Returns the byte counts so
 * callers can publish the metric to the tracker. Doesn't actually
 * build the index (cheap to compute, deterministic).
 */
export declare function rabitqMemoryReduction(corpusSize: number, dimension: number): {
    rawBytes: number;
    rabitqBytes: number;
    reductionFactor: number;
};
export type { CacheSearchHit };
//# sourceMappingURL=quantization.d.ts.map