import data, config, code

def algo1_verify(Algo2Set *set):
    """
    Try to verify each sample in the test set against all classes. We cumulate
    the scoring results for inter-class and intra-class matches to get
    FMR and FNMR curves.
    """
    int total = data_test_samples_count(set)
    printf("Processing %d images (%d offsets).\n", total, set->rotation_offsets)
    set->bins_count = 512
    for int k = 0; k < set->bins_count; k++:
        set->inter_bins[k] = 0
        set->intra_bins[k] = 0

    int n = 0
    double t = 0
    for int i = 0; i < set->classes->count; i++:
        Algo2Class *c = *((Algo2Class **)vector_get(set->classes, i))
        c->inter_total = 0
        c->inter_n = 0
        c->intra_total = 0
        c->intra_n = 0
        c->intra_min = 512
        c->intra_max = -1
        for int j = 0; j < c->test_samples->count; j++:
            Algo2Sample *ts = *((Algo2Sample **)vector_get(c->test_samples, j))
            n += 1
            # We start with i to get intra-class results for the same class.
            # We do not need matching results with earlier classes, because
            # we already matched them and i2 <-> i would have the same result as
            # i <-> i2 had.
            for int i2 = i; i2 < set->classes->count; i2++:
                Algo2Class *c2 = *((Algo2Class **)vector_get(set->classes, i2))

                double t2 = util_time()
                if t2 >= t + 2:
                    fprintf(stderr, " %d/%d\n", n, total)
                    t = t2
                    
                for int j2 = 0; j2 < c2->test_samples->count; j2++:
                    Algo2Sample *os = *((Algo2Sample **)vector_get(c2->test_samples, j2))
                    if c == c2:
                        # For intra-class matching, only match each picture against
                        # each other once.
                        if j2 <= j: continue
                    # c: class of our test sample
                    # ts: our test sample
                    # c2: class we verify against
                    # os: other sample out of class 2

                    int m = 0
                    int d = bitcode_compare(ts->bitcode, os->bitcode,
                        set->rotation_offsets, &m)
                    
                    #int code_w, code_h
                    #int code_bytes = ts->features->count
                    #code_bytes *= ts->features->element_size
                    # We assume exactly one half is code, and the second half
                    # is masking bits.
                    #code_bytes /= 2
                    # FIXME: hack hack hack!
                    # if code_bytes == 512 * 20 / 8:
                    #    code_w = 512
                    #    code_h = 20
                    # elif code_bytes == 256 * 64 / 8:
                    #    code_w = 256
                    #    code_h = 64
                    # else:
                    #    fprintf(stderr, "Malformed code detected.")
                    #    abort()
                    #int m = 0
                    #int d = code_compare_masked(code_w, code_h,
                    #    (char *)ts->features->data,
                    #    (char *)ts->features->data + code_bytes,
                    #    (char *)os->features->data,
                    #    (char *)os->features->data + code_bytes,
                    #    set->rotation_offsets,
                    #    &m)

                    int k
                    if m == 0:
                        # If our image is totally masked, we say it doesn't
                        # match at all...
                        k = set->bins_count - 1
                    else:
                        k = set->bins_count * d / m
                    if k > set->bins_count - 1: k = set->bins_count - 1
                    if c == c2:
                        c->intra_n++
                        c->intra_total += k
                        if k < c->intra_min: c->intra_min = k
                        if k > c->intra_max: c->intra_max = k
                        set->intra_bins[k]++
                    else:
                        c->inter_n++
                        c->inter_total += k
                        set->inter_bins[k]++
    # print some stats
    for int i = 0; i < set->classes->count; i++:
        Algo2Class *c = *((Algo2Class **)vector_get(set->classes, i))
        print("%s: inter: %d %.1f intra: %d %.1f (%.1f..%.1f)\n", c->name,
            c->inter_n, c->inter_total * 100.0 / 512.0 / c->inter_n,
            c->intra_n, c->intra_total * 100.0 / 512.0 / c->intra_n,
            c->intra_min * 100.0 / 512.0, c->intra_max * 100.0 / 512.0)
