Tarantool development patches archive
 help / color / mirror / Atom feed
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

  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