%PDF- %PDF-
Direktori : /usr/include/Imath/ |
Current File : //usr/include/Imath/PyImathFixedMatrix.h |
// // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathFixedMatrix_h_ #define _PyImathFixedMatrix_h_ #include <boost/python.hpp> #include <iostream> #include "PyImathFixedArray.h" #include "PyImathOperators.h" namespace PyImath { // // Utility class for a runtime-specified fixed sized matrix type in python // template <class T> class FixedMatrix { T * _ptr; int _rows; int _cols; int _rowStride; int _colStride; int * _refcount; // refcount if allocated, null if externally allocated public: FixedMatrix(T *ptr, int rows, int cols, int rowStride = 1, int colStride = 1) : _ptr(ptr), _rows(rows), _cols(cols), _rowStride(rowStride), _colStride(colStride), _refcount(0) { // nothing } FixedMatrix(int rows, int cols) : _ptr(new T[rows*cols]), _rows(rows), _cols(cols), _rowStride(1), _colStride(1), _refcount(new int(1)) { // nothing } FixedMatrix(const FixedMatrix &other) : _ptr(other._ptr), _rows(other._rows), _cols(other._cols), _rowStride(other._rowStride), _colStride(other._colStride), _refcount(other._refcount) { if (_refcount) *_refcount += 1; } const FixedMatrix & operator = (const FixedMatrix &other) { if (&other == this) return *this; unref(); _ptr = other._ptr; _rows = other._rows; _cols = other._cols; _rowStride = other._rowStride; _colStride = other._colStride; _refcount = other._refcount; if (_refcount) *_refcount += 1; return *this; } void unref() { if (_refcount) { *_refcount -= 1; if (*_refcount == 0) { delete [] _ptr; delete _refcount; } } _ptr = 0; _rows = 0; _cols = 0; _rowStride = 0; _colStride = 0; _refcount = 0; } ~FixedMatrix() { unref(); } Py_ssize_t convert_index(int index) const { if (index < 0) index += _rows; if (index >= _rows || index < 0) { PyErr_SetString(PyExc_IndexError, "Index out of range"); boost::python::throw_error_already_set(); } return index; } void extract_slice_indices(PyObject *index, Py_ssize_t &start, Py_ssize_t &end, Py_ssize_t &step, Py_ssize_t &slicelength) const { slicelength = 0; if (PySlice_Check(index)) { #if PY_MAJOR_VERSION > 2 PyObject *slice = index; #else PySliceObject *slice = reinterpret_cast<PySliceObject *>(index); #endif if (PySlice_GetIndicesEx(slice,_rows,&start,&end,&step,&slicelength) == -1) { boost::python::throw_error_already_set(); } } else if (PyInt_Check(index)) { Py_ssize_t i = convert_index(PyInt_AS_LONG(index)); start = i; end = i+1; step = 1; slicelength = 1; } else { PyErr_SetString(PyExc_TypeError, "Object is not a slice"); boost::python::throw_error_already_set(); } //std::cout << "Slice indices are " << start << " " << end << " " << step << " " << slicelength << std::endl; } const FixedArray<T> * getitem(int index) const { return new FixedArray<T>(const_cast<T *>(&_ptr[convert_index(index)*_rowStride*_cols*_colStride]),_cols,_colStride); } FixedMatrix getslice(PyObject *index) const { Py_ssize_t start, end, step, slicelength; extract_slice_indices(index,start,end,step,slicelength); FixedMatrix f(slicelength,_cols); for (int i=0; i<slicelength; ++i) { for (int j=0; j<_cols; ++j) { f.element(i,j) = element((start+i*step),j); } } return f; } void setitem_scalar(PyObject *index, const T &data) { Py_ssize_t start, end, step, slicelength; extract_slice_indices(index,start,end,step,slicelength); for (int i=0; i<slicelength; ++i) { for (int j = 0; j < _cols; ++j) { element(start+i*step,j) = data; } } } void setitem_vector(PyObject *index, const FixedArray<T> &data) { Py_ssize_t start, end, step, slicelength; extract_slice_indices(index,start,end,step,slicelength); if (data.len() != _cols) { PyErr_SetString(PyExc_IndexError, "Dimensions of source do not match destination"); boost::python::throw_error_already_set(); } for (int i=0; i<slicelength; ++i) { for (int j = 0; j < _cols; ++j) { element(start+i*step,j) = data[j]; } } } void setitem_matrix(PyObject *index, const FixedMatrix &data) { Py_ssize_t start, end, step, slicelength; extract_slice_indices(index,start,end,step,slicelength); // we have a valid range of indices if (data.rows() != slicelength || data.cols() != cols()) { PyErr_SetString(PyExc_IndexError, "Dimensions of source do not match destination"); boost::python::throw_error_already_set(); } for (int i=0; i<slicelength; ++i) { for (int j=0; j<cols(); ++j) { element(start+i*step,j) = data.element(i,j); } } } int rows() const { return _rows; } int cols() const { return _cols; } int rowStride() const { return _rowStride; } int colStride() const { return _colStride; } T & element(int i, int j) { return _ptr[i*_rowStride*_cols*_colStride+j*_colStride]; } const T & element(int i, int j) const { return _ptr[i*_rowStride*_cols*_colStride+j*_colStride]; } FixedArray<T> operator [] (int i) { return FixedArray<T>(&_ptr[i*_rowStride*_cols*_colStride],_cols,_colStride); } const FixedArray<T> operator [] (int i) const { return FixedArray<T>(const_cast<T *>(&_ptr[i*_rowStride*_cols*_colStride]),_cols,_colStride); } static boost::python::class_<FixedMatrix<T> > register_(const char *name, const char *doc) { boost::python::class_<FixedMatrix<T> > c(name,doc, boost::python::init<int,int>("return an unitialized array of the specified rows and cols")); c .def("__getitem__", &FixedMatrix<T>::getslice) .def("__getitem__", &FixedMatrix<T>::getitem, boost::python::return_internal_reference<>()) .def("__setitem__", &FixedMatrix<T>::setitem_scalar) .def("__setitem__", &FixedMatrix<T>::setitem_vector) .def("__setitem__", &FixedMatrix<T>::setitem_matrix) .def("__len__",&FixedMatrix<T>::rows) .def("rows",&FixedMatrix<T>::rows) .def("columns",&FixedMatrix<T>::cols) ; return c; } template <class T2> int match_dimension(const FixedMatrix<T2> &a1) const { if (rows() != a1.rows() || cols() != a1.cols()) { PyErr_SetString(PyExc_IndexError, "Dimensions of source do not match destination"); boost::python::throw_error_already_set(); } return rows(); } }; // unary operation application template <template <class,class> class Op, class T1, class Ret> FixedMatrix<Ret> apply_matrix_unary_op(const FixedMatrix<T1> &a1) { int rows = a1.rows(); int cols = a1.cols(); FixedMatrix<Ret> retval(rows,cols); for (int i=0;i<rows;++i) for (int j=0; j<cols; ++j) { retval.element(i,j) = Op<T1,Ret>::apply(a1.element(i,j)); } return retval; } // binary operation application template <template <class,class,class> class Op, class T1, class T2, class Ret> FixedMatrix<Ret> apply_matrix_matrix_binary_op(const FixedMatrix<T1> &a1, const FixedMatrix<T2> &a2) { int rows = a1.match_dimension(a2); int cols = a1.cols(); FixedMatrix<Ret> retval(rows,cols); for (int i=0;i<rows;++i) for (int j=0; j<cols; ++j) { retval.element(i,j) = Op<T1,T2,Ret>::apply(a1.element(i,j),a2.element(i,j)); } return retval; } template <template <class,class,class> class Op, class T1, class T2, class Ret> FixedMatrix<Ret> apply_matrix_scalar_binary_op(const FixedMatrix<T1> &a1, const T2 &a2) { int rows = a1.rows(); int cols = a1.cols(); FixedMatrix<Ret> retval(rows,cols); for (int i=0;i<rows;++i) for (int j=0; j<cols; ++j) { retval.element(i,j) = Op<T1,T2,Ret>::apply(a1.element(i,j),a2); } return retval; } template <template <class,class,class> class Op, class T1, class T2, class Ret> FixedMatrix<Ret> apply_matrix_scalar_binary_rop(const FixedMatrix<T1> &a1, const T2 &a2) { int rows = a1.rows(); int cols = a1.cols(); FixedMatrix<Ret> retval(rows,cols); for (int i=0;i<rows;++i) for (int j=0; j<cols; ++j) { retval.element(i,j) = Op<T2,T1,Ret>::apply(a2,a1.element(i,j)); } return retval; } // in-place binary operation application template <template <class,class> class Op, class T1, class T2> FixedMatrix<T1> & apply_matrix_matrix_ibinary_op(FixedMatrix<T1> &a1, const FixedMatrix<T2> &a2) { int rows = a1.match_dimension(a2); int cols = a1.cols(); for (int i=0;i<rows;++i) for (int j=0; j<cols; ++j) { Op<T1,T2>::apply(a1.element(i,j),a2.element(i,j)); } return a1; } // in-place binary operation application template <template <class,class> class Op, class T1, class T2> FixedMatrix<T1> & apply_matrix_scalar_ibinary_op(FixedMatrix<T1> &a1, const T2 &a2) { int rows = a1.rows(); int cols = a1.cols(); for (int i=0;i<rows;++i) for (int j=0; j<cols; ++j) { Op<T1,T2>::apply(a1.element(i,j),a2); } return a1; } // PyObject* PyNumber_Add( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> operator + (const FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_binary_op<op_add,T,T,T>(a0,a1); } template <class T> static FixedMatrix<T> operator + (const FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_binary_op<op_add,T,T,T>(a0,v1); } template <class T> static FixedMatrix<T> operator + (const T &v1, const FixedMatrix<T> &a0) { return a0+v1; } // PyObject* PyNumber_Subtract( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> operator - (const FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_binary_op<op_sub,T,T,T>(a0,a1); } template <class T> static FixedMatrix<T> operator - (const FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_binary_op<op_sub,T,T,T>(a0,v1); } template <class T> static FixedMatrix<T> operator - (const T &v1, const FixedMatrix<T> &a0) { return apply_matrix_scalar_binary_op<op_rsub,T,T,T>(a0,v1); } // PyObject* PyNumber_Multiply( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> operator * (const FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_binary_op<op_mul,T,T,T>(a0,a1); } template <class T> static FixedMatrix<T> operator * (const FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_binary_op<op_mul,T,T,T>(a0,v1); } template <class T> static FixedMatrix<T> operator * (const T &v1, const FixedMatrix<T> &a0) { return a0*v1; } // PyObject* PyNumber_Divide( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> operator / (const FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_binary_op<op_div,T,T,T>(a0,a1); } template <class T> static FixedMatrix<T> operator / (const FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_binary_op<op_div,T,T,T>(a0,v1); } // no reversed scalar/matrix divide - no meaning // PyObject* PyNumber_FloorDivide( PyObject *o1, PyObject *o2) // PyObject* PyNumber_TrueDivide( PyObject *o1, PyObject *o2) // PyObject* PyNumber_Remainder( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> operator % (const FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_binary_op<op_mod,T,T,T>(a0,a1); } template <class T> static FixedMatrix<T> operator % (const FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_binary_op<op_mod,T,T,T>(a0,v1); } // no reversed scalar%matrix remainder - no meaning // PyObject* PyNumber_Divmod( PyObject *o1, PyObject *o2) // PyObject* PyNumber_Power( PyObject *o1, PyObject *o2, PyObject *o3) template <class T> static FixedMatrix<T> pow_matrix_matrix (const FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_binary_op<op_pow,T,T,T>(a0,a1); } template <class T> static FixedMatrix<T> pow_matrix_scalar (const FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_binary_op<op_pow,T,T,T>(a0,v1); } // no reversed scalar/matrix pow - no meaning // PyObject* PyNumber_Negative( PyObject *o) template <class T> static FixedMatrix<T> operator - (const FixedMatrix<T> &a0) { return apply_matrix_unary_op<op_neg,T,T>(a0); } // PyObject* PyNumber_Positive( PyObject *o) // PyObject* PyNumber_Absolute( PyObject *o) template <class T> static FixedMatrix<T> abs (const FixedMatrix<T> &a0) { return apply_matrix_unary_op<op_abs,T,T>(a0); } // PyObject* PyNumber_Invert( PyObject *o) template <class T> static FixedMatrix<T> operator ~ (const FixedMatrix<T> &a0) { return apply_matrix_unary_op<op_inverse,T,T>(a0); } // PyObject* PyNumber_Lshift( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> operator << (const FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_binary_op<op_lshift,T,T,T>(a0,a1); } template <class T> static FixedMatrix<T> operator << (const FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_binary_op<op_lshift,T,T,T>(a0,v1); } // no reversed // PyObject* PyNumber_Rshift( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> operator >> (const FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_binary_op<op_rshift,T,T,T>(a0,a1); } template <class T> static FixedMatrix<T> operator >> (const FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_binary_op<op_rshift,T,T,T>(a0,v1); } // no reversed // PyObject* PyNumber_And( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> operator & (const FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_binary_op<op_bitand,T,T,T>(a0,a1); } template <class T> static FixedMatrix<T> operator & (const FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_binary_op<op_bitand,T,T,T>(a0,v1); } template <class T> static FixedMatrix<T> operator & (const T &v1, const FixedMatrix<T> &a0) { return a0&v1; } // PyObject* PyNumber_Xor( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> operator ^ (const FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_binary_op<op_xor,T,T,T>(a0,a1); } template <class T> static FixedMatrix<T> operator ^ (const FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_binary_op<op_xor,T,T,T>(a0,v1); } template <class T> static FixedMatrix<T> operator ^ (const T &v1, const FixedMatrix<T> &a0) { return a0^v1; } // PyObject* PyNumber_Or( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> operator | (const FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_binary_op<op_bitor,T,T,T>(a0,a1); } template <class T> static FixedMatrix<T> operator | (const FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_binary_op<op_bitor,T,T,T>(a0,v1); } template <class T> static FixedMatrix<T> operator | (const T &v1, const FixedMatrix<T> &a0) { return a0|v1; } // PyObject* PyNumber_InPlaceAdd( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> & operator += (FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_ibinary_op<op_iadd,T,T>(a0,a1); } template <class T> static FixedMatrix<T> & operator += (FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_ibinary_op<op_iadd,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceSubtract( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> & operator -= (FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_ibinary_op<op_isub,T,T>(a0,a1); } template <class T> static FixedMatrix<T> & operator -= (FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_ibinary_op<op_isub,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceMultiply( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> & operator *= (FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_ibinary_op<op_imul,T,T>(a0,a1); } template <class T> static FixedMatrix<T> & operator *= (FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_ibinary_op<op_imul,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceDivide( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> & operator /= (FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_ibinary_op<op_idiv,T,T>(a0,a1); } template <class T> static FixedMatrix<T> & operator /= (FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_ibinary_op<op_idiv,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceFloorDivide( PyObject *o1, PyObject *o2) // not implemented // PyObject* PyNumber_InPlaceTrueDivide( PyObject *o1, PyObject *o2) // not implemented // PyObject* PyNumber_InPlaceRemainder( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> & operator %= (FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_ibinary_op<op_imod,T,T>(a0,a1); } template <class T> static FixedMatrix<T> & operator %= (FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_ibinary_op<op_imod,T,T>(a0,v1); } // PyObject* PyNumber_InPlacePower( PyObject *o1, PyObject *o2, PyObject *o3) template <class T> static FixedMatrix<T> & ipow_matrix_matrix (FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_ibinary_op<op_ipow,T,T>(a0,a1); } template <class T> static FixedMatrix<T> & ipow_matrix_scalar (FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_ibinary_op<op_ipow,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceLshift( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> & operator <<= (FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_ibinary_op<op_ilshift,T,T>(a0,a1); } template <class T> static FixedMatrix<T> & operator <<= (FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_ibinary_op<op_ilshift,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceRshift( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> & operator >>= (FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_ibinary_op<op_irshift,T,T>(a0,a1); } template <class T> static FixedMatrix<T> & operator >>= (FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_ibinary_op<op_irshift,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceAnd( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> & operator &= (FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_ibinary_op<op_ibitand,T,T>(a0,a1); } template <class T> static FixedMatrix<T> & operator &= (FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_ibinary_op<op_ibitand,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceXor( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> & operator ^= (FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_ibinary_op<op_ixor,T,T>(a0,a1); } template <class T> static FixedMatrix<T> & operator ^= (FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_ibinary_op<op_ixor,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceOr( PyObject *o1, PyObject *o2) template <class T> static FixedMatrix<T> & operator |= (FixedMatrix<T> &a0, const FixedMatrix<T> &a1) { return apply_matrix_matrix_ibinary_op<op_ibitor,T,T>(a0,a1); } template <class T> static FixedMatrix<T> & operator |= (FixedMatrix<T> &a0, const T &v1) { return apply_matrix_scalar_ibinary_op<op_ibitor,T,T>(a0,v1); } template <class T> static void add_arithmetic_math_functions(boost::python::class_<FixedMatrix<T> > &c) { using namespace boost::python; c .def("__add__",&apply_matrix_matrix_binary_op<op_add,T,T,T>) .def("__add__",&apply_matrix_scalar_binary_op<op_add,T,T,T>) .def("__radd__",&apply_matrix_scalar_binary_rop<op_add,T,T,T>) .def("__sub__",&apply_matrix_matrix_binary_op<op_sub,T,T,T>) .def("__sub__",&apply_matrix_scalar_binary_op<op_sub,T,T,T>) .def("__rsub__",&apply_matrix_scalar_binary_op<op_rsub,T,T,T>) .def("__mul__",&apply_matrix_matrix_binary_op<op_mul,T,T,T>) .def("__mul__",&apply_matrix_scalar_binary_op<op_mul,T,T,T>) .def("__rmul__",&apply_matrix_scalar_binary_rop<op_mul,T,T,T>) .def("__div__",&apply_matrix_matrix_binary_op<op_div,T,T,T>) .def("__div__",&apply_matrix_scalar_binary_op<op_div,T,T,T>) .def("__truediv__",&apply_matrix_matrix_binary_op<op_div,T,T,T>) .def("__truediv__",&apply_matrix_scalar_binary_op<op_div,T,T,T>) .def("__neg__",&apply_matrix_unary_op<op_neg,T,T>) .def("__iadd__",&apply_matrix_matrix_ibinary_op<op_iadd,T,T>,return_internal_reference<>()) .def("__iadd__",&apply_matrix_scalar_ibinary_op<op_iadd,T,T>,return_internal_reference<>()) .def("__isub__",&apply_matrix_matrix_ibinary_op<op_isub,T,T>,return_internal_reference<>()) .def("__isub__",&apply_matrix_scalar_ibinary_op<op_isub,T,T>,return_internal_reference<>()) .def("__imul__",&apply_matrix_matrix_ibinary_op<op_imul,T,T>,return_internal_reference<>()) .def("__imul__",&apply_matrix_scalar_ibinary_op<op_imul,T,T>,return_internal_reference<>()) .def("__idiv__",&apply_matrix_matrix_ibinary_op<op_idiv,T,T>,return_internal_reference<>()) .def("__idiv__",&apply_matrix_scalar_ibinary_op<op_idiv,T,T>,return_internal_reference<>()) .def("__itruediv__",&apply_matrix_matrix_ibinary_op<op_idiv,T,T>,return_internal_reference<>()) .def("__itruediv__",&apply_matrix_scalar_ibinary_op<op_idiv,T,T>,return_internal_reference<>()) ; } template <class T> static void add_pow_math_functions(boost::python::class_<FixedMatrix<T> > &c) { using namespace boost::python; c .def("__pow__",&pow_matrix_scalar<T>) .def("__pow__",&pow_matrix_matrix<T>) .def("__ipow__",&ipow_matrix_scalar<T>,return_internal_reference<>()) .def("__ipow__",&ipow_matrix_matrix<T>,return_internal_reference<>()) ; } template <class T> static void add_mod_math_functions(boost::python::class_<FixedMatrix<T> > &c) { using namespace boost::python; c .def(self % self) // NOSONAR - suppress SonarCloud bug report. .def(self % other<T>()) .def(self %= self) // NOSONAR - suppress SonarCloud bug report. .def(self %= other<T>()) ; } template <class T> static void add_shift_math_functions(boost::python::class_<FixedMatrix<T> > &c) { using namespace boost::python; c .def(self << self) // NOSONAR - suppress SonarCloud bug report. .def(self << other<T>()) .def(self <<= self) // NOSONAR - suppress SonarCloud bug report. .def(self <<= other<T>()) .def(self >> self) // NOSONAR - suppress SonarCloud bug report. .def(self >> other<T>()) .def(self >>= self) // NOSONAR - suppress SonarCloud bug report. .def(self >>= other<T>()) ; } template <class T> static void add_bitwise_math_functions(boost::python::class_<FixedMatrix<T> > &c) { using namespace boost::python; c .def(self & self) .def(self & other<T>()) .def(self &= self) // NOSONAR - suppress SonarCloud bug report. .def(self &= other<T>()) .def(self | self) .def(self | other<T>()) .def(self |= self) // NOSONAR - suppress SonarCloud bug report. .def(self |= other<T>()) .def(self ^ self) .def(self ^ other<T>()) .def(self ^= self) // NOSONAR - suppress SonarCloud bug report. .def(self ^= other<T>()) ; } } #endif