Skip to content
BitVecJaccardSimilarity

BitVecJaccardSimilarity

Description

Calculate Jaccard similarity between two bitvectors. Jaccard similarity = |intersection| / |union|

Parameters

Name Direction Description
bv1 in First bitvector
bv2 in Second bitvector

Usage example (from documentation)

  double similarity = BitVecJaccardSimilarity(&bv1, &bv2);

Success

Returns the Jaccard similarity coefficient in [0.0, 1.0]. Neither operand is modified.

Failure

Returns 0.0 when both operands have no set bits (degenerate union); the caller cannot distinguish that from a true zero coefficient.

Usage example (Cross-references)

Usage examples (Cross-references)
    }
    
    double BitVecJaccardSimilarity(BitVec *bv1, BitVec *bv2) {
        ValidateBitVec(bv1);
        ValidateBitVec(bv2);
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        WriteFmt("Testing BitVecJaccardSimilarity basic functionality\n");
    
        BitVec bv1    = BitVecInit(ALLOCATOR_OF(&alloc));
        BitVecPush(&bv2, true);
    
        double similarity = BitVecJaccardSimilarity(&bv1, &bv2);
        result            = result && (F64Abs(similarity - 1.0) < 0.001);
        BitVecPush(&bv2, true);
    
        similarity = BitVecJaccardSimilarity(&bv1, &bv2);
        result     = result && (F64Abs(similarity - 0.0) < 0.001);
        // Intersection: 1, Union: 2, Jaccard = 1/2 = 0.5
    
        similarity = BitVecJaccardSimilarity(&bv1, &bv2);
        result     = result && (F64Abs(similarity - 0.5) < 0.001);
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        WriteFmt("Testing BitVecJaccardSimilarity edge cases\n");
    
        BitVec bv1    = BitVecInit(ALLOCATOR_OF(&alloc));
    
        // Test empty bitvectors
        double similarity = BitVecJaccardSimilarity(&bv1, &bv2);
        result            = result && (F64Abs(similarity - 1.0) < 0.001);
        BitVecPush(&bv2, false);
    
        similarity = BitVecJaccardSimilarity(&bv1, &bv2);
        result     = result && (F64Abs(similarity - 1.0) < 0.001);
        // Test that all functions complete without crashing
        u64    hamming     = BitVecHammingDistance(&bv1, &bv2);
        double jaccard     = BitVecJaccardSimilarity(&bv1, &bv2);
        double cosine      = BitVecCosineSimilarity(&bv1, &bv2);
        u64    dot_prod    = BitVecDotProduct(&bv1, &bv2);
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        WriteFmt("Testing BitVecJaccardSimilarity(NULL, bv2) - should fatal\n");
        BitVec bv2 = BitVecInit(ALLOCATOR_OF(&alloc));
        BitVecPush(&bv2, true);
        BitVec bv2 = BitVecInit(ALLOCATOR_OF(&alloc));
        BitVecPush(&bv2, true);
        BitVecJaccardSimilarity(NULL, &bv2);
        BitVecDeinit(&bv2);
        DefaultAllocatorDeinit(&alloc);
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        WriteFmt("Testing BitVecJaccardSimilarity(bv1, NULL) - should fatal\n");
        BitVec bv1 = BitVecInit(ALLOCATOR_OF(&alloc));
        BitVecPush(&bv1, true);
        BitVec bv1 = BitVecInit(ALLOCATOR_OF(&alloc));
        BitVecPush(&bv1, true);
        BitVecJaccardSimilarity(&bv1, NULL);
        BitVecDeinit(&bv1);
        DefaultAllocatorDeinit(&alloc);
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        WriteFmt("Testing BitVecJaccardSimilarity guard only fires when both empty\n");
    
        BitVec empty = BitVecInit(ALLOCATOR_OF(&alloc));
    
        // empty vs {1}: intersection 0, union 1 -> Jaccard 0.0 (kills 1427:41).
        double s1 = BitVecJaccardSimilarity(&empty, &one);
        result    = result && (F64Abs(s1 - 0.0) < 0.001);
    
        // {1} vs empty: same -> 0.0 (kills 1427:21).
        double s2 = BitVecJaccardSimilarity(&one, &empty);
        result    = result && (F64Abs(s2 - 0.0) < 0.001);
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        WriteFmt("Testing BitVecJaccardSimilarity with bv1 shorter than bv2\n");
    
        BitVec bv1 = BitVecInit(ALLOCATOR_OF(&alloc));
        BitVecPush(&bv2, false);
    
        double s      = BitVecJaccardSimilarity(&bv1, &bv2);
        bool   result = (F64Abs(s - 1.0) < 0.001);
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        WriteFmt("Testing BitVecJaccardSimilarity with bv2 shorter than bv1\n");
    
        BitVec bv1 = BitVecInit(ALLOCATOR_OF(&alloc));
        BitVecPush(&bv2, true);
    
        double s      = BitVecJaccardSimilarity(&bv1, &bv2);
        bool   result = (F64Abs(s - 1.0) < 0.001);
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        WriteFmt("Testing BitVecJaccardSimilarity reads bv2 bits in valid region\n");
    
        BitVec bv1 = BitVecInit(ALLOCATOR_OF(&alloc));
        BitVecPush(&bv2, true);
    
        double s      = BitVecJaccardSimilarity(&bv1, &bv2);
        bool   result = (F64Abs(s - 0.0) < 0.001);
        DefaultAllocator alloc = DefaultAllocatorInit();
    
        WriteFmt("Testing BitVecJaccardSimilarity rejects bad second operand\n");
    
        BitVec empty = BitVecInit(ALLOCATOR_OF(&alloc));
        BitVec bad   = {0};
    
        BitVecJaccardSimilarity(&empty, &bad);
    
        BitVecDeinit(&empty);
Last updated on