From e305eb4c7e1efd21663b896105a3a7c1cfd59733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vladim=C3=ADr=20Vondru=C5=A1?= Date: Mon, 13 May 2019 22:45:10 +0200 Subject: [PATCH] python: expose BoolVector. --- src/python/magnum/__init__.py | 4 ++- src/python/magnum/math.cpp | 52 +++++++++++++++++++++++++++++ src/python/magnum/test/test_math.py | 30 +++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) diff --git a/src/python/magnum/__init__.py b/src/python/magnum/__init__.py index 6a29ae8..b227129 100644 --- a/src/python/magnum/__init__.py +++ b/src/python/magnum/__init__.py @@ -28,5 +28,7 @@ from ._magnum import * __all__ = [ - 'Deg', 'Rad' + 'Deg', 'Rad', + + 'BoolVector2', 'BoolVector3', 'BoolVector4', ] diff --git a/src/python/magnum/math.cpp b/src/python/magnum/math.cpp index 52cb3d8..9fa5b4b 100644 --- a/src/python/magnum/math.cpp +++ b/src/python/magnum/math.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include "magnum/bootstrap.h" @@ -107,6 +108,49 @@ template void angle(py::class_& c) { .def("__repr__", repr, "Object representation"); } +template void boolVector(py::class_& c) { + c + /* Constructors */ + .def_static("zero_init", []() { + return T{Math::ZeroInit}; + }, "Construct a zero-filled boolean vector") + .def(py::init(), "Default constructor") + .def(py::init(), "Construct a boolean vector with one value for all fields") + .def(py::init(), "Construct a boolean vector from segment values") + + /* Explicit conversion to bool */ + .def("__bool__", &T::operator bool, "Boolean conversion") + + /* Comparison */ + .def(py::self == py::self, "Equality comparison") + .def(py::self != py::self, "Non-equality comparison") + + /* Member functions */ + .def("all", &T::all, "Whether all bits are set") + .def("none", &T::none, "Whether no bits are set") + .def("any", &T::any, "Whether any bit is set") + + /* Set / get */ + .def("__setitem__", &T::set, "Set a bit at given position", py::arg("i"), py::arg("value")) + .def("__getitem__", &T::operator[], "Bit at given position") + + /* Operators */ + .def(~py::self, "Bitwise inversion") + .def(py::self &= py::self, "Bitwise AND and assign") + .def(py::self & py::self, "Bitwise AND") + .def(py::self |= py::self, "Bitwise OR and assign") + .def(py::self | py::self, "Bitwise OR") + .def(py::self ^= py::self, "Bitwise XOR and assign") + .def(py::self ^ py::self, "Bitwise XOR") + + .def("__repr__", repr, "Object representation"); + + /* Vector length */ + char lenDocstring[] = "Vector size. Returns _."; + lenDocstring[sizeof(lenDocstring) - 3] = '0' + T::Size; + c.def_static("__len__", []() { return int(T::Size); }, lenDocstring); +} + } void math(py::module& root, py::module& m) { @@ -119,6 +163,14 @@ void math(py::module& root, py::module& m) { rad.def(py::init(), "Conversion from degrees"); angle(deg); angle(rad); + + /* BoolVector */ + py::class_> boolVector2{root, "BoolVector2", "Two-component bool vector"}; + py::class_> boolVector3{root, "BoolVector3", "Three-component bool vector"}; + py::class_> boolVector4{root, "BoolVector4", "Four-component bool vector"}; + boolVector(boolVector2); + boolVector(boolVector3); + boolVector(boolVector4); } } diff --git a/src/python/magnum/test/test_math.py b/src/python/magnum/test/test_math.py index 413833e..24af6f6 100644 --- a/src/python/magnum/test/test_math.py +++ b/src/python/magnum/test/test_math.py @@ -67,3 +67,33 @@ class Angle(unittest.TestCase): def test_repr(self): self.assertEqual(repr(Deg(45.3)), 'Deg(45.3)') + +class BoolVector(unittest.TestCase): + def test_init(self): + a = BoolVector2() + b = BoolVector2.zero_init() + c = BoolVector2(0b11) + self.assertFalse(a.any()) + self.assertTrue(c.all()) + self.assertEqual(a, BoolVector2(0b00)) + self.assertEqual(b, BoolVector2(0b00)) + self.assertEqual(c, BoolVector2(0b11)) + + def test_length(self): + self.assertEqual(BoolVector3.__len__(), 3) + #self.assertEqual(len(BoolVector3), 3) TODO: Y not? + self.assertEqual(len(BoolVector4()), 4) + + def test_set_get(self): + a = BoolVector4(0b1010) + self.assertEqual(a[1], 1) + + a[2] = True + self.assertEqual(a, BoolVector4(0b1110)) + + def test_ops(self): + a = BoolVector3(0b101) | BoolVector3(0b010) + self.assertEqual(a, BoolVector3(0b111)) + + def test_repr(self): + self.assertEqual(repr(BoolVector4(0b0101)), 'BoolVector(0b0101)')