示例#1
0
bool serialize_correctly(roaring_bitmap_t *r) {
    uint32_t expectedsize = roaring_bitmap_portable_size_in_bytes(r);
    char *serialized = malloc(expectedsize);
    if (serialized == NULL) {
        printf("failure to allocate memory!\n");
        return false;
    }
    uint32_t serialize_len = roaring_bitmap_portable_serialize(r, serialized);
    if (serialize_len != expectedsize) {
        printf("Bad serialized size!\n");
        free(serialized);
        return false;
    }
    roaring_bitmap_t *r2 = roaring_bitmap_portable_deserialize(serialized);
    free(serialized);
    if (!roaring_bitmap_equals(r, r2)) {
        printf("Won't recover original bitmap!\n");
        roaring_bitmap_free(r2);
        return false;
    }
    if (!roaring_bitmap_equals(r2, r)) {
        printf("Won't recover original bitmap!\n");
        roaring_bitmap_free(r2);
        return false;
    }
    roaring_bitmap_free(r2);
    return true;
}
示例#2
0
bool is_negation_correct(roaring_bitmap_t *bitmap) {
    roaring_statistics_t stats;
    bool answer = true;
    roaring_bitmap_statistics(bitmap, &stats);
    unsigned universe_size = stats.max_value + 1;
    roaring_bitmap_t *inverted = roaring_bitmap_flip(bitmap, 0U, universe_size);

    roaring_bitmap_t *double_inverted =
        roaring_bitmap_flip(inverted, 0U, universe_size);

    answer = (roaring_bitmap_get_cardinality(inverted) +
                  roaring_bitmap_get_cardinality(bitmap) ==
              universe_size);
    if (answer) answer = roaring_bitmap_equals(bitmap, double_inverted);

    if (!answer) {
        printf("Bad flip\n\nbitmap1:\n");
        show_structure(bitmap->high_low_container);  // debug
        printf("\n\nflipped:\n");
        show_structure(inverted->high_low_container);  // debug
    }

    roaring_bitmap_free(double_inverted);
    roaring_bitmap_free(inverted);
    return answer;
}
示例#3
0
bool compare_andnots(roaring_bitmap_t **rnorun, roaring_bitmap_t **rruns,
                     size_t count) {
    roaring_bitmap_t *tempornorun;
    roaring_bitmap_t *temporruns;
    for (size_t i = 0; i + 1 < count; ++i) {
        tempornorun = roaring_bitmap_andnot(rnorun[i], rnorun[i + 1]);
        if (!is_andnot_correct(rnorun[i], rnorun[i + 1])) {
            printf("no-run andnot incorrect\n");
            return false;
        }
        temporruns = roaring_bitmap_andnot(rruns[i], rruns[i + 1]);
        if (!is_andnot_correct(rruns[i], rruns[i + 1])) {
            printf("runs andnots incorrect\n");
            return false;
        }
        if (!slow_bitmap_equals(tempornorun, temporruns)) {
            printf("Andnots don't agree! (slow) \n");
            return false;
        }

        if (!roaring_bitmap_equals(tempornorun, temporruns)) {
            printf("Andnots don't agree!\n");
            printf("\n\nbitmap1:\n");
            show_structure(tempornorun->high_low_container);  // debug
            printf("\n\nbitmap2:\n");
            show_structure(temporruns->high_low_container);  // debug
            return false;
        }
        roaring_bitmap_free(tempornorun);
        roaring_bitmap_free(temporruns);
        tempornorun = inplace_andnot(rnorun[i], rnorun[i + 1]);
        if (!is_andnot_correct(rnorun[i], rnorun[i + 1])) {
            printf("[inplace] no-run andnot incorrect\n");
            return false;
        }
        temporruns = inplace_andnot(rruns[i], rruns[i + 1]);
        if (!is_andnot_correct(rruns[i], rruns[i + 1])) {
            printf("[inplace] runs andnots incorrect\n");
            return false;
        }

        if (!slow_bitmap_equals(tempornorun, temporruns)) {
            printf("[inplace] Andnots don't agree! (slow) \n");
            return false;
        }

        if (!roaring_bitmap_equals(tempornorun, temporruns)) {
            printf("[inplace] Andnots don't agree!\n");
            printf("\n\nbitmap1:\n");
            show_structure(tempornorun->high_low_container);  // debug
            printf("\n\nbitmap2:\n");
            show_structure(temporruns->high_low_container);  // debug
            return false;
        }
        roaring_bitmap_free(tempornorun);
        roaring_bitmap_free(temporruns);
    }
    return true;
}
示例#4
0
bool is_xor_correct(roaring_bitmap_t *bitmap1, roaring_bitmap_t *bitmap2) {
    roaring_bitmap_t *temp = roaring_bitmap_xor(bitmap1, bitmap2);
    roaring_bitmap_t *expected = synthesized_xor(bitmap1, bitmap2);
    bool answer = roaring_bitmap_equals(temp, expected);
    if (!answer) {
        printf("Bad XOR\n\nbitmap1:\n");
        show_structure(bitmap1->high_low_container);  // debug
        printf("\n\nbitmap2:\n");
        show_structure(bitmap2->high_low_container);  // debug
        printf("\n\nresult:\n");
        show_structure(temp->high_low_container);  // debug
        printf("\n\ncorrect result:\n");
        show_structure(expected->high_low_container);  // debug
    }
    roaring_bitmap_free(temp);
    roaring_bitmap_free(expected);
    return answer;
}
示例#5
0
// function copy-pasted from toplevel_unit.c
static roaring_bitmap_t *synthesized_xor(roaring_bitmap_t *r1,
                                         roaring_bitmap_t *r2) {
    unsigned universe_size = 0;
    roaring_statistics_t stats;
    roaring_bitmap_statistics(r1, &stats);
    universe_size = stats.max_value;
    roaring_bitmap_statistics(r2, &stats);
    if (stats.max_value > universe_size) universe_size = stats.max_value;

    roaring_bitmap_t *r1_or_r2 = roaring_bitmap_or(r1, r2);
    roaring_bitmap_t *r1_and_r2 = roaring_bitmap_and(r1, r2);
    roaring_bitmap_t *r1_nand_r2 =
        roaring_bitmap_flip(r1_and_r2, 0U, universe_size + 1U);
    roaring_bitmap_t *r1_xor_r2 = roaring_bitmap_and(r1_or_r2, r1_nand_r2);
    roaring_bitmap_free(r1_or_r2);
    roaring_bitmap_free(r1_and_r2);
    roaring_bitmap_free(r1_nand_r2);
    return r1_xor_r2;
}
示例#6
0
bool is_andnot_correct(roaring_bitmap_t *bitmap1, roaring_bitmap_t *bitmap2) {
    roaring_bitmap_t *temp = roaring_bitmap_andnot(bitmap1, bitmap2);
    roaring_bitmap_t *expected = synthesized_andnot(bitmap1, bitmap2);
    bool answer = roaring_bitmap_equals(temp, expected);
    if (!answer) {
        printf("Bad ANDNOT\n\nbitmap1:\n");
        show_structure(bitmap1->high_low_container);  // debug
        // print_container(3, bitmap1);
        printf("\n\nbitmap2:\n");
        show_structure(bitmap2->high_low_container);  // debug
        printf("\n\nresult:\n");
        show_structure(temp->high_low_container);  // debug
        printf("\n\ncorrect result:\n");
        show_structure(expected->high_low_container);  // debug
        printf("difference is ");
        roaring_bitmap_printf(roaring_bitmap_xor(temp, expected));
    }
    roaring_bitmap_free(temp);
    roaring_bitmap_free(expected);
    return answer;
}
示例#7
0
// see https://github.com/saulius/croaring-rs/issues/6#issuecomment-243341270
int main() {
    size_t N = 1000000;
    uint64_t cycles_start, cycles_final;

    RDTSC_START(cycles_start);
    for(size_t i = 0; i < N; i++) {
      roaring_bitmap_t * bm = roaring_bitmap_create();
      roaring_bitmap_free(bm);
    }
    RDTSC_FINAL(cycles_final);
    printf("%f cycles per object created \n",(cycles_final-cycles_start)*1.0/N);
    return 0;
}
示例#8
0
bool compare_wide_xors(roaring_bitmap_t **rnorun, roaring_bitmap_t **rruns,
                       size_t count) {
    roaring_bitmap_t *tempornorun =
        roaring_bitmap_xor_many(count, (const roaring_bitmap_t **)rnorun);
    roaring_bitmap_t *temporruns =
        roaring_bitmap_xor_many(count, (const roaring_bitmap_t **)rruns);
    if (!slow_bitmap_equals(tempornorun, temporruns)) {
        printf("[compare_wide_xors] Xors don't agree! (fast run-norun) \n");
        return false;
    }
    assert(roaring_bitmap_equals(tempornorun, temporruns));

    roaring_bitmap_t *longtempornorun;
    roaring_bitmap_t *longtemporruns;
    if (count == 1) {
        longtempornorun = rnorun[0];
        longtemporruns = rruns[0];
    } else {
        assert(roaring_bitmap_equals(rnorun[0], rruns[0]));
        assert(roaring_bitmap_equals(rnorun[1], rruns[1]));
        longtempornorun = roaring_bitmap_xor(rnorun[0], rnorun[1]);
        longtemporruns = roaring_bitmap_xor(rruns[0], rruns[1]);
        assert(roaring_bitmap_equals(longtempornorun, longtemporruns));
        for (int i = 2; i < (int)count; ++i) {
            assert(roaring_bitmap_equals(rnorun[i], rruns[i]));
            assert(roaring_bitmap_equals(longtempornorun, longtemporruns));

            roaring_bitmap_t *t1 =
                roaring_bitmap_xor(rnorun[i], longtempornorun);
            roaring_bitmap_t *t2 = roaring_bitmap_xor(rruns[i], longtemporruns);
            assert(roaring_bitmap_equals(t1, t2));
            roaring_bitmap_free(longtempornorun);
            longtempornorun = t1;
            roaring_bitmap_free(longtemporruns);
            longtemporruns = t2;
            assert(roaring_bitmap_equals(longtempornorun, longtemporruns));
        }
    }
    if (!slow_bitmap_equals(longtempornorun, tempornorun)) {
        printf("[compare_wide_xors] Xors don't agree! (regular) \n");
        return false;
    }
    if (!slow_bitmap_equals(temporruns, longtemporruns)) {
        printf("[compare_wide_xors] Xors don't agree! (runs) \n");
        return false;
    }
    roaring_bitmap_free(tempornorun);
    roaring_bitmap_free(temporruns);

    roaring_bitmap_free(longtempornorun);
    roaring_bitmap_free(longtemporruns);

    return true;
}
示例#9
0
bool is_intersection_correct(roaring_bitmap_t *bitmap1,
                             roaring_bitmap_t *bitmap2) {
    roaring_bitmap_t *temp = roaring_bitmap_and(bitmap1, bitmap2);
    uint64_t card1, card2, card;
    card1 = roaring_bitmap_get_cardinality(bitmap1);
    card2 = roaring_bitmap_get_cardinality(bitmap2);
    card = roaring_bitmap_get_cardinality(temp);
    uint32_t *arr1 = (uint32_t *)malloc(card1 * sizeof(uint32_t));
    uint32_t *arr2 = (uint32_t *)malloc(card2 * sizeof(uint32_t));
    uint32_t *arr = (uint32_t *)malloc(card * sizeof(uint32_t));

    if ((arr1 == NULL) || (arr2 == NULL) || (arr == NULL)) {
        free(arr1);
        free(arr2);
        free(arr);
        return false;
    }

    roaring_bitmap_to_uint32_array(bitmap1, arr1);
    roaring_bitmap_to_uint32_array(bitmap2, arr2);
    roaring_bitmap_to_uint32_array(temp, arr);

    uint32_t *buffer = (uint32_t *)malloc(sizeof(uint32_t) * (card1 + card2));
    size_t cardtrue = intersection_uint32(arr1, card1, arr2, card2, buffer);
    bool answer = array_equals(arr, card, buffer, cardtrue);
    if (!answer) {
        printf("\n\nbitmap1:\n");
        show_structure(bitmap1->high_low_container);  // debug
        printf("\n\nbitmap2:\n");
        show_structure(bitmap2->high_low_container);  // debug
        printf("\n\nresult:\n");
        show_structure(temp->high_low_container);  // debug
        roaring_bitmap_t *ca = roaring_bitmap_of_ptr(cardtrue, buffer);
        printf("\n\ncorrect result:\n");
        show_structure(ca->high_low_container);  // debug
        free(ca);
    }
    free(buffer);
    free(arr1);
    free(arr2);
    free(arr);
    roaring_bitmap_free(temp);
    return answer;
}
示例#10
0
void test_example(bool copy_on_write) {
    // create a new empty bitmap
    roaring_bitmap_t *r1 = roaring_bitmap_create();
    r1->copy_on_write = copy_on_write;
    assert_ptr_not_equal(r1, NULL);

    // then we can add values
    for (uint32_t i = 100; i < 1000; i++) {
        roaring_bitmap_add(r1, i);
    }
    // check whether a value is contained
    assert_true(roaring_bitmap_contains(r1, 500));

    // compute how many bits there are:
    uint32_t cardinality = roaring_bitmap_get_cardinality(r1);
    printf("Cardinality = %d \n", cardinality);
    assert_int_equal(900, cardinality);

    // if your bitmaps have long runs, you can compress them by calling
    // run_optimize
    uint32_t size = roaring_bitmap_portable_size_in_bytes(r1);
    roaring_bitmap_run_optimize(r1);
    uint32_t compact_size = roaring_bitmap_portable_size_in_bytes(r1);
    printf("size before run optimize %d bytes, and after %d bytes\n", size,
           compact_size);
    // create a new bitmap with varargs
    roaring_bitmap_t *r2 = roaring_bitmap_of(5, 1, 2, 3, 5, 6);
    assert_ptr_not_equal(r2, NULL);
    roaring_bitmap_printf(r2);
    printf("\n");
    // we can also create a bitmap from a pointer to 32-bit integers
    const uint32_t values[] = {2, 3, 4};
    roaring_bitmap_t *r3 = roaring_bitmap_of_ptr(3, values);
    r3->copy_on_write = copy_on_write;
    // we can also go in reverse and go from arrays to bitmaps
    uint64_t card1 = roaring_bitmap_get_cardinality(r1);
    uint32_t *arr1 = new uint32_t[card1];
    assert_ptr_not_equal(arr1, NULL);
    roaring_bitmap_to_uint32_array(r1, arr1);

    roaring_bitmap_t *r1f = roaring_bitmap_of_ptr(card1, arr1);
    delete[] arr1;
    assert_ptr_not_equal(r1f, NULL);

    // bitmaps shall be equal
    assert_true(roaring_bitmap_equals(r1, r1f));
    roaring_bitmap_free(r1f);

    // we can copy and compare bitmaps
    roaring_bitmap_t *z = roaring_bitmap_copy(r3);
    z->copy_on_write = copy_on_write;
    assert_true(roaring_bitmap_equals(r3, z));

    roaring_bitmap_free(z);

    // we can compute union two-by-two
    roaring_bitmap_t *r1_2_3 = roaring_bitmap_or(r1, r2);
    r1_2_3->copy_on_write = copy_on_write;
    roaring_bitmap_or_inplace(r1_2_3, r3);

    // we can compute a big union
    const roaring_bitmap_t *allmybitmaps[] = {r1, r2, r3};
    roaring_bitmap_t *bigunion = roaring_bitmap_or_many(3, allmybitmaps);
    assert_true(roaring_bitmap_equals(r1_2_3, bigunion));
    roaring_bitmap_t *bigunionheap =
        roaring_bitmap_or_many_heap(3, allmybitmaps);
    assert_true(roaring_bitmap_equals(r1_2_3, bigunionheap));
    roaring_bitmap_free(r1_2_3);
    roaring_bitmap_free(bigunion);
    roaring_bitmap_free(bigunionheap);

    // we can compute intersection two-by-two
    roaring_bitmap_t *i1_2 = roaring_bitmap_and(r1, r2);
    roaring_bitmap_free(i1_2);

    // we can write a bitmap to a pointer and recover it later
    uint32_t expectedsize = roaring_bitmap_portable_size_in_bytes(r1);
    char *serializedbytes = (char *)malloc(expectedsize);
    roaring_bitmap_portable_serialize(r1, serializedbytes);
    roaring_bitmap_t *t = roaring_bitmap_portable_deserialize(serializedbytes);
    assert_true(expectedsize == roaring_bitmap_portable_size_in_bytes(t));
    assert_true(roaring_bitmap_equals(r1, t));
    roaring_bitmap_free(t);
    free(serializedbytes);

    // we can iterate over all values using custom functions
    uint32_t counter = 0;
    roaring_iterate(r1, roaring_iterator_sumall, &counter);
    /**
     * void roaring_iterator_sumall(uint32_t value, void *param) {
     *        *(uint32_t *) param += value;
     *  }
     *
     */

    roaring_bitmap_free(r1);
    roaring_bitmap_free(r2);
    roaring_bitmap_free(r3);
}
int main(int argc, char **argv) {
    int c;
    const char *extension = ".txt";
    bool copy_on_write = false;
    bool runoptimize = true;
    while ((c = getopt(argc, argv, "e:h")) != -1) switch (c) {
            case 'e':
                extension = optarg;
                break;
            case 'h':
                printusage(argv[0]);
                return 0;
            default:
                abort();
        }
    if (optind >= argc) {
        printusage(argv[0]);
        return -1;
    }
    char *dirname = argv[optind];
    size_t count;

    size_t *howmany = NULL;
    uint32_t **numbers =
        read_all_integer_files(dirname, extension, &howmany, &count);
    if (numbers == NULL) {
        printf(
            "I could not find or load any data file with extension %s in "
            "directory %s.\n",
            extension, dirname);
        return -1;
    }

    uint64_t cycles_start = 0, cycles_final = 0;

    RDTSC_START(cycles_start);
    roaring_bitmap_t **bitmaps =
        create_all_bitmaps(howmany, numbers, count, runoptimize, copy_on_write);
    RDTSC_FINAL(cycles_final);
    if (bitmaps == NULL) return -1;
    printf("Loaded %d bitmaps from directory %s \n", (int)count, dirname);

    printf("Creating %zu bitmaps took %" PRIu64 " cycles\n", count,
           cycles_final - cycles_start);
    if(count == 0) return -1;
    uint32_t maxvalue = roaring_bitmap_maximum(bitmaps[0]);
    for (int i = 1; i < (int)count; i ++) {
      uint32_t thismax = roaring_bitmap_maximum(bitmaps[0]);
      if(thismax > maxvalue) maxvalue = thismax;
    }
    const int quartile_test_repetitions = 1000;


    uint64_t quartcount;
    uint64_t cycles;
    STARTBEST(quartile_test_repetitions)
    quartcount = 0;
    for (size_t i = 0; i < count ; ++i) {
        quartcount += roaring_bitmap_contains(bitmaps[i],maxvalue/4);
        quartcount += roaring_bitmap_contains(bitmaps[i],maxvalue/2);
        quartcount += roaring_bitmap_contains(bitmaps[i],3*maxvalue/4);
    }
    ENDBEST(cycles)

    printf("Quartile queries on %zu bitmaps took %" PRIu64 " cycles\n", count,
                           cycles);


    for (int i = 0; i < (int)count; ++i) {
        free(numbers[i]);
        numbers[i] = NULL;  // paranoid
        roaring_bitmap_free(bitmaps[i]);
        bitmaps[i] = NULL;  // paranoid
    }
    free(bitmaps);
    free(howmany);
    free(numbers);

    return (int) quartcount;
}
// this function consumes and frees the inputs
static roaring_bitmap_t *lazy_or_from_lazy_inputs(roaring_bitmap_t *x1,
                                                  roaring_bitmap_t *x2) {
    uint8_t container_result_type = 0;
    const int length1 = ra_get_size(&x1->high_low_container),
              length2 = ra_get_size(&x2->high_low_container);
    if (0 == length1) {
        roaring_bitmap_free(x1);
        return x2;
    }
    if (0 == length2) {
        roaring_bitmap_free(x2);
        return x1;
    }
    uint32_t neededcap = length1 > length2 ? length2 : length1;
    roaring_bitmap_t *answer = roaring_bitmap_create_with_capacity(neededcap);
    int pos1 = 0, pos2 = 0;
    uint8_t container_type_1, container_type_2;
    uint16_t s1 = ra_get_key_at_index(&x1->high_low_container, pos1);
    uint16_t s2 = ra_get_key_at_index(&x2->high_low_container, pos2);
    while (true) {
        if (s1 == s2) {
            // todo: unsharing can be inefficient as it may create a clone where
            // none
            // is needed, but it has the benefit of being easy to reason about.
            ra_unshare_container_at_index(&x1->high_low_container, pos1);
            void *c1 = ra_get_container_at_index(&x1->high_low_container, pos1,
                                                 &container_type_1);
            assert(container_type_1 != SHARED_CONTAINER_TYPE_CODE);
            ra_unshare_container_at_index(&x2->high_low_container, pos2);
            void *c2 = ra_get_container_at_index(&x2->high_low_container, pos2,
                                                 &container_type_2);
            assert(container_type_2 != SHARED_CONTAINER_TYPE_CODE);
            void *c;

            if ((container_type_2 == BITSET_CONTAINER_TYPE_CODE) &&
                (container_type_1 != BITSET_CONTAINER_TYPE_CODE)) {
                c = container_lazy_ior(c2, container_type_2, c1,
                                       container_type_1,
                                       &container_result_type);
                container_free(c1, container_type_1);
                if (c != c2) {
                    container_free(c2, container_type_2);
                }
            } else {
                c = container_lazy_ior(c1, container_type_1, c2,
                                       container_type_2,
                                       &container_result_type);
                container_free(c2, container_type_2);
                if (c != c1) {
                    container_free(c1, container_type_1);
                }
            }
            // since we assume that the initial containers are non-empty, the
            // result here
            // can only be non-empty
            ra_append(&answer->high_low_container, s1, c,
                      container_result_type);
            ++pos1;
            ++pos2;
            if (pos1 == length1) break;
            if (pos2 == length2) break;
            s1 = ra_get_key_at_index(&x1->high_low_container, pos1);
            s2 = ra_get_key_at_index(&x2->high_low_container, pos2);

        } else if (s1 < s2) {  // s1 < s2
            void *c1 = ra_get_container_at_index(&x1->high_low_container, pos1,
                                                 &container_type_1);
            ra_append(&answer->high_low_container, s1, c1, container_type_1);
            pos1++;
            if (pos1 == length1) break;
            s1 = ra_get_key_at_index(&x1->high_low_container, pos1);

        } else {  // s1 > s2
            void *c2 = ra_get_container_at_index(&x2->high_low_container, pos2,
                                                 &container_type_2);
            ra_append(&answer->high_low_container, s2, c2, container_type_2);
            pos2++;
            if (pos2 == length2) break;
            s2 = ra_get_key_at_index(&x2->high_low_container, pos2);
        }
    }
    if (pos1 == length1) {
        ra_append_move_range(&answer->high_low_container,
                             &x2->high_low_container, pos2, length2);
    } else if (pos2 == length2) {
        ra_append_move_range(&answer->high_low_container,
                             &x1->high_low_container, pos1, length1);
    }
    ra_clear_without_containers(&x1->high_low_container);
    ra_clear_without_containers(&x2->high_low_container);
    free(x1);
    free(x2);
    return answer;
}
示例#13
0
bool loadAndCheckAll(const char *dirname, bool copy_on_write) {
    printf("[%s] %s datadir=%s %s\n", __FILE__, __func__, dirname,
           copy_on_write ? "copy-on-write" : "hard-copies");

    char *extension = ".txt";
    size_t count;

    size_t *howmany = NULL;
    uint32_t **numbers =
        read_all_integer_files(dirname, extension, &howmany, &count);
    if (numbers == NULL) {
        printf(
            "I could not find or load any data file with extension %s in "
            "directory %s.\n",
            extension, dirname);
        return false;
    }

    roaring_bitmap_t **bitmaps =
        create_all_bitmaps(howmany, numbers, count, copy_on_write);
    for (size_t i = 0; i < count; i++) {
        if (!is_bitmap_equal_to_array(bitmaps[i], numbers[i], howmany[i])) {
            printf("arrays don't agree with set values\n");
            return false;
        }
    }

    roaring_bitmap_t **bitmapswrun = malloc(sizeof(roaring_bitmap_t *) * count);
    for (int i = 0; i < (int)count; i++) {
        bitmapswrun[i] = roaring_bitmap_copy(bitmaps[i]);
        roaring_bitmap_run_optimize(bitmapswrun[i]);
        if (roaring_bitmap_get_cardinality(bitmaps[i]) !=
            roaring_bitmap_get_cardinality(bitmapswrun[i])) {
            printf("cardinality change due to roaring_bitmap_run_optimize\n");
            return false;
        }
    }
    for (size_t i = 0; i < count; i++) {
        if (!is_bitmap_equal_to_array(bitmapswrun[i], numbers[i], howmany[i])) {
            printf("arrays don't agree with set values\n");
            return false;
        }
    }
    for (int i = 0; i < (int)count; i++) {
        if (!serialize_correctly(bitmaps[i])) {
            return false;  //  memory leaks
        }
        if (!serialize_correctly(bitmapswrun[i])) {
            return false;  //  memory leaks
        }
    }
    if (!compare_intersections(bitmaps, bitmapswrun, count)) {
        return false;  //  memory leaks
    }
    if (!compare_unions(bitmaps, bitmapswrun, count)) {
        return false;  //  memory leaks
    }
    if (!compare_wide_unions(bitmaps, bitmapswrun, count)) {
        return false;  //  memory leaks
    }

    if (!compare_negations(bitmaps, bitmapswrun, count)) {
        return false;  //  memory leaks
    }

    if (!compare_xors(bitmaps, bitmapswrun, count)) {
        return false;  //  memory leaks
    }

    if (!compare_andnots(bitmaps, bitmapswrun, count)) {
        return false;  //  memory leaks
    }

    if (!compare_wide_xors(bitmaps, bitmapswrun, count)) {
        return false;  //  memory leaks
    }

    for (int i = 0; i < (int)count; ++i) {
        free(numbers[i]);
        numbers[i] = NULL;  // paranoid
        roaring_bitmap_free(bitmaps[i]);
        bitmaps[i] = NULL;  // paranoid
        roaring_bitmap_free(bitmapswrun[i]);
        bitmapswrun[i] = NULL;  // paranoid
    }
    free(bitmapswrun);
    free(bitmaps);
    free(howmany);
    free(numbers);

    return true;
}
int main(int argc, char **argv) {
    int c;
    char *extension = ".txt";
    bool copy_on_write = false;
    while ((c = getopt(argc, argv, "e:h")) != -1) switch (c) {
            case 'e':
                extension = optarg;
                break;
            case 'h':
                printusage(argv[0]);
                return 0;
            default:
                abort();
        }
    if (optind >= argc) {
        printusage(argv[0]);
        return -1;
    }
    char *dirname = argv[optind];
    size_t count;

    size_t *howmany = NULL;
    uint32_t **numbers =
        read_all_integer_files(dirname, extension, &howmany, &count);
    if (numbers == NULL) {
        printf(
            "I could not find or load any data file with extension %s in "
            "directory %s.\n",
            extension, dirname);
        return -1;
    }

    uint64_t cycles_start = 0, cycles_final = 0;

    RDTSC_START(cycles_start);
    roaring_bitmap_t **bitmaps = create_all_bitmaps(howmany, numbers, count, copy_on_write);
    RDTSC_FINAL(cycles_final);
    if (bitmaps == NULL) return -1;
    printf("Loaded %d bitmaps from directory %s \n", (int)count, dirname);

    printf("Creating %zu bitmaps took %" PRIu64 " cycles\n", count,
           cycles_final - cycles_start);

    RDTSC_START(cycles_start);
    for (int i = 0; i < (int)count; i += 2) {
        roaring_bitmap_t *CI = roaring_bitmap_copy(
            bitmaps[i]);  // to test the inplace version we create a copy
        roaring_bitmap_free(CI);
    }
    RDTSC_FINAL(cycles_final);
    printf("Copying and freeing %zu bitmaps took %" PRIu64 " cycles\n", count,
           cycles_final - cycles_start);

    uint64_t successive_and = 0;
    uint64_t successive_or = 0;
    // try ANDing and ORing together consecutive pairs
    for (int i = 0; i < (int)count - 1; ++i) {
        uint32_t c1 = roaring_bitmap_get_cardinality(bitmaps[i]);
        uint32_t c2 = roaring_bitmap_get_cardinality(bitmaps[i + 1]);
        RDTSC_START(cycles_start);
        roaring_bitmap_t *tempand =
            roaring_bitmap_and(bitmaps[i], bitmaps[i + 1]);
        RDTSC_FINAL(cycles_final);
        successive_and += cycles_final - cycles_start;

        uint32_t ci = roaring_bitmap_get_cardinality(tempand);
        roaring_bitmap_free(tempand);
        RDTSC_START(cycles_start);
        roaring_bitmap_t *tempor =
            roaring_bitmap_or(bitmaps[i], bitmaps[i + 1]);
        RDTSC_FINAL(cycles_final);
        successive_or += cycles_final - cycles_start;

        uint32_t co = roaring_bitmap_get_cardinality(tempor);
        roaring_bitmap_free(tempor);

        if (c1 + c2 != co + ci) {
            printf(KRED "cardinalities are wrong somehow\n");
            printf("c1 = %d, c2 = %d, co = %d, ci = %d\n", c1, c2, co, ci);
            return -1;
        }
    }
    printf(" %zu successive bitmaps intersections took %" PRIu64 " cycles\n",
           count - 1, successive_and);
    printf(" %zu successive bitmaps unions took %" PRIu64 " cycles\n",
           count - 1, successive_or);

    roaring_bitmap_t **copyofr = malloc(sizeof(roaring_bitmap_t *) * count);
    for (int i = 0; i < (int)count; i++) {
        copyofr[i] = roaring_bitmap_copy(bitmaps[i]);
    }
    RDTSC_START(cycles_start);
    for (int i = 0; i < (int)count - 1; i++) {
        roaring_bitmap_and_inplace(copyofr[i], bitmaps[i + 1]);
    }
    RDTSC_FINAL(cycles_final);
    printf(" %zu successive in-place bitmaps intersections took %" PRIu64
           " cycles\n",
           count - 1, cycles_final - cycles_start);

    free(copyofr);
    copyofr = malloc(sizeof(roaring_bitmap_t *) * count);
    for (int i = 0; i < (int)count; i++) {
        copyofr[i] = roaring_bitmap_copy(bitmaps[i]);
    }
    RDTSC_START(cycles_start);
    for (int i = 0; i < (int)count - 1; i++) {
        roaring_bitmap_or_inplace(copyofr[i], bitmaps[i + 1]);
    }
    RDTSC_FINAL(cycles_final);
    printf(" %zu successive in-place bitmaps unions took %" PRIu64 " cycles\n",
           count - 1, cycles_final - cycles_start);

    for (int i = 0; i < (int)count; ++i) {
        free(numbers[i]);
        numbers[i] = NULL;  // paranoid
        roaring_bitmap_free(bitmaps[i]);
        bitmaps[i] = NULL;  // paranoid
    }
    free(bitmaps);
    free(howmany);
    free(numbers);

    return 0;
}