[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH v3 1/6] internal: add macro to round value to the next closest power of 2



There are two special cases, if the input number is 0 or the number is
larger then 2^31 (for 32bit unsigned int). For the special cases the
return value is 0 because they cannot be rounded.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1076098

Signed-off-by: Pavel Hrdina <phrdina redhat com>
---
 bootstrap.conf   |  1 +
 src/internal.h   |  7 +++++++
 tests/utiltest.c | 39 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+)

diff --git a/bootstrap.conf b/bootstrap.conf
index d24a714..e7ea9c9 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -35,6 +35,7 @@ clock-time
 close
 connect
 configmake
+count-leading-zeros
 count-one-bits
 crypto/md5
 crypto/sha256
diff --git a/src/internal.h b/src/internal.h
index f6a88b2..765b853 100644
--- a/src/internal.h
+++ b/src/internal.h
@@ -62,6 +62,7 @@
 
 # include "c-strcase.h"
 # include "ignore-value.h"
+# include "count-leading-zeros.h"
 
 /* On architectures which lack these limits, define them (ie. Cygwin).
  * Note that the libvirt code should be robust enough to handle the
@@ -382,6 +383,12 @@
 /* round up value to the closest multiple of size */
 # define VIR_ROUND_UP(value, size) (VIR_DIV_UP(value, size) * (size))
 
+/* Round up to the next closest power of 2. It will return rounded number or 0
+ * for 0 or number more than 2^31 (for 32bit unsigned int). */
+# define VIR_ROUND_UP_POWER_OF_TWO(value)                                   \
+    ((value) > 0 && (value) <= 1U<<(sizeof(unsigned int)*8 - 1) ?           \
+     1U<<(sizeof(unsigned int)*8 - count_leading_zeros((value) - 1)) : 0)
+
 
 /* Specific error values for use in forwarding programs such as
  * virt-login-shell; these values match what GNU env does.  */
diff --git a/tests/utiltest.c b/tests/utiltest.c
index 8950cf2..2dbd291 100644
--- a/tests/utiltest.c
+++ b/tests/utiltest.c
@@ -143,6 +143,44 @@ testParseVersionString(const void *data ATTRIBUTE_UNUSED)
 
 
 
+struct testRoundData {
+    unsigned int input;
+    unsigned int output;
+};
+
+static struct testRoundData roundData[] = {
+    { 0, 0 },
+    { 1, 1 },
+    { 1000, 1024 },
+    { 1024, 1024 },
+    { 1025, 2048 },
+    { UINT_MAX, 0 },
+};
+
+static int
+testRoundValueToPowerOfTwo(const void *data ATTRIBUTE_UNUSED)
+{
+    unsigned int result;
+    size_t i;
+
+    for (i = 0; i < ARRAY_CARDINALITY(roundData); i++) {
+        result = VIR_ROUND_UP_POWER_OF_TWO(roundData[i].input);
+        if (roundData[i].output != result) {
+            if (virTestGetDebug() > 0) {
+                fprintf(stderr, "\nInput number [%u]\n", roundData[i].input);
+                fprintf(stderr, "Expected number [%u]\n", roundData[i].output);
+                fprintf(stderr, "Actual number [%u]\n", result);
+            }
+
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+
+
 
 static int
 mymain(void)
@@ -162,6 +200,7 @@ mymain(void)
     DO_TEST(IndexToDiskName);
     DO_TEST(DiskNameToIndex);
     DO_TEST(ParseVersionString);
+    DO_TEST(RoundValueToPowerOfTwo);
 
     return result == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
 }
-- 
2.0.4


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]