From: Kirill Shcherbatov <kshcherbatov@tarantool.org>
To: tarantool-patches@freelists.org, vdavydov.dev@gmail.com
Cc: kostja@tarantool.org, Kirill Shcherbatov <kshcherbatov@tarantool.org>
Subject: [PATCH v1 3/4] box: introduce bitmap_majority_test routine
Date: Thu, 27 Dec 2018 14:15:54 +0300 [thread overview]
Message-ID: <ab60e98b04a7659bcd294423dbb63886e69b1723.1545909237.git.kshcherbatov@tarantool.org> (raw)
In-Reply-To: <cover.1545909236.git.kshcherbatov@tarantool.org>
A new routine bitmap_majority_test allows to test that bitmap
a "majorates" bitmap b, i.e. test that a have at least all b bits.
We need it to test compatibility of required fields bitmap with
another one that is built for tuple on tuple_init_field_map.
Needed for #1012
---
src/lib/bit/bit.h | 45 ++++++++++++++++++++++++++++++++++++++
test/unit/bit.c | 52 ++++++++++++++++++++++++++++++++++++++++++++
test/unit/bit.result | 2 ++
3 files changed, 99 insertions(+)
diff --git a/src/lib/bit/bit.h b/src/lib/bit/bit.h
index 370a0cc5d..2146a0452 100644
--- a/src/lib/bit/bit.h
+++ b/src/lib/bit/bit.h
@@ -614,6 +614,51 @@ bit_iterator_next(struct bit_iterator *it)
return it->word_base + bit;
}
+/**
+ * Check if the passed bitmap a "majorates" bitmap b (test that
+ * a contains at least all b bits). Compare first len memory
+ * blocks of sizeof(uint32_t).
+ * Return 0 when a majorates b. Otherwise -1 is returned and
+ * diff_bit_id is set - the index of first bit that present in
+ * bitmap b, but doesn't present in bitmap a.
+ */
+static inline int
+bitmap_majority_test(uint32_t *a, uint32_t *b, int len, uint32_t *diff_bit_id)
+{
+ int match_cnt = 0;
+ uint32_t *a_ptr = a, *b_ptr = b;
+ uint32_t neg_impl;
+ /*
+ * "Inverted material implication" ~(~x | y) = x & ~y test
+ * is used to find the first bit that differ
+ *
+ * Example:
+ * step 0 -- skip compatible bytes
+ * x: 0b01111101
+ * y: 0b00111101
+ * x & ~y: 0b00000000 == 0 -- next, goto step 0
+ *
+ * step 1 -- the first byte that differ:
+ * x: 0b01011001
+ * y: 0b00111101
+ * x & ~y: 0b00100100
+ *
+ * step 2 -- calculate relative bit index with ctz:
+ * bit_ctz_u32(0b00100100) = 2 -- return diff_bit_id
+ */
+ while (bit_likely((neg_impl = *b_ptr & ~*a_ptr) == 0)) {
+ if (bit_unlikely(++match_cnt >= len)) {
+ return 0;
+ }
+ a_ptr++;
+ b_ptr++;
+ }
+ assert(neg_impl != 0);
+ uint32_t trailing_zeros = bit_ctz_u32(neg_impl);
+ *diff_bit_id = match_cnt * sizeof(uint32_t) * CHAR_BIT + trailing_zeros;
+ return -1;
+}
+
#undef ITER_CTZ
#undef ITER_UINT
diff --git a/test/unit/bit.c b/test/unit/bit.c
index beb89a7e4..10074c412 100644
--- a/test/unit/bit.c
+++ b/test/unit/bit.c
@@ -206,6 +206,57 @@ test_bit_iter_empty(void)
footer();
}
+static void
+test_bitmap_majority(void)
+{
+ header();
+
+ uint32_t id;
+ uint32_t req_bitmap[5];
+ memset(req_bitmap, 0, sizeof(req_bitmap));
+ bit_set(req_bitmap, 4 * sizeof(uint32_t) * CHAR_BIT + 2);
+ bit_set(req_bitmap, 3 * sizeof(uint32_t) * CHAR_BIT + 1);
+ bit_set(req_bitmap, 2 * sizeof(uint32_t) * CHAR_BIT + 4);
+ bit_set(req_bitmap, 2 * sizeof(uint32_t) * CHAR_BIT + 2);
+ bit_set(req_bitmap, 8);
+ fail_if(bitmap_majority_test(req_bitmap, req_bitmap, 5, &id) != 0);
+
+ /*
+ * Verify that bitmap_majority_test returns difference
+ * bits ids in incremental order ignoring test extra bits.
+ */
+ uint32_t test_bitmap[5];
+ memset(test_bitmap, 0, sizeof(test_bitmap));
+ bit_set(test_bitmap, 4 * sizeof(uint32_t) * CHAR_BIT + 8);
+ bit_set(test_bitmap, 4 * sizeof(uint32_t) * CHAR_BIT + 1);
+ bit_set(test_bitmap, 2 * sizeof(uint32_t) * CHAR_BIT + 8);
+
+ fail_if(bitmap_majority_test(test_bitmap, req_bitmap, 5, &id) != -1);
+ fail_unless(id == 8);
+ bit_set(&test_bitmap, 8);
+
+ fail_if(bitmap_majority_test(test_bitmap, req_bitmap, 5, &id) != -1);
+ fail_unless(id == 2 * sizeof(uint32_t) * CHAR_BIT + 2);
+ bit_set(&test_bitmap, 2 * sizeof(uint32_t) * CHAR_BIT + 2);
+
+ fail_if(bitmap_majority_test(test_bitmap, req_bitmap, 5, &id) != -1);
+ fail_unless(id == 2 * sizeof(uint32_t) * CHAR_BIT + 4);
+ bit_set(&test_bitmap, 2 * sizeof(uint32_t) * CHAR_BIT + 4);
+
+ fail_if(bitmap_majority_test(test_bitmap, req_bitmap, 5, &id) != -1);
+ fail_unless(id == 3 * sizeof(uint32_t) * CHAR_BIT + 1);
+ bit_set(&test_bitmap, 3 * sizeof(uint32_t) * CHAR_BIT + 1);
+
+ fail_if(bitmap_majority_test(test_bitmap, req_bitmap, 5, &id) != -1);
+ fail_unless(id == 4 * sizeof(uint32_t) * CHAR_BIT + 2);
+ bit_set(&test_bitmap, 4 * sizeof(uint32_t) * CHAR_BIT + 2);
+
+ /* All different bits have been fixed. */
+ fail_if(bitmap_majority_test(test_bitmap, req_bitmap, 4, &id) != 0);
+
+ footer();
+}
+
int
main(void)
{
@@ -216,4 +267,5 @@ main(void)
test_index();
test_bit_iter();
test_bit_iter_empty();
+ test_bitmap_majority();
}
diff --git a/test/unit/bit.result b/test/unit/bit.result
index e2c5601f3..6123bc58a 100644
--- a/test/unit/bit.result
+++ b/test/unit/bit.result
@@ -891,3 +891,5 @@ Clear: 0, 1, 2, 4, 5, 6, 7, 8, 10, 12, 13, 14, 15, 19, 20, 21, 23, 26, 28, 30, 3
*** test_bit_iter: done ***
*** test_bit_iter_empty ***
*** test_bit_iter_empty: done ***
+ *** test_bitmap_majority ***
+ *** test_bitmap_majority: done ***
--
2.19.2
next prev parent reply other threads:[~2018-12-27 11:15 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-12-27 11:15 [PATCH v1 0/4] box: JSON preparatory patchset Kirill Shcherbatov
2018-12-27 11:15 ` [PATCH v1 1/4] lib: introduce json_tree_snprint_path Kirill Shcherbatov
2018-12-27 18:51 ` Vladimir Davydov
2018-12-27 11:15 ` [PATCH v1 2/4] lib: introduce json_token_is_leaf helper Kirill Shcherbatov
2018-12-27 18:52 ` Vladimir Davydov
2018-12-27 11:15 ` Kirill Shcherbatov [this message]
2018-12-27 18:59 ` [PATCH v1 3/4] box: introduce bitmap_majority_test routine Vladimir Davydov
2018-12-29 12:58 ` [tarantool-patches] " Kirill Shcherbatov
2018-12-29 13:19 ` Vladimir Davydov
2018-12-29 13:57 ` Kirill Shcherbatov
2018-12-29 16:16 ` Vladimir Davydov
2018-12-27 11:15 ` [PATCH v1 4/4] box: refactor tuple_init_field_map to use bitmap Kirill Shcherbatov
2018-12-27 11:48 ` [tarantool-patches] " Konstantin Osipov
2018-12-27 19:12 ` Vladimir Davydov
2018-12-29 12:58 ` [tarantool-patches] " Kirill Shcherbatov
2018-12-29 13:22 ` Vladimir Davydov
2018-12-29 16:25 ` Vladimir Davydov
2018-12-27 19:13 ` [PATCH v1 0/4] box: JSON preparatory patchset Vladimir Davydov
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ab60e98b04a7659bcd294423dbb63886e69b1723.1545909237.git.kshcherbatov@tarantool.org \
--to=kshcherbatov@tarantool.org \
--cc=kostja@tarantool.org \
--cc=tarantool-patches@freelists.org \
--cc=vdavydov.dev@gmail.com \
--subject='Re: [PATCH v1 3/4] box: introduce bitmap_majority_test routine' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox