selene-db-core 1.3.0

Foundation types for the selene-db ISO/IEC 39075:2024 GQL property graph engine.
Documentation
use super::*;

#[test]
fn bit_width_validates_range() {
    assert_eq!(TurboQuantBitWidth::new(2).unwrap().levels(), 4);
    assert_eq!(TurboQuantBitWidth::new(4).unwrap().max_code(), 15);
    assert!(matches!(
        TurboQuantBitWidth::new(1),
        Err(TurboQuantCodecError::InvalidBitWidth { bits: 1 })
    ));
    assert!(matches!(
        TurboQuantBitWidth::new(5),
        Err(TurboQuantCodecError::InvalidBitWidth { bits: 5 })
    ));
}

#[test]
fn packed_codes_round_trip_all_supported_widths() {
    for bits in 2..=4 {
        let bit_width = TurboQuantBitWidth::new(bits).unwrap();
        let mut codes = TurboQuantPackedCodes::new(bit_width, 11, 3).unwrap();
        for row in 0..codes.rows() {
            for dimension in 0..codes.dimensions() {
                let code = ((row + dimension) % bit_width.levels()) as u8;
                codes.write(row, dimension, code).unwrap();
            }
        }
        for row in 0..codes.rows() {
            for dimension in 0..codes.dimensions() {
                let expected = ((row + dimension) % bit_width.levels()) as u8;
                assert_eq!(codes.read(row, dimension).unwrap(), expected);
            }
        }
    }
}

#[test]
fn three_bit_packing_crosses_byte_boundaries() {
    let bit_width = TurboQuantBitWidth::new(3).unwrap();
    let mut codes = TurboQuantPackedCodes::new(bit_width, 5, 1).unwrap();
    assert_eq!(codes.bytes_per_row(), 2);
    for (dimension, code) in [7, 0, 5, 2, 6].into_iter().enumerate() {
        codes.write(0, dimension, code).unwrap();
    }
    assert_ne!(codes.as_bytes(), &[0, 0]);
    assert_eq!(codes.read(0, 0).unwrap(), 7);
    assert_eq!(codes.read(0, 1).unwrap(), 0);
    assert_eq!(codes.read(0, 2).unwrap(), 5);
    assert_eq!(codes.read(0, 3).unwrap(), 2);
    assert_eq!(codes.read(0, 4).unwrap(), 6);
}

#[test]
fn packed_codes_validate_shape_and_bounds() {
    let bit_width = TurboQuantBitWidth::new(4).unwrap();
    assert!(matches!(
        TurboQuantPackedCodes::new(bit_width, 0, 1),
        Err(TurboQuantCodecError::InvalidDimension { dimension: 0, .. })
    ));
    assert!(matches!(
        TurboQuantPackedCodes::from_bytes(bit_width, 3, 2, vec![0; 2]),
        Err(TurboQuantCodecError::ByteLengthMismatch {
            expected: 4,
            actual: 2
        })
    ));

    let mut codes = TurboQuantPackedCodes::new(bit_width, 3, 2).unwrap();
    assert!(matches!(
        codes.read(2, 0),
        Err(TurboQuantCodecError::RowOutOfBounds { row: 2, rows: 2 })
    ));
    assert!(matches!(
        codes.read(0, 3),
        Err(TurboQuantCodecError::DimensionOutOfBounds {
            dimension: 3,
            dimensions: 3
        })
    ));
    assert!(matches!(
        codes.write(0, 0, 16),
        Err(TurboQuantCodecError::InvalidCode { code: 16, max: 15 })
    ));
}

#[test]
fn packed_codes_resize_rows_preserves_existing_codes() {
    let bit_width = TurboQuantBitWidth::new(4).unwrap();
    let mut codes = TurboQuantPackedCodes::new(bit_width, 3, 1).unwrap();
    codes.write(0, 0, 3).unwrap();
    codes.write(0, 1, 7).unwrap();
    codes.write(0, 2, 15).unwrap();

    codes.resize_rows(3).unwrap();
    assert_eq!(codes.rows(), 3);
    assert_eq!(codes.read(0, 0).unwrap(), 3);
    assert_eq!(codes.read(0, 1).unwrap(), 7);
    assert_eq!(codes.read(0, 2).unwrap(), 15);
    for row in 1..3 {
        for dimension in 0..3 {
            assert_eq!(codes.read(row, dimension).unwrap(), 0);
        }
    }

    codes.write(2, 1, 11).unwrap();
    codes.resize_rows(1).unwrap();
    assert_eq!(codes.rows(), 1);
    assert!(matches!(
        codes.read(2, 1),
        Err(TurboQuantCodecError::RowOutOfBounds { row: 2, rows: 1 })
    ));
    assert_eq!(codes.read(0, 2).unwrap(), 15);
}

#[test]
fn codebooks_are_sorted_and_dimension_scaled() {
    let bit_width = TurboQuantBitWidth::new(4).unwrap();
    let clipped = TurboQuantCodebook::clipped_uniform(bit_width, 128).unwrap();
    let lloyd = TurboQuantCodebook::normal_lloyd_max(bit_width, 128).unwrap();

    assert_eq!(clipped.centroids().len(), bit_width.levels());
    assert_eq!(clipped.boundaries().len(), bit_width.levels() - 1);
    assert_eq!(lloyd.centroids().len(), bit_width.levels());
    assert_eq!(lloyd.boundaries().len(), bit_width.levels() - 1);
    assert!(clipped.centroids().windows(2).all(|pair| pair[0] < pair[1]));
    assert!(lloyd.centroids().windows(2).all(|pair| pair[0] < pair[1]));
    assert!(lloyd.centroids()[0] < 0.0);
    assert!(lloyd.centroids()[bit_width.levels() - 1] > 0.0);
}

#[test]
fn codebook_encodes_and_decodes_scalars() {
    let bit_width = TurboQuantBitWidth::new(2).unwrap();
    let codebook = TurboQuantCodebook::clipped_uniform(bit_width, 64).unwrap();
    assert_eq!(
        codebook.encode_scalar(f32::NEG_INFINITY).unwrap_err(),
        TurboQuantCodecError::NonFiniteValue {
            value: f32::NEG_INFINITY,
        }
    );
    assert_eq!(codebook.encode_scalar(-100.0).unwrap(), 0);
    assert_eq!(codebook.encode_scalar(100.0).unwrap(), bit_width.max_code());
    let code = codebook.encode_scalar(0.0).unwrap();
    assert!(code <= bit_width.max_code());
    assert!(codebook.centroid(code).unwrap().is_finite());
    assert!(matches!(
        codebook.centroid(4),
        Err(TurboQuantCodecError::InvalidCode { code: 4, max: 3 })
    ));
}

#[test]
fn codebook_boundary_ties_choose_lower_code() {
    let bit_width = TurboQuantBitWidth::new(4).unwrap();
    let codebook = TurboQuantCodebook::normal_lloyd_max(bit_width, 128).unwrap();

    for (lower_code, boundary) in codebook.boundaries().iter().copied().enumerate() {
        assert_eq!(codebook.encode_scalar(boundary).unwrap(), lower_code as u8);
    }
}

#[test]
fn codebook_rejects_invalid_dimensions() {
    let bit_width = TurboQuantBitWidth::new(4).unwrap();
    assert!(matches!(
        TurboQuantCodebook::normal_lloyd_max(bit_width, 0),
        Err(TurboQuantCodecError::InvalidDimension { dimension: 0, .. })
    ));
    assert!(matches!(
        TurboQuantCodebook::normal_lloyd_max(bit_width, MAX_VECTOR_DIMENSION + 1),
        Err(TurboQuantCodecError::InvalidDimension {
            dimension,
            max: MAX_VECTOR_DIMENSION
        }) if dimension == MAX_VECTOR_DIMENSION + 1
    ));
}