Skip to content

Commit f36600b

Browse files
add python bindings for floor_log2 and ceil_log2
1 parent 7e58e41 commit f36600b

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

src/python.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,20 @@ impl RealAlgebraicNumberPy {
9393
})
9494
.ok_or_else(get_div_by_zero_error)
9595
}
96+
/// returns `floor(log2(self))`
97+
fn floor_log2(&self) -> PyResult<i64> {
98+
Python::acquire_gil()
99+
.python()
100+
.allow_threads(|| self.value.checked_floor_log2())
101+
.ok_or_else(get_floor_ceil_log2_error)
102+
}
103+
/// returns `ceil(log2(self))`
104+
fn ceil_log2(&self) -> PyResult<i64> {
105+
Python::acquire_gil()
106+
.python()
107+
.allow_threads(|| self.value.checked_ceil_log2())
108+
.ok_or_else(get_floor_ceil_log2_error)
109+
}
96110
}
97111

98112
#[pyproto]
@@ -118,6 +132,10 @@ fn get_div_by_zero_error() -> PyErr {
118132
ZeroDivisionError::py_err("can't divide RealAlgebraicNumber by zero")
119133
}
120134

135+
fn get_floor_ceil_log2_error() -> PyErr {
136+
ValueError::py_err("can't extract base-2 logarithm of zero or negative RealAlgebraicNumber")
137+
}
138+
121139
#[pyproto]
122140
impl PyNumberProtocol for RealAlgebraicNumberPy {
123141
fn __add__(lhs: &PyAny, rhs: RealAlgebraicNumberPy) -> PyResult<RealAlgebraicNumberPy> {

tests/test_real_algebraic_number.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,28 @@ def test_abs(self):
227227
self.assertEqual(abs(RealAlgebraicNumber(1)), 1)
228228
self.assertEqual(abs(RealAlgebraicNumber(-2)), 2)
229229

230+
def test_floor_ceil_log2(self):
231+
with self.assertRaises(ValueError):
232+
RealAlgebraicNumber(0).floor_log2()
233+
with self.assertRaises(ValueError):
234+
RealAlgebraicNumber(0).ceil_log2()
235+
with self.assertRaises(ValueError):
236+
RealAlgebraicNumber(-1).floor_log2()
237+
with self.assertRaises(ValueError):
238+
RealAlgebraicNumber(-1).ceil_log2()
239+
self.assertEqual(RealAlgebraicNumber(1).floor_log2(), 0)
240+
self.assertEqual(RealAlgebraicNumber(1).ceil_log2(), 0)
241+
self.assertEqual(RealAlgebraicNumber(2).floor_log2(), 1)
242+
self.assertEqual(RealAlgebraicNumber(2).ceil_log2(), 1)
243+
self.assertEqual(RealAlgebraicNumber(3).floor_log2(), 1)
244+
self.assertEqual(RealAlgebraicNumber(3).ceil_log2(), 2)
245+
self.assertEqual(RealAlgebraicNumber(4).floor_log2(), 2)
246+
self.assertEqual(RealAlgebraicNumber(4).ceil_log2(), 2)
247+
self.assertEqual((RealAlgebraicNumber(1) / 4).floor_log2(), -2)
248+
self.assertEqual((RealAlgebraicNumber(1) / 4).ceil_log2(), -2)
249+
self.assertEqual((RealAlgebraicNumber(1) / 3).floor_log2(), -2)
250+
self.assertEqual((RealAlgebraicNumber(1) / 3).ceil_log2(), -1)
251+
230252

231253
if __name__ == '__main__':
232254
unittest.main()

0 commit comments

Comments
 (0)