[blivet:master 3/3] Add a method that determines whether a number is an exact power of 2.
mulhern
amulhern at redhat.com
Fri Oct 31 15:31:59 UTC 2014
Taking the log to determine whether a number is an exact power of 2 does
not always work, because log computes w/ floats, somehow. It usually works,
because base 2 works well w/ binary floating point representation.
Decimal does not actually have a log function. You can use change of base
to get log base 2, but you do not get an exact result.
Use method in is_valid_pool_chunk_size().
Signed-off-by: mulhern <amulhern at redhat.com>
---
blivet/devicelibs/lvm.py | 3 +--
blivet/util.py | 28 ++++++++++++++++++++++++++++
tests/util_test.py | 22 ++++++++++++++++++++++
3 files changed, 51 insertions(+), 2 deletions(-)
create mode 100644 tests/util_test.py
diff --git a/blivet/devicelibs/lvm.py b/blivet/devicelibs/lvm.py
index cf21902..958b974 100644
--- a/blivet/devicelibs/lvm.py
+++ b/blivet/devicelibs/lvm.py
@@ -20,7 +20,6 @@
# Author(s): Dave Lehman <dlehman at redhat.com>
#
-import math
from decimal import Decimal
from collections import namedtuple
@@ -212,7 +211,7 @@ def is_valid_thin_pool_chunk_size(size, discard=False):
return False
if discard:
- return (math.log(size, 2) % 1.0 == 0)
+ return util.power_of_two(int(size))
else:
return (size % LVM_THINP_MIN_CHUNK_SIZE == Size(0))
diff --git a/blivet/util.py b/blivet/util.py
index a69b694..e045a32 100644
--- a/blivet/util.py
+++ b/blivet/util.py
@@ -524,3 +524,31 @@ def variable_copy(obj, memo, omit=None, shallow=None, duplicate=None):
def get_current_entropy():
with open("/proc/sys/kernel/random/entropy_avail", "r") as fobj:
return int(fobj.readline())
+
+def power_of_two(value):
+ """ Checks whether value is a power of 2 greater than 1.
+
+ :param any value: a value
+ :returns: True if the value is a power of 2
+ :rtype: bool
+ """
+ try:
+ int_value = int(value)
+ except (ValueError, TypeError):
+ return False
+
+ if int_value != value:
+ return False
+
+ value = int_value
+
+ if value < 2:
+ return False
+
+ (q, r) = (value, 0)
+ while q != 0:
+ if r != 0:
+ return False
+ (q, r) = q.__divmod__(2)
+
+ return True
diff --git a/tests/util_test.py b/tests/util_test.py
new file mode 100644
index 0000000..13b8d06
--- /dev/null
+++ b/tests/util_test.py
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+
+import unittest
+from decimal import Decimal
+
+from blivet import util
+
+class MiscTest(unittest.TestCase):
+
+ longMessage = True
+
+ def test_power_of_two(self):
+ self.assertFalse(util.power_of_two(None))
+ self.assertFalse(util.power_of_two("not a number"))
+ self.assertFalse(util.power_of_two(Decimal(2.2)))
+ self.assertFalse(util.power_of_two(-1))
+ self.assertFalse(util.power_of_two(0))
+ self.assertFalse(util.power_of_two(1))
+ for i in range(1, 60, 5):
+ self.assertTrue(util.power_of_two(2 ** i), msg=i)
+ self.assertFalse(util.power_of_two(2 ** i + 1), msg=i)
+ self.assertFalse(util.power_of_two(2 ** i - 1), msg=i)
--
1.9.3
More information about the anaconda-patches
mailing list