// 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;
}
/**
 * Compute the union of 'number' bitmaps using a heap. This can
 * sometimes be faster than roaring_bitmap_or_many which uses
 * a naive algorithm. Caller is responsible for freeing the
 * result.
 */
roaring_bitmap_t *roaring_bitmap_or_many_heap(uint32_t number,
		const roaring_bitmap_t **x) {
	if (number == 0) {
		return roaring_bitmap_create();
	}
	if (number == 1) {
		return roaring_bitmap_copy(x[0]);
	}
	roaring_pq_t *pq = create_pq(x, number);
	while (pq->size > 1) {
		roaring_pq_element_t x1 = pq_poll(pq);
		roaring_pq_element_t x2 = pq_poll(pq);

		if (x1.is_temporary && x2.is_temporary) {
                        roaring_bitmap_t *newb =lazy_or_from_lazy_inputs(x1.bitmap,
					x2.bitmap);
			uint64_t bsize = roaring_bitmap_portable_size_in_bytes(newb);
			roaring_pq_element_t newelement = { .size = bsize, .is_temporary =
					true, .bitmap = newb };
			pq_add(pq, &newelement);
		} else if (x2.is_temporary) {
                        roaring_bitmap_lazy_or_inplace(x2.bitmap, x1.bitmap);
			x2.size = roaring_bitmap_portable_size_in_bytes(x2.bitmap);
			pq_add(pq, &x2);
		} else if (x1.is_temporary) {
			roaring_bitmap_lazy_or_inplace(x1.bitmap, x2.bitmap);
			x1.size = roaring_bitmap_portable_size_in_bytes(x1.bitmap);

			pq_add(pq, &x1);
		} else {
		  roaring_bitmap_t *newb = roaring_bitmap_lazy_or(x1.bitmap,
					x2.bitmap);
			uint64_t bsize = roaring_bitmap_portable_size_in_bytes(newb);
			roaring_pq_element_t newelement = { .size = bsize, .is_temporary =
					true, .bitmap = newb };

			pq_add(pq, &newelement);
		}

	}
	roaring_pq_element_t X = pq_poll(pq);
	roaring_bitmap_t *answer = X.bitmap;
	roaring_bitmap_repair_after_lazy(answer);
	pq_free(pq);
	return answer;
}
/**
 * Compute the union of 'number' bitmaps using a heap. This can
 * sometimes be faster than roaring_bitmap_or_many which uses
 * a naive algorithm. Caller is responsible for freeing the
 * result.
 */
roaring_bitmap_t *roaring_bitmap_or_many_heap(uint32_t number,
                                              const roaring_bitmap_t **x) {
    if (number == 0) {
        return roaring_bitmap_create();
    }
    if (number == 1) {
        return roaring_bitmap_copy(x[0]);
    }
    roaring_pq_t *pq = create_pq(x, number);
    while (pq->size > 1) {
        roaring_pq_element_t x1 = pq_poll(pq);
        roaring_pq_element_t x2 = pq_poll(pq);

        if (x1.is_temporary && x2.is_temporary) {
            roaring_bitmap_t *newb =
                lazy_or_from_lazy_inputs(x1.bitmap, x2.bitmap);
            // should normally return a fresh new bitmap *except* that
            // it can return x1.bitmap or x2.bitmap in degenerate cases
            bool temporary = !((newb == x1.bitmap) && (newb == x2.bitmap));
            uint64_t bsize = roaring_bitmap_portable_size_in_bytes(newb);
            roaring_pq_element_t newelement = {
                .size = bsize, .is_temporary = temporary, .bitmap = newb};
            pq_add(pq, &newelement);
        } else if (x2.is_temporary) {
Beispiel #4
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);
}
// 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;
    roaring_bitmap_t *answer = roaring_bitmap_create();
    const int length1 = x1->high_low_container->size,
              length2 = x2->high_low_container->size;
    if (0 == length1) {
        roaring_bitmap_free(x1);
        return x2;
    }
    if (0 == length2) {
        roaring_bitmap_free(x2);
        return x1;
    }
    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_2 != 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_free_without_containers(x1->high_low_container);
    ra_free_without_containers(x2->high_low_container);
    free(x1);
    free(x2);
    return answer;
}