Browse Source

python: expose matrix types.

Not the Matrix4 / Matrix3 transformation types yet, though.
pull/1/head
Vladimír Vondruš 7 years ago
parent
commit
44503539e7
  1. 2
      src/python/magnum/CMakeLists.txt
  2. 7
      src/python/magnum/__init__.py
  3. 2
      src/python/magnum/bootstrap.h
  4. 2
      src/python/magnum/magnum.cpp
  5. 337
      src/python/magnum/math.matrix.h
  6. 49
      src/python/magnum/math.matrixdouble.cpp
  7. 49
      src/python/magnum/math.matrixfloat.cpp
  8. 96
      src/python/magnum/test/test_math.py

2
src/python/magnum/CMakeLists.txt

@ -26,6 +26,8 @@
set(magnum_SRCS
magnum.cpp
math.cpp
math.matrixfloat.cpp
math.matrixdouble.cpp
math.vectorfloat.cpp
math.vectorintegral.cpp)

7
src/python/magnum/__init__.py

@ -35,4 +35,11 @@ __all__ = [
'Vector2d', 'Vector3d', 'Vector4d',
'Vector2i', 'Vector3i', 'Vector4i',
'Vector2ui', 'Vector3ui', 'Vector4ui',
'Matrix2x2', 'Matrix2x3', 'Matrix2x4',
'Matrix3x2', 'Matrix3x3', 'Matrix3x4',
'Matrix4x2', 'Matrix4x3', 'Matrix4x4',
'Matrix2x2d', 'Matrix2x3d', 'Matrix2x4d',
'Matrix3x2d', 'Matrix3x3d', 'Matrix3x4d',
'Matrix4x2d', 'Matrix4x3d', 'Matrix4x4d',
]

2
src/python/magnum/bootstrap.h

@ -36,6 +36,8 @@ namespace py = pybind11;
void math(py::module& root, py::module& m);
void mathVectorFloat(py::module& root, py::module& m);
void mathVectorIntegral(py::module& root, py::module& m);
void mathMatrixFloat(py::module& root);
void mathMatrixDouble(py::module& root);
}

2
src/python/magnum/magnum.cpp

@ -36,4 +36,6 @@ PYBIND11_MODULE(_magnum, m) {
magnum::math(m, math);
magnum::mathVectorFloat(m, math);
magnum::mathVectorIntegral(m, math);
magnum::mathMatrixFloat(m);
magnum::mathMatrixDouble(m);
}

337
src/python/magnum/math.matrix.h

@ -0,0 +1,337 @@
#ifndef magnum_math_matrix_h
#define magnum_math_matrix_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include <pybind11/pybind11.h>
#include <pybind11/operators.h>
#include "Magnum/Math/Matrix.h"
#include "Magnum/Math/Vector4.h"
#include "magnum/math.h"
namespace magnum {
/* A variant of Magnum's own DimensionTraits, but working for 2/3/4 dimensions
instead of 1/2/3 dimensions */
template<UnsignedInt, class> struct VectorTraits;
template<class T> struct VectorTraits<2, T> { typedef Math::Vector2<T> Type; };
template<class T> struct VectorTraits<3, T> { typedef Math::Vector3<T> Type; };
template<class T> struct VectorTraits<4, T> { typedef Math::Vector4<T> Type; };
template<class T> void rectangularMatrix(py::class_<T>& c) {
/*
Missing APIs:
from(T*)
fromVector() (would need Vector6,...Vector16 for that)
Type
construction from different types
construction by slicing or expanding differently sized matrices
row() / setRow() (function? that's ugly. property? not sure how)
component-wise operations (would need BoolVector6 ... BoolVector16)
ij() (doesn't make sense in generic code as we don't have Matrix1)
*/
c
/* Constructors */
.def_static("from_diagonal", [](const typename VectorTraits<T::DiagonalSize, typename T::Type>::Type& vector) {
return T::fromDiagonal(vector);
}, "Construct a diagonal matrix")
.def_static("zero_init", []() {
return T{Math::ZeroInit};
}, "Construct a zero-filled matrix")
.def(py::init(), "Default constructor")
.def(py::init<typename T::Type>(), "Construct a matrix with one value for all components")
/* Comparison */
.def(py::self == py::self, "Equality comparison")
.def(py::self != py::self, "Non-equality comparison")
/* Set / get. Need to throw IndexError in order to allow iteration:
https://docs.python.org/3/reference/datamodel.html#object.__getitem__ */
.def("__setitem__", [](T& self, std::size_t i, const typename VectorTraits<T::Rows, typename T::Type>::Type& value) {
if(i >= T::Cols) throw pybind11::index_error{};
self[i] = value;
}, "Set a column at given position")
.def("__getitem__", [](const T& self, std::size_t i) -> typename VectorTraits<T::Rows, typename T::Type>::Type {
if(i >= T::Cols) throw pybind11::index_error{};
return self[i];
}, "Column at given position")
/* Set / get for direct elements, because [a][b] = 2.5 won't work
without involving shared pointers */
.def("__setitem__", [](T& self, const std::pair<std::size_t, std::size_t>& i, typename T::Type value) {
if(i.first >= T::Cols || i.second >= T::Rows) throw pybind11::index_error{};
self[i.first][i.second] = value;
}, "Set a value at given col/row")
.def("__getitem__", [](const T& self, const std::pair<std::size_t, std::size_t>& i) {
if(i.first >= T::Cols || i.second >= T::Rows) throw pybind11::index_error{};
return self[i.first][i.second];
}, "Value at given col/row")
/* Operators */
.def(-py::self, "Negated matrix")
.def(py::self += py::self, "Add and assign a matrix")
.def(py::self + py::self, "Add a matrix")
.def(py::self -= py::self, "Subtract and assign a matrix")
.def(py::self - py::self, "Subtract a matrix")
.def(py::self *= typename T::Type{}, "Multiply with a scalar and assign")
.def(py::self * typename T::Type{}, "Multiply with a scalar")
.def(py::self /= typename T::Type{}, "Divide with a scalar and assign")
.def(py::self / typename T::Type{}, "Divide with a scalar")
.def("__mul__", [](const T& self, const typename VectorTraits<T::Cols, typename T::Type>::Type& vector) -> typename VectorTraits<T::Rows, typename T::Type>::Type {
return self*vector;
}, "Multiply a vector")
.def(typename T::Type{} * py::self, "Multiply a scalar with a matrix")
.def(typename T::Type{} / py::self, "Divide a matrix with a scalar and invert")
/* Member functions that don't return a size-dependent type */
.def("flipped_cols", &T::flippedCols, "Matrix with flipped cols")
.def("flipped_rows", &T::flippedRows, "Matrix with flipped rows")
.def("diagonal", [](const T& self) -> typename VectorTraits<T::DiagonalSize, typename T::Type>::Type {
return self.diagonal();
}, "Values on diagonal")
.def("__repr__", repr<T>, "Object representation");
/* Matrix column count */
char lenDocstring[] = "Matrix column count. Returns _.";
lenDocstring[sizeof(lenDocstring) - 3] = '0' + T::Cols;
c.def_static("__len__", []() { return int(T::Cols); }, lenDocstring);
}
template<class T> void matrix(py::class_<T>& c) {
c
/* Constructors */
.def_static("identity_init", [](typename T::Type value) {
return T{Math::IdentityInit, value};
}, "Construct an identity matrix", py::arg("value") = typename T::Type(1))
/* Member functions for square matrices only */
.def("is_orthogonal", &T::isOrthogonal, "Whether the matrix is orthogonal")
.def("trace", &T::trace, "Trace of the matrix")
.def("determinant", &T::determinant, "Determinant")
.def("inverted", &T::inverted, "Inverted matrix")
.def("inverted_orthogonal", &T::invertedOrthogonal, "Inverted orthogonal matrix");
}
template<class T> void matrices(
py::class_<Math::Matrix2x2<T>>& matrix2x2,
py::class_<Math::Matrix2x3<T>>& matrix2x3,
py::class_<Math::Matrix2x4<T>>& matrix2x4,
py::class_<Math::Matrix3x2<T>>& matrix3x2,
py::class_<Math::Matrix3x3<T>>& matrix3x3,
py::class_<Math::Matrix3x4<T>>& matrix3x4,
py::class_<Math::Matrix4x2<T>>& matrix4x2,
py::class_<Math::Matrix4x3<T>>& matrix4x3,
py::class_<Math::Matrix4x4<T>>& matrix4x4
) {
/* Two-column matrices */
matrix2x2
.def(py::init<const Math::Vector2<T>&, const Math::Vector2<T>&>(),
"Construct from column vectors")
.def(py::init([](const std::tuple<Math::Vector2<T>, Math::Vector2<T>>& value) {
return Math::Matrix2x2<T>{std::get<0>(value), std::get<1>(value)};
}), "Construct from a column vector tuple")
.def("__matmul__", [](const Math::Matrix2x2<T>& self, const Math::Matrix2x2<T>& other) -> Math::Matrix2x2<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix2x2<T>& self, const Math::Matrix3x2<T>& other) -> Math::Matrix3x2<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix2x2<T>& self, const Math::Matrix4x2<T>& other) -> Math::Matrix4x2<T> {
return self*other;
}, "Multiply a matrix")
.def("transposed", [](const Math::Matrix2x2<T>& self) -> Math::Matrix2x2<T> {
return self.transposed();
}, "Transposed matrix");
matrix2x3
.def(py::init<const Math::Vector3<T>&, const Math::Vector3<T>&>(),
"Construct from column vectors")
.def(py::init([](const std::tuple<Math::Vector3<T>, Math::Vector3<T>>& value) {
return Math::Matrix2x3<T>{std::get<0>(value), std::get<1>(value)};
}), "Construct from a column vector tuple")
.def("__matmul__", [](const Math::Matrix2x3<T>& self, const Math::Matrix2x2<T>& other) -> Math::Matrix2x3<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix2x3<T>& self, const Math::Matrix3x2<T>& other) -> Math::Matrix3x3<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix2x3<T>& self, const Math::Matrix4x2<T>& other) -> Math::Matrix4x3<T> {
return self*other;
}, "Multiply a matrix")
.def("transposed", [](const Math::Matrix2x3<T>& self) -> Math::Matrix3x2<T> {
return self.transposed();
}, "Transposed matrix");
matrix2x4
.def(py::init<const Math::Vector4<T>&, const Math::Vector4<T>&>(),
"Construct from column vectors")
.def(py::init([](const std::tuple<Math::Vector4<T>, Math::Vector4<T>>& value) {
return Math::Matrix2x4<T>{std::get<0>(value), std::get<1>(value)};
}), "Construct from a column vector tuple")
.def("__matmul__", [](const Math::Matrix2x4<T>& self, const Math::Matrix2x2<T>& other) -> Math::Matrix2x4<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix2x4<T>& self, const Math::Matrix3x2<T>& other) -> Math::Matrix3x4<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix2x4<T>& self, const Math::Matrix4x2<T>& other) -> Math::Matrix4x4<T> {
return self*other;
}, "Multiply a matrix")
.def("transposed", [](const Math::Matrix2x4<T>& self) -> Math::Matrix4x2<T> {
return self.transposed();
}, "Transposed matrix");
rectangularMatrix(matrix2x2);
rectangularMatrix(matrix2x3);
rectangularMatrix(matrix2x4);
matrix(matrix2x2);
/* Three-column matrices */
matrix3x2
.def(py::init<const Math::Vector2<T>&, const Math::Vector2<T>&, const Math::Vector2<T>&>(),
"Construct from column vectors")
.def(py::init([](const std::tuple<Math::Vector2<T>, Math::Vector2<T>, Math::Vector2<T>>& value) {
return Math::Matrix3x2<T>{std::get<0>(value), std::get<1>(value), std::get<2>(value)};
}), "Construct from a column vector tuple")
.def("__matmul__", [](const Math::Matrix3x2<T>& self, const Math::Matrix2x3<T>& other) -> Math::Matrix2x2<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix3x2<T>& self, const Math::Matrix3x3<T>& other) -> Math::Matrix3x2<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix3x2<T>& self, const Math::Matrix4x3<T>& other) -> Math::Matrix4x2<T> {
return self*other;
}, "Multiply a matrix")
.def("transposed", [](const Math::Matrix3x2<T>& self) -> Math::Matrix2x3<T> {
return self.transposed();
}, "Transposed matrix");
matrix3x3
.def(py::init<const Math::Vector3<T>&, const Math::Vector3<T>&, const Math::Vector3<T>&>(),
"Construct from column vectors")
.def(py::init([](const std::tuple<Math::Vector3<T>, Math::Vector3<T>, Math::Vector3<T>>& value) {
return Math::Matrix3x3<T>{std::get<0>(value), std::get<1>(value), std::get<2>(value)};
}), "Construct from a column vector tuple")
.def("__matmul__", [](const Math::Matrix3x3<T>& self, const Math::Matrix2x3<T>& other) -> Math::Matrix2x3<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix3x3<T>& self, const Math::Matrix3x3<T>& other) -> Math::Matrix3x3<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix3x3<T>& self, const Math::Matrix4x3<T>& other) -> Math::Matrix4x3<T> {
return self*other;
}, "Multiply a matrix")
.def("transposed", [](const Math::Matrix3x3<T>& self) -> Math::Matrix3x3<T> {
return self.transposed();
}, "Transposed matrix");
matrix3x4
.def(py::init<const Math::Vector4<T>&, const Math::Vector4<T>&, const Math::Vector4<T>&>(),
"Construct from column vectors")
.def(py::init([](const std::tuple<Math::Vector4<T>, Math::Vector4<T>, Math::Vector4<T>>& value) {
return Math::Matrix3x4<T>{std::get<0>(value), std::get<1>(value), std::get<2>(value)};
}), "Construct from a column vector tuple")
.def("__matmul__", [](const Math::Matrix3x4<T>& self, const Math::Matrix2x3<T>& other) -> Math::Matrix2x4<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix3x4<T>& self, const Math::Matrix3x3<T>& other) -> Math::Matrix3x4<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix3x4<T>& self, const Math::Matrix4x3<T>& other) -> Math::Matrix4x4<T> {
return self*other;
}, "Multiply a matrix")
.def("transposed", [](const Math::Matrix3x4<T>& self) -> Math::Matrix4x3<T> {
return self.transposed();
}, "Transposed matrix");
rectangularMatrix(matrix3x2);
rectangularMatrix(matrix3x3);
rectangularMatrix(matrix3x4);
matrix(matrix3x3);
/* Four-column matrices */
matrix4x2
.def(py::init<const Math::Vector2<T>&, const Math::Vector2<T>&, const Math::Vector2<T>&, const Math::Vector2<T>&>(),
"Construct from column vectors")
.def(py::init([](const std::tuple<Math::Vector2<T>, Math::Vector2<T>, Math::Vector2<T>, Math::Vector2<T>>& value) {
return Math::Matrix4x2<T>{std::get<0>(value), std::get<1>(value), std::get<2>(value), std::get<3>(value)};
}), "Construct from a column vector tuple")
.def("__matmul__", [](const Math::Matrix4x2<T>& self, const Math::Matrix2x4<T>& other) -> Math::Matrix2x2<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix4x2<T>& self, const Math::Matrix3x4<T>& other) -> Math::Matrix3x2<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix4x2<T>& self, const Math::Matrix4x4<T>& other) -> Math::Matrix4x2<T> {
return self*other;
}, "Multiply a matrix")
.def("transposed", [](const Math::Matrix4x2<T>& self) -> Math::Matrix2x4<T> {
return self.transposed();
}, "Transposed matrix");
matrix4x3
.def(py::init<const Math::Vector3<T>&, const Math::Vector3<T>&, const Math::Vector3<T>&, const Math::Vector3<T>&>(),
"Construct from column vectors")
.def(py::init([](const std::tuple<Math::Vector3<T>, Math::Vector3<T>, Math::Vector3<T>, Math::Vector3<T>>& value) {
return Math::Matrix4x3<T>{std::get<0>(value), std::get<1>(value), std::get<2>(value), std::get<3>(value)};
}), "Construct from a column vector tuple")
.def("__matmul__", [](const Math::Matrix4x3<T>& self, const Math::Matrix2x4<T>& other) -> Math::Matrix2x3<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix4x3<T>& self, const Math::Matrix3x4<T>& other) -> Math::Matrix3x3<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix4x3<T>& self, const Math::Matrix4x4<T>& other) -> Math::Matrix4x3<T> {
return self*other;
}, "Multiply a matrix")
.def("transposed", [](const Math::Matrix4x3<T>& self) -> Math::Matrix3x4<T> {
return self.transposed();
}, "Transposed matrix");
matrix4x4
.def(py::init<const Math::Vector4<T>&, const Math::Vector4<T>&, const Math::Vector4<T>&, const Math::Vector4<T>&>(),
"Construct from column vectors")
.def(py::init([](const std::tuple<Math::Vector4<T>, Math::Vector4<T>, Math::Vector4<T>, Math::Vector4<T>>& value) {
return Math::Matrix4x4<T>{std::get<0>(value), std::get<1>(value), std::get<2>(value), std::get<3>(value)};
}), "Construct from a column vector tuple")
.def("__matmul__", [](const Math::Matrix4x4<T>& self, const Math::Matrix2x4<T>& other) -> Math::Matrix2x4<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix4x4<T>& self, const Math::Matrix3x4<T>& other) -> Math::Matrix3x4<T> {
return self*other;
}, "Multiply a matrix")
.def("__matmul__", [](const Math::Matrix4x4<T>& self, const Math::Matrix4x4<T>& other) -> Math::Matrix4x4<T> {
return self*other;
}, "Multiply a matrix")
.def("transposed", [](const Math::Matrix4x4<T>& self) -> Math::Matrix4x4<T> {
return self.transposed();
}, "Transposed matrix");
rectangularMatrix(matrix4x2);
rectangularMatrix(matrix4x3);
rectangularMatrix(matrix4x4);
matrix(matrix4x4);
}
}
#endif

49
src/python/magnum/math.matrixdouble.cpp

@ -0,0 +1,49 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "magnum/math.matrix.h"
namespace magnum {
void mathMatrixDouble(py::module& root) {
py::class_<Matrix2x2d> matrix2x2d{root, "Matrix2x2d", "2x2 double matrix"};
py::class_<Matrix2x3d> matrix2x3d{root, "Matrix2x3d", "2x3 double matrix"};
py::class_<Matrix2x4d> matrix2x4d{root, "Matrix2x4d", "2x4 double matrix"};
py::class_<Matrix3x2d> matrix3x2d{root, "Matrix3x2d", "3x2 double matrix"};
py::class_<Matrix3x3d> matrix3x3d{root, "Matrix3x3d", "3x3 double matrix"};
py::class_<Matrix3x4d> matrix3x4d{root, "Matrix3x4d", "3x4 double matrix"};
py::class_<Matrix4x2d> matrix4x2d{root, "Matrix4x2d", "4x2 double matrix"};
py::class_<Matrix4x3d> matrix4x3d{root, "Matrix4x3d", "4x3 double matrix"};
py::class_<Matrix4x4d> matrix4x4d{root, "Matrix4x4d", "4x4 double matrix"};
matrices<Double>(
matrix2x2d, matrix2x3d, matrix2x4d,
matrix3x2d, matrix3x3d, matrix3x4d,
matrix4x2d, matrix4x3d, matrix4x4d);
}
}

49
src/python/magnum/math.matrixfloat.cpp

@ -0,0 +1,49 @@
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
#include "magnum/math.matrix.h"
namespace magnum {
void mathMatrixFloat(py::module& root) {
py::class_<Matrix2x2> matrix2x2{root, "Matrix2x2", "2x2 float matrix"};
py::class_<Matrix2x3> matrix2x3{root, "Matrix2x3", "2x3 float matrix"};
py::class_<Matrix2x4> matrix2x4{root, "Matrix2x4", "2x4 float matrix"};
py::class_<Matrix3x2> matrix3x2{root, "Matrix3x2", "3x2 float matrix"};
py::class_<Matrix3x3> matrix3x3{root, "Matrix3x3", "3x3 float matrix"};
py::class_<Matrix3x4> matrix3x4{root, "Matrix3x4", "3x4 float matrix"};
py::class_<Matrix4x2> matrix4x2{root, "Matrix4x2", "4x2 float matrix"};
py::class_<Matrix4x3> matrix4x3{root, "Matrix4x3", "4x3 float matrix"};
py::class_<Matrix4x4> matrix4x4{root, "Matrix4x4", "4x4 float matrix"};
matrices<Float>(
matrix2x2, matrix2x3, matrix2x4,
matrix3x2, matrix3x3, matrix3x4,
matrix4x2, matrix4x3, matrix4x4);
}
}

96
src/python/magnum/test/test_math.py

@ -249,3 +249,99 @@ class Vector(unittest.TestCase):
def test_repr(self):
self.assertEqual(repr(Vector3(1.0, 3.14, -13.37)), 'Vector(1, 3.14, -13.37)')
class Matrix(unittest.TestCase):
def test_init(self):
a = Matrix3x2()
self.assertEqual(a[0], Vector2(0))
self.assertEqual(a[1], Vector2(0))
self.assertEqual(a[2], Vector2(0))
b = Matrix4x4.zero_init()
self.assertEqual(b[0], Vector4(0))
self.assertEqual(b[1], Vector4(0))
self.assertEqual(b[2], Vector4(0))
self.assertEqual(b[3], Vector4(0))
c1 = Matrix3x3.identity_init()
self.assertEqual(c1[0], Vector3.x_axis())
self.assertEqual(c1[1], Vector3.y_axis())
self.assertEqual(c1[2], Vector3.z_axis())
c3 = Matrix3x3.identity_init(3.0)
self.assertEqual(c3[0], Vector3.x_axis(3.0))
self.assertEqual(c3[1], Vector3.y_axis(3.0))
self.assertEqual(c3[2], Vector3.z_axis(3.0))
d = Matrix2x3(Vector3(1.0, 2.0, 3.0),
Vector3(4.0, 5.0, 6.0))
self.assertEqual(d[0], Vector3(1.0, 2.0, 3.0))
self.assertEqual(d[1], Vector3(4.0, 5.0, 6.0))
e = Matrix2x3((1.0, 2.0, 3.0),
(4.0, 5.0, 6.0))
self.assertEqual(e[0], Vector3(1.0, 2.0, 3.0))
self.assertEqual(e[1], Vector3(4.0, 5.0, 6.0))
f = Matrix3x2(((1.0, 2.0),
(3.0, 4.0),
(5.0, 6.0)))
self.assertEqual(f[0], Vector2(1.0, 2.0))
self.assertEqual(f[1], Vector2(3.0, 4.0))
self.assertEqual(f[2], Vector2(5.0, 6.0))
def test_length(self):
self.assertEqual(Matrix3x4.__len__(), 3)
#self.assertEqual(len(Matrix4x3), 4) TODO: Y not?
self.assertEqual(len(Matrix4x3()), 4)
def test_set_get(self):
a = Matrix2x3((1.0, 2.0, 3.0),
(4.0, 5.0, 6.0))
self.assertEqual(a[1][2], 6.0)
a[1] = (4.5, 5.5, 6.5)
self.assertEqual(a[1], Vector3(4.5, 5.5, 6.5))
a[0, 1] = 2.5
self.assertEqual(a[0], Vector3(1.0, 2.5, 3.0)) # yes, 2.5
@unittest.expectedFailure
def test_set_two_brackets(self):
a = Matrix2x3((1.0, 2.0, 3.0),
(4.0, 5.0, 6.0))
a[0][1] = 2.5
self.assertEqual(a[0], Vector3(1.0, 2.5, 3.0))
def test_iterate(self):
a = Matrix3x2((1.0, 2.0),
(3.0, 4.0),
(5.0, 6.0))
self.assertEqual([i.sum() for i in a], [3.0, 7.0, 11.0])
def test_ops(self):
a = Matrix2x3((1.0, 2.0, 3.0),
(4.0, 5.0, 6.0))
b = Matrix3x2((1.0, 2.0),
(3.0, 4.0),
(5.0, 6.0))
c = Matrix3x3((9.0, 12.0, 15.0),
(19.0, 26.0, 33.0),
(29.0, 40.0, 51.0))
self.assertEqual(a @ b, c)
def test_ops_number_on_the_left(self):
a = Matrix2x3((1.0, 2.0, 3.0),
(4.0, 5.0, 6.0))
self.assertEqual(2.0*a, Matrix2x3((2.0, 4.0, 6.0),
(8.0, 10.0, 12.0)))
self.assertEqual(6.0/a, Matrix2x3((6.0, 3.0, 2.0),
(1.5, 1.2, 1.0)))
def test_repr(self):
a = Matrix2x3((1.0, 2.0, 3.0),
(4.0, 5.0, 6.0))
self.assertEqual(repr(a), 'Matrix(1, 4,\n'
' 2, 5,\n'
' 3, 6)')

Loading…
Cancel
Save