?????????? ????????? - ??????????????? - /home/agenciai/public_html/cd38d8/Imath.tar
???????
PyImathExport.h 0000644 00000001307 15125213143 0007470 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef PYIMATHEXPORT_H #define PYIMATHEXPORT_H #if defined(IMATH_DLL) #if defined(PLATFORM_VISIBILITY_AVAILABLE) #define PYIMATH_EXPORT __attribute__((visibility("default"))) #define PYIMATH_EXPORT __attribute__((visibility("default"))) #elif defined(_MSC_VER) #if defined(PYIMATH_BUILD) #define PYIMATH_EXPORT __declspec(dllexport) #else #define PYIMATH_EXPORT __declspec(dllimport) #endif #else #define PYIMATH_EXPORT #endif #else #define PYIMATH_EXPORT #endif #endif // #ifndef PYIMATHEXPORT_H PyImathFixedMatrix.h 0000644 00000060120 15125213144 0010432 0 ustar 00 // // 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 PyImathQuat.h 0000644 00000007701 15125213144 0007126 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathQuat_h_ #define _PyImathQuat_h_ #include <Python.h> #include <boost/python.hpp> #include <ImathQuat.h> #include <ImathVec.h> #include "PyImath.h" namespace PyImath { template <class T> boost::python::class_<IMATH_NAMESPACE::Quat<T> > register_Quat(); template <class T> boost::python::class_<PyImath::FixedArray<IMATH_NAMESPACE::Quat<T> > > register_QuatArray(); typedef FixedArray<IMATH_NAMESPACE::Quatf> QuatfArray; typedef FixedArray<IMATH_NAMESPACE::Quatd> QuatdArray; } template <class T> inline IMATH_NAMESPACE::Vec3<T> operator * (const IMATH_NAMESPACE::Vec3<T> &v, const IMATH_NAMESPACE::Quat<T> &q) { return v * q.toMatrix33(); } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > operator *(const IMATH_NAMESPACE::Vec3<T> &va, const PyImath::FixedArray<IMATH_NAMESPACE::Quat<T> > &vb) { size_t len = vb.len(); PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > f(len); for (size_t i = 0; i < len; ++i) f[i] = va * vb[i]; return f; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > operator *(const PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > &va, const IMATH_NAMESPACE::Quat<T> &vb) { size_t len = va.len(); PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > f(len); for (size_t i = 0; i < len; ++i) f[i] = va[i] * vb; return f; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > operator * (const PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > &va, const PyImath::FixedArray<IMATH_NAMESPACE::Quat<T> > &vb) { size_t len = va.match_dimension(vb); PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > f(len); for (size_t i = 0; i < len; ++i) f[i] = va[i] * vb[i]; return f; } // namespace PyImath { // Other code in the Zeno code base assumes the existance of a class with the // same name as the Imath class, and with static functions wrap() and // convert() to produce a PyImath object from an Imath object and vice-versa, // respectively. The class Boost generates from the Imath class does not // have these properties, so we define a companion class here. // The template argument, T, is the element type (e.g.,float, double). template <class T> class Q { public: static PyObject * wrap (const IMATH_NAMESPACE::Quat<T> &q); static int convert (PyObject *p, IMATH_NAMESPACE::Quat<T> *q); }; template <class T> PyObject * Q<T>::wrap (const IMATH_NAMESPACE::Quat<T> &q) { typename boost::python::return_by_value::apply < IMATH_NAMESPACE::Quat<T> >::type converter; PyObject *p = converter (q); return p; } template <class T> int Q<T>::convert (PyObject *p, IMATH_NAMESPACE::Quat<T> *q) { boost::python::extract <IMATH_NAMESPACE::Quatf> extractorQf (p); if (extractorQf.check()) { IMATH_NAMESPACE::Quatf qf = extractorQf(); q->r = T(qf.r); q->v.setValue (qf.v); return 1; } boost::python::extract <IMATH_NAMESPACE::Quatd> extractorQd (p); if (extractorQd.check()) { IMATH_NAMESPACE::Quatd qd = extractorQd(); q->r = T(qd.r); q->v.setValue (qd.v); return 1; } boost::python::extract <boost::python::tuple> extractorTuple (p); if (extractorTuple.check()) { boost::python::tuple t = extractorTuple(); if (t.attr ("__len__") () == 4) { // Extracting the tuple elements as doubles and casting them to // Ts in setValue() works better than extracting them as Ts from // the start. double r = boost::python::extract <double> (t[0]); double x = boost::python::extract <double> (t[1]); double y = boost::python::extract <double> (t[2]); double z = boost::python::extract <double> (t[3]); q->r = T(r); q->v.setValue (T(x), T(y), T(z)); return 1; } } return 0; } typedef Q<float> Quatf; typedef Q<double> Quatd; } #endif ImathLineAlgo.h 0000644 00000013035 15125213144 0007372 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // Algorithms applied to or in conjunction with Imath::Line class // #ifndef INCLUDED_IMATHLINEALGO_H #define INCLUDED_IMATHLINEALGO_H #include "ImathFun.h" #include "ImathLine.h" #include "ImathNamespace.h" #include "ImathVecAlgo.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// /// Compute point1 and point2 such that point1 is on line1, point2 /// is on line2 and the distance between point1 and point2 is minimal. /// /// This function returns true if point1 and point2 can be computed, /// or false if line1 and line2 are parallel or nearly parallel. /// This function assumes that line1.dir and line2.dir are normalized. /// template <class T> IMATH_CONSTEXPR14 bool closestPoints (const Line3<T>& line1, const Line3<T>& line2, Vec3<T>& point1, Vec3<T>& point2) IMATH_NOEXCEPT { Vec3<T> w = line1.pos - line2.pos; T d1w = line1.dir ^ w; T d2w = line2.dir ^ w; T d1d2 = line1.dir ^ line2.dir; T n1 = d1d2 * d2w - d1w; T n2 = d2w - d1d2 * d1w; T d = 1 - d1d2 * d1d2; T absD = abs (d); if ((absD > 1) || (abs (n1) < std::numeric_limits<T>::max() * absD && abs (n2) < std::numeric_limits<T>::max() * absD)) { point1 = line1 (n1 / d); point2 = line2 (n2 / d); return true; } else { return false; } } /// /// Given a line and a triangle (v0, v1, v2), the intersect() function /// finds the intersection of the line and the plane that contains the /// triangle. /// /// If the intersection point cannot be computed, either because the /// line and the triangle's plane are nearly parallel or because the /// triangle's area is very small, intersect() returns false. /// /// If the intersection point is outside the triangle, intersect /// returns false. /// /// If the intersection point, pt, is inside the triangle, intersect() /// computes a front-facing flag and the barycentric coordinates of /// the intersection point, and returns true. /// /// The front-facing flag is true if the dot product of the triangle's /// normal, (v2-v1)%(v1-v0), and the line's direction is negative. /// /// The barycentric coordinates have the following property: /// /// pt = v0 * barycentric.x + v1 * barycentric.y + v2 * barycentric.z /// template <class T> IMATH_CONSTEXPR14 bool intersect (const Line3<T>& line, const Vec3<T>& v0, const Vec3<T>& v1, const Vec3<T>& v2, Vec3<T>& pt, Vec3<T>& barycentric, bool& front) IMATH_NOEXCEPT { Vec3<T> edge0 = v1 - v0; Vec3<T> edge1 = v2 - v1; Vec3<T> normal = edge1 % edge0; T l = normal.length(); if (l != 0) normal /= l; else return false; // zero-area triangle // // d is the distance of line.pos from the plane that contains the triangle. // The intersection point is at line.pos + (d/nd) * line.dir. // T d = normal ^ (v0 - line.pos); T nd = normal ^ line.dir; if (abs (nd) > 1 || abs (d) < std::numeric_limits<T>::max() * abs (nd)) pt = line (d / nd); else return false; // line and plane are nearly parallel // // Compute the barycentric coordinates of the intersection point. // The intersection is inside the triangle if all three barycentric // coordinates are between zero and one. // { Vec3<T> en = edge0.normalized(); Vec3<T> a = pt - v0; Vec3<T> b = v2 - v0; Vec3<T> c = (a - en * (en ^ a)); Vec3<T> d = (b - en * (en ^ b)); T e = c ^ d; T f = d ^ d; if (e >= 0 && e <= f) barycentric.z = e / f; else return false; // outside } { Vec3<T> en = edge1.normalized(); Vec3<T> a = pt - v1; Vec3<T> b = v0 - v1; Vec3<T> c = (a - en * (en ^ a)); Vec3<T> d = (b - en * (en ^ b)); T e = c ^ d; T f = d ^ d; if (e >= 0 && e <= f) barycentric.x = e / f; else return false; // outside } barycentric.y = 1 - barycentric.x - barycentric.z; if (barycentric.y < 0) return false; // outside front = ((line.dir ^ normal) < 0); return true; } /// /// Return the vertex that is closest to the given line. The returned /// point is either v0, v1, or v2. /// template <class T> IMATH_CONSTEXPR14 Vec3<T> closestVertex (const Vec3<T>& v0, const Vec3<T>& v1, const Vec3<T>& v2, const Line3<T>& l) IMATH_NOEXCEPT { Vec3<T> nearest = v0; T neardot = (v0 - l.closestPointTo (v0)).length2(); T tmp = (v1 - l.closestPointTo (v1)).length2(); if (tmp < neardot) { neardot = tmp; nearest = v1; } tmp = (v2 - l.closestPointTo (v2)).length2(); if (tmp < neardot) { neardot = tmp; nearest = v2; } return nearest; } /// /// Rotate the point p around the line l by the given angle. /// template <class T> IMATH_CONSTEXPR14 Vec3<T> rotatePoint (const Vec3<T> p, Line3<T> l, T angle) IMATH_NOEXCEPT { // // Form a coordinate frame with <x,y,a>. The rotation is the in xy // plane. // Vec3<T> q = l.closestPointTo (p); Vec3<T> x = p - q; T radius = x.length(); x.normalize(); Vec3<T> y = (x % l.dir).normalize(); T cosangle = std::cos (angle); T sinangle = std::sin (angle); Vec3<T> r = q + x * radius * cosangle + y * radius * sinangle; return r; } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHLINEALGO_H PyImathColor3ArrayImpl.h 0000644 00000003061 15125213144 0011171 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathColor3ArrayImpl_h_ #define _PyImathColor3ArrayImpl_h_ // // This .C file was turned into a header file so that instantiations // of the various V3* types can be spread across multiple files in // order to work around MSVC limitations. // #include <Python.h> #include <boost/python.hpp> #include <boost/python/make_constructor.hpp> #include <boost/format.hpp> #include "PyImath.h" #include "PyImathMathExc.h" #include "PyImathDecorators.h" namespace PyImath { using namespace boost::python; using namespace IMATH_NAMESPACE; // XXX fixme - template this // really this should get generated automatically... template <class T,int index> static FixedArray<T> Color3Array_get(FixedArray<IMATH_NAMESPACE::Color3<T> > &ca) { return FixedArray<T>(&(ca.unchecked_index(0)[index]), ca.len(),3*ca.stride(),ca.handle(),ca.writable()); } // Currently we are only exposing the RGBA components. template <class T> class_<FixedArray<IMATH_NAMESPACE::Color3<T> > > register_Color3Array() { class_<FixedArray<IMATH_NAMESPACE::Color3<T> > > color3Array_class = FixedArray<IMATH_NAMESPACE::Color3<T> >::register_("Fixed length array of Imath::Color3"); color3Array_class .add_property("r",&Color3Array_get<T,0>) .add_property("g",&Color3Array_get<T,1>) .add_property("b",&Color3Array_get<T,2>) ; return color3Array_class; } } // namespace PyImath #endif // _PyImathColor3ArrayImpl_h_ ImathFrame.h 0000644 00000013462 15125213144 0006736 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // Functions for computing reference frames. // #ifndef INCLUDED_IMATHFRAME_H #define INCLUDED_IMATHFRAME_H #include "ImathNamespace.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// @cond Doxygen_Suppress template <class T> class Vec3; template <class T> class Matrix44; /// @endcond /// /// @{ /// @name Functions for computing reference frames /// /// These methods compute a set of reference frames, defined by their /// transformation matrix, along a curve. It is designed so that the /// array of points and the array of matrices used to fetch these /// routines don't need to be ordered as the curve. /// /// A typical usage would be : /// /// m[0] = IMATH_INTERNAL_NAMESPACE::firstFrame( p[0], p[1], p[2] ); /// for( int i = 1; i < n - 1; i++ ) /// { /// m[i] = IMATH_INTERNAL_NAMESPACE::nextFrame( m[i-1], p[i-1], p[i], t[i-1], t[i] ); /// } /// m[n-1] = IMATH_INTERNAL_NAMESPACE::lastFrame( m[n-2], p[n-2], p[n-1] ); /// /// See Graphics Gems I for the underlying algorithm. template <class T> Matrix44<T> constexpr firstFrame (const Vec3<T>&, // First point const Vec3<T>&, // Second point const Vec3<T>&) IMATH_NOEXCEPT; // Third point template <class T> Matrix44<T> constexpr nextFrame (const Matrix44<T>&, // Previous matrix const Vec3<T>&, // Previous point const Vec3<T>&, // Current point Vec3<T>&, // Previous tangent Vec3<T>&) IMATH_NOEXCEPT; // Current tangent template <class T> Matrix44<T> constexpr lastFrame (const Matrix44<T>&, // Previous matrix const Vec3<T>&, // Previous point const Vec3<T>&) IMATH_NOEXCEPT; // Last point /// /// Compute the first reference frame along a curve. /// /// This function returns the transformation matrix to the reference /// frame defined by the three points `pi`, `pj` and `pk`. Note that /// if the two vectors <`pi`,`pj`> and <`pi`,`pk`> are colinears, an /// arbitrary twist value will be choosen. /// /// Throw `std::domain_error` if `pi` and `pj` are equal. /// /// @param pi /// First point /// @param pj /// Second point /// @param pk /// Third point /// template <class T> Matrix44<T> constexpr firstFrame (const Vec3<T>& pi, // first point const Vec3<T>& pj, // secont point const Vec3<T>& pk) IMATH_NOEXCEPT // third point { Vec3<T> t = pj - pi; t.normalizeExc(); Vec3<T> n = t.cross (pk - pi); n.normalize(); if (n.length() == 0.0f) { int i = fabs (t[0]) < fabs (t[1]) ? 0 : 1; if (fabs (t[2]) < fabs (t[i])) i = 2; Vec3<T> v (0.0, 0.0, 0.0); v[i] = 1.0; n = t.cross (v); n.normalize(); } Vec3<T> b = t.cross (n); Matrix44<T> M; M[0][0] = t[0]; M[0][1] = t[1]; M[0][2] = t[2]; M[0][3] = 0.0, M[1][0] = n[0]; M[1][1] = n[1]; M[1][2] = n[2]; M[1][3] = 0.0, M[2][0] = b[0]; M[2][1] = b[1]; M[2][2] = b[2]; M[2][3] = 0.0, M[3][0] = pi[0]; M[3][1] = pi[1]; M[3][2] = pi[2]; M[3][3] = 1.0; return M; } /// /// Compute the next reference frame along a curve. /// /// This function returns the transformation matrix to the next reference /// frame defined by the previously computed transformation matrix and the /// new point and tangent vector along the curve. /// /// @param Mi /// The previous matrix /// @param pi /// The previous point /// @param pj /// The current point /// @param ti /// The previous tangent vector /// @param tj /// The current tangent vector template <class T> Matrix44<T> constexpr nextFrame (const Matrix44<T>& Mi, // Previous matrix const Vec3<T>& pi, // Previous point const Vec3<T>& pj, // Current point Vec3<T>& ti, // Previous tangent vector Vec3<T>& tj) IMATH_NOEXCEPT // Current tangent vector { Vec3<T> a (0.0, 0.0, 0.0); /// Rotation axis. T r = 0.0; // Rotation angle. if (ti.length() != 0.0 && tj.length() != 0.0) { ti.normalize(); tj.normalize(); T dot = ti.dot (tj); // // This is *really* necessary : // if (dot > 1.0) dot = 1.0; else if (dot < -1.0) dot = -1.0; r = acosf (dot); a = ti.cross (tj); } if (a.length() != 0.0 && r != 0.0) { Matrix44<T> R; R.setAxisAngle (a, r); Matrix44<T> Tj; Tj.translate (pj); Matrix44<T> Ti; Ti.translate (-pi); return Mi * Ti * R * Tj; } else { Matrix44<T> Tr; Tr.translate (pj - pi); return Mi * Tr; } } /// /// Compute the last reference frame along a curve. /// /// This function returns the transformation matrix to the last reference /// frame defined by the previously computed transformation matrix and the /// last point along the curve. /// /// @param Mi /// The previous matrix /// @param pi /// The previous point /// @param pj /// The last point template <class T> Matrix44<T> constexpr lastFrame (const Matrix44<T>& Mi, // Previous matrix const Vec3<T>& pi, // Previous point const Vec3<T>& pj) IMATH_NOEXCEPT // Last point { Matrix44<T> Tr; Tr.translate (pj - pi); return Mi * Tr; } /// @} IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHFRAME_H ImathFrustumTest.h 0000644 00000027263 15125213144 0010215 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // A viewing frustum class // // This file contains algorithms applied to or in conjunction with // Frustum visibility testing (Imath::Frustum). // // Methods for frustum-based rejection of primitives are contained here. // #ifndef INCLUDED_IMATHFRUSTUMTEST_H #define INCLUDED_IMATHFRUSTUMTEST_H #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathBox.h" #include "ImathFrustum.h" #include "ImathMatrix.h" #include "ImathSphere.h" #include "ImathVec.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// /// template class FrustumTest<T> /// /// This is a helper class, designed to accelerate the case /// where many tests are made against the same frustum. /// That's a really common case. /// /// The acceleration is achieved by pre-computing the planes of /// the frustum, along with the ablsolute values of the plane normals. /// /// How to use this /// /// Given that you already have: /// Imath::Frustum myFrustum /// Imath::Matrix44 myCameraWorldMatrix /// /// First, make a frustum test object: /// FrustumTest myFrustumTest(myFrustum, myCameraWorldMatrix) /// /// Whenever the camera or frustum changes, call: /// myFrustumTest.setFrustum(myFrustum, myCameraWorldMatrix) /// /// For each object you want to test for visibility, call: /// myFrustumTest.isVisible(myBox) /// myFrustumTest.isVisible(mySphere) /// myFrustumTest.isVisible(myVec3) /// myFrustumTest.completelyContains(myBox) /// myFrustumTest.completelyContains(mySphere) /// /// Explanation of how it works /// /// We store six world-space Frustum planes (nx, ny, nz, offset) /// /// Points: To test a Vec3 for visibility, test it against each plane /// using the normal (v dot n - offset) method. (the result is exact) /// /// BBoxes: To test an axis-aligned bbox, test the center against each plane /// using the normal (v dot n - offset) method, but offset by the /// box extents dot the abs of the plane normal. (the result is NOT /// exact, but will not return false-negatives.) /// /// Spheres: To test a sphere, test the center against each plane /// using the normal (v dot n - offset) method, but offset by the /// sphere's radius. (the result is NOT exact, but will not return /// false-negatives.) /// /// /// SPECIAL NOTE: "Where are the dot products?" /// Actual dot products are currently slow for most SIMD architectures. /// In order to keep this code optimization-ready, the dot products /// are all performed using vector adds and multipies. /// /// In order to do this, the plane equations are stored in "transpose" /// form, with the X components grouped into an X vector, etc. /// template <class T> class IMATH_EXPORT_TEMPLATE_TYPE FrustumTest { public: /// @{ /// @name Constructors /// Initialize camera matrix to identity FrustumTest() IMATH_NOEXCEPT { Frustum<T> frust; Matrix44<T> cameraMat; cameraMat.makeIdentity(); setFrustum (frust, cameraMat); } /// Initialize to a given frustum and camera matrix. FrustumTest (const Frustum<T>& frustum, const Matrix44<T>& cameraMat) IMATH_NOEXCEPT { setFrustum (frustum, cameraMat); } /// @} /// @{ /// @name Set Value /// Update the frustum test with a new frustum and matrix. /// This should usually be called just once per frame, or however /// often the camera moves. void setFrustum (const Frustum<T>& frustum, const Matrix44<T>& cameraMat) IMATH_NOEXCEPT; /// @} /// @{ /// @name Query /// Return true if any part of the sphere is inside the frustum. /// The result MAY return close false-positives, but not false-negatives. bool isVisible (const Sphere3<T>& sphere) const IMATH_NOEXCEPT; /// Return true if any part of the box is inside the frustum. /// The result MAY return close false-positives, but not false-negatives. bool isVisible (const Box<Vec3<T>>& box) const IMATH_NOEXCEPT; /// Return true if the point is inside the frustum. bool isVisible (const Vec3<T>& vec) const IMATH_NOEXCEPT; /// Return true if every part of the sphere is inside the frustum. /// The result MAY return close false-negatives, but not false-positives. bool completelyContains (const Sphere3<T>& sphere) const IMATH_NOEXCEPT; /// Return true if every part of the box is inside the frustum. /// The result MAY return close false-negatives, but not false-positives. bool completelyContains (const Box<Vec3<T>>& box) const IMATH_NOEXCEPT; /// Return the camera matrix (primarily for debugging) IMATH_INTERNAL_NAMESPACE::Matrix44<T> cameraMat() const IMATH_NOEXCEPT { return cameraMatrix; } /// Return the viewing frustum (primarily for debugging) IMATH_INTERNAL_NAMESPACE::Frustum<T> currentFrustum() const IMATH_NOEXCEPT { return currFrustum; } /// @} protected: // To understand why the planes are stored this way, see // the SPECIAL NOTE above. /// @cond Doxygen_Suppress Vec3<T> planeNormX[2]; // The X components from 6 plane equations Vec3<T> planeNormY[2]; // The Y components from 6 plane equations Vec3<T> planeNormZ[2]; // The Z components from 6 plane equations Vec3<T> planeOffsetVec[2]; // The distance offsets from 6 plane equations // The absolute values are stored to assist with bounding box tests. Vec3<T> planeNormAbsX[2]; // The abs(X) components from 6 plane equations Vec3<T> planeNormAbsY[2]; // The abs(X) components from 6 plane equations Vec3<T> planeNormAbsZ[2]; // The abs(X) components from 6 plane equations // These are kept primarily for debugging tools. Frustum<T> currFrustum; Matrix44<T> cameraMatrix; /// @endcond }; template <class T> void FrustumTest<T>::setFrustum (const Frustum<T>& frustum, const Matrix44<T>& cameraMat) IMATH_NOEXCEPT { Plane3<T> frustumPlanes[6]; frustum.planes (frustumPlanes, cameraMat); // Here's where we effectively transpose the plane equations. // We stuff all six X's into the two planeNormX vectors, etc. for (int i = 0; i < 2; ++i) { int index = i * 3; planeNormX[i] = Vec3<T> (frustumPlanes[index + 0].normal.x, frustumPlanes[index + 1].normal.x, frustumPlanes[index + 2].normal.x); planeNormY[i] = Vec3<T> (frustumPlanes[index + 0].normal.y, frustumPlanes[index + 1].normal.y, frustumPlanes[index + 2].normal.y); planeNormZ[i] = Vec3<T> (frustumPlanes[index + 0].normal.z, frustumPlanes[index + 1].normal.z, frustumPlanes[index + 2].normal.z); planeNormAbsX[i] = Vec3<T> (std::abs (planeNormX[i].x), std::abs (planeNormX[i].y), std::abs (planeNormX[i].z)); planeNormAbsY[i] = Vec3<T> (std::abs (planeNormY[i].x), std::abs (planeNormY[i].y), std::abs (planeNormY[i].z)); planeNormAbsZ[i] = Vec3<T> (std::abs (planeNormZ[i].x), std::abs (planeNormZ[i].y), std::abs (planeNormZ[i].z)); planeOffsetVec[i] = Vec3<T> (frustumPlanes[index + 0].distance, frustumPlanes[index + 1].distance, frustumPlanes[index + 2].distance); } currFrustum = frustum; cameraMatrix = cameraMat; } template <typename T> bool FrustumTest<T>::isVisible (const Sphere3<T>& sphere) const IMATH_NOEXCEPT { Vec3<T> center = sphere.center; Vec3<T> radiusVec = Vec3<T> (sphere.radius, sphere.radius, sphere.radius); // This is a vertical dot-product on three vectors at once. Vec3<T> d0 = planeNormX[0] * center.x + planeNormY[0] * center.y + planeNormZ[0] * center.z - radiusVec - planeOffsetVec[0]; if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0) return false; Vec3<T> d1 = planeNormX[1] * center.x + planeNormY[1] * center.y + planeNormZ[1] * center.z - radiusVec - planeOffsetVec[1]; if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0) return false; return true; } template <typename T> bool FrustumTest<T>::completelyContains (const Sphere3<T>& sphere) const IMATH_NOEXCEPT { Vec3<T> center = sphere.center; Vec3<T> radiusVec = Vec3<T> (sphere.radius, sphere.radius, sphere.radius); // This is a vertical dot-product on three vectors at once. Vec3<T> d0 = planeNormX[0] * center.x + planeNormY[0] * center.y + planeNormZ[0] * center.z + radiusVec - planeOffsetVec[0]; if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0) return false; Vec3<T> d1 = planeNormX[1] * center.x + planeNormY[1] * center.y + planeNormZ[1] * center.z + radiusVec - planeOffsetVec[1]; if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0) return false; return true; } template <typename T> bool FrustumTest<T>::isVisible (const Box<Vec3<T>>& box) const IMATH_NOEXCEPT { if (box.isEmpty()) return false; Vec3<T> center = (box.min + box.max) / 2; Vec3<T> extent = (box.max - center); // This is a vertical dot-product on three vectors at once. Vec3<T> d0 = planeNormX[0] * center.x + planeNormY[0] * center.y + planeNormZ[0] * center.z - planeNormAbsX[0] * extent.x - planeNormAbsY[0] * extent.y - planeNormAbsZ[0] * extent.z - planeOffsetVec[0]; if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0) return false; Vec3<T> d1 = planeNormX[1] * center.x + planeNormY[1] * center.y + planeNormZ[1] * center.z - planeNormAbsX[1] * extent.x - planeNormAbsY[1] * extent.y - planeNormAbsZ[1] * extent.z - planeOffsetVec[1]; if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0) return false; return true; } template <typename T> bool FrustumTest<T>::completelyContains (const Box<Vec3<T>>& box) const IMATH_NOEXCEPT { if (box.isEmpty()) return false; Vec3<T> center = (box.min + box.max) / 2; Vec3<T> extent = (box.max - center); // This is a vertical dot-product on three vectors at once. Vec3<T> d0 = planeNormX[0] * center.x + planeNormY[0] * center.y + planeNormZ[0] * center.z + planeNormAbsX[0] * extent.x + planeNormAbsY[0] * extent.y + planeNormAbsZ[0] * extent.z - planeOffsetVec[0]; if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0) return false; Vec3<T> d1 = planeNormX[1] * center.x + planeNormY[1] * center.y + planeNormZ[1] * center.z + planeNormAbsX[1] * extent.x + planeNormAbsY[1] * extent.y + planeNormAbsZ[1] * extent.z - planeOffsetVec[1]; if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0) return false; return true; } template <typename T> bool FrustumTest<T>::isVisible (const Vec3<T>& vec) const IMATH_NOEXCEPT { // This is a vertical dot-product on three vectors at once. Vec3<T> d0 = (planeNormX[0] * vec.x) + (planeNormY[0] * vec.y) + (planeNormZ[0] * vec.z) - planeOffsetVec[0]; if (d0.x >= 0 || d0.y >= 0 || d0.z >= 0) return false; Vec3<T> d1 = (planeNormX[1] * vec.x) + (planeNormY[1] * vec.y) + (planeNormZ[1] * vec.z) - planeOffsetVec[1]; if (d1.x >= 0 || d1.y >= 0 || d1.z >= 0) return false; return true; } /// FrustymTest of type float typedef FrustumTest<float> FrustumTestf; /// FrustymTest of type double typedef FrustumTest<double> FrustumTestd; IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHFRUSTUMTEST_H ImathTypeTraits.h 0000644 00000016674 15125213144 0010024 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // This file contains type traits related to or used by the Imath library. // #ifndef INCLUDED_IMATHTYPETRAITS_H #define INCLUDED_IMATHTYPETRAITS_H #include <type_traits> #include "ImathPlatform.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// Define Imath::enable_if_t to be std for C++14, equivalent for C++11. #if (IMATH_CPLUSPLUS_VERSION >= 14) using std::enable_if_t; // Use C++14 std::enable_if_t #else // Define enable_if_t for C++11 template <bool B, class T = void> using enable_if_t = typename std::enable_if<B, T>::type; #endif /// An enable_if helper to be used in template parameters which results in /// much shorter symbols. #define IMATH_ENABLE_IF(...) Imath::enable_if_t<(__VA_ARGS__), int> = 0 #if IMATH_FOREIGN_VECTOR_INTEROP /// @{ /// @name Detecting interoperable types. /// /// In order to construct or assign from external "compatible" types without /// prior knowledge of their definitions, we have a few helper type traits. /// The intent of these is to allow custom linear algebra types in an /// application that have seamless conversion to and from Imath types. /// /// `has_xy<T,Base>`, `has_xyz<T,Base>`, `has_xyzw<T,Base>` detect if class /// `T` has elements `.x`, `.y`, and `.z` all of type `Base` and seems to be /// the right size to hold exactly those members and nothing more. /// /// `has_subscript<T,Base,N>` detects if class `T` can perform `T[int]` /// to yield a `Base`, and that it seems to be exactly the right size to /// hold `N` of those elements. /// /// This is not exact. It's possible that for a particular user-defined /// type, this may yield a false negative or false positive. For example: /// * A class for a 3-vector that contains an extra element of padding /// so that it will have the right size and alignment to use 4-wide /// SIMD math ops will appear to be the wrong size. /// * A `std::vector<T>` is subscriptable and might have N elements at /// runtime, but the size is dynamic and so would fail this test. /// * A foreign type may have .x, .y, .z that are not matching our base /// type but we still want it to work (with appropriate conversions). /// /// In these cases, user code may declare an exception -- for example, /// stating that `mytype` should be considered implicitly convertible to /// an Imath::V3f by subscripting: /// /// template<> /// struct Imath::has_subscript<mytype, float, 3> : public std::true_type { }; /// /// And similarly, user code may correct a potential false positive (that /// is, a `mytype` looks like it should be convertible to a V3f, but you /// don't want it to ever happen): /// /// template<typename B, int N> /// struct Imath::has_subscript<mytype, B, N> : public std::false_type { }; /// /// `has_xy<T,Base>::value` will be true if type `T` has member variables /// `.x` and `.y`, all of type `Base`, and the size of a `T` is exactly big /// enough to hold 2 Base values. template <typename T, typename Base> struct has_xy { private: typedef char Yes[1]; typedef char No[2]; // Valid only if .x, .y exist and are the right type: return a Yes. template<typename C, IMATH_ENABLE_IF(std::is_same<decltype(C().x), Base>::value), IMATH_ENABLE_IF(std::is_same<decltype(C().y), Base>::value)> static Yes& test(int); // Fallback, default to returning a No. template<typename C> static No& test(...); public: enum { value = (sizeof(test<T>(0)) == sizeof(Yes) && sizeof(T) == 2*sizeof(Base)) }; }; /// `has_xyz<T,Base>::value` will be true if type `T` has member variables /// `.x`, `.y`, and `.z`, all of type `Base`, and the size of a `T` is /// exactly big enough to hold 3 Base values. template <typename T, typename Base> struct has_xyz { private: typedef char Yes[1]; typedef char No[2]; // Valid only if .x, .y, .z exist and are the right type: return a Yes. template<typename C, IMATH_ENABLE_IF(std::is_same<decltype(C().x), Base>::value), IMATH_ENABLE_IF(std::is_same<decltype(C().y), Base>::value), IMATH_ENABLE_IF(std::is_same<decltype(C().z), Base>::value)> static Yes& test(int); // Fallback, default to returning a No. template<typename C> static No& test(...); public: enum { value = (sizeof(test<T>(0)) == sizeof(Yes) && sizeof(T) == 3*sizeof(Base)) }; }; /// `has_xyzw<T,Base>::value` will be true if type `T` has member variables /// `.x`, `.y`, `.z`, and `.w`, all of type `Base`, and the size of a `T` is /// exactly big enough to hold 4 Base values. template <typename T, typename Base> struct has_xyzw { private: typedef char Yes[1]; typedef char No[2]; // Valid only if .x, .y, .z, .w exist and are the right type: return a Yes. template<typename C, IMATH_ENABLE_IF(std::is_same<decltype(C().x), Base>::value), IMATH_ENABLE_IF(std::is_same<decltype(C().y), Base>::value), IMATH_ENABLE_IF(std::is_same<decltype(C().z), Base>::value), IMATH_ENABLE_IF(std::is_same<decltype(C().w), Base>::value)> static Yes& test(int); // Fallback, default to returning a No. template<typename C> static No& test(...); public: enum { value = (sizeof(test<T>(0)) == sizeof(Yes) && sizeof(T) == 4*sizeof(Base)) }; }; /// `has_subscript<T,Base,Nelem>::value` will be true if type `T` has /// subscripting syntax, a `T[int]` returns a `Base`, and the size of a `T` /// is exactly big enough to hold `Nelem` `Base` values. template <typename T, typename Base, int Nelem> struct has_subscript { private: typedef char Yes[1]; typedef char No[2]; // Valid only if T[] is possible and is the right type: return a Yes. template<typename C, IMATH_ENABLE_IF(std::is_same<typename std::decay<decltype(C()[0])>::type, Base>::value)> static Yes& test(int); // Fallback, default to returning a No. template<typename C> static No& test(...); public: enum { value = (sizeof(test<T>(0)) == sizeof(Yes) && sizeof(T) == Nelem*sizeof(Base)) }; }; /// C arrays of just the right length also are qualified for has_subscript. template<typename Base, int Nelem> struct has_subscript<Base[Nelem], Base, Nelem> : public std::true_type { }; /// `has_double_subscript<T,Base,Rows,Cols>::value` will be true if type `T` /// has 2-level subscripting syntax, a `T[int][int]` returns a `Base`, and /// the size of a `T` is exactly big enough to hold `R*C` `Base` values. template <typename T, typename Base, int Rows, int Cols> struct has_double_subscript { private: typedef char Yes[1]; typedef char No[2]; // Valid only if T[][] is possible and is the right type: return a Yes. template<typename C, IMATH_ENABLE_IF(std::is_same<typename std::decay<decltype(C()[0][0])>::type, Base>::value)> static Yes& test(int); // Fallback, default to returning a No. template<typename C> static No& test(...); public: enum { value = (sizeof(test<T>(0)) == sizeof(Yes) && sizeof(T) == (Rows*Cols)*sizeof(Base)) }; }; /// C arrays of just the right length also are qualified for has_double_subscript. template<typename Base, int Rows, int Cols> struct has_double_subscript<Base[Rows][Cols], Base, Rows, Cols> : public std::true_type { }; /// @} #endif IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHTYPETRAITS_H ImathMatrixAlgo.h 0000644 00000133403 15125213144 0007751 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // // Functions operating on Matrix22, Matrix33, and Matrix44 types // // This file also defines a few predefined constant matrices. // #ifndef INCLUDED_IMATHMATRIXALGO_H #define INCLUDED_IMATHMATRIXALGO_H #include "ImathEuler.h" #include "ImathExport.h" #include "ImathMatrix.h" #include "ImathNamespace.h" #include "ImathQuat.h" #include "ImathVec.h" #include <math.h> IMATH_INTERNAL_NAMESPACE_HEADER_ENTER //------------------ // Identity matrices //------------------ /// M22f identity matrix IMATH_EXPORT_CONST M22f identity22f; /// M33f identity matrix IMATH_EXPORT_CONST M33f identity33f; /// M44f identity matrix IMATH_EXPORT_CONST M44f identity44f; /// M22d identity matrix IMATH_EXPORT_CONST M22d identity22d; /// M33d identity matrix IMATH_EXPORT_CONST M33d identity33d; /// M44d identity matrix IMATH_EXPORT_CONST M44d identity44d; //---------------------------------------------------------------------- // Extract scale, shear, rotation, and translation values from a matrix: // // Notes: // // This implementation follows the technique described in the paper by // Spencer W. Thomas in the Graphics Gems II article: "Decomposing a // Matrix into Simple Transformations", p. 320. // // - Some of the functions below have an optional exc parameter // that determines the functions' behavior when the matrix' // scaling is very close to zero: // // If exc is true, the functions throw a std::domain_error exception. // // If exc is false: // // extractScaling (m, s) returns false, s is invalid // sansScaling (m) returns m // removeScaling (m) returns false, m is unchanged // sansScalingAndShear (m) returns m // removeScalingAndShear (m) returns false, m is unchanged // extractAndRemoveScalingAndShear (m, s, h) // returns false, m is unchanged, // (sh) are invalid // checkForZeroScaleInRow () returns false // extractSHRT (m, s, h, r, t) returns false, (shrt) are invalid // // - Functions extractEuler(), extractEulerXYZ() and extractEulerZYX() // assume that the matrix does not include shear or non-uniform scaling, // but they do not examine the matrix to verify this assumption. // Matrices with shear or non-uniform scaling are likely to produce // meaningless results. Therefore, you should use the // removeScalingAndShear() routine, if necessary, prior to calling // extractEuler...() . // // - All functions assume that the matrix does not include perspective // transformation(s), but they do not examine the matrix to verify // this assumption. Matrices with perspective transformations are // likely to produce meaningless results. // //---------------------------------------------------------------------- // // Declarations for 4x4 matrix. // /// Extract the scaling component of the given 4x4 matrix. /// /// @param[in] mat The input matrix /// @param[out] scl The extracted scale, i.e. the output value /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. /// @return True if the scale could be extracted, false if the matrix is degenerate. template <class T> bool extractScaling (const Matrix44<T>& mat, Vec3<T>& scl, bool exc = true); /// Return the given 4x4 matrix with scaling removed. /// /// @param[in] mat The input matrix /// @param[in] exc If true, throw an exception if the scaling in `mat` template <class T> Matrix44<T> sansScaling (const Matrix44<T>& mat, bool exc = true); /// Remove scaling from the given 4x4 matrix in place. Return true if the /// scale could be successfully extracted, false if the matrix is /// degenerate. // /// @param[in] mat The matrix to operate on /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. /// @return True if the scale could be extracted, false if the matrix is degenerate. template <class T> bool removeScaling (Matrix44<T>& mat, bool exc = true); /// Extract the scaling and shear components of the given 4x4 matrix. /// Return true if the scale could be successfully extracted, false if /// the matrix is degenerate. /// /// @param[in] mat The input matrix /// @param[out] scl The extracted scale /// @param[out] shr The extracted shear /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. /// @return True if the scale could be extracted, false if the matrix is degenerate. template <class T> bool extractScalingAndShear (const Matrix44<T>& mat, Vec3<T>& scl, Vec3<T>& shr, bool exc = true); /// Return the given 4x4 matrix with scaling and shear removed. /// /// @param[in] mat The input matrix /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. template <class T> Matrix44<T> sansScalingAndShear (const Matrix44<T>& mat, bool exc = true); /// Extract scaling and shear from the given 4x4 matrix in-place. /// /// @param[in,out] result The output matrix /// @param[in] mat The return value if `result` is degenerate /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. template <class T> void sansScalingAndShear (Matrix44<T>& result, const Matrix44<T>& mat, bool exc = true); /// Remove scaling and shear from the given 4x4 matrix in place. // /// @param[in,out] mat The matrix to operate on /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. /// @return True if the scale could be extracted, false if the matrix is degenerate. template <class T> bool removeScalingAndShear (Matrix44<T>& mat, bool exc = true); /// Remove scaling and shear from the given 4x4 matrix in place, returning /// the extracted values. // /// @param[in,out] mat The matrix to operate on /// @param[out] scl The extracted scale /// @param[out] shr The extracted shear /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. /// @return True if the scale could be extracted, false if the matrix is degenerate. template <class T> bool extractAndRemoveScalingAndShear (Matrix44<T>& mat, Vec3<T>& scl, Vec3<T>& shr, bool exc = true); /// Extract the rotation from the given 4x4 matrix in the form of XYZ /// euler angles. /// /// @param[in] mat The input matrix /// @param[out] rot The extracted XYZ euler angle vector template <class T> void extractEulerXYZ (const Matrix44<T>& mat, Vec3<T>& rot); /// Extract the rotation from the given 4x4 matrix in the form of ZYX /// euler angles. /// /// @param[in] mat The input matrix /// @param[out] rot The extracted ZYX euler angle vector template <class T> void extractEulerZYX (const Matrix44<T>& mat, Vec3<T>& rot); /// Extract the rotation from the given 4x4 matrix in the form of a quaternion. /// /// @param[in] mat The input matrix /// @return The extracted quaternion template <class T> Quat<T> extractQuat (const Matrix44<T>& mat); /// Extract the scaling, shear, rotation, and translation components /// of the given 4x4 matrix. The values are such that: /// /// M = S * H * R * T /// /// @param[in] mat The input matrix /// @param[out] s The extracted scale /// @param[out] h The extracted shear /// @param[out] r The extracted rotation /// @param[out] t The extracted translation /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. /// @param[in] rOrder The order with which to extract the rotation /// @return True if the values could be extracted, false if the matrix is degenerate. template <class T> bool extractSHRT (const Matrix44<T>& mat, Vec3<T>& s, Vec3<T>& h, Vec3<T>& r, Vec3<T>& t, bool exc /*= true*/, typename Euler<T>::Order rOrder); /// Extract the scaling, shear, rotation, and translation components /// of the given 4x4 matrix. /// /// @param[in] mat The input matrix /// @param[out] s The extracted scale /// @param[out] h The extracted shear /// @param[out] r The extracted rotation, in XYZ euler angles /// @param[out] t The extracted translation /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. /// @return True if the values could be extracted, false if the matrix is degenerate. template <class T> bool extractSHRT (const Matrix44<T>& mat, Vec3<T>& s, Vec3<T>& h, Vec3<T>& r, Vec3<T>& t, bool exc = true); /// Extract the scaling, shear, rotation, and translation components /// of the given 4x4 matrix. /// /// @param[in] mat The input matrix /// @param[out] s The extracted scale /// @param[out] h The extracted shear /// @param[out] r The extracted rotation, in Euler angles /// @param[out] t The extracted translation /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. /// @return True if the values could be extracted, false if the matrix is degenerate. template <class T> bool extractSHRT (const Matrix44<T>& mat, Vec3<T>& s, Vec3<T>& h, Euler<T>& r, Vec3<T>& t, bool exc = true); /// Return true if the given scale can be removed from the given row /// matrix, false if `scl` is small enough that the operation would /// overflow. If `exc` is true, throw an exception on overflow. template <class T> bool checkForZeroScaleInRow (const T& scl, const Vec3<T>& row, bool exc = true); /// Return the 4x4 outer product two 4-vectors template <class T> Matrix44<T> outerProduct (const Vec4<T>& a, const Vec4<T>& b); /// /// Return a 4x4 matrix that rotates the vector `fromDirection` to `toDirection` /// template <class T> Matrix44<T> rotationMatrix (const Vec3<T>& fromDirection, const Vec3<T>& toDirection); /// /// Return a 4x4 matrix that rotates the `fromDir` vector /// so that it points towards `toDir1. You may also /// specify that you want the up vector to be pointing /// in a certain direction 1upDir`. template <class T> Matrix44<T> rotationMatrixWithUpDir (const Vec3<T>& fromDir, const Vec3<T>& toDir, const Vec3<T>& upDir); /// /// Construct a 4x4 matrix that rotates the z-axis so that it points /// towards `targetDir`. You must also specify that you want the up /// vector to be pointing in a certain direction `upDir`. /// /// Notes: The following degenerate cases are handled: /// (a) when the directions given by `toDir` and `upDir` /// are parallel or opposite (the direction vectors must have a non-zero cross product); /// (b) when any of the given direction vectors have zero length /// /// @param[out] result The output matrix /// @param[in] targetDir The target direction vector /// @param[in] upDir The up direction vector template <class T> void alignZAxisWithTargetDir (Matrix44<T>& result, Vec3<T> targetDir, Vec3<T> upDir); /// Compute an orthonormal direct 4x4 frame from a position, an x axis /// direction and a normal to the y axis. If the x axis and normal are /// perpendicular, then the normal will have the same direction as the /// z axis. /// /// @param[in] p The position of the frame /// @param[in] xDir The x axis direction of the frame /// @param[in] normal A normal to the y axis of the frame /// @return The orthonormal frame template <class T> Matrix44<T> computeLocalFrame (const Vec3<T>& p, const Vec3<T>& xDir, const Vec3<T>& normal); /// Add a translate/rotate/scale offset to a 4x4 input frame /// and put it in another frame of reference /// /// @param[in] inMat Input frame /// @param[in] tOffset Translation offset /// @param[in] rOffset Rotation offset in degrees /// @param[in] sOffset Scale offset /// @param[in] ref Frame of reference /// @return The offsetted frame template <class T> Matrix44<T> addOffset (const Matrix44<T>& inMat, const Vec3<T>& tOffset, const Vec3<T>& rOffset, const Vec3<T>& sOffset, const Vec3<T>& ref); /// Compute 4x4 translate/rotate/scale matrix from `A` with the /// rotate/scale of `B`. /// /// @param[in] keepRotateA If true, keep rotate from matrix `A`, use `B` otherwise /// @param[in] keepScaleA If true, keep scale from matrix `A`, use `B` otherwise /// @param[in] A Matrix A /// @param[in] B Matrix B /// @return Matrix `A` with tweaked rotation/scale template <class T> Matrix44<T> computeRSMatrix (bool keepRotateA, bool keepScaleA, const Matrix44<T>& A, const Matrix44<T>& B); // // Declarations for 3x3 matrix. // /// Extract the scaling component of the given 3x3 matrix. /// /// @param[in] mat The input matrix /// @param[out] scl The extracted scale, i.e. the output value /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. /// @return True if the scale could be extracted, false if the matrix is degenerate. template <class T> bool extractScaling (const Matrix33<T>& mat, Vec2<T>& scl, bool exc = true); /// Return the given 3x3 matrix with scaling removed. /// /// @param[in] mat The input matrix /// @param[in] exc If true, throw an exception if the scaling in `mat` template <class T> Matrix33<T> sansScaling (const Matrix33<T>& mat, bool exc = true); /// Remove scaling from the given 3x3 matrix in place. Return true if the /// scale could be successfully extracted, false if the matrix is /// degenerate. // /// @param[in] mat The matrix to operate on /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. /// @return True if the scale could be extracted, false if the matrix is degenerate. template <class T> bool removeScaling (Matrix33<T>& mat, bool exc = true); /// Extract the scaling and shear components of the given 3x3 matrix. /// Return true if the scale could be successfully extracted, false if /// the matrix is degenerate. /// /// @param[in] mat The input matrix /// @param[out] scl The extracted scale /// @param[out] shr The extracted shear /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. /// @return True if the scale could be extracted, false if the matrix is degenerate. template <class T> bool extractScalingAndShear (const Matrix33<T>& mat, Vec2<T>& scl, T& shr, bool exc = true); /// Return the given 3x3 matrix with scaling and shear removed. /// /// @param[in] mat The input matrix /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. template <class T> Matrix33<T> sansScalingAndShear (const Matrix33<T>& mat, bool exc = true); /// Remove scaling and shear from the given 3x3e matrix in place. // /// @param[in,out] mat The matrix to operate on /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. /// @return True if the scale could be extracted, false if the matrix is degenerate. template <class T> bool removeScalingAndShear (Matrix33<T>& mat, bool exc = true); /// Remove scaling and shear from the given 3x3 matrix in place, returning /// the extracted values. // /// @param[in,out] mat The matrix to operate on /// @param[out] scl The extracted scale /// @param[out] shr The extracted shear /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. /// @return True if the scale could be extracted, false if the matrix is degenerate. template <class T> bool extractAndRemoveScalingAndShear (Matrix33<T>& mat, Vec2<T>& scl, T& shr, bool exc = true); /// Extract the rotation from the given 2x2 matrix /// /// @param[in] mat The input matrix /// @param[out] rot The extracted rotation value template <class T> void extractEuler (const Matrix22<T>& mat, T& rot); /// Extract the rotation from the given 3x3 matrix /// /// @param[in] mat The input matrix /// @param[out] rot The extracted rotation value template <class T> void extractEuler (const Matrix33<T>& mat, T& rot); /// Extract the scaling, shear, rotation, and translation components /// of the given 3x3 matrix. The values are such that: /// /// M = S * H * R * T /// /// @param[in] mat The input matrix /// @param[out] s The extracted scale /// @param[out] h The extracted shear /// @param[out] r The extracted rotation /// @param[out] t The extracted translation /// @param[in] exc If true, throw an exception if the scaling in `mat` is very close to zero. /// @return True if the values could be extracted, false if the matrix is degenerate. template <class T> bool extractSHRT (const Matrix33<T>& mat, Vec2<T>& s, T& h, T& r, Vec2<T>& t, bool exc = true); /// Return true if the given scale can be removed from the given row /// matrix, false if `scl` is small enough that the operation would /// overflow. If `exc` is true, throw an exception on overflow. template <class T> bool checkForZeroScaleInRow (const T& scl, const Vec2<T>& row, bool exc = true); /// Return the 3xe outer product two 3-vectors template <class T> Matrix33<T> outerProduct (const Vec3<T>& a, const Vec3<T>& b); //------------------------------ // Implementation for 4x4 Matrix //------------------------------ template <class T> bool extractScaling (const Matrix44<T>& mat, Vec3<T>& scl, bool exc) { Vec3<T> shr; Matrix44<T> M (mat); if (!extractAndRemoveScalingAndShear (M, scl, shr, exc)) return false; return true; } template <class T> Matrix44<T> sansScaling (const Matrix44<T>& mat, bool exc) { Vec3<T> scl; Vec3<T> shr; Vec3<T> rot; Vec3<T> tran; if (!extractSHRT (mat, scl, shr, rot, tran, exc)) return mat; Matrix44<T> M; M.translate (tran); M.rotate (rot); M.shear (shr); return M; } template <class T> bool removeScaling (Matrix44<T>& mat, bool exc) { Vec3<T> scl; Vec3<T> shr; Vec3<T> rot; Vec3<T> tran; if (!extractSHRT (mat, scl, shr, rot, tran, exc)) return false; mat.makeIdentity(); mat.translate (tran); mat.rotate (rot); mat.shear (shr); return true; } template <class T> bool extractScalingAndShear (const Matrix44<T>& mat, Vec3<T>& scl, Vec3<T>& shr, bool exc) { Matrix44<T> M (mat); if (!extractAndRemoveScalingAndShear (M, scl, shr, exc)) return false; return true; } template <class T> Matrix44<T> sansScalingAndShear (const Matrix44<T>& mat, bool exc) { Vec3<T> scl; Vec3<T> shr; Matrix44<T> M (mat); if (!extractAndRemoveScalingAndShear (M, scl, shr, exc)) return mat; return M; } template <class T> void sansScalingAndShear (Matrix44<T>& result, const Matrix44<T>& mat, bool exc) { Vec3<T> scl; Vec3<T> shr; if (!extractAndRemoveScalingAndShear (result, scl, shr, exc)) result = mat; } template <class T> bool removeScalingAndShear (Matrix44<T>& mat, bool exc) { Vec3<T> scl; Vec3<T> shr; if (!extractAndRemoveScalingAndShear (mat, scl, shr, exc)) return false; return true; } template <class T> bool extractAndRemoveScalingAndShear (Matrix44<T>& mat, Vec3<T>& scl, Vec3<T>& shr, bool exc) { // // This implementation follows the technique described in the paper by // Spencer W. Thomas in the Graphics Gems II article: "Decomposing a // Matrix into Simple Transformations", p. 320. // Vec3<T> row[3]; row[0] = Vec3<T> (mat[0][0], mat[0][1], mat[0][2]); row[1] = Vec3<T> (mat[1][0], mat[1][1], mat[1][2]); row[2] = Vec3<T> (mat[2][0], mat[2][1], mat[2][2]); T maxVal = 0; for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) if (IMATH_INTERNAL_NAMESPACE::abs (row[i][j]) > maxVal) maxVal = IMATH_INTERNAL_NAMESPACE::abs (row[i][j]); // // We normalize the 3x3 matrix here. // It was noticed that this can improve numerical stability significantly, // especially when many of the upper 3x3 matrix's coefficients are very // close to zero; we correct for this step at the end by multiplying the // scaling factors by maxVal at the end (shear and rotation are not // affected by the normalization). if (maxVal != 0) { for (int i = 0; i < 3; i++) if (!checkForZeroScaleInRow (maxVal, row[i], exc)) return false; else row[i] /= maxVal; } // Compute X scale factor. scl.x = row[0].length(); if (!checkForZeroScaleInRow (scl.x, row[0], exc)) return false; // Normalize first row. row[0] /= scl.x; // An XY shear factor will shear the X coord. as the Y coord. changes. // There are 6 combinations (XY, XZ, YZ, YX, ZX, ZY), although we only // extract the first 3 because we can effect the last 3 by shearing in // XY, XZ, YZ combined rotations and scales. // // shear matrix < 1, YX, ZX, 0, // XY, 1, ZY, 0, // XZ, YZ, 1, 0, // 0, 0, 0, 1 > // Compute XY shear factor and make 2nd row orthogonal to 1st. shr[0] = row[0].dot (row[1]); row[1] -= shr[0] * row[0]; // Now, compute Y scale. scl.y = row[1].length(); if (!checkForZeroScaleInRow (scl.y, row[1], exc)) return false; // Normalize 2nd row and correct the XY shear factor for Y scaling. row[1] /= scl.y; shr[0] /= scl.y; // Compute XZ and YZ shears, orthogonalize 3rd row. shr[1] = row[0].dot (row[2]); row[2] -= shr[1] * row[0]; shr[2] = row[1].dot (row[2]); row[2] -= shr[2] * row[1]; // Next, get Z scale. scl.z = row[2].length(); if (!checkForZeroScaleInRow (scl.z, row[2], exc)) return false; // Normalize 3rd row and correct the XZ and YZ shear factors for Z scaling. row[2] /= scl.z; shr[1] /= scl.z; shr[2] /= scl.z; // At this point, the upper 3x3 matrix in mat is orthonormal. // Check for a coordinate system flip. If the determinant // is less than zero, then negate the matrix and the scaling factors. if (row[0].dot (row[1].cross (row[2])) < 0) for (int i = 0; i < 3; i++) { scl[i] *= -1; row[i] *= -1; } // Copy over the orthonormal rows into the returned matrix. // The upper 3x3 matrix in mat is now a rotation matrix. for (int i = 0; i < 3; i++) { mat[i][0] = row[i][0]; mat[i][1] = row[i][1]; mat[i][2] = row[i][2]; } // Correct the scaling factors for the normalization step that we // performed above; shear and rotation are not affected by the // normalization. scl *= maxVal; return true; } template <class T> void extractEulerXYZ (const Matrix44<T>& mat, Vec3<T>& rot) { // // Normalize the local x, y and z axes to remove scaling. // Vec3<T> i (mat[0][0], mat[0][1], mat[0][2]); Vec3<T> j (mat[1][0], mat[1][1], mat[1][2]); Vec3<T> k (mat[2][0], mat[2][1], mat[2][2]); i.normalize(); j.normalize(); k.normalize(); Matrix44<T> M (i[0], i[1], i[2], 0, j[0], j[1], j[2], 0, k[0], k[1], k[2], 0, 0, 0, 0, 1); // // Extract the first angle, rot.x. // rot.x = std::atan2 (M[1][2], M[2][2]); // // Remove the rot.x rotation from M, so that the remaining // rotation, N, is only around two axes, and gimbal lock // cannot occur. // Matrix44<T> N; N.rotate (Vec3<T> (-rot.x, 0, 0)); N = N * M; // // Extract the other two angles, rot.y and rot.z, from N. // T cy = std::sqrt (N[0][0] * N[0][0] + N[0][1] * N[0][1]); rot.y = std::atan2 (-N[0][2], cy); rot.z = std::atan2 (-N[1][0], N[1][1]); } template <class T> void extractEulerZYX (const Matrix44<T>& mat, Vec3<T>& rot) { // // Normalize the local x, y and z axes to remove scaling. // Vec3<T> i (mat[0][0], mat[0][1], mat[0][2]); Vec3<T> j (mat[1][0], mat[1][1], mat[1][2]); Vec3<T> k (mat[2][0], mat[2][1], mat[2][2]); i.normalize(); j.normalize(); k.normalize(); Matrix44<T> M (i[0], i[1], i[2], 0, j[0], j[1], j[2], 0, k[0], k[1], k[2], 0, 0, 0, 0, 1); // // Extract the first angle, rot.x. // rot.x = -std::atan2 (M[1][0], M[0][0]); // // Remove the x rotation from M, so that the remaining // rotation, N, is only around two axes, and gimbal lock // cannot occur. // Matrix44<T> N; N.rotate (Vec3<T> (0, 0, -rot.x)); N = N * M; // // Extract the other two angles, rot.y and rot.z, from N. // T cy = std::sqrt (N[2][2] * N[2][2] + N[2][1] * N[2][1]); rot.y = -std::atan2 (-N[2][0], cy); rot.z = -std::atan2 (-N[1][2], N[1][1]); } template <class T> Quat<T> extractQuat (const Matrix44<T>& mat) { Matrix44<T> rot; T tr, s; T q[4]; int i, j, k; Quat<T> quat; int nxt[3] = { 1, 2, 0 }; tr = mat[0][0] + mat[1][1] + mat[2][2]; // check the diagonal if (tr > 0.0) { s = std::sqrt (tr + T (1.0)); quat.r = s / T (2.0); s = T (0.5) / s; quat.v.x = (mat[1][2] - mat[2][1]) * s; quat.v.y = (mat[2][0] - mat[0][2]) * s; quat.v.z = (mat[0][1] - mat[1][0]) * s; } else { // diagonal is negative i = 0; if (mat[1][1] > mat[0][0]) i = 1; if (mat[2][2] > mat[i][i]) i = 2; j = nxt[i]; k = nxt[j]; s = std::sqrt ((mat[i][i] - (mat[j][j] + mat[k][k])) + T (1.0)); q[i] = s * T (0.5); if (s != T (0.0)) s = T (0.5) / s; q[3] = (mat[j][k] - mat[k][j]) * s; q[j] = (mat[i][j] + mat[j][i]) * s; q[k] = (mat[i][k] + mat[k][i]) * s; quat.v.x = q[0]; quat.v.y = q[1]; quat.v.z = q[2]; quat.r = q[3]; } return quat; } template <class T> bool extractSHRT (const Matrix44<T>& mat, Vec3<T>& s, Vec3<T>& h, Vec3<T>& r, Vec3<T>& t, bool exc /* = true */, typename Euler<T>::Order rOrder /* = Euler<T>::XYZ */) { Matrix44<T> rot; rot = mat; if (!extractAndRemoveScalingAndShear (rot, s, h, exc)) return false; extractEulerXYZ (rot, r); t.x = mat[3][0]; t.y = mat[3][1]; t.z = mat[3][2]; if (rOrder != Euler<T>::XYZ) { Euler<T> eXYZ (r, Euler<T>::XYZ); Euler<T> e (eXYZ, rOrder); r = e.toXYZVector(); } return true; } template <class T> bool extractSHRT (const Matrix44<T>& mat, Vec3<T>& s, Vec3<T>& h, Vec3<T>& r, Vec3<T>& t, bool exc) { return extractSHRT (mat, s, h, r, t, exc, Euler<T>::XYZ); } template <class T> bool extractSHRT (const Matrix44<T>& mat, Vec3<T>& s, Vec3<T>& h, Euler<T>& r, Vec3<T>& t, bool exc /* = true */) { return extractSHRT (mat, s, h, r, t, exc, r.order()); } template <class T> bool checkForZeroScaleInRow (const T& scl, const Vec3<T>& row, bool exc /* = true */) { for (int i = 0; i < 3; i++) { if ((abs (scl) < 1 && abs (row[i]) >= std::numeric_limits<T>::max() * abs (scl))) { if (exc) throw std::domain_error ("Cannot remove zero scaling " "from matrix."); else return false; } } return true; } template <class T> Matrix44<T> outerProduct (const Vec4<T>& a, const Vec4<T>& b) { return Matrix44<T> (a.x * b.x, a.x * b.y, a.x * b.z, a.x * b.w, a.y * b.x, a.y * b.y, a.y * b.z, a.x * b.w, a.z * b.x, a.z * b.y, a.z * b.z, a.x * b.w, a.w * b.x, a.w * b.y, a.w * b.z, a.w * b.w); } template <class T> Matrix44<T> rotationMatrix (const Vec3<T>& from, const Vec3<T>& to) { Quat<T> q; q.setRotation (from, to); return q.toMatrix44(); } template <class T> Matrix44<T> rotationMatrixWithUpDir (const Vec3<T>& fromDir, const Vec3<T>& toDir, const Vec3<T>& upDir) { // // The goal is to obtain a rotation matrix that takes // "fromDir" to "toDir". We do this in two steps and // compose the resulting rotation matrices; // (a) rotate "fromDir" into the z-axis // (b) rotate the z-axis into "toDir" // // The from direction must be non-zero; but we allow zero to and up dirs. if (fromDir.length() == 0) return Matrix44<T>(); else { Matrix44<T> zAxis2FromDir (UNINITIALIZED); alignZAxisWithTargetDir (zAxis2FromDir, fromDir, Vec3<T> (0, 1, 0)); Matrix44<T> fromDir2zAxis = zAxis2FromDir.transposed(); Matrix44<T> zAxis2ToDir (UNINITIALIZED); alignZAxisWithTargetDir (zAxis2ToDir, toDir, upDir); return fromDir2zAxis * zAxis2ToDir; } } template <class T> void alignZAxisWithTargetDir (Matrix44<T>& result, Vec3<T> targetDir, Vec3<T> upDir) { // // Ensure that the target direction is non-zero. // if (targetDir.length() == 0) targetDir = Vec3<T> (0, 0, 1); // // Ensure that the up direction is non-zero. // if (upDir.length() == 0) upDir = Vec3<T> (0, 1, 0); // // Check for degeneracies. If the upDir and targetDir are parallel // or opposite, then compute a new, arbitrary up direction that is // not parallel or opposite to the targetDir. // if (upDir.cross (targetDir).length() == 0) { upDir = targetDir.cross (Vec3<T> (1, 0, 0)); if (upDir.length() == 0) upDir = targetDir.cross (Vec3<T> (0, 0, 1)); } // // Compute the x-, y-, and z-axis vectors of the new coordinate system. // Vec3<T> targetPerpDir = upDir.cross (targetDir); Vec3<T> targetUpDir = targetDir.cross (targetPerpDir); // // Rotate the x-axis into targetPerpDir (row 0), // rotate the y-axis into targetUpDir (row 1), // rotate the z-axis into targetDir (row 2). // Vec3<T> row[3]; row[0] = targetPerpDir.normalized(); row[1] = targetUpDir.normalized(); row[2] = targetDir.normalized(); result.x[0][0] = row[0][0]; result.x[0][1] = row[0][1]; result.x[0][2] = row[0][2]; result.x[0][3] = (T) 0; result.x[1][0] = row[1][0]; result.x[1][1] = row[1][1]; result.x[1][2] = row[1][2]; result.x[1][3] = (T) 0; result.x[2][0] = row[2][0]; result.x[2][1] = row[2][1]; result.x[2][2] = row[2][2]; result.x[2][3] = (T) 0; result.x[3][0] = (T) 0; result.x[3][1] = (T) 0; result.x[3][2] = (T) 0; result.x[3][3] = (T) 1; } // Compute an orthonormal direct frame from : a position, an x axis direction and a normal to the y axis // If the x axis and normal are perpendicular, then the normal will have the same direction as the z axis. // Inputs are : // -the position of the frame // -the x axis direction of the frame // -a normal to the y axis of the frame // Return is the orthonormal frame template <class T> Matrix44<T> computeLocalFrame (const Vec3<T>& p, const Vec3<T>& xDir, const Vec3<T>& normal) { Vec3<T> _xDir (xDir); Vec3<T> x = _xDir.normalize(); Vec3<T> y = (normal % x).normalize(); Vec3<T> z = (x % y).normalize(); Matrix44<T> L; L[0][0] = x[0]; L[0][1] = x[1]; L[0][2] = x[2]; L[0][3] = 0.0; L[1][0] = y[0]; L[1][1] = y[1]; L[1][2] = y[2]; L[1][3] = 0.0; L[2][0] = z[0]; L[2][1] = z[1]; L[2][2] = z[2]; L[2][3] = 0.0; L[3][0] = p[0]; L[3][1] = p[1]; L[3][2] = p[2]; L[3][3] = 1.0; return L; } /// Add a translate/rotate/scale offset to an input frame and put it /// in another frame of reference. /// /// @param inMat input frame /// @param tOffset translate offset /// @param rOffset rotate offset in degrees /// @param sOffset scale offset /// @param ref Frame of reference /// @return The offsetted frame template <class T> Matrix44<T> addOffset (const Matrix44<T>& inMat, const Vec3<T>& tOffset, const Vec3<T>& rOffset, const Vec3<T>& sOffset, const Matrix44<T>& ref) { Matrix44<T> O; Vec3<T> _rOffset (rOffset); _rOffset *= M_PI / 180.0; O.rotate (_rOffset); O[3][0] = tOffset[0]; O[3][1] = tOffset[1]; O[3][2] = tOffset[2]; Matrix44<T> S; S.scale (sOffset); Matrix44<T> X = S * O * inMat * ref; return X; } // Compute Translate/Rotate/Scale matrix from matrix A with the Rotate/Scale of Matrix B // Inputs are : // -keepRotateA : if true keep rotate from matrix A, use B otherwise // -keepScaleA : if true keep scale from matrix A, use B otherwise // -Matrix A // -Matrix B // Return Matrix A with tweaked rotation/scale template <class T> Matrix44<T> computeRSMatrix (bool keepRotateA, bool keepScaleA, const Matrix44<T>& A, const Matrix44<T>& B) { Vec3<T> as, ah, ar, at; extractSHRT (A, as, ah, ar, at); Vec3<T> bs, bh, br, bt; extractSHRT (B, bs, bh, br, bt); if (!keepRotateA) ar = br; if (!keepScaleA) as = bs; Matrix44<T> mat; mat.makeIdentity(); mat.translate (at); mat.rotate (ar); mat.scale (as); return mat; } //----------------------------------------------------------------------------- // Implementation for 3x3 Matrix //------------------------------ template <class T> bool extractScaling (const Matrix33<T>& mat, Vec2<T>& scl, bool exc) { T shr; Matrix33<T> M (mat); if (!extractAndRemoveScalingAndShear (M, scl, shr, exc)) return false; return true; } template <class T> Matrix33<T> sansScaling (const Matrix33<T>& mat, bool exc) { Vec2<T> scl; T shr; T rot; Vec2<T> tran; if (!extractSHRT (mat, scl, shr, rot, tran, exc)) return mat; Matrix33<T> M; M.translate (tran); M.rotate (rot); M.shear (shr); return M; } template <class T> bool removeScaling (Matrix33<T>& mat, bool exc) { Vec2<T> scl; T shr; T rot; Vec2<T> tran; if (!extractSHRT (mat, scl, shr, rot, tran, exc)) return false; mat.makeIdentity(); mat.translate (tran); mat.rotate (rot); mat.shear (shr); return true; } template <class T> bool extractScalingAndShear (const Matrix33<T>& mat, Vec2<T>& scl, T& shr, bool exc) { Matrix33<T> M (mat); if (!extractAndRemoveScalingAndShear (M, scl, shr, exc)) return false; return true; } template <class T> Matrix33<T> sansScalingAndShear (const Matrix33<T>& mat, bool exc) { Vec2<T> scl; T shr; Matrix33<T> M (mat); if (!extractAndRemoveScalingAndShear (M, scl, shr, exc)) return mat; return M; } template <class T> bool removeScalingAndShear (Matrix33<T>& mat, bool exc) { Vec2<T> scl; T shr; if (!extractAndRemoveScalingAndShear (mat, scl, shr, exc)) return false; return true; } template <class T> bool extractAndRemoveScalingAndShear (Matrix33<T>& mat, Vec2<T>& scl, T& shr, bool exc) { Vec2<T> row[2]; row[0] = Vec2<T> (mat[0][0], mat[0][1]); row[1] = Vec2<T> (mat[1][0], mat[1][1]); T maxVal = 0; for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) if (IMATH_INTERNAL_NAMESPACE::abs (row[i][j]) > maxVal) maxVal = IMATH_INTERNAL_NAMESPACE::abs (row[i][j]); // // We normalize the 2x2 matrix here. // It was noticed that this can improve numerical stability significantly, // especially when many of the upper 2x2 matrix's coefficients are very // close to zero; we correct for this step at the end by multiplying the // scaling factors by maxVal at the end (shear and rotation are not // affected by the normalization). if (maxVal != 0) { for (int i = 0; i < 2; i++) if (!checkForZeroScaleInRow (maxVal, row[i], exc)) return false; else row[i] /= maxVal; } // Compute X scale factor. scl.x = row[0].length(); if (!checkForZeroScaleInRow (scl.x, row[0], exc)) return false; // Normalize first row. row[0] /= scl.x; // An XY shear factor will shear the X coord. as the Y coord. changes. // There are 2 combinations (XY, YX), although we only extract the XY // shear factor because we can effect the an YX shear factor by // shearing in XY combined with rotations and scales. // // shear matrix < 1, YX, 0, // XY, 1, 0, // 0, 0, 1 > // Compute XY shear factor and make 2nd row orthogonal to 1st. shr = row[0].dot (row[1]); row[1] -= shr * row[0]; // Now, compute Y scale. scl.y = row[1].length(); if (!checkForZeroScaleInRow (scl.y, row[1], exc)) return false; // Normalize 2nd row and correct the XY shear factor for Y scaling. row[1] /= scl.y; shr /= scl.y; // At this point, the upper 2x2 matrix in mat is orthonormal. // Check for a coordinate system flip. If the determinant // is -1, then flip the rotation matrix and adjust the scale(Y) // and shear(XY) factors to compensate. if (row[0][0] * row[1][1] - row[0][1] * row[1][0] < 0) { row[1][0] *= -1; row[1][1] *= -1; scl[1] *= -1; shr *= -1; } // Copy over the orthonormal rows into the returned matrix. // The upper 2x2 matrix in mat is now a rotation matrix. for (int i = 0; i < 2; i++) { mat[i][0] = row[i][0]; mat[i][1] = row[i][1]; } scl *= maxVal; return true; } template <class T> void extractEuler (const Matrix22<T>& mat, T& rot) { // // Normalize the local x and y axes to remove scaling. // Vec2<T> i (mat[0][0], mat[0][1]); Vec2<T> j (mat[1][0], mat[1][1]); i.normalize(); j.normalize(); // // Extract the angle, rot. // rot = -std::atan2 (j[0], i[0]); } template <class T> void extractEuler (const Matrix33<T>& mat, T& rot) { // // Normalize the local x and y axes to remove scaling. // Vec2<T> i (mat[0][0], mat[0][1]); Vec2<T> j (mat[1][0], mat[1][1]); i.normalize(); j.normalize(); // // Extract the angle, rot. // rot = -std::atan2 (j[0], i[0]); } template <class T> bool extractSHRT (const Matrix33<T>& mat, Vec2<T>& s, T& h, T& r, Vec2<T>& t, bool exc) { Matrix33<T> rot; rot = mat; if (!extractAndRemoveScalingAndShear (rot, s, h, exc)) return false; extractEuler (rot, r); t.x = mat[2][0]; t.y = mat[2][1]; return true; } /// @cond Doxygen_Suppress template <class T> bool checkForZeroScaleInRow (const T& scl, const Vec2<T>& row, bool exc /* = true */) { for (int i = 0; i < 2; i++) { if ((abs (scl) < 1 && abs (row[i]) >= std::numeric_limits<T>::max() * abs (scl))) { if (exc) throw std::domain_error ("Cannot remove zero scaling from matrix."); else return false; } } return true; } /// @endcond template <class T> Matrix33<T> outerProduct (const Vec3<T>& a, const Vec3<T>& b) { return Matrix33<T> (a.x * b.x, a.x * b.y, a.x * b.z, a.y * b.x, a.y * b.y, a.y * b.z, a.z * b.x, a.z * b.y, a.z * b.z); } /// Computes the translation and rotation that brings the 'from' points /// as close as possible to the 'to' points under the Frobenius norm. /// To be more specific, let x be the matrix of 'from' points and y be /// the matrix of 'to' points, we want to find the matrix A of the form /// [ R t ] /// [ 0 1 ] /// that minimizes /// || (A*x - y)^T * W * (A*x - y) ||_F /// If doScaling is true, then a uniform scale is allowed also. /// @param A From points /// @param B To points /// @param weights Per-point weights /// @param numPoints The number of points in `A`, `B`, and `weights` (must be equal) /// @param doScaling If true, include a scaling transformation /// @return The procrustes transformation template <typename T> M44d procrustesRotationAndTranslation (const Vec3<T>* A, const Vec3<T>* B, const T* weights, const size_t numPoints, const bool doScaling = false); /// Computes the translation and rotation that brings the 'from' points /// as close as possible to the 'to' points under the Frobenius norm. /// To be more specific, let x be the matrix of 'from' points and y be /// the matrix of 'to' points, we want to find the matrix A of the form /// [ R t ] /// [ 0 1 ] /// that minimizes /// || (A*x - y)^T * W * (A*x - y) ||_F /// If doScaling is true, then a uniform scale is allowed also. /// @param A From points /// @param B To points /// @param numPoints The number of points in `A` and `B` (must be equal) /// @param doScaling If true, include a scaling transformation /// @return The procrustes transformation template <typename T> M44d procrustesRotationAndTranslation (const Vec3<T>* A, const Vec3<T>* B, const size_t numPoints, const bool doScaling = false); /// Compute the SVD of a 3x3 matrix using Jacobi transformations. This method /// should be quite accurate (competitive with LAPACK) even for poorly /// conditioned matrices, and because it has been written specifically for the /// 3x3/4x4 case it is much faster than calling out to LAPACK. /// /// The SVD of a 3x3/4x4 matrix A is defined as follows: /// A = U * S * V^T /// where S is the diagonal matrix of singular values and both U and V are /// orthonormal. By convention, the entries S are all positive and sorted from /// the largest to the smallest. However, some uses of this function may /// require that the matrix U*V^T have positive determinant; in this case, we /// may make the smallest singular value negative to ensure that this is /// satisfied. /// /// Currently only available for single- and double-precision matrices. template <typename T> void jacobiSVD (const Matrix33<T>& A, Matrix33<T>& U, Vec3<T>& S, Matrix33<T>& V, const T tol = std::numeric_limits<T>::epsilon(), const bool forcePositiveDeterminant = false); /// Compute the SVD of a 3x3 matrix using Jacobi transformations. This method /// should be quite accurate (competitive with LAPACK) even for poorly /// conditioned matrices, and because it has been written specifically for the /// 3x3/4x4 case it is much faster than calling out to LAPACK. /// /// The SVD of a 3x3/4x4 matrix A is defined as follows: /// A = U * S * V^T /// where S is the diagonal matrix of singular values and both U and V are /// orthonormal. By convention, the entries S are all positive and sorted from /// the largest to the smallest. However, some uses of this function may /// require that the matrix U*V^T have positive determinant; in this case, we /// may make the smallest singular value negative to ensure that this is /// satisfied. /// /// Currently only available for single- and double-precision matrices. template <typename T> void jacobiSVD (const Matrix44<T>& A, Matrix44<T>& U, Vec4<T>& S, Matrix44<T>& V, const T tol = std::numeric_limits<T>::epsilon(), const bool forcePositiveDeterminant = false); /// Compute the eigenvalues (S) and the eigenvectors (V) of a real /// symmetric matrix using Jacobi transformation, using a given /// tolerance `tol`. /// /// Jacobi transformation of a 3x3/4x4 matrix A outputs S and V: /// A = V * S * V^T /// where V is orthonormal and S is the diagonal matrix of eigenvalues. /// Input matrix A must be symmetric. A is also modified during /// the computation so that upper diagonal entries of A become zero. template <typename T> void jacobiEigenSolver (Matrix33<T>& A, Vec3<T>& S, Matrix33<T>& V, const T tol); /// Compute the eigenvalues (S) and the eigenvectors (V) of /// a real symmetric matrix using Jacobi transformation. /// /// Jacobi transformation of a 3x3/4x4 matrix A outputs S and V: /// A = V * S * V^T /// where V is orthonormal and S is the diagonal matrix of eigenvalues. /// Input matrix A must be symmetric. A is also modified during /// the computation so that upper diagonal entries of A become zero. template <typename T> inline void jacobiEigenSolver (Matrix33<T>& A, Vec3<T>& S, Matrix33<T>& V) { jacobiEigenSolver (A, S, V, std::numeric_limits<T>::epsilon()); } /// Compute the eigenvalues (S) and the eigenvectors (V) of a real /// symmetric matrix using Jacobi transformation, using a given /// tolerance `tol`. /// /// Jacobi transformation of a 3x3/4x4 matrix A outputs S and V: /// A = V * S * V^T /// where V is orthonormal and S is the diagonal matrix of eigenvalues. /// Input matrix A must be symmetric. A is also modified during /// the computation so that upper diagonal entries of A become zero. template <typename T> void jacobiEigenSolver (Matrix44<T>& A, Vec4<T>& S, Matrix44<T>& V, const T tol); /// Compute the eigenvalues (S) and the eigenvectors (V) of /// a real symmetric matrix using Jacobi transformation. /// /// Jacobi transformation of a 3x3/4x4 matrix A outputs S and V: /// A = V * S * V^T /// where V is orthonormal and S is the diagonal matrix of eigenvalues. /// Input matrix A must be symmetric. A is also modified during /// the computation so that upper diagonal entries of A become zero. template <typename T> inline void jacobiEigenSolver (Matrix44<T>& A, Vec4<T>& S, Matrix44<T>& V) { jacobiEigenSolver (A, S, V, std::numeric_limits<T>::epsilon()); } /// Compute a eigenvector corresponding to the abs max eigenvalue /// of a real symmetric matrix using Jacobi transformation. template <typename TM, typename TV> void maxEigenVector (TM& A, TV& S); /// Compute a eigenvector corresponding to the abs min eigenvalue /// of a real symmetric matrix using Jacobi transformation. template <typename TM, typename TV> void minEigenVector (TM& A, TV& S); IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHMATRIXALGO_H PyImathVec4Impl.h 0000644 00000065443 15125213144 0007646 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathVec3Impl_h_ #define _PyImathVec3Impl_h_ // // This .C file was turned into a header file so that instantiations // of the various V3* types can be spread across multiple files in // order to work around MSVC limitations. // #include <Python.h> #include <boost/python.hpp> #include <boost/python/make_constructor.hpp> #include <boost/format.hpp> #include <ImathVec.h> #include <ImathVecAlgo.h> #include "PyImath.h" #include "PyImathVec.h" #include "PyImathDecorators.h" #include "PyImathMathExc.h" namespace PyImath { using namespace boost::python; using namespace IMATH_NAMESPACE; template <class T> struct Vec4Name { static const char *value(); }; // create a new default constructor that initializes Vec3<T> to zero. template <class T> static Vec4<T> * Vec4_construct_default() { return new Vec4<T>(T(0),T(0),T(0),T(0)); } template <class T> static Vec4<T> * Vec4_object_constructor1(const object &obj) { Vec4<T> res; extract<Vec4<int> > e1(obj); extract<Vec4<float> > e2(obj); extract<Vec4<double> > e3(obj); extract<tuple> e4(obj); extract<double> e5(obj); extract<list> e6(obj); if(e1.check()) { res = e1(); } else if(e2.check()) { res = e2(); } else if(e3.check()) { res = e3(); } else if(e4.check()) { tuple t = e4(); if(t.attr("__len__")() == 4) { res.x = extract<T>(t[0]); res.y = extract<T>(t[1]); res.z = extract<T>(t[2]); res.w = extract<T>(t[3]); } else throw std::invalid_argument ("tuple must have length of 4"); } else if(e5.check()) { T a = (T) e5(); res = IMATH_NAMESPACE::Vec4<T>(a, a, a, a); } else if(e6.check()) { list l = e6(); if(l.attr("__len__")() == 4) { res.x = extract<T>(l[0]); res.y = extract<T>(l[1]); res.z = extract<T>(l[2]); res.w = extract<T>(l[3]); } else throw std::invalid_argument ("list must have length of 4"); } else throw std::invalid_argument ("invalid parameters passed to Vec4 constructor"); Vec4<T> *v = new Vec4<T>; *v = res; return v; } template <class T> static Vec4<T> * Vec4_object_constructor2(const object &obj1, const object &obj2, const object &obj3, const object& obj4) { extract<double> e1(obj1); extract<double> e2(obj2); extract<double> e3(obj3); extract<double> e4(obj4); Vec4<T> *v = new Vec4<T>; if(e1.check()) { v->x = (T) e1();} else { throw std::invalid_argument ("invalid parameters passed to Vec4 constructor"); } if(e2.check()) { v->y = (T) e2();} else { throw std::invalid_argument ("invalid parameters passed to Vec4 constructor"); } if(e3.check()) { v->z = (T) e3();} else { throw std::invalid_argument ("invalid parameters passed to Vec4 constructor"); } if(e4.check()) { v->w = (T) e4();} else { throw std::invalid_argument ("invalid parameters passed to Vec4 constructor"); } return v; } // Implementations of str and repr are same here, // but we'll specialize repr for float and double to make them exact. template <class T> static std::string Vec4_str(const Vec4<T> &v) { std::stringstream stream; stream << Vec4Name<T>::value() << "(" << v.x << ", " << v.y << ", " << v.z << ", " << v.w << ")"; return stream.str(); } template <class T> static std::string Vec4_repr(const Vec4<T> &v) { std::stringstream stream; stream << Vec4Name<T>::value() << "(" << v.x << ", " << v.y << ", " << v.z << ", " << v.w << ")"; return stream.str(); } template <class T> static T Vec4_dot(const IMATH_NAMESPACE::Vec4<T> &v, const IMATH_NAMESPACE::Vec4<T> &other) { MATH_EXC_ON; return v.dot(other); } template <class T> static FixedArray<T> Vec4_dot_Vec4Array(const IMATH_NAMESPACE::Vec4<T> &va, const FixedArray<IMATH_NAMESPACE::Vec4<T> > &vb) { PY_IMATH_LEAVE_PYTHON; size_t len = vb.len(); FixedArray<T> f(len); for (size_t i = 0; i < len; ++i) f[i] = va.dot(vb[i]); return f; } template <class T> static T Vec4_length(const IMATH_NAMESPACE::Vec4<T> &v) { MATH_EXC_ON; return v.length(); } template <class T> static T Vec4_length2(const IMATH_NAMESPACE::Vec4<T> &v) { MATH_EXC_ON; return v.length2(); } template <class T> static const Vec4<T> & Vec4_normalize(IMATH_NAMESPACE::Vec4<T> &v) { MATH_EXC_ON; return v.normalize(); } template <class T> static const Vec4<T> & Vec4_normalizeExc(IMATH_NAMESPACE::Vec4<T> &v) { MATH_EXC_ON; return v.normalizeExc(); } template <class T> static const Vec4<T> & Vec4_normalizeNonNull(IMATH_NAMESPACE::Vec4<T> &v) { MATH_EXC_ON; return v.normalizeNonNull(); } template <class T> static Vec4<T> Vec4_normalized(const IMATH_NAMESPACE::Vec4<T> &v) { MATH_EXC_ON; return v.normalized(); } template <class T> static Vec4<T> Vec4_normalizedExc(const IMATH_NAMESPACE::Vec4<T> &v) { MATH_EXC_ON; return v.normalizedExc(); } template <class T> static Vec4<T> Vec4_normalizedNonNull(const IMATH_NAMESPACE::Vec4<T> &v) { MATH_EXC_ON; return v.normalizedNonNull(); } template <class T> static const Vec4<T> & Vec4_negate(IMATH_NAMESPACE::Vec4<T> &v) { MATH_EXC_ON; return v.negate(); } template <class T> static Vec4<T> orthogonal(const Vec4<T> &v, const Vec4<T> &v0) { MATH_EXC_ON; return IMATH_NAMESPACE::orthogonal(v, v0); } template <class T> static Vec4<T> project(const Vec4<T> &v, const Vec4<T> &v0) { MATH_EXC_ON; return IMATH_NAMESPACE::project(v0, v); } template <class T> static Vec4<T> reflect(const Vec4<T> &v, const Vec4<T> &v0) { MATH_EXC_ON; return IMATH_NAMESPACE::reflect(v, v0); } template <class T> static void setValue(Vec4<T> &v, T a, T b, T c, T d) { v.x = a; v.y = b; v.z = c; v.w = d; } template <class T> static Vec4<T> Vec4_add (const Vec4<T> &v, const Vec4<T> &w) { MATH_EXC_ON; return v + w; } template <class T> static Vec4<T> Vec4_sub (const Vec4<T> &v, const Vec4<T> &w) { MATH_EXC_ON; return v - w; } template <class T> static Vec4<T> Vec4_neg (const Vec4<T> &v) { MATH_EXC_ON; return -v; } template <class T, class U> static Vec4<T> Vec4_mul (const Vec4<T> &v, Vec4<U> &w) { MATH_EXC_ON; Vec4<T> w2 (w); return v * w2; } template <class T> static Vec4<T> Vec4_mulT (const Vec4<T> &v, T t) { MATH_EXC_ON; return v * t; } template <class T> static FixedArray<IMATH_NAMESPACE::Vec4<T> > Vec4_mulTArray (const Vec4<T> &v, const FixedArray<T> &t) { PY_IMATH_LEAVE_PYTHON; size_t len = t.len(); FixedArray<IMATH_NAMESPACE::Vec4<T> > retval(len); for (size_t i=0; i<len; ++i) retval[i] = v*t[i]; return retval; } template <class T> static FixedArray<IMATH_NAMESPACE::Vec4<T> > Vec4_rmulTArray (const Vec4<T> &v, const FixedArray<T> &t) { return Vec4_mulTArray(v,t); } template <class T,class S> static Vec4<T> Vec4_div (Vec4<T> &v, Vec4<S> &w) { MATH_EXC_ON; return v / w; } template <class T> static Vec4<T> Vec4_rmulT (Vec4<T> &v, T t) { MATH_EXC_ON; return t * v; } template <class T, class U> static const Vec4<T> & Vec4_imulV(Vec4<T> &v, const Vec4<U> &w) { MATH_EXC_ON; return v *= w; } template <class T> static const Vec4<T> & Vec4_imulT(IMATH_NAMESPACE::Vec4<T> &v, T t) { MATH_EXC_ON; return v *= t; } template <class T, class U> static Vec4<T> Vec4_mulM44 (Vec4<T> &v, const Matrix44<U> &m) { MATH_EXC_ON; return v * m; } template <class T> static const Vec4<T> & Vec4_idivObj(IMATH_NAMESPACE::Vec4<T> &v, const object &o) { MATH_EXC_ON; Vec4<T> v2; if (PyImath::V4<T>::convert (o.ptr(), &v2)) { return v /= v2; } else { extract<double> e(o); if (e.check()) return v /= (T) e(); else throw std::invalid_argument ("V4 division expects an argument " "convertible to a V4"); } } template <class T> static Vec4<T> Vec4_subT(const Vec4<T> &v, T a) { MATH_EXC_ON; Vec4<T> w; setValue(w, (T) (v.x - a), (T) (v.y - a), (T) (v.z - a), (T) (v.w - a)); return w; } template <class T,class BoostPyType> static Vec4<T> Vec4_subTuple(const Vec4<T> &v, const BoostPyType &t) { MATH_EXC_ON; Vec4<T> w; if(t.attr("__len__")() == 4) { w.x = v.x - extract<T>(t[0]); w.y = v.y - extract<T>(t[1]); w.z = v.z - extract<T>(t[2]); w.w = v.w - extract<T>(t[3]); } else throw std::invalid_argument ("tuple must have length of 4"); return w; } template <class T> static Vec4<T> Vec4_rsubT(const Vec4<T> &v, T a) { MATH_EXC_ON; Vec4<T> w(a - v.x, a - v.y, a - v.z, a - v.w); return w; } template <class T, class BoostPyType> static Vec4<T> Vec4_rsubTuple(const Vec4<T> &v, const BoostPyType &t) { MATH_EXC_ON; Vec4<T> w; if(t.attr("__len__")() == 4) { w.x = extract<T>(t[0]) - v.x; w.y = extract<T>(t[1]) - v.y; w.z = extract<T>(t[2]) - v.z; w.w = extract<T>(t[3]) - v.w; } else throw std::invalid_argument ("tuple must have length of 4"); return w; } template <class T, class BoostPyType> static Vec4<T> Vec4_addTuple(const Vec4<T> &v, const BoostPyType &t) { MATH_EXC_ON; Vec4<T> w; if(t.attr("__len__")() == 4) { w.x = v.x + extract<T>(t[0]); w.y = v.y + extract<T>(t[1]); w.z = v.z + extract<T>(t[2]); w.w = v.w + extract<T>(t[3]); } else throw std::invalid_argument ("tuple must have length of 4"); return w; } template <class T> static Vec4<T> Vec4_addT(const Vec4<T> &v, T a) { MATH_EXC_ON; Vec4<T> w; setValue(w, (T) (v.x + a), (T) (v.y + a), (T) (v.z + a), (T) (v.w + a)); return w; } template <class T, class U> static Vec4<T> Vec4_addV(const Vec4<T> &v, const Vec4<U> &w) { MATH_EXC_ON; return v + w; } template <class T, class U> static const Vec4<T> & Vec4_iaddV(Vec4<T> &v, const Vec4<U> &w) { MATH_EXC_ON; return v += w; } template <class T, class U> static Vec4<T> Vec4_subV(const Vec4<T> &v, const Vec4<U> &w) { MATH_EXC_ON; return v - w; } template <class T, class U> static const Vec4<T> & Vec4_isubV(Vec4<T> &v, const Vec4<U> &w) { MATH_EXC_ON; return v -= w; } template <class T> static Vec4<T> mult(const Vec4<T> &v, tuple t) { MATH_EXC_ON; Vec4<T> w; if(t.attr("__len__")() == 1){ w.x = v.x*extract<T>(t[0]); w.y = v.y*extract<T>(t[0]); w.z = v.z*extract<T>(t[0]); w.w = v.w*extract<T>(t[0]); } else if(t.attr("__len__")() == 4){ w.x = v.x*extract<T>(t[0]); w.y = v.y*extract<T>(t[1]); w.z = v.z*extract<T>(t[2]); w.w = v.w*extract<T>(t[3]); } else throw std::invalid_argument ("tuple must have length of 1 or 4"); return w; } template <class T, class U> static const Vec4<T> & Vec4_imulM44 (Vec4<T> &v, const Matrix44<U> &m) { MATH_EXC_ON; return v *= m; } template <class T, class BoostPyType> static Vec4<T> Vec4_divTuple(const Vec4<T> &v, const BoostPyType &t) { if(t.attr("__len__")() == 4) { T x = extract<T>(t[0]); T y = extract<T>(t[1]); T z = extract<T>(t[2]); T w = extract<T>(t[3]); if(x != T(0) && y != T(0) && z != T(0) && w != T(0)) return Vec4<T>(v.x / x, v.y / y, v.z / z, v.w / w); else throw std::domain_error ("Division by zero"); } else throw std::invalid_argument ("Vec4 expects tuple of length 4"); } template <class T, class BoostPyType> static Vec4<T> Vec4_rdivTuple(const Vec4<T> &v, const BoostPyType &t) { MATH_EXC_ON; Vec4<T> res; if(t.attr("__len__")() == 4) { T x = extract<T>(t[0]); T y = extract<T>(t[1]); T z = extract<T>(t[2]); T w = extract<T>(t[3]); if(v.x != T(0) && v.y != T(0) && v.z != T(0) && v.w != T(0)){ setValue(res, (T) (x / v.x), (T) (y / v.y), (T) (z / v.z), (T) (w / v.w)); } else throw std::domain_error ("Division by zero"); } else throw std::invalid_argument ("tuple must have length of 4"); return res; } template <class T> static Vec4<T> Vec4_divT(const Vec4<T> &v, T a) { MATH_EXC_ON; Vec4<T> res; if(a != T(0)){ setValue(res, (T) (v.x / a), (T) (v.y / a), (T) (v.z / a), (T) (v.w / a)); } else throw std::domain_error ("Division by zero"); return res; } template <class T> static Vec4<T> Vec4_rdivT(const Vec4<T> &v, T a) { MATH_EXC_ON; Vec4<T> res; if(v.x != T(0) && v.y != T(0) && v.z != T(0) && v.w != T(0)){ setValue(res, (T) (a / v.x), (T) (a / v.y), (T) (a / v.z), (T) (a / v.w)); } else throw std::domain_error ("Division by zero"); return res; } template <class T> static Vec4<T> Vec4_Vec4_mulT(const Vec4<T>& v, const Vec4<T>& w) { MATH_EXC_ON; return v*w; } template <class T> static Vec4<T> Vec4_Vec4_divT(const Vec4<T>& v, const Vec4<T>& w) { MATH_EXC_ON; return v/w; } template <class T> static bool lessThan(const Vec4<T> &v, const object &obj) { extract<Vec4<T> > e1(obj); extract<tuple> e2(obj); Vec4<T> res; if(e1.check()) { res = e1(); } else if(e2.check()) { tuple t = e2(); T x = extract<T>(t[0]); T y = extract<T>(t[1]); T z = extract<T>(t[2]); T w = extract<T>(t[3]); setValue(res,x,y,z,w); } else throw std::invalid_argument ("invalid parameters passed to operator <"); bool isLessThan = (v.x <= res.x && v.y <= res.y && v.z <= res.z && v.w <= res.w) && v != res; return isLessThan; } template <class T> static bool greaterThan(const Vec4<T> &v, const object &obj) { extract<Vec4<T> > e1(obj); extract<tuple> e2(obj); Vec4<T> res; if(e1.check()) { res = e1(); } else if(e2.check()) { tuple t = e2(); T x = extract<T>(t[0]); T y = extract<T>(t[1]); T z = extract<T>(t[2]); T w = extract<T>(t[3]); setValue(res,x,y,z,w); } else throw std::invalid_argument ("invalid parameters passed to operator >"); bool isGreaterThan = (v.x >= res.x && v.y >= res.y && v.z >= res.z && v.w >= res.w) && v != res; return isGreaterThan; } template <class T> static bool lessThanEqual(const Vec4<T> &v, const object &obj) { extract<Vec4<T> > e1(obj); extract<tuple> e2(obj); Vec4<T> res; if(e1.check()) { res = e1(); } else if(e2.check()) { tuple t = e2(); T x = extract<T>(t[0]); T y = extract<T>(t[1]); T z = extract<T>(t[2]); T w = extract<T>(t[2]); setValue(res,x,y,z,w); } else throw std::invalid_argument ("invalid parameters passed to operator <="); bool isLessThanEqual = (v.x <= res.x && v.y <= res.y && v.z <= res.z && v.w <= res.w); return isLessThanEqual; } template <class T> static bool greaterThanEqual(const Vec4<T> &v, const object &obj) { extract<Vec4<T> > e1(obj); extract<tuple> e2(obj); Vec4<T> res; if(e1.check()) { res = e1(); } else if(e2.check()) { tuple t = e2(); T x = extract<T>(t[0]); T y = extract<T>(t[1]); T z = extract<T>(t[2]); T w = extract<T>(t[3]); setValue(res,x,y,z,w); } else throw std::invalid_argument ("invalid parameters passed to operator >="); bool isGreaterThanEqual = (v.x >= res.x && v.y >= res.y && v.z >= res.z && v.w >= res.w); return isGreaterThanEqual; } template <class T> static bool equalWithAbsErrorObj(const Vec4<T> &v, const object &obj1, const object &obj2) { extract<Vec4<int> > e1(obj1); extract<Vec4<float> > e2(obj1); extract<Vec4<double> > e3(obj1); extract<tuple> e4(obj1); extract<double> e5(obj2); Vec4<T> res; if(e1.check()) { res = e1(); } else if(e2.check()) { res = e2(); } else if(e3.check()) { res = e3(); } else if(e4.check()) { tuple t = e4(); if(t.attr("__len__")() == 4) { res.x = extract<T>(t[0]); res.y = extract<T>(t[1]); res.z = extract<T>(t[2]); res.z = extract<T>(t[3]); } else throw std::invalid_argument ("tuple of length 4 expected"); } else throw std::invalid_argument ("invalid parameters passed to equalWithAbsError"); if(e5.check()) { return v.equalWithAbsError(res, (T) e5()); } else throw std::invalid_argument ("invalid parameters passed to equalWithAbsError"); } template <class T> static bool equalWithRelErrorObj(const Vec4<T> &v, const object &obj1, const object &obj2) { extract<Vec4<int> > e1(obj1); extract<Vec4<float> > e2(obj1); extract<Vec4<double> > e3(obj1); extract<tuple> e4(obj1); extract<double> e5(obj2); Vec4<T> res; if(e1.check()) { res = e1(); } else if(e2.check()) { res = e2(); } else if(e3.check()) { res = e3(); } else if(e4.check()) { tuple t = e4(); if(t.attr("__len__")() == 4) { res.x = extract<T>(t[0]); res.y = extract<T>(t[1]); res.z = extract<T>(t[2]); res.w = extract<T>(t[3]); } else throw std::invalid_argument ("tuple of length 4 expected"); } else throw std::invalid_argument ("invalid parameters passed to equalWithRelError"); if(e5.check()) { return v.equalWithRelError(res, (T) e5()); } else throw std::invalid_argument ("invalid parameters passed to equalWithRelError"); } template <class T> static bool equal(const Vec4<T> &v, const tuple &t) { Vec4<T> res; if(t.attr("__len__")() == 4) { res.x = extract<T>(t[0]); res.y = extract<T>(t[1]); res.z = extract<T>(t[2]); res.w = extract<T>(t[3]); return (v == res); } else throw std::invalid_argument ("tuple of length 4 expected"); } template <class T> static bool notequal(const Vec4<T> &v, const tuple &t) { Vec4<T> res; if(t.attr("__len__")() == 4) { res.x = extract<T>(t[0]); res.y = extract<T>(t[1]); res.z = extract<T>(t[2]); res.w = extract<T>(t[3]); return (v != res); } else throw std::invalid_argument ("tuple of length 4 expected"); } // Trick to register methods for float-only-based vectors template <class T, IMATH_ENABLE_IF(!std::is_integral<T>::value)> void register_Vec4_floatonly(class_<Vec4<T>>& vec4_class) { vec4_class .def("length", &Vec4_length<T>,"length() magnitude of the vector") .def("normalize", &Vec4_normalize<T>,return_internal_reference<>(), "v.normalize() destructively normalizes v and returns a reference to it") .def("normalizeExc", &Vec4_normalizeExc<T>,return_internal_reference<>(), "v.normalizeExc() destructively normalizes V and returns a reference to it, throwing an exception if length() == 0") .def("normalizeNonNull", &Vec4_normalizeNonNull<T>,return_internal_reference<>(), "v.normalizeNonNull() destructively normalizes V and returns a reference to it, faster if lngth() != 0") .def("normalized", &Vec4_normalized<T>, "v.normalized() returns a normalized copy of v") .def("normalizedExc", &Vec4_normalizedExc<T>, "v.normalizedExc() returns a normalized copy of v, throwing an exception if length() == 0") .def("normalizedNonNull", &Vec4_normalizedNonNull<T>, "v.normalizedNonNull() returns a normalized copy of v, faster if lngth() != 0") .def("orthogonal", &orthogonal<T>) .def("project", &project<T>) .def("reflect", &reflect<T>) ; } template <class T, IMATH_ENABLE_IF(std::is_integral<T>::value)> void register_Vec4_floatonly(class_<Vec4<T>>& vec4_class) { } template <class T> class_<Vec4<T> > register_Vec4() { typedef PyImath::StaticFixedArray<Vec4<T>,T,4> Vec4_helper; class_<Vec4<T> > vec4_class(Vec4Name<T>::value(), Vec4Name<T>::value(),init<Vec4<T> >("copy construction")); vec4_class .def("__init__",make_constructor(Vec4_construct_default<T>),"initialize to (0,0,0,0)") .def("__init__",make_constructor(Vec4_object_constructor1<T>)) .def("__init__",make_constructor(Vec4_object_constructor2<T>)) .def_readwrite("x", &Vec4<T>::x) .def_readwrite("y", &Vec4<T>::y) .def_readwrite("z", &Vec4<T>::z) .def_readwrite("w", &Vec4<T>::w) .def("baseTypeEpsilon", &Vec4<T>::baseTypeEpsilon,"baseTypeEpsilon() epsilon value of the base type of the vector") .staticmethod("baseTypeEpsilon") .def("baseTypeMax", &Vec4<T>::baseTypeMax,"baseTypeMax() max value of the base type of the vector") .staticmethod("baseTypeMax") .def("baseTypeLowest", &Vec4<T>::baseTypeLowest,"baseTypeLowest() largest negative value of the base type of the vector") .staticmethod("baseTypeLowest") .def("baseTypeSmallest", &Vec4<T>::baseTypeSmallest,"baseTypeSmallest() smallest value of the base type of the vector") .staticmethod("baseTypeSmallest") .def("dimensions", &Vec4<T>::dimensions,"dimensions() number of dimensions in the vector") .staticmethod("dimensions") .def("dot", &Vec4_dot<T>,"v1.dot(v2) inner product of the two vectors") .def("dot", &Vec4_dot_Vec4Array<T>,"v1.dot(v2) array inner product") .def("equalWithAbsError", &Vec4<T>::equalWithAbsError, "v1.equalWithAbsError(v2) true if the elements " "of v1 and v2 are the same with an absolute error of no more than e, " "i.e., abs(v1[i] - v2[i]) <= e") .def("equalWithAbsError", &equalWithAbsErrorObj<T>) .def("equalWithRelError", &Vec4<T>::equalWithRelError, "v1.equalWithAbsError(v2) true if the elements " "of v1 and v2 are the same with an absolute error of no more than e, " "i.e., abs(v1[i] - v2[i]) <= e * abs(v1[i])") .def("equalWithRelError", &equalWithRelErrorObj<T>) .def("length2", &Vec4_length2<T>,"length2() square magnitude of the vector") .def("__len__", Vec4_helper::len) .def("__getitem__", Vec4_helper::getitem,return_value_policy<copy_non_const_reference>()) .def("__setitem__", Vec4_helper::setitem) .def("negate", &Vec4_negate<T>, return_internal_reference<>()) .def("setValue", &setValue<T>) .def("__neg__", &Vec4_neg<T>) .def("__mul__", &Vec4_mul<T, int>) .def("__mul__", &Vec4_mul<T, float>) .def("__mul__", &Vec4_mul<T, double>) .def("__mul__", &Vec4_mulT<T>) .def("__mul__", &Vec4_mulTArray<T>) .def("__rmul__", &Vec4_rmulT<T>) .def("__rmul__", &Vec4_rmulTArray<T>) .def("__imul__", &Vec4_imulV<T, int>,return_internal_reference<>()) .def("__imul__", &Vec4_imulV<T, float>,return_internal_reference<>()) .def("__imul__", &Vec4_imulV<T, double>,return_internal_reference<>()) .def("__imul__", &Vec4_imulT<T>,return_internal_reference<>()) .def("__div__", &Vec4_Vec4_divT<T>) .def("__truediv__", &Vec4_Vec4_divT<T>) .def("__mul__", &Vec4_mulM44<T, float>) .def("__mul__", &Vec4_mulM44<T, double>) .def("__mul__", &Vec4_Vec4_mulT<T>) .def("__div__", &Vec4_div<T,int>) .def("__div__", &Vec4_div<T,float>) .def("__div__", &Vec4_div<T,double>) .def("__div__", &Vec4_divTuple<T,tuple>) .def("__div__", &Vec4_divTuple<T,list>) .def("__div__", &Vec4_divT<T>) .def("__truediv__", &Vec4_div<T,int>) .def("__truediv__", &Vec4_div<T,float>) .def("__truediv__", &Vec4_div<T,double>) .def("__truediv__", &Vec4_divTuple<T,tuple>) .def("__truediv__", &Vec4_divTuple<T,list>) .def("__truediv__", &Vec4_divT<T>) .def("__rdiv__", &Vec4_rdivTuple<T,tuple>) .def("__rdiv__", &Vec4_rdivTuple<T,list>) .def("__rdiv__", &Vec4_rdivT<T>) .def("__rtruediv__", &Vec4_rdivTuple<T,tuple>) .def("__rtruediv__", &Vec4_rdivTuple<T,list>) .def("__rtruediv__", &Vec4_rdivT<T>) .def("__idiv__", &Vec4_idivObj<T>,return_internal_reference<>()) .def("__itruediv__", &Vec4_idivObj<T>,return_internal_reference<>()) .def("__xor__", &Vec4_dot<T>) .def(self == self) // NOSONAR - suppress SonarCloud bug report. .def(self != self) // NOSONAR - suppress SonarCloud bug report. .def("__add__", &Vec4_add<T>) .def("__add__", &Vec4_addV<T, int>) .def("__add__", &Vec4_addV<T, float>) .def("__add__", &Vec4_addV<T, double>) .def("__add__", &Vec4_addT<T>) .def("__add__", &Vec4_addTuple<T,tuple>) .def("__add__", &Vec4_addTuple<T,list>) .def("__radd__", &Vec4_addT<T>) .def("__radd__", &Vec4_addTuple<T,tuple>) .def("__radd__", &Vec4_addTuple<T,list>) .def("__radd__", &Vec4_add<T>) .def("__iadd__", &Vec4_iaddV<T, int>, return_internal_reference<>()) .def("__iadd__", &Vec4_iaddV<T, float>, return_internal_reference<>()) .def("__iadd__", &Vec4_iaddV<T, double>, return_internal_reference<>()) .def("__sub__", &Vec4_sub<T>) .def("__sub__", &Vec4_subV<T, int>) .def("__sub__", &Vec4_subV<T, float>) .def("__sub__", &Vec4_subV<T, double>) .def("__sub__", &Vec4_subT<T>) .def("__sub__", &Vec4_subTuple<T,tuple>) .def("__sub__", &Vec4_subTuple<T,list>) .def("__rsub__", &Vec4_rsubT<T>) .def("__rsub__", &Vec4_rsubTuple<T,tuple>) .def("__rsub__", &Vec4_rsubTuple<T,list>) .def("__isub__", &Vec4_isubV<T, int>, return_internal_reference<>()) .def("__isub__", &Vec4_isubV<T, float>, return_internal_reference<>()) .def("__isub__", &Vec4_isubV<T, double>, return_internal_reference<>()) .def("__mul__", &mult<T>) .def("__rmul__", &mult<T>) .def("__imul__", &Vec4_imulM44<T, float>, return_internal_reference<>()) .def("__imul__", &Vec4_imulM44<T, double>, return_internal_reference<>()) .def("__lt__", &lessThan<T>) .def("__gt__", &greaterThan<T>) .def("__le__", &lessThanEqual<T>) .def("__ge__", &greaterThanEqual<T>) .def("__eq__", &equal<T>) .def("__ne__", ¬equal<T>) //.def(self_ns::str(self)) .def("__str__",&Vec4_str<T>) .def("__repr__",&Vec4_repr<T>) ; register_Vec4_floatonly<T>(vec4_class); decoratecopy(vec4_class); //add_swizzle3_operators(v3f_class); return vec4_class; } } // namespace PyImath #endif // _PyImathVec4Impl_h_ PyImathRandom.h 0000644 00000001251 15125213144 0007426 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathRandom_h_ #define _PyImathRandom_h_ #include <Python.h> #include <boost/python.hpp> #include <ImathRandom.h> #include "PyImathExport.h" namespace PyImath { PYIMATH_EXPORT boost::python::class_<IMATH_NAMESPACE::Rand32> register_Rand32(); PYIMATH_EXPORT boost::python::class_<IMATH_NAMESPACE::Rand48> register_Rand48(); class PYIMATH_EXPORT Rand32 { public: static PyObject * wrap (const IMATH_NAMESPACE::Rand32 &r); }; class PYIMATH_EXPORT Rand48 { public: static PyObject * wrap (const IMATH_NAMESPACE::Rand48 &r); }; } #endif ImathFrustum.h 0000644 00000073123 15125213144 0007351 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // A viewing frustum class // #ifndef INCLUDED_IMATHFRUSTUM_H #define INCLUDED_IMATHFRUSTUM_H #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathFun.h" #include "ImathLine.h" #include "ImathMatrix.h" #include "ImathPlane.h" #include "ImathVec.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// /// Template class `Frustum<T>` /// /// The frustum is always located with the eye point at the origin /// facing down -Z. This makes the Frustum class compatable with /// OpenGL (or anything that assumes a camera looks down -Z, hence /// with a right-handed coordinate system) but not with RenderMan /// which assumes the camera looks down +Z. Additional functions are /// provided for conversion from and from various camera coordinate /// spaces. /// /// nearPlane/farPlane: near/far are keywords used by Microsoft's /// compiler, so we use nearPlane/farPlane instead to avoid /// issues. template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Frustum { public: /// @{ /// @name Constructors and Assignment /// /// Initialize with default values: /// near=0.1, far=1000.0, left=-1.0, right=1.0, top=1.0, bottom=-1.0, ortho=false IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Frustum() IMATH_NOEXCEPT; /// Copy constructor IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Frustum (const Frustum&) IMATH_NOEXCEPT; /// Initialize to specific values IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Frustum (T nearPlane, T farPlane, T left, T right, T top, T bottom, bool ortho = false) IMATH_NOEXCEPT; /// Initialize with fov and aspect IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Frustum (T nearPlane, T farPlane, T fovx, T fovy, T aspect) IMATH_NOEXCEPT; /// Destructor virtual ~Frustum() IMATH_NOEXCEPT; /// Component-wise assignment IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Frustum& operator= (const Frustum&) IMATH_NOEXCEPT; /// @} /// @{ /// @name Comparison /// Equality IMATH_HOSTDEVICE constexpr bool operator== (const Frustum<T>& src) const IMATH_NOEXCEPT; /// Inequality IMATH_HOSTDEVICE constexpr bool operator!= (const Frustum<T>& src) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Query /// Return true if the frustum is orthographic, false if perspective IMATH_HOSTDEVICE constexpr bool orthographic() const IMATH_NOEXCEPT { return _orthographic; } /// Return the near clipping plane IMATH_HOSTDEVICE constexpr T nearPlane() const IMATH_NOEXCEPT { return _nearPlane; } /// Return the near clipping plane IMATH_HOSTDEVICE constexpr T hither() const IMATH_NOEXCEPT { return _nearPlane; } /// Return the far clipping plane IMATH_HOSTDEVICE constexpr T farPlane() const IMATH_NOEXCEPT { return _farPlane; } /// Return the far clipping plane IMATH_HOSTDEVICE constexpr T yon() const IMATH_NOEXCEPT { return _farPlane; } /// Return the left of the frustum IMATH_HOSTDEVICE constexpr T left() const IMATH_NOEXCEPT { return _left; } /// Return the right of the frustum IMATH_HOSTDEVICE constexpr T right() const IMATH_NOEXCEPT { return _right; } /// Return the bottom of the frustum IMATH_HOSTDEVICE constexpr T bottom() const IMATH_NOEXCEPT { return _bottom; } /// Return the top of the frustum IMATH_HOSTDEVICE constexpr T top() const IMATH_NOEXCEPT { return _top; } /// Return the field of view in X IMATH_HOSTDEVICE constexpr T fovx() const IMATH_NOEXCEPT; /// Return the field of view in Y IMATH_HOSTDEVICE constexpr T fovy() const IMATH_NOEXCEPT; /// Return the aspect ratio IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T aspect() const IMATH_NOEXCEPT; /// Return the aspect ratio. Throw an exception if the aspect /// ratio is undefined. IMATH_CONSTEXPR14 T aspectExc() const; /// Return the project matrix that the frustum defines IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44<T> projectionMatrix() const IMATH_NOEXCEPT; /// Return the project matrix that the frustum defines. Throw an /// exception if the frustum is degenerate. IMATH_CONSTEXPR14 Matrix44<T> projectionMatrixExc() const; /// Return true if the frustum is degenerate. IMATH_HOSTDEVICE constexpr bool degenerate() const IMATH_NOEXCEPT; /// @} /// @{ /// @name Set Value /// Set functions change the entire state of the Frustum IMATH_HOSTDEVICE void set (T nearPlane, T farPlane, T left, T right, T top, T bottom, bool ortho = false) IMATH_NOEXCEPT; /// Set functions change the entire state of the Frustum using /// field of view and aspect ratio IMATH_HOSTDEVICE void set (T nearPlane, T farPlane, T fovx, T fovy, T aspect) IMATH_NOEXCEPT; /// Set functions change the entire state of the Frustum using /// field of view and aspect ratio. Throw an exception if `fovx` /// and/or `fovy` are invalid. void setExc (T nearPlane, T farPlane, T fovx, T fovy, T aspect); /// Set the near and far clipping planes IMATH_HOSTDEVICE void modifyNearAndFar (T nearPlane, T farPlane) IMATH_NOEXCEPT; /// Set the ortographic state IMATH_HOSTDEVICE void setOrthographic (bool) IMATH_NOEXCEPT; /// Set the planes in p to be the six bounding planes of the frustum, in /// the following order: top, right, bottom, left, near, far. /// Note that the planes have normals that point out of the frustum. IMATH_HOSTDEVICE void planes (Plane3<T> p[6]) const IMATH_NOEXCEPT; /// Set the planes in p to be the six bounding planes of the /// frustum, in the following order: top, right, bottom, left, /// near, far. Note that the planes have normals that point out /// of the frustum. Apply the given matrix to transform the /// frustum before setting the planes. IMATH_HOSTDEVICE void planes (Plane3<T> p[6], const Matrix44<T>& M) const IMATH_NOEXCEPT; /// Takes a rectangle in the screen space (i.e., -1 <= left <= right <= 1 /// and -1 <= bottom <= top <= 1) of this Frustum, and returns a new /// Frustum whose near clipping-plane window is that rectangle in local /// space. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 IMATH_HOSTDEVICE Frustum<T> window (T left, T right, T top, T bottom) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Utility Methods /// Project a point in screen spaced to 3d ray IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Line3<T> projectScreenToRay (const Vec2<T>&) const IMATH_NOEXCEPT; /// Project a 3D point into screen coordinates IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec2<T> projectPointToScreen (const Vec3<T>&) const IMATH_NOEXCEPT; /// Project a 3D point into screen coordinates. Throw an /// exception if the point cannot be projected. IMATH_CONSTEXPR14 Vec2<T> projectPointToScreenExc (const Vec3<T>&) const; /// Map a z value to its depth in the frustum. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T ZToDepth (long zval, long min, long max) const IMATH_NOEXCEPT; /// Map a z value to its depth in the frustum. IMATH_CONSTEXPR14 T ZToDepthExc (long zval, long min, long max) const; /// Map a normalized z value to its depth in the frustum. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T normalizedZToDepth (T zval) const IMATH_NOEXCEPT; /// Map a normalized z value to its depth in the frustum. Throw an /// exception on error. IMATH_CONSTEXPR14 T normalizedZToDepthExc (T zval) const; /// Map depth to z value. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 long DepthToZ (T depth, long zmin, long zmax) const IMATH_NOEXCEPT; /// Map depth to z value. Throw an exception on error. IMATH_CONSTEXPR14 long DepthToZExc (T depth, long zmin, long zmax) const; /// Compute worldRadius IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T worldRadius (const Vec3<T>& p, T radius) const IMATH_NOEXCEPT; /// Compute worldRadius. Throw an exception on error. IMATH_CONSTEXPR14 T worldRadiusExc (const Vec3<T>& p, T radius) const; /// Compute screen radius IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T screenRadius (const Vec3<T>& p, T radius) const IMATH_NOEXCEPT; /// Compute screen radius. Throw an exception on error. IMATH_CONSTEXPR14 T screenRadiusExc (const Vec3<T>& p, T radius) const; /// @} protected: /// Map point from screen space to local space IMATH_HOSTDEVICE constexpr Vec2<T> screenToLocal (const Vec2<T>&) const IMATH_NOEXCEPT; /// Map point from local space to screen space IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec2<T> localToScreen (const Vec2<T>&) const IMATH_NOEXCEPT; /// Map point from local space to screen space. Throw an exception /// on error. IMATH_CONSTEXPR14 Vec2<T> localToScreenExc (const Vec2<T>&) const; protected: /// @cond Doxygen_Suppress T _nearPlane; T _farPlane; T _left; T _right; T _top; T _bottom; bool _orthographic; /// @endcond }; template <class T> IMATH_CONSTEXPR14 inline Frustum<T>::Frustum() IMATH_NOEXCEPT { set (T (0.1), T (1000.0), T (-1.0), T (1.0), T (1.0), T (-1.0), false); } template <class T> IMATH_CONSTEXPR14 inline Frustum<T>::Frustum (const Frustum& f) IMATH_NOEXCEPT { *this = f; } template <class T> IMATH_CONSTEXPR14 inline Frustum<T>::Frustum (T n, T f, T l, T r, T t, T b, bool o) IMATH_NOEXCEPT { set (n, f, l, r, t, b, o); } template <class T> IMATH_CONSTEXPR14 inline Frustum<T>::Frustum (T nearPlane, T farPlane, T fovx, T fovy, T aspect) IMATH_NOEXCEPT { set (nearPlane, farPlane, fovx, fovy, aspect); } template <class T> Frustum<T>::~Frustum() IMATH_NOEXCEPT {} template <class T> IMATH_CONSTEXPR14 inline const Frustum<T>& Frustum<T>::operator= (const Frustum& f) IMATH_NOEXCEPT { _nearPlane = f._nearPlane; _farPlane = f._farPlane; _left = f._left; _right = f._right; _top = f._top; _bottom = f._bottom; _orthographic = f._orthographic; return *this; } template <class T> constexpr inline bool Frustum<T>::operator== (const Frustum<T>& src) const IMATH_NOEXCEPT { return _nearPlane == src._nearPlane && _farPlane == src._farPlane && _left == src._left && _right == src._right && _top == src._top && _bottom == src._bottom && _orthographic == src._orthographic; } template <class T> constexpr inline bool Frustum<T>::operator!= (const Frustum<T>& src) const IMATH_NOEXCEPT { return !operator== (src); } template <class T> inline void Frustum<T>::set (T n, T f, T l, T r, T t, T b, bool o) IMATH_NOEXCEPT { _nearPlane = n; _farPlane = f; _left = l; _right = r; _bottom = b; _top = t; _orthographic = o; } template <class T> inline void Frustum<T>::modifyNearAndFar (T n, T f) IMATH_NOEXCEPT { if (_orthographic) { _nearPlane = n; } else { Line3<T> lowerLeft (Vec3<T> (0, 0, 0), Vec3<T> (_left, _bottom, -_nearPlane)); Line3<T> upperRight (Vec3<T> (0, 0, 0), Vec3<T> (_right, _top, -_nearPlane)); Plane3<T> nearPlane (Vec3<T> (0, 0, -1), n); Vec3<T> ll = Vec3<T> (0, 0, 0); Vec3<T> ur = Vec3<T> (0, 0, 0); nearPlane.intersect (lowerLeft, ll); nearPlane.intersect (upperRight, ur); _left = ll.x; _right = ur.x; _top = ur.y; _bottom = ll.y; _nearPlane = n; _farPlane = f; } _farPlane = f; } template <class T> inline void Frustum<T>::setOrthographic (bool ortho) IMATH_NOEXCEPT { _orthographic = ortho; } template <class T> inline void Frustum<T>::setExc (T nearPlane, T farPlane, T fovx, T fovy, T aspect) { if (fovx != T (0) && fovy != T (0)) throw std::domain_error ("fovx and fovy cannot both be non-zero."); const T two = static_cast<T> (2); if (fovx != T (0)) { _right = nearPlane * std::tan (fovx / two); _left = -_right; _top = ((_right - _left) / aspect) / two; _bottom = -_top; } else { _top = nearPlane * std::tan (fovy / two); _bottom = -_top; _right = (_top - _bottom) * aspect / two; _left = -_right; } _nearPlane = nearPlane; _farPlane = farPlane; _orthographic = false; } template <class T> inline void Frustum<T>::set (T nearPlane, T farPlane, T fovx, T fovy, T aspect) IMATH_NOEXCEPT { const T two = static_cast<T> (2); if (fovx != T (0)) { _right = nearPlane * std::tan (fovx / two); _left = -_right; _top = ((_right - _left) / aspect) / two; _bottom = -_top; } else { _top = nearPlane * std::tan (fovy / two); _bottom = -_top; _right = (_top - _bottom) * aspect / two; _left = -_right; } _nearPlane = nearPlane; _farPlane = farPlane; _orthographic = false; } template <class T> constexpr inline T Frustum<T>::fovx() const IMATH_NOEXCEPT { return std::atan2 (_right, _nearPlane) - std::atan2 (_left, _nearPlane); } template <class T> constexpr inline T Frustum<T>::fovy() const IMATH_NOEXCEPT { return std::atan2 (_top, _nearPlane) - std::atan2 (_bottom, _nearPlane); } template <class T> IMATH_CONSTEXPR14 inline T Frustum<T>::aspectExc() const { T rightMinusLeft = _right - _left; T topMinusBottom = _top - _bottom; if (abs (topMinusBottom) < T (1) && abs (rightMinusLeft) > std::numeric_limits<T>::max() * abs (topMinusBottom)) { throw std::domain_error ("Bad viewing frustum: " "aspect ratio cannot be computed."); } return rightMinusLeft / topMinusBottom; } template <class T> IMATH_CONSTEXPR14 inline T Frustum<T>::aspect() const IMATH_NOEXCEPT { T rightMinusLeft = _right - _left; T topMinusBottom = _top - _bottom; return rightMinusLeft / topMinusBottom; } template <class T> IMATH_CONSTEXPR14 inline Matrix44<T> Frustum<T>::projectionMatrixExc() const { T rightPlusLeft = _right + _left; T rightMinusLeft = _right - _left; T topPlusBottom = _top + _bottom; T topMinusBottom = _top - _bottom; T farPlusNear = _farPlane + _nearPlane; T farMinusNear = _farPlane - _nearPlane; if ((abs (rightMinusLeft) < T (1) && abs (rightPlusLeft) > std::numeric_limits<T>::max() * abs (rightMinusLeft)) || (abs (topMinusBottom) < T (1) && abs (topPlusBottom) > std::numeric_limits<T>::max() * abs (topMinusBottom)) || (abs (farMinusNear) < 1 && abs (farPlusNear) > std::numeric_limits<T>::max() * abs (farMinusNear))) { throw std::domain_error ("Bad viewing frustum: " "projection matrix cannot be computed."); } if (_orthographic) { T tx = -rightPlusLeft / rightMinusLeft; T ty = -topPlusBottom / topMinusBottom; T tz = -farPlusNear / farMinusNear; if ((abs (rightMinusLeft) < T (1) && T (2) > std::numeric_limits<T>::max() * abs (rightMinusLeft)) || (abs (topMinusBottom) < T (1) && T (2) > std::numeric_limits<T>::max() * abs (topMinusBottom)) || (abs (farMinusNear) < T (1) && T (2) > std::numeric_limits<T>::max() * abs (farMinusNear))) { throw std::domain_error ("Bad viewing frustum: " "projection matrix cannot be computed."); } T A = T (2) / rightMinusLeft; T B = T (2) / topMinusBottom; T C = T (-2) / farMinusNear; return Matrix44<T> (A, 0, 0, 0, 0, B, 0, 0, 0, 0, C, 0, tx, ty, tz, 1.f); } else { T A = rightPlusLeft / rightMinusLeft; T B = topPlusBottom / topMinusBottom; T C = -farPlusNear / farMinusNear; T farTimesNear = T (-2) * _farPlane * _nearPlane; if (abs (farMinusNear) < T (1) && abs (farTimesNear) > std::numeric_limits<T>::max() * abs (farMinusNear)) { throw std::domain_error ("Bad viewing frustum: " "projection matrix cannot be computed."); } T D = farTimesNear / farMinusNear; T twoTimesNear = T (2) * _nearPlane; if ((abs (rightMinusLeft) < T (1) && abs (twoTimesNear) > std::numeric_limits<T>::max() * abs (rightMinusLeft)) || (abs (topMinusBottom) < T (1) && abs (twoTimesNear) > std::numeric_limits<T>::max() * abs (topMinusBottom))) { throw std::domain_error ("Bad viewing frustum: " "projection matrix cannot be computed."); } T E = twoTimesNear / rightMinusLeft; T F = twoTimesNear / topMinusBottom; return Matrix44<T> (E, 0, 0, 0, 0, F, 0, 0, A, B, C, -1, 0, 0, D, 0); } } template <class T> IMATH_CONSTEXPR14 inline Matrix44<T> Frustum<T>::projectionMatrix() const IMATH_NOEXCEPT { T rightPlusLeft = _right + _left; T rightMinusLeft = _right - _left; T topPlusBottom = _top + _bottom; T topMinusBottom = _top - _bottom; T farPlusNear = _farPlane + _nearPlane; T farMinusNear = _farPlane - _nearPlane; if (_orthographic) { T tx = -rightPlusLeft / rightMinusLeft; T ty = -topPlusBottom / topMinusBottom; T tz = -farPlusNear / farMinusNear; T A = T (2) / rightMinusLeft; T B = T (2) / topMinusBottom; T C = T (-2) / farMinusNear; return Matrix44<T> (A, 0, 0, 0, 0, B, 0, 0, 0, 0, C, 0, tx, ty, tz, 1.f); } else { T A = rightPlusLeft / rightMinusLeft; T B = topPlusBottom / topMinusBottom; T C = -farPlusNear / farMinusNear; T farTimesNear = T (-2) * _farPlane * _nearPlane; T D = farTimesNear / farMinusNear; T twoTimesNear = T (2) * _nearPlane; T E = twoTimesNear / rightMinusLeft; T F = twoTimesNear / topMinusBottom; return Matrix44<T> (E, 0, 0, 0, 0, F, 0, 0, A, B, C, -1, 0, 0, D, 0); } } template <class T> constexpr inline bool Frustum<T>::degenerate() const IMATH_NOEXCEPT { return (_nearPlane == _farPlane) || (_left == _right) || (_top == _bottom); } template <class T> IMATH_CONSTEXPR14 inline Frustum<T> Frustum<T>::window (T l, T r, T t, T b) const IMATH_NOEXCEPT { // move it to 0->1 space Vec2<T> bl = screenToLocal (Vec2<T> (l, b)); Vec2<T> tr = screenToLocal (Vec2<T> (r, t)); return Frustum<T> (_nearPlane, _farPlane, bl.x, tr.x, tr.y, bl.y, _orthographic); } template <class T> constexpr inline Vec2<T> Frustum<T>::screenToLocal (const Vec2<T>& s) const IMATH_NOEXCEPT { return Vec2<T> (_left + (_right - _left) * (1.f + s.x) / 2.f, _bottom + (_top - _bottom) * (1.f + s.y) / 2.f); } template <class T> IMATH_CONSTEXPR14 inline Vec2<T> Frustum<T>::localToScreenExc (const Vec2<T>& p) const { T leftPlusRight = _left - T (2) * p.x + _right; T leftMinusRight = _left - _right; T bottomPlusTop = _bottom - T (2) * p.y + _top; T bottomMinusTop = _bottom - _top; if ((abs (leftMinusRight) < T (1) && abs (leftPlusRight) > std::numeric_limits<T>::max() * abs (leftMinusRight)) || (abs (bottomMinusTop) < T (1) && abs (bottomPlusTop) > std::numeric_limits<T>::max() * abs (bottomMinusTop))) { throw std::domain_error ("Bad viewing frustum: " "local-to-screen transformation cannot be computed"); } return Vec2<T> (leftPlusRight / leftMinusRight, bottomPlusTop / bottomMinusTop); } template <class T> IMATH_CONSTEXPR14 inline Vec2<T> Frustum<T>::localToScreen (const Vec2<T>& p) const IMATH_NOEXCEPT { T leftPlusRight = _left - T (2) * p.x + _right; T leftMinusRight = _left - _right; T bottomPlusTop = _bottom - T (2) * p.y + _top; T bottomMinusTop = _bottom - _top; return Vec2<T> (leftPlusRight / leftMinusRight, bottomPlusTop / bottomMinusTop); } template <class T> IMATH_CONSTEXPR14 inline Line3<T> Frustum<T>::projectScreenToRay (const Vec2<T>& p) const IMATH_NOEXCEPT { Vec2<T> point = screenToLocal (p); if (orthographic()) return Line3<T> (Vec3<T> (point.x, point.y, 0.0), Vec3<T> (point.x, point.y, -1.0)); else return Line3<T> (Vec3<T> (0, 0, 0), Vec3<T> (point.x, point.y, -_nearPlane)); } template <class T> IMATH_CONSTEXPR14 Vec2<T> Frustum<T>::projectPointToScreenExc (const Vec3<T>& point) const { if (orthographic() || point.z == T (0)) return localToScreenExc (Vec2<T> (point.x, point.y)); else return localToScreenExc ( Vec2<T> (point.x * _nearPlane / -point.z, point.y * _nearPlane / -point.z)); } template <class T> IMATH_CONSTEXPR14 Vec2<T> Frustum<T>::projectPointToScreen (const Vec3<T>& point) const IMATH_NOEXCEPT { if (orthographic() || point.z == T (0)) return localToScreen (Vec2<T> (point.x, point.y)); else return localToScreen ( Vec2<T> (point.x * _nearPlane / -point.z, point.y * _nearPlane / -point.z)); } template <class T> IMATH_CONSTEXPR14 T Frustum<T>::ZToDepthExc (long zval, long zmin, long zmax) const { int zdiff = zmax - zmin; if (zdiff == 0) { throw std::domain_error ("Bad call to Frustum::ZToDepth: zmax == zmin"); } if (zval > zmax + 1) zval -= zdiff; T fzval = (T (zval) - T (zmin)) / T (zdiff); return normalizedZToDepthExc (fzval); } template <class T> IMATH_CONSTEXPR14 T Frustum<T>::ZToDepth (long zval, long zmin, long zmax) const IMATH_NOEXCEPT { int zdiff = zmax - zmin; if (zval > zmax + 1) zval -= zdiff; T fzval = (T (zval) - T (zmin)) / T (zdiff); return normalizedZToDepth (fzval); } template <class T> IMATH_CONSTEXPR14 T Frustum<T>::normalizedZToDepthExc (T zval) const { T Zp = zval * T (2) - T (1); if (_orthographic) { return -(Zp * (_farPlane - _nearPlane) + (_farPlane + _nearPlane)) / T (2); } else { T farTimesNear = 2 * _farPlane * _nearPlane; T farMinusNear = Zp * (_farPlane - _nearPlane) - _farPlane - _nearPlane; if (abs (farMinusNear) < 1 && abs (farTimesNear) > std::numeric_limits<T>::max() * abs (farMinusNear)) { throw std::domain_error ("Frustum::normalizedZToDepth cannot be computed: " "near and far clipping planes of the viewing frustum " "may be too close to each other"); } return farTimesNear / farMinusNear; } } template <class T> IMATH_CONSTEXPR14 T Frustum<T>::normalizedZToDepth (T zval) const IMATH_NOEXCEPT { T Zp = zval * T (2) - T (1); if (_orthographic) { return -(Zp * (_farPlane - _nearPlane) + (_farPlane + _nearPlane)) / T (2); } else { T farTimesNear = 2 * _farPlane * _nearPlane; T farMinusNear = Zp * (_farPlane - _nearPlane) - _farPlane - _nearPlane; return farTimesNear / farMinusNear; } } template <class T> IMATH_CONSTEXPR14 long Frustum<T>::DepthToZExc (T depth, long zmin, long zmax) const { long zdiff = zmax - zmin; T farMinusNear = _farPlane - _nearPlane; if (_orthographic) { T farPlusNear = T (2) * depth + _farPlane + _nearPlane; if (abs (farMinusNear) < T (1) && abs (farPlusNear) > std::numeric_limits<T>::max() * abs (farMinusNear)) { throw std::domain_error ("Bad viewing frustum: " "near and far clipping planes " "are too close to each other"); } T Zp = -farPlusNear / farMinusNear; return long (0.5 * (Zp + 1) * zdiff) + zmin; } else { // Perspective T farTimesNear = T (2) * _farPlane * _nearPlane; if (abs (depth) < T (1) && abs (farTimesNear) > std::numeric_limits<T>::max() * abs (depth)) { throw std::domain_error ("Bad call to DepthToZ function: " "value of `depth' is too small"); } T farPlusNear = farTimesNear / depth + _farPlane + _nearPlane; if (abs (farMinusNear) < T (1) && abs (farPlusNear) > std::numeric_limits<T>::max() * abs (farMinusNear)) { throw std::domain_error ("Bad viewing frustum: " "near and far clipping planes " "are too close to each other"); } T Zp = farPlusNear / farMinusNear; return long (0.5 * (Zp + 1) * zdiff) + zmin; } } template <class T> IMATH_CONSTEXPR14 long Frustum<T>::DepthToZ (T depth, long zmin, long zmax) const IMATH_NOEXCEPT { long zdiff = zmax - zmin; T farMinusNear = _farPlane - _nearPlane; if (_orthographic) { T farPlusNear = T (2) * depth + _farPlane + _nearPlane; T Zp = -farPlusNear / farMinusNear; return long (0.5 * (Zp + 1) * zdiff) + zmin; } else { // Perspective T farTimesNear = T (2) * _farPlane * _nearPlane; T farPlusNear = farTimesNear / depth + _farPlane + _nearPlane; T Zp = farPlusNear / farMinusNear; return long (0.5 * (Zp + 1) * zdiff) + zmin; } } template <class T> IMATH_CONSTEXPR14 T Frustum<T>::screenRadiusExc (const Vec3<T>& p, T radius) const { // Derivation: // Consider X-Z plane. // X coord of projection of p = xp = p.x * (-_nearPlane / p.z) // Let q be p + (radius, 0, 0). // X coord of projection of q = xq = (p.x - radius) * (-_nearPlane / p.z) // X coord of projection of segment from p to q = r = xp - xq // = radius * (-_nearPlane / p.z) // A similar analysis holds in the Y-Z plane. // So r is the quantity we want to return. if (abs (p.z) > T (1) || abs (-_nearPlane) < std::numeric_limits<T>::max() * abs (p.z)) { return radius * (-_nearPlane / p.z); } else { throw std::domain_error ("Bad call to Frustum::screenRadius: " "magnitude of `p' is too small"); } return radius * (-_nearPlane / p.z); } template <class T> IMATH_CONSTEXPR14 T Frustum<T>::screenRadius (const Vec3<T>& p, T radius) const IMATH_NOEXCEPT { // Derivation: // Consider X-Z plane. // X coord of projection of p = xp = p.x * (-_nearPlane / p.z) // Let q be p + (radius, 0, 0). // X coord of projection of q = xq = (p.x - radius) * (-_nearPlane / p.z) // X coord of projection of segment from p to q = r = xp - xq // = radius * (-_nearPlane / p.z) // A similar analysis holds in the Y-Z plane. // So r is the quantity we want to return. return radius * (-_nearPlane / p.z); } template <class T> IMATH_CONSTEXPR14 T Frustum<T>::worldRadiusExc (const Vec3<T>& p, T radius) const { if (abs (-_nearPlane) > T (1) || abs (p.z) < std::numeric_limits<T>::max() * abs (-_nearPlane)) { return radius * (p.z / -_nearPlane); } else { throw std::domain_error ("Bad viewing frustum: " "near clipping plane is too close to zero"); } } template <class T> IMATH_CONSTEXPR14 T Frustum<T>::worldRadius (const Vec3<T>& p, T radius) const IMATH_NOEXCEPT { return radius * (p.z / -_nearPlane); } template <class T> void Frustum<T>::planes (Plane3<T> p[6]) const IMATH_NOEXCEPT { // // Plane order: Top, Right, Bottom, Left, Near, Far. // Normals point outwards. // if (!_orthographic) { Vec3<T> a (_left, _bottom, -_nearPlane); Vec3<T> b (_left, _top, -_nearPlane); Vec3<T> c (_right, _top, -_nearPlane); Vec3<T> d (_right, _bottom, -_nearPlane); Vec3<T> o (0, 0, 0); p[0].set (o, c, b); p[1].set (o, d, c); p[2].set (o, a, d); p[3].set (o, b, a); } else { p[0].set (Vec3<T> (0, 1, 0), _top); p[1].set (Vec3<T> (1, 0, 0), _right); p[2].set (Vec3<T> (0, -1, 0), -_bottom); p[3].set (Vec3<T> (-1, 0, 0), -_left); } p[4].set (Vec3<T> (0, 0, 1), -_nearPlane); p[5].set (Vec3<T> (0, 0, -1), _farPlane); } template <class T> void Frustum<T>::planes (Plane3<T> p[6], const Matrix44<T>& M) const IMATH_NOEXCEPT { // // Plane order: Top, Right, Bottom, Left, Near, Far. // Normals point outwards. // Vec3<T> a = Vec3<T> (_left, _bottom, -_nearPlane) * M; Vec3<T> b = Vec3<T> (_left, _top, -_nearPlane) * M; Vec3<T> c = Vec3<T> (_right, _top, -_nearPlane) * M; Vec3<T> d = Vec3<T> (_right, _bottom, -_nearPlane) * M; if (!_orthographic) { double s = _farPlane / double (_nearPlane); T farLeft = (T) (s * _left); T farRight = (T) (s * _right); T farTop = (T) (s * _top); T farBottom = (T) (s * _bottom); Vec3<T> e = Vec3<T> (farLeft, farBottom, -_farPlane) * M; Vec3<T> f = Vec3<T> (farLeft, farTop, -_farPlane) * M; Vec3<T> g = Vec3<T> (farRight, farTop, -_farPlane) * M; Vec3<T> o = Vec3<T> (0, 0, 0) * M; p[0].set (o, c, b); p[1].set (o, d, c); p[2].set (o, a, d); p[3].set (o, b, a); p[4].set (a, d, c); p[5].set (e, f, g); } else { Vec3<T> e = Vec3<T> (_left, _bottom, -_farPlane) * M; Vec3<T> f = Vec3<T> (_left, _top, -_farPlane) * M; Vec3<T> g = Vec3<T> (_right, _top, -_farPlane) * M; Vec3<T> h = Vec3<T> (_right, _bottom, -_farPlane) * M; p[0].set (c, g, f); p[1].set (d, h, g); p[2].set (a, e, h); p[3].set (b, f, e); p[4].set (a, d, c); p[5].set (e, f, g); } } /// Frustum of type float typedef Frustum<float> Frustumf; /// Frustum of type double typedef Frustum<double> Frustumd; IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #if defined _WIN32 || defined _WIN64 # ifdef _redef_near # define near # endif # ifdef _redef_far # define far # endif #endif #endif // INCLUDED_IMATHFRUSTUM_H ImathRandom.h 0000644 00000014575 15125213144 0007132 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // Generators for uniformly distributed pseudo-random numbers and // functions that use those generators to generate numbers with // non-uniform distributions // // Note: class Rand48() calls erand48() and nrand48(), which are not // available on all operating systems. For compatibility we include // our own versions of erand48() and nrand48(). Our functions // have been reverse-engineered from the corresponding Unix/Linux // man page. // #ifndef INCLUDED_IMATHRANDOM_H #define INCLUDED_IMATHRANDOM_H #include "ImathExport.h" #include "ImathNamespace.h" #include <math.h> #include <stdlib.h> IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// Fast random-number generator that generates /// a uniformly distributed sequence with a period /// length of 2^32. class IMATH_EXPORT Rand32 { public: /// Constructor, given a seed IMATH_HOSTDEVICE Rand32 (unsigned long int seed = 0); /// Re-initialize with a given seed IMATH_HOSTDEVICE void init (unsigned long int seed); /// Get the next value in the sequence (range: [false, true]) IMATH_HOSTDEVICE bool nextb(); /// Get the next value in the sequence (range: [0 ... 0xffffffff]) IMATH_HOSTDEVICE unsigned long int nexti(); /// Get the next value in the sequence (range: [0 ... 1[) IMATH_HOSTDEVICE float nextf(); /// Get the next value in the sequence (range [rangeMin ... rangeMax[) IMATH_HOSTDEVICE float nextf (float rangeMin, float rangeMax); private: IMATH_HOSTDEVICE void next(); unsigned long int _state; }; /// Random-number generator based on the C Standard Library /// functions erand48(), nrand48() & company; generates a /// uniformly distributed sequence. class Rand48 { public: /// Constructor IMATH_HOSTDEVICE Rand48 (unsigned long int seed = 0); /// Re-initialize with a given seed IMATH_HOSTDEVICE void init (unsigned long int seed); /// Get the next value in the sequence (range: [false, true]) IMATH_HOSTDEVICE bool nextb(); /// Get the next value in the sequence (range: [0 ... 0x7fffffff]) IMATH_HOSTDEVICE long int nexti(); /// Get the next value in the sequence (range: [0 ... 1[) IMATH_HOSTDEVICE double nextf(); /// Get the next value in the sequence (range [rangeMin ... rangeMax[) IMATH_HOSTDEVICE double nextf (double rangeMin, double rangeMax); private: unsigned short int _state[3]; }; /// Return random points uniformly distributed in a sphere with /// radius 1 around the origin (distance from origin <= 1). template <class Vec, class Rand> IMATH_HOSTDEVICE Vec solidSphereRand (Rand& rand); /// Return random points uniformly distributed on the surface of /// a sphere with radius 1 around the origin. template <class Vec, class Rand> IMATH_HOSTDEVICE Vec hollowSphereRand (Rand& rand); /// Return random numbers with a normal (Gaussian) /// distribution with zero mean and unit variance. template <class Rand> IMATH_HOSTDEVICE float gaussRand (Rand& rand); /// Return random points whose distance from the origin /// has a normal (Gaussian) distribution with zero mean /// and unit variance. template <class Vec, class Rand> IMATH_HOSTDEVICE Vec gaussSphereRand (Rand& rand); //--------------------------------- // erand48(), nrand48() and friends //--------------------------------- /// @cond Doxygen_Suppress IMATH_HOSTDEVICE IMATH_EXPORT double erand48 (unsigned short state[3]); IMATH_HOSTDEVICE IMATH_EXPORT double drand48(); IMATH_HOSTDEVICE IMATH_EXPORT long int nrand48 (unsigned short state[3]); IMATH_HOSTDEVICE IMATH_EXPORT long int lrand48(); IMATH_HOSTDEVICE IMATH_EXPORT void srand48 (long int seed); /// @endcond //--------------- // Implementation //--------------- inline void Rand32::init (unsigned long int seed) { _state = (seed * 0xa5a573a5L) ^ 0x5a5a5a5aL; } inline Rand32::Rand32 (unsigned long int seed) { init (seed); } inline void Rand32::next() { _state = 1664525L * _state + 1013904223L; } inline bool Rand32::nextb() { next(); // Return the 31st (most significant) bit, by and-ing with 2 ^ 31. return !!(_state & 2147483648UL); } inline unsigned long int Rand32::nexti() { next(); return _state & 0xffffffff; } inline float Rand32::nextf (float rangeMin, float rangeMax) { float f = nextf(); return rangeMin * (1 - f) + rangeMax * f; } inline void Rand48::init (unsigned long int seed) { seed = (seed * 0xa5a573a5L) ^ 0x5a5a5a5aL; _state[0] = (unsigned short int) (seed & 0xFFFF); _state[1] = (unsigned short int) ((seed >> 16) & 0xFFFF); _state[2] = (unsigned short int) (seed & 0xFFFF); } inline Rand48::Rand48 (unsigned long int seed) { init (seed); } inline bool Rand48::nextb() { return nrand48 (_state) & 1; } inline long int Rand48::nexti() { return nrand48 (_state); } inline double Rand48::nextf() { return erand48 (_state); } inline double Rand48::nextf (double rangeMin, double rangeMax) { double f = nextf(); return rangeMin * (1 - f) + rangeMax * f; } template <class Vec, class Rand> Vec solidSphereRand (Rand& rand) { Vec v; do { for (unsigned int i = 0; i < Vec::dimensions(); i++) v[i] = (typename Vec::BaseType) rand.nextf (-1, 1); } while (v.length2() > 1); return v; } template <class Vec, class Rand> Vec hollowSphereRand (Rand& rand) { Vec v; typename Vec::BaseType length; do { for (unsigned int i = 0; i < Vec::dimensions(); i++) v[i] = (typename Vec::BaseType) rand.nextf (-1, 1); length = v.length(); } while (length > 1 || length == 0); return v / length; } template <class Rand> float gaussRand (Rand& rand) { float x; // Note: to avoid numerical problems with very small float y; // numbers, we make these variables singe-precision float length2; // floats, but later we call the double-precision log() // and sqrt() functions instead of logf() and sqrtf(). do { x = float (rand.nextf (-1, 1)); y = float (rand.nextf (-1, 1)); length2 = x * x + y * y; } while (length2 >= 1 || length2 == 0); return x * sqrt (-2 * log (double (length2)) / length2); } template <class Vec, class Rand> Vec gaussSphereRand (Rand& rand) { return hollowSphereRand<Vec> (rand) * gaussRand (rand); } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHRANDOM_H PyImathFrustum.h 0000644 00000004207 15125213144 0007657 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathFrustum_h_ #define _PyImathFrustum_h_ #include <Python.h> #include <boost/python.hpp> #include <ImathFrustum.h> #include <ImathFrustumTest.h> #include "PyImath.h" namespace PyImath { template <class T> boost::python::class_<IMATH_NAMESPACE::Frustum<T> > register_Frustum(); template <class T> boost::python::class_<IMATH_NAMESPACE::FrustumTest<T> > register_FrustumTest(); // // Other code in the Zeno code base assumes the existance of a class with the // same name as the Imath class, and with static functions wrap() and // convert() to produce a PyImath object from an Imath object and vice-versa, // respectively. The class Boost generates from the Imath class does not // have these properties, so we define a companion class here. // The template argument, T, is the element type (e.g.,float, double). template <class T> class F { public: static PyObject * wrap (const IMATH_NAMESPACE::Frustum<T> &f); static int convert (PyObject *p, IMATH_NAMESPACE::Frustum<T> *f); }; template <class T> PyObject * F<T>::wrap (const IMATH_NAMESPACE::Frustum<T> &f) { typename boost::python::return_by_value::apply < IMATH_NAMESPACE::Frustum<T> >::type converter; PyObject *p = converter (f); return p; } template <class T> int F<T>::convert (PyObject *p, IMATH_NAMESPACE::Frustum<T> *f) { boost::python::extract <IMATH_NAMESPACE::Frustumf> extractorEf (p); if (extractorEf.check()) { IMATH_NAMESPACE::Frustumf e = extractorEf(); f->set (T(e.nearPlane()), T(e.farPlane()), T(e.left()), T(e.right()), T(e.top()), T(e.bottom()), e.orthographic()); return 1; } boost::python::extract <IMATH_NAMESPACE::Frustumd> extractorEd (p); if (extractorEd.check()) { IMATH_NAMESPACE::Frustumd e = extractorEd(); f->set (T(e.nearPlane()), T(e.farPlane()), T(e.left()), T(e.right()), T(e.top()), T(e.bottom()), e.orthographic()); return 1; } return 0; } typedef F<float> Frustumf; typedef F<double> Frustumd; } #endif PyImathEuler.h 0000644 00000004465 15125213144 0007274 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathEuler_h_ #define _PyImathEuler_h_ #include <Python.h> #include <boost/python.hpp> #include <ImathEuler.h> #include <ImathVec.h> #include "PyImath.h" namespace PyImath { template <class T> boost::python::class_<IMATH_NAMESPACE::Euler<T>,boost::python::bases<IMATH_NAMESPACE::Vec3<T> > > register_Euler(); template <class T> boost::python::class_<PyImath::FixedArray<IMATH_NAMESPACE::Euler<T> > > register_EulerArray(); typedef FixedArray<IMATH_NAMESPACE::Eulerf> EulerfArray; typedef FixedArray<IMATH_NAMESPACE::Eulerd> EulerdArray; // // Other code in the Zeno code base assumes the existance of a class with the // same name as the Imath class, and with static functions wrap() and // convert() to produce a PyImath object from an Imath object and vice-versa, // respectively. The class Boost generates from the Imath class does not // have these properties, so we define a companion class here. // The template argument, T, is the element type for the axis vector // (e.g.,float, double). template <class T> class E { public: static PyObject * wrap (const IMATH_NAMESPACE::Euler<T> &e); static int convert (PyObject *p, IMATH_NAMESPACE::Euler<T> *v); }; template <class T> PyObject * E<T>::wrap (const IMATH_NAMESPACE::Euler<T> &e) { typename boost::python::return_by_value::apply < IMATH_NAMESPACE::Euler<T> >::type converter; PyObject *p = converter (e); return p; } template <class T> int E<T>::convert (PyObject *p, IMATH_NAMESPACE::Euler<T> *v) { boost::python::extract <IMATH_NAMESPACE::Eulerf> extractorEf (p); if (extractorEf.check()) { IMATH_NAMESPACE::Eulerf e = extractorEf(); v->x = T(e.x); v->y = T(e.y); v->z = T(e.z); v->setOrder (typename IMATH_NAMESPACE::Euler<T>::Order (e.order())); return 1; } boost::python::extract <IMATH_NAMESPACE::Eulerd> extractorEd (p); if (extractorEd.check()) { IMATH_NAMESPACE::Eulerd e = extractorEd(); v->x = T(e.x); v->y = T(e.y); v->z = T(e.z); v->setOrder (typename IMATH_NAMESPACE::Euler<T>::Order (e.order())); return 1; } return 0; } typedef E<float> Eulerf; typedef E<double> Eulerd; } #endif ImathVecAlgo.h 0000644 00000005015 15125213144 0007217 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // Algorithms applied to or in conjunction with points (Imath::Vec2 // and Imath::Vec3). // // The assumption made is that these functions are called much // less often than the basic point functions or these functions // require more support classes. // #ifndef INCLUDED_IMATHVECALGO_H #define INCLUDED_IMATHVECALGO_H #include "ImathNamespace.h" #include "ImathVec.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// @cond Doxygen_Suppress // // Note: doxygen doesn't understand these templates, so omit these // functions from the docs. // /// Find the projection of vector `t` onto vector `s` (`Vec2`, `Vec3`, `Vec4`) /// /// Only defined for floating-point types, e.g. `V2f`, `V3d`, etc. template <class Vec, IMATH_ENABLE_IF(!std::is_integral<typename Vec::BaseType>::value)> IMATH_CONSTEXPR14 inline Vec project (const Vec& s, const Vec& t) IMATH_NOEXCEPT { Vec sNormalized = s.normalized(); return sNormalized * (sNormalized ^ t); } /// Find a vector that is perpendicular to `s` and /// in the same plane as `s` and `t` (`Vec2`, `Vec3`, `Vec4`) /// /// Only defined for floating-point types, e.g. `V2f`, `V3d`, etc. template <class Vec, IMATH_ENABLE_IF(!std::is_integral<typename Vec::BaseType>::value)> constexpr inline Vec orthogonal (const Vec& s, const Vec& t) IMATH_NOEXCEPT { return t - project (s, t); } /// Find the direction of a ray `s` after reflection /// off a plane with normal `t` (`Vec2`, `Vec3`, `Vec4`) /// /// Only defined for floating-point types, e.g. `V2f`, `V3d`, etc. template <class Vec, IMATH_ENABLE_IF(!std::is_integral<typename Vec::BaseType>::value)> constexpr inline Vec reflect (const Vec& s, const Vec& t) IMATH_NOEXCEPT { return s - typename Vec::BaseType (2) * (s - project (t, s)); } /// @endcond /// Find the vertex of triangle `(v0, v1, v2)` that is closest to point `p` /// (`Vec2`, `Vec3`, `Vec4`) template <class Vec> IMATH_CONSTEXPR14 Vec closestVertex (const Vec& v0, const Vec& v1, const Vec& v2, const Vec& p) IMATH_NOEXCEPT { Vec nearest = v0; typename Vec::BaseType neardot = (v0 - p).length2(); typename Vec::BaseType tmp = (v1 - p).length2(); if (tmp < neardot) { neardot = tmp; nearest = v1; } tmp = (v2 - p).length2(); if (tmp < neardot) { neardot = tmp; nearest = v2; } return nearest; } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHVECALGO_H ImathNamespace.h 0000644 00000005750 15125213144 0007601 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // The Imath library namespace // // The purpose of this file is to make it possible to specify an // IMATH_INTERNAL_NAMESPACE as a preprocessor definition and have all of the // Imath symbols defined within that namespace rather than the standard // Imath namespace. Those symbols are made available to client code through // the IMATH_NAMESPACE in addition to the IMATH_INTERNAL_NAMESPACE. // // To ensure source code compatibility, the IMATH_NAMESPACE defaults to Imath // and then "using namespace IMATH_INTERNAL_NAMESPACE;" brings all of the // declarations from the IMATH_INTERNAL_NAMESPACE into the IMATH_NAMESPACE. // This means that client code can continue to use syntax like Imath::V3f, // but at link time it will resolve to a mangled symbol based on the // IMATH_INTERNAL_NAMESPACE. // // As an example, if one needed to build against a newer version of Imath and // have it run alongside an older version in the same application, it is now // possible to use an internal namespace to prevent collisions between the // older versions of Imath symbols and the newer ones. To do this, the // following could be defined at build time: // // IMATH_INTERNAL_NAMESPACE = Imath_v2 // // This means that declarations inside Imath headers look like this (after // the preprocessor has done its work): // // namespace Imath_v2 { // ... // class declarations // ... // } // // namespace Imath { // using namespace Imath_v2; // } // #ifndef INCLUDED_IMATHNAMESPACE_H #define INCLUDED_IMATHNAMESPACE_H /// @cond Doxygen_Suppress #include "ImathConfig.h" #ifndef IMATH_NAMESPACE # define IMATH_NAMESPACE Imath #endif #ifndef IMATH_INTERNAL_NAMESPACE # define IMATH_INTERNAL_NAMESPACE IMATH_NAMESPACE #endif #ifdef __cplusplus // // We need to be sure that we import the internal namespace into the public one. // To do this, we use the small bit of code below which initially defines // IMATH_INTERNAL_NAMESPACE (so it can be referenced) and then defines // IMATH_NAMESPACE and pulls the internal symbols into the public // namespace. // namespace IMATH_INTERNAL_NAMESPACE {} namespace IMATH_NAMESPACE { using namespace IMATH_INTERNAL_NAMESPACE; } // // There are identical pairs of HEADER/SOURCE ENTER/EXIT macros so that // future extension to the namespace mechanism is possible without changing // project source code. // #define IMATH_INTERNAL_NAMESPACE_HEADER_ENTER \ namespace IMATH_INTERNAL_NAMESPACE \ { #define IMATH_INTERNAL_NAMESPACE_HEADER_EXIT } #define IMATH_INTERNAL_NAMESPACE_SOURCE_ENTER \ namespace IMATH_INTERNAL_NAMESPACE \ { #define IMATH_INTERNAL_NAMESPACE_SOURCE_EXIT } #endif // __cplusplus /// @endcond #endif /* INCLUDED_IMATHNAMESPACE_H */ ImathPlatform.h 0000644 00000003630 15125213144 0007464 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // This file contains functions and constants which aren't // provided by the system libraries, compilers, or includes on // certain platforms. // #ifndef INCLUDED_IMATHPLATFORM_H #define INCLUDED_IMATHPLATFORM_H /// @cond Doxygen_Suppress #include <math.h> #include "ImathNamespace.h" #ifdef __cplusplus IMATH_INTERNAL_NAMESPACE_HEADER_ENTER // // Helpful macros for checking which C++ standard we are compiling with. // #if (__cplusplus >= 202002L) # define IMATH_CPLUSPLUS_VERSION 20 #elif (__cplusplus >= 201703L) # define IMATH_CPLUSPLUS_VERSION 17 #elif (__cplusplus >= 201402L) || (defined(_MSC_VER) && _MSC_VER >= 1914) # define IMATH_CPLUSPLUS_VERSION 14 #elif (__cplusplus >= 201103L) || (defined(_MSC_VER) && _MSC_VER >= 1900) # define IMATH_CPLUSPLUS_VERSION 11 #else # error "This version of Imath is meant to work only with C++11 and above" #endif // // Constexpr C++14 conditional definition // #if (IMATH_CPLUSPLUS_VERSION >= 14) #define IMATH_CONSTEXPR14 constexpr #else #define IMATH_CONSTEXPR14 /* can not be constexpr before c++14 */ #endif #endif // __cplusplus #ifndef M_PI # define M_PI 3.14159265358979323846 #endif #ifndef M_PI_2 # define M_PI_2 1.57079632679489661923 // pi/2 #endif //----------------------------------------------------------------------------- // // Some, but not all, C++ compilers support the C99 restrict // keyword or some variant of it, for example, __restrict. // //----------------------------------------------------------------------------- #if defined(__GNUC__) || defined(__clang__) || defined(_MSC_VER) || defined(__INTEL_COMPILER) # define IMATH_RESTRICT __restrict #else # define IMATH_RESTRICT #endif #ifdef __cplusplus IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // __cplusplus /// @endcond #endif // INCLUDED_IMATHPLATFORM_H PyImathFixedArray2D.h 0000644 00000112655 15125213144 0010445 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathFixedArray2D_h_ #define _PyImathFixedArray2D_h_ #include <boost/python.hpp> #include <boost/operators.hpp> #include <boost/shared_array.hpp> #include <boost/any.hpp> #include <iostream> #include <ImathVec.h> #include "PyImathFixedArray.h" #include "PyImathOperators.h" namespace PyImath { template <class T> class FixedArray2D { T * _ptr; IMATH_NAMESPACE::Vec2<size_t> _length; IMATH_NAMESPACE::Vec2<size_t> _stride; size_t _size; //flattened size of the array // this handle optionally stores a shared_array to allocated array data // so that everything is freed properly on exit. boost::any _handle; public: FixedArray2D(T *ptr, Py_ssize_t lengthX, Py_ssize_t lengthY, Py_ssize_t strideX = 1) : _ptr(ptr), _length(lengthX, lengthY), _stride(strideX, lengthX), _handle() { if (lengthX < 0 || lengthY < 0) throw std::domain_error("Fixed array 2d lengths must be non-negative"); if (strideX <= 0) throw std::domain_error("Fixed array 2d strides must be positive"); initializeSize(); //std::cout << "fixed array external construct" << std::endl; // nothing } FixedArray2D(T *ptr, Py_ssize_t lengthX, Py_ssize_t lengthY, Py_ssize_t strideX, Py_ssize_t strideY) : _ptr(ptr), _length(lengthX, lengthY), _stride(strideX, strideY), _handle() { if (lengthX < 0 || lengthY < 0) throw std::domain_error("Fixed array 2d lengths must be non-negative"); if (strideX <= 0 || strideY < 0) throw std::domain_error("Fixed array 2d strides must be positive"); initializeSize(); //std::cout << "fixed array external construct" << std::endl; // nothing } FixedArray2D(T *ptr, Py_ssize_t lengthX, Py_ssize_t lengthY, Py_ssize_t strideX, Py_ssize_t strideY, boost::any handle) : _ptr(ptr), _length(lengthX, lengthY), _stride(strideX, strideY), _handle(handle) { initializeSize(); //std::cout << "fixed array external construct with handle" << std::endl; // nothing } explicit FixedArray2D(Py_ssize_t lengthX, Py_ssize_t lengthY) : _ptr(0), _length(lengthX, lengthY), _stride(1, lengthX), _handle() { if (lengthX < 0 || lengthY < 0) throw std::domain_error("Fixed array 2d lengths must be non-negative"); initializeSize(); T tmp = FixedArrayDefaultValue<T>::value(); boost::shared_array<T> a(new T[_size]); for (size_t i=0; i<_size; ++i) a[i] = tmp; _handle = a; _ptr = a.get(); } explicit FixedArray2D(const IMATH_NAMESPACE::V2i& length) : _ptr(0), _length(length), _stride(1, length.x), _handle() { if (length.x < 0 || length.y < 0) throw std::domain_error("Fixed array 2d lengths must be non-negative"); initializeSize(); T tmp = FixedArrayDefaultValue<T>::value(); boost::shared_array<T> a(new T[_size]); for (size_t i=0; i<_size; ++i) a[i] = tmp; _handle = a; _ptr = a.get(); } FixedArray2D(const T &initialValue, Py_ssize_t lengthX, Py_ssize_t lengthY) : _ptr(0), _length(lengthX, lengthY), _stride(1, lengthX), _handle() { if (lengthX < 0 || lengthY < 0) throw std::domain_error("Fixed array 2d lengths must be non-negative"); initializeSize(); boost::shared_array<T> a(new T[_size]); for (size_t i=0; i<_size; ++i) a[i] = initialValue; _handle = a; _ptr = a.get(); } void initializeSize() { _size = _length.x*_length.y; } template <class S> explicit FixedArray2D(const FixedArray2D<S> &other) : _ptr(0), _length(other.len()), _stride(1, other.len().x), _handle() { initializeSize(); boost::shared_array<T> a(new T[_size]); size_t z = 0; for (size_t j = 0; j < _length.y; ++j) for (size_t i = 0; i < _length.x; ++i) a[z++] = T(other(i,j)); _handle = a; _ptr = a.get(); } FixedArray2D(const FixedArray2D &other) : _ptr(other._ptr), _length(other._length), _stride(other._stride), _size(other._size), _handle(other._handle) { //std::cout << "fixed array copy consturct construct" << std::endl; // nothing } const FixedArray2D & operator = (const FixedArray2D &other) { if (&other == this) return *this; //std::cout << "fixed array assign" << std::endl; _ptr = other._ptr; _length = other._length; _stride = other._stride; _handle = other._handle; _size = _length.x*_length.y; return *this; } ~FixedArray2D() { //std::cout << "fixed array delete" << std::endl; } const boost::any & handle() { return _handle; } size_t canonical_index(Py_ssize_t index, size_t length) const { if (index < 0) index += length; if ((size_t) index >= length || index < 0) { PyErr_SetString(PyExc_IndexError, "Index out of range"); boost::python::throw_error_already_set(); } return index; } void extract_slice_indices(PyObject *index, size_t length, size_t &start, size_t &end, Py_ssize_t &step, size_t &slicelength) const { if (PySlice_Check(index)) { #if PY_MAJOR_VERSION > 2 PyObject *slice = index; #else PySliceObject *slice = reinterpret_cast<PySliceObject *>(index); #endif Py_ssize_t s, e, sl; if (PySlice_GetIndicesEx(slice,length,&s,&e,&step,&sl) == -1) { boost::python::throw_error_already_set(); } if (s < 0 || e < 0 || sl < 0) { throw std::domain_error("Slice extraction produced invalid start, end, or length indices"); } start = s; end = e; slicelength = sl; } else if (PyInt_Check(index)) { size_t i = canonical_index(PyInt_AsSsize_t(index), length); 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; } // return_internal_reference doesn't seem to work with non-class types typedef typename boost::mpl::if_<boost::is_class<T>,T&,T>::type get_type; // get_type getitem(Py_ssize_t index) const { return _ptr[canonical_index(index)*_stride]; } //FIXME: const does not work here with at least IMATH_NAMESPACE::Color4, why it works for V3fArray? get_type getitem(Py_ssize_t i, Py_ssize_t j) //const { return (*this)(canonical_index(i, _length.x), canonical_index(j, _length.y)); } //FIXME: anyway to seperate 2:3,4:5 from 2,4? we'd like to return int for the second one, and also 1d array for 2, 4:5 or 2:3, 4 FixedArray2D getslice(PyObject *index) const { if (PyTuple_Check(index) && PyTuple_Size(index) == 2) { size_t startx=0, endx=0, slicelengthx=0; size_t starty=0, endy=0, slicelengthy=0; Py_ssize_t stepx=0; Py_ssize_t stepy=0; extract_slice_indices(PyTuple_GetItem(index, 0),_length.x,startx,endx,stepx,slicelengthx); extract_slice_indices(PyTuple_GetItem(index, 1),_length.y,starty,endy,stepy,slicelengthy); FixedArray2D f(slicelengthx, slicelengthy); for (size_t j=0,z=0; j<slicelengthy; j++) for (size_t i=0; i<slicelengthx; ++i) f._ptr[z++] = (*this)(startx+i*stepx, starty+j*stepy); return f; } else { PyErr_SetString(PyExc_TypeError, "Slice syntax error"); boost::python::throw_error_already_set(); } return FixedArray2D(0,0); } //FIXME: for 2D array, cannot reduce the size, or maybe returning 1D array? FixedArray2D getslice_mask(const FixedArray2D<int> &mask) const { // size_t len = match_dimension(mask); // size_t slicelength = 0; // for (size_t i=0; i<len; ++i) if (mask[i]) slicelength++; // FixedArray2D f(slicelength, _length.y); // for (size_t i=0,z=0; i<len; ++i) { // if (mask[i]) { // for (size_t j = 0; j < _length.y; j++) // f._ptr[z++] = (*this)(i,j); // } // } // return f; IMATH_NAMESPACE::Vec2<size_t> len = match_dimension(mask); FixedArray2D f(len); for (size_t j=0; j<len.y; j++) for (size_t i=0; i<len.x; i++) if (mask(i,j)) f(i,j) = (*this)(i,j); return f; } // void setitem(const boost::python::tuple& index, const T &data) // { // Py_ssize_t i = boost::python::extract<Py_ssize_t>(index[0]); // Py_ssize_t j = boost::python::extract<Py_ssize_t>(index[1]); // (*this)(i,j) = data; // } void setitem_scalar(PyObject *index, const T &data) { if (!PyTuple_Check(index) || PyTuple_Size(index) != 2) { PyErr_SetString(PyExc_TypeError, "Slice syntax error"); boost::python::throw_error_already_set(); } size_t startx=0, endx=0, slicelengthx=0; size_t starty=0, endy=0, slicelengthy=0; Py_ssize_t stepx=0; Py_ssize_t stepy=0; extract_slice_indices(PyTuple_GetItem(index, 0),_length.x,startx,endx,stepx,slicelengthx); extract_slice_indices(PyTuple_GetItem(index, 1),_length.y,starty,endy,stepy,slicelengthy); for (size_t j=0; j<slicelengthy; j++) for (size_t i=0; i<slicelengthx; ++i) (*this)(startx+i*stepx, starty+j*stepy) = data; } void setitem_scalar_mask(const FixedArray2D<int> &mask, const T &data) { IMATH_NAMESPACE::Vec2<size_t> len = match_dimension(mask); for (size_t j = 0; j < len.y; j++) for (size_t i=0; i<len.x; ++i) if (mask(i,j)) (*this)(i,j) = data; } void setitem_vector(PyObject *index, const FixedArray2D &data) { //TODO:sanity check size_t startx=0, endx=0, slicelengthx=0; size_t starty=0, endy=0, slicelengthy=0; Py_ssize_t stepx=0; Py_ssize_t stepy=0; extract_slice_indices(PyTuple_GetItem(index, 0),_length.x,startx,endx,stepx,slicelengthx); extract_slice_indices(PyTuple_GetItem(index, 1),_length.y,starty,endy,stepy,slicelengthy); // we have a valid range of indices if (data.len() != IMATH_NAMESPACE::Vec2<size_t>(slicelengthx, slicelengthy)) { PyErr_SetString(PyExc_IndexError, "Dimensions of source do not match destination"); boost::python::throw_error_already_set(); } for (size_t i=0; i<slicelengthx; ++i) for (size_t j=0; j<slicelengthy; ++j) (*this)(startx+i*stepx, starty+j*stepy) = data(i,j); } void setitem_vector_mask(const FixedArray2D<int> &mask, const FixedArray2D &data) { IMATH_NAMESPACE::Vec2<size_t> len = match_dimension(mask); if (data.len() == len) { for (size_t j = 0; j < len.y; j++) for (size_t i=0; i<len.x; ++i) if (mask(i,j)) (*this)(i,j) = data(i,j); } else { PyErr_SetString(PyExc_IndexError, "Dimensions of source data do not match destination"); boost::python::throw_error_already_set(); } } void setitem_array1d_mask(const FixedArray2D<int> &mask, const FixedArray<T> &data) { IMATH_NAMESPACE::Vec2<size_t> len = match_dimension(mask); if ((size_t) data.len() == len.x*len.y) { for (size_t j = 0, z = 0; j < len.y; j++) for (size_t i=0; i<len.x; ++i, ++z) if (mask(i,j)) (*this)(i,j) = data[z]; } else { size_t count = 0; for (size_t j = 0, z = 0; j < len.y; j++) for (size_t i=0; i<len.x; ++i, ++z) if (mask(i,j)) count++; if ((size_t) data.len() != count) { PyErr_SetString(PyExc_IndexError, "Dimensions of source data do not match destination either masked or unmasked"); boost::python::throw_error_already_set(); } for (size_t j = 0, z = 0; j < len.y; j++) for (size_t i=0; i<len.x; ++i) if (mask(i,j)) (*this)(i,j) = data[z++]; } } void setitem_array1d(PyObject *index, const FixedArray<T> &data) { //TODO:sanity check size_t startx=0, endx=0, slicelengthx=0; size_t starty=0, endy=0, slicelengthy=0; Py_ssize_t stepx=0; Py_ssize_t stepy=0; extract_slice_indices(PyTuple_GetItem(index, 0),_length.x,startx,endx,stepx,slicelengthx); extract_slice_indices(PyTuple_GetItem(index, 1),_length.y,starty,endy,stepy,slicelengthy); // we have a valid range of indices if ((size_t) data.len() != slicelengthx*slicelengthy) { PyErr_SetString(PyExc_IndexError, "Dimensions of source data do not match destination"); boost::python::throw_error_already_set(); } for (size_t j=0, z=0; j<slicelengthy; ++j) for (size_t i=0; i<slicelengthx; ++i, ++z) (*this)(startx+i*stepx, starty+j*stepy) = data[z]; } IMATH_NAMESPACE::Vec2<size_t> len() const { return _length; } IMATH_NAMESPACE::Vec2<size_t> stride() const { return _stride; } T & operator () (size_t i, size_t j) { return _ptr[_stride.x*(j*_stride.y + i)]; } const T & operator () (size_t i, size_t j) const { return _ptr[_stride.x*(j*_stride.y + i)]; } size_t totalLen() const { return _size; } boost::python::tuple size() const { return boost::python::make_tuple(_length.x, _length.y); } static boost::python::class_<FixedArray2D<T> > register_(const char *name, const char *doc) { // a little tricky, but here we go - class types return internal references // but fundemental types just get copied. this typedef sets up the appropriate // call policy for each type. typedef typename boost::mpl::if_< boost::is_class<T>, boost::python::return_internal_reference<>, boost::python::default_call_policies>::type call_policy; boost::python::class_<FixedArray2D<T> > c(name,doc, boost::python::init<size_t, size_t>( "construct an array of the specified length initialized to the default value for the type")); c .def(boost::python::init<const FixedArray2D<T> &>("construct an array with the same values as the given array")) .def(boost::python::init<const T &,size_t,size_t>("construct an array of the specified length initialized to the specified default value")) .def("__getitem__", &FixedArray2D<T>::getslice) .def("__getitem__", &FixedArray2D<T>::getslice_mask) // .def("__getitem__", &FixedArray2D<T>::getitem, call_policy()) .def("item", &FixedArray2D<T>::getitem, call_policy()) // .def("__setitem__", &FixedArray2D<T>::setitem) .def("__setitem__", &FixedArray2D<T>::setitem_scalar) .def("__setitem__", &FixedArray2D<T>::setitem_scalar_mask) .def("__setitem__", &FixedArray2D<T>::setitem_vector) .def("__setitem__", &FixedArray2D<T>::setitem_vector_mask) .def("__setitem__", &FixedArray2D<T>::setitem_array1d) .def("__setitem__", &FixedArray2D<T>::setitem_array1d_mask) .def("__len__",&FixedArray2D<T>::totalLen) .def("size",&FixedArray2D<T>::size) .def("ifelse",&FixedArray2D<T>::ifelse_scalar) .def("ifelse",&FixedArray2D<T>::ifelse_vector) ; return c; } // template <class T2> // size_t match_dimension(const FixedArray<T2> &a1) const // { // if (_length.x != a1.len()) { // PyErr_SetString(PyExc_IndexError, "Dimensions of source do not match destination"); // boost::python::throw_error_already_set(); // } // return _length.x; // } template <class T2> IMATH_NAMESPACE::Vec2<size_t> match_dimension(const FixedArray2D<T2> &a1) const { if (len() != a1.len()) { PyErr_SetString(PyExc_IndexError, "Dimensions of source do not match destination"); boost::python::throw_error_already_set(); } return len(); } FixedArray2D<T> ifelse_vector(const FixedArray2D<int> &choice, const FixedArray2D<T> &other) { IMATH_NAMESPACE::Vec2<size_t> len = match_dimension(choice); match_dimension(other); FixedArray2D<T> tmp(len); // should use default construction but V3f doens't initialize for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) tmp(i,j) = choice(i,j) ? (*this)(i,j) : other(i,j); return tmp; } FixedArray2D<T> ifelse_scalar(const FixedArray2D<int> &choice, const T &other) { IMATH_NAMESPACE::Vec2<size_t> len = match_dimension(choice); FixedArray2D<T> tmp(len); // should use default construction but V3f doens't initialize for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) tmp(i,j) = choice(i,j) ? (*this)(i,j) : other; return tmp; } }; // unary operation application template <template <class,class> class Op, class T1, class Ret> FixedArray2D<Ret> apply_array2d_unary_op(const FixedArray2D<T1> &a1) { IMATH_NAMESPACE::Vec2<size_t> len = a1.len(); FixedArray2D<Ret> retval(len.x,len.y); for (size_t j=0; j<len.y; ++j) { for (size_t i=0;i<len.x;++i) { retval(i,j) = Op<T1,Ret>::apply(a1(i,j)); } } return retval; } // binary operation application template <template <class,class,class> class Op, class T1, class T2, class Ret> FixedArray2D<Ret> apply_array2d_array2d_binary_op(const FixedArray2D<T1> &a1, const FixedArray2D<T2> &a2) { IMATH_NAMESPACE::Vec2<size_t> len = a1.match_dimension(a2); FixedArray2D<Ret> retval(len.x,len.y); for (size_t j=0; j<len.y; ++j) { for (size_t i=0;i<len.x;++i) { retval(i,j) = Op<T1,T2,Ret>::apply(a1(i,j),a2(i,j)); } } return retval; } template <template <class,class,class> class Op, class T1, class T2, class Ret> FixedArray2D<Ret> apply_array2d_scalar_binary_op(const FixedArray2D<T1> &a1, const T2 &a2) { IMATH_NAMESPACE::Vec2<size_t> len = a1.len(); FixedArray2D<Ret> retval(len.x,len.y); for (size_t j=0; j<len.y; ++j) { for (size_t i=0;i<len.x;++i) { retval(i,j) = Op<T1,T2,Ret>::apply(a1(i,j),a2); } } return retval; } template <template <class,class,class> class Op, class T1, class T2, class Ret> FixedArray2D<Ret> apply_array2d_scalar_binary_rop(const FixedArray2D<T1> &a1, const T2 &a2) { IMATH_NAMESPACE::Vec2<size_t> len = a1.len(); FixedArray2D<Ret> retval(len.x,len.y); for (size_t j=0; j<len.y; ++j) { for (size_t i=0;i<len.x;++i) { retval(i,j) = Op<T2,T1,Ret>::apply(a2,a1(i,j)); } } return retval; } // in-place binary operation application template <template <class,class> class Op, class T1, class T2> FixedArray2D<T1> & apply_array2d_array2d_ibinary_op(FixedArray2D<T1> &a1, const FixedArray2D<T2> &a2) { IMATH_NAMESPACE::Vec2<size_t> len = a1.match_dimension(a2); for (size_t j=0; j<len.y; ++j) { for (size_t i=0;i<len.x;++i) { Op<T1,T2>::apply(a1(i,j),a2(i,j)); } } return a1; } // in-place binary operation application template <template <class,class> class Op, class T1, class T2> FixedArray2D<T1> & apply_array2d_scalar_ibinary_op(FixedArray2D<T1> &a1, const T2 &a2) { IMATH_NAMESPACE::Vec2<size_t> len = a1.len(); for (size_t j=0; j<len.y; ++j) { for (size_t i=0;i<len.x;++i) { Op<T1,T2>::apply(a1(i,j),a2); } } return a1; } // PyObject* PyNumber_Add( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> operator + (const FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_binary_op<op_add,T,T,T>(a0,a1); } template <class T> static FixedArray2D<T> operator + (const FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_binary_op<op_add,T,T,T>(a0,v1); } template <class T> static FixedArray2D<T> operator + (const T &v1, const FixedArray2D<T> &a0) { return a0+v1; } // PyObject* PyNumber_Subtract( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> operator - (const FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_binary_op<op_sub,T,T,T>(a0,a1); } template <class T> static FixedArray2D<T> operator - (const FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_binary_op<op_sub,T,T,T>(a0,v1); } template <class T> static FixedArray2D<T> operator - (const T &v1, const FixedArray2D<T> &a0) { return apply_array2d_scalar_binary_op<op_rsub,T,T,T>(a0,v1); } // PyObject* PyNumber_Multiply( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> operator * (const FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_binary_op<op_mul,T,T,T>(a0,a1); } template <class T> static FixedArray2D<T> operator * (const FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_binary_op<op_mul,T,T,T>(a0,v1); } template <class T> static FixedArray2D<T> operator * (const T &v1, const FixedArray2D<T> &a0) { return a0*v1; } // PyObject* PyNumber_Divide( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> operator / (const FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_binary_op<op_div,T,T,T>(a0,a1); } template <class T> static FixedArray2D<T> operator / (const FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_binary_op<op_div,T,T,T>(a0,v1); } // no reversed scalar/array2d 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 FixedArray2D<T> operator % (const FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_binary_op<op_mod,T,T,T>(a0,a1); } template <class T> static FixedArray2D<T> operator % (const FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_binary_op<op_mod,T,T,T>(a0,v1); } // no reversed scalar%array2d remainder - no meaning // PyObject* PyNumber_Divmod( PyObject *o1, PyObject *o2) // PyObject* PyNumber_Power( PyObject *o1, PyObject *o2, PyObject *o3) template <class T> static FixedArray2D<T> pow_array2d_array2d (const FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_binary_op<op_pow,T,T,T>(a0,a1); } template <class T> static FixedArray2D<T> pow_array2d_scalar (const FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_binary_op<op_pow,T,T,T>(a0,v1); } // no reversed scalar/array2d pow - no meaning // PyObject* PyNumber_Negative( PyObject *o) template <class T> static FixedArray2D<T> operator - (const FixedArray2D<T> &a0) { return apply_array2d_unary_op<op_neg,T,T>(a0); } // PyObject* PyNumber_Positive( PyObject *o) // PyObject* PyNumber_Absolute( PyObject *o) template <class T> static FixedArray2D<T> abs (const FixedArray2D<T> &a0) { return apply_array2d_unary_op<op_abs,T,T>(a0); } // PyObject* PyNumber_Invert( PyObject *o) template <class T> static FixedArray2D<T> operator ~ (const FixedArray2D<T> &a0) { return apply_array2d_unary_op<op_inverse,T,T>(a0); } // PyObject* PyNumber_Lshift( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> operator << (const FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_binary_op<op_lshift,T,T,T>(a0,a1); } template <class T> static FixedArray2D<T> operator << (const FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_binary_op<op_lshift,T,T,T>(a0,v1); } // no reversed // PyObject* PyNumber_Rshift( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> operator >> (const FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_binary_op<op_rshift,T,T,T>(a0,a1); } template <class T> static FixedArray2D<T> operator >> (const FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_binary_op<op_rshift,T,T,T>(a0,v1); } // no reversed // PyObject* PyNumber_And( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> operator & (const FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_binary_op<op_bitand,T,T,T>(a0,a1); } template <class T> static FixedArray2D<T> operator & (const FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_binary_op<op_bitand,T,T,T>(a0,v1); } template <class T> static FixedArray2D<T> operator & (const T &v1, const FixedArray2D<T> &a0) { return a0&v1; } // PyObject* PyNumber_Xor( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> operator ^ (const FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_binary_op<op_xor,T,T,T>(a0,a1); } template <class T> static FixedArray2D<T> operator ^ (const FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_binary_op<op_xor,T,T,T>(a0,v1); } template <class T> static FixedArray2D<T> operator ^ (const T &v1, const FixedArray2D<T> &a0) { return a0^v1; } // PyObject* PyNumber_Or( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> operator | (const FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_binary_op<op_bitor,T,T,T>(a0,a1); } template <class T> static FixedArray2D<T> operator | (const FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_binary_op<op_bitor,T,T,T>(a0,v1); } template <class T> static FixedArray2D<T> operator | (const T &v1, const FixedArray2D<T> &a0) { return a0|v1; } // PyObject* PyNumber_InPlaceAdd( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> & operator += (FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_ibinary_op<op_iadd,T,T>(a0,a1); } template <class T> static FixedArray2D<T> & operator += (FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_ibinary_op<op_iadd,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceSubtract( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> & operator -= (FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_ibinary_op<op_isub,T,T>(a0,a1); } template <class T> static FixedArray2D<T> & operator -= (FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_ibinary_op<op_isub,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceMultiply( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> & operator *= (FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_ibinary_op<op_imul,T,T>(a0,a1); } template <class T> static FixedArray2D<T> & operator *= (FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_ibinary_op<op_imul,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceDivide( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> & operator /= (FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_ibinary_op<op_idiv,T,T>(a0,a1); } template <class T> static FixedArray2D<T> & operator /= (FixedArray2D<T> &a0, const T &v1) { return apply_array2d_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 FixedArray2D<T> & operator %= (FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_ibinary_op<op_imod,T,T>(a0,a1); } template <class T> static FixedArray2D<T> & operator %= (FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_ibinary_op<op_imod,T,T>(a0,v1); } // PyObject* PyNumber_InPlacePower( PyObject *o1, PyObject *o2, PyObject *o3) template <class T> static FixedArray2D<T> & ipow_array2d_array2d (FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_ibinary_op<op_ipow,T,T>(a0,a1); } template <class T> static FixedArray2D<T> & ipow_array2d_scalar (FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_ibinary_op<op_ipow,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceLshift( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> & operator <<= (FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_ibinary_op<op_ilshift,T,T>(a0,a1); } template <class T> static FixedArray2D<T> & operator <<= (FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_ibinary_op<op_ilshift,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceRshift( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> & operator >>= (FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_ibinary_op<op_irshift,T,T>(a0,a1); } template <class T> static FixedArray2D<T> & operator >>= (FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_ibinary_op<op_irshift,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceAnd( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> & operator &= (FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_ibinary_op<op_ibitand,T,T>(a0,a1); } template <class T> static FixedArray2D<T> & operator &= (FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_ibinary_op<op_ibitand,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceXor( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> & operator ^= (FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_ibinary_op<op_ixor,T,T>(a0,a1); } template <class T> static FixedArray2D<T> & operator ^= (FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_ibinary_op<op_ixor,T,T>(a0,v1); } // PyObject* PyNumber_InPlaceOr( PyObject *o1, PyObject *o2) template <class T> static FixedArray2D<T> & operator |= (FixedArray2D<T> &a0, const FixedArray2D<T> &a1) { return apply_array2d_array2d_ibinary_op<op_ibitor,T,T>(a0,a1); } template <class T> static FixedArray2D<T> & operator |= (FixedArray2D<T> &a0, const T &v1) { return apply_array2d_scalar_ibinary_op<op_ibitor,T,T>(a0,v1); } template <class T> static void add_arithmetic_math_functions(boost::python::class_<FixedArray2D<T> > &c) { using namespace boost::python; c .def("__add__",&apply_array2d_array2d_binary_op<op_add,T,T,T>) .def("__add__",&apply_array2d_scalar_binary_op<op_add,T,T,T>) .def("__radd__",&apply_array2d_scalar_binary_rop<op_add,T,T,T>) .def("__sub__",&apply_array2d_array2d_binary_op<op_sub,T,T,T>) .def("__sub__",&apply_array2d_scalar_binary_op<op_sub,T,T,T>) .def("__rsub__",&apply_array2d_scalar_binary_op<op_rsub,T,T,T>) .def("__mul__",&apply_array2d_array2d_binary_op<op_mul,T,T,T>) .def("__mul__",&apply_array2d_scalar_binary_op<op_mul,T,T,T>) .def("__rmul__",&apply_array2d_scalar_binary_rop<op_mul,T,T,T>) .def("__div__",&apply_array2d_array2d_binary_op<op_div,T,T,T>) .def("__div__",&apply_array2d_scalar_binary_op<op_div,T,T,T>) .def("__truediv__",&apply_array2d_array2d_binary_op<op_div,T,T,T>) .def("__truediv__",&apply_array2d_scalar_binary_op<op_div,T,T,T>) .def("__neg__",&apply_array2d_unary_op<op_neg,T,T>) .def("__iadd__",&apply_array2d_array2d_ibinary_op<op_iadd,T,T>,return_internal_reference<>()) .def("__iadd__",&apply_array2d_scalar_ibinary_op<op_iadd,T,T>,return_internal_reference<>()) .def("__isub__",&apply_array2d_array2d_ibinary_op<op_isub,T,T>,return_internal_reference<>()) .def("__isub__",&apply_array2d_scalar_ibinary_op<op_isub,T,T>,return_internal_reference<>()) .def("__imul__",&apply_array2d_array2d_ibinary_op<op_imul,T,T>,return_internal_reference<>()) .def("__imul__",&apply_array2d_scalar_ibinary_op<op_imul,T,T>,return_internal_reference<>()) .def("__idiv__",&apply_array2d_array2d_ibinary_op<op_idiv,T,T>,return_internal_reference<>()) .def("__idiv__",&apply_array2d_scalar_ibinary_op<op_idiv,T,T>,return_internal_reference<>()) .def("__itruediv__",&apply_array2d_array2d_ibinary_op<op_idiv,T,T>,return_internal_reference<>()) .def("__itruediv__",&apply_array2d_scalar_ibinary_op<op_idiv,T,T>,return_internal_reference<>()) ; } template <class T> static void add_pow_math_functions(boost::python::class_<FixedArray2D<T> > &c) { using namespace boost::python; c .def("__pow__",&apply_array2d_array2d_binary_op<op_pow,T,T,T>) .def("__pow__",&apply_array2d_scalar_binary_op<op_pow,T,T,T>) .def("__rpow__",&apply_array2d_scalar_binary_rop<op_rpow,T,T,T>) .def("__ipow__",&apply_array2d_array2d_ibinary_op<op_ipow,T,T>,return_internal_reference<>()) .def("__ipow__",&apply_array2d_scalar_ibinary_op<op_ipow,T,T>,return_internal_reference<>()) ; } template <class T> static void add_mod_math_functions(boost::python::class_<FixedArray2D<T> > &c) { using namespace boost::python; c .def("__mod__",&apply_array2d_array2d_binary_op<op_mod,T,T,T>) .def("__mod__",&apply_array2d_scalar_binary_op<op_mod,T,T,T>) .def("__imod__",&apply_array2d_array2d_ibinary_op<op_imod,T,T>,return_internal_reference<>()) .def("__imod__",&apply_array2d_scalar_ibinary_op<op_imod,T,T>,return_internal_reference<>()) ; } template <class T> static void add_shift_math_functions(boost::python::class_<FixedArray2D<T> > &c) { using namespace boost::python; c .def("__lshift__",&apply_array2d_array2d_binary_op<op_lshift,T,T,T>) .def("__lshift__",&apply_array2d_scalar_binary_op<op_lshift,T,T,T>) .def("__ilshift__",&apply_array2d_array2d_ibinary_op<op_ilshift,T,T>,return_internal_reference<>()) .def("__ilshift__",&apply_array2d_scalar_ibinary_op<op_ilshift,T,T>,return_internal_reference<>()) .def("__rshift__",&apply_array2d_array2d_binary_op<op_rshift,T,T,T>) .def("__rshift__",&apply_array2d_scalar_binary_op<op_rshift,T,T,T>) .def("__irshift__",&apply_array2d_array2d_ibinary_op<op_irshift,T,T>,return_internal_reference<>()) .def("__irshift__",&apply_array2d_scalar_ibinary_op<op_irshift,T,T>,return_internal_reference<>()) ; } template <class T> static void add_bitwise_math_functions(boost::python::class_<FixedArray2D<T> > &c) { using namespace boost::python; c .def("__and__",&apply_array2d_array2d_binary_op<op_bitand,T,T,T>) .def("__and__",&apply_array2d_scalar_binary_op<op_bitand,T,T,T>) .def("__iand__",&apply_array2d_array2d_ibinary_op<op_ibitand,T,T>,return_internal_reference<>()) .def("__iand__",&apply_array2d_scalar_ibinary_op<op_ibitand,T,T>,return_internal_reference<>()) .def("__or__",&apply_array2d_array2d_binary_op<op_bitor,T,T,T>) .def("__or__",&apply_array2d_scalar_binary_op<op_bitor,T,T,T>) .def("__ior__",&apply_array2d_array2d_ibinary_op<op_ibitor,T,T>,return_internal_reference<>()) .def("__ior__",&apply_array2d_scalar_ibinary_op<op_ibitor,T,T>,return_internal_reference<>()) .def("__xor__",&apply_array2d_array2d_binary_op<op_xor,T,T,T>) .def("__xor__",&apply_array2d_scalar_binary_op<op_xor,T,T,T>) .def("__ixor__",&apply_array2d_array2d_ibinary_op<op_ixor,T,T>,return_internal_reference<>()) .def("__ixor__",&apply_array2d_scalar_ibinary_op<op_ixor,T,T>,return_internal_reference<>()) ; } template <class T> static void add_comparison_functions(boost::python::class_<FixedArray2D<T> > &c) { using namespace boost::python; c .def("__eq__",&apply_array2d_array2d_binary_op<op_eq,T,T,int>) .def("__eq__",&apply_array2d_scalar_binary_op<op_eq,T,T,int>) .def("__ne__",&apply_array2d_array2d_binary_op<op_ne,T,T,int>) .def("__ne__",&apply_array2d_scalar_binary_op<op_ne,T,T,int>) ; } template <class T> static void add_ordered_comparison_functions(boost::python::class_<FixedArray2D<T> > &c) { using namespace boost::python; c .def("__lt__",&apply_array2d_array2d_binary_op<op_lt,T,T,int>) .def("__lt__",&apply_array2d_scalar_binary_op<op_lt,T,T,int>) .def("__gt__",&apply_array2d_array2d_binary_op<op_gt,T,T,int>) .def("__gt__",&apply_array2d_scalar_binary_op<op_gt,T,T,int>) .def("__le__",&apply_array2d_array2d_binary_op<op_le,T,T,int>) .def("__le__",&apply_array2d_scalar_binary_op<op_le,T,T,int>) .def("__ge__",&apply_array2d_array2d_binary_op<op_ge,T,T,int>) .def("__ge__",&apply_array2d_scalar_binary_op<op_ge,T,T,int>) ; } template <class S,class T> static void add_explicit_construction_from_type(boost::python::class_<FixedArray2D<T> > &c) { using namespace boost::python; c.def(boost::python::init<FixedArray2D<S> >("copy contents of other array into this one")); } } #endif ImathColor.h 0000644 00000042625 15125213144 0006765 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // 3-channel and 4-channel color representations // #ifndef INCLUDED_IMATHCOLOR_H #define INCLUDED_IMATHCOLOR_H #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathVec.h" #include "half.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// /// 3-channel color class that inherits from Vec3. /// /// This class does not impose interpretation on the channels, which /// can represent either rgb or hsv color values. /// /// Note: because Color3 inherits from Vec3, its member fields are /// called `x`, `y`, and `z`. template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Color3 : public Vec3<T> { public: /// @{ /// @name Constructors and Assignemt /// No initialization by default IMATH_HOSTDEVICE Color3() IMATH_NOEXCEPT; /// Initialize to (a a a) IMATH_HOSTDEVICE constexpr explicit Color3 (T a) IMATH_NOEXCEPT; /// Initialize to (a b c) IMATH_HOSTDEVICE constexpr Color3 (T a, T b, T c) IMATH_NOEXCEPT; /// Construct from Color3 IMATH_HOSTDEVICE constexpr Color3 (const Color3& c) IMATH_NOEXCEPT; /// Construct from Vec3 template <class S> IMATH_HOSTDEVICE constexpr Color3 (const Vec3<S>& v) IMATH_NOEXCEPT; /// Destructor ~Color3() = default; /// Component-wise assignment IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Color3& operator= (const Color3& c) IMATH_NOEXCEPT; /// @} /// @{ /// @name Arithmetic /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Color3& operator+= (const Color3& c) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE constexpr Color3 operator+ (const Color3& c) const IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Color3& operator-= (const Color3& c) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE constexpr Color3 operator- (const Color3& c) const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE constexpr Color3 operator-() const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Color3& negate() IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Color3& operator*= (const Color3& c) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Color3& operator*= (T a) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Color3 operator* (const Color3& c) const IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Color3 operator* (T a) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Color3& operator/= (const Color3& c) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Color3& operator/= (T a) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Color3 operator/ (const Color3& c) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Color3 operator/ (T a) const IMATH_NOEXCEPT; /// @} }; /// /// A 4-channel color class: 3 channels plus alpha. /// /// For convenience, the fields are named `r`, `g`, and `b`, although /// this class does not impose interpretation on the channels, which /// can represent either rgb or hsv color values. /// template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Color4 { public: /// @{ /// @name Direct access to elements T r, g, b, a; /// @} /// @{ /// @name Constructors and Assignment /// No initialization by default IMATH_HOSTDEVICE Color4() IMATH_NOEXCEPT; /// Initialize to `(a a a a)` IMATH_HOSTDEVICE IMATH_CONSTEXPR14 explicit Color4 (T a) IMATH_NOEXCEPT; /// Initialize to `(a b c d)` IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Color4 (T a, T b, T c, T d) IMATH_NOEXCEPT; /// Construct from Color4 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Color4 (const Color4& v) IMATH_NOEXCEPT; /// Construct from Color4 template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Color4 (const Color4<S>& v) IMATH_NOEXCEPT; /// Destructor ~Color4() = default; /// Assignment IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Color4& operator= (const Color4& v) IMATH_NOEXCEPT; /// Component-wise value IMATH_HOSTDEVICE T& operator[] (int i) IMATH_NOEXCEPT; /// Component-wise value IMATH_HOSTDEVICE const T& operator[] (int i) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Arithmetic and Comparison /// Equality template <class S> IMATH_HOSTDEVICE constexpr bool operator== (const Color4<S>& v) const IMATH_NOEXCEPT; /// Inequality template <class S> IMATH_HOSTDEVICE constexpr bool operator!= (const Color4<S>& v) const IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Color4& operator+= (const Color4& v) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE constexpr Color4 operator+ (const Color4& v) const IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Color4& operator-= (const Color4& v) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE constexpr Color4 operator- (const Color4& v) const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE constexpr Color4 operator-() const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Color4& negate() IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Color4& operator*= (const Color4& v) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Color4& operator*= (T a) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Color4 operator* (const Color4& v) const IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Color4 operator* (T a) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Color4& operator/= (const Color4& v) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Color4& operator/= (T a) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Color4 operator/ (const Color4& v) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Color4 operator/ (T a) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Numeric Limits /// Number of dimensions (channels), i.e. 4 for a Color4 IMATH_HOSTDEVICE constexpr static unsigned int dimensions() IMATH_NOEXCEPT { return 4; } /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits<T>::lowest(); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits<T>::max(); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits<T>::min(); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits<T>::epsilon(); } /// @} /// The base type: In templates that accept a parameter `V` (could /// be a Color4), you can refer to `T` as `V::BaseType` typedef T BaseType; /// @{ /// @name Compatibilty with Sb /// Set the value template <class S> IMATH_HOSTDEVICE void setValue (S a, S b, S c, S d) IMATH_NOEXCEPT; /// Set the value template <class S> IMATH_HOSTDEVICE void setValue (const Color4<S>& v) IMATH_NOEXCEPT; /// Return the value template <class S> IMATH_HOSTDEVICE void getValue (S& a, S& b, S& c, S& d) const IMATH_NOEXCEPT; /// Return the value template <class S> IMATH_HOSTDEVICE void getValue (Color4<S>& v) const IMATH_NOEXCEPT; /// Return raw pointer to the value IMATH_HOSTDEVICE T* getValue() IMATH_NOEXCEPT; /// Return raw pointer to the value IMATH_HOSTDEVICE const T* getValue() const IMATH_NOEXCEPT; /// @} }; /// Stream output, as "(r g b a)" template <class T> std::ostream& operator<< (std::ostream& s, const Color4<T>& v); /// Reverse multiplication: S * Color4 template <class S, class T> constexpr Color4<T> operator* (S a, const Color4<T>& v) IMATH_NOEXCEPT; /// 3 float channels typedef Color3<float> Color3f; /// 3 half channels typedef Color3<half> Color3h; /// 3 8-bit integer channels typedef Color3<unsigned char> Color3c; /// 3 half channels typedef Color3<half> C3h; /// 3 float channels typedef Color3<float> C3f; /// 3 8-bit integer channels typedef Color3<unsigned char> C3c; /// 4 float channels typedef Color4<float> Color4f; /// 4 half channels typedef Color4<half> Color4h; /// 4 8-bit integer channels typedef Color4<unsigned char> Color4c; /// 4 float channels typedef Color4<float> C4f; /// 4 half channels typedef Color4<half> C4h; /// 4 8-bit integer channels typedef Color4<unsigned char> C4c; /// Packed 32-bit integer typedef unsigned int PackedColor; // // Implementation of Color3 // template <class T> inline Color3<T>::Color3() IMATH_NOEXCEPT : Vec3<T>() { // empty } template <class T> constexpr inline Color3<T>::Color3 (T a) IMATH_NOEXCEPT : Vec3<T> (a) { // empty } template <class T> constexpr inline Color3<T>::Color3 (T a, T b, T c) IMATH_NOEXCEPT : Vec3<T> (a, b, c) { // empty } template <class T> constexpr inline Color3<T>::Color3 (const Color3& c) IMATH_NOEXCEPT : Vec3<T> (c) { // empty } template <class T> template <class S> constexpr inline Color3<T>::Color3 (const Vec3<S>& v) IMATH_NOEXCEPT : Vec3<T> (v) { //empty } template <class T> IMATH_CONSTEXPR14 inline const Color3<T>& Color3<T>::operator= (const Color3& c) IMATH_NOEXCEPT { *((Vec3<T>*) this) = c; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Color3<T>& Color3<T>::operator+= (const Color3& c) IMATH_NOEXCEPT { *((Vec3<T>*) this) += c; return *this; } template <class T> constexpr inline Color3<T> Color3<T>::operator+ (const Color3& c) const IMATH_NOEXCEPT { return Color3 (*(Vec3<T>*) this + (const Vec3<T>&) c); } template <class T> IMATH_CONSTEXPR14 inline const Color3<T>& Color3<T>::operator-= (const Color3& c) IMATH_NOEXCEPT { *((Vec3<T>*) this) -= c; return *this; } template <class T> constexpr inline Color3<T> Color3<T>::operator- (const Color3& c) const IMATH_NOEXCEPT { return Color3 (*(Vec3<T>*) this - (const Vec3<T>&) c); } template <class T> constexpr inline Color3<T> Color3<T>::operator-() const IMATH_NOEXCEPT { return Color3 (-(*(Vec3<T>*) this)); } template <class T> IMATH_CONSTEXPR14 inline const Color3<T>& Color3<T>::negate() IMATH_NOEXCEPT { ((Vec3<T>*) this)->negate(); return *this; } template <class T> IMATH_CONSTEXPR14 inline const Color3<T>& Color3<T>::operator*= (const Color3& c) IMATH_NOEXCEPT { *((Vec3<T>*) this) *= c; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Color3<T>& Color3<T>::operator*= (T a) IMATH_NOEXCEPT { *((Vec3<T>*) this) *= a; return *this; } template <class T> constexpr inline Color3<T> Color3<T>::operator* (const Color3& c) const IMATH_NOEXCEPT { return Color3 (*(Vec3<T>*) this * (const Vec3<T>&) c); } template <class T> constexpr inline Color3<T> Color3<T>::operator* (T a) const IMATH_NOEXCEPT { return Color3 (*(Vec3<T>*) this * a); } template <class T> IMATH_CONSTEXPR14 inline const Color3<T>& Color3<T>::operator/= (const Color3& c) IMATH_NOEXCEPT { *((Vec3<T>*) this) /= c; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Color3<T>& Color3<T>::operator/= (T a) IMATH_NOEXCEPT { *((Vec3<T>*) this) /= a; return *this; } template <class T> constexpr inline Color3<T> Color3<T>::operator/ (const Color3& c) const IMATH_NOEXCEPT { return Color3 (*(Vec3<T>*) this / (const Vec3<T>&) c); } template <class T> constexpr inline Color3<T> Color3<T>::operator/ (T a) const IMATH_NOEXCEPT { return Color3 (*(Vec3<T>*) this / a); } // // Implementation of Color4 // template <class T> inline T& Color4<T>::operator[] (int i) IMATH_NOEXCEPT { return (&r)[i]; } template <class T> inline const T& Color4<T>::operator[] (int i) const IMATH_NOEXCEPT { return (&r)[i]; } template <class T> inline Color4<T>::Color4() IMATH_NOEXCEPT { // empty } template <class T> IMATH_CONSTEXPR14 inline Color4<T>::Color4 (T x) IMATH_NOEXCEPT { r = g = b = a = x; } template <class T> IMATH_CONSTEXPR14 inline Color4<T>::Color4 (T x, T y, T z, T w) IMATH_NOEXCEPT { r = x; g = y; b = z; a = w; } template <class T> IMATH_CONSTEXPR14 inline Color4<T>::Color4 (const Color4& v) IMATH_NOEXCEPT { r = v.r; g = v.g; b = v.b; a = v.a; } template <class T> template <class S> IMATH_CONSTEXPR14 inline Color4<T>::Color4 (const Color4<S>& v) IMATH_NOEXCEPT { r = T (v.r); g = T (v.g); b = T (v.b); a = T (v.a); } template <class T> IMATH_CONSTEXPR14 inline const Color4<T>& Color4<T>::operator= (const Color4& v) IMATH_NOEXCEPT { r = v.r; g = v.g; b = v.b; a = v.a; return *this; } template <class T> template <class S> inline void Color4<T>::setValue (S x, S y, S z, S w) IMATH_NOEXCEPT { r = T (x); g = T (y); b = T (z); a = T (w); } template <class T> template <class S> inline void Color4<T>::setValue (const Color4<S>& v) IMATH_NOEXCEPT { r = T (v.r); g = T (v.g); b = T (v.b); a = T (v.a); } template <class T> template <class S> inline void Color4<T>::getValue (S& x, S& y, S& z, S& w) const IMATH_NOEXCEPT { x = S (r); y = S (g); z = S (b); w = S (a); } template <class T> template <class S> inline void Color4<T>::getValue (Color4<S>& v) const IMATH_NOEXCEPT { v.r = S (r); v.g = S (g); v.b = S (b); v.a = S (a); } template <class T> inline T* Color4<T>::getValue() IMATH_NOEXCEPT { return (T*) &r; } template <class T> inline const T* Color4<T>::getValue() const IMATH_NOEXCEPT { return (const T*) &r; } template <class T> template <class S> constexpr inline bool Color4<T>::operator== (const Color4<S>& v) const IMATH_NOEXCEPT { return r == v.r && g == v.g && b == v.b && a == v.a; } template <class T> template <class S> constexpr inline bool Color4<T>::operator!= (const Color4<S>& v) const IMATH_NOEXCEPT { return r != v.r || g != v.g || b != v.b || a != v.a; } template <class T> IMATH_CONSTEXPR14 inline const Color4<T>& Color4<T>::operator+= (const Color4& v) IMATH_NOEXCEPT { r += v.r; g += v.g; b += v.b; a += v.a; return *this; } template <class T> constexpr inline Color4<T> Color4<T>::operator+ (const Color4& v) const IMATH_NOEXCEPT { return Color4 (r + v.r, g + v.g, b + v.b, a + v.a); } template <class T> IMATH_CONSTEXPR14 inline const Color4<T>& Color4<T>::operator-= (const Color4& v) IMATH_NOEXCEPT { r -= v.r; g -= v.g; b -= v.b; a -= v.a; return *this; } template <class T> constexpr inline Color4<T> Color4<T>::operator- (const Color4& v) const IMATH_NOEXCEPT { return Color4 (r - v.r, g - v.g, b - v.b, a - v.a); } template <class T> constexpr inline Color4<T> Color4<T>::operator-() const IMATH_NOEXCEPT { return Color4 (-r, -g, -b, -a); } template <class T> IMATH_CONSTEXPR14 inline const Color4<T>& Color4<T>::negate() IMATH_NOEXCEPT { r = -r; g = -g; b = -b; a = -a; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Color4<T>& Color4<T>::operator*= (const Color4& v) IMATH_NOEXCEPT { r *= v.r; g *= v.g; b *= v.b; a *= v.a; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Color4<T>& Color4<T>::operator*= (T x) IMATH_NOEXCEPT { r *= x; g *= x; b *= x; a *= x; return *this; } template <class T> constexpr inline Color4<T> Color4<T>::operator* (const Color4& v) const IMATH_NOEXCEPT { return Color4 (r * v.r, g * v.g, b * v.b, a * v.a); } template <class T> constexpr inline Color4<T> Color4<T>::operator* (T x) const IMATH_NOEXCEPT { return Color4 (r * x, g * x, b * x, a * x); } template <class T> IMATH_CONSTEXPR14 inline const Color4<T>& Color4<T>::operator/= (const Color4& v) IMATH_NOEXCEPT { r /= v.r; g /= v.g; b /= v.b; a /= v.a; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Color4<T>& Color4<T>::operator/= (T x) IMATH_NOEXCEPT { r /= x; g /= x; b /= x; a /= x; return *this; } template <class T> constexpr inline Color4<T> Color4<T>::operator/ (const Color4& v) const IMATH_NOEXCEPT { return Color4 (r / v.r, g / v.g, b / v.b, a / v.a); } template <class T> constexpr inline Color4<T> Color4<T>::operator/ (T x) const IMATH_NOEXCEPT { return Color4 (r / x, g / x, b / x, a / x); } template <class T> std::ostream& operator<< (std::ostream& s, const Color4<T>& v) { return s << '(' << v.r << ' ' << v.g << ' ' << v.b << ' ' << v.a << ')'; } // // Implementation of reverse multiplication // template <class S, class T> constexpr inline Color4<T> operator* (S x, const Color4<T>& v) IMATH_NOEXCEPT { return Color4<T> (x * v.r, x * v.g, x * v.b, x * v.a); } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHCOLOR_H PyImathBox.h 0000644 00000014044 15125213144 0006742 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathBox_h_ #define _PyImathBox_h_ #include <Python.h> #include <boost/python.hpp> #include <ImathBox.h> #include "PyImathVec.h" #include "PyImathFixedArray.h" namespace PyImath { template <class T> boost::python::class_<IMATH_NAMESPACE::Box<T> > register_Box2(); template <class T> boost::python::class_<IMATH_NAMESPACE::Box<T> > register_Box3(); template <class T> boost::python::class_<FixedArray<IMATH_NAMESPACE::Box<T> > > register_BoxArray(); typedef FixedArray<IMATH_NAMESPACE::Box2s> Box2sArray; typedef FixedArray<IMATH_NAMESPACE::Box2i> Box2iArray; typedef FixedArray<IMATH_NAMESPACE::Box2i64> Box2i64Array; typedef FixedArray<IMATH_NAMESPACE::Box2f> Box2fArray; typedef FixedArray<IMATH_NAMESPACE::Box2d> Box2dArray; typedef FixedArray<IMATH_NAMESPACE::Box3s> Box3sArray; typedef FixedArray<IMATH_NAMESPACE::Box3i> Box3iArray; typedef FixedArray<IMATH_NAMESPACE::Box3i64> Box3i64Array; typedef FixedArray<IMATH_NAMESPACE::Box3f> Box3fArray; typedef FixedArray<IMATH_NAMESPACE::Box3d> Box3dArray; // // Other code in the Zeno code base assumes the existance of a class with the // same name as the Imath class, and with static functions wrap() and // convert() to produce a PyImath object from an Imath object and vice-versa, // respectively. The class Boost generates from the Imath class does not // have these properties, so we define a companion class here. // The template argument, T, is the element type for the box (e.g., int, // float). template <class T> class Box2 { public: static PyObject * wrap (const IMATH_NAMESPACE::Box< IMATH_NAMESPACE::Vec2<T> > &b); static int convert (PyObject *p, IMATH_NAMESPACE::Box< IMATH_NAMESPACE::Vec2<T> > *b); }; template <class T> class Box3 { public: static PyObject * wrap (const IMATH_NAMESPACE::Box< IMATH_NAMESPACE::Vec3<T> > &b); static int convert (PyObject *p, IMATH_NAMESPACE::Box< IMATH_NAMESPACE::Vec3<T> > *v); }; template <class T> PyObject * Box2<T>::wrap (const IMATH_NAMESPACE::Box< IMATH_NAMESPACE::Vec2<T> > &b) { typename boost::python::return_by_value::apply < IMATH_NAMESPACE::Box< IMATH_NAMESPACE::Vec2<T> > >::type converter; PyObject *p = converter (b); return p; } template <class T> PyObject * Box3<T>::wrap (const IMATH_NAMESPACE::Box< IMATH_NAMESPACE::Vec3<T> > &b) { typename boost::python::return_by_value::apply < IMATH_NAMESPACE::Box< IMATH_NAMESPACE::Vec3<T> > >::type converter; PyObject *p = converter (b); return p; } template <class T> int Box2<T>::convert (PyObject *p, IMATH_NAMESPACE::Box< IMATH_NAMESPACE::Vec2<T> > *v) { boost::python::extract < IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V2i> > extractorV2i (p); if (extractorV2i.check()) { IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V2i> b = extractorV2i(); v->min = b.min; v->max = b.max; return 1; } boost::python::extract < IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V2f> > extractorV2f (p); if (extractorV2f.check()) { IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V2f> b = extractorV2f(); v->min = b.min; v->max = b.max; return 1; } boost::python::extract < IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V2d> > extractorV2d (p); if (extractorV2d.check()) { IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V2d> b = extractorV2d(); v->min = b.min; v->max = b.max; return 1; } boost::python::extract <boost::python::tuple> extractorTuple (p); if (extractorTuple.check()) { boost::python::tuple t = extractorTuple(); if (t.attr ("__len__") () == 2) { PyObject *minObj = boost::python::extract <boost::python::object> (t[0])().ptr(); PyObject *maxObj = boost::python::extract <boost::python::object> (t[1])().ptr(); IMATH_NAMESPACE::Vec2<T> min, max; if (! V2<T>::convert (minObj, &min)) return 0; if (! V2<T>::convert (maxObj, &max)) return 0; v->min = min; v->max = max; return 1; } } return 0; } template <class T> int Box3<T>::convert (PyObject *p, IMATH_NAMESPACE::Box< IMATH_NAMESPACE::Vec3<T> > *v) { boost::python::extract < IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V3i> > extractorV3i (p); if (extractorV3i.check()) { IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V3i> b = extractorV3i(); v->min = b.min; v->max = b.max; return 1; } boost::python::extract < IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V3f> > extractorV3f (p); if (extractorV3f.check()) { IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V3f> b = extractorV3f(); v->min = b.min; v->max = b.max; return 1; } boost::python::extract < IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V3d> > extractorV3d (p); if (extractorV3d.check()) { IMATH_NAMESPACE::Box<IMATH_NAMESPACE::V3d> b = extractorV3d(); v->min = b.min; v->max = b.max; return 1; } boost::python::extract <boost::python::tuple> extractorTuple (p); if (extractorTuple.check()) { boost::python::tuple t = extractorTuple(); if (t.attr ("__len__") () == 2) { PyObject *minObj = boost::python::extract <boost::python::object> (t[0])().ptr(); PyObject *maxObj = boost::python::extract <boost::python::object> (t[1])().ptr(); IMATH_NAMESPACE::Vec3<T> min, max; if (! V3<T>::convert (minObj, &min)) return 0; if (! V3<T>::convert (maxObj, &max)) return 0; v->min = min; v->max = max; return 1; } } return 0; } typedef Box2<int> Box2i; typedef Box2<int64_t> Box2i64; typedef Box2<float> Box2f; typedef Box2<double> Box2d; typedef Box3<int> Box3i; typedef Box3<int64_t> Box3i64; typedef Box3<float> Box3f; typedef Box3<double> Box3d; } #endif ImathLine.h 0000644 00000010235 15125213144 0006566 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // A 3D line class template // #ifndef INCLUDED_IMATHLINE_H #define INCLUDED_IMATHLINE_H #include "ImathMatrix.h" #include "ImathNamespace.h" #include "ImathVec.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// /// The `Line3` class represents a 3D line, defined by a point and a /// direction vector. /// template <class T> class Line3 { public: /// @{ /// @name Direct access to member fields /// A point on the line Vec3<T> pos; /// The direction of the line Vec3<T> dir; /// @} /// @{ /// @name Constructors /// Uninitialized by default IMATH_HOSTDEVICE constexpr Line3() IMATH_NOEXCEPT {} /// Initialize with two points. The direction is the difference /// between the points. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Line3 (const Vec3<T>& point1, const Vec3<T>& point2) IMATH_NOEXCEPT; /// @} /// @{ /// @name Manipulation /// Set the line defined by two points. The direction is the difference /// between the points. IMATH_HOSTDEVICE void set (const Vec3<T>& point1, const Vec3<T>& point2) IMATH_NOEXCEPT; /// @} /// @{ /// @name Utility Methods /// Return the point on the line at the given parameter value, /// e.g. L(t) IMATH_HOSTDEVICE constexpr Vec3<T> operator() (T parameter) const IMATH_NOEXCEPT; /// Return the distance to the given point IMATH_HOSTDEVICE constexpr T distanceTo (const Vec3<T>& point) const IMATH_NOEXCEPT; /// Return the distance to the given line IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T distanceTo (const Line3<T>& line) const IMATH_NOEXCEPT; /// Return the point on the line closest to the given point IMATH_HOSTDEVICE constexpr Vec3<T> closestPointTo (const Vec3<T>& point) const IMATH_NOEXCEPT; /// Return the point on the line closest to the given line IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3<T> closestPointTo (const Line3<T>& line) const IMATH_NOEXCEPT; /// @} }; /// Line of type float typedef Line3<float> Line3f; /// Line of type double typedef Line3<double> Line3d; template <class T> IMATH_CONSTEXPR14 inline Line3<T>::Line3 (const Vec3<T>& p0, const Vec3<T>& p1) IMATH_NOEXCEPT { set (p0, p1); } template <class T> inline void Line3<T>::set (const Vec3<T>& p0, const Vec3<T>& p1) IMATH_NOEXCEPT { pos = p0; dir = p1 - p0; dir.normalize(); } template <class T> constexpr inline Vec3<T> Line3<T>::operator() (T parameter) const IMATH_NOEXCEPT { return pos + dir * parameter; } template <class T> constexpr inline T Line3<T>::distanceTo (const Vec3<T>& point) const IMATH_NOEXCEPT { return (closestPointTo (point) - point).length(); } template <class T> constexpr inline Vec3<T> Line3<T>::closestPointTo (const Vec3<T>& point) const IMATH_NOEXCEPT { return ((point - pos) ^ dir) * dir + pos; } template <class T> IMATH_CONSTEXPR14 inline T Line3<T>::distanceTo (const Line3<T>& line) const IMATH_NOEXCEPT { T d = (dir % line.dir) ^ (line.pos - pos); return (d >= 0) ? d : -d; } template <class T> IMATH_CONSTEXPR14 inline Vec3<T> Line3<T>::closestPointTo (const Line3<T>& line) const IMATH_NOEXCEPT { // Assumes the lines are normalized Vec3<T> posLpos = pos - line.pos; T c = dir ^ posLpos; T a = line.dir ^ dir; T f = line.dir ^ posLpos; T num = c - a * f; T denom = a * a - 1; T absDenom = ((denom >= 0) ? denom : -denom); if (absDenom < 1) { T absNum = ((num >= 0) ? num : -num); if (absNum >= absDenom * std::numeric_limits<T>::max()) return pos; } return pos + dir * (num / denom); } /// Stream output, as "(pos dir)" template <class T> std::ostream& operator<< (std::ostream& o, const Line3<T>& line) { return o << "(" << line.pos << ", " << line.dir << ")"; } /// Transform a line by a matrix template <class S, class T> constexpr inline Line3<S> operator* (const Line3<S>& line, const Matrix44<T>& M) IMATH_NOEXCEPT { return Line3<S> (line.pos * M, (line.pos + line.dir) * M); } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHLINE_H ImathMath.h 0000644 00000011265 15125213144 0006574 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // Obsolete functions provided for compatibility, deprecated in favor // of std:: functions. // #ifndef INCLUDED_IMATHMATH_H #define INCLUDED_IMATHMATH_H #include "ImathNamespace.h" #include "ImathPlatform.h" #include <cmath> #include <limits> IMATH_INTERNAL_NAMESPACE_HEADER_ENTER //---------------------------------------------------------------------------- // // The deprecated Math<T> methods were intended to allow templated access to // math functions so that they would automatically choose either the double // (e.g. sin()) or float (e.g., sinf()) version. // // Beginning wth C++11, this is unnecessary, as std:: versions of all these // functions are available and are templated by type. // // We keep these old definitions for backward compatibility but encourage // users to prefer the std:: versions. Some day we may remove these // deprecated versions. // //---------------------------------------------------------------------------- /// @cond Doxygen_Suppress template <class T> struct Math { IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T acos (T x) { return std::acos (x); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T asin (T x) { return std::asin (x); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T atan (T x) { return std::atan (x); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T atan2 (T x, T y) { return std::atan2 (x, y); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T cos (T x) { return std::cos (x); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T sin (T x) { return std::sin (x); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T tan (T x) { return std::tan (x); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T cosh (T x) { return std::cosh (x); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T sinh (T x) { return std::sinh (x); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T tanh (T x) { return std::tanh (x); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T exp (T x) { return std::exp (x); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T log (T x) { return std::log (x); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T log10 (T x) { return std::log10 (x); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T modf (T x, T* iptr) { T ival; T rval (std::modf (T (x), &ival)); *iptr = ival; return rval; } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T pow (T x, T y) { return std::pow (x, y); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T sqrt (T x) { return std::sqrt (x); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T ceil (T x) { return std::ceil (x); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T fabs (T x) { return std::fabs (x); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T floor (T x) { return std::floor (x); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T fmod (T x, T y) { return std::fmod (x, y); } IMATH_HOSTDEVICE IMATH_DEPRECATED("use std::math functions") static T hypot (T x, T y) { return std::hypot (x, y); } }; /// @endcond /// Don Hatch's version of sin(x)/x, which is accurate for very small x. /// Returns 1 for x == 0. template <class T> IMATH_HOSTDEVICE inline T sinx_over_x (T x) { if (x * x < std::numeric_limits<T>::epsilon()) return T (1); else return std::sin (x) / x; } /// Compare two numbers and test if they are "approximately equal": /// /// @return Ttrue if x1 is the same as x2 with an absolute error of /// no more than e: /// /// abs (x1 - x2) <= e template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool equalWithAbsError (T x1, T x2, T e) IMATH_NOEXCEPT { return ((x1 > x2) ? x1 - x2 : x2 - x1) <= e; } /// Compare two numbers and test if they are "approximately equal": /// /// @return True if x1 is the same as x2 with an relative error of /// no more than e, /// /// abs (x1 - x2) <= e * x1 template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline bool equalWithRelError (T x1, T x2, T e) IMATH_NOEXCEPT { return ((x1 > x2) ? x1 - x2 : x2 - x1) <= e * ((x1 > 0) ? x1 : -x1); } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHMATH_H PyImathVec3ArrayImpl.h 0000644 00000014161 15125213144 0010633 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathVec3ArrayImpl_h_ #define _PyImathVec3ArrayImpl_h_ // // This .C file was turned into a header file so that instantiations // of the various V3* types can be spread across multiple files in // order to work around MSVC limitations. // #include <Python.h> #include <boost/python.hpp> #include <boost/python/make_constructor.hpp> #include <boost/format.hpp> #include <ImathVec.h> #include <ImathVecAlgo.h> #include "PyImath.h" #include "PyImathBox.h" #include "PyImathVec.h" #include "PyImathDecorators.h" #include "PyImathMathExc.h" #include "PyImathOperators.h" #include "PyImathVecOperators.h" namespace PyImath { using namespace boost::python; using namespace IMATH_NAMESPACE; // XXX fixme - template this // really this should get generated automatically... template <class T,int index> static FixedArray<T> Vec3Array_get(FixedArray<IMATH_NAMESPACE::Vec3<T> > &va) { return FixedArray<T>(&(va.unchecked_index(0)[index]), va.len(), 3*va.stride(), va.handle(), va.writable()); } template <class T> static void setItemTuple(FixedArray<IMATH_NAMESPACE::Vec3<T> > &va, Py_ssize_t index, const tuple &t) { if(t.attr("__len__")() == 3) { Vec3<T> v; v.x = extract<T>(t[0]); v.y = extract<T>(t[1]); v.z = extract<T>(t[2]); va[va.canonical_index(index)] = v; } else throw std::invalid_argument ("tuple of length 3 expected"); } template <class T> static IMATH_NAMESPACE::Vec3<T> Vec3Array_min(const FixedArray<IMATH_NAMESPACE::Vec3<T> > &a) { Vec3<T> tmp(Vec3<T>(0)); size_t len = a.len(); if (len > 0) tmp = a[0]; for (size_t i=1; i < len; ++i) { if (a[i].x < tmp.x) tmp.x = a[i].x; if (a[i].y < tmp.y) tmp.y = a[i].y; if (a[i].z < tmp.z) tmp.z = a[i].z; } return tmp; } template <class T> static IMATH_NAMESPACE::Vec3<T> Vec3Array_max(const FixedArray<IMATH_NAMESPACE::Vec3<T> > &a) { Vec3<T> tmp(Vec3<T>(0)); size_t len = a.len(); if (len > 0) tmp = a[0]; for (size_t i=1; i < len; ++i) { if (a[i].x > tmp.x) tmp.x = a[i].x; if (a[i].y > tmp.y) tmp.y = a[i].y; if (a[i].z > tmp.z) tmp.z = a[i].z; } return tmp; } template <class T> static IMATH_NAMESPACE::Box<IMATH_NAMESPACE::Vec3<T> > Vec3Array_bounds(const FixedArray<IMATH_NAMESPACE::Vec3<T> > &a) { Box<Vec3<T> > tmp; size_t len = a.len(); for (size_t i=0; i < len; ++i) tmp.extendBy(a[i]); return tmp; } // Trick to register methods for float-only-based vectors template <class T, IMATH_ENABLE_IF(!std::is_integral<T>::value)> void register_Vec3Array_floatonly(class_<FixedArray<Vec3<T>>>& vec3Array_class) { generate_member_bindings<op_vecLength<IMATH_NAMESPACE::Vec3<T> > >(vec3Array_class,"length",""); generate_member_bindings<op_vecNormalize<IMATH_NAMESPACE::Vec3<T> > >(vec3Array_class,"normalize",""); generate_member_bindings<op_vecNormalized<IMATH_NAMESPACE::Vec3<T> > >(vec3Array_class,"normalized",""); generate_member_bindings<op_vecNormalizeExc<IMATH_NAMESPACE::Vec3<T> > >(vec3Array_class,"normalizeExc",""); generate_member_bindings<op_vecNormalizedExc<IMATH_NAMESPACE::Vec3<T> > >(vec3Array_class,"normalizedExc",""); } template <class T, IMATH_ENABLE_IF(std::is_integral<T>::value)> void register_Vec3Array_floatonly(class_<FixedArray<Vec3<T>>>& vec3Array_class) { } template <class T> class_<FixedArray<IMATH_NAMESPACE::Vec3<T> > > register_Vec3Array() { using boost::mpl::true_; using boost::mpl::false_; class_<FixedArray<IMATH_NAMESPACE::Vec3<T> > > vec3Array_class = FixedArray<IMATH_NAMESPACE::Vec3<T> >::register_("Fixed length array of IMATH_NAMESPACE::Vec3"); vec3Array_class .add_property("x",&Vec3Array_get<T,0>) .add_property("y",&Vec3Array_get<T,1>) .add_property("z",&Vec3Array_get<T,2>) .def("__setitem__", &setItemTuple<T>) .def("min", &Vec3Array_min<T>) .def("max", &Vec3Array_max<T>) .def("bounds", &Vec3Array_bounds<T>) ; add_arithmetic_math_functions(vec3Array_class); add_comparison_functions(vec3Array_class); register_Vec3Array_floatonly(vec3Array_class); generate_member_bindings<op_vecLength2<IMATH_NAMESPACE::Vec3<T> > >(vec3Array_class,"length2",""); generate_member_bindings<op_vec3Cross<T>, true_>(vec3Array_class,"cross","return the cross product of (self,x)",boost::python::args("x")); generate_member_bindings<op_vecDot<IMATH_NAMESPACE::Vec3<T> >,true_>(vec3Array_class,"dot","return the inner product of (self,x)",boost::python::args("x")); generate_member_bindings<op_mul<IMATH_NAMESPACE::Vec3<T>,T>, true_>(vec3Array_class,"__mul__" ,"self*x", boost::python::args("x")); generate_member_bindings<op_mul<IMATH_NAMESPACE::Vec3<T>,IMATH_NAMESPACE::M44f>,false_>(vec3Array_class,"__mul__" ,"self*x", boost::python::args("x")); generate_member_bindings<op_mul<IMATH_NAMESPACE::Vec3<T>,IMATH_NAMESPACE::M44d>,false_>(vec3Array_class,"__mul__" ,"self*x", boost::python::args("x")); generate_member_bindings<op_mul<IMATH_NAMESPACE::Vec3<T>,T>, true_>(vec3Array_class,"__rmul__","x*self", boost::python::args("x")); generate_member_bindings<op_imul<IMATH_NAMESPACE::Vec3<T>,T>, true_>(vec3Array_class,"__imul__","self*=x",boost::python::args("x")); generate_member_bindings<op_div<IMATH_NAMESPACE::Vec3<T>,T>, true_>(vec3Array_class,"__div__" ,"self/x", boost::python::args("x")); generate_member_bindings<op_div<IMATH_NAMESPACE::Vec3<T>,T>, true_>(vec3Array_class,"__truediv__" ,"self/x", boost::python::args("x")); generate_member_bindings<op_idiv<IMATH_NAMESPACE::Vec3<T>,T>, true_>(vec3Array_class,"__idiv__","self/=x",boost::python::args("x")); generate_member_bindings<op_idiv<IMATH_NAMESPACE::Vec3<T>,T>, true_>(vec3Array_class,"__itruediv__","self/=x",boost::python::args("x")); decoratecopy(vec3Array_class); return vec3Array_class; } } // namespace PyImath #endif // _PyImathVec3ArrayImpl_h_ ImathGL.h 0000644 00000007411 15125213144 0006203 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // Convenience functions that call GL with Imath types // #ifndef INCLUDED_IMATHGL_H #define INCLUDED_IMATHGL_H #include <GL/gl.h> #include "ImathFun.h" #include "ImathMatrix.h" #include "ImathNamespace.h" #include "ImathVec.h" /// Call glVertex3f inline void glVertex (const IMATH_INTERNAL_NAMESPACE::V3f& v) { glVertex3f (v.x, v.y, v.z); } /// Call glVertex2f inline void glVertex (const IMATH_INTERNAL_NAMESPACE::V2f& v) { glVertex2f (v.x, v.y); } /// Call glNormal3f inline void glNormal (const IMATH_INTERNAL_NAMESPACE::V3f& n) { glNormal3f (n.x, n.y, n.z); } /// Call glColor3f inline void glColor (const IMATH_INTERNAL_NAMESPACE::V3f& c) { glColor3f (c.x, c.y, c.z); } /// Call glTranslatef inline void glTranslate (const IMATH_INTERNAL_NAMESPACE::V3f& t) { glTranslatef (t.x, t.y, t.z); } /// Call glTexCoord2f inline void glTexCoord (const IMATH_INTERNAL_NAMESPACE::V2f& t) { glTexCoord2f (t.x, t.y); } /// Disable GL textures inline void glDisableTexture() { glActiveTexture (GL_TEXTURE1); glBindTexture (GL_TEXTURE_2D, 0); glDisable (GL_TEXTURE_2D); glActiveTexture (GL_TEXTURE0); } namespace { const float GL_FLOAT_MAX = 1.8e+19; // sqrt (FLT_MAX) inline bool badFloat (float f) { return !IMATH_INTERNAL_NAMESPACE::finitef (f) || f < -GL_FLOAT_MAX || f > GL_FLOAT_MAX; } } // namespace /// Throw an exception if m is not a valid matrix for GL inline void throwBadMatrix (const IMATH_INTERNAL_NAMESPACE::M44f& m) { if (badFloat (m[0][0]) || badFloat (m[0][1]) || badFloat (m[0][2]) || badFloat (m[0][3]) || badFloat (m[1][0]) || badFloat (m[1][1]) || badFloat (m[1][2]) || badFloat (m[1][3]) || badFloat (m[2][0]) || badFloat (m[2][1]) || badFloat (m[2][2]) || badFloat (m[2][3]) || badFloat (m[3][0]) || badFloat (m[3][1]) || badFloat (m[3][2]) || badFloat (m[3][3])) throw std::invalid_argument ("GL matrix overflow"); } /// Call glMultmatrixf. Throw an exception if m is not a valid matrix for GL. inline void glMultMatrix (const IMATH_INTERNAL_NAMESPACE::M44f& m) { throwBadMatrix (m); glMultMatrixf ((GLfloat*) m[0]); } /// Call glMultmatrixf. Throw an exception if m is not a valid matrix for GL. inline void glMultMatrix (const IMATH_INTERNAL_NAMESPACE::M44f* m) { throwBadMatrix (*m); glMultMatrixf ((GLfloat*) (*m)[0]); } /// Call glLoadmatrixf. Throw an exception if m is not a valid matrix for GL. inline void glLoadMatrix (const IMATH_INTERNAL_NAMESPACE::M44f& m) { throwBadMatrix (m); glLoadMatrixf ((GLfloat*) m[0]); } /// Call glLoadmatrixf. Throw an exception if m is not a valid matrix for GL. inline void glLoadMatrix (const IMATH_INTERNAL_NAMESPACE::M44f* m) { throwBadMatrix (*m); glLoadMatrixf ((GLfloat*) (*m)[0]); } IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// /// A class object that pushes/pops the GL matrix. This object assists with /// proper cleanup of the state when exceptions are thrown. /// class GLPushMatrix { public: GLPushMatrix() { glPushMatrix(); } ~GLPushMatrix() { glPopMatrix(); } }; /// /// A class object that pushes/pops the current GL attribute state. This object assists with /// proper cleanup of the state when exceptions are thrown. /// class GLPushAttrib { public: /// call glPushAttrib() GLPushAttrib (GLbitfield mask) { glPushAttrib (mask); } /// call glPopAttrib() ~GLPushAttrib() { glPopAttrib(); } }; /// /// A class object that wraps glBegin/glEnd. The constructor calls /// glBegin(). The destructor calls glEnd(). /// class GLBegin { public: /// Call glBegin() GLBegin (GLenum mode) { glBegin (mode); } /// Call glEnd() ~GLBegin() { glEnd(); } }; IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif PyImathBufferProtocol.h 0000644 00000001074 15125213144 0011144 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathBufferProtocol_h_ #define _PyImathBufferProtocol_h_ #include <boost/python.hpp> namespace PyImath { // For more information on working with the protocol see: // // https://docs.python.org/2.7/c-api/buffer.html // https://docs.python.org/3.7.10/c-api/buffer.html template <class T> void add_buffer_protocol (boost::python::class_<T> &classObj); template <class ArrayT> ArrayT* fixedArrayFromBuffer (PyObject *obj); } #endif ImathBoxAlgo.h 0000644 00000055723 15125213144 0007245 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // Axis-aligned bounding box utility functions // #ifndef INCLUDED_IMATHBOXALGO_H #define INCLUDED_IMATHBOXALGO_H #include "ImathNamespace.h" #include "ImathBox.h" #include "ImathLineAlgo.h" #include "ImathMatrix.h" #include "ImathPlane.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// /// Clip the coordinates of a point, `p`, against a `Box<T>`, `box`. /// Return the closest point to `p` that is inside the box. /// template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T clip (const T& p, const Box<T>& box) IMATH_NOEXCEPT { T q; for (int i = 0; i < int (box.min.dimensions()); i++) { if (p[i] < box.min[i]) q[i] = box.min[i]; else if (p[i] > box.max[i]) q[i] = box.max[i]; else q[i] = p[i]; } return q; } /// /// Return the point in or on the `Box<T>`, `box`, that is closesest to /// the point, `p`. /// template <class T> IMATH_HOSTDEVICE constexpr inline T closestPointInBox (const T& p, const Box<T>& box) IMATH_NOEXCEPT { return clip (p, box); } /// /// Return the point on the surface of the `Box<T>`, `box`, that is /// closest to point `p`. /// /// If the box is empty, return `p`. /// template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3<T> closestPointOnBox (const Vec3<T>& p, const Box<Vec3<T>>& box) IMATH_NOEXCEPT { if (box.isEmpty()) return p; Vec3<T> q = closestPointInBox (p, box); if (q == p) { Vec3<T> d1 = p - box.min; Vec3<T> d2 = box.max - p; Vec3<T> d ((d1.x < d2.x) ? d1.x : d2.x, (d1.y < d2.y) ? d1.y : d2.y, (d1.z < d2.z) ? d1.z : d2.z); if (d.x < d.y && d.x < d.z) { q.x = (d1.x < d2.x) ? box.min.x : box.max.x; } else if (d.y < d.z) { q.y = (d1.y < d2.y) ? box.min.y : box.max.y; } else { q.z = (d1.z < d2.z) ? box.min.z : box.max.z; } } return q; } /// /// Transform a 3D box by a matrix, and compute a new box that /// tightly encloses the transformed box. Return the transformed box. /// /// If `m` is an affine transform, then we use James Arvo's fast /// method as described in "Graphics Gems", Academic Press, 1990, /// pp. 548-550. /// /// A transformed empty box is still empty, and a transformed infinite box /// is still infinite. /// template <class S, class T> IMATH_HOSTDEVICE Box<Vec3<S>> transform (const Box<Vec3<S>>& box, const Matrix44<T>& m) IMATH_NOEXCEPT { if (box.isEmpty() || box.isInfinite()) return box; // // If the last column of m is (0 0 0 1) then m is an affine // transform, and we use the fast Graphics Gems trick. // if (m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1) { Box<Vec3<S>> newBox; for (int i = 0; i < 3; i++) { newBox.min[i] = newBox.max[i] = (S) m[3][i]; for (int j = 0; j < 3; j++) { S a, b; a = (S) m[j][i] * box.min[j]; b = (S) m[j][i] * box.max[j]; if (a < b) { newBox.min[i] += a; newBox.max[i] += b; } else { newBox.min[i] += b; newBox.max[i] += a; } } } return newBox; } // // M is a projection matrix. Do things the naive way: // Transform the eight corners of the box, and find an // axis-parallel box that encloses the transformed corners. // Vec3<S> points[8]; points[0][0] = points[1][0] = points[2][0] = points[3][0] = box.min[0]; points[4][0] = points[5][0] = points[6][0] = points[7][0] = box.max[0]; points[0][1] = points[1][1] = points[4][1] = points[5][1] = box.min[1]; points[2][1] = points[3][1] = points[6][1] = points[7][1] = box.max[1]; points[0][2] = points[2][2] = points[4][2] = points[6][2] = box.min[2]; points[1][2] = points[3][2] = points[5][2] = points[7][2] = box.max[2]; Box<Vec3<S>> newBox; for (int i = 0; i < 8; i++) newBox.extendBy (points[i] * m); return newBox; } /// /// Transform a 3D box by a matrix, and compute a new box that /// tightly encloses the transformed box. The transformed box is /// returned in the `result` argument. /// /// If m is an affine transform, then we use James Arvo's fast /// method as described in "Graphics Gems", Academic Press, 1990, /// pp. 548-550. /// /// A transformed empty box is still empty, and a transformed infinite /// box is still infinite /// template <class S, class T> IMATH_HOSTDEVICE void transform (const Box<Vec3<S>>& box, const Matrix44<T>& m, Box<Vec3<S>>& result) IMATH_NOEXCEPT { if (box.isEmpty() || box.isInfinite()) { return; } // // If the last column of m is (0 0 0 1) then m is an affine // transform, and we use the fast Graphics Gems trick. // if (m[0][3] == 0 && m[1][3] == 0 && m[2][3] == 0 && m[3][3] == 1) { for (int i = 0; i < 3; i++) { result.min[i] = result.max[i] = (S) m[3][i]; for (int j = 0; j < 3; j++) { S a, b; a = (S) m[j][i] * box.min[j]; b = (S) m[j][i] * box.max[j]; if (a < b) { result.min[i] += a; result.max[i] += b; } else { result.min[i] += b; result.max[i] += a; } } } return; } // // M is a projection matrix. Do things the naive way: // Transform the eight corners of the box, and find an // axis-parallel box that encloses the transformed corners. // Vec3<S> points[8]; points[0][0] = points[1][0] = points[2][0] = points[3][0] = box.min[0]; points[4][0] = points[5][0] = points[6][0] = points[7][0] = box.max[0]; points[0][1] = points[1][1] = points[4][1] = points[5][1] = box.min[1]; points[2][1] = points[3][1] = points[6][1] = points[7][1] = box.max[1]; points[0][2] = points[2][2] = points[4][2] = points[6][2] = box.min[2]; points[1][2] = points[3][2] = points[5][2] = points[7][2] = box.max[2]; for (int i = 0; i < 8; i++) result.extendBy (points[i] * m); } /// /// Transform a 3D box by a matrix whose rightmost column `(0 0 0 1)`, /// and compute a new box that tightly encloses the transformed /// box. Return the transformed box. /// /// As in the transform() function, use James Arvo's fast method if /// possible. /// /// A transformed empty or infinite box is still empty or infinite. /// template <class S, class T> IMATH_HOSTDEVICE Box<Vec3<S>> affineTransform (const Box<Vec3<S>>& box, const Matrix44<T>& m) IMATH_NOEXCEPT { if (box.isEmpty() || box.isInfinite()) return box; Box<Vec3<S>> newBox; for (int i = 0; i < 3; i++) { newBox.min[i] = newBox.max[i] = (S) m[3][i]; for (int j = 0; j < 3; j++) { S a, b; a = (S) m[j][i] * box.min[j]; b = (S) m[j][i] * box.max[j]; if (a < b) { newBox.min[i] += a; newBox.max[i] += b; } else { newBox.min[i] += b; newBox.max[i] += a; } } } return newBox; } /// /// Transform a 3D box by a matrix whose rightmost column is /// `(0 0 0 1)`, and compute a new box that tightly encloses /// the transformed box. Return the transformed box in the `result` /// argument. /// /// As in the transform() function, use James Arvo's fast method if /// possible. /// /// A transformed empty or infinite box is still empty or infinite. /// template <class S, class T> IMATH_HOSTDEVICE void affineTransform (const Box<Vec3<S>>& box, const Matrix44<T>& m, Box<Vec3<S>>& result) IMATH_NOEXCEPT { if (box.isEmpty()) { result.makeEmpty(); return; } if (box.isInfinite()) { result.makeInfinite(); return; } for (int i = 0; i < 3; i++) { result.min[i] = result.max[i] = (S) m[3][i]; for (int j = 0; j < 3; j++) { S a, b; a = (S) m[j][i] * box.min[j]; b = (S) m[j][i] * box.max[j]; if (a < b) { result.min[i] += a; result.max[i] += b; } else { result.min[i] += b; result.max[i] += a; } } } } /// /// Compute the points where a ray, `r`, enters and exits a 3D box, `b`: /// /// Return true if the ray starts inside the box or if the ray starts /// outside and intersects the box, or return false otherwise (that /// is, if the ray does not intersect the box). /// /// The entry and exit points are the points on two of the faces of /// the box when the function returns true (the entry end exit points /// may be on either side of the ray's origin), or undefined if the /// the function returns false. /// template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool findEntryAndExitPoints (const Line3<T>& r, const Box<Vec3<T>>& b, Vec3<T>& entry, Vec3<T>& exit) IMATH_NOEXCEPT { if (b.isEmpty()) { // // No ray intersects an empty box // return false; } // // The following description assumes that the ray's origin is outside // the box, but the code below works even if the origin is inside the // box: // // Between one and three "frontfacing" sides of the box are oriented // towards the ray's origin, and between one and three "backfacing" // sides are oriented away from the ray's origin. // We intersect the ray with the planes that contain the sides of the // box, and compare the distances between the ray's origin and the // ray-plane intersections. The ray intersects the box if the most // distant frontfacing intersection is nearer than the nearest // backfacing intersection. If the ray does intersect the box, then // the most distant frontfacing ray-plane intersection is the entry // point and the nearest backfacing ray-plane intersection is the // exit point. // const T TMAX = std::numeric_limits<T>::max(); T tFrontMax = -TMAX; T tBackMin = TMAX; // // Minimum and maximum X sides. // if (r.dir.x >= 0) { T d1 = b.max.x - r.pos.x; T d2 = b.min.x - r.pos.x; if (r.dir.x > 1 || (abs (d1) < TMAX * r.dir.x && abs (d2) < TMAX * r.dir.x)) { T t1 = d1 / r.dir.x; T t2 = d2 / r.dir.x; if (tBackMin > t1) { tBackMin = t1; exit.x = b.max.x; exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y); exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z); } if (tFrontMax < t2) { tFrontMax = t2; entry.x = b.min.x; entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y); entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z); } } else if (r.pos.x < b.min.x || r.pos.x > b.max.x) { return false; } } else // r.dir.x < 0 { T d1 = b.min.x - r.pos.x; T d2 = b.max.x - r.pos.x; if (r.dir.x < -1 || (abs (d1) < -TMAX * r.dir.x && abs (d2) < -TMAX * r.dir.x)) { T t1 = d1 / r.dir.x; T t2 = d2 / r.dir.x; if (tBackMin > t1) { tBackMin = t1; exit.x = b.min.x; exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y); exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z); } if (tFrontMax < t2) { tFrontMax = t2; entry.x = b.max.x; entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y); entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z); } } else if (r.pos.x < b.min.x || r.pos.x > b.max.x) { return false; } } // // Minimum and maximum Y sides. // if (r.dir.y >= 0) { T d1 = b.max.y - r.pos.y; T d2 = b.min.y - r.pos.y; if (r.dir.y > 1 || (abs (d1) < TMAX * r.dir.y && abs (d2) < TMAX * r.dir.y)) { T t1 = d1 / r.dir.y; T t2 = d2 / r.dir.y; if (tBackMin > t1) { tBackMin = t1; exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x); exit.y = b.max.y; exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z); } if (tFrontMax < t2) { tFrontMax = t2; entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x); entry.y = b.min.y; entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z); } } else if (r.pos.y < b.min.y || r.pos.y > b.max.y) { return false; } } else // r.dir.y < 0 { T d1 = b.min.y - r.pos.y; T d2 = b.max.y - r.pos.y; if (r.dir.y < -1 || (abs (d1) < -TMAX * r.dir.y && abs (d2) < -TMAX * r.dir.y)) { T t1 = d1 / r.dir.y; T t2 = d2 / r.dir.y; if (tBackMin > t1) { tBackMin = t1; exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x); exit.y = b.min.y; exit.z = clamp (r.pos.z + t1 * r.dir.z, b.min.z, b.max.z); } if (tFrontMax < t2) { tFrontMax = t2; entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x); entry.y = b.max.y; entry.z = clamp (r.pos.z + t2 * r.dir.z, b.min.z, b.max.z); } } else if (r.pos.y < b.min.y || r.pos.y > b.max.y) { return false; } } // // Minimum and maximum Z sides. // if (r.dir.z >= 0) { T d1 = b.max.z - r.pos.z; T d2 = b.min.z - r.pos.z; if (r.dir.z > 1 || (abs (d1) < TMAX * r.dir.z && abs (d2) < TMAX * r.dir.z)) { T t1 = d1 / r.dir.z; T t2 = d2 / r.dir.z; if (tBackMin > t1) { tBackMin = t1; exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x); exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y); exit.z = b.max.z; } if (tFrontMax < t2) { tFrontMax = t2; entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x); entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y); entry.z = b.min.z; } } else if (r.pos.z < b.min.z || r.pos.z > b.max.z) { return false; } } else // r.dir.z < 0 { T d1 = b.min.z - r.pos.z; T d2 = b.max.z - r.pos.z; if (r.dir.z < -1 || (abs (d1) < -TMAX * r.dir.z && abs (d2) < -TMAX * r.dir.z)) { T t1 = d1 / r.dir.z; T t2 = d2 / r.dir.z; if (tBackMin > t1) { tBackMin = t1; exit.x = clamp (r.pos.x + t1 * r.dir.x, b.min.x, b.max.x); exit.y = clamp (r.pos.y + t1 * r.dir.y, b.min.y, b.max.y); exit.z = b.min.z; } if (tFrontMax < t2) { tFrontMax = t2; entry.x = clamp (r.pos.x + t2 * r.dir.x, b.min.x, b.max.x); entry.y = clamp (r.pos.y + t2 * r.dir.y, b.min.y, b.max.y); entry.z = b.max.z; } } else if (r.pos.z < b.min.z || r.pos.z > b.max.z) { return false; } } return tFrontMax <= tBackMin; } /// /// Intersect a ray, `r`, with a 3D box, `b, and compute the intersection /// point, returned in `ip`. /// /// The intersection point is /// - the ray's origin if the ray starts inside the box /// - a point on one of the faces of the box if the ray /// starts outside the box /// - undefined when intersect() returns false /// /// @return /// - true if the ray starts inside the box or if the /// ray starts outside and intersects the box /// - false if the ray starts outside the box and intersects it, /// but the intersection is behind the ray's origin. /// - false if the ray starts outside and does not intersect it /// template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersects (const Box<Vec3<T>>& b, const Line3<T>& r, Vec3<T>& ip) IMATH_NOEXCEPT { if (b.isEmpty()) { // // No ray intersects an empty box // return false; } if (b.intersects (r.pos)) { // // The ray starts inside the box // ip = r.pos; return true; } // // The ray starts outside the box. Between one and three "frontfacing" // sides of the box are oriented towards the ray, and between one and // three "backfacing" sides are oriented away from the ray. // We intersect the ray with the planes that contain the sides of the // box, and compare the distances between ray's origin and the ray-plane // intersections. // The ray intersects the box if the most distant frontfacing intersection // is nearer than the nearest backfacing intersection. If the ray does // intersect the box, then the most distant frontfacing ray-plane // intersection is the ray-box intersection. // const T TMAX = std::numeric_limits<T>::max(); T tFrontMax = -1; T tBackMin = TMAX; // // Minimum and maximum X sides. // if (r.dir.x > 0) { if (r.pos.x > b.max.x) return false; T d = b.max.x - r.pos.x; if (r.dir.x > 1 || d < TMAX * r.dir.x) { T t = d / r.dir.x; if (tBackMin > t) tBackMin = t; } if (r.pos.x <= b.min.x) { T d = b.min.x - r.pos.x; T t = (r.dir.x > 1 || d < TMAX * r.dir.x) ? d / r.dir.x : TMAX; if (tFrontMax < t) { tFrontMax = t; ip.x = b.min.x; ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y); ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z); } } } else if (r.dir.x < 0) { if (r.pos.x < b.min.x) return false; T d = b.min.x - r.pos.x; if (r.dir.x < -1 || d > TMAX * r.dir.x) { T t = d / r.dir.x; if (tBackMin > t) tBackMin = t; } if (r.pos.x >= b.max.x) { T d = b.max.x - r.pos.x; T t = (r.dir.x < -1 || d > TMAX * r.dir.x) ? d / r.dir.x : TMAX; if (tFrontMax < t) { tFrontMax = t; ip.x = b.max.x; ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y); ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z); } } } else // r.dir.x == 0 { if (r.pos.x < b.min.x || r.pos.x > b.max.x) return false; } // // Minimum and maximum Y sides. // if (r.dir.y > 0) { if (r.pos.y > b.max.y) return false; T d = b.max.y - r.pos.y; if (r.dir.y > 1 || d < TMAX * r.dir.y) { T t = d / r.dir.y; if (tBackMin > t) tBackMin = t; } if (r.pos.y <= b.min.y) { T d = b.min.y - r.pos.y; T t = (r.dir.y > 1 || d < TMAX * r.dir.y) ? d / r.dir.y : TMAX; if (tFrontMax < t) { tFrontMax = t; ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x); ip.y = b.min.y; ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z); } } } else if (r.dir.y < 0) { if (r.pos.y < b.min.y) return false; T d = b.min.y - r.pos.y; if (r.dir.y < -1 || d > TMAX * r.dir.y) { T t = d / r.dir.y; if (tBackMin > t) tBackMin = t; } if (r.pos.y >= b.max.y) { T d = b.max.y - r.pos.y; T t = (r.dir.y < -1 || d > TMAX * r.dir.y) ? d / r.dir.y : TMAX; if (tFrontMax < t) { tFrontMax = t; ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x); ip.y = b.max.y; ip.z = clamp (r.pos.z + t * r.dir.z, b.min.z, b.max.z); } } } else // r.dir.y == 0 { if (r.pos.y < b.min.y || r.pos.y > b.max.y) return false; } // // Minimum and maximum Z sides. // if (r.dir.z > 0) { if (r.pos.z > b.max.z) return false; T d = b.max.z - r.pos.z; if (r.dir.z > 1 || d < TMAX * r.dir.z) { T t = d / r.dir.z; if (tBackMin > t) tBackMin = t; } if (r.pos.z <= b.min.z) { T d = b.min.z - r.pos.z; T t = (r.dir.z > 1 || d < TMAX * r.dir.z) ? d / r.dir.z : TMAX; if (tFrontMax < t) { tFrontMax = t; ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x); ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y); ip.z = b.min.z; } } } else if (r.dir.z < 0) { if (r.pos.z < b.min.z) return false; T d = b.min.z - r.pos.z; if (r.dir.z < -1 || d > TMAX * r.dir.z) { T t = d / r.dir.z; if (tBackMin > t) tBackMin = t; } if (r.pos.z >= b.max.z) { T d = b.max.z - r.pos.z; T t = (r.dir.z < -1 || d > TMAX * r.dir.z) ? d / r.dir.z : TMAX; if (tFrontMax < t) { tFrontMax = t; ip.x = clamp (r.pos.x + t * r.dir.x, b.min.x, b.max.x); ip.y = clamp (r.pos.y + t * r.dir.y, b.min.y, b.max.y); ip.z = b.max.z; } } } else // r.dir.z == 0 { if (r.pos.z < b.min.z || r.pos.z > b.max.z) return false; } return tFrontMax <= tBackMin; } /// /// Return whether the the ray `ray` interects the 3D box `box`. /// template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersects (const Box<Vec3<T>>& box, const Line3<T>& ray) IMATH_NOEXCEPT { Vec3<T> ignored; return intersects (box, ray, ignored); } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHBOXALGO_H ImathForward.h 0000644 00000004363 15125213144 0007310 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // #ifndef INCLUDED_IMATHFORWARD_H #define INCLUDED_IMATHFORWARD_H #include "ImathNamespace.h" #include "ImathExport.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// @cond Doxygen_Suppress // // Basic template type declarations. // // // Note: declarations with attributes generate warnings with // -Wattributes or -Wall if the type is already defined, i.e. the // header is already included. To avoid the warning, only make the // forward declaration if the header has not yet been included. // #ifndef INCLUDED_IMATHBOX_H template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Box; #endif #ifndef INCLUDED_IMATHCOLOR_H template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Color3; template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Color4; #endif #ifndef INCLUDED_IMATHEULER_H template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Euler; #endif #ifndef INCLUDED_IMATHFRUSTUM_H template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Frustum; #endif #ifndef INCLUDED_IMATHFRUSTUMTEST_H template <class T> class IMATH_EXPORT_TEMPLATE_TYPE FrustumTest; #endif #ifndef INCLUDED_IMATHINTERVAL_H template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Interval; #endif #ifndef INCLUDED_IMATHLINE_H template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Line3; #endif #ifndef INCLUDED_IMATHMATRIX_H template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Matrix33; template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Matrix44; #endif #ifndef INCLUDED_IMATHPLANE_H template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Plane3; #endif #ifndef INCLUDED_IMATHQUAT_H template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Quat; #endif #ifndef INCLUDED_IMATHSHEAR_H template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Shear6; #endif #ifndef INCLUDED_IMATHSPHERE_H template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Sphere3; #endif #ifndef INCLUDED_IMATHVEC_H template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Vec2; template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Vec3; template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Vec4; #endif #ifndef INCLUDED_IMATHRANDOM_H class IMATH_EXPORT_TYPE Rand32; class IMATH_EXPORT_TYPE Rand48; #endif /// @endcond IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHFORWARD_H ImathEuler.h 0000644 00000063734 15125213144 0006767 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // Euler angle representation of rotation/orientation // #ifndef INCLUDED_IMATHEULER_H #define INCLUDED_IMATHEULER_H #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathMath.h" #include "ImathMatrix.h" #include "ImathQuat.h" #include "ImathVec.h" #include <iostream> IMATH_INTERNAL_NAMESPACE_HEADER_ENTER #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER // Disable MS VC++ warnings about conversion from double to float # pragma warning(push) # pragma warning(disable : 4244) #endif /// /// Template class `Euler<T>` /// /// The Euler class represents euler angle orientations. The class /// inherits from Vec3 to it can be freely cast. The additional /// information is the euler priorities rep. This class is /// essentially a rip off of Ken Shoemake's GemsIV code. It has /// been modified minimally to make it more understandable, but /// hardly enough to make it easy to grok completely. /// /// There are 24 possible combonations of Euler angle /// representations of which 12 are common in CG and you will /// probably only use 6 of these which in this scheme are the /// non-relative-non-repeating types. /// /// The representations can be partitioned according to two /// criteria: /// /// 1) Are the angles measured relative to a set of fixed axis /// or relative to each other (the latter being what happens /// when rotation matrices are multiplied together and is /// almost ubiquitous in the cg community) /// /// 2) Is one of the rotations repeated (ala XYX rotation) /// /// When you construct a given representation from scratch you /// must order the angles according to their priorities. So, the /// easiest is a softimage or aerospace (yaw/pitch/roll) ordering /// of ZYX. /// /// float x_rot = 1; /// float y_rot = 2; /// float z_rot = 3; /// /// Eulerf angles(z_rot, y_rot, x_rot, Eulerf::ZYX); /// /// or: /// /// Eulerf angles( V3f(z_rot,y_rot,z_rot), Eulerf::ZYX ); /// /// /// If instead, the order was YXZ for instance you would have to /// do this: /// /// float x_rot = 1; /// float y_rot = 2; /// float z_rot = 3; /// /// Eulerf angles(y_rot, x_rot, z_rot, Eulerf::YXZ); /// /// or: /// /// /// Eulerf angles( V3f(y_rot,x_rot,z_rot), Eulerf::YXZ ); /// /// Notice how the order you put the angles into the three slots /// should correspond to the enum (YXZ) ordering. The input angle /// vector is called the "ijk" vector -- not an "xyz" vector. The /// ijk vector order is the same as the enum. If you treat the /// Euler as a Vec3 (which it inherts from) you will find the /// angles are ordered in the same way, i.e.: /// /// V3f v = angles; /// v.x == y_rot, v.y == x_rot, v.z == z_rot /// /// If you just want the x, y, and z angles stored in a vector in /// that order, you can do this: /// /// V3f v = angles.toXYZVector() /// v.x == x_rot, v.y == y_rot, v.z == z_rot /// /// If you want to set the Euler with an XYZVector use the /// optional layout argument: /// /// Eulerf angles(x_rot, y_rot, z_rot, Eulerf::YXZ, Eulerf::XYZLayout); /// /// This is the same as: /// /// Eulerf angles(y_rot, x_rot, z_rot, Eulerf::YXZ); /// /// Note that this won't do anything intelligent if you have a /// repeated axis in the euler angles (e.g. XYX) /// /// If you need to use the "relative" versions of these, you will /// need to use the "r" enums. /// /// The units of the rotation angles are assumed to be radians. /// template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Euler : public Vec3<T> { public: using Vec3<T>::x; using Vec3<T>::y; using Vec3<T>::z; /// /// All 24 possible orderings /// enum IMATH_EXPORT_ENUM Order { XYZ = 0x0101, // "usual" orderings XZY = 0x0001, YZX = 0x1101, YXZ = 0x1001, ZXY = 0x2101, ZYX = 0x2001, XZX = 0x0011, // first axis repeated XYX = 0x0111, YXY = 0x1011, YZY = 0x1111, ZYZ = 0x2011, ZXZ = 0x2111, XYZr = 0x2000, // relative orderings -- not common XZYr = 0x2100, YZXr = 0x1000, YXZr = 0x1100, ZXYr = 0x0000, ZYXr = 0x0100, XZXr = 0x2110, // relative first axis repeated XYXr = 0x2010, YXYr = 0x1110, YZYr = 0x1010, ZYZr = 0x0110, ZXZr = 0x0010, // |||| // VVVV // ABCD // Legend: // A -> Initial Axis (0==x, 1==y, 2==z) // B -> Parity Even (1==true) // C -> Initial Repeated (1==true) // D -> Frame Static (1==true) // Legal = XYZ | XZY | YZX | YXZ | ZXY | ZYX | XZX | XYX | YXY | YZY | ZYZ | ZXZ | XYZr | XZYr | YZXr | YXZr | ZXYr | ZYXr | XZXr | XYXr | YXYr | YZYr | ZYZr | ZXZr, Min = 0x0000, Max = 0x2111, Default = XYZ }; /// /// Axes /// enum IMATH_EXPORT_ENUM Axis { X = 0, Y = 1, Z = 2 }; /// /// Layout /// enum IMATH_EXPORT_ENUM InputLayout { XYZLayout, IJKLayout }; /// @{ /// @name Constructors /// /// All default to `ZYX` non-relative (ala Softimage 3D/Maya), /// where there is no argument to specify it. /// /// The Euler-from-matrix constructors assume that the matrix does /// not include shear or non-uniform scaling, but the constructors /// do not examine the matrix to verify this assumption. If necessary, /// you can adjust the matrix by calling the removeScalingAndShear() /// function, defined in ImathMatrixAlgo.h. /// No initialization by default IMATH_HOSTDEVICE constexpr Euler() IMATH_NOEXCEPT; /// Copy constructor IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Euler (const Euler&) IMATH_NOEXCEPT; /// Construct from given Order IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Euler (Order p) IMATH_NOEXCEPT; /// Construct from vector, order, layout IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Euler (const Vec3<T>& v, Order o = Default, InputLayout l = IJKLayout) IMATH_NOEXCEPT; /// Construct from explicit axes, order, layout IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Euler (T i, T j, T k, Order o = Default, InputLayout l = IJKLayout) IMATH_NOEXCEPT; /// Copy constructor with new Order IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Euler (const Euler<T>& euler, Order newp) IMATH_NOEXCEPT; /// Construct from Matrix33 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Euler (const Matrix33<T>&, Order o = Default) IMATH_NOEXCEPT; /// Construct from Matrix44 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Euler (const Matrix44<T>&, Order o = Default) IMATH_NOEXCEPT; /// Destructor ~Euler() = default; /// @} /// @{ /// @name Query /// Return whether the given value is a legal Order IMATH_HOSTDEVICE constexpr static bool legal (Order) IMATH_NOEXCEPT; /// Return the order IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Order order() const IMATH_NOEXCEPT; /// Return frameStatic IMATH_HOSTDEVICE constexpr bool frameStatic() const { return _frameStatic; } /// Return intialRepeated IMATH_HOSTDEVICE constexpr bool initialRepeated() const { return _initialRepeated; } /// Return partityEven IMATH_HOSTDEVICE constexpr bool parityEven() const { return _parityEven; } /// Return initialAxis IMATH_HOSTDEVICE constexpr Axis initialAxis() const { return _initialAxis; } /// Unpack angles from ijk form IMATH_HOSTDEVICE void angleOrder (int& i, int& j, int& k) const IMATH_NOEXCEPT; /// Determine mapping from xyz to ijk (reshuffle the xyz to match the order) IMATH_HOSTDEVICE void angleMapping (int& i, int& j, int& k) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Set Value /// Set the order. This does NOT convert the angles, but it /// does reorder the input vector. IMATH_HOSTDEVICE void setOrder (Order) IMATH_NOEXCEPT; /// Set the euler value: set the first angle to `v[0]`, the second to /// `v[1]`, the third to `v[2]`. IMATH_HOSTDEVICE void setXYZVector (const Vec3<T>&) IMATH_NOEXCEPT; /// Set the value. IMATH_HOSTDEVICE void set (Axis initial, bool relative, bool parityEven, bool firstRepeats) IMATH_NOEXCEPT; /// @} /// @{ /// @name Assignments and Conversions /// /// Assignment IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Euler<T>& operator= (const Euler<T>&) IMATH_NOEXCEPT; /// Assignment IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Euler<T>& operator= (const Vec3<T>&) IMATH_NOEXCEPT; /// Assign from Matrix33, assumed to be affine IMATH_HOSTDEVICE void extract (const Matrix33<T>&) IMATH_NOEXCEPT; /// Assign from Matrix44, assumed to be affine IMATH_HOSTDEVICE void extract (const Matrix44<T>&) IMATH_NOEXCEPT; /// Assign from Quaternion IMATH_HOSTDEVICE void extract (const Quat<T>&) IMATH_NOEXCEPT; /// Convert to Matrix33 IMATH_HOSTDEVICE Matrix33<T> toMatrix33() const IMATH_NOEXCEPT; /// Convert to Matrix44 IMATH_HOSTDEVICE Matrix44<T> toMatrix44() const IMATH_NOEXCEPT; /// Convert to Quat IMATH_HOSTDEVICE Quat<T> toQuat() const IMATH_NOEXCEPT; /// Reorder the angles so that the X rotation comes first, /// followed by the Y and Z in cases like XYX ordering, the /// repeated angle will be in the "z" component IMATH_HOSTDEVICE Vec3<T> toXYZVector() const IMATH_NOEXCEPT; /// @} /// @{ /// @name Utility Methods /// /// Utility methods for getting continuous rotations. None of these /// methods change the orientation given by its inputs (or at least /// that is the intent). /// Convert an angle to its equivalent in [-PI, PI] IMATH_HOSTDEVICE IMATH_CONSTEXPR14 static float angleMod (T angle) IMATH_NOEXCEPT; /// Adjust xyzRot so that its components differ from targetXyzRot by no more than +/-PI IMATH_HOSTDEVICE static void simpleXYZRotation (Vec3<T>& xyzRot, const Vec3<T>& targetXyzRot) IMATH_NOEXCEPT; /// Adjust xyzRot so that its components differ from targetXyzRot by as little as possible. /// Note that xyz here really means ijk, because the order must be provided. IMATH_HOSTDEVICE static void nearestRotation (Vec3<T>& xyzRot, const Vec3<T>& targetXyzRot, Order order = XYZ) IMATH_NOEXCEPT; /// Adjusts "this" Euler so that its components differ from target /// by as little as possible. This method might not make sense for /// Eulers with different order and it probably doesn't work for /// repeated axis and relative orderings (TODO). IMATH_HOSTDEVICE void makeNear (const Euler<T>& target) IMATH_NOEXCEPT; /// @} protected: /// relative or static rotations bool _frameStatic : 1; /// init axis repeated as last bool _initialRepeated : 1; /// "parity of axis permutation" bool _parityEven : 1; #if defined _WIN32 || defined _WIN64 /// First axis of rotation Axis _initialAxis; #else /// First axis of rotation Axis _initialAxis : 2; #endif }; // // Convenient typedefs // /// Euler of type float typedef Euler<float> Eulerf; /// Euler of type double typedef Euler<double> Eulerd; // // Implementation // /// @cond Doxygen_Suppress template <class T> inline void Euler<T>::angleOrder (int& i, int& j, int& k) const IMATH_NOEXCEPT { i = _initialAxis; j = _parityEven ? (i + 1) % 3 : (i > 0 ? i - 1 : 2); k = _parityEven ? (i > 0 ? i - 1 : 2) : (i + 1) % 3; } template <class T> inline void Euler<T>::angleMapping (int& i, int& j, int& k) const IMATH_NOEXCEPT { int m[3]; m[_initialAxis] = 0; m[(_initialAxis + 1) % 3] = _parityEven ? 1 : 2; m[(_initialAxis + 2) % 3] = _parityEven ? 2 : 1; i = m[0]; j = m[1]; k = m[2]; } template <class T> inline void Euler<T>::setXYZVector (const Vec3<T>& v) IMATH_NOEXCEPT { int i, j, k; angleMapping (i, j, k); (*this)[i] = v.x; (*this)[j] = v.y; (*this)[k] = v.z; } template <class T> inline Vec3<T> Euler<T>::toXYZVector() const IMATH_NOEXCEPT { int i, j, k; angleMapping (i, j, k); return Vec3<T> ((*this)[i], (*this)[j], (*this)[k]); } template <class T> constexpr inline Euler<T>::Euler() IMATH_NOEXCEPT : Vec3<T> (0, 0, 0), _frameStatic (true), _initialRepeated (false), _parityEven (true), _initialAxis (X) {} template <class T> IMATH_CONSTEXPR14 inline Euler<T>::Euler (typename Euler<T>::Order p) IMATH_NOEXCEPT : Vec3<T> (0, 0, 0), _frameStatic (true), _initialRepeated (false), _parityEven (true), _initialAxis (X) { setOrder (p); } template <class T> IMATH_CONSTEXPR14 inline Euler<T>::Euler (const Vec3<T>& v, typename Euler<T>::Order p, typename Euler<T>::InputLayout l) IMATH_NOEXCEPT { setOrder (p); if (l == XYZLayout) setXYZVector (v); else { x = v.x; y = v.y; z = v.z; } } template <class T> IMATH_CONSTEXPR14 inline Euler<T>::Euler (const Euler<T>& euler) IMATH_NOEXCEPT { operator= (euler); } template <class T> IMATH_CONSTEXPR14 inline Euler<T>::Euler (const Euler<T>& euler, Order p) IMATH_NOEXCEPT { setOrder (p); Matrix33<T> M = euler.toMatrix33(); extract (M); } template <class T> IMATH_CONSTEXPR14 inline Euler<T>::Euler (T xi, T yi, T zi, typename Euler<T>::Order p, typename Euler<T>::InputLayout l) IMATH_NOEXCEPT { setOrder (p); if (l == XYZLayout) setXYZVector (Vec3<T> (xi, yi, zi)); else { x = xi; y = yi; z = zi; } } template <class T> IMATH_CONSTEXPR14 inline Euler<T>::Euler (const Matrix33<T>& M, typename Euler::Order p) IMATH_NOEXCEPT { setOrder (p); extract (M); } template <class T> IMATH_CONSTEXPR14 inline Euler<T>::Euler (const Matrix44<T>& M, typename Euler::Order p) IMATH_NOEXCEPT { setOrder (p); extract (M); } template <class T> inline void Euler<T>::extract (const Quat<T>& q) IMATH_NOEXCEPT { extract (q.toMatrix33()); } template <class T> void Euler<T>::extract (const Matrix33<T>& M) IMATH_NOEXCEPT { int i, j, k; angleOrder (i, j, k); if (_initialRepeated) { // // Extract the first angle, x. // x = std::atan2 (M[j][i], M[k][i]); // // Remove the x rotation from M, so that the remaining // rotation, N, is only around two axes, and gimbal lock // cannot occur. // Vec3<T> r (0, 0, 0); r[i] = (_parityEven ? -x : x); Matrix44<T> N; N.rotate (r); N = N * Matrix44<T> (M[0][0], M[0][1], M[0][2], 0, M[1][0], M[1][1], M[1][2], 0, M[2][0], M[2][1], M[2][2], 0, 0, 0, 0, 1); // // Extract the other two angles, y and z, from N. // T sy = std::sqrt (N[j][i] * N[j][i] + N[k][i] * N[k][i]); y = std::atan2 (sy, N[i][i]); z = std::atan2 (N[j][k], N[j][j]); } else { // // Extract the first angle, x. // x = std::atan2 (M[j][k], M[k][k]); // // Remove the x rotation from M, so that the remaining // rotation, N, is only around two axes, and gimbal lock // cannot occur. // Vec3<T> r (0, 0, 0); r[i] = (_parityEven ? -x : x); Matrix44<T> N; N.rotate (r); N = N * Matrix44<T> (M[0][0], M[0][1], M[0][2], 0, M[1][0], M[1][1], M[1][2], 0, M[2][0], M[2][1], M[2][2], 0, 0, 0, 0, 1); // // Extract the other two angles, y and z, from N. // T cy = std::sqrt (N[i][i] * N[i][i] + N[i][j] * N[i][j]); y = std::atan2 (-N[i][k], cy); z = std::atan2 (-N[j][i], N[j][j]); } if (!_parityEven) *this *= -1; if (!_frameStatic) { T t = x; x = z; z = t; } } template <class T> void Euler<T>::extract (const Matrix44<T>& M) IMATH_NOEXCEPT { int i, j, k; angleOrder (i, j, k); if (_initialRepeated) { // // Extract the first angle, x. // x = std::atan2 (M[j][i], M[k][i]); // // Remove the x rotation from M, so that the remaining // rotation, N, is only around two axes, and gimbal lock // cannot occur. // Vec3<T> r (0, 0, 0); r[i] = (_parityEven ? -x : x); Matrix44<T> N; N.rotate (r); N = N * M; // // Extract the other two angles, y and z, from N. // T sy = std::sqrt (N[j][i] * N[j][i] + N[k][i] * N[k][i]); y = std::atan2 (sy, N[i][i]); z = std::atan2 (N[j][k], N[j][j]); } else { // // Extract the first angle, x. // x = std::atan2 (M[j][k], M[k][k]); // // Remove the x rotation from M, so that the remaining // rotation, N, is only around two axes, and gimbal lock // cannot occur. // Vec3<T> r (0, 0, 0); r[i] = (_parityEven ? -x : x); Matrix44<T> N; N.rotate (r); N = N * M; // // Extract the other two angles, y and z, from N. // T cy = std::sqrt (N[i][i] * N[i][i] + N[i][j] * N[i][j]); y = std::atan2 (-N[i][k], cy); z = std::atan2 (-N[j][i], N[j][j]); } if (!_parityEven) *this *= -1; if (!_frameStatic) { T t = x; x = z; z = t; } } template <class T> Matrix33<T> Euler<T>::toMatrix33() const IMATH_NOEXCEPT { int i, j, k; angleOrder (i, j, k); Vec3<T> angles; if (_frameStatic) angles = (*this); else angles = Vec3<T> (z, y, x); if (!_parityEven) angles *= -1.0; T ci = std::cos (angles.x); T cj = std::cos (angles.y); T ch = std::cos (angles.z); T si = std::sin (angles.x); T sj = std::sin (angles.y); T sh = std::sin (angles.z); T cc = ci * ch; T cs = ci * sh; T sc = si * ch; T ss = si * sh; Matrix33<T> M; if (_initialRepeated) { M[i][i] = cj; M[j][i] = sj * si; M[k][i] = sj * ci; M[i][j] = sj * sh; M[j][j] = -cj * ss + cc; M[k][j] = -cj * cs - sc; M[i][k] = -sj * ch; M[j][k] = cj * sc + cs; M[k][k] = cj * cc - ss; } else { M[i][i] = cj * ch; M[j][i] = sj * sc - cs; M[k][i] = sj * cc + ss; M[i][j] = cj * sh; M[j][j] = sj * ss + cc; M[k][j] = sj * cs - sc; M[i][k] = -sj; M[j][k] = cj * si; M[k][k] = cj * ci; } return M; } template <class T> Matrix44<T> Euler<T>::toMatrix44() const IMATH_NOEXCEPT { int i, j, k; angleOrder (i, j, k); Vec3<T> angles; if (_frameStatic) angles = (*this); else angles = Vec3<T> (z, y, x); if (!_parityEven) angles *= -1.0; T ci = std::cos (angles.x); T cj = std::cos (angles.y); T ch = std::cos (angles.z); T si = std::sin (angles.x); T sj = std::sin (angles.y); T sh = std::sin (angles.z); T cc = ci * ch; T cs = ci * sh; T sc = si * ch; T ss = si * sh; Matrix44<T> M; if (_initialRepeated) { M[i][i] = cj; M[j][i] = sj * si; M[k][i] = sj * ci; M[i][j] = sj * sh; M[j][j] = -cj * ss + cc; M[k][j] = -cj * cs - sc; M[i][k] = -sj * ch; M[j][k] = cj * sc + cs; M[k][k] = cj * cc - ss; } else { M[i][i] = cj * ch; M[j][i] = sj * sc - cs; M[k][i] = sj * cc + ss; M[i][j] = cj * sh; M[j][j] = sj * ss + cc; M[k][j] = sj * cs - sc; M[i][k] = -sj; M[j][k] = cj * si; M[k][k] = cj * ci; } return M; } template <class T> Quat<T> Euler<T>::toQuat() const IMATH_NOEXCEPT { Vec3<T> angles; int i, j, k; angleOrder (i, j, k); if (_frameStatic) angles = (*this); else angles = Vec3<T> (z, y, x); if (!_parityEven) angles.y = -angles.y; T ti = angles.x * 0.5; T tj = angles.y * 0.5; T th = angles.z * 0.5; T ci = std::cos (ti); T cj = std::cos (tj); T ch = std::cos (th); T si = std::sin (ti); T sj = std::sin (tj); T sh = std::sin (th); T cc = ci * ch; T cs = ci * sh; T sc = si * ch; T ss = si * sh; T parity = _parityEven ? 1.0 : -1.0; Quat<T> q; Vec3<T> a; if (_initialRepeated) { a[i] = cj * (cs + sc); a[j] = sj * (cc + ss) * parity, // NOSONAR - suppress SonarCloud bug report. a[k] = sj * (cs - sc); q.r = cj * (cc - ss); } else { a[i] = cj * sc - sj * cs, a[j] = (cj * ss + sj * cc) * parity, // NOSONAR - suppress SonarCloud bug report. a[k] = cj * cs - sj * sc; q.r = cj * cc + sj * ss; } q.v = a; return q; } template <class T> constexpr inline bool Euler<T>::legal (typename Euler<T>::Order order) IMATH_NOEXCEPT { return (order & ~Legal) ? false : true; } template <class T> IMATH_CONSTEXPR14 typename Euler<T>::Order Euler<T>::order() const IMATH_NOEXCEPT { int foo = (_initialAxis == Z ? 0x2000 : (_initialAxis == Y ? 0x1000 : 0)); if (_parityEven) foo |= 0x0100; if (_initialRepeated) foo |= 0x0010; if (_frameStatic) foo++; return (Order) foo; } template <class T> inline void Euler<T>::setOrder (typename Euler<T>::Order p) IMATH_NOEXCEPT { set (p & 0x2000 ? Z : (p & 0x1000 ? Y : X), // initial axis !(p & 0x1), // static? !!(p & 0x100), // permutation even? !!(p & 0x10)); // initial repeats? } template <class T> inline void Euler<T>::set (typename Euler<T>::Axis axis, bool relative, bool parityEven, bool firstRepeats) IMATH_NOEXCEPT { _initialAxis = axis; _frameStatic = !relative; _parityEven = parityEven; _initialRepeated = firstRepeats; } template <class T> IMATH_CONSTEXPR14 inline const Euler<T>& Euler<T>::operator= (const Euler<T>& euler) IMATH_NOEXCEPT { x = euler.x; y = euler.y; z = euler.z; _initialAxis = euler._initialAxis; _frameStatic = euler._frameStatic; _parityEven = euler._parityEven; _initialRepeated = euler._initialRepeated; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Euler<T>& Euler<T>::operator= (const Vec3<T>& v) IMATH_NOEXCEPT { x = v.x; y = v.y; z = v.z; return *this; } template <class T> IMATH_CONSTEXPR14 inline float Euler<T>::angleMod (T angle) IMATH_NOEXCEPT { const T pi = static_cast<T> (M_PI); angle = fmod (T (angle), T (2 * pi)); if (angle < -pi) angle += 2 * pi; if (angle > +pi) angle -= 2 * pi; return angle; } template <class T> inline void Euler<T>::simpleXYZRotation (Vec3<T>& xyzRot, const Vec3<T>& targetXyzRot) IMATH_NOEXCEPT { Vec3<T> d = xyzRot - targetXyzRot; xyzRot[0] = targetXyzRot[0] + angleMod (d[0]); xyzRot[1] = targetXyzRot[1] + angleMod (d[1]); xyzRot[2] = targetXyzRot[2] + angleMod (d[2]); } template <class T> void Euler<T>::nearestRotation (Vec3<T>& xyzRot, const Vec3<T>& targetXyzRot, Order order) IMATH_NOEXCEPT { int i, j, k; Euler<T> e (0, 0, 0, order); e.angleOrder (i, j, k); simpleXYZRotation (xyzRot, targetXyzRot); Vec3<T> otherXyzRot; otherXyzRot[i] = M_PI + xyzRot[i]; otherXyzRot[j] = M_PI - xyzRot[j]; otherXyzRot[k] = M_PI + xyzRot[k]; simpleXYZRotation (otherXyzRot, targetXyzRot); Vec3<T> d = xyzRot - targetXyzRot; Vec3<T> od = otherXyzRot - targetXyzRot; T dMag = d.dot (d); T odMag = od.dot (od); if (odMag < dMag) { xyzRot = otherXyzRot; } } template <class T> void Euler<T>::makeNear (const Euler<T>& target) IMATH_NOEXCEPT { Vec3<T> xyzRot = toXYZVector(); Vec3<T> targetXyz; if (order() != target.order()) { Euler<T> targetSameOrder = Euler<T> (target, order()); targetXyz = targetSameOrder.toXYZVector(); } else { targetXyz = target.toXYZVector(); } nearestRotation (xyzRot, targetXyz, order()); setXYZVector (xyzRot); } /// @endcond /// Stream ouput, as "(x y z i j k)" template <class T> std::ostream& operator<< (std::ostream& o, const Euler<T>& euler) { char a[3] = { 'X', 'Y', 'Z' }; const char* r = euler.frameStatic() ? "" : "r"; int i, j, k; euler.angleOrder (i, j, k); if (euler.initialRepeated()) k = i; return o << "(" << euler.x << " " << euler.y << " " << euler.z << " " << a[i] << a[j] << a[k] << r << ")"; } #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER # pragma warning(pop) #endif IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHEULER_H PyImathVec.h 0000644 00000042462 15125213144 0006734 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathVec_h_ #define _PyImathVec_h_ #include <Python.h> #include <boost/python.hpp> #include <ImathVec.h> #include "PyImath.h" #include "PyImathFixedArray.h" namespace PyImath { template <class T> boost::python::class_<IMATH_NAMESPACE::Vec2<T> > register_Vec2(); template <class T> boost::python::class_<FixedArray<IMATH_NAMESPACE::Vec2<T> > > register_Vec2Array(); typedef FixedArray<IMATH_NAMESPACE::V2s> V2sArray; typedef FixedArray<IMATH_NAMESPACE::V2i> V2iArray; typedef FixedArray<IMATH_NAMESPACE::V2i64> V2i64Array; typedef FixedArray<IMATH_NAMESPACE::V2f> V2fArray; typedef FixedArray<IMATH_NAMESPACE::V2d> V2dArray; // TODO: template <class T> class Vec2Array : public FixedArray<IMATH_NAMESPACE::Vec2<T> > } // define vector*float array multiplication template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec2<T> > operator * (const PyImath::FixedArray<IMATH_NAMESPACE::Vec2<T> > &a0, T v1) { PY_IMATH_LEAVE_PYTHON; size_t len = a0.len(); PyImath::FixedArray<IMATH_NAMESPACE::Vec2<T> > f(len); for (size_t i=0;i<len;++i) f[i]=a0[i]*v1; return f; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec2<T> > operator * (T v0, const PyImath::FixedArray<IMATH_NAMESPACE::Vec2<T> > &a1) { return a1*v0; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec2<T> > operator * (const PyImath::FixedArray<IMATH_NAMESPACE::Vec2<T> > &a0, const PyImath::FixedArray<T> &a1) { PY_IMATH_LEAVE_PYTHON; size_t len = a0.match_dimension(a1); PyImath::FixedArray<IMATH_NAMESPACE::Vec2<T> > f(len); for (size_t i=0;i<len;++i) f[i]=a0[i]*a1[i]; return f; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec2<T> > operator * (const PyImath::FixedArray<T> &a0, const PyImath::FixedArray<IMATH_NAMESPACE::Vec2<T> > &a1) { return a1*a0; } // define vector/float array division template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec2<T> > operator / (const PyImath::FixedArray<IMATH_NAMESPACE::Vec2<T> > &a0, T v1) { PY_IMATH_LEAVE_PYTHON; size_t len = a0.len(); PyImath::FixedArray<IMATH_NAMESPACE::Vec2<T> > f(len); for (size_t i=0;i<len;++i) f[i]=a0[i]/v1; return f; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec2<T> > operator / (const PyImath::FixedArray<IMATH_NAMESPACE::Vec2<T> > &a0, const PyImath::FixedArray<T> &a1) { PY_IMATH_LEAVE_PYTHON; size_t len = a0.match_dimension(a1); PyImath::FixedArray<IMATH_NAMESPACE::Vec2<T> > f(len); for (size_t i=0;i<len;++i) f[i]=a0[i]/a1[i]; return f; } namespace PyImath { template <class T> boost::python::class_<IMATH_NAMESPACE::Vec3<T> > register_Vec3(); template <class T> boost::python::class_<FixedArray<IMATH_NAMESPACE::Vec3<T> > > register_Vec3Array(); typedef FixedArray<IMATH_NAMESPACE::Vec3<unsigned char> > V3cArray; typedef FixedArray<IMATH_NAMESPACE::V3s> V3sArray; typedef FixedArray<IMATH_NAMESPACE::V3i> V3iArray; typedef FixedArray<IMATH_NAMESPACE::V3i64> V3i64Array; typedef FixedArray<IMATH_NAMESPACE::V3f> V3fArray; typedef FixedArray<IMATH_NAMESPACE::V3d> V3dArray; // TODO: template <class T> class Vec3Array : public FixedArray<IMATH_NAMESPACE::Vec3<T> > } // define vector*float array multiplication template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > operator * (const PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > &a0, T v1) { PY_IMATH_LEAVE_PYTHON; size_t len = a0.len(); PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > f(len); for (size_t i=0;i<len;++i) f[i]=a0[i]*v1; return f; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > operator * (T v0, const PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > &a1) { return a1*v0; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > operator * (const PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > &a0, const PyImath::FixedArray<T> &a1) { PY_IMATH_LEAVE_PYTHON; size_t len = a0.match_dimension(a1); PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > f(len); for (size_t i=0;i<len;++i) f[i]=a0[i]*a1[i]; return f; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > operator * (const PyImath::FixedArray<T> &a0, const PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > &a1) { return a1*a0; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > operator * (const PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > &va, const IMATH_NAMESPACE::M44f &m) { PY_IMATH_LEAVE_PYTHON; size_t len = va.len(); PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > f(len); for (size_t i = 0; i < len; ++i) f[i] = va[i] * m; return f; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > operator * (const PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > &va, const IMATH_NAMESPACE::M44d &m) { PY_IMATH_LEAVE_PYTHON; size_t len = va.len(); PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > f(len); for (size_t i = 0; i < len; ++i) f[i] = va[i] * m; return f; } // define vector/float array division template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > operator / (const PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > &a0, T v1) { PY_IMATH_LEAVE_PYTHON; size_t len = a0.len(); PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > f(len); for (size_t i=0;i<len;++i) f[i]=a0[i]/v1; return f; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > operator / (const PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > &a0, const PyImath::FixedArray<T> &a1) { PY_IMATH_LEAVE_PYTHON; size_t len = a0.match_dimension(a1); PyImath::FixedArray<IMATH_NAMESPACE::Vec3<T> > f(len); for (size_t i=0;i<len;++i) f[i]=a0[i]/a1[i]; return f; } namespace PyImath { template <class T> boost::python::class_<IMATH_NAMESPACE::Vec4<T> > register_Vec4(); template <class T> boost::python::class_<PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > > register_Vec4Array(); typedef FixedArray<IMATH_NAMESPACE::Vec4<unsigned char> > V4cArray; typedef FixedArray<IMATH_NAMESPACE::V4s> V4sArray; typedef FixedArray<IMATH_NAMESPACE::V4i> V4iArray; typedef FixedArray<IMATH_NAMESPACE::V4i64> V4i64Array; typedef FixedArray<IMATH_NAMESPACE::V4f> V4fArray; typedef FixedArray<IMATH_NAMESPACE::V4d> V4dArray; // TODO: template <class T> class Vec3Array : public FixedArray<IMATH_NAMESPACE::Vec3<T> > } // define vector*float array multiplication template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > operator * (const PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > &a0, T v1) { PY_IMATH_LEAVE_PYTHON; size_t len = a0.len(); PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > f(len); for (size_t i=0;i<len;++i) f[i]=a0[i]*v1; return f; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > operator * (T v0, const PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > &a1) { return a1*v0; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > operator * (const PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > &a0, const PyImath::FixedArray<T> &a1) { PY_IMATH_LEAVE_PYTHON; size_t len = a0.match_dimension(a1); PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > f(len); for (size_t i=0;i<len;++i) f[i]=a0[i]*a1[i]; return f; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > operator * (const PyImath::FixedArray<T> &a0, const PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > &a1) { return a1*a0; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > operator * (const PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > &va, const IMATH_NAMESPACE::M44f &m) { PY_IMATH_LEAVE_PYTHON; size_t len = va.len(); PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > f(len); for (size_t i = 0; i < len; ++i) f[i] = va[i] * m; return f; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > operator * (const PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > &va, const IMATH_NAMESPACE::M44d &m) { PY_IMATH_LEAVE_PYTHON; size_t len = va.len(); PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > f(len); for (size_t i = 0; i < len; ++i) f[i] = va[i] * m; return f; } // define vector/float array division template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > operator / (const PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > &a0, T v1) { PY_IMATH_LEAVE_PYTHON; size_t len = a0.len(); PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > f(len); for (size_t i=0;i<len;++i) f[i]=a0[i]/v1; return f; } template <class T> static PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > operator / (const PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > &a0, const PyImath::FixedArray<T> &a1) { PY_IMATH_LEAVE_PYTHON; size_t len = a0.match_dimension(a1); PyImath::FixedArray<IMATH_NAMESPACE::Vec4<T> > f(len); for (size_t i=0;i<len;++i) f[i]=a0[i]/a1[i]; return f; } // namespace PyImath { // Other code in the Zeno code base assumes the existance of a class with the // same name as the Imath class, and with static functions wrap() and // convert() to produce a PyImath object from an Imath object and vice-versa, // respectively. The class Boost generates from the Imath class does not // have these properties, so we define a companion class here. // The template argument, T, is the element type for the vector (e.g., int, // float, double). template <class T> class V2 { public: static PyObject * wrap (const IMATH_NAMESPACE::Vec2<T> &v); static int convert (PyObject *p, IMATH_NAMESPACE::Vec2<T> *v); }; template <class T> class V3 { public: static PyObject * wrap (const IMATH_NAMESPACE::Vec3<T> &v); static int convert (PyObject *p, IMATH_NAMESPACE::Vec3<T> *v); }; template <class T> class V4 { public: static PyObject * wrap (const IMATH_NAMESPACE::Vec4<T> &v); static int convert (PyObject *p, IMATH_NAMESPACE::Vec4<T> *v); }; template <class T> PyObject * V2<T>::wrap (const IMATH_NAMESPACE::Vec2<T> &v) { typename boost::python::return_by_value::apply < IMATH_NAMESPACE::Vec2<T> >::type converter; PyObject *p = converter (v); return p; } template <class T> PyObject * V3<T>::wrap (const IMATH_NAMESPACE::Vec3<T> &v) { typename boost::python::return_by_value::apply < IMATH_NAMESPACE::Vec3<T> >::type converter; PyObject *p = converter (v); return p; } template <class T> PyObject * V4<T>::wrap (const IMATH_NAMESPACE::Vec4<T> &v) { typename boost::python::return_by_value::apply < IMATH_NAMESPACE::Vec4<T> >::type converter; PyObject *p = converter (v); return p; } template <class T> int V2<T>::convert (PyObject *p, IMATH_NAMESPACE::Vec2<T> *v) { boost::python::extract <IMATH_NAMESPACE::V2i> extractorV2i (p); if (extractorV2i.check()) { IMATH_NAMESPACE::V2i v2i = extractorV2i(); v->setValue (T(v2i[0]), T(v2i[1])); return 1; } boost::python::extract <IMATH_NAMESPACE::V2i64> extractorV2i64 (p); if (extractorV2i64.check()) { IMATH_NAMESPACE::V2i64 v2i64 = extractorV2i64(); v->setValue (T(v2i64[0]), T(v2i64[1])); return 1; } boost::python::extract <IMATH_NAMESPACE::V2f> extractorV2f (p); if (extractorV2f.check()) { IMATH_NAMESPACE::V2f v2f = extractorV2f(); v->setValue (T(v2f[0]), T(v2f[1])); return 1; } boost::python::extract <IMATH_NAMESPACE::V2d> extractorV2d (p); if (extractorV2d.check()) { IMATH_NAMESPACE::V2d v2d = extractorV2d(); v->setValue (T(v2d[0]), T(v2d[1])); return 1; } boost::python::extract <boost::python::tuple> extractorTuple (p); if (extractorTuple.check()) { boost::python::tuple t = extractorTuple(); if (t.attr ("__len__") () == 2) { // Extracting the tuple elements as doubles and casting them to // Ts in setValue() works better than extracting them as Ts from // the start. Extracting them as Ts can fail in certain // circumstances if T is int and the tuples elemnts are floats. // In particular, this kind of failure occurs in PyImathBox.h, // when Box2<int>::convert() is passed a tuple of two tuples of // floats. double a = boost::python::extract <double> (t[0]); double b = boost::python::extract <double> (t[1]); v->setValue (T(a), T(b)); return 1; } } boost::python::extract <boost::python::list> extractorList (p); if (extractorList.check()) { boost::python::list l = extractorList(); if (l.attr ("__len__") () == 2) { boost::python::extract <double> extractor0 (l[0]); boost::python::extract <double> extractor1 (l[1]); if (extractor0.check() && extractor1.check()) { v->setValue (T(extractor0()), T(extractor1())); return 1; } } } return 0; } template <class T> int V3<T>::convert (PyObject *p, IMATH_NAMESPACE::Vec3<T> *v) { boost::python::extract <IMATH_NAMESPACE::V3i> extractorV3i (p); if (extractorV3i.check()) { IMATH_NAMESPACE::V3i v3i = extractorV3i(); v->setValue (T(v3i[0]), T(v3i[1]), T(v3i[2])); return 1; } boost::python::extract <IMATH_NAMESPACE::V3i64> extractorV3i64 (p); if (extractorV3i64.check()) { IMATH_NAMESPACE::V3i64 v3i64 = extractorV3i64(); v->setValue (T(v3i64[0]), T(v3i64[1]), T(v3i64[2])); return 1; } boost::python::extract <IMATH_NAMESPACE::V3f> extractorV3f (p); if (extractorV3f.check()) { IMATH_NAMESPACE::V3f v3f = extractorV3f(); v->setValue (T(v3f[0]), T(v3f[1]), T(v3f[2])); return 1; } boost::python::extract <IMATH_NAMESPACE::V3d> extractorV3d (p); if (extractorV3d.check()) { IMATH_NAMESPACE::V3d v3d = extractorV3d(); v->setValue (T(v3d[0]), T(v3d[1]), T(v3d[2])); return 1; } boost::python::extract <boost::python::tuple> extractorTuple (p); if (extractorTuple.check()) { boost::python::tuple t = extractorTuple(); if (t.attr ("__len__") () == 3) { // See the comment in V2<T>::convert(). double a = boost::python::extract <double> (t[0]); double b = boost::python::extract <double> (t[1]); double c = boost::python::extract <double> (t[2]); v->setValue (T(a), T(b), T(c)); return 1; } } boost::python::extract <boost::python::list> extractorList (p); if (extractorList.check()) { boost::python::list l = extractorList(); if (l.attr ("__len__") () == 3) { boost::python::extract <double> extractor0 (l[0]); boost::python::extract <double> extractor1 (l[1]); boost::python::extract <double> extractor2 (l[2]); if (extractor0.check() && extractor1.check() && extractor2.check()) { v->setValue (T(extractor0()), T(extractor1()), T(extractor2())); return 1; } } } return 0; } template <class T> int V4<T>::convert (PyObject *p, IMATH_NAMESPACE::Vec4<T> *v) { boost::python::extract <IMATH_NAMESPACE::V4i> extractorV4i (p); if (extractorV4i.check()) { IMATH_NAMESPACE::V4i v4i = extractorV4i(); *v = IMATH_NAMESPACE::Vec4<T>(v4i); return 1; } boost::python::extract <IMATH_NAMESPACE::V4f> extractorV4f (p); if (extractorV4f.check()) { IMATH_NAMESPACE::V4f v4f = extractorV4f(); *v = IMATH_NAMESPACE::Vec4<T>(v4f); return 1; } boost::python::extract <IMATH_NAMESPACE::V4d> extractorV4d (p); if (extractorV4d.check()) { IMATH_NAMESPACE::V4d v4d = extractorV4d(); *v = IMATH_NAMESPACE::Vec4<T>(v4d); return 1; } boost::python::extract <boost::python::tuple> extractorTuple (p); if (extractorTuple.check()) { boost::python::tuple t = extractorTuple(); if (t.attr ("__len__") () == 4) { // See the comment in V2<T>::convert(). double a = boost::python::extract <double> (t[0]); double b = boost::python::extract <double> (t[1]); double c = boost::python::extract <double> (t[2]); double d = boost::python::extract <double> (t[3]); *v = IMATH_NAMESPACE::Vec4<T>(T(a), T(b), T(c), T(d)); return 1; } } boost::python::extract <boost::python::list> extractorList (p); if (extractorList.check()) { boost::python::list l = extractorList(); if (l.attr ("__len__") () == 4) { boost::python::extract <double> extractor0 (l[0]); boost::python::extract <double> extractor1 (l[1]); boost::python::extract <double> extractor2 (l[2]); boost::python::extract <double> extractor3 (l[3]); if (extractor0.check() && extractor1.check() && extractor2.check() && extractor3.check()) { *v = IMATH_NAMESPACE::Vec4<T>(T(extractor0()), T(extractor1()), T(extractor2()), T(extractor3())); return 1; } } } return 0; } typedef V2<int> V2i; typedef V2<float> V2f; typedef V2<double> V2d; typedef V3<int> V3i; typedef V3<float> V3f; typedef V3<double> V3d; typedef V4<int> V4i; typedef V4<float> V4f; typedef V4<double> V4d; } #endif PyImathAutovectorize.h 0000644 00000360204 15125213144 0011057 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathAutovectorize_h_ #define _PyImathAutovectorize_h_ #include <Python.h> #include <boost/python.hpp> #include <boost/mpl/size.hpp> #include <boost/mpl/pop_front.hpp> #include <boost/mpl/push_front.hpp> #include <boost/mpl/front.hpp> #include <boost/mpl/eval_if.hpp> #include <boost/mpl/bool.hpp> #include <boost/mpl/vector.hpp> #include <boost/mpl/transform.hpp> #include <boost/mpl/remove_if.hpp> #include <boost/mpl/equal.hpp> #include <boost/mpl/for_each.hpp> #include <boost/mpl/not.hpp> #include <boost/mpl/count.hpp> #include <boost/mpl/or.hpp> #include <boost/type_traits/is_base_of.hpp> #include <boost/type_traits/function_traits.hpp> #include <boost/static_assert.hpp> #include <boost/python/args.hpp> #include <iostream> #include "PyImathFixedArray.h" #include "PyImathTask.h" #include "PyImathUtil.h" namespace PyImath { struct op_with_precomputation {}; namespace detail { using boost::is_base_of; using boost::is_same; using boost::is_const; using boost::remove_const; using boost::remove_reference; using boost::function_traits; using boost::mpl::at; using boost::mpl::at_c; using boost::mpl::push_front; using boost::mpl::vector; using boost::mpl::push_back; using boost::mpl::transform; using boost::mpl::fold; using boost::mpl::_; using boost::mpl::_1; using boost::mpl::_2; using boost::mpl::long_; using boost::mpl::false_; using boost::mpl::true_; using boost::mpl::not_; using boost::mpl::or_; using boost::mpl::and_; using boost::mpl::size; using boost::mpl::remove_if; using boost::mpl::if_; using boost::mpl::for_each; struct null_precomputation { static void precompute(size_t len) { return; } }; template <class T> struct op_precompute { static void apply(size_t len) { if_<is_base_of<op_with_precomputation,T>, T, null_precomputation>::type::precompute(len); } }; template <int N> struct possible_vectorizations { typedef typename fold< typename possible_vectorizations<N-1>::type, vector<>, push_back<push_back<_1,push_back<_2,false_> >,push_back<_2,true_> > >::type type; }; template <> struct possible_vectorizations<0> { typedef vector<vector<> > type; }; template <class Vectorizable> struct disallow_vectorization { template <class Vectorize> struct apply { // Valid = !Vectorize || Vectorizable typedef typename transform<Vectorize,not_<_> >::type DontVectorize; typedef typename transform<DontVectorize,Vectorizable,or_<_,_> >::type Valid; typedef typename not_<fold<Valid,true_,and_<_,_> > >::type type; }; }; template <class Vectorizable> struct allowable_vectorizations { typedef typename possible_vectorizations<size<Vectorizable>::value>::type possible; typedef typename remove_if<possible,disallow_vectorization<Vectorizable> >::type type; }; template <class T> bool any_masked(const T &value) { return false; }; template <class T> bool any_masked(const PyImath::FixedArray<T> &value) { return value.isMaskedReference(); }; template <class T1, class T2> bool any_masked(const T1 &a, const T2 &b) { return any_masked(a) || any_masked(b); } template <class T1, class T2, class T3> bool any_masked(const T1 &a, const T2 &b, const T3 &c) { return any_masked(a,b) || any_masked(c); } template <class T1, class T2, class T3, class T4> bool any_masked(const T1 &a, const T2 &b, const T3 &c, const T4 &d) { return any_masked(a,b) || any_masked(c,d); } //----------------------------------------------------------------------------------------- // // measure_argument returns a pair indicating the integral length of the argument // (scalar arguments have implicit length 1), and a bool indicating whether the argument // is a vectorized argument. // template <class T> struct measure_argument { static inline std::pair<size_t,bool> apply(T arg) { return std::make_pair(1,false); } }; template <class T> struct measure_argument<PyImath::FixedArray<T> > { static inline std::pair<size_t,bool> apply(const PyImath::FixedArray<T> &arg) { return std::make_pair(arg.len(),true); } }; // // match_lengths returns the compatible length given two argument lengths // static inline std::pair<size_t,bool> match_lengths(const std::pair<size_t,bool> &len1, const std::pair<size_t,bool> &len2) { // scalar arguemnts are always compatible with other arguments if (len1.second == false) return len2; if (len2.second == false) return len1; // now both arguments are vectorized, check for dimension match if (len1.first != len2.first) throw std::invalid_argument("Array dimensions passed into function do not match"); return len1; } // // measure_arguments finds the length that a return value from a given // set of arguments should have, throwing an exception if the lengths // are incompatible. If all arguments are scalar, length 1 is returned. // template <class arg1_type> size_t measure_arguments(const arg1_type &arg1) { std::pair<size_t,bool> len = measure_argument<arg1_type>::apply(arg1); return len.first; } template <class arg1_type, class arg2_type> size_t measure_arguments(const arg1_type &arg1, const arg2_type &arg2) { std::pair<size_t,bool> len = measure_argument<arg1_type>::apply(arg1); len = match_lengths(len,measure_argument<arg2_type>::apply(arg2)); return len.first; } template <class arg1_type, class arg2_type, class arg3_type> size_t measure_arguments(const arg1_type &arg1, const arg2_type &arg2, const arg3_type &arg3) { std::pair<size_t,bool> len = measure_argument<arg1_type>::apply(arg1); len = match_lengths(len,measure_argument<arg2_type>::apply(arg2)); len = match_lengths(len,measure_argument<arg3_type>::apply(arg3)); return len.first; } template <class arg1_type, class arg2_type, class arg3_type, class arg4_type> size_t measure_arguments(const arg1_type &arg1, const arg2_type &arg2, const arg3_type &arg3, const arg4_type &arg4) { std::pair<size_t,bool> len = measure_argument<arg1_type>::apply(arg1); len = match_lengths(len,measure_argument<arg2_type>::apply(arg2)); len = match_lengths(len,measure_argument<arg3_type>::apply(arg3)); len = match_lengths(len,measure_argument<arg4_type>::apply(arg4)); return len.first; } template <class arg1_type, class arg2_type, class arg3_type, class arg4_type, class arg5_type> size_t measure_arguments(const arg1_type &arg1, const arg2_type &arg2, const arg3_type &arg3, const arg4_type &arg4, const arg5_type &arg5) { std::pair<size_t,bool> len = measure_argument<arg1_type>::apply(arg1); len = match_lengths(len,measure_argument<arg2_type>::apply(arg2)); len = match_lengths(len,measure_argument<arg3_type>::apply(arg3)); len = match_lengths(len,measure_argument<arg4_type>::apply(arg4)); len = match_lengths(len,measure_argument<arg5_type>::apply(arg5)); return len.first; } //----------------------------------------------------------------------------------------- template <class T> struct create_uninitalized_return_value { static T apply(size_t length) { return T(); } }; template <class T> struct create_uninitalized_return_value<PyImath::FixedArray<T> > { static PyImath::FixedArray<T> apply(size_t length) { return PyImath::FixedArray<T>(Py_ssize_t(length),PyImath::UNINITIALIZED); } }; template <class T, class VectorizeArg> struct vectorized_result_type { typedef typename if_<VectorizeArg,PyImath::FixedArray<T>,T>::type type; }; template <typename T> struct SimpleNonArrayWrapper { struct ReadOnlyDirectAccess { ReadOnlyDirectAccess (const T& arg) : _arg (arg) {} ReadOnlyDirectAccess (const ReadOnlyDirectAccess& other) : _arg (other._arg) {} const T& operator[] (size_t) const { return _arg; } private: const T& _arg; }; struct WritableDirectAccess : public ReadOnlyDirectAccess { WritableDirectAccess (T& arg) : ReadOnlyDirectAccess (arg), _arg (arg) {} WritableDirectAccess (const WritableDirectAccess& other) : ReadOnlyDirectAccess (other), _arg (other._arg) {} T& operator[] (size_t) { return _arg; } private: T& _arg; }; typedef ReadOnlyDirectAccess ReadOnlyMaskedAccess; typedef WritableDirectAccess WritableMaskedAccess; }; template <class T> struct access_type { typedef typename remove_reference<T>::type prim_type; typedef typename remove_const<prim_type>::type base_type; typedef typename if_<is_const<prim_type>, const PyImath::FixedArray<base_type> &, PyImath::FixedArray<base_type> &>::type reference_type; typedef typename remove_reference<reference_type>::type class_type; typedef typename if_<is_const<prim_type>, typename class_type::ReadOnlyMaskedAccess, typename class_type::WritableMaskedAccess>::type masked; typedef typename if_<is_const<prim_type>, typename class_type::ReadOnlyDirectAccess, typename class_type::WritableDirectAccess>::type direct; }; template <class T, class VectorizeArg> struct argument_access_type { typedef typename remove_const<typename remove_reference<T>::type>::type base_type; typedef typename if_<VectorizeArg,const PyImath::FixedArray<base_type> &,T>::type type; typedef typename if_<VectorizeArg, typename remove_reference<type>::type, SimpleNonArrayWrapper<base_type> >::type _class_type; typedef typename _class_type::ReadOnlyMaskedAccess masked; typedef typename _class_type::ReadOnlyDirectAccess direct; }; template <class T, class VectorizeArg> struct result_access_type { typedef typename remove_const<typename remove_reference<T>::type>::type base_type; typedef typename if_<VectorizeArg,PyImath::FixedArray<base_type>,T>::type type; typedef typename if_<VectorizeArg, type, SimpleNonArrayWrapper<base_type> >::type _class_type; typedef typename _class_type::WritableMaskedAccess masked; typedef typename _class_type::WritableDirectAccess direct; }; template <class AccessType, class T> AccessType getArrayAccess (T& value) { return AccessType (value); } template <class AccessType, class T> AccessType getArrayAccess (const PyImath::FixedArray<T>& array) { return AccessType (array); } template <class AccessType, class T> AccessType getArrayAccess (PyImath::FixedArray<T>& array) { return AccessType (array); } // template <class Op, class result_access_type, class access_type> struct VectorizedOperation1 : public Task { result_access_type retAccess; access_type access; VectorizedOperation1 (result_access_type r, access_type a1) : retAccess (r), access (a1) {} void execute(size_t start, size_t end) { for (size_t i = start; i < end; ++i) { retAccess[i] = Op::apply (access[i]); } } }; template <class Op, class result_access_type, class access_type, class arg1_access_type> struct VectorizedOperation2 : public Task { result_access_type retAccess; access_type access; arg1_access_type argAccess; VectorizedOperation2(result_access_type r, access_type a1, arg1_access_type a2) : retAccess (r), access (a1), argAccess (a2) {} void execute(size_t start, size_t end) { for (size_t i = start; i < end; ++i) { retAccess[i] = Op::apply (access[i], argAccess[i]); } } }; template <class Op, class result_access_type, class access_type, class arg1_access_type, class arg2_access_type> struct VectorizedOperation3 : public Task { result_access_type retAccess; access_type access; arg1_access_type arg1Access; arg2_access_type arg2Access; VectorizedOperation3(result_access_type r, access_type a, arg1_access_type a1, arg2_access_type a2) : retAccess(r), access(a), arg1Access(a1), arg2Access(a2) {} void execute(size_t start, size_t end) { for (size_t i = start; i < end; ++i) { retAccess[i] = Op::apply(access[i], arg1Access[i], arg2Access[i]); } } }; template <class Op, class result_access_type, class access_type, class arg1_access_type, class arg2_access_type, class arg3_access_type> struct VectorizedOperation4 : public Task { result_access_type retAccess; access_type access; arg1_access_type arg1Access; arg2_access_type arg2Access; arg3_access_type arg3Access; VectorizedOperation4(result_access_type r, access_type a, arg1_access_type a1, arg2_access_type a2, arg3_access_type a3) : retAccess(r), access(a), arg1Access(a1), arg2Access(a2), arg3Access(a3) {} void execute(size_t start, size_t end) { for (size_t i = start; i < end; ++i) { retAccess[i] = Op::apply(access[i], arg1Access[i], arg2Access[i], arg3Access[i]); } } }; template <class Op, class result_access_type, class access_type, class arg1_access_type, class arg2_access_type, class arg3_access_type, class arg4_access_type> struct VectorizedOperation5 : public Task { result_access_type retAccess; access_type access; arg1_access_type arg1Access; arg2_access_type arg2Access; arg3_access_type arg3Access; arg4_access_type arg4Access; VectorizedOperation5(result_access_type r, access_type a, arg1_access_type a1, arg2_access_type a2, arg3_access_type a3, arg4_access_type a4) : retAccess(r), access(a), arg1Access(a1), arg2Access(a2), arg3Access(a3), arg4Access(a4) {} void execute(size_t start, size_t end) { for (size_t i = start; i < end; ++i) { retAccess[i] = Op::apply(access[i], arg1Access[i], arg2Access[i], arg3Access[i], arg4Access[i]); } } }; template <class Op, class Vectorize, class Func> struct VectorizedFunction1 { BOOST_STATIC_ASSERT((size<Vectorize>::value == function_traits<Func>::arity)); typedef function_traits<Func> traits; typedef typename fold<Vectorize,false_,or_<_,_> >::type any_vectorized; typedef typename result_access_type<typename traits::result_type, any_vectorized>::type result_type; typedef typename result_access_type<typename traits::result_type, any_vectorized>::direct result_access_type; // Result array is created here 'from scratch', so is always 'direct' access. typedef typename argument_access_type<typename traits::arg1_type, typename at<Vectorize,long_<0> >::type>::type arg1_type; typedef typename argument_access_type<typename traits::arg1_type, typename at<Vectorize,long_<0> >::type>::direct arg1_direct_access_type; typedef typename argument_access_type<typename traits::arg1_type, typename at<Vectorize,long_<0> >::type>::masked arg1_masked_access_type; static result_type apply(arg1_type arg1) { PY_IMATH_LEAVE_PYTHON; size_t len = measure_arguments(arg1); op_precompute<Op>::apply(len); result_type retval = create_uninitalized_return_value<result_type>::apply(len); result_access_type resultAccess = getArrayAccess<result_access_type> (retval); if (any_masked(arg1)) { arg1_masked_access_type argAccess = getArrayAccess<arg1_masked_access_type> (arg1); VectorizedOperation1<Op,result_access_type,arg1_masked_access_type> vop (resultAccess, argAccess); dispatchTask(vop,len); } else { arg1_direct_access_type argAccess = getArrayAccess<arg1_direct_access_type> (arg1); VectorizedOperation1<Op,result_access_type,arg1_direct_access_type> vop (resultAccess, argAccess); dispatchTask(vop,len); } PY_IMATH_RETURN_PYTHON; return retval; } static std::string format_arguments(const boost::python::detail::keywords<1> &args) { // TODO: add types here return std::string("(")+args.elements[0].name+") - "; } }; template <class Op, class Vectorize, class Func> struct VectorizedFunction2 { BOOST_STATIC_ASSERT((size<Vectorize>::value == function_traits<Func>::arity)); typedef function_traits<Func> traits; typedef typename fold<Vectorize,false_,or_<_,_> >::type any_vectorized; typedef typename result_access_type<typename traits::result_type, any_vectorized>::type result_type; typedef typename result_access_type<typename traits::result_type, any_vectorized>::direct result_access_type; // Result array is created here 'from scratch', so is always 'direct' access. typedef typename argument_access_type<typename traits::arg1_type, typename at<Vectorize,long_<0> >::type>::type arg1_type; typedef typename argument_access_type<typename traits::arg1_type, typename at<Vectorize,long_<0> >::type>::direct arg1_direct_access_type; typedef typename argument_access_type<typename traits::arg1_type, typename at<Vectorize,long_<0> >::type>::masked arg1_masked_access_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<1> >::type>::type arg2_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<1> >::type>::direct arg2_direct_access_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<1> >::type>::masked arg2_masked_access_type; static result_type apply(arg1_type arg1, arg2_type arg2) { PY_IMATH_LEAVE_PYTHON; size_t len = measure_arguments(arg1,arg2); op_precompute<Op>::apply(len); result_type retval = create_uninitalized_return_value<result_type>::apply(len); result_access_type resultAccess = getArrayAccess<result_access_type> (retval); if (any_masked(arg1)) { arg1_masked_access_type arg1Access = getArrayAccess<arg1_masked_access_type> (arg1); if (any_masked(arg2)) { arg2_masked_access_type arg2Access = getArrayAccess<arg2_masked_access_type> (arg2); VectorizedOperation2<Op,result_access_type, arg1_masked_access_type, arg2_masked_access_type> vop (resultAccess, arg1Access, arg2Access); dispatchTask(vop,len); } else { arg2_direct_access_type arg2Access = getArrayAccess<arg2_direct_access_type> (arg2); VectorizedOperation2<Op,result_access_type, arg1_masked_access_type, arg2_direct_access_type> vop (resultAccess, arg1Access, arg2Access); dispatchTask(vop,len); } } else { arg1_direct_access_type arg1Access = getArrayAccess<arg1_direct_access_type> (arg1); if (any_masked(arg2)) { arg2_masked_access_type arg2Access = getArrayAccess<arg2_masked_access_type> (arg2); VectorizedOperation2<Op,result_access_type, arg1_direct_access_type, arg2_masked_access_type> vop (resultAccess, arg1Access, arg2Access); dispatchTask(vop,len); } else { arg2_direct_access_type arg2Access = getArrayAccess<arg2_direct_access_type> (arg2); VectorizedOperation2<Op,result_access_type, arg1_direct_access_type, arg2_direct_access_type> vop (resultAccess, arg1Access, arg2Access); dispatchTask(vop,len); } } PY_IMATH_RETURN_PYTHON; return retval; } static std::string format_arguments(const boost::python::detail::keywords<2> &args) { // TODO: add types here return std::string("(")+args.elements[0].name+","+args.elements[1].name+") - "; } }; template <class Op, class Vectorize, class Func> struct VectorizedFunction3 { BOOST_STATIC_ASSERT((size<Vectorize>::value == function_traits<Func>::arity)); typedef function_traits<Func> traits; typedef typename fold<Vectorize,false_,or_<_,_> >::type any_vectorized; typedef typename result_access_type<typename traits::result_type, any_vectorized>::type result_type; typedef typename result_access_type<typename traits::result_type, any_vectorized>::direct result_access_type; // Result array is created here 'from scratch', so is always 'direct' access. typedef typename argument_access_type<typename traits::arg1_type, typename at<Vectorize,long_<0> >::type>::type arg1_type; typedef typename argument_access_type<typename traits::arg1_type, typename at<Vectorize,long_<0> >::type>::direct arg1_direct_access_type; typedef typename argument_access_type<typename traits::arg1_type, typename at<Vectorize,long_<0> >::type>::masked arg1_masked_access_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<1> >::type>::type arg2_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<1> >::type>::direct arg2_direct_access_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<1> >::type>::masked arg2_masked_access_type; typedef typename argument_access_type<typename traits::arg3_type, typename at<Vectorize,long_<2> >::type>::type arg3_type; typedef typename argument_access_type<typename traits::arg3_type, typename at<Vectorize,long_<2> >::type>::direct arg3_direct_access_type; typedef typename argument_access_type<typename traits::arg3_type, typename at<Vectorize,long_<2> >::type>::masked arg3_masked_access_type; static result_type apply(arg1_type arg1, arg2_type arg2, arg3_type arg3) { PY_IMATH_LEAVE_PYTHON; size_t len = measure_arguments(arg1,arg2,arg3); op_precompute<Op>::apply(len); result_type retval = create_uninitalized_return_value<result_type>::apply(len); result_access_type resultAccess = getArrayAccess<result_access_type> (retval); if (any_masked(arg1)) { arg1_masked_access_type arg1Access = getArrayAccess<arg1_masked_access_type> (arg1); if (any_masked(arg2)) { arg2_masked_access_type arg2Access = getArrayAccess<arg2_masked_access_type> (arg2); if (any_masked(arg3)) { arg3_masked_access_type arg3Access = getArrayAccess<arg3_masked_access_type> (arg3); VectorizedOperation3<Op,result_access_type, arg1_masked_access_type, arg2_masked_access_type, arg3_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access); dispatchTask(vop,len); } else { arg3_direct_access_type arg3Access = getArrayAccess<arg3_direct_access_type> (arg3); VectorizedOperation3<Op,result_access_type, arg1_masked_access_type, arg2_masked_access_type, arg3_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access); dispatchTask(vop,len); } } else { arg2_direct_access_type arg2Access = getArrayAccess<arg2_direct_access_type> (arg2); if (any_masked(arg3)) { arg3_masked_access_type arg3Access = getArrayAccess<arg3_masked_access_type> (arg3); VectorizedOperation3<Op,result_access_type, arg1_masked_access_type, arg2_direct_access_type, arg3_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access); dispatchTask(vop,len); } else { arg3_direct_access_type arg3Access = getArrayAccess<arg3_direct_access_type> (arg3); VectorizedOperation3<Op,result_access_type, arg1_masked_access_type, arg2_direct_access_type, arg3_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access); dispatchTask(vop,len); } } } else { arg1_direct_access_type arg1Access = getArrayAccess<arg1_direct_access_type> (arg1); if (any_masked(arg2)) { arg2_masked_access_type arg2Access = getArrayAccess<arg2_masked_access_type> (arg2); if (any_masked(arg3)) { arg3_masked_access_type arg3Access = getArrayAccess<arg3_masked_access_type> (arg3); VectorizedOperation3<Op,result_access_type, arg1_direct_access_type, arg2_masked_access_type, arg3_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access); dispatchTask(vop,len); } else { arg3_direct_access_type arg3Access = getArrayAccess<arg3_direct_access_type> (arg3); VectorizedOperation3<Op,result_access_type, arg1_direct_access_type, arg2_masked_access_type, arg3_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access); dispatchTask(vop,len); } } else { arg2_direct_access_type arg2Access = getArrayAccess<arg2_direct_access_type> (arg2); if (any_masked(arg3)) { arg3_masked_access_type arg3Access = getArrayAccess<arg3_masked_access_type> (arg3); VectorizedOperation3<Op,result_access_type, arg1_direct_access_type, arg2_direct_access_type, arg3_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access); dispatchTask(vop,len); } else { arg3_direct_access_type arg3Access = getArrayAccess<arg3_direct_access_type> (arg3); VectorizedOperation3<Op,result_access_type, arg1_direct_access_type, arg2_direct_access_type, arg3_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access); dispatchTask(vop,len); } } } PY_IMATH_RETURN_PYTHON; return retval; } static std::string format_arguments(const boost::python::detail::keywords<3> &args) { // TODO: add types here return std::string("(")+args.elements[0].name+","+args.elements[1].name+","+args.elements[2].name+") - "; } }; template <class Op, class Vectorize, class Func> struct VectorizedFunction4 { BOOST_STATIC_ASSERT((size<Vectorize>::value == function_traits<Func>::arity)); typedef function_traits<Func> traits; typedef typename fold<Vectorize,false_,or_<_,_> >::type any_vectorized; typedef typename result_access_type<typename traits::result_type, any_vectorized>::type result_type; typedef typename result_access_type<typename traits::result_type, any_vectorized>::direct result_access_type; // Result array is created here 'from scratch', so is always 'direct' access. typedef typename argument_access_type<typename traits::arg1_type, typename at<Vectorize,long_<0> >::type>::type arg1_type; typedef typename argument_access_type<typename traits::arg1_type, typename at<Vectorize,long_<0> >::type>::direct arg1_direct_access_type; typedef typename argument_access_type<typename traits::arg1_type, typename at<Vectorize,long_<0> >::type>::masked arg1_masked_access_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<1> >::type>::type arg2_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<1> >::type>::direct arg2_direct_access_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<1> >::type>::masked arg2_masked_access_type; typedef typename argument_access_type<typename traits::arg3_type, typename at<Vectorize,long_<2> >::type>::type arg3_type; typedef typename argument_access_type<typename traits::arg3_type, typename at<Vectorize,long_<2> >::type>::direct arg3_direct_access_type; typedef typename argument_access_type<typename traits::arg3_type, typename at<Vectorize,long_<2> >::type>::masked arg3_masked_access_type; typedef typename argument_access_type<typename traits::arg4_type, typename at<Vectorize,long_<3> >::type>::type arg4_type; typedef typename argument_access_type<typename traits::arg4_type, typename at<Vectorize,long_<3> >::type>::direct arg4_direct_access_type; typedef typename argument_access_type<typename traits::arg4_type, typename at<Vectorize,long_<3> >::type>::masked arg4_masked_access_type; static result_type apply(arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4) { PY_IMATH_LEAVE_PYTHON; size_t len = measure_arguments(arg1,arg2,arg3,arg4); op_precompute<Op>::apply(len); result_type retval = create_uninitalized_return_value<result_type>::apply(len); result_access_type resultAccess = getArrayAccess<result_access_type> (retval); if (any_masked(arg1)) { arg1_masked_access_type arg1Access = getArrayAccess<arg1_masked_access_type> (arg1); if (any_masked(arg2)) { arg2_masked_access_type arg2Access = getArrayAccess<arg2_masked_access_type> (arg2); if (any_masked(arg3)) { arg3_masked_access_type arg3Access = getArrayAccess<arg3_masked_access_type> (arg3); if (any_masked(arg4)) { arg4_masked_access_type arg4Access = getArrayAccess<arg4_masked_access_type> (arg4); VectorizedOperation4<Op,result_access_type, arg1_masked_access_type, arg2_masked_access_type, arg3_masked_access_type, arg4_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access); dispatchTask(vop,len); } else { arg4_direct_access_type arg4Access = getArrayAccess<arg4_direct_access_type> (arg4); VectorizedOperation4<Op,result_access_type, arg1_masked_access_type, arg2_masked_access_type, arg3_masked_access_type, arg4_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access); dispatchTask(vop,len); } } else { arg3_direct_access_type arg3Access = getArrayAccess<arg3_direct_access_type> (arg3); if (any_masked(arg4)) { arg4_masked_access_type arg4Access = getArrayAccess<arg4_masked_access_type> (arg4); VectorizedOperation4<Op,result_access_type, arg1_masked_access_type, arg2_masked_access_type, arg3_direct_access_type, arg4_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access); } else { arg4_direct_access_type arg4Access = getArrayAccess<arg4_direct_access_type> (arg4); VectorizedOperation4<Op,result_access_type, arg1_masked_access_type, arg2_masked_access_type, arg3_direct_access_type, arg4_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access); dispatchTask(vop,len); } } } else { arg2_direct_access_type arg2Access = getArrayAccess<arg2_direct_access_type> (arg2); if (any_masked(arg3)) { arg3_masked_access_type arg3Access = getArrayAccess<arg3_masked_access_type> (arg3); if (any_masked(arg4)) { arg4_masked_access_type arg4Access = getArrayAccess<arg4_masked_access_type> (arg4); VectorizedOperation4<Op,result_access_type, arg1_masked_access_type, arg2_direct_access_type, arg3_masked_access_type, arg4_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access); dispatchTask(vop,len); } else { arg4_direct_access_type arg4Access = getArrayAccess<arg4_direct_access_type> (arg4); VectorizedOperation4<Op,result_access_type, arg1_masked_access_type, arg2_direct_access_type, arg3_masked_access_type, arg4_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access); dispatchTask(vop,len); } } else { arg3_direct_access_type arg3Access = getArrayAccess<arg3_direct_access_type> (arg3); if (any_masked(arg4)) { arg4_masked_access_type arg4Access = getArrayAccess<arg4_masked_access_type> (arg4); VectorizedOperation4<Op,result_access_type, arg1_masked_access_type, arg2_direct_access_type, arg3_direct_access_type, arg4_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access); dispatchTask(vop,len); } else { arg4_direct_access_type arg4Access = getArrayAccess<arg4_direct_access_type> (arg4); VectorizedOperation4<Op,result_access_type, arg1_masked_access_type, arg2_direct_access_type, arg3_direct_access_type, arg4_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access); dispatchTask(vop,len); } } } } else { arg1_direct_access_type arg1Access = getArrayAccess<arg1_direct_access_type> (arg1); if (any_masked(arg2)) { arg2_masked_access_type arg2Access = getArrayAccess<arg2_masked_access_type> (arg2); if (any_masked(arg3)) { arg3_masked_access_type arg3Access = getArrayAccess<arg3_masked_access_type> (arg3); if (any_masked(arg4)) { arg4_masked_access_type arg4Access = getArrayAccess<arg4_masked_access_type> (arg4); VectorizedOperation4<Op,result_access_type, arg1_direct_access_type, arg2_masked_access_type, arg3_masked_access_type, arg4_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access); dispatchTask(vop,len); } else { arg4_direct_access_type arg4Access = getArrayAccess<arg4_direct_access_type> (arg4); VectorizedOperation4<Op,result_access_type, arg1_direct_access_type, arg2_masked_access_type, arg3_masked_access_type, arg4_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access); dispatchTask(vop,len); } } else { arg3_direct_access_type arg3Access = getArrayAccess<arg3_direct_access_type> (arg3); if (any_masked(arg4)) { arg4_masked_access_type arg4Access = getArrayAccess<arg4_masked_access_type> (arg4); VectorizedOperation4<Op,result_access_type, arg1_direct_access_type, arg2_masked_access_type, arg3_direct_access_type, arg4_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access); dispatchTask(vop,len); } else { arg4_direct_access_type arg4Access = getArrayAccess<arg4_direct_access_type> (arg4); VectorizedOperation4<Op,result_access_type, arg1_direct_access_type, arg2_masked_access_type, arg3_direct_access_type, arg4_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access); dispatchTask(vop,len); } } } else { arg2_direct_access_type arg2Access = getArrayAccess<arg2_direct_access_type> (arg2); if (any_masked(arg3)) { arg3_masked_access_type arg3Access = getArrayAccess<arg3_masked_access_type> (arg3); if (any_masked(arg4)) { arg4_masked_access_type arg4Access = getArrayAccess<arg4_masked_access_type> (arg4); VectorizedOperation4<Op,result_access_type, arg1_direct_access_type, arg2_direct_access_type, arg3_masked_access_type, arg4_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access); dispatchTask(vop,len); } else { arg4_direct_access_type arg4Access = getArrayAccess<arg4_direct_access_type> (arg4); VectorizedOperation4<Op,result_access_type, arg1_direct_access_type, arg2_direct_access_type, arg3_masked_access_type, arg4_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access); dispatchTask(vop,len); } } else { arg3_direct_access_type arg3Access = getArrayAccess<arg3_direct_access_type> (arg3); if (any_masked(arg4)) { arg4_masked_access_type arg4Access = getArrayAccess<arg4_masked_access_type> (arg4); VectorizedOperation4<Op,result_access_type, arg1_direct_access_type, arg2_direct_access_type, arg3_direct_access_type, arg4_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access); dispatchTask(vop,len); } else { arg4_direct_access_type arg4Access = getArrayAccess<arg4_direct_access_type> (arg4); VectorizedOperation4<Op,result_access_type, arg1_direct_access_type, arg2_direct_access_type, arg3_direct_access_type, arg4_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access); dispatchTask(vop,len); } } } } PY_IMATH_RETURN_PYTHON; return retval; } static std::string format_arguments(const boost::python::detail::keywords<4> &args) { // TODO: add types here return std::string("(")+args.elements[0].name+","+args.elements[1].name+","+args.elements[2].name+","+args.elements[3].name+") - "; } }; template <class Op, class Vectorize, class Func> struct VectorizedFunction5 { BOOST_STATIC_ASSERT((size<Vectorize>::value == function_traits<Func>::arity)); typedef function_traits<Func> traits; typedef typename fold<Vectorize,false_,or_<_,_> >::type any_vectorized; typedef typename result_access_type<typename traits::result_type, any_vectorized>::type result_type; typedef typename result_access_type<typename traits::result_type, any_vectorized>::direct result_access_type; // Result array is created here 'from scratch', so is always 'direct' access. typedef typename argument_access_type<typename traits::arg1_type, typename at<Vectorize,long_<0> >::type>::type arg1_type; typedef typename argument_access_type<typename traits::arg1_type, typename at<Vectorize,long_<0> >::type>::direct arg1_direct_access_type; typedef typename argument_access_type<typename traits::arg1_type, typename at<Vectorize,long_<0> >::type>::masked arg1_masked_access_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<1> >::type>::type arg2_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<1> >::type>::direct arg2_direct_access_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<1> >::type>::masked arg2_masked_access_type; typedef typename argument_access_type<typename traits::arg3_type, typename at<Vectorize,long_<2> >::type>::type arg3_type; typedef typename argument_access_type<typename traits::arg3_type, typename at<Vectorize,long_<2> >::type>::direct arg3_direct_access_type; typedef typename argument_access_type<typename traits::arg3_type, typename at<Vectorize,long_<2> >::type>::masked arg3_masked_access_type; typedef typename argument_access_type<typename traits::arg4_type, typename at<Vectorize,long_<3> >::type>::type arg4_type; typedef typename argument_access_type<typename traits::arg4_type, typename at<Vectorize,long_<3> >::type>::direct arg4_direct_access_type; typedef typename argument_access_type<typename traits::arg4_type, typename at<Vectorize,long_<3> >::type>::masked arg4_masked_access_type; typedef typename argument_access_type<typename traits::arg5_type, typename at<Vectorize,long_<4> >::type>::type arg5_type; typedef typename argument_access_type<typename traits::arg5_type, typename at<Vectorize,long_<4> >::type>::direct arg5_direct_access_type; typedef typename argument_access_type<typename traits::arg5_type, typename at<Vectorize,long_<4> >::type>::masked arg5_masked_access_type; static result_type apply(arg1_type arg1, arg2_type arg2, arg3_type arg3, arg4_type arg4, arg5_type arg5) { PY_IMATH_LEAVE_PYTHON; size_t len = measure_arguments(arg1,arg2,arg3,arg4,arg5); op_precompute<Op>::apply(len); result_type retval = create_uninitalized_return_value<result_type>::apply(len); result_access_type resultAccess = getArrayAccess<result_access_type> (retval); if (any_masked(arg1)) { arg1_masked_access_type arg1Access = getArrayAccess<arg1_masked_access_type> (arg1); if (any_masked(arg2)) { arg2_masked_access_type arg2Access = getArrayAccess<arg2_masked_access_type> (arg2); if (any_masked(arg3)) { arg3_masked_access_type arg3Access = getArrayAccess<arg3_masked_access_type> (arg3); if (any_masked(arg4)) { arg4_masked_access_type arg4Access = getArrayAccess<arg4_masked_access_type> (arg4); if (any_masked(arg5)) { arg5_masked_access_type arg5Access = getArrayAccess<arg5_masked_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_masked_access_type, arg2_masked_access_type, arg3_masked_access_type, arg4_masked_access_type, arg5_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } else { arg5_direct_access_type arg5Access = getArrayAccess<arg5_direct_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_masked_access_type, arg2_masked_access_type, arg3_masked_access_type, arg4_masked_access_type, arg5_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } } else { arg4_direct_access_type arg4Access = getArrayAccess<arg4_direct_access_type> (arg4); if (any_masked(arg5)) { arg5_masked_access_type arg5Access = getArrayAccess<arg5_masked_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_masked_access_type, arg2_masked_access_type, arg3_masked_access_type, arg4_direct_access_type, arg5_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } else { arg5_direct_access_type arg5Access = getArrayAccess<arg5_direct_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_masked_access_type, arg2_masked_access_type, arg3_masked_access_type, arg4_direct_access_type, arg5_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } } } else { arg3_direct_access_type arg3Access = getArrayAccess<arg3_direct_access_type> (arg3); if (any_masked(arg4)) { arg4_masked_access_type arg4Access = getArrayAccess<arg4_masked_access_type> (arg4); if (any_masked(arg5)) { arg5_masked_access_type arg5Access = getArrayAccess<arg5_masked_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_masked_access_type, arg2_masked_access_type, arg3_direct_access_type, arg4_masked_access_type, arg5_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } else { arg5_direct_access_type arg5Access = getArrayAccess<arg5_direct_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_masked_access_type, arg2_masked_access_type, arg3_direct_access_type, arg4_masked_access_type, arg5_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } } else { arg4_direct_access_type arg4Access = getArrayAccess<arg4_direct_access_type> (arg4); if (any_masked(arg5)) { arg5_masked_access_type arg5Access = getArrayAccess<arg5_masked_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_masked_access_type, arg2_masked_access_type, arg3_direct_access_type, arg4_direct_access_type, arg5_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } else { arg5_direct_access_type arg5Access = getArrayAccess<arg5_direct_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_masked_access_type, arg2_masked_access_type, arg3_direct_access_type, arg4_direct_access_type, arg5_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } } } } else { arg2_direct_access_type arg2Access = getArrayAccess<arg2_direct_access_type> (arg2); if (any_masked(arg3)) { arg3_masked_access_type arg3Access = getArrayAccess<arg3_masked_access_type> (arg3); if (any_masked(arg4)) { arg4_masked_access_type arg4Access = getArrayAccess<arg4_masked_access_type> (arg4); if (any_masked(arg5)) { arg5_masked_access_type arg5Access = getArrayAccess<arg5_masked_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_masked_access_type, arg2_direct_access_type, arg3_masked_access_type, arg4_masked_access_type, arg5_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } else { arg5_direct_access_type arg5Access = getArrayAccess<arg5_direct_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_masked_access_type, arg2_direct_access_type, arg3_masked_access_type, arg4_masked_access_type, arg5_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } } else { arg4_direct_access_type arg4Access = getArrayAccess<arg4_direct_access_type> (arg4); if (any_masked(arg5)) { arg5_masked_access_type arg5Access = getArrayAccess<arg5_masked_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_masked_access_type, arg2_direct_access_type, arg3_masked_access_type, arg4_direct_access_type, arg5_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } else { arg5_direct_access_type arg5Access = getArrayAccess<arg5_direct_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_masked_access_type, arg2_direct_access_type, arg3_masked_access_type, arg4_direct_access_type, arg5_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } } } else { arg3_direct_access_type arg3Access = getArrayAccess<arg3_direct_access_type> (arg3); if (any_masked(arg4)) { arg4_masked_access_type arg4Access = getArrayAccess<arg4_masked_access_type> (arg4); if (any_masked(arg5)) { arg5_masked_access_type arg5Access = getArrayAccess<arg5_masked_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_masked_access_type, arg2_direct_access_type, arg3_direct_access_type, arg4_masked_access_type, arg5_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } else { arg5_direct_access_type arg5Access = getArrayAccess<arg5_direct_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_masked_access_type, arg2_direct_access_type, arg3_direct_access_type, arg4_masked_access_type, arg5_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } } else { arg4_direct_access_type arg4Access = getArrayAccess<arg4_direct_access_type> (arg4); if (any_masked(arg5)) { arg5_masked_access_type arg5Access = getArrayAccess<arg5_masked_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_masked_access_type, arg2_direct_access_type, arg3_direct_access_type, arg4_direct_access_type, arg5_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } else { arg5_direct_access_type arg5Access = getArrayAccess<arg5_direct_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_masked_access_type, arg2_direct_access_type, arg3_direct_access_type, arg4_direct_access_type, arg5_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } } } } } else { arg1_direct_access_type arg1Access = getArrayAccess<arg1_direct_access_type> (arg1); if (any_masked(arg2)) { arg2_masked_access_type arg2Access = getArrayAccess<arg2_masked_access_type> (arg2); if (any_masked(arg3)) { arg3_masked_access_type arg3Access = getArrayAccess<arg3_masked_access_type> (arg3); if (any_masked(arg4)) { arg4_masked_access_type arg4Access = getArrayAccess<arg4_masked_access_type> (arg4); if (any_masked(arg5)) { arg5_masked_access_type arg5Access = getArrayAccess<arg5_masked_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_direct_access_type, arg2_masked_access_type, arg3_masked_access_type, arg4_masked_access_type, arg5_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } else { arg5_direct_access_type arg5Access = getArrayAccess<arg5_direct_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_direct_access_type, arg2_masked_access_type, arg3_masked_access_type, arg4_masked_access_type, arg5_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } } else { arg4_direct_access_type arg4Access = getArrayAccess<arg4_direct_access_type> (arg4); if (any_masked(arg5)) { arg5_masked_access_type arg5Access = getArrayAccess<arg5_masked_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_direct_access_type, arg2_masked_access_type, arg3_masked_access_type, arg4_direct_access_type, arg5_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } else { arg5_direct_access_type arg5Access = getArrayAccess<arg5_direct_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_direct_access_type, arg2_masked_access_type, arg3_masked_access_type, arg4_direct_access_type, arg5_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } } } else { arg3_direct_access_type arg3Access = getArrayAccess<arg3_direct_access_type> (arg3); if (any_masked(arg4)) { arg4_masked_access_type arg4Access = getArrayAccess<arg4_masked_access_type> (arg4); if (any_masked(arg5)) { arg5_masked_access_type arg5Access = getArrayAccess<arg5_masked_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_direct_access_type, arg2_masked_access_type, arg3_direct_access_type, arg4_masked_access_type, arg5_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } else { arg5_direct_access_type arg5Access = getArrayAccess<arg5_direct_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_direct_access_type, arg2_masked_access_type, arg3_direct_access_type, arg4_masked_access_type, arg5_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } } else { arg4_direct_access_type arg4Access = getArrayAccess<arg4_direct_access_type> (arg4); if (any_masked(arg5)) { arg5_masked_access_type arg5Access = getArrayAccess<arg5_masked_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_direct_access_type, arg2_masked_access_type, arg3_direct_access_type, arg4_direct_access_type, arg5_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } else { arg5_direct_access_type arg5Access = getArrayAccess<arg5_direct_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_direct_access_type, arg2_masked_access_type, arg3_direct_access_type, arg4_direct_access_type, arg5_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } } } } else { arg2_direct_access_type arg2Access = getArrayAccess<arg2_direct_access_type> (arg2); if (any_masked(arg3)) { arg3_masked_access_type arg3Access = getArrayAccess<arg3_masked_access_type> (arg3); if (any_masked(arg4)) { arg4_masked_access_type arg4Access = getArrayAccess<arg4_masked_access_type> (arg4); if (any_masked(arg5)) { arg5_masked_access_type arg5Access = getArrayAccess<arg5_masked_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_direct_access_type, arg2_direct_access_type, arg3_masked_access_type, arg4_masked_access_type, arg5_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } else { arg5_direct_access_type arg5Access = getArrayAccess<arg5_direct_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_direct_access_type, arg2_direct_access_type, arg3_masked_access_type, arg4_masked_access_type, arg5_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } } else { arg4_direct_access_type arg4Access = getArrayAccess<arg4_direct_access_type> (arg4); if (any_masked(arg5)) { arg5_masked_access_type arg5Access = getArrayAccess<arg5_masked_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_direct_access_type, arg2_direct_access_type, arg3_masked_access_type, arg4_direct_access_type, arg5_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } else { arg5_direct_access_type arg5Access = getArrayAccess<arg5_direct_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_direct_access_type, arg2_direct_access_type, arg3_masked_access_type, arg4_direct_access_type, arg5_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } } } else { arg3_direct_access_type arg3Access = getArrayAccess<arg3_direct_access_type> (arg3); if (any_masked(arg4)) { arg4_masked_access_type arg4Access = getArrayAccess<arg4_masked_access_type> (arg4); if (any_masked(arg5)) { arg5_masked_access_type arg5Access = getArrayAccess<arg5_masked_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_direct_access_type, arg2_direct_access_type, arg3_direct_access_type, arg4_masked_access_type, arg5_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } else { arg5_direct_access_type arg5Access = getArrayAccess<arg5_direct_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_direct_access_type, arg2_direct_access_type, arg3_direct_access_type, arg4_masked_access_type, arg5_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } } else { arg4_direct_access_type arg4Access = getArrayAccess<arg4_direct_access_type> (arg4); if (any_masked(arg5)) { arg5_masked_access_type arg5Access = getArrayAccess<arg5_masked_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_direct_access_type, arg2_direct_access_type, arg3_direct_access_type, arg4_direct_access_type, arg5_masked_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } else { arg5_direct_access_type arg5Access = getArrayAccess<arg5_direct_access_type> (arg5); VectorizedOperation5<Op,result_access_type, arg1_direct_access_type, arg2_direct_access_type, arg3_direct_access_type, arg4_direct_access_type, arg5_direct_access_type> vop (resultAccess, arg1Access, arg2Access, arg3Access, arg4Access, arg5Access); dispatchTask(vop,len); } } } } } PY_IMATH_RETURN_PYTHON; return retval; } static std::string format_arguments(const boost::python::detail::keywords<5> &args) { // TODO: add types here return std::string("(")+args.elements[0].name+","+args.elements[1].name+","+args.elements[2].name+","+args.elements[3].name+","+args.elements[4].name+") - "; } }; template <class Op, class Func, class Keywords> struct function_binding { std::string _name, _doc; const Keywords &_args; function_binding(const std::string &name, const std::string &doc,const Keywords &args) : _name(name), _doc(doc), _args(args) {} template <class Vectorize> void operator()(Vectorize) const { typedef typename at<vector< int, // unused, arity 0 VectorizedFunction1<Op,Vectorize,Func>, VectorizedFunction2<Op,Vectorize,Func>, VectorizedFunction3<Op,Vectorize,Func>, VectorizedFunction4<Op,Vectorize,Func>, VectorizedFunction5<Op,Vectorize,Func> >, long_<function_traits<Func>::arity> >::type vectorized_function_type; std::string doc = _name + vectorized_function_type::format_arguments(_args) + _doc; boost::python::def(_name.c_str(),&vectorized_function_type::apply,doc.c_str(),_args); } }; template <class Op,class Func,class Keywords> function_binding<Op,Func,Keywords> build_function_binding(Func *func,const std::string &name,const std::string &doc,const Keywords &args) { return function_binding<Op,Func,Keywords>(name,doc,args); } template <class Op,class Vectorizable,class Keywords> struct generate_bindings_struct { //BOOST_STATIC_ASSERT(size<Vectorizable>::value == function_traits<Op::apply>::arity); static void apply(const std::string &name,const std::string &doc,const Keywords &args) { for_each<typename allowable_vectorizations<Vectorizable>::type>(build_function_binding<Op>(Op::apply,name,doc,args)); } }; template <class Op, class access_type> struct VectorizedVoidOperation0 : public Task { access_type access; VectorizedVoidOperation0 (access_type a) : access(a) {} void execute (size_t start, size_t end) { for (size_t i = start; i < end; ++i) { Op::apply (access[i]); } } }; template <class Op, class access_type, class arg1_access_type> struct VectorizedVoidOperation1 : public Task { access_type access; arg1_access_type arg1; VectorizedVoidOperation1(access_type a, arg1_access_type a1) : access(a), arg1(a1) {} void execute(size_t start, size_t end) { for (size_t i = start; i < end; ++i) { Op::apply (access[i], arg1[i]); } } }; template <class Op, class access_type, class arg1_access_type, class array_type> struct VectorizedMaskedVoidOperation1 : public Task { access_type access; arg1_access_type arg1; array_type array; VectorizedMaskedVoidOperation1(access_type a, arg1_access_type a1, array_type arr) : access(a), arg1(a1), array(arr) {} void execute(size_t start, size_t end) { for (size_t i = start; i < end; ++i) { const size_t ri = array.raw_ptr_index(i); Op::apply (access[i], arg1[ri]); } } }; template <class Op, class access_type, class arg1_access_type, class arg2_access_type> struct VectorizedVoidOperation2 : public Task { access_type access; arg1_access_type arg1; arg2_access_type arg2; VectorizedVoidOperation2(access_type a, arg1_access_type a1, arg2_access_type a2) : access(a), arg1(a1), arg2(a2) {} void execute(size_t start, size_t end) { for (size_t i = start; i < end; ++i) { Op::apply (access[i], arg1[i], arg2[i]); } } }; template <class Op, class Vectorize, class Func> struct VectorizedVoidMemberFunction0 { BOOST_STATIC_ASSERT((size<Vectorize>::value+1 == function_traits<Func>::arity)); typedef function_traits<Func> traits; typedef typename access_type<typename traits::arg1_type>::reference_type reference_type; typedef typename access_type<typename traits::arg1_type>::direct direct_access_type; typedef typename access_type<typename traits::arg1_type>::masked masked_access_type; static reference_type apply(reference_type array) { PY_IMATH_LEAVE_PYTHON; size_t len = measure_arguments(array); op_precompute<Op>::apply(len); if (any_masked(array)) { masked_access_type access (array); VectorizedVoidOperation0<Op,masked_access_type> vop (access); dispatchTask(vop,len); } else { direct_access_type access (array); VectorizedVoidOperation0<Op,direct_access_type> vop (access); dispatchTask(vop,len); } PY_IMATH_RETURN_PYTHON; return array; } }; template <class Op, class Vectorize, class Func> struct VectorizedVoidMemberFunction1 { BOOST_STATIC_ASSERT((size<Vectorize>::value+1 == function_traits<Func>::arity)); typedef function_traits<Func> traits; typedef typename access_type<typename traits::arg1_type>::reference_type reference_type; typedef typename access_type<typename traits::arg1_type>::direct direct_access_type; typedef typename access_type<typename traits::arg1_type>::masked masked_access_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<0> >::type>::type arg1_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<0> >::type>::direct arg1_direct_access_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<0> >::type>::masked arg1_masked_access_type; static reference_type apply(reference_type array, arg1_type arg1) { PY_IMATH_LEAVE_PYTHON; size_t len = measure_arguments(array,arg1); op_precompute<Op>::apply(len); if (any_masked(array)) { masked_access_type arrayAccess (array); if (any_masked(arg1)) { arg1_masked_access_type argAccess = getArrayAccess<arg1_masked_access_type> (arg1); VectorizedVoidOperation1<Op,masked_access_type,arg1_masked_access_type> vop (arrayAccess, argAccess); dispatchTask(vop,len); } else { arg1_direct_access_type argAccess = getArrayAccess<arg1_direct_access_type> (arg1); VectorizedVoidOperation1<Op,masked_access_type,arg1_direct_access_type> vop (arrayAccess, argAccess); dispatchTask(vop,len); } } else { direct_access_type arrayAccess (array); if (any_masked(arg1)) { arg1_masked_access_type argAccess = getArrayAccess<arg1_masked_access_type> (arg1); VectorizedVoidOperation1<Op,direct_access_type,arg1_masked_access_type> vop (arrayAccess, argAccess); dispatchTask(vop,len); } else { arg1_direct_access_type argAccess = getArrayAccess<arg1_direct_access_type> (arg1); VectorizedVoidOperation1<Op,direct_access_type,arg1_direct_access_type> vop (arrayAccess, argAccess); dispatchTask(vop,len); } } PY_IMATH_RETURN_PYTHON; return array; } static std::string format_arguments(const boost::python::detail::keywords<1> &args) { // TODO: add types here return std::string("(")+args.elements[0].name+") - "; } }; // // special class to handle single argument void memberfunctions, such as those // used for the inplace operators like +=, -=, etc. In this case we allow additional // compatibilty between a masked class and an unmasked right hand side, using the // mask to select results. // template <class Op, class Func> struct VectorizedVoidMaskableMemberFunction1 { BOOST_STATIC_ASSERT((2 == function_traits<Func>::arity)); typedef function_traits<Func> traits; typedef typename access_type<typename traits::arg1_type>::reference_type reference_type; typedef typename access_type<typename traits::arg1_type>::direct direct_access_type; typedef typename access_type<typename traits::arg1_type>::masked masked_access_type; typedef typename argument_access_type<typename traits::arg2_type, boost::mpl::true_>::type arg1_type; typedef typename argument_access_type<typename traits::arg2_type, boost::mpl::true_>::direct arg1_direct_access_type; typedef typename argument_access_type<typename traits::arg2_type, boost::mpl::true_>::masked arg1_masked_access_type; static reference_type apply(reference_type array, arg1_type arg1) { PY_IMATH_LEAVE_PYTHON; size_t len = array.match_dimension(arg1, false); op_precompute<Op>::apply(len); if (array.isMaskedReference() && (size_t) arg1.len() == array.unmaskedLength()) { // class is masked, and the unmasked length matches the right hand side masked_access_type arrayAccess (array); if (any_masked(arg1)) { arg1_masked_access_type argAccess = getArrayAccess<arg1_masked_access_type> (arg1); VectorizedMaskedVoidOperation1<Op,masked_access_type, arg1_masked_access_type, reference_type> vop (arrayAccess, argAccess, array); dispatchTask(vop,len); } else { arg1_direct_access_type argAccess = getArrayAccess<arg1_direct_access_type> (arg1); VectorizedMaskedVoidOperation1<Op,masked_access_type, arg1_direct_access_type, reference_type> vop (arrayAccess, argAccess, array); dispatchTask(vop,len); } } else { // the two arrays match length (masked or otherwise), use the standard path. if (any_masked(array)) { masked_access_type arrayAccess (array); if (any_masked(arg1)) { arg1_masked_access_type argAccess = getArrayAccess<arg1_masked_access_type> (arg1); VectorizedVoidOperation1<Op,masked_access_type,arg1_masked_access_type> vop (arrayAccess, argAccess); dispatchTask(vop,len); } else { arg1_direct_access_type argAccess = getArrayAccess<arg1_direct_access_type> (arg1); VectorizedVoidOperation1<Op,masked_access_type,arg1_direct_access_type> vop (arrayAccess, argAccess); dispatchTask(vop,len); } } else { direct_access_type arrayAccess (array); if (any_masked(arg1)) { arg1_masked_access_type argAccess = getArrayAccess<arg1_masked_access_type> (arg1); VectorizedVoidOperation1<Op,direct_access_type,arg1_masked_access_type> vop (arrayAccess, argAccess); dispatchTask(vop,len); } else { arg1_direct_access_type argAccess = getArrayAccess<arg1_direct_access_type> (arg1); VectorizedVoidOperation1<Op,direct_access_type,arg1_direct_access_type> vop (arrayAccess, argAccess); dispatchTask(vop,len); } } } PY_IMATH_RETURN_PYTHON; return array; } static std::string format_arguments(const boost::python::detail::keywords<1> &args) { // TODO: add types here return std::string("(")+args.elements[0].name+") - "; } }; template <class Op, class Vectorize, class Func> struct VectorizedVoidMemberFunction2 { BOOST_STATIC_ASSERT((size<Vectorize>::value+1 == function_traits<Func>::arity)); typedef function_traits<Func> traits; typedef typename access_type<typename traits::arg1_type>::reference_type reference_type; typedef typename access_type<typename traits::arg1_type>::direct direct_access_type; typedef typename access_type<typename traits::arg1_type>::masked masked_access_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<0> >::type>::type arg1_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<0> >::type>::direct arg1_direct_access_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<0> >::type>::masked arg1_masked_access_type; typedef typename argument_access_type<typename traits::arg3_type, typename at<Vectorize,long_<1> >::type>::type arg2_type; typedef typename argument_access_type<typename traits::arg3_type, typename at<Vectorize,long_<1> >::type>::direct arg2_direct_access_type; typedef typename argument_access_type<typename traits::arg3_type, typename at<Vectorize,long_<1> >::type>::masked arg2_masked_access_type; static reference_type apply(reference_type array, arg1_type arg1, arg2_type arg2) { PY_IMATH_LEAVE_PYTHON; size_t len = measure_arguments(array,arg1,arg2); op_precompute<Op>::apply(len); if (any_masked(array)) { masked_access_type arrayAccess (array); if (any_masked(arg1)) { arg1_masked_access_type arg1Access = getArrayAccess<arg1_masked_access_type> (arg1); if (any_masked(arg2)) { arg2_masked_access_type arg2Access = getArrayAccess<arg2_masked_access_type> (arg2); VectorizedVoidOperation2<Op,masked_access_type, arg1_masked_access_type, arg2_masked_access_type> vop (arrayAccess, arg1Access, arg2Access); dispatchTask(vop,len); } else { arg2_direct_access_type arg2Access = getArrayAccess<arg2_direct_access_type> (arg2); VectorizedVoidOperation2<Op,masked_access_type, arg1_masked_access_type, arg2_direct_access_type> vop (arrayAccess, arg1Access, arg2Access); dispatchTask(vop,len); } } else { arg1_direct_access_type arg1Access = getArrayAccess<arg1_direct_access_type> (arg1); if (any_masked(arg2)) { arg2_masked_access_type arg2Access = getArrayAccess<arg2_masked_access_type> (arg2); VectorizedVoidOperation2<Op,masked_access_type, arg1_direct_access_type, arg2_masked_access_type> vop (arrayAccess, arg1Access, arg2Access); dispatchTask(vop,len); } else { arg2_direct_access_type arg2Access = getArrayAccess<arg2_direct_access_type> (arg2); VectorizedVoidOperation2<Op,masked_access_type, arg1_direct_access_type, arg2_direct_access_type> vop (arrayAccess, arg1Access, arg2Access); dispatchTask(vop,len); } } } else { direct_access_type arrayAccess (array); if (any_masked(arg1)) { arg1_masked_access_type arg1Access = getArrayAccess<arg1_masked_access_type> (arg1); if (any_masked(arg2)) { arg2_masked_access_type arg2Access = getArrayAccess<arg2_masked_access_type> (arg2); VectorizedVoidOperation2<Op,direct_access_type, arg1_masked_access_type, arg2_masked_access_type> vop (arrayAccess, arg1Access, arg2Access); dispatchTask(vop,len); } else { arg2_direct_access_type arg2Access = getArrayAccess<arg2_direct_access_type> (arg2); VectorizedVoidOperation2<Op,direct_access_type, arg1_masked_access_type, arg2_direct_access_type> vop (arrayAccess, arg1Access, arg2Access); dispatchTask(vop,len); } } else { arg1_direct_access_type arg1Access = getArrayAccess<arg1_direct_access_type> (arg1); if (any_masked(arg2)) { arg2_masked_access_type arg2Access = getArrayAccess<arg2_masked_access_type> (arg2); VectorizedVoidOperation2<Op,direct_access_type, arg1_direct_access_type, arg2_masked_access_type> vop (arrayAccess, arg1Access, arg2Access); dispatchTask(vop,len); } else { arg2_direct_access_type arg2Access = getArrayAccess<arg2_direct_access_type> (arg2); VectorizedVoidOperation2<Op,direct_access_type, arg1_direct_access_type, arg2_direct_access_type> vop (arrayAccess, arg1Access, arg2Access); dispatchTask(vop,len); } } } PY_IMATH_RETURN_PYTHON; return array; } static std::string format_arguments(const boost::python::detail::keywords<2> &args) { // TODO: add types here return std::string("(")+args.elements[0].name+","+args.elements[1].name+") - "; } }; template <class Op, class Vectorize, class Func> struct VectorizedMemberFunction0 { BOOST_STATIC_ASSERT((size<Vectorize>::value+1 == function_traits<Func>::arity)); typedef function_traits<Func> traits; typedef typename vectorized_result_type<typename traits::result_type,true_>::type result_type; typedef typename access_type<typename traits::arg1_type>::reference_type reference_type; typedef typename access_type<typename traits::arg1_type>::direct direct_access_type; typedef typename access_type<typename traits::arg1_type>::masked masked_access_type; // The return value can't be const or masked. Verify that condition. BOOST_STATIC_ASSERT( !is_const<result_type>::value ); typedef typename result_type::WritableDirectAccess result_access_type; static result_type apply(reference_type array) { PY_IMATH_LEAVE_PYTHON; size_t len = measure_arguments(array); op_precompute<Op>::apply(len); result_type retval = create_uninitalized_return_value<result_type>::apply(len); result_access_type returnAccess (retval); if (any_masked(array)) { masked_access_type access (array); VectorizedOperation1<Op,result_access_type,masked_access_type> vop(returnAccess,access); dispatchTask(vop,len); } else { direct_access_type access (array); VectorizedOperation1<Op,result_access_type,direct_access_type> vop(returnAccess,access); dispatchTask(vop,len); } PY_IMATH_RETURN_PYTHON; return retval; } }; template <class Op, class Vectorize, class Func> struct VectorizedMemberFunction1 { BOOST_STATIC_ASSERT((size<Vectorize>::value+1 == function_traits<Func>::arity)); typedef function_traits<Func> traits; typedef typename vectorized_result_type<typename traits::result_type,true_>::type result_type; typedef typename access_type<typename traits::arg1_type>::reference_type reference_type; typedef typename access_type<typename traits::arg1_type>::direct direct_access_type; typedef typename access_type<typename traits::arg1_type>::masked masked_access_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<0> >::type>::type arg1_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<0> >::type>::direct arg1_direct_access_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<0> >::type>::masked arg1_masked_access_type; // The return value can't be const or masked. Verify that condition. BOOST_STATIC_ASSERT( !is_const<result_type>::value ); typedef typename result_type::WritableDirectAccess result_access_type; static result_type apply(reference_type array, arg1_type arg1) { PY_IMATH_LEAVE_PYTHON; size_t len = measure_arguments(array,arg1); op_precompute<Op>::apply(len); result_type retval = create_uninitalized_return_value<result_type>::apply(len); result_access_type returnAccess (retval); if (any_masked(array)) { masked_access_type access (array); if (any_masked(arg1)) { arg1_masked_access_type argAccess = getArrayAccess<arg1_masked_access_type> (arg1); VectorizedOperation2<Op,result_access_type, masked_access_type, arg1_masked_access_type> vop (returnAccess, access, argAccess); dispatchTask(vop,len); } else { arg1_direct_access_type argAccess = getArrayAccess<arg1_direct_access_type> (arg1); VectorizedOperation2<Op,result_access_type, masked_access_type, arg1_direct_access_type> vop (returnAccess, access, argAccess); dispatchTask(vop,len); } } else { direct_access_type access (array); if (any_masked(arg1)) { arg1_masked_access_type argAccess = getArrayAccess<arg1_masked_access_type> (arg1); VectorizedOperation2<Op,result_access_type, direct_access_type, arg1_masked_access_type> vop (returnAccess, access, argAccess); dispatchTask(vop,len); } else { arg1_direct_access_type argAccess = getArrayAccess<arg1_direct_access_type> (arg1); VectorizedOperation2<Op,result_access_type, direct_access_type, arg1_direct_access_type> vop (returnAccess, access, argAccess); dispatchTask(vop,len); } } PY_IMATH_RETURN_PYTHON; return retval; } static std::string format_arguments(const boost::python::detail::keywords<1> &args) { // TODO: add types here return std::string("(")+args.elements[0].name+") - "; } }; template <class Op, class Vectorize, class Func> struct VectorizedMemberFunction2 { BOOST_STATIC_ASSERT((size<Vectorize>::value+1 == function_traits<Func>::arity)); typedef function_traits<Func> traits; typedef typename vectorized_result_type<typename traits::result_type,true_>::type result_type; typedef typename access_type<typename traits::arg1_type>::reference_type reference_type; typedef typename access_type<typename traits::arg1_type>::direct direct_access_type; typedef typename access_type<typename traits::arg1_type>::masked masked_access_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<0> >::type>::type arg1_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<0> >::type>::direct arg1_direct_access_type; typedef typename argument_access_type<typename traits::arg2_type, typename at<Vectorize,long_<0> >::type>::masked arg1_masked_access_type; typedef typename argument_access_type<typename traits::arg3_type, typename at<Vectorize,long_<1> >::type>::type arg2_type; typedef typename argument_access_type<typename traits::arg3_type, typename at<Vectorize,long_<1> >::type>::direct arg2_direct_access_type; typedef typename argument_access_type<typename traits::arg3_type, typename at<Vectorize,long_<1> >::type>::masked arg2_masked_access_type; // The return value can't be const or masked. Verify that condition. BOOST_STATIC_ASSERT( !is_const<result_type>::value ); typedef typename result_type::WritableDirectAccess result_access_type; static result_type apply(reference_type array, arg1_type arg1, arg2_type arg2) { PY_IMATH_LEAVE_PYTHON; size_t len = measure_arguments(array,arg1,arg2); op_precompute<Op>::apply(len); result_type retval = create_uninitalized_return_value<result_type>::apply(len); result_access_type returnAccess (retval); if (any_masked(array)) { masked_access_type access (array); if (any_masked(arg1)) { arg1_masked_access_type arg1Access = getArrayAccess<arg1_masked_access_type> (arg1); if (any_masked(arg2)) { arg2_masked_access_type arg2Access = getArrayAccess<arg2_masked_access_type> (arg2); VectorizedOperation3<Op,result_access_type, masked_access_type, arg1_masked_access_type, arg2_masked_access_type> vop (returnAccess, access, arg1Access, arg2Access); dispatchTask(vop,len); } else { arg2_direct_access_type arg2Access = getArrayAccess<arg2_direct_access_type> (arg2); VectorizedOperation3<Op,result_access_type, masked_access_type, arg1_masked_access_type, arg2_direct_access_type> vop (returnAccess, access, arg1Access, arg2Access); dispatchTask(vop,len); } } else { arg1_direct_access_type arg1Access = getArrayAccess<arg1_direct_access_type> (arg1); if (any_masked(arg2)) { arg2_masked_access_type arg2Access = getArrayAccess<arg2_masked_access_type> (arg2); VectorizedOperation3<Op,result_access_type, masked_access_type, arg1_direct_access_type, arg2_masked_access_type> vop (returnAccess, access, arg1Access, arg2Access); dispatchTask(vop,len); } else { arg2_direct_access_type arg2Access = getArrayAccess<arg2_direct_access_type> (arg2); VectorizedOperation3<Op,result_access_type, masked_access_type, arg1_direct_access_type, arg2_direct_access_type> vop (returnAccess, access, arg1Access, arg2Access); dispatchTask(vop,len); } } } else { direct_access_type access (array); if (any_masked(arg1)) { arg1_masked_access_type arg1Access = getArrayAccess<arg1_masked_access_type> (arg1); if (any_masked(arg2)) { arg2_masked_access_type arg2Access = getArrayAccess<arg2_masked_access_type> (arg2); VectorizedOperation3<Op,result_access_type, direct_access_type, arg1_masked_access_type, arg2_masked_access_type> vop (returnAccess, access, arg1Access, arg2Access); dispatchTask(vop,len); } else { arg2_direct_access_type arg2Access = getArrayAccess<arg2_direct_access_type> (arg2); VectorizedOperation3<Op,result_access_type, direct_access_type, arg1_masked_access_type, arg2_direct_access_type> vop (returnAccess, access, arg1Access, arg2Access); dispatchTask(vop,len); } } else { arg1_direct_access_type arg1Access = getArrayAccess<arg1_direct_access_type> (arg1); if (any_masked(arg2)) { arg2_masked_access_type arg2Access = getArrayAccess<arg2_masked_access_type> (arg2); VectorizedOperation3<Op,result_access_type, direct_access_type, arg1_direct_access_type, arg2_masked_access_type> vop (returnAccess, access, arg1Access, arg2Access); dispatchTask(vop,len); } else { arg2_direct_access_type arg2Access = getArrayAccess<arg2_direct_access_type> (arg2); VectorizedOperation3<Op,result_access_type, direct_access_type, arg1_direct_access_type, arg2_direct_access_type> vop (returnAccess, access, arg1Access, arg2Access); dispatchTask(vop,len); } } } PY_IMATH_RETURN_PYTHON; return retval; } static std::string format_arguments(const boost::python::detail::keywords<2> &args) { // TODO: add types here return std::string("(")+args.elements[0].name+","+args.elements[1].name+") - "; } }; template <class Op, class Cls, class Func, class Keywords> struct member_function_binding { Cls &_cls; std::string _name, _doc; const Keywords &_args; member_function_binding(Cls &cls,const std::string &name, const std::string &doc,const Keywords &args) : _cls(cls), _name(name), _doc(doc), _args(args) {} template <class Vectorize> void operator()(Vectorize) const { typedef typename if_<is_same<void,typename function_traits<Func>::result_type>, typename if_<boost::mpl::equal<Vectorize,boost::mpl::vector<boost::mpl::true_> >, VectorizedVoidMaskableMemberFunction1<Op,Func>, VectorizedVoidMemberFunction1<Op,Vectorize,Func> >::type, VectorizedMemberFunction1<Op,Vectorize,Func> >::type member_func1_type; typedef typename if_<is_same<void,typename function_traits<Func>::result_type>, VectorizedVoidMemberFunction2<Op,Vectorize,Func>, VectorizedMemberFunction2<Op,Vectorize,Func> >::type member_func2_type; typedef typename if_<is_same<void,typename function_traits<Func>::result_type>, boost::python::return_internal_reference<>, // the void vectorizations return a reference to self boost::python::default_call_policies>::type call_policies; typedef typename at<vector< int, // unused, arity 0 int, // unused, arity 1 - first argument corresponds to the class type member_func1_type, member_func2_type >, long_<function_traits<Func>::arity> >::type vectorized_function_type; std::string doc = _name + vectorized_function_type::format_arguments(_args) + _doc; _cls.def(_name.c_str(),&vectorized_function_type::apply,doc.c_str(),_args,call_policies()); } }; template <class Op,class Cls,class Func,class Keywords> member_function_binding<Op,Cls,Func,Keywords> build_member_function_binding(Cls &cls,Func *func,const std::string &name,const std::string &doc,const Keywords &args) { return member_function_binding<Op,Cls,Func,Keywords>(cls,name,doc,args); } template <class Op,class Cls,class Vectorizable,class Keywords> struct generate_member_bindings_struct { //BOOST_STATIC_ASSERT(size<Vectorizable>::value+1 == function_traits<Op::apply>::arity); static void apply(Cls &cls,const std::string &name,const std::string &doc,const Keywords &args) { for_each<typename allowable_vectorizations<Vectorizable>::type>(build_member_function_binding<Op>(cls,Op::apply,name,doc,args)); } }; template <class Op,class Cls,class Func> void generate_single_member_binding(Cls &cls,Func *func,const std::string &name,const std::string &doc) { typedef typename if_<is_same<void,typename function_traits<Func>::result_type>, VectorizedVoidMemberFunction0<Op,boost::mpl::vector<>,Func>, VectorizedMemberFunction0<Op,boost::mpl::vector<>,Func> >::type vectorized_function_type; typedef typename if_<is_same<void,typename function_traits<Func>::result_type>, boost::python::return_internal_reference<>, // the void vectorizations return a reference to self boost::python::default_call_policies>::type call_policies; cls.def(name.c_str(),&vectorized_function_type::apply,doc.c_str(),call_policies()); } } // namespace detail // TODO: update for arg("name")=default_value syntax template <class Op,class Vectorizable0> void generate_bindings(const std::string &name,const std::string &doc,const boost::python::detail::keywords<1> &args) { using namespace detail; generate_bindings_struct<Op,vector<Vectorizable0>,boost::python::detail::keywords<1> >::apply(name,doc,args); } template <class Op,class Vectorizable0, class Vectorizable1> void generate_bindings(const std::string &name,const std::string &doc,const boost::python::detail::keywords<2> &args) { using namespace detail; generate_bindings_struct<Op,vector<Vectorizable0,Vectorizable1>,boost::python::detail::keywords<2> >::apply(name,doc,args); } template <class Op,class Vectorizable0, class Vectorizable1, class Vectorizable2> void generate_bindings(const std::string &name,const std::string &doc,const boost::python::detail::keywords<3> &args) { using namespace detail; generate_bindings_struct<Op,vector<Vectorizable0,Vectorizable1,Vectorizable2>,boost::python::detail::keywords<3> >::apply(name,doc,args); } template <class Op,class Vectorizable0, class Vectorizable1, class Vectorizable2, class Vectorizable3> void generate_bindings(const std::string &name,const std::string &doc,const boost::python::detail::keywords<4> &args) { using namespace detail; generate_bindings_struct<Op,vector<Vectorizable0,Vectorizable1,Vectorizable2,Vectorizable3>,boost::python::detail::keywords<4> >::apply(name,doc,args); } template <class Op,class Vectorizable0, class Vectorizable1, class Vectorizable2, class Vectorizable3, class Vectorizable4> void generate_bindings(const std::string &name,const std::string &doc,const boost::python::detail::keywords<5> &args) { using namespace detail; generate_bindings_struct<Op,vector<Vectorizable0,Vectorizable1,Vectorizable2,Vectorizable3,Vectorizable4>,boost::python::detail::keywords<5> >::apply(name,doc,args); } template <class Op,class Cls> void generate_member_bindings(Cls &cls,const std::string &name,const std::string &doc) { using namespace detail; generate_single_member_binding<Op>(cls,&Op::apply,name,doc); } template <class Op,class Vectorizable0,class Cls> void generate_member_bindings(Cls &cls,const std::string &name,const std::string &doc, const boost::python::detail::keywords<1> &args) { using boost::mpl::vector; detail::generate_member_bindings_struct<Op,Cls,vector<Vectorizable0>, boost::python::detail::keywords<1> >::apply(cls,name,doc,args); } template <class Op,class Vectorizable0,class Vectorizable1,class Cls> void generate_member_bindings(Cls &cls,const std::string &name,const std::string &doc, const boost::python::detail::keywords<2> &args) { using boost::mpl::vector; detail::generate_member_bindings_struct<Op,Cls,vector<Vectorizable0,Vectorizable1>, boost::python::detail::keywords<2> >::apply(cls,name,doc,args); } } // namespace PyImath #endif // _PyImathAutovectorize_h_ PyImathMatrix.h 0000644 00000013374 15125213144 0007463 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathMatrix_h_ #define _PyImathMatrix_h_ #include <Python.h> #include <boost/python.hpp> #include <ImathMatrix.h> #include <ImathMatrixAlgo.h> #include "PyImath.h" namespace PyImath { template <class T> boost::python::class_<IMATH_NAMESPACE::Matrix22<T> > register_Matrix22(); template <class T> boost::python::class_<IMATH_NAMESPACE::Matrix33<T> > register_Matrix33(); template <class T> boost::python::class_<IMATH_NAMESPACE::Matrix44<T> > register_Matrix44(); template <class T> boost::python::class_<FixedArray<IMATH_NAMESPACE::Matrix44<T> > > register_M44Array(); template <class T> boost::python::class_<FixedArray<IMATH_NAMESPACE::Matrix33<T> > > register_M33Array(); template <class T> boost::python::class_<FixedArray<IMATH_NAMESPACE::Matrix22<T> > > register_M22Array(); typedef FixedArray<IMATH_NAMESPACE::Matrix22<float> > M22fArray; typedef FixedArray<IMATH_NAMESPACE::Matrix22<double> > M22dArray; typedef FixedArray<IMATH_NAMESPACE::Matrix33<float> > M33fArray; typedef FixedArray<IMATH_NAMESPACE::Matrix33<double> > M33dArray; typedef FixedArray<IMATH_NAMESPACE::Matrix44<float> > M44fArray; typedef FixedArray<IMATH_NAMESPACE::Matrix44<double> > M44dArray; // // Other code in the Zeno code base assumes the existance of a class with the // same name as the Imath class, and with static functions wrap() and // convert() to produce a PyImath object from an Imath object and vice-versa, // respectively. The class Boost generates from the Imath class does not // have these properties, so we define a companion class here. // The template argument, T, is the element type (e.g.,float, double). template <class T> class M22 { public: static PyObject * wrap (const IMATH_NAMESPACE::Matrix22<T> &m); static int convert (PyObject *p, IMATH_NAMESPACE::Matrix22<T> *m); }; template <class T> class M33 { public: static PyObject * wrap (const IMATH_NAMESPACE::Matrix33<T> &m); static int convert (PyObject *p, IMATH_NAMESPACE::Matrix33<T> *m); }; template <class T> class M44 { public: static PyObject * wrap (const IMATH_NAMESPACE::Matrix44<T> &m); static int convert (PyObject *p, IMATH_NAMESPACE::Matrix44<T> *m); }; template <class T> PyObject * M22<T>::wrap (const IMATH_NAMESPACE::Matrix22<T> &m) { typename boost::python::return_by_value::apply < IMATH_NAMESPACE::Matrix22<T> >::type converter; PyObject *p = converter (m); return p; } template <class T> PyObject * M33<T>::wrap (const IMATH_NAMESPACE::Matrix33<T> &m) { typename boost::python::return_by_value::apply < IMATH_NAMESPACE::Matrix33<T> >::type converter; PyObject *p = converter (m); return p; } template <class T> PyObject * M44<T>::wrap (const IMATH_NAMESPACE::Matrix44<T> &m) { typename boost::python::return_by_value::apply < IMATH_NAMESPACE::Matrix44<T> >::type converter; PyObject *p = converter (m); return p; } template <class T> int M22<T>::convert (PyObject *p, IMATH_NAMESPACE::Matrix22<T> *m) { boost::python::extract <IMATH_NAMESPACE::M22f> extractorMf (p); if (extractorMf.check()) { IMATH_NAMESPACE::M22f e = extractorMf(); m->setValue (e); return 1; } boost::python::extract <IMATH_NAMESPACE::M22d> extractorMd (p); if (extractorMd.check()) { IMATH_NAMESPACE::M22d e = extractorMd(); m->setValue (e); return 1; } return 0; } template <class T> int M33<T>::convert (PyObject *p, IMATH_NAMESPACE::Matrix33<T> *m) { boost::python::extract <IMATH_NAMESPACE::M33f> extractorMf (p); if (extractorMf.check()) { IMATH_NAMESPACE::M33f e = extractorMf(); m->setValue (e); return 1; } boost::python::extract <IMATH_NAMESPACE::M33d> extractorMd (p); if (extractorMd.check()) { IMATH_NAMESPACE::M33d e = extractorMd(); m->setValue (e); return 1; } return 0; } template <class T> int M44<T>::convert (PyObject *p, IMATH_NAMESPACE::Matrix44<T> *m) { boost::python::extract <IMATH_NAMESPACE::M44f> extractorMf (p); if (extractorMf.check()) { IMATH_NAMESPACE::M44f e = extractorMf(); m->setValue (e); return 1; } boost::python::extract <IMATH_NAMESPACE::M44d> extractorMd (p); if (extractorMd.check()) { IMATH_NAMESPACE::M44d e = extractorMd(); m->setValue (e); return 1; } return 0; } template <class Matrix> boost::python::tuple jacobiEigensolve(const Matrix& m) { typedef typename Matrix::BaseType T; typedef typename Matrix::BaseVecType Vec; // For the C++ version, we just assume that the passed-in matrix is // symmetric, but we assume that many of our script users are less // sophisticated and might get tripped up by this. Also, the cost // of doing this check is likely miniscule compared to the Pythonic // overhead. // Give a fairly generous tolerance to account for possible epsilon drift: const int d = Matrix::dimensions(); const T tol = std::sqrt(std::numeric_limits<T>::epsilon()); for (int i = 0; i < d; ++i) { for (int j = i+1; j < d; ++j) { const T Aij = m[i][j], Aji = m[j][i]; if (std::abs(Aij - Aji) >= tol){ throw std::invalid_argument ("Symmetric eigensolve requires a symmetric matrix (matrix[i][j] == matrix[j][i])."); } } } Matrix tmp = m; Matrix Q; Vec S; IMATH_NAMESPACE::jacobiEigenSolver (tmp, S, Q); return boost::python::make_tuple (Q, S); } typedef M22<float> M22f; typedef M22<double> M22d; typedef M33<float> M33f; typedef M33<double> M33d; typedef M44<float> M44f; typedef M44<double> M44d; } #endif PyImathFun.h 0000644 00000000414 15125213144 0006736 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathFun_h_ #define _PyImathFun_h_ #include "PyImathExport.h" namespace PyImath { PYIMATH_EXPORT void register_functions(); } #endif PyImathUtil.h 0000644 00000012712 15125213144 0007127 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef INCLUDED_PYIMATHUTIL_H #define INCLUDED_PYIMATHUTIL_H //---------------------------------------------------------------------------- // // PyImathUtil.h -- miscellaneous classes, functions // and macros that are useful for Python wrapping // of C++ objects. // //---------------------------------------------------------------------------- #include <Python.h> #include "PyImathExport.h" #include <PyImathAPI.h> namespace PyImath { /** * PyAcquireLock ensures that python is prepared for multi-threaded use and * ensures that this thread has the global lock. * * This object must be instantiated (and continue to be in scope) during all * threaded api calls. It assumes the python interpretter is instantiated and * multithreading is enabled. * * Note: this is not compatible with additional interpreters (calls to * Py_NewInterpreter()); */ class PyAcquireLock { public: PYIMATH_EXPORT PyAcquireLock(); PYIMATH_EXPORT ~PyAcquireLock(); PYIMATH_EXPORT PyAcquireLock(const PyAcquireLock& other) = delete; PYIMATH_EXPORT PyAcquireLock & operator = (PyAcquireLock& other) = delete; PYIMATH_EXPORT PyAcquireLock(PyAcquireLock&& other) = delete; PYIMATH_EXPORT PyAcquireLock & operator = (PyAcquireLock&& other) = delete; private: PyGILState_STATE _gstate; }; /** * This object causes the python global lock to be released for the duration * of it's existence. * * This object should be instantiated (and continue to be in scope) in thread- * safe c++ functions called from python. This call is designed to be * instantiated while an AcquireLock is in effect (nested). * */ class PyReleaseLock { public: PYIMATH_EXPORT PyReleaseLock(); PYIMATH_EXPORT ~PyReleaseLock(); PYIMATH_EXPORT PyReleaseLock(const PyReleaseLock& other) = delete; PYIMATH_EXPORT PyReleaseLock & operator = (PyReleaseLock& other) = delete; PYIMATH_EXPORT PyReleaseLock(PyReleaseLock&& other) = delete; PYIMATH_EXPORT PyReleaseLock & operator = (PyReleaseLock&& other) = delete; private: PyThreadState *_save; }; /** * This object is safe object wrapper intended to use with boost python objects. * * This object correctly acquires the python lock for creation, copying and * desctruction of the given object. * */ template <class T> class PySafeObject { public: PySafeObject() : _object(0) { PyAcquireLock pylock; _object = new T(); } PySafeObject(const T &value) : _object(0) { PyAcquireLock pylock; _object = new T(value); } ~PySafeObject() { PyAcquireLock pylock; delete _object; _object = 0; } PySafeObject(const PySafeObject &other) : _object(0) { PyAcquireLock pylock; _object = new T(*other._object); } const PySafeObject & operator = (const PySafeObject &other) { if (&other == this) return *this; PyAcquireLock pylock; *_object = *other._object; return *this; } bool operator == (const PySafeObject &other) const { if (&other == this) return true; PyAcquireLock pylock; return *_object == *other._object; } bool operator != (const PySafeObject &other) const { if (&other == this) return false; PyAcquireLock pylock; return *_object != *other._object; } T & get() { return *_object; } const T & get() const { return *_object; } private: T *_object; }; /** * A special selectable postcall policy used in python wrappings. * * It expects the initial result to be a touple where the first * object represents an integer value 0, 1, 2 which corresponds * to which of the templated call polices should be applied. * * This postcall policy is modeled after a similar one defined * in PyGeomParticleUtil.h of the PyGeomParticle project. * */ template <class policy0, class policy1, class policy2> struct selectable_postcall_policy_from_tuple : policy0 { static PyObject * postcall (PyObject* args, PyObject* result) { if (!PyTuple_Check (result)) { PyErr_SetString (PyExc_TypeError, "selectable_postcall: retval was not a tuple"); return 0; } if (PyTuple_Size(result) != 2) { PyErr_SetString (PyExc_IndexError, "selectable_postcall: retval was not a tuple of length 2"); return 0; } // borrowed references within the tuple PyObject* object0 = PyTuple_GetItem (result, 0); // 'Choice' integer PyObject* object1 = PyTuple_GetItem (result, 1); // The actual object if (!PyInt_Check (object0)) { PyErr_SetString (PyExc_TypeError, "selectable_postcall: tuple item 0 was not an integer choice"); return 0; } const long usePolicy = PyInt_AsLong (object0); // ensure correct reference count for returned object and decref the tuple Py_INCREF (object1); Py_DECREF (result ); if (usePolicy <= 0) return policy0::postcall (args, object1); else if (usePolicy == 1) return policy1::postcall (args, object1); else // usePolicy >= 2 return policy2::postcall (args, object1); } }; } // namespace PyImath #endif PyImathVec2Impl.h 0000644 00000100774 15125213144 0007641 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathVec2Impl_h_ #define _PyImathVec2Impl_h_ // // This .C file was turned into a header file so that instantiations // of the various V2* types can be spread across multiple files in // order to work around MSVC limitations. // #include <Python.h> #include <boost/python.hpp> #include <boost/python/make_constructor.hpp> #include <boost/format.hpp> #include <boost/cast.hpp> #include <ImathVec.h> #include <ImathVecAlgo.h> #include "PyImath.h" #include "PyImathMathExc.h" #include "PyImathBox.h" #include "PyImathVec.h" #include "PyImathDecorators.h" #include "PyImathOperators.h" #include "PyImathVecOperators.h" namespace PyImath { using namespace boost::python; using namespace IMATH_NAMESPACE; template <class T> struct Vec2Name { static const char *value; }; // create a new default constructor that initializes Vec2<T> to zero. template <class T> static Vec2<T> * Vec2_construct_default() { return new Vec2<T>(T(0),T(0)); } template <class T,class BoostPyType> static Vec2<T> * Vec2_tuple_constructor(const BoostPyType &t) { if(t.attr("__len__")() == 1) return new Vec2<T>(extract<T>(t[0]), extract<T>(t[0])); else if(t.attr("__len__")() == 2) return new Vec2<T>(extract<T>(t[0]), extract<T>(t[1])); else throw std::invalid_argument ("Vec2 constructor expects tuple of length 1 or 2"); } template <class T> static Vec2<T> * Vec2_object_constructor1(const object &obj) { Vec2<T> w; extract<Vec2<int> > e1(obj); extract<Vec2<float> > e2(obj); extract<Vec2<double> > e3(obj); extract<tuple> e4(obj); extract<double> e5(obj); extract<list> e6(obj); if(e1.check()){ w = e1(); } else if(e2.check()) { w = e2(); } else if(e3.check()) { w = e3(); } else if(e4.check()) { tuple t = e4(); if(t.attr("__len__")() == 2) { w.x = extract<T>(t[0]); w.y = extract<T>(t[1]); } else throw std::invalid_argument ("tuple must have length of 2"); } else if(e5.check()) { T a = e5(); w.setValue(a, a); } else if(e6.check()) { list l = e6(); if(l.attr("__len__")() == 2) { w.x = extract<T>(l[0]); w.y = extract<T>(l[1]); } else throw std::invalid_argument ("list must have length of 2"); } else throw std::invalid_argument ("invalid parameters passed to Vec2 constructor"); Vec2<T> *v = new Vec2<T>; *v = w; return v; } template <class T> static Vec2<T> * Vec2_object_constructor2(const object &obj1, const object &obj2) { extract<double> e1(obj1); extract<double> e2(obj2); Vec2<T> *v = new Vec2<T>; if(e1.check()) { v->x = boost::numeric_cast<T>(e1());} else { throw std::invalid_argument ("invalid parameters passed to Vec2 constructor"); } if(e2.check()) { v->y = boost::numeric_cast<T>(e2());} else { throw std::invalid_argument ("invalid parameters passed to Vec2 constructor"); } return v; } // Implementations of str and repr are same here, // but we'll specialize repr for float and double to make them exact. template <class T> static std::string Vec2_str(const Vec2<T> &v) { std::stringstream stream; stream << Vec2Name<T>::value << "(" << v.x << ", " << v.y << ")"; return stream.str(); } template <class T> static std::string Vec2_repr(const Vec2<T> &v) { std::stringstream stream; stream << Vec2Name<T>::value << "(" << v.x << ", " << v.y << ")"; return stream.str(); } template <class T> static T Vec2_cross(const IMATH_NAMESPACE::Vec2<T> &v, const IMATH_NAMESPACE::Vec2<T> &other) { MATH_EXC_ON; return v.cross(other); } template <class T> static FixedArray<T> Vec2_cross_Vec2Array(const IMATH_NAMESPACE::Vec2<T> &va, const FixedArray<IMATH_NAMESPACE::Vec2<T> > &vb) { PY_IMATH_LEAVE_PYTHON; size_t len = vb.len(); FixedArray<T> f(len); for (size_t i = 0; i < len; ++i) f[i] = va.cross(vb[i]); return f; } template <class T> static T Vec2_dot(const IMATH_NAMESPACE::Vec2<T> &v, const IMATH_NAMESPACE::Vec2<T> &other) { MATH_EXC_ON; return v.dot(other); } template <class T> static FixedArray<T> Vec2_dot_Vec2Array(const IMATH_NAMESPACE::Vec2<T> &va, const FixedArray<IMATH_NAMESPACE::Vec2<T> > &vb) { PY_IMATH_LEAVE_PYTHON; size_t len = vb.len(); FixedArray<T> f(len); for (size_t i = 0; i < len; ++i) f[i] = va.dot(vb[i]); return f; } template <class T> static T Vec2_length(const IMATH_NAMESPACE::Vec2<T> &v) { MATH_EXC_ON; return v.length(); } template <class T> static T Vec2_length2(const IMATH_NAMESPACE::Vec2<T> &v) { MATH_EXC_ON; return v.length2(); } template <class T> static const Vec2<T> & Vec2_normalize(IMATH_NAMESPACE::Vec2<T> &v) { MATH_EXC_ON; return v.normalize(); } template <class T> static const Vec2<T> & Vec2_normalizeExc(IMATH_NAMESPACE::Vec2<T> &v) { MATH_EXC_ON; return v.normalizeExc(); } template <class T> static const Vec2<T> & Vec2_normalizeNonNull(IMATH_NAMESPACE::Vec2<T> &v) { MATH_EXC_ON; return v.normalizeNonNull(); } template <class T> static Vec2<T> Vec2_normalized(const IMATH_NAMESPACE::Vec2<T> &v) { MATH_EXC_ON; return v.normalized(); } template <class T> static Vec2<T> Vec2_normalizedExc(const IMATH_NAMESPACE::Vec2<T> &v) { MATH_EXC_ON; return v.normalizedExc(); } template <class T> static Vec2<T> Vec2_normalizedNonNull(const IMATH_NAMESPACE::Vec2<T> &v) { MATH_EXC_ON; return v.normalizedNonNull(); } template <class T> static Vec2<T> closestVertex(Vec2<T> &p, const Vec2<T> &v0, const Vec2<T> &v1, const Vec2<T> &v2) { MATH_EXC_ON; return IMATH_NAMESPACE::closestVertex(v0, v1, v2, p); } template <class T> static const Vec2<T> & Vec2_negate(IMATH_NAMESPACE::Vec2<T> &v) { MATH_EXC_ON; return v.negate(); } template <class T> static Vec2<T> orthogonal(const Vec2<T> &v, const Vec2<T> &v0) { MATH_EXC_ON; return IMATH_NAMESPACE::orthogonal(v, v0); } template <class T> static Vec2<T> project(const Vec2<T> &v, const Vec2<T> &v0) { MATH_EXC_ON; return IMATH_NAMESPACE::project(v0, v); } template <class T> static Vec2<T> reflect(const Vec2<T> &v, const Vec2<T> &v0) { MATH_EXC_ON; return IMATH_NAMESPACE::reflect(v, v0); } template <class T> static void setValue(Vec2<T> &v, T a, T b) { v.x = a; v.y = b; } template <class T> static Vec2<T> Vec2_add (const Vec2<T> &v, const Vec2<T> &w) { MATH_EXC_ON; return v + w; } template <class T> static Vec2<T> Vec2_sub (const Vec2<T> &v, const Vec2<T> &w) { MATH_EXC_ON; return v - w; } template <class T> static Vec2<T> Vec2_neg (const Vec2<T> &v) { MATH_EXC_ON; return -v; } template <class T, class U> static Vec2<T> Vec2_mul (const Vec2<T> &v, const Vec2<U> &w) { MATH_EXC_ON; Vec2<T> w2 (w); return v * w2; } template <class T> static Vec2<T> Vec2_mulT (const Vec2<T> &v, T t) { MATH_EXC_ON; return v * t; } template <class T> static FixedArray<IMATH_NAMESPACE::Vec2<T> > Vec2_mulTArray (const Vec2<T> &v, const FixedArray<T> &t) { PY_IMATH_LEAVE_PYTHON; size_t len = t.len(); FixedArray<IMATH_NAMESPACE::Vec2<T> > retval(len); for (size_t i=0; i<len; ++i) retval[i] = v*t[i]; return retval; } template <class T> static FixedArray<IMATH_NAMESPACE::Vec2<T> > Vec2_rmulTArray (const Vec2<T> &v, const FixedArray<T> &t) { return Vec2_mulTArray(v,t); } template <class T,class S> static Vec2<T> Vec2_div (Vec2<T> &v, Vec2<S> &w) { MATH_EXC_ON; return v / w; } template <class T> static Vec2<T> Vec2_rmulT (Vec2<T> &v, T t) { MATH_EXC_ON; return t * v; } template <class T, class U> static const Vec2<T> & Vec2_imulV(Vec2<T> &v, const Vec2<U> &w) { MATH_EXC_ON; return v *= w; } template <class T> static const Vec2<T> & Vec2_imulT(IMATH_NAMESPACE::Vec2<T> &v, T t) { MATH_EXC_ON; return v *= t; } template <class T, class U> static Vec2<T> Vec2_mulM22 (Vec2<T> &v, const Matrix22<U> &m) { MATH_EXC_ON; return v * m; } template <class T, class U> static Vec2<T> Vec2_mulM33 (Vec2<T> &v, const Matrix33<U> &m) { MATH_EXC_ON; return v * m; } template <class T> static const Vec2<T> & Vec2_idivObj(IMATH_NAMESPACE::Vec2<T> &v, const object &o) { MATH_EXC_ON; Vec2<T> v2; if (PyImath::V2<T>::convert (o.ptr(), &v2)) { return v /= v2; } else { extract<double> e(o); if (e.check()) return v /= e(); else throw std::invalid_argument ("V2 division expects an argument" "convertible to a V2"); } } template <class T> static Vec2<T> Vec2_subT(const Vec2<T> &v, T a) { MATH_EXC_ON; Vec2<T> w; w.setValue(v.x - a, v.y - a); return w; } template <class T,class BoostPyType> static Vec2<T> Vec2_subTuple(const Vec2<T> &v, const BoostPyType &t) { MATH_EXC_ON; Vec2<T> w; if(t.attr("__len__")() == 2) { w.x = v.x - extract<T>(t[0]); w.y = v.y - extract<T>(t[1]); } else throw std::invalid_argument ("tuple must have length of 2"); return w; } template <class T> static Vec2<T> Vec2_rsubT(const Vec2<T> &v, T a) { MATH_EXC_ON; Vec2<T> w; w.setValue(a - v.x, a - v.y); return w; } template <class T,class BoostPyType> static Vec2<T> Vec2_rsubTuple(const Vec2<T> &v, const BoostPyType &t) { MATH_EXC_ON; Vec2<T> w; if(t.attr("__len__")() == 2) { w.x = extract<T>(t[0]) - v.x; w.y = extract<T>(t[1]) - v.y; } else throw std::invalid_argument ("tuple must have length of 2"); return w; } template <class T,class BoostPyType> static Vec2<T> Vec2_addTuple(const Vec2<T> &v, const BoostPyType &t) { MATH_EXC_ON; Vec2<T> w; if(t.attr("__len__")() == 2) { w.x = v.x + extract<T>(t[0]); w.y = v.y + extract<T>(t[1]); } else throw std::invalid_argument ("tuple must have length of 2"); return w; } template <class T> static Vec2<T> Vec2_addT(const Vec2<T> &v, T a) { MATH_EXC_ON; Vec2<T> w; w.setValue(v.x + a, v.y + a); return w; } template <class T, class U> static Vec2<T> Vec2_addV(const Vec2<T> &v, const Vec2<U> &w) { MATH_EXC_ON; return v + w; } template <class T, class U> static const Vec2<T> & Vec2_iaddV(Vec2<T> &v, const Vec2<U> &w) { MATH_EXC_ON; return v += w; } template <class T, class U> static Vec2<T> Vec2_subV(const Vec2<T> &v, const Vec2<U> &w) { MATH_EXC_ON; return v - w; } template <class T, class U> static const Vec2<T> & Vec2_isubV(Vec2<T> &v, const Vec2<U> &w) { MATH_EXC_ON; return v -= w; } template <class T,class BoostPyType> static Vec2<T> Vec2_mulTuple(const Vec2<T> &v, BoostPyType t) { MATH_EXC_ON; Vec2<T> w; if(t.attr("__len__")() == 1){ w.x = v.x*extract<T>(t[0]); w.y = v.y*extract<T>(t[0]); } else if(t.attr("__len__")() == 2){ w.x = v.x*extract<T>(t[0]); w.y = v.y*extract<T>(t[1]); } else throw std::invalid_argument ("tuple must have length of 1 or 2"); return w; } template <class T, class U> static const Vec2<T> & Vec2_imulM22 (Vec2<T> &v, const Matrix22<U> &m) { MATH_EXC_ON; return v *= m; } template <class T, class U> static const Vec2<T> & Vec2_imulM33 (Vec2<T> &v, const Matrix33<U> &m) { MATH_EXC_ON; return v *= m; } template <class T,class BoostPyType> static Vec2<T> Vec2_divTuple(const Vec2<T> &v, const BoostPyType &t) { if(t.attr("__len__")() == 2) { T x = extract<T>(t[0]); T y = extract<T>(t[1]); if(x != T(0) && y != T(0)) return Vec2<T>(v.x / x, v.y / y); else throw std::domain_error ("Division by zero"); } else throw std::invalid_argument ("Vec2 expects tuple of length 2"); } template <class T,class BoostPyType> static Vec2<T> Vec2_rdivTuple(const Vec2<T> &v, const BoostPyType &t) { MATH_EXC_ON; Vec2<T> w; if(t.attr("__len__")() == 2) { T x = extract<T>(t[0]); T y = extract<T>(t[1]); if(v.x != T(0) && v.y != T(0)){ w.setValue(x / v.x, y / v.y); } else throw std::domain_error ("Division by zero"); } else throw std::invalid_argument ("tuple must have length of 2"); return w; } template <class T> static Vec2<T> Vec2_divT(const Vec2<T> &v, T a) { MATH_EXC_ON; Vec2<T> w; if(a != T(0)){ w.setValue(v.x / a, v.y / a); } else throw std::domain_error ("Division by zero"); return w; } template <class T> static Vec2<T> Vec2_rdivT(const Vec2<T> &v, T a) { MATH_EXC_ON; Vec2<T> w; if(v.x != T(0) && v.y != T(0)){ w.setValue(a / v.x, a / v.y); } else throw std::domain_error ("Division by zero"); return w; } template <class T> static bool lessThan(const Vec2<T> &v, const object &obj) { extract<Vec2<T> > e1(obj); extract<tuple> e2(obj); Vec2<T> w; if(e1.check()) { w = e1(); } else if(e2.check()) { tuple t = e2(); if(t.attr("__len__")() == 2){ T x = extract<T>(t[0]); T y = extract<T>(t[1]); w.setValue(x,y); } else throw std::invalid_argument ("Vec2 expects tuple of length 2"); } else throw std::invalid_argument ("invalid parameters passed to operator <"); bool isLessThan = (v.x <= w.x && v.y <= w.y) && v != w; return isLessThan; } template <class T> static bool greaterThan(const Vec2<T> &v, const object &obj) { extract<Vec2<T> > e1(obj); extract<tuple> e2(obj); Vec2<T> w; if(e1.check()) { w = e1(); } else if(e2.check()) { tuple t = e2(); if(t.attr("__len__")() == 2){ T x = extract<T>(t[0]); T y = extract<T>(t[1]); w.setValue(x,y); } else throw std::invalid_argument ("Vec2 expects tuple of length 2"); } else throw std::invalid_argument ("invalid parameters passed to operator >"); bool isGreaterThan = (v.x >= w.x && v.y >= w.y) && v != w; return isGreaterThan; } template <class T> static bool lessThanEqual(const Vec2<T> &v, const object &obj) { extract<Vec2<T> > e1(obj); extract<tuple> e2(obj); Vec2<T> w; if(e1.check()) { w = e1(); } else if(e2.check()) { tuple t = e2(); if(t.attr("__len__")() == 2){ T x = extract<T>(t[0]); T y = extract<T>(t[1]); w.setValue(x,y); } else throw std::invalid_argument ("Vec2 expects tuple of length 2"); } else throw std::invalid_argument ("invalid parameters passed to operator <="); bool isLessThanEqual = (v.x <= w.x && v.y <= w.y); return isLessThanEqual; } template <class T> static bool greaterThanEqual(const Vec2<T> &v, const object &obj) { extract<Vec2<T> > e1(obj); extract<tuple> e2(obj); Vec2<T> w; if(e1.check()) { w = e1(); } else if(e2.check()) { tuple t = e2(); if(t.attr("__len__")() == 2){ T x = extract<T>(t[0]); T y = extract<T>(t[1]); w.setValue(x,y); } else throw std::invalid_argument ("Vec2 expects tuple of length 2"); } else throw std::invalid_argument ("invalid parameters passed to operator >="); bool isGreaterThanEqual = (v.x >= w.x && v.y >= w.y); return isGreaterThanEqual; } template <class T,class BoostPyType> static void setItemTuple(FixedArray<IMATH_NAMESPACE::Vec2<T> > &va, Py_ssize_t index, const BoostPyType &t) { if(t.attr("__len__")() == 2) { Vec2<T> v; v.x = extract<T>(t[0]); v.y = extract<T>(t[1]); va[va.canonical_index(index)] = v; } else throw std::invalid_argument ("tuple of length 2 expected"); } template <class T> static bool equalWithAbsErrorObj(const Vec2<T> &v, const object &obj1, const object &obj2) { extract<Vec2<int> > e1(obj1); extract<Vec2<float> > e2(obj1); extract<Vec2<double> > e3(obj1); extract<tuple> e4(obj1); extract<double> e5(obj2); Vec2<T> w; if(e1.check()) { w = e1(); } else if(e2.check()) { w = e2(); } else if(e3.check()) { w = e3(); } else if(e4.check()) { tuple t = e4(); if(t.attr("__len__")() == 2) { w.x = extract<T>(t[0]); w.y = extract<T>(t[1]); } else throw std::invalid_argument ("tuple of length 2 expected"); } else throw std::invalid_argument ("invalid parameters passed to equalWithAbsError"); if(e5.check()) { return v.equalWithAbsError(w, e5()); } else throw std::invalid_argument ("invalid parameters passed to equalWithAbsError"); } template <class T> static bool equalWithRelErrorObj(const Vec2<T> &v, const object &obj1, const object &obj2) { extract<Vec2<int> > e1(obj1); extract<Vec2<float> > e2(obj1); extract<Vec2<double> > e3(obj1); extract<tuple> e4(obj1); extract<double> e5(obj2); Vec2<T> w; if(e1.check()) { w = e1(); } else if(e2.check()) { w = e2(); } else if(e3.check()) { w = e3(); } else if(e4.check()) { tuple t = e4(); if(t.attr("__len__")() == 2) { w.x = extract<T>(t[0]); w.y = extract<T>(t[1]); } else throw std::invalid_argument ("tuple of length 2 expected"); } else throw std::invalid_argument ("invalid parameters passed to equalWithRelError"); if(e5.check()) { return v.equalWithRelError(w, e5()); } else throw std::invalid_argument ("invalid parameters passed to equalWithRelError"); } /* template <class T> static bool equalWithAbsErrorTuple(Vec2<T> &v, const tuple &t, T e) { Vec2<T> w; if(t.attr("__len__")() == 2) { w.x = extract<T>(t[0]); w.y = extract<T>(t[1]); } else throw std::invalid_argument ("tuple of length 2 expected"); return v.equalWithAbsError(w, e); } template <class T> static bool equalWithRelErrorTuple(Vec2<T> &v, const tuple &t, T e) { std::cout << "RelError Tuple called" << std::endl; Vec2<T> w; if(t.attr("__len__")() == 2) { w.x = extract<T>(t[0]); w.y = extract<T>(t[1]); } else throw std::invalid_argument ("tuple of length 2 expected"); return v.equalWithRelError(w, e); } */ template <class T,class BoostPyType> static bool equal(const Vec2<T> &v, const BoostPyType &t) { Vec2<T> w; if(t.attr("__len__")() == 2) { w.x = extract<T>(t[0]); w.y = extract<T>(t[1]); return (v == w); } else throw std::invalid_argument ("tuple of length 2 expected"); } template <class T,class BoostPyType> static bool notequal(const Vec2<T> &v, const BoostPyType &t) { Vec2<T> w; if(t.attr("__len__")() == 2) { w.x = extract<T>(t[0]); w.y = extract<T>(t[1]); return (v != w); } else throw std::invalid_argument ("tuple of length 2 expected"); } // Trick to register methods for float-only-based vectors template <class T, IMATH_ENABLE_IF(!std::is_integral<T>::value)> void register_Vec2_floatonly(class_<Vec2<T>>& vec2_class) { vec2_class .def("length", &Vec2_length<T>,"length() magnitude of the vector") .def("normalize", &Vec2_normalize<T>,return_internal_reference<>(), "v.normalize() destructively normalizes v and returns a reference to it") .def("normalizeExc", &Vec2_normalizeExc<T>,return_internal_reference<>(), "v.normalizeExc() destructively normalizes V and returns a reference to it, throwing an exception if length() == 0") .def("normalizeNonNull", &Vec2_normalizeNonNull<T>,return_internal_reference<>(), "v.normalizeNonNull() destructively normalizes V and returns a reference to it, faster if lngth() != 0") .def("normalized", &Vec2_normalized<T>, "v.normalized() returns a normalized copy of v") .def("normalizedExc", &Vec2_normalizedExc<T>, "v.normalizedExc() returns a normalized copy of v, throwing an exception if length() == 0") .def("normalizedNonNull", &Vec2_normalizedNonNull<T>, "v.normalizedNonNull() returns a normalized copy of v, faster if lngth() != 0") .def("orthogonal", &orthogonal<T>) .def("project", &project<T>) .def("reflect", &reflect<T>) ; } template <class T, IMATH_ENABLE_IF(std::is_integral<T>::value)> void register_Vec2_floatonly(class_<Vec2<T>>& vec2_class) { } template <class T> class_<Vec2<T> > register_Vec2() { typedef PyImath::StaticFixedArray<Vec2<T>,T,2> Vec2_helper; class_<Vec2<T> > vec2_class(Vec2Name<T>::value, Vec2Name<T>::value,init<Vec2<T> >("copy construction")); vec2_class .def("__init__",make_constructor(Vec2_construct_default<T>),"initialize to (0,0)") .def("__init__",make_constructor(Vec2_object_constructor1<T>)) .def("__init__",make_constructor(Vec2_object_constructor2<T>)) .def_readwrite("x", &Vec2<T>::x) .def_readwrite("y", &Vec2<T>::y) .def("baseTypeEpsilon", &Vec2<T>::baseTypeEpsilon,"baseTypeEpsilon() epsilon value of the base type of the vector") .staticmethod("baseTypeEpsilon") .def("baseTypeMax", &Vec2<T>::baseTypeMax,"baseTypeMax() max value of the base type of the vector") .staticmethod("baseTypeMax") .def("baseTypeLowest", &Vec2<T>::baseTypeLowest,"baseTypeLowest() largest negative value of the base type of the vector") .staticmethod("baseTypeLowest") .def("baseTypeSmallest", &Vec2<T>::baseTypeSmallest,"baseTypeSmallest() smallest value of the base type of the vector") .staticmethod("baseTypeSmallest") .def("cross", &Vec2_cross<T>,"v1.cross(v2) right handed cross product") .def("cross", &Vec2_cross_Vec2Array<T>,"v1.cross(v2) right handed array cross product") .def("dimensions", &Vec2<T>::dimensions,"dimensions() number of dimensions in the vector") .staticmethod("dimensions") .def("dot", &Vec2_dot<T>,"v1.dot(v2) inner product of the two vectors") .def("dot", &Vec2_dot_Vec2Array<T>,"v1.dot(v2) array inner product") .def("equalWithAbsError", &Vec2<T>::equalWithAbsError, "v1.equalWithAbsError(v2) true if the elements " "of v1 and v2 are the same with an absolute error of no more than e, " "i.e., abs(v1[i] - v2[i]) <= e") .def("equalWithAbsError", &equalWithAbsErrorObj<T>) .def("equalWithRelError", &Vec2<T>::equalWithRelError, "v1.equalWithAbsError(v2) true if the elements " "of v1 and v2 are the same with an absolute error of no more than e, " "i.e., abs(v1[i] - v2[i]) <= e * abs(v1[i])") .def("equalWithRelError", &equalWithRelErrorObj<T>) .def("length2", &Vec2_length2<T>,"length2() square magnitude of the vector") .def("__len__", Vec2_helper::len) .def("__getitem__", Vec2_helper::getitem,return_value_policy<copy_non_const_reference>()) .def("__setitem__", Vec2_helper::setitem) .def("closestVertex", &closestVertex<T>) .def("negate", &Vec2_negate<T>, return_internal_reference<>()) .def("setValue", &setValue<T>) .def("__neg__", &Vec2_neg<T>) .def("__mul__", &Vec2_mul<T, int>) .def("__mul__", &Vec2_mul<T, float>) .def("__mul__", &Vec2_mul<T, double>) .def("__mul__", &Vec2_mulT<T>) .def("__mul__", &Vec2_mulTArray<T>) .def("__mul__", &Vec2_mulTuple<T,tuple>) .def("__mul__", &Vec2_mulTuple<T,list>) .def("__rmul__", &Vec2_rmulT<T>) .def("__rmul__", &Vec2_rmulTArray<T>) .def("__rmul__", &Vec2_mulTuple<T,tuple>) .def("__rmul__", &Vec2_mulTuple<T,list>) .def("__imul__", &Vec2_imulV<T, int>,return_internal_reference<>()) .def("__imul__", &Vec2_imulV<T, float>,return_internal_reference<>()) .def("__imul__", &Vec2_imulV<T, double>,return_internal_reference<>()) .def("__imul__", &Vec2_imulT<T>,return_internal_reference<>()) .def(self * self) .def("__mul__", &Vec2_mulM22<T, float>) .def("__mul__", &Vec2_mulM22<T, double>) .def("__mul__", &Vec2_mulM33<T, float>) .def("__mul__", &Vec2_mulM33<T, double>) .def("__imul__", &Vec2_imulM22<T, float>, return_internal_reference<>()) .def("__imul__", &Vec2_imulM22<T, double>, return_internal_reference<>()) .def("__imul__", &Vec2_imulM33<T, float>, return_internal_reference<>()) .def("__imul__", &Vec2_imulM33<T, double>, return_internal_reference<>()) .def(self / self) // NOSONAR - suppress SonarCloud bug report. .def("__div__", &Vec2_div<T,int>) .def("__div__", &Vec2_div<T,float>) .def("__div__", &Vec2_div<T,double>) .def("__div__", &Vec2_divTuple<T,tuple>) .def("__div__", &Vec2_divTuple<T,list>) .def("__div__", &Vec2_divT<T>) .def("__truediv__", &Vec2_div<T,int>) .def("__truediv__", &Vec2_div<T,float>) .def("__truediv__", &Vec2_div<T,double>) .def("__truediv__", &Vec2_divTuple<T,tuple>) .def("__truediv__", &Vec2_divTuple<T,list>) .def("__truediv__", &Vec2_divT<T>) .def("__rdiv__", &Vec2_rdivTuple<T,tuple>) .def("__rdiv__", &Vec2_rdivTuple<T,list>) .def("__rdiv__", &Vec2_rdivT<T>) .def("__rtruediv__", &Vec2_rdivTuple<T,tuple>) .def("__rtruediv__", &Vec2_rdivTuple<T,list>) .def("__rtruediv__", &Vec2_rdivT<T>) .def("__idiv__", &Vec2_idivObj<T>,return_internal_reference<>()) .def("__itruediv__", &Vec2_idivObj<T>,return_internal_reference<>()) .def("__xor__", &Vec2_dot<T>) .def("__mod__", &Vec2_cross<T>) .def(self == self) // NOSONAR - suppress SonarCloud bug report. .def(self != self) // NOSONAR - suppress SonarCloud bug report. .def("__eq__", &equal<T,tuple>) .def("__ne__", ¬equal<T,tuple>) .def("__add__", &Vec2_add<T>) .def("__add__", &Vec2_addV<T, int>) .def("__add__", &Vec2_addV<T, float>) .def("__add__", &Vec2_addV<T, double>) .def("__add__", &Vec2_addT<T>) .def("__add__", &Vec2_addTuple<T,tuple>) .def("__add__", &Vec2_addTuple<T,list>) .def("__radd__", &Vec2_add<T>) .def("__radd__", &Vec2_addT<T>) .def("__radd__", &Vec2_addTuple<T,tuple>) .def("__radd__", &Vec2_addTuple<T,list>) .def("__iadd__", &Vec2_iaddV<T, int>, return_internal_reference<>()) .def("__iadd__", &Vec2_iaddV<T, float>, return_internal_reference<>()) .def("__iadd__", &Vec2_iaddV<T, double>, return_internal_reference<>()) .def("__sub__", &Vec2_sub<T>) .def("__sub__", &Vec2_subV<T, int>) .def("__sub__", &Vec2_subV<T, float>) .def("__sub__", &Vec2_subV<T, double>) .def("__sub__", &Vec2_subT<T>) .def("__sub__", &Vec2_subTuple<T,tuple>) .def("__sub__", &Vec2_subTuple<T,list>) .def("__rsub__", &Vec2_rsubT<T>) .def("__rsub__", &Vec2_rsubTuple<T,tuple>) .def("__rsub__", &Vec2_rsubTuple<T,list>) .def("__isub__", &Vec2_isubV<T, int>, return_internal_reference<>()) .def("__isub__", &Vec2_isubV<T, float>, return_internal_reference<>()) .def("__isub__", &Vec2_isubV<T, double>, return_internal_reference<>()) .def("__lt__", &lessThan<T>) .def("__gt__", &greaterThan<T>) .def("__le__", &lessThanEqual<T>) .def("__ge__", &greaterThanEqual<T>) //.def(self_ns::str(self)) .def("__str__",&Vec2_str<T>) .def("__repr__",&Vec2_repr<T>) ; register_Vec2_floatonly<T>(vec2_class); decoratecopy(vec2_class); //add_swizzle2_operators(v2f_class); return vec2_class; } // XXX fixme - template this // really this should get generated automatically... template <class T,int index> static FixedArray<T> Vec2Array_get(FixedArray<IMATH_NAMESPACE::Vec2<T> > &va) { return FixedArray<T>(&(va.unchecked_index(0)[index]), va.len(), 2*va.stride(), va.handle(), va.writable()); } template <class T> static IMATH_NAMESPACE::Vec2<T> Vec2Array_min(const FixedArray<IMATH_NAMESPACE::Vec2<T> > &a) { Vec2<T> tmp(Vec2<T>(0)); size_t len = a.len(); if (len > 0) tmp = a[0]; for (size_t i=1; i < len; ++i) { if (a[i].x < tmp.x) tmp.x = a[i].x; if (a[i].y < tmp.y) tmp.y = a[i].y; } return tmp; } template <class T> static IMATH_NAMESPACE::Vec2<T> Vec2Array_max(const FixedArray<IMATH_NAMESPACE::Vec2<T> > &a) { Vec2<T> tmp(Vec2<T>(0)); size_t len = a.len(); if (len > 0) tmp = a[0]; for (size_t i=1; i < len; ++i) { if (a[i].x > tmp.x) tmp.x = a[i].x; if (a[i].y > tmp.y) tmp.y = a[i].y; } return tmp; } template <class T> static IMATH_NAMESPACE::Box<IMATH_NAMESPACE::Vec2<T> > Vec2Array_bounds(const FixedArray<IMATH_NAMESPACE::Vec2<T> > &a) { Box<Vec2<T> > tmp; size_t len = a.len(); for (size_t i=0; i < len; ++i) tmp.extendBy(a[i]); return tmp; } // Trick to register methods for float-only-based vectors template <class T, IMATH_ENABLE_IF(!std::is_integral<T>::value)> void register_Vec2Array_floatonly(class_<FixedArray<Vec2<T>>>& vec2Array_class) { generate_member_bindings<op_vecLength<IMATH_NAMESPACE::Vec2<T> > >(vec2Array_class,"length",""); generate_member_bindings<op_vecNormalize<IMATH_NAMESPACE::Vec2<T> > >(vec2Array_class,"normalize",""); generate_member_bindings<op_vecNormalized<IMATH_NAMESPACE::Vec2<T> > >(vec2Array_class,"normalized",""); generate_member_bindings<op_vecNormalizeExc<IMATH_NAMESPACE::Vec2<T> > >(vec2Array_class,"normalizeExc",""); generate_member_bindings<op_vecNormalizedExc<IMATH_NAMESPACE::Vec2<T> > >(vec2Array_class,"normalizedExc",""); } template <class T, IMATH_ENABLE_IF(std::is_integral<T>::value)> void register_Vec2Array_floatonly(class_<FixedArray<Vec2<T>>>& vec2Array_class) { } template <class T> class_<FixedArray<IMATH_NAMESPACE::Vec2<T> > > register_Vec2Array() { using boost::mpl::true_; using boost::mpl::false_; class_<FixedArray<IMATH_NAMESPACE::Vec2<T> > > vec2Array_class = FixedArray<IMATH_NAMESPACE::Vec2<T> >::register_("Fixed length array of IMATH_NAMESPACE::Vec2"); vec2Array_class .add_property("x",&Vec2Array_get<T,0>) .add_property("y",&Vec2Array_get<T,1>) .def("__setitem__", &setItemTuple<T,tuple>) .def("__setitem__", &setItemTuple<T,list>) .def("min", &Vec2Array_min<T>) .def("max", &Vec2Array_max<T>) .def("bounds", &Vec2Array_bounds<T>) ; add_arithmetic_math_functions(vec2Array_class); add_comparison_functions(vec2Array_class); register_Vec2Array_floatonly(vec2Array_class); generate_member_bindings<op_vecLength2<IMATH_NAMESPACE::Vec2<T> > >(vec2Array_class,"length2",""); generate_member_bindings<op_vec2Cross<T>, true_>(vec2Array_class,"cross","return the cross product of (self,x)",boost::python::args("x")); generate_member_bindings<op_vecDot<IMATH_NAMESPACE::Vec2<T> >,true_>(vec2Array_class,"dot","return the inner product of (self,x)",boost::python::args("x")); generate_member_bindings<op_mul<IMATH_NAMESPACE::Vec2<T>,T>, true_>(vec2Array_class,"__mul__" ,"self*x", boost::python::args("x")); generate_member_bindings<op_mul<IMATH_NAMESPACE::Vec2<T>,T>, true_>(vec2Array_class,"__rmul__","x*self", boost::python::args("x")); generate_member_bindings<op_imul<IMATH_NAMESPACE::Vec2<T>,T>, true_>(vec2Array_class,"__imul__","self*=x",boost::python::args("x")); generate_member_bindings<op_div<IMATH_NAMESPACE::Vec2<T>,T>, true_>(vec2Array_class,"__div__" ,"self/x", boost::python::args("x")); generate_member_bindings<op_div<IMATH_NAMESPACE::Vec2<T>,T>, true_>(vec2Array_class,"__truediv__" ,"self/x", boost::python::args("x")); generate_member_bindings<op_idiv<IMATH_NAMESPACE::Vec2<T>,T>, true_>(vec2Array_class,"__idiv__","self/=x",boost::python::args("x")); generate_member_bindings<op_idiv<IMATH_NAMESPACE::Vec2<T>,T>, true_>(vec2Array_class,"__itruediv__","self/=x",boost::python::args("x")); decoratecopy(vec2Array_class); return vec2Array_class; } } #endif halfLimits.h 0000644 00000005527 15125213144 0007020 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // Primary origin authors: // Florian Kainz <kainz@ilm.com> // Rod Bogart <rgb@ilm.com> // #ifndef INCLUDED_HALF_LIMITS_H #define INCLUDED_HALF_LIMITS_H //------------------------------------------------------------------------ // // C++ standard library-style numeric_limits for class half // //------------------------------------------------------------------------ #include "half.h" #include <limits> /// @cond Doxygen_Suppress namespace std { template <> class numeric_limits<half> { public: static const bool is_specialized = true; static constexpr half min() IMATH_NOEXCEPT { return half(half::FromBits, 0x0400); /*HALF_MIN*/ } static constexpr half max() IMATH_NOEXCEPT { return half(half::FromBits, 0x7bff); /*HALF_MAX*/ } static constexpr half lowest() { return half(half::FromBits, 0xfbff); /* -HALF_MAX */ } static constexpr int digits = HALF_MANT_DIG; static constexpr int digits10 = HALF_DIG; static constexpr int max_digits10 = HALF_DECIMAL_DIG; static constexpr bool is_signed = true; static constexpr bool is_integer = false; static constexpr bool is_exact = false; static constexpr int radix = HALF_RADIX; static constexpr half epsilon() IMATH_NOEXCEPT { return half(half::FromBits, 0x1400); /*HALF_EPSILON*/ } static constexpr half round_error() IMATH_NOEXCEPT { return half(half::FromBits, 0x3800); /*0.5*/ } static constexpr int min_exponent = HALF_DENORM_MIN_EXP; static constexpr int min_exponent10 = HALF_DENORM_MIN_10_EXP; static constexpr int max_exponent = HALF_MAX_EXP; static constexpr int max_exponent10 = HALF_MAX_10_EXP; static constexpr bool has_infinity = true; static constexpr bool has_quiet_NaN = true; static constexpr bool has_signaling_NaN = true; static constexpr float_denorm_style has_denorm = denorm_present; static constexpr bool has_denorm_loss = false; static constexpr half infinity() IMATH_NOEXCEPT { return half(half::FromBits, 0x7c00); /*half::posInf()*/ } static constexpr half quiet_NaN() IMATH_NOEXCEPT { return half(half::FromBits, 0x7fff); /*half::qNan()*/ } static constexpr half signaling_NaN() IMATH_NOEXCEPT { return half(half::FromBits, 0x7dff); /*half::sNan()*/ } static constexpr half denorm_min() IMATH_NOEXCEPT { return half(half::FromBits, 0x0001); /*HALF_DENORM_MIN*/ } static constexpr bool is_iec559 = false; static constexpr bool is_bounded = false; static constexpr bool is_modulo = false; static constexpr bool traps = true; static constexpr bool tinyness_before = false; static constexpr float_round_style round_style = round_to_nearest; }; /// @endcond } // namespace std #endif PyImathVec4ArrayImpl.h 0000644 00000012753 15125213144 0010641 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathVec4ArrayImpl_h_ #define _PyImathVec4ArrayImpl_h_ // // This .C file was turned into a header file so that instantiations // of the various V4* types can be spread across multiple files in // order to work around MSVC limitations. // #include <Python.h> #include <boost/python.hpp> #include <boost/python/make_constructor.hpp> #include <boost/format.hpp> #include <ImathVec.h> #include <ImathVecAlgo.h> #include "PyImath.h" #include "PyImathVec.h" #include "PyImathDecorators.h" #include "PyImathMathExc.h" #include "PyImathOperators.h" #include "PyImathVecOperators.h" namespace PyImath { using namespace boost::python; using namespace IMATH_NAMESPACE; // XXX fixme - template this // really this should get generated automatically... template <class T,int index> static FixedArray<T> Vec4Array_get(FixedArray<IMATH_NAMESPACE::Vec4<T> > &va) { return FixedArray<T>(&(va.unchecked_index(0)[index]), va.len(), 4*va.stride(), va.handle(), va.writable()); } template <class T> static void setItemTuple(FixedArray<IMATH_NAMESPACE::Vec4<T> > &va, Py_ssize_t index, const tuple &t) { if(t.attr("__len__")() == 4) { Vec4<T> v; v.x = extract<T>(t[0]); v.y = extract<T>(t[1]); v.z = extract<T>(t[2]); v.w = extract<T>(t[3]); va[va.canonical_index(index)] = v; } else throw std::invalid_argument ("tuple of length 4 expected"); } template <class T> static IMATH_NAMESPACE::Vec4<T> Vec4Array_min(const FixedArray<IMATH_NAMESPACE::Vec4<T> > &a) { Vec4<T> tmp(Vec4<T>(0)); size_t len = a.len(); if (len > 0) tmp = a[0]; for (size_t i=1; i < len; ++i) { if (a[i].x < tmp.x) tmp.x = a[i].x; if (a[i].y < tmp.y) tmp.y = a[i].y; if (a[i].z < tmp.z) tmp.z = a[i].z; if (a[i].w < tmp.w) tmp.w = a[i].w; } return tmp; } template <class T> static IMATH_NAMESPACE::Vec4<T> Vec4Array_max(const FixedArray<IMATH_NAMESPACE::Vec4<T> > &a) { Vec4<T> tmp(Vec4<T>(0)); size_t len = a.len(); if (len > 0) tmp = a[0]; for (size_t i=1; i < len; ++i) { if (a[i].x > tmp.x) tmp.x = a[i].x; if (a[i].y > tmp.y) tmp.y = a[i].y; if (a[i].z > tmp.z) tmp.z = a[i].z; if (a[i].w > tmp.w) tmp.w = a[i].w; } return tmp; } // Trick to register methods for float-only-based vectors template <class T, IMATH_ENABLE_IF(!std::is_integral<T>::value)> void register_Vec4Array_floatonly(class_<FixedArray<Vec4<T>>>& vec4Array_class) { generate_member_bindings<op_vecLength<IMATH_NAMESPACE::Vec4<T> > >(vec4Array_class,"length",""); generate_member_bindings<op_vecNormalize<IMATH_NAMESPACE::Vec4<T> > >(vec4Array_class,"normalize",""); generate_member_bindings<op_vecNormalized<IMATH_NAMESPACE::Vec4<T> > >(vec4Array_class,"normalized",""); generate_member_bindings<op_vecNormalizeExc<IMATH_NAMESPACE::Vec4<T> > >(vec4Array_class,"normalizeExc",""); generate_member_bindings<op_vecNormalizedExc<IMATH_NAMESPACE::Vec4<T> > >(vec4Array_class,"normalizedExc",""); } template <class T, IMATH_ENABLE_IF(std::is_integral<T>::value)> void register_Vec4Array_floatonly(class_<FixedArray<Vec4<T>>>& vec4Array_class) { } template <class T> class_<FixedArray<IMATH_NAMESPACE::Vec4<T> > > register_Vec4Array() { using boost::mpl::true_; class_<FixedArray<IMATH_NAMESPACE::Vec4<T> > > vec4Array_class = FixedArray<IMATH_NAMESPACE::Vec4<T> >::register_("Fixed length array of IMATH_NAMESPACE::Vec4"); vec4Array_class .add_property("x",&Vec4Array_get<T,0>) .add_property("y",&Vec4Array_get<T,1>) .add_property("z",&Vec4Array_get<T,2>) .add_property("w",&Vec4Array_get<T,3>) .def("__setitem__", &setItemTuple<T>) .def("min", &Vec4Array_min<T>) .def("max", &Vec4Array_max<T>) ; add_arithmetic_math_functions(vec4Array_class); add_comparison_functions(vec4Array_class); register_Vec4Array_floatonly(vec4Array_class); generate_member_bindings<op_vecLength2<IMATH_NAMESPACE::Vec4<T> > >(vec4Array_class,"length2",""); generate_member_bindings<op_vecDot<IMATH_NAMESPACE::Vec4<T> >,true_>(vec4Array_class,"dot","return the inner product of (self,x)",boost::python::args("x")); generate_member_bindings<op_mul<IMATH_NAMESPACE::Vec4<T>,T>, true_>(vec4Array_class,"__mul__" ,"self*x", boost::python::args("x")); generate_member_bindings<op_mul<IMATH_NAMESPACE::Vec4<T>,T>, true_>(vec4Array_class,"__rmul__","x*self", boost::python::args("x")); generate_member_bindings<op_imul<IMATH_NAMESPACE::Vec4<T>,T>, true_>(vec4Array_class,"__imul__","self*=x",boost::python::args("x")); generate_member_bindings<op_div<IMATH_NAMESPACE::Vec4<T>,T>, true_>(vec4Array_class,"__div__" ,"self/x", boost::python::args("x")); generate_member_bindings<op_div<IMATH_NAMESPACE::Vec4<T>,T>, true_>(vec4Array_class,"__truediv__" ,"self/x", boost::python::args("x")); generate_member_bindings<op_idiv<IMATH_NAMESPACE::Vec4<T>,T>, true_>(vec4Array_class,"__idiv__","self/=x",boost::python::args("x")); generate_member_bindings<op_idiv<IMATH_NAMESPACE::Vec4<T>,T>, true_>(vec4Array_class,"__itruediv__","self/=x",boost::python::args("x")); decoratecopy(vec4Array_class); return vec4Array_class; } } // namespace PyImath #endif // _PyImathVec4ArrayImpl_h_ half.h 0000644 00000056670 15125213144 0005643 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // Primary original authors: // Florian Kainz <kainz@ilm.com> // Rod Bogart <rgb@ilm.com> // #ifndef IMATH_HALF_H_ #define IMATH_HALF_H_ #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathPlatform.h" /// @file half.h /// The half type is a 16-bit floating number, compatible with the /// IEEE 754-2008 binary16 type. /// /// **Representation of a 32-bit float:** /// /// We assume that a float, f, is an IEEE 754 single-precision /// floating point number, whose bits are arranged as follows: /// /// 31 (msb) /// | /// | 30 23 /// | | | /// | | | 22 0 (lsb) /// | | | | | /// X XXXXXXXX XXXXXXXXXXXXXXXXXXXXXXX /// /// s e m /// /// S is the sign-bit, e is the exponent and m is the significand. /// /// If e is between 1 and 254, f is a normalized number: /// /// s e-127 /// f = (-1) * 2 * 1.m /// /// If e is 0, and m is not zero, f is a denormalized number: /// /// s -126 /// f = (-1) * 2 * 0.m /// /// If e and m are both zero, f is zero: /// /// f = 0.0 /// /// If e is 255, f is an "infinity" or "not a number" (NAN), /// depending on whether m is zero or not. /// /// Examples: /// /// 0 00000000 00000000000000000000000 = 0.0 /// 0 01111110 00000000000000000000000 = 0.5 /// 0 01111111 00000000000000000000000 = 1.0 /// 0 10000000 00000000000000000000000 = 2.0 /// 0 10000000 10000000000000000000000 = 3.0 /// 1 10000101 11110000010000000000000 = -124.0625 /// 0 11111111 00000000000000000000000 = +infinity /// 1 11111111 00000000000000000000000 = -infinity /// 0 11111111 10000000000000000000000 = NAN /// 1 11111111 11111111111111111111111 = NAN /// /// **Representation of a 16-bit half:** /// /// Here is the bit-layout for a half number, h: /// /// 15 (msb) /// | /// | 14 10 /// | | | /// | | | 9 0 (lsb) /// | | | | | /// X XXXXX XXXXXXXXXX /// /// s e m /// /// S is the sign-bit, e is the exponent and m is the significand. /// /// If e is between 1 and 30, h is a normalized number: /// /// s e-15 /// h = (-1) * 2 * 1.m /// /// If e is 0, and m is not zero, h is a denormalized number: /// /// S -14 /// h = (-1) * 2 * 0.m /// /// If e and m are both zero, h is zero: /// /// h = 0.0 /// /// If e is 31, h is an "infinity" or "not a number" (NAN), /// depending on whether m is zero or not. /// /// Examples: /// /// 0 00000 0000000000 = 0.0 /// 0 01110 0000000000 = 0.5 /// 0 01111 0000000000 = 1.0 /// 0 10000 0000000000 = 2.0 /// 0 10000 1000000000 = 3.0 /// 1 10101 1111000001 = -124.0625 /// 0 11111 0000000000 = +infinity /// 1 11111 0000000000 = -infinity /// 0 11111 1000000000 = NAN /// 1 11111 1111111111 = NAN /// /// **Conversion via Lookup Table:** /// /// Converting from half to float is performed by default using a /// lookup table. There are only 65,536 different half numbers; each /// of these numbers has been converted and stored in a table pointed /// to by the ``imath_half_to_float_table`` pointer. /// /// Prior to Imath v3.1, conversion from float to half was /// accomplished with the help of an exponent look table, but this is /// now replaced with explicit bit shifting. /// /// **Conversion via Hardware:** /// /// For Imath v3.1, the conversion routines have been extended to use /// F16C SSE instructions whenever present and enabled by compiler /// flags. /// /// **Conversion via Bit-Shifting** /// /// If F16C SSE instructions are not available, conversion can be /// accomplished by a bit-shifting algorithm. For half-to-float /// conversion, this is generally slower than the lookup table, but it /// may be preferable when memory limits preclude storing of the /// 65,536-entry lookup table. /// /// The lookup table symbol is included in the compilation even if /// ``IMATH_HALF_USE_LOOKUP_TABLE`` is false, because application code /// using the exported ``half.h`` may choose to enable the use of the table. /// /// An implementation can eliminate the table from compilation by /// defining the ``IMATH_HALF_NO_LOOKUP_TABLE`` preprocessor symbol. /// Simply add: /// /// #define IMATH_HALF_NO_LOOKUP_TABLE /// /// before including ``half.h``, or define the symbol on the compile /// command line. /// /// Furthermore, an implementation wishing to receive ``FE_OVERFLOW`` /// and ``FE_UNDERFLOW`` floating point exceptions when converting /// float to half by the bit-shift algorithm can define the /// preprocessor symbol ``IMATH_HALF_ENABLE_FP_EXCEPTIONS`` prior to /// including ``half.h``: /// /// #define IMATH_HALF_ENABLE_FP_EXCEPTIONS /// /// **Conversion Performance Comparison:** /// /// Testing on a Core i9, the timings are approximately: /// /// half to float /// - table: 0.71 ns / call /// - no table: 1.06 ns / call /// - f16c: 0.45 ns / call /// /// float-to-half: /// - original: 5.2 ns / call /// - no exp table + opt: 1.27 ns / call /// - f16c: 0.45 ns / call /// /// **Note:** the timing above depends on the distribution of the /// floats in question. /// #ifdef _WIN32 # include <intrin.h> #elif defined(__x86_64__) # include <x86intrin.h> #endif #include <stdint.h> #include <stdio.h> #ifdef IMATH_HALF_ENABLE_FP_EXCEPTIONS # include <fenv.h> #endif //------------------------------------------------------------------------- // Limits // // Visual C++ will complain if HALF_DENORM_MIN, HALF_NRM_MIN etc. are not float // constants, but at least one other compiler (gcc 2.96) produces incorrect // results if they are. //------------------------------------------------------------------------- #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER /// Smallest positive denormalized half # define HALF_DENORM_MIN 5.96046448e-08f /// Smallest positive normalized half # define HALF_NRM_MIN 6.10351562e-05f /// Smallest positive normalized half # define HALF_MIN 6.10351562e-05f /// Largest positive half # define HALF_MAX 65504.0f /// Smallest positive e for which ``half(1.0 + e) != half(1.0)`` # define HALF_EPSILON 0.00097656f #else /// Smallest positive denormalized half # define HALF_DENORM_MIN 5.96046448e-08 /// Smallest positive normalized half # define HALF_NRM_MIN 6.10351562e-05 /// Smallest positive normalized half # define HALF_MIN 6.10351562e-05f /// Largest positive half # define HALF_MAX 65504.0 /// Smallest positive e for which ``half(1.0 + e) != half(1.0)`` # define HALF_EPSILON 0.00097656 #endif /// Number of digits in mantissa (significand + hidden leading 1) #define HALF_MANT_DIG 11 /// Number of base 10 digits that can be represented without change: /// /// ``floor( (HALF_MANT_DIG - 1) * log10(2) ) => 3.01... -> 3`` #define HALF_DIG 3 /// Number of base-10 digits that are necessary to uniquely represent /// all distinct values: /// /// ``ceil(HALF_MANT_DIG * log10(2) + 1) => 4.31... -> 5`` #define HALF_DECIMAL_DIG 5 /// Base of the exponent #define HALF_RADIX 2 /// Minimum negative integer such that ``HALF_RADIX`` raised to the power /// of one less than that integer is a normalized half #define HALF_DENORM_MIN_EXP -13 /// Maximum positive integer such that ``HALF_RADIX`` raised to the power /// of one less than that integer is a normalized half #define HALF_MAX_EXP 16 /// Minimum positive integer such that 10 raised to that power is a /// normalized half #define HALF_DENORM_MIN_10_EXP -4 /// Maximum positive integer such that 10 raised to that power is a /// normalized half #define HALF_MAX_10_EXP 4 /// a type for both C-only programs and C++ to use the same utilities typedef union imath_half_uif { uint32_t i; float f; } imath_half_uif_t; /// a type for both C-only programs and C++ to use the same utilities typedef uint16_t imath_half_bits_t; #if !defined(__cplusplus) && !defined(__CUDACC__) /// if we're in a C-only context, alias the half bits type to half typedef imath_half_bits_t half; #endif #if !defined(IMATH_HALF_NO_LOOKUP_TABLE) # if defined(__cplusplus) extern "C" # else extern # endif IMATH_EXPORT const imath_half_uif_t* imath_half_to_float_table; #endif /// /// Convert half to float /// static inline float imath_half_to_float (imath_half_bits_t h) { #if defined(__F16C__) // NB: The intel implementation does seem to treat NaN slightly // different than the original toFloat table does (i.e. where the // 1 bits are, meaning the signalling or not bits). This seems // benign, given that the original library didn't really deal with // signalling vs non-signalling NaNs # ifdef _MSC_VER /* msvc does not seem to have cvtsh_ss :( */ return _mm_cvtss_f32 (_mm_cvtph_ps (_mm_set1_epi16 (h))); # else return _cvtsh_ss (h); # endif #elif defined(IMATH_HALF_USE_LOOKUP_TABLE) && !defined(IMATH_HALF_NO_LOOKUP_TABLE) return imath_half_to_float_table[h].f; #else imath_half_uif_t v; // this code would be clearer, although it does appear to be faster // (1.06 vs 1.08 ns/call) to avoid the constants and just do 4 // shifts. // uint32_t hexpmant = ( (uint32_t)(h) << 17 ) >> 4; v.i = ((uint32_t)(h >> 15)) << 31; // the likely really does help if most of your numbers are "normal" half numbers if (IMATH_LIKELY ((hexpmant >= 0x00800000))) { v.i |= hexpmant; // either we are a normal number, in which case add in the bias difference // otherwise make sure all exponent bits are set if (IMATH_LIKELY ((hexpmant < 0x0f800000))) v.i += 0x38000000; else v.i |= 0x7f800000; } else if (hexpmant != 0) { // exponent is 0 because we're denormal, don't have to extract // the mantissa, can just use as is // // // other compilers may provide count-leading-zeros primitives, // but we need the community to inform us of the variants uint32_t lc; # if defined(_MSC_VER) lc = __lzcnt (hexpmant); # elif defined(__GNUC__) || defined(__clang__) lc = (uint32_t) __builtin_clz (hexpmant); # else lc = 0; while (0 == ((hexpmant << lc) & 0x80000000)) ++lc; # endif lc -= 8; // so nominally we want to remove that extra bit we shifted // up, but we are going to add that bit back in, then subtract // from it with the 0x38800000 - (lc << 23).... // // by combining, this allows us to skip the & operation (and // remove a constant) // // hexpmant &= ~0x00800000; v.i |= 0x38800000; // lc is now x, where the desired exponent is then // -14 - lc // + 127 -> new exponent v.i |= (hexpmant << lc); v.i -= (lc << 23); } return v.f; #endif } /// /// Convert half to float /// /// Note: This only supports the "round to even" rounding mode, which /// was the only mode supported by the original OpenEXR library /// static inline imath_half_bits_t imath_float_to_half (float f) { #if defined(__F16C__) # ifdef _MSC_VER // msvc does not seem to have cvtsh_ss :( return _mm_extract_epi16 ( _mm_cvtps_ph (_mm_set_ss (f), (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)), 0); # else // preserve the fixed rounding mode to nearest return _cvtss_sh (f, (_MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC)); # endif #else imath_half_uif_t v; imath_half_bits_t ret; uint32_t e, m, ui, r, shift; v.f = f; ui = (v.i & ~0x80000000); ret = ((v.i >> 16) & 0x8000); // exponent large enough to result in a normal number, round and return if (ui >= 0x38800000) { // inf or nan if (IMATH_UNLIKELY (ui >= 0x7f800000)) { ret |= 0x7c00; if (ui == 0x7f800000) return ret; m = (ui & 0x7fffff) >> 13; // make sure we have at least one bit after shift to preserve nan-ness return ret | (uint16_t)m | (uint16_t)(m == 0); } // too large, round to infinity if (IMATH_UNLIKELY (ui > 0x477fefff)) { # ifdef IMATH_HALF_ENABLE_FP_EXCEPTIONS feraiseexcept (FE_OVERFLOW); # endif return ret | 0x7c00; } ui -= 0x38000000; ui = ((ui + 0x00000fff + ((ui >> 13) & 1)) >> 13); return ret | (uint16_t)ui; } // zero or flush to 0 if (ui < 0x33000001) { # ifdef IMATH_HALF_ENABLE_FP_EXCEPTIONS if (ui == 0) return ret; feraiseexcept (FE_UNDERFLOW); # endif return ret; } // produce a denormalized half e = (ui >> 23); shift = 0x7e - e; m = 0x800000 | (ui & 0x7fffff); r = m << (32 - shift); ret |= (m >> shift); if (r > 0x80000000 || (r == 0x80000000 && (ret & 0x1) != 0)) ++ret; return ret; #endif } //////////////////////////////////////// #ifdef __cplusplus # include <iostream> IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// /// /// class half -- 16-bit floating point number /// /// Type half can represent positive and negative numbers whose /// magnitude is between roughly 6.1e-5 and 6.5e+4 with a relative /// error of 9.8e-4; numbers smaller than 6.1e-5 can be represented /// with an absolute error of 6.0e-8. All integers from -2048 to /// +2048 can be represented exactly. /// /// Type half behaves (almost) like the built-in C++ floating point /// types. In arithmetic expressions, half, float and double can be /// mixed freely. Here are a few examples: /// /// half a (3.5); /// float b (a + sqrt (a)); /// a += b; /// b += a; /// b = a + 7; /// /// Conversions from half to float are lossless; all half numbers /// are exactly representable as floats. /// /// Conversions from float to half may not preserve a float's value /// exactly. If a float is not representable as a half, then the /// float value is rounded to the nearest representable half. If a /// float value is exactly in the middle between the two closest /// representable half values, then the float value is rounded to /// the closest half whose least significant bit is zero. /// /// Overflows during float-to-half conversions cause arithmetic /// exceptions. An overflow occurs when the float value to be /// converted is too large to be represented as a half, or if the /// float value is an infinity or a NAN. /// /// The implementation of type half makes the following assumptions /// about the implementation of the built-in C++ types: /// /// * float is an IEEE 754 single-precision number /// * sizeof (float) == 4 /// * sizeof (unsigned int) == sizeof (float) /// * alignof (unsigned int) == alignof (float) /// * sizeof (uint16_t) == 2 /// class IMATH_EXPORT_TYPE half { public: /// A special tag that lets us initialize a half from the raw bits. enum IMATH_EXPORT_ENUM FromBitsTag { FromBits }; /// @{ /// @name Constructors /// Default construction provides no initialization (hence it is /// not constexpr). half() IMATH_NOEXCEPT = default; /// Construct from float half (float f) IMATH_NOEXCEPT; /// Construct from bit-vector constexpr half (FromBitsTag, uint16_t bits) IMATH_NOEXCEPT; /// Copy constructor constexpr half (const half&) IMATH_NOEXCEPT = default; /// Move constructor constexpr half (half&&) IMATH_NOEXCEPT = default; /// Destructor ~half() IMATH_NOEXCEPT = default; /// @} /// Conversion to float operator float() const IMATH_NOEXCEPT; /// @{ /// @name Basic Algebra /// Unary minus constexpr half operator-() const IMATH_NOEXCEPT; /// Assignment half& operator= (const half& h) IMATH_NOEXCEPT = default; /// Move assignment half& operator= (half&& h) IMATH_NOEXCEPT = default; /// Assignment from float half& operator= (float f) IMATH_NOEXCEPT; /// Addition assignment half& operator+= (half h) IMATH_NOEXCEPT; /// Addition assignment from float half& operator+= (float f) IMATH_NOEXCEPT; /// Subtraction assignment half& operator-= (half h) IMATH_NOEXCEPT; /// Subtraction assignment from float half& operator-= (float f) IMATH_NOEXCEPT; /// Multiplication assignment half& operator*= (half h) IMATH_NOEXCEPT; /// Multiplication assignment from float half& operator*= (float f) IMATH_NOEXCEPT; /// Division assignment half& operator/= (half h) IMATH_NOEXCEPT; /// Division assignment from float half& operator/= (float f) IMATH_NOEXCEPT; /// @} /// Round to n-bit precision (n should be between 0 and 10). /// After rounding, the significand's 10-n least significant /// bits will be zero. IMATH_CONSTEXPR14 half round (unsigned int n) const IMATH_NOEXCEPT; /// @{ /// @name Classification /// Return true if a normalized number, a denormalized number, or /// zero. constexpr bool isFinite() const IMATH_NOEXCEPT; /// Return true if a normalized number. constexpr bool isNormalized() const IMATH_NOEXCEPT; /// Return true if a denormalized number. constexpr bool isDenormalized() const IMATH_NOEXCEPT; /// Return true if zero. constexpr bool isZero() const IMATH_NOEXCEPT; /// Return true if NAN. constexpr bool isNan() const IMATH_NOEXCEPT; /// Return true if a positive or a negative infinity constexpr bool isInfinity() const IMATH_NOEXCEPT; /// Return true if the sign bit is set (negative) constexpr bool isNegative() const IMATH_NOEXCEPT; /// @} /// @{ /// @name Special values /// Return +infinity static constexpr half posInf() IMATH_NOEXCEPT; /// Return -infinity static constexpr half negInf() IMATH_NOEXCEPT; /// Returns a NAN with the bit pattern 0111111111111111 static constexpr half qNan() IMATH_NOEXCEPT; /// Return a NAN with the bit pattern 0111110111111111 static constexpr half sNan() IMATH_NOEXCEPT; /// @} /// @{ /// @name Access to the internal representation /// Return the bit pattern IMATH_EXPORT constexpr uint16_t bits() const IMATH_NOEXCEPT; /// Set the bit pattern IMATH_EXPORT IMATH_CONSTEXPR14 void setBits (uint16_t bits) IMATH_NOEXCEPT; /// @} public: static_assert (sizeof (float) == sizeof (uint32_t), "Assumption about the size of floats correct"); using uif = imath_half_uif; private: constexpr uint16_t mantissa() const IMATH_NOEXCEPT; constexpr uint16_t exponent() const IMATH_NOEXCEPT; uint16_t _h; }; //---------------------------- // Half-from-float constructor //---------------------------- inline half::half (float f) IMATH_NOEXCEPT : _h (imath_float_to_half (f)) { } //------------------------------------------ // Half from raw bits constructor //------------------------------------------ inline constexpr half::half (FromBitsTag, uint16_t bits) IMATH_NOEXCEPT : _h (bits) {} //------------------------- // Half-to-float conversion //------------------------- inline half::operator float() const IMATH_NOEXCEPT { return imath_half_to_float (_h); } //------------------------- // Round to n-bit precision //------------------------- inline IMATH_CONSTEXPR14 half half::round (unsigned int n) const IMATH_NOEXCEPT { // // Parameter check. // if (n >= 10) return *this; // // Disassemble h into the sign, s, // and the combined exponent and significand, e. // uint16_t s = _h & 0x8000; uint16_t e = _h & 0x7fff; // // Round the exponent and significand to the nearest value // where ones occur only in the (10-n) most significant bits. // Note that the exponent adjusts automatically if rounding // up causes the significand to overflow. // e >>= 9 - n; e += e & 1; e <<= 9 - n; // // Check for exponent overflow. // if (e >= 0x7c00) { // // Overflow occurred -- truncate instead of rounding. // e = _h; e >>= 10 - n; e <<= 10 - n; } // // Put the original sign bit back. // half h (FromBits, s | e); return h; } //----------------------- // Other inline functions //----------------------- inline constexpr half half::operator-() const IMATH_NOEXCEPT { return half (FromBits, bits() ^ 0x8000); } inline half& half::operator= (float f) IMATH_NOEXCEPT { *this = half (f); return *this; } inline half& half::operator+= (half h) IMATH_NOEXCEPT { *this = half (float (*this) + float (h)); return *this; } inline half& half::operator+= (float f) IMATH_NOEXCEPT { *this = half (float (*this) + f); return *this; } inline half& half::operator-= (half h) IMATH_NOEXCEPT { *this = half (float (*this) - float (h)); return *this; } inline half& half::operator-= (float f) IMATH_NOEXCEPT { *this = half (float (*this) - f); return *this; } inline half& half::operator*= (half h) IMATH_NOEXCEPT { *this = half (float (*this) * float (h)); return *this; } inline half& half::operator*= (float f) IMATH_NOEXCEPT { *this = half (float (*this) * f); return *this; } inline half& half::operator/= (half h) IMATH_NOEXCEPT { *this = half (float (*this) / float (h)); return *this; } inline half& half::operator/= (float f) IMATH_NOEXCEPT { *this = half (float (*this) / f); return *this; } inline constexpr uint16_t half::mantissa() const IMATH_NOEXCEPT { return _h & 0x3ff; } inline constexpr uint16_t half::exponent() const IMATH_NOEXCEPT { return (_h >> 10) & 0x001f; } inline constexpr bool half::isFinite() const IMATH_NOEXCEPT { return exponent() < 31; } inline constexpr bool half::isNormalized() const IMATH_NOEXCEPT { return exponent() > 0 && exponent() < 31; } inline constexpr bool half::isDenormalized() const IMATH_NOEXCEPT { return exponent() == 0 && mantissa() != 0; } inline constexpr bool half::isZero() const IMATH_NOEXCEPT { return (_h & 0x7fff) == 0; } inline constexpr bool half::isNan() const IMATH_NOEXCEPT { return exponent() == 31 && mantissa() != 0; } inline constexpr bool half::isInfinity() const IMATH_NOEXCEPT { return exponent() == 31 && mantissa() == 0; } inline constexpr bool half::isNegative() const IMATH_NOEXCEPT { return (_h & 0x8000) != 0; } inline constexpr half half::posInf() IMATH_NOEXCEPT { return half (FromBits, 0x7c00); } inline constexpr half half::negInf() IMATH_NOEXCEPT { return half (FromBits, 0xfc00); } inline constexpr half half::qNan() IMATH_NOEXCEPT { return half (FromBits, 0x7fff); } inline constexpr half half::sNan() IMATH_NOEXCEPT { return half (FromBits, 0x7dff); } inline constexpr uint16_t half::bits() const IMATH_NOEXCEPT { return _h; } inline IMATH_CONSTEXPR14 void half::setBits (uint16_t bits) IMATH_NOEXCEPT { _h = bits; } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT /// Output h to os, formatted as a float IMATH_EXPORT std::ostream& operator<< (std::ostream& os, IMATH_INTERNAL_NAMESPACE::half h); /// Input h from is IMATH_EXPORT std::istream& operator>> (std::istream& is, IMATH_INTERNAL_NAMESPACE::half& h); //---------- // Debugging //---------- IMATH_EXPORT void printBits (std::ostream& os, IMATH_INTERNAL_NAMESPACE::half h); IMATH_EXPORT void printBits (std::ostream& os, float f); IMATH_EXPORT void printBits (char c[19], IMATH_INTERNAL_NAMESPACE::half h); IMATH_EXPORT void printBits (char c[35], float f); # ifndef __CUDACC__ using half = IMATH_INTERNAL_NAMESPACE::half; # else # include <cuda_fp16.h> # endif #endif // __cplusplus #endif // IMATH_HALF_H_ PyImathFixedArrayTraits.h 0000644 00000026513 15125213144 0011443 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PYIMATH_FIXEDARRAY_TRAITS_H #define _PYIMATH_FIXEDARRAY_TRAITS_H #include <Python.h> #include <ImathVec.h> #include <half.h> #include <string> namespace PyImath { // See https://docs.python.org/2/library/struct.html // // Section 7.3.2.2 // static char PyFmtStr_int[2] = {'i', '\0'}; static char PyFmtStr_float[2] = {'f', '\0'}; static char PyFmtStr_double[2] = {'d', '\0'}; static char PyFmtStr_bool[2] = {'?', '\0'}; static char PyFmtStr_char[2] = {'b', '\0'}; static char PyFmtStr_short[2] = {'h', '\0'}; static char PyFmtStr_long[2] = {'l', '\0'}; static char PyFmtStr_longlong[2] = {'q', '\0'}; static char PyFmtStr_uchar[2] = {'B', '\0'}; static char PyFmtStr_ushort[2] = {'H', '\0'}; static char PyFmtStr_uint[2] = {'I', '\0'}; static char PyFmtStr_ulong[2] = {'L', '\0'}; static char PyFmtStr_ulonglong[2] = {'Q', '\0'}; static char PyFmtStr_half[2] = {'e', '\0'}; template <typename T> constexpr char* PyFormat(); template <> constexpr char* PyFormat<int>() { return PyFmtStr_int; } template <> constexpr char* PyFormat<float>() { return PyFmtStr_float; } template <> constexpr char* PyFormat<double>() { return PyFmtStr_double; } template <> constexpr char* PyFormat<bool>() { return PyFmtStr_bool; } template <> constexpr char* PyFormat<char>() { return PyFmtStr_char; } template <> constexpr char* PyFormat<short>() { return PyFmtStr_short; } template <> constexpr char* PyFormat<long>() { return PyFmtStr_long; } template <> constexpr char* PyFormat<long long>() { return PyFmtStr_longlong; } template <> constexpr char* PyFormat<unsigned char>() { return PyFmtStr_uchar; } template <> constexpr char* PyFormat<unsigned short>() { return PyFmtStr_ushort; } template <> constexpr char* PyFormat<unsigned int>() { return PyFmtStr_uint; } template <> constexpr char* PyFormat<unsigned long>() { return PyFmtStr_ulong; } template <> constexpr char* PyFormat<unsigned long long>() { return PyFmtStr_ulonglong; } template <> constexpr char* PyFormat<half>() { return PyFmtStr_half; } template <> constexpr char* PyFormat<IMATH_NAMESPACE::Vec2<short> >() { return PyFmtStr_short; } template <> constexpr char* PyFormat<IMATH_NAMESPACE::Vec2<int> >() { return PyFmtStr_int; } template <> constexpr char* PyFormat<IMATH_NAMESPACE::Vec2<int64_t> >() { return PyFmtStr_long; } template <> constexpr char* PyFormat<IMATH_NAMESPACE::Vec2<float> >() { return PyFmtStr_float; } template <> constexpr char* PyFormat<IMATH_NAMESPACE::Vec2<double> >() { return PyFmtStr_double; } template <> constexpr char* PyFormat<IMATH_NAMESPACE::Vec3<short> >() { return PyFmtStr_short; } template <> constexpr char* PyFormat<IMATH_NAMESPACE::Vec3<int> >() { return PyFmtStr_int; } template <> constexpr char* PyFormat<IMATH_NAMESPACE::Vec3<int64_t> >() { return PyFmtStr_long; } template <> constexpr char* PyFormat<IMATH_NAMESPACE::Vec3<float> >() { return PyFmtStr_float; } template <> constexpr char* PyFormat<IMATH_NAMESPACE::Vec3<double> >() { return PyFmtStr_double; } template <> constexpr char* PyFormat<IMATH_NAMESPACE::Vec4<short> >() { return PyFmtStr_short; } template <> constexpr char* PyFormat<IMATH_NAMESPACE::Vec4<int> >() { return PyFmtStr_int; } template <> constexpr char* PyFormat<IMATH_NAMESPACE::Vec4<int64_t> >() { return PyFmtStr_long; } template <> constexpr char* PyFormat<IMATH_NAMESPACE::Vec4<float> >() { return PyFmtStr_float; } template <> constexpr char* PyFormat<IMATH_NAMESPACE::Vec4<double> >() { return PyFmtStr_double; } template <typename T> struct FixedArrayWidth { static const Py_ssize_t value; }; template <> struct FixedArrayWidth<short> { static const Py_ssize_t value = 1; }; template <> struct FixedArrayWidth<int> { static const Py_ssize_t value = 1; }; template <> struct FixedArrayWidth<int64_t> { static const Py_ssize_t value = 1; }; template <> struct FixedArrayWidth<float> { static const Py_ssize_t value = 1; }; template <> struct FixedArrayWidth<double> { static const Py_ssize_t value = 1; }; template <> struct FixedArrayWidth<unsigned char> { static const Py_ssize_t value = 1; }; template <> struct FixedArrayWidth<IMATH_NAMESPACE::Vec2<short> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayWidth<IMATH_NAMESPACE::Vec2<int> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayWidth<IMATH_NAMESPACE::Vec2<int64_t> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayWidth<IMATH_NAMESPACE::Vec2<float> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayWidth<IMATH_NAMESPACE::Vec2<double> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayWidth<IMATH_NAMESPACE::Vec3<short> > { static const Py_ssize_t value = 3; }; template <> struct FixedArrayWidth<IMATH_NAMESPACE::Vec3<int> > { static const Py_ssize_t value = 3; }; template <> struct FixedArrayWidth<IMATH_NAMESPACE::Vec3<int64_t> > { static const Py_ssize_t value = 3; }; template <> struct FixedArrayWidth<IMATH_NAMESPACE::Vec3<float> > { static const Py_ssize_t value = 3; }; template <> struct FixedArrayWidth<IMATH_NAMESPACE::Vec3<double> > { static const Py_ssize_t value = 3; }; template <> struct FixedArrayWidth<IMATH_NAMESPACE::Vec4<short> > { static const Py_ssize_t value = 4; }; template <> struct FixedArrayWidth<IMATH_NAMESPACE::Vec4<int> > { static const Py_ssize_t value = 4; }; template <> struct FixedArrayWidth<IMATH_NAMESPACE::Vec4<int64_t> > { static const Py_ssize_t value = 4; }; template <> struct FixedArrayWidth<IMATH_NAMESPACE::Vec4<float> > { static const Py_ssize_t value = 4; }; template <> struct FixedArrayWidth<IMATH_NAMESPACE::Vec4<double> > { static const Py_ssize_t value = 4; }; template <typename T> struct FixedArrayDimension { static const Py_ssize_t value; }; template <> struct FixedArrayDimension<short> { static const Py_ssize_t value = 1; }; template <> struct FixedArrayDimension<int> { static const Py_ssize_t value = 1; }; template <> struct FixedArrayDimension<int64_t> { static const Py_ssize_t value = 1; }; template <> struct FixedArrayDimension<float> { static const Py_ssize_t value = 1; }; template <> struct FixedArrayDimension<double> { static const Py_ssize_t value = 1; }; template <> struct FixedArrayDimension<unsigned char> { static const Py_ssize_t value = 1; }; template <> struct FixedArrayDimension<IMATH_NAMESPACE::Vec2<short> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayDimension<IMATH_NAMESPACE::Vec2<int> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayDimension<IMATH_NAMESPACE::Vec2<int64_t> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayDimension<IMATH_NAMESPACE::Vec2<float> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayDimension<IMATH_NAMESPACE::Vec2<double> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayDimension<IMATH_NAMESPACE::Vec3<short> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayDimension<IMATH_NAMESPACE::Vec3<int> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayDimension<IMATH_NAMESPACE::Vec3<int64_t> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayDimension<IMATH_NAMESPACE::Vec3<float> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayDimension<IMATH_NAMESPACE::Vec3<double> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayDimension<IMATH_NAMESPACE::Vec4<short> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayDimension<IMATH_NAMESPACE::Vec4<int> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayDimension<IMATH_NAMESPACE::Vec4<int64_t> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayDimension<IMATH_NAMESPACE::Vec4<float> > { static const Py_ssize_t value = 2; }; template <> struct FixedArrayDimension<IMATH_NAMESPACE::Vec4<double> > { static const Py_ssize_t value = 2; }; template <typename T> struct FixedArrayAtomicSize { static const Py_ssize_t value; }; template <> struct FixedArrayAtomicSize<short> { static const Py_ssize_t value = sizeof(short); }; template <> struct FixedArrayAtomicSize<int> { static const Py_ssize_t value = sizeof(int); }; template <> struct FixedArrayAtomicSize<int64_t> { static const Py_ssize_t value = sizeof(int); }; template <> struct FixedArrayAtomicSize<float> { static const Py_ssize_t value = sizeof(float); }; template <> struct FixedArrayAtomicSize<double> { static const Py_ssize_t value = sizeof(double); }; template <> struct FixedArrayAtomicSize<unsigned char> { static const Py_ssize_t value = sizeof(unsigned char); }; template <> struct FixedArrayAtomicSize<IMATH_NAMESPACE::Vec2<short> > { static const Py_ssize_t value = sizeof(short); }; template <> struct FixedArrayAtomicSize<IMATH_NAMESPACE::Vec2<int> > { static const Py_ssize_t value = sizeof(int); }; template <> struct FixedArrayAtomicSize<IMATH_NAMESPACE::Vec2<int64_t> > { static const Py_ssize_t value = sizeof(int64_t); }; template <> struct FixedArrayAtomicSize<IMATH_NAMESPACE::Vec2<float> > { static const Py_ssize_t value = sizeof(float); }; template <> struct FixedArrayAtomicSize<IMATH_NAMESPACE::Vec2<double> > { static const Py_ssize_t value = sizeof(double); }; template <> struct FixedArrayAtomicSize<IMATH_NAMESPACE::Vec3<short> > { static const Py_ssize_t value = sizeof(short); }; template <> struct FixedArrayAtomicSize<IMATH_NAMESPACE::Vec3<int> > { static const Py_ssize_t value = sizeof(int); }; template <> struct FixedArrayAtomicSize<IMATH_NAMESPACE::Vec3<int64_t> > { static const Py_ssize_t value = sizeof(int64_t); }; template <> struct FixedArrayAtomicSize<IMATH_NAMESPACE::Vec3<float> > { static const Py_ssize_t value = sizeof(float); }; template <> struct FixedArrayAtomicSize<IMATH_NAMESPACE::Vec3<double> > { static const Py_ssize_t value = sizeof(double); }; template <> struct FixedArrayAtomicSize<IMATH_NAMESPACE::Vec4<short> > { static const Py_ssize_t value = sizeof(short); }; template <> struct FixedArrayAtomicSize<IMATH_NAMESPACE::Vec4<int> > { static const Py_ssize_t value = sizeof(int); }; template <> struct FixedArrayAtomicSize<IMATH_NAMESPACE::Vec4<int64_t> > { static const Py_ssize_t value = sizeof(int64_t); }; template <> struct FixedArrayAtomicSize<IMATH_NAMESPACE::Vec4<float> > { static const Py_ssize_t value = sizeof(float); }; template <> struct FixedArrayAtomicSize<IMATH_NAMESPACE::Vec4<double> > { static const Py_ssize_t value = sizeof(double); }; } // namespace #endif PyImathStringTable.h 0000644 00000007246 15125213144 0010436 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathStringTable_h_ #define _PyImathStringTable_h_ #include <string> #include <stdint.h> #include <boost/multi_index_container.hpp> #include <boost/multi_index/ordered_index.hpp> #include <boost/multi_index/identity.hpp> #include <boost/multi_index/member.hpp> namespace PyImath { // define a separate index type so as not to have // any confusion between ints and indices struct StringTableIndex { public: typedef uint32_t index_type; // the default constructor was a private member before to prevent // the empty instantiation. But, it became public now to resolve // a linking error on windows platform. PyImathStringArray is // exposed with PYIMATH_EXPORT, This causes to expose all the members // of PyImathFixedArray<StringTableIndex> also. StringTableIndex() : _index(0) {} StringTableIndex (const StringTableIndex &si) : _index (si._index) {} explicit StringTableIndex (index_type i) : _index (i) {} ~StringTableIndex() = default; const StringTableIndex & operator = (const StringTableIndex &si) { if (&si != this) _index = si._index; return *this; } bool operator == (const StringTableIndex &si) const { return _index == si._index; } bool operator != (const StringTableIndex &si) const { return _index != si._index; } // operator less for sorting bool operator < (const StringTableIndex &si) const { return _index < si._index; } index_type index() const { return _index; } private: index_type _index; }; } // namespace PyImath // Add a type trait for string indices to allow use in an AlignedArray namespace boost { template <> struct is_pod< ::PyImath::StringTableIndex> { BOOST_STATIC_CONSTANT(bool,value=true); }; } // namespace boost namespace PyImath { // // A string table entry containing a unique index and string template<class T> struct StringTableEntry { StringTableEntry(StringTableIndex ii,const T &ss) : i(ii), s(ss) {} StringTableIndex i; T s; }; namespace { using boost::multi_index_container; using namespace boost::multi_index; // // A map data structure for string strings. // It exposes two index types : StringTableIndex and string // template<class T> class StringTableDetailT { public: typedef boost::multi_index_container< StringTableEntry<T>, indexed_by< ordered_unique<member<StringTableEntry<T>,StringTableIndex,&StringTableEntry<T>::i> >, ordered_unique<member<StringTableEntry<T>,T,&StringTableEntry<T>::s> > > > StringTableContainer; }; } // namespace typedef StringTableDetailT<std::string> StringTableDetail; typedef StringTableDetailT<std::wstring> WStringTableDetail; // // Storage class for storing unique string elements. // // template<class T> class StringTableT { public: // look up a string table entry either by value or index StringTableIndex lookup(const T &s) const; const T & lookup(StringTableIndex index) const; // return the index to a string table entry, adding if not found StringTableIndex intern(const T &i); size_t size() const; bool hasString(const T &s) const; bool hasStringIndex(const StringTableIndex &s) const; private: typedef typename StringTableDetailT<T>::StringTableContainer Table; Table _table; }; typedef StringTableT<std::string> StringTable; typedef StringTableT<std::wstring> WStringTable; } // namespace PyImath #endif PyImathFixedVArray.h 0000644 00000013452 15125213144 0010400 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathFixedVArray_h_ #define _PyImathFixedVArray_h_ #include <boost/python.hpp> #include <boost/any.hpp> #include <vector> #include "PyImathFixedArray.h" namespace PyImath { template <class T> class FixedVArray { // This class (at least for now) holds a std::vector of 'T' types. // This will give us the 'variable' part of the array. Generally, // we will initially support only a very small subset of accessor // methods before the semantics are fully defined. Currently, the // VArray semantics are defined in the 'varraySemantics.txt' file. std::vector<T> * _ptr; size_t _length; size_t _stride; bool _writable; // This handle optionally stores a shared_array to allocated array data // so that everything is freed properly on exit. boost::any _handle; boost::shared_array<size_t> _indices; // non-NULL if we're a masked reference size_t _unmaskedLength; public: typedef T BaseType; FixedVArray (std::vector<T>* ptr, Py_ssize_t length, Py_ssize_t stride = 1, bool writable = true); FixedVArray (std::vector<T>* ptr, Py_ssize_t length, Py_ssize_t stride, boost::any handle, bool writable = true); FixedVArray (const std::vector<T>* ptr, Py_ssize_t length, Py_ssize_t stride = 1); FixedVArray (const std::vector<T>* ptr, Py_ssize_t length, Py_ssize_t stride, boost::any handle); explicit FixedVArray (Py_ssize_t length); FixedVArray (const T& initialValue, Py_ssize_t length); FixedVArray (FixedVArray<T>& f, const FixedArray<int>& mask); FixedVArray (const FixedArray<int>& size, const T& initialValue); FixedVArray (const FixedVArray<T>& other); const FixedVArray& operator = (const FixedVArray<T>& other); ~FixedVArray(); // ---------------- const boost::any& handle() { return _handle; } Py_ssize_t len() const { return _length; } size_t stride() const { return _stride; } bool writable() const { return _writable; } // This method is mainly here for use in confidence tests, but there may // be other use-cases where a writable array needs to be made read-only. // Note that we do not provide a 'makeWritable' method here, because that // type of operation shouldn't be allowed. void makeReadOnly() { _writable = false; } bool isMaskedReference() const { return _indices.get() != 0; } size_t unmaskedLength() const { return _unmaskedLength; } std::vector<T>& operator [] (size_t i); const std::vector<T>& operator [] (size_t i) const; // ---------------- FixedArray<T> getitem (Py_ssize_t index); FixedVArray<T> getslice (PyObject* index) const; FixedVArray<T> getslice_mask (const FixedArray<int>& mask); void setitem_scalar (PyObject* index, const FixedArray<T>& data); void setitem_scalar_mask (const FixedArray<int>& mask, const FixedArray<T>& data); void setitem_vector (PyObject* index, const FixedVArray<T>& data); void setitem_vector_mask (const FixedArray<int>& mask, const FixedVArray<T>& data); struct SizeHelper { SizeHelper(FixedVArray &a) : _a(a) {} int getitem(Py_ssize_t index) const; FixedArray<int> getitem_slice(PyObject* index) const; FixedArray<int> getitem_mask(const FixedArray<int>& mask) const; void setitem_scalar (PyObject* index, size_t size); void setitem_scalar_mask (const FixedArray<int>& mask, size_t size); void setitem_vector (PyObject* index, const FixedArray<int>& size); void setitem_vector_mask (const FixedArray<int>& mask, const FixedArray<int>& size); private: FixedVArray &_a; }; boost::shared_ptr<SizeHelper> getSizeHelper(); friend struct SizeHelper; // ---------------- static boost::python::class_<FixedVArray<T> > register_(const char* doc); // Instantiations of fixed variable arrays must implement this static member. static const char* name(); template <class T2> size_t match_dimension (const FixedArray<T2>& mask, bool strictComparison = true) const { if (len() == mask.len()) { return len(); } bool throwExc = false; if (strictComparison) { throwExc = true; } else if (_indices) { if (_unmaskedLength != (size_t) mask.len()) { throwExc = true; } } else { throwExc = true; } if (throwExc) { throw std::invalid_argument("Dimensions of source do not match destination"); } return len(); } size_t match_dimension (const FixedVArray<T>& other, bool strictComparison = true) const { if (len() == other.len()) { return len(); } bool throwExc = false; if (strictComparison) { throwExc = true; } else if (_indices) { if (_unmaskedLength != (size_t) other.len()) { throwExc = true; } } else { throwExc = true; } if (throwExc) { throw std::invalid_argument("Dimensions of source do not match destination"); } return len(); } protected: size_t raw_ptr_index (size_t i) const; }; } // namespace PyImath #endif // _PyImathFixedVArray_h_ PyImathStringArray.h 0000644 00000006571 15125213144 0010465 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathStringArray_h_ #define _PyImathStringArray_h_ #include "PyImathFixedArray.h" #include "PyImathStringTable.h" // // A fixed lengy array class for string and wide string type in python. // The implementation of StringArray is does not follow other FixeArray // types. StringArray de-duplicate repeated strings using StringTable // internally for compact memory usage. // namespace PyImath { template <class T> class StringArrayT : public FixedArray<StringTableIndex> { public: typedef T BaseType; typedef FixedArray<StringTableIndex> super; static StringArrayT<T>* createDefaultArray(size_t length); static StringArrayT<T>* createUniformArray(const T& initialValue, size_t length); static StringArrayT<T>* createFromRawArray(const T* rawArray, size_t length, bool writable = true); StringArrayT(StringTableT<T> &table, StringTableIndex *ptr, size_t length, size_t stride = 1, boost::any tableHandle = boost::any(), bool writable = true); StringArrayT(StringTableT<T> &table, StringTableIndex *ptr, size_t length, size_t stride, boost::any handle, boost::any tableHandle = boost::any(), bool writable = true); StringArrayT(const StringTableT<T> &table, const StringTableIndex *ptr, size_t length, size_t stride = 1, boost::any tableHandle = boost::any()); StringArrayT(const StringTableT<T> &table, const StringTableIndex *ptr, size_t length, size_t stride, boost::any handle, boost::any tableHandle = boost::any()); StringArrayT(StringArrayT& s, const FixedArray<int>& mask); const StringTableT<T> & stringTable() const { return _table; } T getitem_string(Py_ssize_t index) const {return _table.lookup(getitem(index)); } StringArrayT* getslice_string(PyObject *index) const; StringArrayT* getslice_mask_string(const FixedArray<int>& mask); void setitem_string_scalar(PyObject *index, const T &data); void setitem_string_scalar_mask(const FixedArray<int> &mask, const T &data); void setitem_string_vector(PyObject *index, const StringArrayT<T> &data); void setitem_string_vector_mask(const FixedArray<int> &mask, const StringArrayT<T> &data); private: typedef StringArrayT<T> this_type; StringTableT<T> &_table; // StringArray can borrow a string table from somewhere else or maintain // its own string table. This handle optionally stores a shared pointer to // a allocated StringTable class instance boost::any _tableHandle; }; template<class T> FixedArray<int> operator == (const StringArrayT<T> &a0, const StringArrayT<T> &a1); template<class T> FixedArray<int> operator == (const StringArrayT<T> &a0, const T &v1); template<class T> FixedArray<int> operator == (const T &v1,const StringArrayT<T> &a0); template<class T> FixedArray<int> operator != (const StringArrayT<T> &a0, const StringArrayT<T> &a1); template<class T> FixedArray<int> operator != (const StringArrayT<T> &a0, const T &v1); template<class T> FixedArray<int> operator != (const T &v1,const StringArrayT<T> &a0); typedef StringArrayT<std::string> StringArray; typedef StringArrayT<std::wstring> WstringArray; } // namespace PyImath #endif ImathSphere.h 0000644 00000007050 15125213144 0007126 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // A 3D sphere class template // #ifndef INCLUDED_IMATHSPHERE_H #define INCLUDED_IMATHSPHERE_H #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathBox.h" #include "ImathLine.h" #include "ImathVec.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// /// A 3D sphere /// template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Sphere3 { public: /// @{ /// @name Direct access to member fields /// Center Vec3<T> center; /// Radius T radius; /// @} /// @{ /// @name Constructors /// Default is center at (0,0,0) and radius of 0. IMATH_HOSTDEVICE constexpr Sphere3() : center (0, 0, 0), radius (0) {} /// Initialize to a given center and radius IMATH_HOSTDEVICE constexpr Sphere3 (const Vec3<T>& c, T r) : center (c), radius (r) {} /// @} /// @{ /// @name Manipulation /// Set the center and radius of the sphere so that it tightly /// encloses Box b. IMATH_HOSTDEVICE void circumscribe (const Box<Vec3<T>>& box); /// @} /// @{ /// @name Utility Methods /// If the sphere and line `l` intersect, then compute the /// smallest `t` with `t>=0` so that `l(t)` is a point on the sphere. /// /// @param[in] l The line /// @param[out] intersection The point of intersection /// @return True if the sphere and line intersect, false if they /// do not. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersect (const Line3<T>& l, Vec3<T>& intersection) const; /// If the sphere and line `l` intersect, then compute the /// smallest `t` with `t>=0` so that `l(t)` is a point on the sphere. /// /// @param[in] l The line /// @param[out] t The parameter of the line at the intersection point /// @return True if the sphere and line intersect, false if they /// do not. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersectT (const Line3<T>& l, T& t) const; /// @} }; /// Sphere of type float typedef Sphere3<float> Sphere3f; /// Sphere of type double typedef Sphere3<double> Sphere3d; //--------------- // Implementation //--------------- template <class T> inline void Sphere3<T>::circumscribe (const Box<Vec3<T>>& box) { center = T (0.5) * (box.min + box.max); radius = (box.max - center).length(); } template <class T> IMATH_CONSTEXPR14 bool Sphere3<T>::intersectT (const Line3<T>& line, T& t) const { bool doesIntersect = true; Vec3<T> v = line.pos - center; T B = T (2.0) * (line.dir ^ v); T C = (v ^ v) - (radius * radius); // compute discriminant // if negative, there is no intersection T discr = B * B - T (4.0) * C; if (discr < 0.0) { // line and Sphere3 do not intersect doesIntersect = false; } else { // t0: (-B - sqrt(B^2 - 4AC)) / 2A (A = 1) T sqroot = std::sqrt (discr); t = (-B - sqroot) * T (0.5); if (t < 0.0) { // no intersection, try t1: (-B + sqrt(B^2 - 4AC)) / 2A (A = 1) t = (-B + sqroot) * T (0.5); } if (t < 0.0) doesIntersect = false; } return doesIntersect; } template <class T> IMATH_CONSTEXPR14 bool Sphere3<T>::intersect (const Line3<T>& line, Vec3<T>& intersection) const { T t (0); if (intersectT (line, t)) { intersection = line (t); return true; } else { return false; } } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHSPHERE_H PyImathBoxArrayImpl.h 0000644 00000004303 15125213144 0010560 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathBoxArrayImpl_h_ #define _PyImathBoxArrayImpl_h_ // // This .C file was turned into a header file so that instantiations // of the various Box* types can be spread across multiple files in // order to work around MSVC limitations. // #include <Python.h> #include <boost/python.hpp> #include <boost/python/make_constructor.hpp> #include <boost/format.hpp> #include <ImathVec.h> #include <ImathVecAlgo.h> #include <ImathBox.h> #include "PyImath.h" #include "PyImathBox.h" #include "PyImathDecorators.h" #include "PyImathMathExc.h" #include "PyImathOperators.h" #include "PyImathVecOperators.h" namespace PyImath { using namespace boost::python; using namespace IMATH_NAMESPACE; template <class T,int index> static FixedArray<T> BoxArray_get(FixedArray<IMATH_NAMESPACE::Box<T> > &va) { return index == 0 ? FixedArray<T>(&(va.unchecked_index(0).min), va.len(),2*va.stride(),va.handle(),va.writable()) : FixedArray<T>(&(va.unchecked_index(0).max), va.len(),2*va.stride(),va.handle(),va.writable()); } template <class T> static void setItemTuple(FixedArray<IMATH_NAMESPACE::Box<T> > &va, Py_ssize_t index, const tuple &t) { if(t.attr("__len__")() == 2) { Box<T> v; v.min = extract<T>(t[0]); v.max = extract<T>(t[1]); va[(size_t)va.canonical_index(index)] = v; } else throw std::invalid_argument ("tuple of length 2 expected"); } template <class T> class_<FixedArray<IMATH_NAMESPACE::Box<T> > > register_BoxArray() { using boost::mpl::true_; using boost::mpl::false_; class_<FixedArray<IMATH_NAMESPACE::Box<T> > > boxArray_class = FixedArray<IMATH_NAMESPACE::Box<T> >::register_("Fixed length array of IMATH_NAMESPACE::Box"); boxArray_class .add_property("min",&BoxArray_get<T,0>) .add_property("max",&BoxArray_get<T,1>) .def("__setitem__", &setItemTuple<T>) ; add_comparison_functions(boxArray_class); decoratecopy(boxArray_class); return boxArray_class; } } // namespace PyImath #endif // _PyImathBoxArrayImpl_h_ PyImathPlane.h 0000644 00000003600 15125213144 0007245 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathPlane_h_ #define _PyImathPlane_h_ #include <Python.h> #include <boost/python.hpp> #include <ImathPlane.h> #include "PyImath.h" namespace PyImath { template <class T> boost::python::class_<IMATH_NAMESPACE::Plane3<T> > register_Plane(); // // Other code in the Zeno code base assumes the existance of a class with the // same name as the Imath class, and with static functions wrap() and // convert() to produce a PyImath object from an Imath object and vice-versa, // respectively. The class Boost generates from the Imath class does not // have these properties, so we define a companion class here. // The template argument, T, is the element type (e.g.,float, double). template <class T> class P3 { public: static PyObject * wrap (const IMATH_NAMESPACE::Plane3<T> &pl); static int convert (PyObject *p, IMATH_NAMESPACE::Plane3<T> *pl); }; template <class T> PyObject * P3<T>::wrap (const IMATH_NAMESPACE::Plane3<T> &pl) { typename boost::python::return_by_value::apply < IMATH_NAMESPACE::Plane3<T> >::type converter; PyObject *p = converter (pl); return p; } template <class T> int P3<T>::convert (PyObject *p, IMATH_NAMESPACE::Plane3<T> *pl) { boost::python::extract <IMATH_NAMESPACE::Plane3f> extractorPf (p); if (extractorPf.check()) { IMATH_NAMESPACE::Plane3f e = extractorPf(); pl->normal.setValue (e.normal); pl->distance = T(e.distance); return 1; } boost::python::extract <IMATH_NAMESPACE::Plane3d> extractorPd (p); if (extractorPd.check()) { IMATH_NAMESPACE::Plane3d e = extractorPd(); pl->normal.setValue (e.normal); pl->distance = T(e.distance); return 1; } return 0; } typedef P3<float> Plane3f; typedef P3<double> Plane3d; } #endif PyImathColor4Array2DImpl.h 0000644 00000047302 15125213144 0011366 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathColor4Array2DImpl_h_ #define _PyImathColor4Array2DImpl_h_ // // This .C file was turned into a header file so that instantiations // of the various V3* types can be spread across multiple files in // order to work around MSVC limitations. // #include <Python.h> #include <boost/python.hpp> #include <boost/python/make_constructor.hpp> #include <boost/format.hpp> #include "PyImath.h" #include "PyImathMathExc.h" #include "PyImathDecorators.h" namespace PyImath { using namespace boost::python; using namespace IMATH_NAMESPACE; template <class T> struct Color4Array2DName { static const char *value(); }; // XXX fixme - template this // really this should get generated automatically... template <class T,int index> static FixedArray2D<T> Color4Array2D_get(FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va) { return FixedArray2D<T>(&va(0,0)[index], va.len().x,va.len().y, 4*va.stride().x, va.stride().y, va.handle()); } // template <class T> // static FixedArray2D<IMATH_NAMESPACE::Color4<T> > // Color4Array_cross0(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &vb) // { // PY_IMATH_LEAVE_PYTHON; // IMATH_NAMESPACE::Vec2<size_t> len = va.match_dimension(vb); // FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); // for (size_t i = 0; i < len; ++i) // f(i,j) = va(i,j).cross(vb(i,j)); // return f; // } // // template <class T> // static FixedArray2D<IMATH_NAMESPACE::Color4<T> > // Color4Array_cross1(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const IMATH_NAMESPACE::Color4<T> &vb) // { // PY_IMATH_LEAVE_PYTHON; // IMATH_NAMESPACE::Vec2<size_t> len = va.len(); // FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); // for (size_t i = 0; i < len; ++i) // f(i,j) = va(i,j).cross(vb); // return f; // } // // template <class T> // static FixedArray2D<T> // Color4Array_dot0(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &vb) // { // PY_IMATH_LEAVE_PYTHON; // IMATH_NAMESPACE::Vec2<size_t> len = va.match_dimension(vb); // FixedArray2D<T> f(len); // for (size_t i = 0; i < len; ++i) // f(i,j) = va(i,j).dot(vb(i,j)); // return f; // } // // template <class T> // static FixedArray2D<T> // Color4Array_dot1(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const IMATH_NAMESPACE::Color4<T> &vb) // { // PY_IMATH_LEAVE_PYTHON; // IMATH_NAMESPACE::Vec2<size_t> len = va.len(); // FixedArray2D<T> f(len); // for (size_t i = 0; i < len; ++i) // f(i,j) = va(i,j).dot(vb); // return f; // } // template <class T> // static FixedArray2D<T> // Color4Array_length(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va) // { // PY_IMATH_LEAVE_PYTHON; // IMATH_NAMESPACE::Vec2<size_t> len = va.len(); // FixedArray2D<T> f(len); // for (size_t i = 0; i < len; ++i) // f(i,j) = va(i,j).length(); // return f; // } // // template <class T> // static FixedArray2D<T> // Color4Array_length2(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va) // { // PY_IMATH_LEAVE_PYTHON; // IMATH_NAMESPACE::Vec2<size_t> len = va.len(); // FixedArray2D<T> f(len); // for (size_t i = 0; i < len; ++i) // f(i,j) = va(i,j).length2(); // return f; // } // // template <class T> // static FixedArray2D<IMATH_NAMESPACE::Color4<T> > & // Color4Array_normalize(FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va) // { // PY_IMATH_LEAVE_PYTHON; // IMATH_NAMESPACE::Vec2<size_t> len = va.len(); // for (size_t i = 0; i < len; ++i) // va(i,j).normalize(); // return va; // } // // template <class T> static FixedArray2D<IMATH_NAMESPACE::Color4<T> > // Color4Array_normalized(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va) // { // PY_IMATH_LEAVE_PYTHON; // IMATH_NAMESPACE::Vec2<size_t> len = va.len(); // FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); // for (size_t i = 0; i < len; ++i) // f(i,j) = va(i,j).normalized(); // return f; // } // template <class T> static FixedArray2D<IMATH_NAMESPACE::Color4<T> > Color4Array_mulT(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, T t) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.len(); FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) f(i,j) = va(i,j) * t; return f; } // // template <class T, class U> // static FixedArray2D<IMATH_NAMESPACE::Color4<T> > // Color4Array_mulM44(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const IMATH_NAMESPACE::Matrix44<U> &m) // { // PY_IMATH_LEAVE_PYTHON; // IMATH_NAMESPACE::Vec2<size_t> len = va.len(); // FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); // for (size_t i = 0; i < len; ++i) // f(i,j) = va(i,j) * m; // return f; // } // template <class T> static FixedArray2D<IMATH_NAMESPACE::Color4<T> > Color4Array_mulArrayT(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const FixedArray2D<T> &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.match_dimension(vb); FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) f(i,j) = va(i,j) * vb(i,j); return f; } template <class T> static const FixedArray2D<IMATH_NAMESPACE::Color4<T> > & Color4Array_imulT(FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, T t) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.len(); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) va(i,j) *= t; return va; } template <class T> static const FixedArray2D<IMATH_NAMESPACE::Color4<T> > & Color4Array_imulArrayT(FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const FixedArray2D<T> &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.match_dimension(vb); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) va(i,j) *= vb(i,j); return va; } template <class T> static FixedArray2D<IMATH_NAMESPACE::Color4<T> > Color4Array_divT(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, T t) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.len(); FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) f(i,j) = va(i,j) / t; return f; } template <class T> static FixedArray2D<IMATH_NAMESPACE::Color4<T> > Color4Array_divArrayT(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const FixedArray2D<T> &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.match_dimension(vb); FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) f(i,j) = va(i,j) / vb(i,j); return f; } template <class T> static const FixedArray2D<IMATH_NAMESPACE::Color4<T> > & Color4Array_idivT(FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, T t) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.len(); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) va(i,j) /= t; return va; } template <class T> static const FixedArray2D<IMATH_NAMESPACE::Color4<T> > & Color4Array_idivArrayT(FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const FixedArray2D<T> &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.match_dimension(vb); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) va(i,j) /= vb(i,j); return va; } template <class T> static FixedArray2D<IMATH_NAMESPACE::Color4<T> > Color4Array_add(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.match_dimension(vb); FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) f(i,j) = va(i,j) + vb(i,j); return f; } template <class T> static FixedArray2D<IMATH_NAMESPACE::Color4<T> > Color4Array_addColor(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const IMATH_NAMESPACE::Color4<T> &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.len(); FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) f(i,j) = va(i,j) + vb; return f; } template <class T> static FixedArray2D<IMATH_NAMESPACE::Color4<T> > Color4Array_sub(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.match_dimension(vb); FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) f(i,j) = va(i,j) - vb(i,j); return f; } template <class T> static FixedArray2D<IMATH_NAMESPACE::Color4<T> > Color4Array_subColor(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const IMATH_NAMESPACE::Color4<T> &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.len(); FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) f(i,j) = va(i,j) - vb; return f; } template <class T> static FixedArray2D<IMATH_NAMESPACE::Color4<T> > Color4Array_rsubColor(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const IMATH_NAMESPACE::Color4<T> &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.len(); FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) f(i,j) = vb - va(i,j); return f; } template <class T> static FixedArray2D<IMATH_NAMESPACE::Color4<T> > Color4Array_mul(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.match_dimension(vb); FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) f(i,j) = va(i,j) * vb(i,j); return f; } template <class T> static FixedArray2D<IMATH_NAMESPACE::Color4<T> > Color4Array_mulColor(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const IMATH_NAMESPACE::Color4<T> &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.len(); FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) f(i,j) = va(i,j) * vb; return f; } template <class T> static FixedArray2D<IMATH_NAMESPACE::Color4<T> > Color4Array_div(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.match_dimension(vb); FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) f(i,j) = va(i,j) / vb(i,j); return f; } template <class T> static FixedArray2D<IMATH_NAMESPACE::Color4<T> > Color4Array_divColor(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const IMATH_NAMESPACE::Color4<T> &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.len(); FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) f(i,j) = va(i,j) / vb; return f; } template <class T> static FixedArray2D<IMATH_NAMESPACE::Color4<T> > Color4Array_neg(const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.len(); FixedArray2D<IMATH_NAMESPACE::Color4<T> > f(len); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) f(i,j) = -va(i,j); return f; } template <class T> static const FixedArray2D<IMATH_NAMESPACE::Color4<T> > & Color4Array_iadd(FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.match_dimension(vb); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) va(i,j) += vb(i,j); return va; } template <class T> static const FixedArray2D<IMATH_NAMESPACE::Color4<T> > & Color4Array_iaddColor(FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const IMATH_NAMESPACE::Color4<T> &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.len(); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) va(i,j) += vb; return va; } template <class T> static const FixedArray2D<IMATH_NAMESPACE::Color4<T> > & Color4Array_isub(FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.match_dimension(vb); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) va(i,j) -= vb(i,j); return va; } template <class T> static const FixedArray2D<IMATH_NAMESPACE::Color4<T> > & Color4Array_isubColor(FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const IMATH_NAMESPACE::Color4<T> &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.len(); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) va(i,j) -= vb; return va; } template <class T> static const FixedArray2D<IMATH_NAMESPACE::Color4<T> > & Color4Array_imul(FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.match_dimension(vb); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) va(i,j) *= vb(i,j); return va; } template <class T> static const FixedArray2D<IMATH_NAMESPACE::Color4<T> > & Color4Array_imulColor(FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const IMATH_NAMESPACE::Color4<T> &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.len(); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) va(i,j) *= vb; return va; } template <class T> static const FixedArray2D<IMATH_NAMESPACE::Color4<T> > & Color4Array_idiv(FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const FixedArray2D<IMATH_NAMESPACE::Color4<T> > &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.match_dimension(vb); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) va(i,j) /= vb(i,j); return va; } template <class T> static const FixedArray2D<IMATH_NAMESPACE::Color4<T> > & Color4Array_idivColor(FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const IMATH_NAMESPACE::Color4<T> &vb) { PY_IMATH_LEAVE_PYTHON; IMATH_NAMESPACE::Vec2<size_t> len = va.len(); for (size_t j = 0; j < len.y; ++j) for (size_t i = 0; i < len.x; ++i) va(i,j) /= vb; return va; } template <class T> static void setItemTuple(FixedArray2D<IMATH_NAMESPACE::Color4<T> > &va, const tuple &index, const tuple &t) { if(t.attr("__len__")() == 4 && index.attr("__len__")() == 2) { Color4<T> v; v.r = extract<T>(t[0]); v.g = extract<T>(t[1]); v.b = extract<T>(t[2]); v.a = extract<T>(t[3]); va(va.canonical_index(extract<Py_ssize_t>(index[0]),va.len()[0]), va.canonical_index(extract<Py_ssize_t>(index[1]),va.len()[1])) = v; } else throw std::invalid_argument ("tuple of length 4 expected"); } template <class T> class_<FixedArray2D<IMATH_NAMESPACE::Color4<T> > > register_Color4Array2D() { class_<FixedArray2D<IMATH_NAMESPACE::Color4<T> > > color4Array2D_class = FixedArray2D<IMATH_NAMESPACE::Color4<T> >::register_(Color4Array2DName<T>::value(),"Fixed length 2d array of IMATH_NAMESPACE::Color4"); color4Array2D_class .add_property("r",&Color4Array2D_get<T,0>) .add_property("g",&Color4Array2D_get<T,1>) .add_property("b",&Color4Array2D_get<T,2>) .add_property("a",&Color4Array2D_get<T,3>) // .def("dot",&Color4Array_dot0<T>) // .def("dot",&Color4Array_dot1<T>) // .def("cross", &Color4Array_cross0<T>) // .def("cross", &Color4Array_cross1<T>) // .def("length", &Color4Array_length<T>) // .def("length2", &Color4Array_length2<T>) // .def("normalize", &Color4Array_normalize<T>,return_internal_reference<>()) // .def("normalized", &Color4Array_normalized<T>) .def("__setitem__", &setItemTuple<T>) .def("__mul__", &Color4Array_mulT<T>) // .def("__mul__", &Color4Array_mulM44<T, float>) // .def("__mul__", &Color4Array_mulM44<T, double>) .def("__rmul__", &Color4Array_mulT<T>) .def("__mul__", &Color4Array_mulArrayT<T>) .def("__rmul__", &Color4Array_mulArrayT<T>) .def("__imul__", &Color4Array_imulT<T>,return_internal_reference<>()) .def("__imul__", &Color4Array_imulArrayT<T>,return_internal_reference<>()) .def("__div__", &Color4Array_divT<T>) .def("__div__", &Color4Array_divArrayT<T>) .def("__truediv__", &Color4Array_divT<T>) .def("__truediv__", &Color4Array_divArrayT<T>) .def("__idiv__", &Color4Array_idivT<T>,return_internal_reference<>()) .def("__idiv__", &Color4Array_idivArrayT<T>,return_internal_reference<>()) .def("__itruediv__", &Color4Array_idivT<T>,return_internal_reference<>()) .def("__itruediv__", &Color4Array_idivArrayT<T>,return_internal_reference<>()) .def("__add__",&Color4Array_add<T>) .def("__add__",&Color4Array_addColor<T>) .def("__radd__",&Color4Array_addColor<T>) .def("__sub__",&Color4Array_sub<T>) .def("__sub__",&Color4Array_subColor<T>) .def("__rsub__",&Color4Array_rsubColor<T>) .def("__mul__",&Color4Array_mul<T>) .def("__mul__",&Color4Array_mulColor<T>) .def("__rmul__",&Color4Array_mulColor<T>) .def("__div__",&Color4Array_div<T>) .def("__div__",&Color4Array_divColor<T>) .def("__truediv__",&Color4Array_div<T>) .def("__truediv__",&Color4Array_divColor<T>) .def("__neg__",&Color4Array_neg<T>) .def("__iadd__",&Color4Array_iadd<T>, return_internal_reference<>()) .def("__iadd__",&Color4Array_iaddColor<T>, return_internal_reference<>()) .def("__isub__",&Color4Array_isub<T>, return_internal_reference<>()) .def("__isub__",&Color4Array_isubColor<T>, return_internal_reference<>()) .def("__imul__",&Color4Array_imul<T>, return_internal_reference<>()) .def("__imul__",&Color4Array_imulColor<T>, return_internal_reference<>()) .def("__idiv__",&Color4Array_idiv<T>, return_internal_reference<>()) .def("__idiv__",&Color4Array_idivColor<T>, return_internal_reference<>()) .def("__itruediv__",&Color4Array_idiv<T>, return_internal_reference<>()) .def("__itruediv__",&Color4Array_idivColor<T>, return_internal_reference<>()) ; add_comparison_functions(color4Array2D_class); decoratecopy(color4Array2D_class); return color4Array2D_class; } } // namespace PyImath #endif // _PyImathColor4ArrayImpl_h_ PyImathM44Array.h 0000644 00000002014 15125213144 0007547 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathM44Array_h_ #define _PyImathM44Array_h_ #include <boost/python.hpp> #include <ImathMatrix.h> #include "PyImathOperators.h" namespace PyImath { using namespace boost::python; template <class T> struct M44ArrayName { static const char *value(); }; template <class T> static void setM44ArrayItem(FixedArray<IMATH_NAMESPACE::Matrix44<T> > &ma, Py_ssize_t index, const IMATH_NAMESPACE::Matrix44<T> &m) { ma[ma.canonical_index(index)] = m; } template <class T> class_<FixedArray<IMATH_NAMESPACE::Matrix44<T> > > register_M44Array() { class_<FixedArray<IMATH_NAMESPACE::Matrix44<T> > > m44Array_class = FixedArray<IMATH_NAMESPACE::Matrix44<T> >::register_("Fixed length array of IMATH_NAMESPACE::M44"); m44Array_class .def("__setitem__", &setM44ArrayItem<T>) ; return m44Array_class; } } // namespace PyImath #endif // _PyImathM44Array_h_ ImathInt64.h 0000644 00000002123 15125213144 0006600 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // 64-bit integer types // // Deprecated, use int64_t/uint64_t instead. // #ifndef INCLUDED_IMATH_INT64_H #define INCLUDED_IMATH_INT64_H #include "ImathNamespace.h" #include <limits.h> IMATH_INTERNAL_NAMESPACE_HEADER_ENTER #if (defined _WIN32 || defined _WIN64) && _MSC_VER >= 1300 /// Int64 - unsigned 64-bit integer IMATH_DEPRECATED("use uint64_t") typedef unsigned __int64 Int64; /// SInt64 - signed 64-bit integer IMATH_DEPRECATED("use sint64_t") typedef __int64 SInt64; #elif ULONG_MAX == 18446744073709551615LU /// Int64 - unsigned 64-bit integer IMATH_DEPRECATED("use uint64_t") typedef long unsigned int Int64; /// SInt64 - signed 64-bit integer IMATH_DEPRECATED("use sint64_t") typedef long int SInt64; #else /// Int64 - unsigned 64-bit integer IMATH_DEPRECATED("use uint64_t") typedef long long unsigned int Int64; /// SInt64 - signed 64-bit integer IMATH_DEPRECATED("use sint64_t") typedef long long int SInt64; #endif IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATH_INT64_H ImathVec.h 0000644 00000167022 15125213144 0006423 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // 2D, 3D and 4D point/vector class templates // #ifndef INCLUDED_IMATHVEC_H #define INCLUDED_IMATHVEC_H #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathTypeTraits.h" #include "ImathMath.h" #include <iostream> #include <limits> #include <stdexcept> #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER // suppress exception specification warnings # pragma warning(push) # pragma warning(disable : 4290) #endif IMATH_INTERNAL_NAMESPACE_HEADER_ENTER template <class T> class Vec2; template <class T> class Vec3; template <class T> class Vec4; /// Enum for the Vec4 to Vec3 conversion constructor enum IMATH_EXPORT_ENUM InfException { INF_EXCEPTION }; /// /// 2-element vector /// template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Vec2 { public: /// @{ /// @name Direct access to elements T x, y; /// @} /// Element access by index. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT; /// Element access by index. IMATH_HOSTDEVICE constexpr const T& operator[] (int i) const IMATH_NOEXCEPT; /// @{ /// @name Constructors and Assignment /// Uninitialized by default IMATH_HOSTDEVICE Vec2() IMATH_NOEXCEPT; /// Initialize to a scalar `(a,a)` IMATH_HOSTDEVICE constexpr explicit Vec2 (T a) IMATH_NOEXCEPT; /// Initialize to given elements `(a,b)` IMATH_HOSTDEVICE constexpr Vec2 (T a, T b) IMATH_NOEXCEPT; /// Copy constructor IMATH_HOSTDEVICE constexpr Vec2 (const Vec2& v) IMATH_NOEXCEPT; /// Construct from Vec2 of another base type template <class S> IMATH_HOSTDEVICE constexpr Vec2 (const Vec2<S>& v) IMATH_NOEXCEPT; /// Assignment IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator= (const Vec2& v) IMATH_NOEXCEPT; /// Destructor ~Vec2() IMATH_NOEXCEPT = default; /// @} #if IMATH_FOREIGN_VECTOR_INTEROP /// @{ /// @name Interoperability with other vector types /// /// Construction and assignment are allowed from other classes that /// appear to be equivalent vector types, provided that they have either /// a subscripting operator, or data members .x and .y, that are of the /// same type as the elements of this vector, and their size appears to /// be the right number of elements. /// /// This functionality is disabled for gcc 4.x, which seems to have a /// compiler bug that results in spurious errors. It can also be /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to /// including any Imath header files. /// template<typename V, IMATH_ENABLE_IF(has_xy<V,T>::value)> IMATH_HOSTDEVICE explicit constexpr Vec2 (const V& v) IMATH_NOEXCEPT : Vec2(T(v.x), T(v.y)) { } template<typename V, IMATH_ENABLE_IF(has_subscript<V,T,2>::value && !has_xy<V,T>::value)> IMATH_HOSTDEVICE explicit Vec2 (const V& v) : Vec2(T(v[0]), T(v[1])) { } template<typename V, IMATH_ENABLE_IF(has_xy<V,T>::value)> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator= (const V& v) IMATH_NOEXCEPT { x = T(v.x); y = T(v.y); return *this; } template<typename V, IMATH_ENABLE_IF(has_subscript<V,T,2>::value && !has_xy<V,T>::value)> IMATH_HOSTDEVICE const Vec2& operator= (const V& v) { x = T(v[0]); y = T(v[1]); return *this; } #endif /// @{ /// @name Compatibility with Sb /// Set the value template <class S> IMATH_HOSTDEVICE void setValue (S a, S b) IMATH_NOEXCEPT; /// Set the value template <class S> IMATH_HOSTDEVICE void setValue (const Vec2<S>& v) IMATH_NOEXCEPT; /// Return the value in `a` and `b` template <class S> IMATH_HOSTDEVICE void getValue (S& a, S& b) const IMATH_NOEXCEPT; /// Return the value in `v` template <class S> IMATH_HOSTDEVICE void getValue (Vec2<S>& v) const IMATH_NOEXCEPT; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE T* getValue() IMATH_NOEXCEPT; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE const T* getValue() const IMATH_NOEXCEPT; /// @} /// @{ /// @name Arithmetic and Comparison /// Equality template <class S> IMATH_HOSTDEVICE constexpr bool operator== (const Vec2<S>& v) const IMATH_NOEXCEPT; /// Inequality template <class S> IMATH_HOSTDEVICE constexpr bool operator!= (const Vec2<S>& v) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and `m` are the same /// with an absolute error of no more than e, i.e., for all i, j: /// /// abs (this[i][j] - m[i][j]) <= e IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Vec2<T>& v, T e) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and m are the same with /// a relative error of no more than e, i.e., for all i, j: /// /// abs (this[i] - v[i][j]) <= e * abs (this[i][j]) IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithRelError (const Vec2<T>& v, T e) const IMATH_NOEXCEPT; /// Dot product IMATH_HOSTDEVICE constexpr T dot (const Vec2& v) const IMATH_NOEXCEPT; /// Dot product IMATH_HOSTDEVICE constexpr T operator^ (const Vec2& v) const IMATH_NOEXCEPT; /// Right-handed cross product, i.e. z component of /// Vec3 (this->x, this->y, 0) % Vec3 (v.x, v.y, 0) IMATH_HOSTDEVICE constexpr T cross (const Vec2& v) const IMATH_NOEXCEPT; /// Right-handed cross product, i.e. z component of /// Vec3 (this->x, this->y, 0) % Vec3 (v.x, v.y, 0) IMATH_HOSTDEVICE constexpr T operator% (const Vec2& v) const IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator+= (const Vec2& v) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE constexpr Vec2 operator+ (const Vec2& v) const IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator-= (const Vec2& v) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE constexpr Vec2 operator- (const Vec2& v) const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE constexpr Vec2 operator-() const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& negate() IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator*= (const Vec2& v) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator*= (T a) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Vec2 operator* (const Vec2& v) const IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Vec2 operator* (T a) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator/= (const Vec2& v) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec2& operator/= (T a) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Vec2 operator/ (const Vec2& v) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Vec2 operator/ (T a) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Query and Manipulation /// Return the Euclidean norm IMATH_HOSTDEVICE T length() const IMATH_NOEXCEPT; /// Return the square of the Euclidean norm, i.e. the dot product /// with itself. IMATH_HOSTDEVICE constexpr T length2() const IMATH_NOEXCEPT; /// Normalize in place. If length()==0, return a null vector. IMATH_HOSTDEVICE const Vec2& normalize() IMATH_NOEXCEPT; /// Normalize in place. If length()==0, throw an exception. const Vec2& normalizeExc(); /// Normalize without any checks for length()==0. Slightly faster /// than the other normalization routines, but if v.length() is /// 0.0, the result is undefined. IMATH_HOSTDEVICE const Vec2& normalizeNonNull() IMATH_NOEXCEPT; /// Return a normalized vector. Does not modify *this. IMATH_HOSTDEVICE Vec2<T> normalized() const IMATH_NOEXCEPT; /// Return a normalized vector. Does not modify *this. Throw an /// exception if length()==0. Vec2<T> normalizedExc() const; /// Return a normalized vector. Does not modify *this, and does /// not check for length()==0. Slightly faster than the other /// normalization routines, but if v.length() is 0.0, the result /// is undefined. IMATH_HOSTDEVICE Vec2<T> normalizedNonNull() const IMATH_NOEXCEPT; /// @} /// @{ /// @name Numeric Limits /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits<T>::lowest(); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits<T>::max(); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits<T>::min(); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits<T>::epsilon(); } /// @} /// Return the number of dimensions, i.e. 2 IMATH_HOSTDEVICE constexpr static unsigned int dimensions() IMATH_NOEXCEPT { return 2; } /// The base type: In templates that accept a parameter `V`, you /// can refer to `T` as `V::BaseType` typedef T BaseType; private: IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T lengthTiny() const IMATH_NOEXCEPT; }; /// /// 3-element vector /// template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Vec3 { public: /// @{ /// @name Direct access to elements T x, y, z; /// @} /// Element access by index. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT; /// Element access by index. IMATH_HOSTDEVICE constexpr const T& operator[] (int i) const IMATH_NOEXCEPT; /// @{ /// @name Constructors and Assignment /// Uninitialized by default IMATH_HOSTDEVICE Vec3() IMATH_NOEXCEPT; /// Initialize to a scalar `(a,a,a)` IMATH_HOSTDEVICE constexpr explicit Vec3 (T a) IMATH_NOEXCEPT; /// Initialize to given elements `(a,b,c)` IMATH_HOSTDEVICE constexpr Vec3 (T a, T b, T c) IMATH_NOEXCEPT; /// Copy constructor IMATH_HOSTDEVICE constexpr Vec3 (const Vec3& v) IMATH_NOEXCEPT; /// Construct from Vec3 of another base type template <class S> IMATH_HOSTDEVICE constexpr Vec3 (const Vec3<S>& v) IMATH_NOEXCEPT; /// Vec4 to Vec3 conversion: divide x, y and z by w, even if w is /// 0. The result depends on how the environment handles /// floating-point exceptions. template <class S> IMATH_HOSTDEVICE explicit constexpr Vec3 (const Vec4<S>& v) IMATH_NOEXCEPT; /// Vec4 to Vec3 conversion: divide x, y and z by w. Throws an /// exception if w is zero or if division by w would overflow. template <class S> explicit IMATH_CONSTEXPR14 Vec3 (const Vec4<S>& v, InfException); /// Assignment IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator= (const Vec3& v) IMATH_NOEXCEPT; /// Destructor ~Vec3() IMATH_NOEXCEPT = default; /// @} #if IMATH_FOREIGN_VECTOR_INTEROP /// @{ /// @name Interoperability with other vector types /// /// Construction and assignment are allowed from other classes that /// appear to be equivalent vector types, provided that they have either /// a subscripting operator, or data members .x, .y, .z, that are of the /// same type as the elements of this vector, and their size appears to /// be the right number of elements. /// /// This functionality is disabled for gcc 4.x, which seems to have a /// compiler bug that results in spurious errors. It can also be /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to /// including any Imath header files. /// template<typename V, IMATH_ENABLE_IF(has_xyz<V,T>::value)> IMATH_HOSTDEVICE explicit constexpr Vec3 (const V& v) IMATH_NOEXCEPT : Vec3(T(v.x), T(v.y), T(v.z)) { } template<typename V, IMATH_ENABLE_IF(has_subscript<V,T,3>::value && !has_xyz<V,T>::value)> IMATH_HOSTDEVICE explicit Vec3 (const V& v) : Vec3(T(v[0]), T(v[1]), T(v[2])) { } /// Interoperability assignment from another type that behaves as if it /// were an equivalent vector. template<typename V, IMATH_ENABLE_IF(has_xyz<V,T>::value)> IMATH_HOSTDEVICE const Vec3& operator= (const V& v) IMATH_NOEXCEPT { x = T(v.x); y = T(v.y); z = T(v.z); return *this; } template<typename V, IMATH_ENABLE_IF(has_subscript<V,T,3>::value && !has_xyz<V,T>::value)> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator= (const V& v) { x = T(v[0]); y = T(v[1]); z = T(v[2]); return *this; } /// @} #endif /// @{ /// @name Compatibility with Sb /// Set the value template <class S> IMATH_HOSTDEVICE void setValue (S a, S b, S c) IMATH_NOEXCEPT; /// Set the value template <class S> IMATH_HOSTDEVICE void setValue (const Vec3<S>& v) IMATH_NOEXCEPT; /// Return the value in `a`, `b`, and `c` template <class S> IMATH_HOSTDEVICE void getValue (S& a, S& b, S& c) const IMATH_NOEXCEPT; /// Return the value in `v` template <class S> IMATH_HOSTDEVICE void getValue (Vec3<S>& v) const IMATH_NOEXCEPT; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE T* getValue() IMATH_NOEXCEPT; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE const T* getValue() const IMATH_NOEXCEPT; /// @} /// @{ /// @name Arithmetic and Comparison /// Equality template <class S> IMATH_HOSTDEVICE constexpr bool operator== (const Vec3<S>& v) const IMATH_NOEXCEPT; /// Inequality template <class S> IMATH_HOSTDEVICE constexpr bool operator!= (const Vec3<S>& v) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and `m` are the same /// with an absolute error of no more than e, i.e., for all i, j: /// /// abs (this[i][j] - m[i][j]) <= e IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Vec3<T>& v, T e) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and m are the same with /// a relative error of no more than e, i.e., for all i, j: /// /// abs (this[i] - v[i][j]) <= e * abs (this[i][j]) IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithRelError (const Vec3<T>& v, T e) const IMATH_NOEXCEPT; /// Dot product IMATH_HOSTDEVICE constexpr T dot (const Vec3& v) const IMATH_NOEXCEPT; /// Dot product IMATH_HOSTDEVICE constexpr T operator^ (const Vec3& v) const IMATH_NOEXCEPT; /// Right-handed cross product IMATH_HOSTDEVICE constexpr Vec3 cross (const Vec3& v) const IMATH_NOEXCEPT; /// Right-handed cross product IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator%= (const Vec3& v) IMATH_NOEXCEPT; /// Right-handed cross product IMATH_HOSTDEVICE constexpr Vec3 operator% (const Vec3& v) const IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator+= (const Vec3& v) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE constexpr Vec3 operator+ (const Vec3& v) const IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator-= (const Vec3& v) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE constexpr Vec3 operator- (const Vec3& v) const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE constexpr Vec3 operator-() const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& negate() IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator*= (const Vec3& v) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator*= (T a) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Vec3 operator* (const Vec3& v) const IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Vec3 operator* (T a) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator/= (const Vec3& v) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec3& operator/= (T a) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Vec3 operator/ (const Vec3& v) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Vec3 operator/ (T a) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Query and Manipulation /// Return the Euclidean norm IMATH_HOSTDEVICE T length() const IMATH_NOEXCEPT; /// Return the square of the Euclidean norm, i.e. the dot product /// with itself. IMATH_HOSTDEVICE constexpr T length2() const IMATH_NOEXCEPT; /// Normalize in place. If length()==0, return a null vector. IMATH_HOSTDEVICE const Vec3& normalize() IMATH_NOEXCEPT; /// Normalize in place. If length()==0, throw an exception. const Vec3& normalizeExc(); /// Normalize without any checks for length()==0. Slightly faster /// than the other normalization routines, but if v.length() is /// 0.0, the result is undefined. IMATH_HOSTDEVICE const Vec3& normalizeNonNull() IMATH_NOEXCEPT; /// Return a normalized vector. Does not modify *this. IMATH_HOSTDEVICE Vec3<T> normalized() const IMATH_NOEXCEPT; // does not modify *this /// Return a normalized vector. Does not modify *this. Throw an /// exception if length()==0. Vec3<T> normalizedExc() const; /// Return a normalized vector. Does not modify *this, and does /// not check for length()==0. Slightly faster than the other /// normalization routines, but if v.length() is 0.0, the result /// is undefined. IMATH_HOSTDEVICE Vec3<T> normalizedNonNull() const IMATH_NOEXCEPT; /// @} /// @{ /// @name Numeric Limits /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits<T>::lowest(); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits<T>::max(); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits<T>::min(); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits<T>::epsilon(); } /// @} /// Return the number of dimensions, i.e. 3 IMATH_HOSTDEVICE constexpr static unsigned int dimensions() IMATH_NOEXCEPT { return 3; } /// The base type: In templates that accept a parameter `V`, you /// can refer to `T` as `V::BaseType` typedef T BaseType; private: IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T lengthTiny() const IMATH_NOEXCEPT; }; /// /// 4-element vector /// template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Vec4 { public: /// @{ /// @name Direct access to elements T x, y, z, w; /// @} /// Element access by index. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i) IMATH_NOEXCEPT; /// Element access by index. IMATH_HOSTDEVICE constexpr const T& operator[] (int i) const IMATH_NOEXCEPT; /// @{ /// @name Constructors and Assignment /// Uninitialized by default IMATH_HOSTDEVICE Vec4() IMATH_NOEXCEPT; // no initialization /// Initialize to a scalar `(a,a,a,a)` IMATH_HOSTDEVICE constexpr explicit Vec4 (T a) IMATH_NOEXCEPT; /// Initialize to given elements `(a,b,c,d)` IMATH_HOSTDEVICE constexpr Vec4 (T a, T b, T c, T d) IMATH_NOEXCEPT; /// Copy constructor IMATH_HOSTDEVICE constexpr Vec4 (const Vec4& v) IMATH_NOEXCEPT; /// Construct from Vec4 of another base type template <class S> IMATH_HOSTDEVICE constexpr Vec4 (const Vec4<S>& v) IMATH_NOEXCEPT; /// Vec3 to Vec4 conversion, sets w to 1. template <class S> IMATH_HOSTDEVICE explicit constexpr Vec4 (const Vec3<S>& v) IMATH_NOEXCEPT; /// Assignment IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator= (const Vec4& v) IMATH_NOEXCEPT; /// Destructor ~Vec4() IMATH_NOEXCEPT = default; /// @} #if IMATH_FOREIGN_VECTOR_INTEROP /// @{ /// @name Interoperability with other vector types /// /// Construction and assignment are allowed from other classes that /// appear to be equivalent vector types, provided that they have either /// a subscripting operator, or data members .x, .y, .z, .w that are of /// the same type as the elements of this vector, and their size appears /// to be the right number of elements. /// /// This functionality is disabled for gcc 4.x, which seems to have a /// compiler bug that results in spurious errors. It can also be /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to /// including any Imath header files. /// template<typename V, IMATH_ENABLE_IF(has_xyzw<V,T>::value)> IMATH_HOSTDEVICE explicit constexpr Vec4 (const V& v) IMATH_NOEXCEPT : Vec4(T(v.x), T(v.y), T(v.z), T(v.w)) { } template<typename V, IMATH_ENABLE_IF(has_subscript<V,T,4>::value && !has_xyzw<V,T>::value)> IMATH_HOSTDEVICE explicit Vec4 (const V& v) : Vec4(T(v[0]), T(v[1]), T(v[2]), T(v[3])) { } template<typename V, IMATH_ENABLE_IF(has_xyzw<V,T>::value)> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator= (const V& v) IMATH_NOEXCEPT { x = T(v.x); y = T(v.y); z = T(v.z); w = T(v.w); return *this; } template<typename V, IMATH_ENABLE_IF(has_subscript<V,T,4>::value && !has_xyzw<V,T>::value)> IMATH_HOSTDEVICE const Vec4& operator= (const V& v) { x = T(v[0]); y = T(v[1]); z = T(v[2]); w = T(v[3]); return *this; } /// @} #endif /// @{ /// @name Arithmetic and Comparison /// Equality template <class S> IMATH_HOSTDEVICE constexpr bool operator== (const Vec4<S>& v) const IMATH_NOEXCEPT; /// Inequality template <class S> IMATH_HOSTDEVICE constexpr bool operator!= (const Vec4<S>& v) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and `m` are the same /// with an absolute error of no more than e, i.e., for all i, j: /// /// abs (this[i][j] - m[i][j]) <= e IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Vec4<T>& v, T e) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and m are the same with /// a relative error of no more than e, i.e., for all i, j: /// /// abs (this[i] - v[i][j]) <= e * abs (this[i][j]) IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithRelError (const Vec4<T>& v, T e) const IMATH_NOEXCEPT; /// Dot product IMATH_HOSTDEVICE constexpr T dot (const Vec4& v) const IMATH_NOEXCEPT; /// Dot product IMATH_HOSTDEVICE constexpr T operator^ (const Vec4& v) const IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator+= (const Vec4& v) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE constexpr Vec4 operator+ (const Vec4& v) const IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator-= (const Vec4& v) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE constexpr Vec4 operator- (const Vec4& v) const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE constexpr Vec4 operator-() const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& negate() IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator*= (const Vec4& v) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator*= (T a) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Vec4 operator* (const Vec4& v) const IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Vec4 operator* (T a) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator/= (const Vec4& v) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Vec4& operator/= (T a) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Vec4 operator/ (const Vec4& v) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Vec4 operator/ (T a) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Query and Manipulation /// Return the Euclidean norm IMATH_HOSTDEVICE T length() const IMATH_NOEXCEPT; /// Return the square of the Euclidean norm, i.e. the dot product /// with itself. IMATH_HOSTDEVICE constexpr T length2() const IMATH_NOEXCEPT; /// Normalize in place. If length()==0, return a null vector. IMATH_HOSTDEVICE const Vec4& normalize() IMATH_NOEXCEPT; // modifies *this /// Normalize in place. If length()==0, throw an exception. const Vec4& normalizeExc(); /// Normalize without any checks for length()==0. Slightly faster /// than the other normalization routines, but if v.length() is /// 0.0, the result is undefined. IMATH_HOSTDEVICE const Vec4& normalizeNonNull() IMATH_NOEXCEPT; /// Return a normalized vector. Does not modify *this. IMATH_HOSTDEVICE Vec4<T> normalized() const IMATH_NOEXCEPT; // does not modify *this /// Return a normalized vector. Does not modify *this. Throw an /// exception if length()==0. Vec4<T> normalizedExc() const; /// Return a normalized vector. Does not modify *this, and does /// not check for length()==0. Slightly faster than the other /// normalization routines, but if v.length() is 0.0, the result /// is undefined. IMATH_HOSTDEVICE Vec4<T> normalizedNonNull() const IMATH_NOEXCEPT; /// @} /// @{ /// @name Numeric Limits /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits<T>::lowest(); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits<T>::max(); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits<T>::min(); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits<T>::epsilon(); } /// @} /// Return the number of dimensions, i.e. 4 IMATH_HOSTDEVICE constexpr static unsigned int dimensions() IMATH_NOEXCEPT { return 4; } /// The base type: In templates that accept a parameter `V`, you /// can refer to `T` as `V::BaseType` typedef T BaseType; private: IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T lengthTiny() const IMATH_NOEXCEPT; }; /// Stream output, as "(x y)" template <class T> std::ostream& operator<< (std::ostream& s, const Vec2<T>& v); /// Stream output, as "(x y z)" template <class T> std::ostream& operator<< (std::ostream& s, const Vec3<T>& v); /// Stream output, as "(x y z w)" template <class T> std::ostream& operator<< (std::ostream& s, const Vec4<T>& v); /// Reverse multiplication: S * Vec2<T> template <class T> IMATH_HOSTDEVICE constexpr Vec2<T> operator* (T a, const Vec2<T>& v) IMATH_NOEXCEPT; /// Reverse multiplication: S * Vec3<T> template <class T> IMATH_HOSTDEVICE constexpr Vec3<T> operator* (T a, const Vec3<T>& v) IMATH_NOEXCEPT; /// Reverse multiplication: S * Vec4<T> template <class T> IMATH_HOSTDEVICE constexpr Vec4<T> operator* (T a, const Vec4<T>& v) IMATH_NOEXCEPT; //------------------------- // Typedefs for convenience //------------------------- /// Vec2 of short typedef Vec2<short> V2s; /// Vec2 of integer typedef Vec2<int> V2i; /// Vec2 of int64_t typedef Vec2<int64_t> V2i64; /// Vec2 of float typedef Vec2<float> V2f; /// Vec2 of double typedef Vec2<double> V2d; /// Vec3 of short typedef Vec3<short> V3s; /// Vec3 of integer typedef Vec3<int> V3i; /// Vec3 of int64_t typedef Vec3<int64_t> V3i64; /// Vec3 of float typedef Vec3<float> V3f; /// Vec3 of double typedef Vec3<double> V3d; /// Vec4 of short typedef Vec4<short> V4s; /// Vec4 of integer typedef Vec4<int> V4i; /// Vec4 of int64_t typedef Vec4<int64_t> V4i64; /// Vec4 of float typedef Vec4<float> V4f; /// Vec4 of double typedef Vec4<double> V4d; //---------------------------------------------------------------------------- // Specializations for VecN<short>, VecN<int> // // Normalize and length don't make sense for integer vectors, so disable them. //---------------------------------------------------------------------------- // Vec2<short> template <> short Vec2<short>::length() const IMATH_NOEXCEPT = delete; template <> const Vec2<short>& Vec2<short>::normalize() IMATH_NOEXCEPT = delete; template <> const Vec2<short>& Vec2<short>::normalizeExc() = delete; template <> const Vec2<short>& Vec2<short>::normalizeNonNull() IMATH_NOEXCEPT = delete; template <> Vec2<short> Vec2<short>::normalized() const IMATH_NOEXCEPT = delete; template <> Vec2<short> Vec2<short>::normalizedExc() const = delete; template <> Vec2<short> Vec2<short>::normalizedNonNull() const IMATH_NOEXCEPT = delete; // Vec2<int> template <> int Vec2<int>::length() const IMATH_NOEXCEPT = delete; template <> const Vec2<int>& Vec2<int>::normalize() IMATH_NOEXCEPT = delete; template <> const Vec2<int>& Vec2<int>::normalizeExc() = delete; template <> const Vec2<int>& Vec2<int>::normalizeNonNull() IMATH_NOEXCEPT = delete; template <> Vec2<int> Vec2<int>::normalized() const IMATH_NOEXCEPT = delete; template <> Vec2<int> Vec2<int>::normalizedExc() const = delete; template <> Vec2<int> Vec2<int>::normalizedNonNull() const IMATH_NOEXCEPT = delete; // Vec2<int64_t> template <> int64_t Vec2<int64_t>::length() const IMATH_NOEXCEPT = delete; template <> const Vec2<int64_t>& Vec2<int64_t>::normalize() IMATH_NOEXCEPT = delete; template <> const Vec2<int64_t>& Vec2<int64_t>::normalizeExc() = delete; template <> const Vec2<int64_t>& Vec2<int64_t>::normalizeNonNull() IMATH_NOEXCEPT = delete; template <> Vec2<int64_t> Vec2<int64_t>::normalized() const IMATH_NOEXCEPT = delete; template <> Vec2<int64_t> Vec2<int64_t>::normalizedExc() const = delete; template <> Vec2<int64_t> Vec2<int64_t>::normalizedNonNull() const IMATH_NOEXCEPT = delete; // Vec3<short> template <> short Vec3<short>::length() const IMATH_NOEXCEPT = delete; template <> const Vec3<short>& Vec3<short>::normalize() IMATH_NOEXCEPT = delete; template <> const Vec3<short>& Vec3<short>::normalizeExc() = delete; template <> const Vec3<short>& Vec3<short>::normalizeNonNull() IMATH_NOEXCEPT = delete; template <> Vec3<short> Vec3<short>::normalized() const IMATH_NOEXCEPT = delete; template <> Vec3<short> Vec3<short>::normalizedExc() const = delete; template <> Vec3<short> Vec3<short>::normalizedNonNull() const IMATH_NOEXCEPT = delete; // Vec3<int> template <> int Vec3<int>::length() const IMATH_NOEXCEPT = delete; template <> const Vec3<int>& Vec3<int>::normalize() IMATH_NOEXCEPT = delete; template <> const Vec3<int>& Vec3<int>::normalizeExc() = delete; template <> const Vec3<int>& Vec3<int>::normalizeNonNull() IMATH_NOEXCEPT = delete; template <> Vec3<int> Vec3<int>::normalized() const IMATH_NOEXCEPT = delete; template <> Vec3<int> Vec3<int>::normalizedExc() const = delete; template <> Vec3<int> Vec3<int>::normalizedNonNull() const IMATH_NOEXCEPT = delete; // Vec3<int64_t> template <> int64_t Vec3<int64_t>::length() const IMATH_NOEXCEPT = delete; template <> const Vec3<int64_t>& Vec3<int64_t>::normalize() IMATH_NOEXCEPT = delete; template <> const Vec3<int64_t>& Vec3<int64_t>::normalizeExc() = delete; template <> const Vec3<int64_t>& Vec3<int64_t>::normalizeNonNull() IMATH_NOEXCEPT = delete; template <> Vec3<int64_t> Vec3<int64_t>::normalized() const IMATH_NOEXCEPT = delete; template <> Vec3<int64_t> Vec3<int64_t>::normalizedExc() const = delete; template <> Vec3<int64_t> Vec3<int64_t>::normalizedNonNull() const IMATH_NOEXCEPT = delete; // Vec4<short> template <> short Vec4<short>::length() const IMATH_NOEXCEPT = delete; template <> const Vec4<short>& Vec4<short>::normalize() IMATH_NOEXCEPT = delete; template <> const Vec4<short>& Vec4<short>::normalizeExc() = delete; template <> const Vec4<short>& Vec4<short>::normalizeNonNull() IMATH_NOEXCEPT = delete; template <> Vec4<short> Vec4<short>::normalized() const IMATH_NOEXCEPT = delete; template <> Vec4<short> Vec4<short>::normalizedExc() const = delete; template <> Vec4<short> Vec4<short>::normalizedNonNull() const IMATH_NOEXCEPT = delete; // Vec4<int> template <> int Vec4<int>::length() const IMATH_NOEXCEPT = delete; template <> const Vec4<int>& Vec4<int>::normalize() IMATH_NOEXCEPT = delete; template <> const Vec4<int>& Vec4<int>::normalizeExc() = delete; template <> const Vec4<int>& Vec4<int>::normalizeNonNull() IMATH_NOEXCEPT = delete; template <> Vec4<int> Vec4<int>::normalized() const IMATH_NOEXCEPT = delete; template <> Vec4<int> Vec4<int>::normalizedExc() const = delete; template <> Vec4<int> Vec4<int>::normalizedNonNull() const IMATH_NOEXCEPT = delete; // Vec4<int64_t> template <> int64_t Vec4<int64_t>::length() const IMATH_NOEXCEPT = delete; template <> const Vec4<int64_t>& Vec4<int64_t>::normalize() IMATH_NOEXCEPT = delete; template <> const Vec4<int64_t>& Vec4<int64_t>::normalizeExc() = delete; template <> const Vec4<int64_t>& Vec4<int64_t>::normalizeNonNull() IMATH_NOEXCEPT = delete; template <> Vec4<int64_t> Vec4<int64_t>::normalized() const IMATH_NOEXCEPT = delete; template <> Vec4<int64_t> Vec4<int64_t>::normalizedExc() const = delete; template <> Vec4<int64_t> Vec4<int64_t>::normalizedNonNull() const IMATH_NOEXCEPT = delete; //------------------------ // Implementation of Vec2: //------------------------ template <class T> IMATH_CONSTEXPR14 inline T& Vec2<T>::operator[] (int i) IMATH_NOEXCEPT { return (&x)[i]; // NOSONAR - suppress SonarCloud bug report. } template <class T> constexpr inline const T& Vec2<T>::operator[] (int i) const IMATH_NOEXCEPT { return (&x)[i]; // NOSONAR - suppress SonarCloud bug report. } template <class T> inline Vec2<T>::Vec2() IMATH_NOEXCEPT { // empty, and not constexpr because data is uninitialized. } template <class T> constexpr inline Vec2<T>::Vec2 (T a) IMATH_NOEXCEPT : x(a), y(a) { } template <class T> constexpr inline Vec2<T>::Vec2 (T a, T b) IMATH_NOEXCEPT : x(a), y(b) { } template <class T> constexpr inline Vec2<T>::Vec2 (const Vec2& v) IMATH_NOEXCEPT : x(v.x), y(v.y) { } template <class T> template <class S> constexpr inline Vec2<T>::Vec2 (const Vec2<S>& v) IMATH_NOEXCEPT : x(T(v.x)), y(T(v.y)) { } template <class T> IMATH_CONSTEXPR14 inline const Vec2<T>& Vec2<T>::operator= (const Vec2& v) IMATH_NOEXCEPT { x = v.x; y = v.y; return *this; } template <class T> template <class S> inline void Vec2<T>::setValue (S a, S b) IMATH_NOEXCEPT { x = T (a); y = T (b); } template <class T> template <class S> inline void Vec2<T>::setValue (const Vec2<S>& v) IMATH_NOEXCEPT { x = T (v.x); y = T (v.y); } template <class T> template <class S> inline void Vec2<T>::getValue (S& a, S& b) const IMATH_NOEXCEPT { a = S (x); b = S (y); } template <class T> template <class S> inline void Vec2<T>::getValue (Vec2<S>& v) const IMATH_NOEXCEPT { v.x = S (x); v.y = S (y); } template <class T> inline T* Vec2<T>::getValue() IMATH_NOEXCEPT { return (T*) &x; } template <class T> inline const T* Vec2<T>::getValue() const IMATH_NOEXCEPT { return (const T*) &x; } template <class T> template <class S> constexpr inline bool Vec2<T>::operator== (const Vec2<S>& v) const IMATH_NOEXCEPT { return x == v.x && y == v.y; } template <class T> template <class S> constexpr inline bool Vec2<T>::operator!= (const Vec2<S>& v) const IMATH_NOEXCEPT { return x != v.x || y != v.y; } template <class T> IMATH_CONSTEXPR14 inline bool Vec2<T>::equalWithAbsError (const Vec2<T>& v, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 2; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e)) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline bool Vec2<T>::equalWithRelError (const Vec2<T>& v, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 2; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e)) return false; return true; } template <class T> constexpr inline T Vec2<T>::dot (const Vec2& v) const IMATH_NOEXCEPT { return x * v.x + y * v.y; } template <class T> constexpr inline T Vec2<T>::operator^ (const Vec2& v) const IMATH_NOEXCEPT { return dot (v); } template <class T> constexpr inline T Vec2<T>::cross (const Vec2& v) const IMATH_NOEXCEPT { return x * v.y - y * v.x; } template <class T> constexpr inline T Vec2<T>::operator% (const Vec2& v) const IMATH_NOEXCEPT { return x * v.y - y * v.x; } template <class T> IMATH_CONSTEXPR14 inline const Vec2<T>& Vec2<T>::operator+= (const Vec2& v) IMATH_NOEXCEPT { x += v.x; y += v.y; return *this; } template <class T> constexpr inline Vec2<T> Vec2<T>::operator+ (const Vec2& v) const IMATH_NOEXCEPT { return Vec2 (x + v.x, y + v.y); } template <class T> IMATH_CONSTEXPR14 inline const Vec2<T>& Vec2<T>::operator-= (const Vec2& v) IMATH_NOEXCEPT { x -= v.x; y -= v.y; return *this; } template <class T> constexpr inline Vec2<T> Vec2<T>::operator- (const Vec2& v) const IMATH_NOEXCEPT { return Vec2 (x - v.x, y - v.y); } template <class T> constexpr inline Vec2<T> Vec2<T>::operator-() const IMATH_NOEXCEPT { return Vec2 (-x, -y); } template <class T> IMATH_CONSTEXPR14 inline const Vec2<T>& Vec2<T>::negate() IMATH_NOEXCEPT { x = -x; y = -y; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Vec2<T>& Vec2<T>::operator*= (const Vec2& v) IMATH_NOEXCEPT { x *= v.x; y *= v.y; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Vec2<T>& Vec2<T>::operator*= (T a) IMATH_NOEXCEPT { x *= a; y *= a; return *this; } template <class T> constexpr inline Vec2<T> Vec2<T>::operator* (const Vec2& v) const IMATH_NOEXCEPT { return Vec2 (x * v.x, y * v.y); } template <class T> constexpr inline Vec2<T> Vec2<T>::operator* (T a) const IMATH_NOEXCEPT { return Vec2 (x * a, y * a); } template <class T> IMATH_CONSTEXPR14 inline const Vec2<T>& Vec2<T>::operator/= (const Vec2& v) IMATH_NOEXCEPT { x /= v.x; y /= v.y; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Vec2<T>& Vec2<T>::operator/= (T a) IMATH_NOEXCEPT { x /= a; y /= a; return *this; } template <class T> constexpr inline Vec2<T> Vec2<T>::operator/ (const Vec2& v) const IMATH_NOEXCEPT { return Vec2 (x / v.x, y / v.y); } template <class T> constexpr inline Vec2<T> Vec2<T>::operator/ (T a) const IMATH_NOEXCEPT { return Vec2 (x / a, y / a); } template <class T> IMATH_CONSTEXPR14 inline T Vec2<T>::lengthTiny() const IMATH_NOEXCEPT { T absX = std::abs(x); T absY = std::abs(y); T max = absX; if (max < absY) max = absY; if (IMATH_UNLIKELY(max == T (0))) return T (0); // // Do not replace the divisions by max with multiplications by 1/max. // Computing 1/max can overflow but the divisions below will always // produce results less than or equal to 1. // absX /= max; absY /= max; return max * std::sqrt (absX * absX + absY * absY); } template <class T> inline T Vec2<T>::length() const IMATH_NOEXCEPT { T length2 = dot (*this); if (IMATH_UNLIKELY(length2 < T (2) * std::numeric_limits<T>::min())) return lengthTiny(); return std::sqrt (length2); } template <class T> constexpr inline T Vec2<T>::length2() const IMATH_NOEXCEPT { return dot (*this); } template <class T> inline const Vec2<T>& Vec2<T>::normalize() IMATH_NOEXCEPT { T l = length(); if (IMATH_LIKELY(l != T (0))) { // // Do not replace the divisions by l with multiplications by 1/l. // Computing 1/l can overflow but the divisions below will always // produce results less than or equal to 1. // x /= l; y /= l; } return *this; } template <class T> inline const Vec2<T>& Vec2<T>::normalizeExc() { T l = length(); if (IMATH_UNLIKELY(l == T (0))) throw std::domain_error ("Cannot normalize null vector."); x /= l; y /= l; return *this; } template <class T> inline const Vec2<T>& Vec2<T>::normalizeNonNull() IMATH_NOEXCEPT { T l = length(); x /= l; y /= l; return *this; } template <class T> inline Vec2<T> Vec2<T>::normalized() const IMATH_NOEXCEPT { T l = length(); if (IMATH_UNLIKELY(l == T (0))) return Vec2 (T (0)); return Vec2 (x / l, y / l); } template <class T> inline Vec2<T> Vec2<T>::normalizedExc() const { T l = length(); if (IMATH_UNLIKELY(l == T (0))) throw std::domain_error ("Cannot normalize null vector."); return Vec2 (x / l, y / l); } template <class T> inline Vec2<T> Vec2<T>::normalizedNonNull() const IMATH_NOEXCEPT { T l = length(); return Vec2 (x / l, y / l); } //----------------------- // Implementation of Vec3 //----------------------- template <class T> IMATH_CONSTEXPR14 inline T& Vec3<T>::operator[] (int i) IMATH_NOEXCEPT { return (&x)[i]; // NOSONAR - suppress SonarCloud bug report. } template <class T> constexpr inline const T& Vec3<T>::operator[] (int i) const IMATH_NOEXCEPT { return (&x)[i]; // NOSONAR - suppress SonarCloud bug report. } template <class T> inline Vec3<T>::Vec3() IMATH_NOEXCEPT { // empty, and not constexpr because data is uninitialized. } template <class T> constexpr inline Vec3<T>::Vec3 (T a) IMATH_NOEXCEPT : x(a), y(a), z(a) { } template <class T> constexpr inline Vec3<T>::Vec3 (T a, T b, T c) IMATH_NOEXCEPT : x(a), y(b), z(c) { } template <class T> constexpr inline Vec3<T>::Vec3 (const Vec3& v) IMATH_NOEXCEPT : x(v.x), y(v.y), z(v.z) { } template <class T> template <class S> constexpr inline Vec3<T>::Vec3 (const Vec3<S>& v) IMATH_NOEXCEPT : x(T(v.x)), y(T(v.y)), z(T(v.z)) { } template <class T> IMATH_CONSTEXPR14 inline const Vec3<T>& Vec3<T>::operator= (const Vec3& v) IMATH_NOEXCEPT { x = v.x; y = v.y; z = v.z; return *this; } template <class T> template <class S> constexpr inline Vec3<T>::Vec3 (const Vec4<S>& v) IMATH_NOEXCEPT : x(T(v.x/v.w)), y(T(v.y/v.w)), z(T(v.z/v.w)) { } template <class T> template <class S> IMATH_CONSTEXPR14 inline Vec3<T>::Vec3 (const Vec4<S>& v, InfException) { T vx = T (v.x); T vy = T (v.y); T vz = T (v.z); T vw = T (v.w); T absW = (vw >= T (0)) ? vw : -vw; if (absW < 1) { T m = baseTypeMax() * absW; if (vx <= -m || vx >= m || vy <= -m || vy >= m || vz <= -m || vz >= m) throw std::domain_error ("Cannot normalize point at infinity."); } x = vx / vw; y = vy / vw; z = vz / vw; } template <class T> template <class S> inline void Vec3<T>::setValue (S a, S b, S c) IMATH_NOEXCEPT { x = T (a); y = T (b); z = T (c); } template <class T> template <class S> inline void Vec3<T>::setValue (const Vec3<S>& v) IMATH_NOEXCEPT { x = T (v.x); y = T (v.y); z = T (v.z); } template <class T> template <class S> inline void Vec3<T>::getValue (S& a, S& b, S& c) const IMATH_NOEXCEPT { a = S (x); b = S (y); c = S (z); } template <class T> template <class S> inline void Vec3<T>::getValue (Vec3<S>& v) const IMATH_NOEXCEPT { v.x = S (x); v.y = S (y); v.z = S (z); } template <class T> inline T* Vec3<T>::getValue() IMATH_NOEXCEPT { return (T*) &x; } template <class T> inline const T* Vec3<T>::getValue() const IMATH_NOEXCEPT { return (const T*) &x; } template <class T> template <class S> constexpr inline bool Vec3<T>::operator== (const Vec3<S>& v) const IMATH_NOEXCEPT { return x == v.x && y == v.y && z == v.z; } template <class T> template <class S> constexpr inline bool Vec3<T>::operator!= (const Vec3<S>& v) const IMATH_NOEXCEPT { return x != v.x || y != v.y || z != v.z; } template <class T> IMATH_CONSTEXPR14 inline bool Vec3<T>::equalWithAbsError (const Vec3<T>& v, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 3; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e)) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline bool Vec3<T>::equalWithRelError (const Vec3<T>& v, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 3; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e)) return false; return true; } template <class T> constexpr inline T Vec3<T>::dot (const Vec3& v) const IMATH_NOEXCEPT { return x * v.x + y * v.y + z * v.z; } template <class T> constexpr inline T Vec3<T>::operator^ (const Vec3& v) const IMATH_NOEXCEPT { return dot (v); } template <class T> constexpr inline Vec3<T> Vec3<T>::cross (const Vec3& v) const IMATH_NOEXCEPT { return Vec3 (y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); } template <class T> IMATH_CONSTEXPR14 inline const Vec3<T>& Vec3<T>::operator%= (const Vec3& v) IMATH_NOEXCEPT { T a = y * v.z - z * v.y; T b = z * v.x - x * v.z; T c = x * v.y - y * v.x; x = a; y = b; z = c; return *this; } template <class T> constexpr inline Vec3<T> Vec3<T>::operator% (const Vec3& v) const IMATH_NOEXCEPT { return Vec3 (y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); } template <class T> IMATH_CONSTEXPR14 inline const Vec3<T>& Vec3<T>::operator+= (const Vec3& v) IMATH_NOEXCEPT { x += v.x; y += v.y; z += v.z; return *this; } template <class T> constexpr inline Vec3<T> Vec3<T>::operator+ (const Vec3& v) const IMATH_NOEXCEPT { return Vec3 (x + v.x, y + v.y, z + v.z); } template <class T> IMATH_CONSTEXPR14 inline const Vec3<T>& Vec3<T>::operator-= (const Vec3& v) IMATH_NOEXCEPT { x -= v.x; y -= v.y; z -= v.z; return *this; } template <class T> constexpr inline Vec3<T> Vec3<T>::operator- (const Vec3& v) const IMATH_NOEXCEPT { return Vec3 (x - v.x, y - v.y, z - v.z); } template <class T> constexpr inline Vec3<T> Vec3<T>::operator-() const IMATH_NOEXCEPT { return Vec3 (-x, -y, -z); } template <class T> IMATH_CONSTEXPR14 inline const Vec3<T>& Vec3<T>::negate() IMATH_NOEXCEPT { x = -x; y = -y; z = -z; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Vec3<T>& Vec3<T>::operator*= (const Vec3& v) IMATH_NOEXCEPT { x *= v.x; y *= v.y; z *= v.z; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Vec3<T>& Vec3<T>::operator*= (T a) IMATH_NOEXCEPT { x *= a; y *= a; z *= a; return *this; } template <class T> constexpr inline Vec3<T> Vec3<T>::operator* (const Vec3& v) const IMATH_NOEXCEPT { return Vec3 (x * v.x, y * v.y, z * v.z); } template <class T> constexpr inline Vec3<T> Vec3<T>::operator* (T a) const IMATH_NOEXCEPT { return Vec3 (x * a, y * a, z * a); } template <class T> IMATH_CONSTEXPR14 inline const Vec3<T>& Vec3<T>::operator/= (const Vec3& v) IMATH_NOEXCEPT { x /= v.x; y /= v.y; z /= v.z; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Vec3<T>& Vec3<T>::operator/= (T a) IMATH_NOEXCEPT { x /= a; y /= a; z /= a; return *this; } template <class T> constexpr inline Vec3<T> Vec3<T>::operator/ (const Vec3& v) const IMATH_NOEXCEPT { return Vec3 (x / v.x, y / v.y, z / v.z); } template <class T> constexpr inline Vec3<T> Vec3<T>::operator/ (T a) const IMATH_NOEXCEPT { return Vec3 (x / a, y / a, z / a); } template <class T> IMATH_CONSTEXPR14 inline T Vec3<T>::lengthTiny() const IMATH_NOEXCEPT { T absX = (x >= T (0)) ? x : -x; T absY = (y >= T (0)) ? y : -y; T absZ = (z >= T (0)) ? z : -z; T max = absX; if (max < absY) max = absY; if (max < absZ) max = absZ; if (IMATH_UNLIKELY(max == T (0))) return T (0); // // Do not replace the divisions by max with multiplications by 1/max. // Computing 1/max can overflow but the divisions below will always // produce results less than or equal to 1. // absX /= max; absY /= max; absZ /= max; return max * std::sqrt (absX * absX + absY * absY + absZ * absZ); } template <class T> inline T Vec3<T>::length() const IMATH_NOEXCEPT { T length2 = dot (*this); if (IMATH_UNLIKELY(length2 < T (2) * std::numeric_limits<T>::min())) return lengthTiny(); return std::sqrt (length2); } template <class T> constexpr inline T Vec3<T>::length2() const IMATH_NOEXCEPT { return dot (*this); } template <class T> inline const Vec3<T>& Vec3<T>::normalize() IMATH_NOEXCEPT { T l = length(); if (IMATH_LIKELY(l != T (0))) { // // Do not replace the divisions by l with multiplications by 1/l. // Computing 1/l can overflow but the divisions below will always // produce results less than or equal to 1. // x /= l; y /= l; z /= l; } return *this; } template <class T> inline const Vec3<T>& Vec3<T>::normalizeExc() { T l = length(); if (IMATH_UNLIKELY(l == T (0))) throw std::domain_error ("Cannot normalize null vector."); x /= l; y /= l; z /= l; return *this; } template <class T> inline const Vec3<T>& Vec3<T>::normalizeNonNull() IMATH_NOEXCEPT { T l = length(); x /= l; y /= l; z /= l; return *this; } template <class T> inline Vec3<T> Vec3<T>::normalized() const IMATH_NOEXCEPT { T l = length(); if (IMATH_UNLIKELY((l == T (0)))) return Vec3 (T (0)); return Vec3 (x / l, y / l, z / l); } template <class T> inline Vec3<T> Vec3<T>::normalizedExc() const { T l = length(); if (IMATH_UNLIKELY(l == T (0))) throw std::domain_error ("Cannot normalize null vector."); return Vec3 (x / l, y / l, z / l); } template <class T> inline Vec3<T> Vec3<T>::normalizedNonNull() const IMATH_NOEXCEPT { T l = length(); return Vec3 (x / l, y / l, z / l); } //----------------------- // Implementation of Vec4 //----------------------- template <class T> IMATH_CONSTEXPR14 inline T& Vec4<T>::operator[] (int i) IMATH_NOEXCEPT { return (&x)[i]; // NOSONAR - suppress SonarCloud bug report. } template <class T> constexpr inline const T& Vec4<T>::operator[] (int i) const IMATH_NOEXCEPT { return (&x)[i]; // NOSONAR - suppress SonarCloud bug report. } template <class T> inline Vec4<T>::Vec4() IMATH_NOEXCEPT { // empty, and not constexpr because data is uninitialized. } template <class T> constexpr inline Vec4<T>::Vec4 (T a) IMATH_NOEXCEPT : x(a), y(a), z(a), w(a) { } template <class T> constexpr inline Vec4<T>::Vec4 (T a, T b, T c, T d) IMATH_NOEXCEPT : x(a), y(b), z(c), w(d) { } template <class T> constexpr inline Vec4<T>::Vec4 (const Vec4& v) IMATH_NOEXCEPT : x(v.x), y(v.y), z(v.z), w(v.w) { } template <class T> template <class S> constexpr inline Vec4<T>::Vec4 (const Vec4<S>& v) IMATH_NOEXCEPT : x(T(v.x)), y(T(v.y)), z(T(v.z)), w(T(v.w)) { } template <class T> IMATH_CONSTEXPR14 inline const Vec4<T>& Vec4<T>::operator= (const Vec4& v) IMATH_NOEXCEPT { x = v.x; y = v.y; z = v.z; w = v.w; return *this; } template <class T> template <class S> constexpr inline Vec4<T>::Vec4 (const Vec3<S>& v) IMATH_NOEXCEPT : x(T(v.x)), y(T(v.y)), z(T(v.z)), w(T(1)) { } template <class T> template <class S> constexpr inline bool Vec4<T>::operator== (const Vec4<S>& v) const IMATH_NOEXCEPT { return x == v.x && y == v.y && z == v.z && w == v.w; } template <class T> template <class S> constexpr inline bool Vec4<T>::operator!= (const Vec4<S>& v) const IMATH_NOEXCEPT { return x != v.x || y != v.y || z != v.z || w != v.w; } template <class T> IMATH_CONSTEXPR14 inline bool Vec4<T>::equalWithAbsError (const Vec4<T>& v, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 4; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], v[i], e)) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline bool Vec4<T>::equalWithRelError (const Vec4<T>& v, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 4; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], v[i], e)) return false; return true; } template <class T> constexpr inline T Vec4<T>::dot (const Vec4& v) const IMATH_NOEXCEPT { return x * v.x + y * v.y + z * v.z + w * v.w; } template <class T> constexpr inline T Vec4<T>::operator^ (const Vec4& v) const IMATH_NOEXCEPT { return dot (v); } template <class T> IMATH_CONSTEXPR14 inline const Vec4<T>& Vec4<T>::operator+= (const Vec4& v) IMATH_NOEXCEPT { x += v.x; y += v.y; z += v.z; w += v.w; return *this; } template <class T> constexpr inline Vec4<T> Vec4<T>::operator+ (const Vec4& v) const IMATH_NOEXCEPT { return Vec4 (x + v.x, y + v.y, z + v.z, w + v.w); } template <class T> IMATH_CONSTEXPR14 inline const Vec4<T>& Vec4<T>::operator-= (const Vec4& v) IMATH_NOEXCEPT { x -= v.x; y -= v.y; z -= v.z; w -= v.w; return *this; } template <class T> constexpr inline Vec4<T> Vec4<T>::operator- (const Vec4& v) const IMATH_NOEXCEPT { return Vec4 (x - v.x, y - v.y, z - v.z, w - v.w); } template <class T> constexpr inline Vec4<T> Vec4<T>::operator-() const IMATH_NOEXCEPT { return Vec4 (-x, -y, -z, -w); } template <class T> IMATH_CONSTEXPR14 inline const Vec4<T>& Vec4<T>::negate() IMATH_NOEXCEPT { x = -x; y = -y; z = -z; w = -w; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Vec4<T>& Vec4<T>::operator*= (const Vec4& v) IMATH_NOEXCEPT { x *= v.x; y *= v.y; z *= v.z; w *= v.w; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Vec4<T>& Vec4<T>::operator*= (T a) IMATH_NOEXCEPT { x *= a; y *= a; z *= a; w *= a; return *this; } template <class T> constexpr inline Vec4<T> Vec4<T>::operator* (const Vec4& v) const IMATH_NOEXCEPT { return Vec4 (x * v.x, y * v.y, z * v.z, w * v.w); } template <class T> constexpr inline Vec4<T> Vec4<T>::operator* (T a) const IMATH_NOEXCEPT { return Vec4 (x * a, y * a, z * a, w * a); } template <class T> IMATH_CONSTEXPR14 inline const Vec4<T>& Vec4<T>::operator/= (const Vec4& v) IMATH_NOEXCEPT { x /= v.x; y /= v.y; z /= v.z; w /= v.w; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Vec4<T>& Vec4<T>::operator/= (T a) IMATH_NOEXCEPT { x /= a; y /= a; z /= a; w /= a; return *this; } template <class T> constexpr inline Vec4<T> Vec4<T>::operator/ (const Vec4& v) const IMATH_NOEXCEPT { return Vec4 (x / v.x, y / v.y, z / v.z, w / v.w); } template <class T> constexpr inline Vec4<T> Vec4<T>::operator/ (T a) const IMATH_NOEXCEPT { return Vec4 (x / a, y / a, z / a, w / a); } template <class T> IMATH_CONSTEXPR14 inline T Vec4<T>::lengthTiny() const IMATH_NOEXCEPT { T absX = (x >= T (0)) ? x : -x; T absY = (y >= T (0)) ? y : -y; T absZ = (z >= T (0)) ? z : -z; T absW = (w >= T (0)) ? w : -w; T max = absX; if (max < absY) max = absY; if (max < absZ) max = absZ; if (max < absW) max = absW; if (IMATH_UNLIKELY(max == T (0))) return T (0); // // Do not replace the divisions by max with multiplications by 1/max. // Computing 1/max can overflow but the divisions below will always // produce results less than or equal to 1. // absX /= max; absY /= max; absZ /= max; absW /= max; return max * std::sqrt (absX * absX + absY * absY + absZ * absZ + absW * absW); } template <class T> inline T Vec4<T>::length() const IMATH_NOEXCEPT { T length2 = dot (*this); if (IMATH_UNLIKELY(length2 < T (2) * std::numeric_limits<T>::min())) return lengthTiny(); return std::sqrt (length2); } template <class T> constexpr inline T Vec4<T>::length2() const IMATH_NOEXCEPT { return dot (*this); } template <class T> const inline Vec4<T>& Vec4<T>::normalize() IMATH_NOEXCEPT { T l = length(); if (IMATH_LIKELY(l != T (0))) { // // Do not replace the divisions by l with multiplications by 1/l. // Computing 1/l can overflow but the divisions below will always // produce results less than or equal to 1. // x /= l; y /= l; z /= l; w /= l; } return *this; } template <class T> const inline Vec4<T>& Vec4<T>::normalizeExc() { T l = length(); if (IMATH_UNLIKELY(l == T (0))) throw std::domain_error ("Cannot normalize null vector."); x /= l; y /= l; z /= l; w /= l; return *this; } template <class T> inline const Vec4<T>& Vec4<T>::normalizeNonNull() IMATH_NOEXCEPT { T l = length(); x /= l; y /= l; z /= l; w /= l; return *this; } template <class T> inline Vec4<T> Vec4<T>::normalized() const IMATH_NOEXCEPT { T l = length(); if (IMATH_UNLIKELY(l == T (0))) return Vec4 (T (0)); return Vec4 (x / l, y / l, z / l, w / l); } template <class T> inline Vec4<T> Vec4<T>::normalizedExc() const { T l = length(); if (IMATH_UNLIKELY(l == T (0))) throw std::domain_error ("Cannot normalize null vector."); return Vec4 (x / l, y / l, z / l, w / l); } template <class T> inline Vec4<T> Vec4<T>::normalizedNonNull() const IMATH_NOEXCEPT { T l = length(); return Vec4 (x / l, y / l, z / l, w / l); } //----------------------------- // Stream output implementation //----------------------------- template <class T> std::ostream& operator<< (std::ostream& s, const Vec2<T>& v) { return s << '(' << v.x << ' ' << v.y << ')'; } template <class T> std::ostream& operator<< (std::ostream& s, const Vec3<T>& v) { return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ')'; } template <class T> std::ostream& operator<< (std::ostream& s, const Vec4<T>& v) { return s << '(' << v.x << ' ' << v.y << ' ' << v.z << ' ' << v.w << ')'; } //----------------------------------------- // Implementation of reverse multiplication //----------------------------------------- template <class T> constexpr inline Vec2<T> operator* (T a, const Vec2<T>& v) IMATH_NOEXCEPT { return Vec2<T> (a * v.x, a * v.y); } template <class T> constexpr inline Vec3<T> operator* (T a, const Vec3<T>& v) IMATH_NOEXCEPT { return Vec3<T> (a * v.x, a * v.y, a * v.z); } template <class T> constexpr inline Vec4<T> operator* (T a, const Vec4<T>& v) IMATH_NOEXCEPT { return Vec4<T> (a * v.x, a * v.y, a * v.z, a * v.w); } #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER # pragma warning(pop) #endif IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHVEC_H PyImathLine.h 0000644 00000003523 15125213144 0007101 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathLine_h_ #define _PyImathLine_h_ #include <Python.h> #include <boost/python.hpp> #include <ImathLine.h> #include "PyImath.h" namespace PyImath { template <class T> boost::python::class_<IMATH_NAMESPACE::Line3<T> > register_Line(); // // Other code in the Zeno code base assumes the existance of a class with the // same name as the Imath class, and with static functions wrap() and // convert() to produce a PyImath object from an Imath object and vice-versa, // respectively. The class Boost generates from the Imath class does not // have these properties, so we define a companion class here. // The template argument, T, is the element type (e.g.,float, double). template <class T> class L3 { public: static PyObject * wrap (const IMATH_NAMESPACE::Line3<T> &l); static int convert (PyObject *p, IMATH_NAMESPACE::Line3<T> *l); }; template <class T> PyObject * L3<T>::wrap (const IMATH_NAMESPACE::Line3<T> &l) { typename boost::python::return_by_value::apply < IMATH_NAMESPACE::Line3<T> >::type converter; PyObject *p = converter (l); return p; } template <class T> int L3<T>::convert (PyObject *p, IMATH_NAMESPACE::Line3<T> *l) { boost::python::extract <IMATH_NAMESPACE::Line3f> extractorLf (p); if (extractorLf.check()) { IMATH_NAMESPACE::Line3f e = extractorLf(); l->pos.setValue (e.pos); l->dir.setValue (e.dir); return 1; } boost::python::extract <IMATH_NAMESPACE::Line3d> extractorLd (p); if (extractorLd.check()) { IMATH_NAMESPACE::Line3d e = extractorLd(); l->pos.setValue (e.pos); l->dir.setValue (e.dir); return 1; } return 0; } typedef L3<float> Line3f; typedef L3<double> Line3d; } #endif PyImathFixedArray.h 0000644 00000066412 15125213144 0010256 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathFixedArray_h_ #define _PyImathFixedArray_h_ #include <boost/python.hpp> #include <boost/operators.hpp> #include <boost/shared_array.hpp> #include <boost/any.hpp> #include <iostream> #include "PyImathUtil.h" // // Note: when PyImath from the v2 release of OpenEXR depended on Iex, // the PY_IMATH_LEAVE/RETURN_PYTHON macros bracketed calls that // enabled/disabled float-point exceptions via via the MathExcOn // class. This was a compile-time option based on the setting of // PYIMATH_ENABLE_EXCEPTIONS. This behavior is now deprecated, hence // the empty macros. // #define PY_IMATH_LEAVE_PYTHON PyImath::PyReleaseLock pyunlock; #define PY_IMATH_RETURN_PYTHON namespace PyImath { namespace { // // Utility classes used for converting array members to boost python objects. // template <class T> struct ReturnReference { static boost::python::object applyReadOnly (const T& val) { typename boost::python::copy_const_reference::apply<const T&>::type converter; return boost::python::object(boost::python::handle<>(converter(val))); } static boost::python::object applyWritable (T& val) { typename boost::python::reference_existing_object::apply<T&>::type converter; return boost::python::object(boost::python::handle<>(converter(val))); } static bool isReferenceWrap () { return true; } }; template <class T> struct ReturnByValue { static boost::python::object applyReadOnly (const T& val) { typename boost::python::return_by_value::apply<T>::type converter; return boost::python::object(boost::python::handle<>(converter(val))); } static boost::python::object applyWritable (T& val) { return applyReadOnly (val); } static bool isReferenceWrap () { return false; } }; } // namespace // // Utility class for a runtime-specified fixed length array type in python // template <class T> struct FixedArrayDefaultValue { static T value(); }; enum Uninitialized {UNINITIALIZED}; template <class T> class FixedArray { T * _ptr; size_t _length; size_t _stride; bool _writable; // this handle optionally stores a shared_array to allocated array data // so that everything is freed properly on exit. boost::any _handle; boost::shared_array<size_t> _indices; // non-NULL iff I'm a masked reference size_t _unmaskedLength; public: typedef T BaseType; FixedArray(T *ptr, Py_ssize_t length, Py_ssize_t stride = 1, bool writable = true) : _ptr(ptr), _length(length), _stride(stride), _writable(writable), _handle(), _unmaskedLength(0) { if (length < 0) { throw std::domain_error ("Fixed array length must be non-negative"); } if (stride <= 0) { throw std::domain_error ("Fixed array stride must be positive"); } // nothing } FixedArray(T *ptr, Py_ssize_t length, Py_ssize_t stride, boost::any handle, bool writable = true) : _ptr(ptr), _length(length), _stride(stride), _writable(writable), _handle(handle), _unmaskedLength(0) { if (_length < 0) { throw std::domain_error("Fixed array length must be non-negative"); } if (stride <= 0) { throw std::domain_error("Fixed array stride must be positive"); } // nothing } FixedArray(const T *ptr, Py_ssize_t length, Py_ssize_t stride = 1) : _ptr(const_cast<T *>(ptr)), _length(length), _stride(stride), _writable(false), _handle(), _unmaskedLength(0) { if (length < 0) { throw std::logic_error("Fixed array length must be non-negative"); } if (stride <= 0) { throw std::logic_error("Fixed array stride must be positive"); } // nothing } FixedArray(const T *ptr, Py_ssize_t length, Py_ssize_t stride, boost::any handle) : _ptr(const_cast<T *>(ptr)), _length(length), _stride(stride), _writable(false), _handle(handle), _unmaskedLength(0) { if (_length < 0) { throw std::logic_error("Fixed array length must be non-negative"); } if (stride <= 0) { throw std::logic_error("Fixed array stride must be positive"); } // nothing } explicit FixedArray(Py_ssize_t length) : _ptr(0), _length(length), _stride(1), _writable(true), _handle(), _unmaskedLength(0) { if (_length < 0) { throw std::domain_error("Fixed array length must be non-negative"); } boost::shared_array<T> a(new T[length]); T tmp = FixedArrayDefaultValue<T>::value(); for (Py_ssize_t i=0; i<length; ++i) a[i] = tmp; _handle = a; _ptr = a.get(); } FixedArray(Py_ssize_t length,Uninitialized) : _ptr(0), _length(length), _stride(1), _writable(true), _handle(), _unmaskedLength(0) { if (_length < 0) { throw std::domain_error("Fixed array length must be non-negative"); } boost::shared_array<T> a(new T[length]); _handle = a; _ptr = a.get(); } FixedArray(const T &initialValue, Py_ssize_t length) : _ptr(0), _length(length), _stride(1), _writable(true), _handle(), _unmaskedLength(0) { if (_length < 0) { throw std::domain_error("Fixed array length must be non-negative"); } boost::shared_array<T> a(new T[length]); for (Py_ssize_t i=0; i<length; ++i) a[i] = initialValue; _handle = a; _ptr = a.get(); } template <typename MaskArrayType> FixedArray(FixedArray& f, const MaskArrayType& mask) : _ptr(f._ptr), _stride(f._stride), _writable(f._writable), _handle(f._handle), _unmaskedLength(0) { if (f.isMaskedReference()) { throw std::invalid_argument("Masking an already-masked FixedArray not supported yet (SQ27000)"); } size_t len = f.match_dimension(mask); _unmaskedLength = len; size_t reduced_len = 0; for (size_t i = 0; i < len; ++i) if (mask[i]) reduced_len++; _indices.reset(new size_t[reduced_len]); for (size_t i = 0, j = 0; i < len; ++i) { if (mask[i]) { _indices[j] = i; j++; } } _length = reduced_len; } template <typename MaskArrayType> FixedArray(const FixedArray& f, const MaskArrayType& mask) : _ptr(f._ptr), _stride(f._stride), _writable(false), _handle(f._handle), _unmaskedLength(0) { if (f.isMaskedReference()) { throw std::invalid_argument("Masking an already-masked FixedArray not supported yet (SQ27000)"); } size_t len = f.match_dimension(mask); _unmaskedLength = len; size_t reduced_len = 0; for (size_t i = 0; i < len; ++i) if (mask[i]) reduced_len++; _indices.reset(new size_t[reduced_len]); for (size_t i = 0, j = 0; i < len; ++i) { if (mask[i]) { _indices[j] = i; j++; } } _length = reduced_len; } template <class S> explicit FixedArray(const FixedArray<S> &other) : _ptr(0), _length(other.len()), _stride(1), _writable(true), _handle(), _unmaskedLength(other.unmaskedLength()) { boost::shared_array<T> a(new T[_length]); for (size_t i=0; i<_length; ++i) a[i] = T(other[i]); _handle = a; _ptr = a.get(); if (_unmaskedLength) { _indices.reset(new size_t[_length]); for (size_t i = 0; i < _length; ++i) _indices[i] = other.raw_ptr_index(i); } } FixedArray(const FixedArray &other) : _ptr(other._ptr), _length(other._length), _stride(other._stride), _writable(other._writable), _handle(other._handle), _indices(other._indices), _unmaskedLength(other._unmaskedLength) { } const FixedArray & operator = (const FixedArray &other) { if (&other == this) return *this; _ptr = other._ptr; _length = other._length; _stride = other._stride; _writable = other._writable; _handle = other._handle; _unmaskedLength = other._unmaskedLength; _indices = other._indices; return *this; } ~FixedArray() { // nothing } explicit operator bool() const {return _ptr != nullptr;} const boost::any & handle() { return _handle; } // // Make an index suitable for indexing into an array in c++ from // a python index, which can be negative for indexing relative to // the end of an array // size_t canonical_index(Py_ssize_t index) const { if (index < 0) index += len(); if (index >= len() || index < 0) { PyErr_SetString(PyExc_IndexError, "Index out of range"); boost::python::throw_error_already_set(); } return index; // still a virtual index if this is a masked reference array } void extract_slice_indices(PyObject *index, size_t &start, size_t &end, Py_ssize_t &step, size_t &slicelength) const { if (PySlice_Check(index)) { #if PY_MAJOR_VERSION > 2 PyObject *slice = index; #else PySliceObject *slice = reinterpret_cast<PySliceObject *>(index); #endif Py_ssize_t s,e,sl; if (PySlice_GetIndicesEx(slice,_length,&s,&e,&step,&sl) == -1) { boost::python::throw_error_already_set(); } // e can be -1 if the iteration is backwards with a negative slice operator [::-n] (n > 0). if (s < 0 || e < -1 || sl < 0) { throw std::domain_error("Slice extraction produced invalid start, end, or length indices"); } start = s; end = e; slicelength = sl; } else if (PyInt_Check(index)) { size_t i = canonical_index(PyInt_AsSsize_t(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(); } } // Although this method isn't used directly by this class, // there are some sub-classes that are using it. typedef typename boost::mpl::if_<boost::is_class<T>, T&,T>::type get_type; get_type getitem(Py_ssize_t index) { return (*this)[canonical_index(index)]; } typedef typename boost::mpl::if_<boost::is_class<T>,const T&,T>::type get_type_const; get_type_const getitem(Py_ssize_t index) const { return (*this)[canonical_index(index)]; } // We return an internal reference for class-types and a copy of the data // for non-class types. Returning an internal refeference doesn't seem // to work with non-class types. boost::python::object getobjectTuple (Py_ssize_t index) { typedef typename boost::mpl::if_<boost::is_class<T>, ReturnReference<T>, ReturnByValue<T> >::type convertType; boost::python::object retval; int referenceMode = 0; const size_t i = canonical_index(index); T& val = _ptr[(isMaskedReference() ? raw_ptr_index(i) : i) * _stride]; if (_writable) { retval = convertType::applyWritable (val); if (convertType::isReferenceWrap()) referenceMode = 0; // Managed reference. else referenceMode = 2; // Default policy (return-by-value) } else { retval = convertType::applyReadOnly (val); if (convertType::isReferenceWrap()) referenceMode = 1; // Copy const reference else referenceMode = 2; // Default policy (return-by-value) } return boost::python::make_tuple (referenceMode, retval); } boost::python::object getobjectTuple (Py_ssize_t index) const { typedef typename boost::mpl::if_<boost::is_class<T>, ReturnReference<T>, ReturnByValue<T> >::type convertType; boost::python::object retval; int referenceMode = 1; const size_t i = canonical_index(index); const T& val = _ptr[(isMaskedReference() ? raw_ptr_index(i) : i) * _stride]; retval = convertType::applyReadOnly (val); if (convertType::isReferenceWrap()) referenceMode = 1; // Copy const reference else referenceMode = 2; // Default policy (return-by-value) return boost::python::make_tuple (referenceMode, retval); } FixedArray getslice(::PyObject *index) const { size_t start=0, end=0, slicelength=0; Py_ssize_t step; extract_slice_indices(index,start,end,step,slicelength); FixedArray f(slicelength); if (isMaskedReference()) { for (size_t i=0; i<slicelength; ++i) f._ptr[i] = _ptr[raw_ptr_index(start+i*step)*_stride]; } else { for (size_t i=0; i<slicelength; ++i) f._ptr[i] = _ptr[(start+i*step)*_stride]; } return f; } template <typename MaskArrayType> FixedArray getslice_mask(const MaskArrayType& mask) { // 'writable' state is preserved in the returned fixed-array. FixedArray f(*this, mask); return f; } void setitem_scalar(PyObject *index, const T &data) { if (!_writable) throw std::invalid_argument("Fixed array is read-only."); size_t start=0, end=0, slicelength=0; Py_ssize_t step; extract_slice_indices(index,start,end,step,slicelength); if (isMaskedReference()) { for (size_t i=0; i<slicelength; ++i) _ptr[raw_ptr_index(start+i*step)*_stride] = data; } else { for (size_t i=0; i<slicelength; ++i) _ptr[(start+i*step)*_stride] = data; } } template <typename MaskArrayType> void setitem_scalar_mask(const MaskArrayType &mask, const T &data) { if (!_writable) throw std::invalid_argument("Fixed array is read-only."); size_t len = match_dimension(mask, false); if (isMaskedReference()) { for (size_t i = 0; i < len; ++i) _ptr[raw_ptr_index(i)*_stride] = data; } else { for (size_t i=0; i<len; ++i) if (mask[i]) _ptr[i*_stride] = data; } } template <typename ArrayType> void setitem_vector(::PyObject *index, const ArrayType &data) { if (!_writable) throw std::invalid_argument("Fixed array is read-only."); size_t start=0, end=0, slicelength=0; Py_ssize_t step; extract_slice_indices(index,start,end,step,slicelength); // we have a valid range of indices if ((size_t)data.len() != slicelength) { PyErr_SetString(PyExc_IndexError, "Dimensions of source do not match destination"); boost::python::throw_error_already_set(); } if (isMaskedReference()) { for (size_t i=0; i<slicelength; ++i) _ptr[raw_ptr_index(start+i*step)*_stride] = data[i]; } else { for (size_t i=0; i<slicelength; ++i) _ptr[(start+i*step)*_stride] = data[i]; } } template <typename MaskArrayType, typename ArrayType> void setitem_vector_mask(const MaskArrayType &mask, const ArrayType &data) { if (!_writable) throw std::invalid_argument("Fixed array is read-only."); // We could relax this but this restriction if there's a good // enough reason too. if (isMaskedReference()) { throw std::invalid_argument("We don't support setting item masks for masked reference arrays."); } size_t len = match_dimension(mask); if ((size_t)data.len() == len) { for (size_t i = 0; i < len; ++i) if (mask[i]) _ptr[i*_stride] = data[i]; } else { size_t count = 0; for (size_t i = 0; i < len; ++i) if (mask[i]) count++; if (data.len() != count) { throw std::invalid_argument("Dimensions of source data do not match destination either masked or unmasked"); } Py_ssize_t dataIndex = 0; for (size_t i = 0; i < len; ++i) { if (mask[i]) { _ptr[i*_stride] = data[dataIndex]; dataIndex++; } } } } // exposed as Py_ssize_t for compatilbity with standard python sequences Py_ssize_t len() const { return _length; } size_t stride() const { return _stride; } bool writable() const { return _writable; } // This method is mainly here for use in confidence tests, but there may // be other use-cases where a writable array needs to be made read-only. // Note that we do not provide a 'makeWritable' method here, because that // type of operation shouldn't be allowed. void makeReadOnly() { _writable = false; } // no bounds checking on i! T& operator [] (size_t i) { if (!_writable) throw std::invalid_argument("Fixed array is read-only."); return _ptr[(isMaskedReference() ? raw_ptr_index(i) : i) * _stride]; } // no bounds checking on i! const T& operator [] (size_t i) const { return _ptr[(isMaskedReference() ? raw_ptr_index(i) : i) * _stride]; } // no mask conversion or bounds checking on i! T& direct_index(size_t i) { if (!_writable) throw std::invalid_argument("Fixed array is read-only."); return _ptr[i*_stride]; } // no mask conversion or bounds checking on i! const T& direct_index (size_t i) const { return _ptr[i*_stride]; } // In some cases, an access to the raw data without the 'writable' check // is needed. Generally in specialized python-wrapping helpers. T& unchecked_index (size_t i) { return _ptr[(isMaskedReference() ? raw_ptr_index(i) : i) * _stride]; } T& unchecked_direct_index (size_t i) { return _ptr[i*_stride]; } bool isMaskedReference() const {return _indices.get() != 0;} size_t unmaskedLength() const {return _unmaskedLength;} // Conversion of indices to raw pointer indices. // This should only be called when this is a masked reference. // No safety checks done for performance. size_t raw_ptr_index(size_t i) const { assert(isMaskedReference()); assert(i < _length); assert(_indices[i] >= 0 && _indices[i] < _unmaskedLength); return _indices[i]; } static boost::python::class_<FixedArray<T> > register_(const char *doc) { // Depending on the data-type (class or fundamental) and the writable // state of the array, different forms are returned by the '__getitem__' // method. If writable and a class, an internal reference to the data // is returned so that its value can be changed. If not-writable or a // fundemental data type (float, int, etc.), then a 'copy' of the data // is returned. typename boost::python::object (FixedArray<T>::*nonconst_getobject)(Py_ssize_t) = &FixedArray<T>::getobjectTuple; typename boost::python::object (FixedArray<T>:: *const_getobject)(Py_ssize_t) const = &FixedArray<T>::getobjectTuple; boost::python::class_<FixedArray<T> > c(name(),doc, boost::python::init<size_t>("construct an array of the specified length initialized to the default value for the type")); c .def(boost::python::init<const FixedArray<T> &>("construct an array with the same values as the given array")) .def(boost::python::init<const T &,size_t>("construct an array of the specified length initialized to the specified default value")) .def("__getitem__", &FixedArray<T>::getslice) .def("__getitem__", &FixedArray<T>::getslice_mask<FixedArray<int> > ) .def("__getitem__", const_getobject, selectable_postcall_policy_from_tuple< boost::python::with_custodian_and_ward_postcall<0,1>, boost::python::return_value_policy<boost::python::copy_const_reference>, boost::python::default_call_policies>()) .def("__getitem__", nonconst_getobject, selectable_postcall_policy_from_tuple< boost::python::with_custodian_and_ward_postcall<0,1>, boost::python::return_value_policy<boost::python::copy_const_reference>, boost::python::default_call_policies>()) .def("__setitem__", &FixedArray<T>::setitem_scalar) .def("__setitem__", &FixedArray<T>::setitem_scalar_mask<FixedArray<int> >) .def("__setitem__", &FixedArray<T>::setitem_vector<FixedArray<T> >) .def("__setitem__", &FixedArray<T>::setitem_vector_mask<FixedArray<int>, FixedArray<T> >) .def("__len__",&FixedArray<T>::len) .def("writable",&FixedArray<T>::writable) .def("makeReadOnly", &FixedArray<T>::makeReadOnly) .def("ifelse",&FixedArray<T>::ifelse_scalar) .def("ifelse",&FixedArray<T>::ifelse_vector) ; return c; } template <typename ArrayType> size_t match_dimension(const ArrayType &a1, bool strictComparison = true) const { if (len() == a1.len()) return len(); bool throwExc = false; if (strictComparison) throwExc = true; else if (isMaskedReference()) { if (_unmaskedLength != a1.len()) throwExc = true; } else throwExc = true; if (throwExc) { throw std::invalid_argument("Dimensions of source do not match destination"); } return len(); } FixedArray<T> ifelse_vector(const FixedArray<int> &choice, const FixedArray<T> &other) { size_t len = match_dimension(choice); match_dimension(other); FixedArray<T> tmp(len); // should use default construction but V3f doens't initialize for (size_t i=0; i < len; ++i) tmp[i] = choice[i] ? (*this)[i] : other[i]; return tmp; } FixedArray<T> ifelse_scalar(const FixedArray<int> &choice, const T &other) { size_t len = match_dimension(choice); FixedArray<T> tmp(len); // should use default construction but V3f doens't initialize for (size_t i=0; i < len; ++i) tmp[i] = choice[i] ? (*this)[i] : other; return tmp; } // Instantiations of fixed ararys must implement this static member static const char *name(); // Various 'Accessor' classes used in performance-critical areas while also // managing the writable/read-only state efficiently. class ReadOnlyDirectAccess { public: ReadOnlyDirectAccess (const FixedArray<T>& array) : _ptr (array._ptr), _stride (array._stride) { if (array.isMaskedReference()) throw std::invalid_argument ("Fixed array is masked. ReadOnlyDirectAccess not granted."); } ReadOnlyDirectAccess (const ReadOnlyDirectAccess& other) : _ptr (other._ptr), _stride (other._stride) {} const T& operator[] (size_t i) const { return _ptr[i*_stride]; } private: const T* _ptr; protected: const size_t _stride; }; class WritableDirectAccess : public ReadOnlyDirectAccess { public: WritableDirectAccess (FixedArray<T>& array) : ReadOnlyDirectAccess (array), _ptr (array._ptr) { if (!array.writable()) throw std::invalid_argument ("Fixed array is read-only. WritableDirectAccess not granted."); } WritableDirectAccess (const WritableDirectAccess& other) : ReadOnlyDirectAccess (other), _ptr (other._ptr) {} T& operator[] (size_t i) { return _ptr[i*_stride]; } private: T* _ptr; using ReadOnlyDirectAccess::_stride; }; // class ReadOnlyMaskedAccess { public: ReadOnlyMaskedAccess (const FixedArray<T>& array) : _ptr (array._ptr), _stride (array._stride), _indices (array._indices) { if (!array.isMaskedReference()) throw std::invalid_argument ("Fixed array is not masked. ReadOnlyMaskedAccess not granted."); } ReadOnlyMaskedAccess (const ReadOnlyMaskedAccess& other) : _ptr (other._ptr), _stride (other._stride), _indices (other._indices) {} // No index-range check here. const T& operator[] (size_t i) const { return _ptr[_indices[i]*_stride]; } private: const T* _ptr; protected: const size_t _stride; boost::shared_array<size_t> _indices; }; class WritableMaskedAccess : public ReadOnlyMaskedAccess { public: WritableMaskedAccess (FixedArray<T>& array) : ReadOnlyMaskedAccess (array), _ptr (array._ptr) { if (!array.writable()) std::invalid_argument ("Fixed array is read-only. WritableMaskedAccess not granted."); } WritableMaskedAccess (const WritableMaskedAccess& other) : ReadOnlyMaskedAccess (other), _ptr (other._ptr) {} // No index-range check here. T& operator[] (size_t i) { return _ptr[_indices[i]*_stride]; } private: T* _ptr; using ReadOnlyMaskedAccess::_stride; using ReadOnlyMaskedAccess::_indices; }; }; // // Helper struct for arary indexing with a known compile time length // template <class Container, class Data> struct IndexAccessDefault { typedef Data & result_type; static Data & apply(Container &c, size_t i) { return c[i]; } }; template <class Container, class Data, int Length, class IndexAccess = IndexAccessDefault<Container,Data> > struct StaticFixedArray { static Py_ssize_t len(const Container &) { return Length; } static typename IndexAccess::result_type getitem(Container &c, Py_ssize_t index) { return IndexAccess::apply(c,canonical_index(index)); } static void setitem(Container &c, Py_ssize_t index, const Data &data) { IndexAccess::apply(c,canonical_index(index)) = data; } static size_t canonical_index(Py_ssize_t index) { if (index < 0) index += Length; if (index < 0 || index >= Length) { PyErr_SetString(PyExc_IndexError, "Index out of range"); boost::python::throw_error_already_set(); } return index; } }; } #endif // _PyImathFixedArray_h_ PyImathQuatOperators.h 0000644 00000001565 15125213144 0011027 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathQuatOperators_h_ #define _PyImathQuatOperators_h_ #include <ImathQuat.h> namespace PyImath { template <class T> struct op_quatDot { static inline typename T::BaseType apply (const T &self, const T &qB) { return self.euclideanInnerProduct (qB); } }; template <class T> struct op_quatNormalize { static inline void apply (T &self) { self.normalize(); } }; template <class T> struct op_quatNormalized { static inline T apply (const T &self) { return self.normalized(); } }; template <class T> struct op_quatSlerp { static inline T apply (const T &self, const T &qB, const typename T::BaseType t) { return Imath::slerpShortestArc (self, qB, t); } }; } // namespace PyImath #endif // _PyImathQuatOperators_h_ PyImathMathExc.h 0000644 00000000773 15125213144 0007547 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathMathExc_h_ #define _PyImathMathExc_h_ // // Note: when PyImath from the v2 release of OpenEXR depended on Iex, // the MATH_EXC_ON macro enabled float-point exceptions via the // MathExcOn class. This was a compile-time option based on the // setting of PYIMATH_ENABLE_EXCEPTIONS. This behavior is now // deprecated, hence the empty macro. // #define MATH_EXC_ON #endif PyImath.h 0000644 00000002446 15125213144 0006274 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImath_h_ #define _PyImath_h_ #include <ImathVec.h> #include <ImathQuat.h> #include <PyImathAPI.h> #include "PyImathFixedArray.h" #include "PyImathFixedMatrix.h" #include "PyImathFixedArray2D.h" #include "PyImathFixedVArray.h" namespace PyImath { typedef FixedArray<bool> BoolArray; typedef FixedArray<signed char> SignedCharArray; typedef FixedArray<unsigned char> UnsignedCharArray; typedef FixedArray<short> ShortArray; typedef FixedArray<unsigned short> UnsignedShortArray; typedef FixedArray<int> IntArray; typedef FixedArray<unsigned int> UnsignedIntArray; typedef FixedArray<float> FloatArray; typedef FixedArray<double> DoubleArray; typedef FixedArray<IMATH_NAMESPACE::Quatf> QuatfArray; typedef FixedArray<IMATH_NAMESPACE::Quatd> QuatdArray; typedef FixedMatrix<int> IntMatrix; typedef FixedMatrix<float> FloatMatrix; typedef FixedMatrix<double> DoubleMatrix; typedef FixedArray2D<float> FloatArray2D; typedef FixedArray2D<int> IntArray2D; typedef FixedArray2D<double> DoubleArray2D; typedef FixedVArray<int> VIntArray; typedef FixedVArray<float> VFloatArray; typedef FixedVArray<Imath::Vec2<int> > VV2iArray; typedef FixedVArray<Imath::Vec2<float> > VV2fArray; } #endif PyImathColor.h 0000644 00000016444 15125213144 0007276 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathColor3_h_ #define _PyImathColor3_h_ #include <Python.h> #include <boost/python.hpp> #include <ImathColor.h> #include "PyImath.h" namespace PyImath { template <class T> boost::python::class_<IMATH_NAMESPACE::Color4<T> > register_Color4(); template <class T> boost::python::class_<PyImath::FixedArray2D<IMATH_NAMESPACE::Color4<T> > > register_Color4Array2D(); template <class T> boost::python::class_<PyImath::FixedArray<IMATH_NAMESPACE::Color4<T> > > register_Color4Array(); template <class T> boost::python::class_<IMATH_NAMESPACE::Color3<T>, boost::python::bases<IMATH_NAMESPACE::Vec3<T> > > register_Color3(); template <class T> boost::python::class_<PyImath::FixedArray<IMATH_NAMESPACE::Color3<T> > > register_Color3Array(); typedef FixedArray2D<IMATH_NAMESPACE::Color4f> Color4fArray; typedef FixedArray2D<IMATH_NAMESPACE::Color4c> Color4cArray; typedef FixedArray<IMATH_NAMESPACE::Color4f> C4fArray; typedef FixedArray<IMATH_NAMESPACE::Color4c> C4cArray; typedef FixedArray<IMATH_NAMESPACE::Color3f> C3fArray; typedef FixedArray<IMATH_NAMESPACE::Color3c> C3cArray; // // Other code in the Zeno code base assumes the existance of a class with the // same name as the Imath class, and with static functions wrap() and // convert() to produce a PyImath object from an Imath object and vice-versa, // respectively. The class Boost generates from the Imath class does not // have these properties, so we define a companion class here. // The template argument, T, is the element type for the color in C++ (e.g., char, // float). The other argument, U, is how this type is represented in Python // (e.g., int, float). template <class T, class U> class C3 { public: static PyObject * wrap (const IMATH_NAMESPACE::Color3<T> &c); static int convert (PyObject *p, IMATH_NAMESPACE::Color3<T> *v); }; template <class T, class U> class C4 { public: static PyObject * wrap (const IMATH_NAMESPACE::Color4<T> &c); static int convert (PyObject *p, IMATH_NAMESPACE::Color4<T> *v); }; template <class T, class U> PyObject * C3<T, U>::wrap (const IMATH_NAMESPACE::Color3<T> &c) { typename boost::python::return_by_value::apply < IMATH_NAMESPACE::Color3<T> >::type converter; PyObject *p = converter (c); return p; } template <class T, class U> PyObject * C4<T, U>::wrap (const IMATH_NAMESPACE::Color4<T> &c) { typename boost::python::return_by_value::apply < IMATH_NAMESPACE::Color4<T> >::type converter; PyObject *p = converter (c); return p; } template <class T, class U> int C3<T, U>::convert (PyObject *p, IMATH_NAMESPACE::Color3<T> *v) { boost::python::extract <IMATH_NAMESPACE::C3c> extractorC3c (p); if (extractorC3c.check()) { IMATH_NAMESPACE::C3c c3c = extractorC3c(); v->setValue (U(c3c[0]), U(c3c[1]), U(c3c[2])); return 1; } boost::python::extract <IMATH_NAMESPACE::C3f> extractorC3f (p); if (extractorC3f.check()) { IMATH_NAMESPACE::C3f c3f = extractorC3f(); v->setValue (U(c3f[0]), U(c3f[1]), U(c3f[2])); return 1; } boost::python::extract <boost::python::tuple> extractorTuple (p); if (extractorTuple.check()) { boost::python::tuple t = extractorTuple(); if (t.attr ("__len__") () == 3) { double a = boost::python::extract <double> (t[0]); double b = boost::python::extract <double> (t[1]); double c = boost::python::extract <double> (t[2]); v->setValue (U(a), U(b), U(c)); return 1; } } boost::python::extract <boost::python::list> extractorList (p); if (extractorList.check()) { boost::python::list l = extractorList(); if (l.attr ("__len__") () == 3) { boost::python::extract <double> extractor0 (l[0]); boost::python::extract <double> extractor1 (l[1]); boost::python::extract <double> extractor2 (l[2]); if (extractor0.check() && extractor1.check() && extractor2.check()) { v->setValue (U(extractor0()), U(extractor1()), U(extractor2())); return 1; } } } boost::python::extract <IMATH_NAMESPACE::V3i> extractorV3i (p); if (extractorV3i.check()) { IMATH_NAMESPACE::V3i v3i = extractorV3i(); v->setValue (U(v3i[0]), U(v3i[1]), U(v3i[2])); return 1; } boost::python::extract <IMATH_NAMESPACE::V3f> extractorV3f (p); if (extractorV3f.check()) { IMATH_NAMESPACE::V3f v3f = extractorV3f(); v->setValue (U(v3f[0]), U(v3f[1]), U(v3f[2])); return 1; } boost::python::extract <IMATH_NAMESPACE::V3d> extractorV3d (p); if (extractorV3d.check()) { IMATH_NAMESPACE::V3d v3d = extractorV3d(); v->setValue (U(v3d[0]), U(v3d[1]), U(v3d[2])); return 1; } return 0; } template <class T, class U> int C4<T, U>::convert (PyObject *p, IMATH_NAMESPACE::Color4<T> *v) { boost::python::extract <IMATH_NAMESPACE::C4c> extractorC4c (p); if (extractorC4c.check()) { IMATH_NAMESPACE::C4c c4c = extractorC4c(); v->setValue (U(c4c[0]), U(c4c[1]), U(c4c[2]), U(c4c[3])); return 1; } boost::python::extract <IMATH_NAMESPACE::C4f> extractorC4f (p); if (extractorC4f.check()) { IMATH_NAMESPACE::C4f c4f = extractorC4f(); v->setValue (U(c4f[0]), U(c4f[1]), U(c4f[2]), U(c4f[3])); return 1; } boost::python::extract <boost::python::tuple> extractorTuple (p); if (extractorTuple.check()) { boost::python::tuple t = extractorTuple(); if (t.attr ("__len__") () == 4) { // As with V3<T>, we extract the tuple elements as doubles and // cast them to Ts in setValue(), to avoid any odd cases where // extracting them as Ts from the start would fail. double a = boost::python::extract <double> (t[0]); double b = boost::python::extract <double> (t[1]); double c = boost::python::extract <double> (t[2]); double d = boost::python::extract <double> (t[3]); v->setValue (U(a), U(b), U(c), U(d)); return 1; } } boost::python::extract <boost::python::list> extractorList (p); if (extractorList.check()) { boost::python::list l = extractorList(); if (l.attr ("__len__") () == 4) { boost::python::extract <double> extractor0 (l[0]); boost::python::extract <double> extractor1 (l[1]); boost::python::extract <double> extractor2 (l[2]); boost::python::extract <double> extractor3 (l[3]); if (extractor0.check() && extractor1.check() && extractor2.check() && extractor3.check()) { v->setValue (U(extractor0()), U(extractor1()), U(extractor2()), U(extractor3())); return 1; } } } return 0; } typedef C3<float, float> Color3f; typedef C3<unsigned char, int> Color3c; typedef Color3f C3f; typedef Color3c C3c; typedef C4<float, float> Color4f; typedef C4<unsigned char, int> Color4c; typedef Color4f C4f; typedef Color4c C4c; } #endif PyImathVec3Impl.h 0000644 00000065174 15125213144 0007646 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathVec3Impl_h_ #define _PyImathVec3Impl_h_ // // This .C file was turned into a header file so that instantiations // of the various V3* types can be spread across multiple files in // order to work around MSVC limitations. // #include <Python.h> #include <boost/python.hpp> #include <boost/python/make_constructor.hpp> #include <boost/format.hpp> #include <ImathVec.h> #include <ImathVecAlgo.h> #include "PyImath.h" #include "PyImathMathExc.h" #include "PyImathVec.h" #include "PyImathDecorators.h" namespace PyImath { using namespace boost::python; using namespace IMATH_NAMESPACE; template <class T> struct Vec3Name { static const char *value(); }; // create a new default constructor that initializes Vec3<T> to zero. template <class T> static Vec3<T> * Vec3_construct_default() { return new Vec3<T>(T(0),T(0),T(0)); } template <class T> static Vec3<T> * Vec3_object_constructor1(const object &obj) { Vec3<T> w; extract<Vec3<int> > e1(obj); extract<Vec3<float> > e2(obj); extract<Vec3<double> > e3(obj); extract<tuple> e4(obj); extract<double> e5(obj); extract<list> e6(obj); if(e1.check()) { w = e1(); } else if(e2.check()) { w = e2(); } else if(e3.check()) { w = e3(); } else if(e4.check()) { tuple t = e4(); if(t.attr("__len__")() == 3) { w.x = extract<T>(t[0]); w.y = extract<T>(t[1]); w.z = extract<T>(t[2]); } else throw std::invalid_argument ("tuple must have length of 3"); } else if(e5.check()) { T a = e5(); w.setValue(a, a, a); } else if(e6.check()) { list l = e6(); if(l.attr("__len__")() == 3) { w.x = extract<T>(l[0]); w.y = extract<T>(l[1]); w.z = extract<T>(l[2]); } else throw std::invalid_argument ("list must have length of 3"); } else throw std::invalid_argument ("invalid parameters passed to Vec3 constructor"); Vec3<T> *v = new Vec3<T>; *v = w; return v; } template <class T> static Vec3<T> * Vec3_object_constructor2(const object &obj1, const object &obj2, const object &obj3) { extract<double> e1(obj1); extract<double> e2(obj2); extract<double> e3(obj3); Vec3<T> *v = new Vec3<T>; if(e1.check()) { v->x = e1();} else { throw std::invalid_argument ("invalid parameters passed to Vec3 constructor"); } if(e2.check()) { v->y = e2();} else { throw std::invalid_argument ("invalid parameters passed to Vec3 constructor"); } if(e3.check()) { v->z = e3();} else { throw std::invalid_argument ("invalid parameters passed to Vec3 constructor"); } return v; } // Implementations of str and repr are same here, // but we'll specialize repr for float and double to make them exact. template <class T> static std::string Vec3_str(const Vec3<T> &v) { std::stringstream stream; stream << Vec3Name<T>::value() << "(" << v.x << ", " << v.y << ", " << v.z << ")"; return stream.str(); } template <class T> static std::string Vec3_repr(const Vec3<T> &v) { std::stringstream stream; stream << Vec3Name<T>::value() << "(" << v.x << ", " << v.y << ", " << v.z << ")"; return stream.str(); } template <class T> static IMATH_NAMESPACE::Vec3<T> Vec3_cross(const IMATH_NAMESPACE::Vec3<T> &v, const IMATH_NAMESPACE::Vec3<T> &other) { MATH_EXC_ON; return v.cross(other); } template <class T> static FixedArray<IMATH_NAMESPACE::Vec3<T> > Vec3_cross_Vec3Array(const IMATH_NAMESPACE::Vec3<T> &va, const FixedArray<IMATH_NAMESPACE::Vec3<T> > &vb) { MATH_EXC_ON; size_t len = vb.len(); FixedArray<IMATH_NAMESPACE::Vec3<T> > f(len); for (size_t i = 0; i < len; ++i) f[i] = va.cross(vb[i]); return f; } template <class T> static T Vec3_dot(const IMATH_NAMESPACE::Vec3<T> &v, const IMATH_NAMESPACE::Vec3<T> &other) { MATH_EXC_ON; return v.dot(other); } template <class T> static FixedArray<T> Vec3_dot_Vec3Array(const IMATH_NAMESPACE::Vec3<T> &va, const FixedArray<IMATH_NAMESPACE::Vec3<T> > &vb) { MATH_EXC_ON; size_t len = vb.len(); FixedArray<T> f(len); for (size_t i = 0; i < len; ++i) f[i] = va.dot(vb[i]); return f; } template <class T> static T Vec3_length(const IMATH_NAMESPACE::Vec3<T> &v) { MATH_EXC_ON; return v.length(); } template <class T> static T Vec3_length2(const IMATH_NAMESPACE::Vec3<T> &v) { MATH_EXC_ON; return v.length2(); } template <class T> static const Vec3<T> & Vec3_normalize(IMATH_NAMESPACE::Vec3<T> &v) { MATH_EXC_ON; return v.normalize(); } template <class T> static const Vec3<T> & Vec3_normalizeExc(IMATH_NAMESPACE::Vec3<T> &v) { MATH_EXC_ON; return v.normalizeExc(); } template <class T> static const Vec3<T> & Vec3_normalizeNonNull(IMATH_NAMESPACE::Vec3<T> &v) { MATH_EXC_ON; return v.normalizeNonNull(); } template <class T> static Vec3<T> Vec3_normalized(const IMATH_NAMESPACE::Vec3<T> &v) { MATH_EXC_ON; return v.normalized(); } template <class T> static Vec3<T> Vec3_normalizedExc(const IMATH_NAMESPACE::Vec3<T> &v) { MATH_EXC_ON; return v.normalizedExc(); } template <class T> static Vec3<T> Vec3_normalizedNonNull(const IMATH_NAMESPACE::Vec3<T> &v) { MATH_EXC_ON; return v.normalizedNonNull(); } template <class T> static Vec3<T> closestVertex(Vec3<T> &p, const Vec3<T> &v0, const Vec3<T> &v1, const Vec3<T> &v2) { MATH_EXC_ON; return IMATH_NAMESPACE::closestVertex(v0, v1, v2, p); } template <class T> static const Vec3<T> & Vec3_negate(IMATH_NAMESPACE::Vec3<T> &v) { MATH_EXC_ON; return v.negate(); } template <class T> static Vec3<T> orthogonal(const Vec3<T> &v, const Vec3<T> &v0) { MATH_EXC_ON; return IMATH_NAMESPACE::orthogonal(v, v0); } template <class T> static Vec3<T> project(const Vec3<T> &v, const Vec3<T> &v0) { MATH_EXC_ON; return IMATH_NAMESPACE::project(v0, v); } template <class T> static Vec3<T> reflect(const Vec3<T> &v, const Vec3<T> &v0) { MATH_EXC_ON; return IMATH_NAMESPACE::reflect(v, v0); } template <class T> static void setValue(Vec3<T> &v, T a, T b, T c) { v.x = a; v.y = b; v.z = c; } template <class T> static Vec3<T> Vec3_add (const Vec3<T> &v, const Vec3<T> &w) { MATH_EXC_ON; return v + w; } template <class T> static Vec3<T> Vec3_sub (const Vec3<T> &v, const Vec3<T> &w) { MATH_EXC_ON; return v - w; } template <class T> static Vec3<T> Vec3_neg (const Vec3<T> &v) { MATH_EXC_ON; return -v; } template <class T, class U> static Vec3<T> Vec3_mul (const Vec3<T> &v, Vec3<U> &w) { MATH_EXC_ON; Vec3<T> w2 (w); return v * w2; } template <class T> static Vec3<T> Vec3_mulT (const Vec3<T> &v, T t) { MATH_EXC_ON; return v * t; } template <class T> static FixedArray<IMATH_NAMESPACE::Vec3<T> > Vec3_mulTArray (const Vec3<T> &v, const FixedArray<T> &t) { MATH_EXC_ON; size_t len = t.len(); FixedArray<IMATH_NAMESPACE::Vec3<T> > retval(len); for (size_t i=0; i<len; ++i) retval[i] = v*t[i]; return retval; } template <class T> static FixedArray<IMATH_NAMESPACE::Vec3<T> > Vec3_rmulTArray (const Vec3<T> &v, const FixedArray<T> &t) { return Vec3_mulTArray(v,t); } template <class T,class S> static Vec3<T> Vec3_div (Vec3<T> &v, Vec3<S> &w) { MATH_EXC_ON; return v / w; } template <class T> static Vec3<T> Vec3_rmulT (Vec3<T> &v, T t) { MATH_EXC_ON; return t * v; } template <class T, class U> static const Vec3<T> & Vec3_imulV(Vec3<T> &v, const Vec3<U> &w) { MATH_EXC_ON; return v *= w; } template <class T> static const Vec3<T> & Vec3_imulT(IMATH_NAMESPACE::Vec3<T> &v, T t) { MATH_EXC_ON; return v *= t; } template <class T, class U> static Vec3<T> Vec3_mulM33 (Vec3<T> &v, const Matrix33<U> &m) { MATH_EXC_ON; return v * m; } template <class T, class U> static Vec3<T> Vec3_mulM44 (Vec3<T> &v, const Matrix44<U> &m) { MATH_EXC_ON; return v * m; } template <class T> static const Vec3<T> & Vec3_idivObj(IMATH_NAMESPACE::Vec3<T> &v, const object &o) { MATH_EXC_ON; Vec3<T> v2; if (PyImath::V3<T>::convert (o.ptr(), &v2)) { return v /= v2; } else { extract<double> e(o); if (e.check()) return v /= e(); else throw std::invalid_argument ("V3 division expects an argument" "convertible to a V3"); } } template <class T> static Vec3<T> Vec3_subT(const Vec3<T> &v, T a) { MATH_EXC_ON; Vec3<T> w; w.setValue(v.x - a, v.y - a, v.z - a); return w; } template <class T,class BoostPyType> static Vec3<T> Vec3_subTuple(const Vec3<T> &v, const BoostPyType &t) { MATH_EXC_ON; Vec3<T> w; if(t.attr("__len__")() == 3) { w.x = v.x - extract<T>(t[0]); w.y = v.y - extract<T>(t[1]); w.z = v.z - extract<T>(t[2]); } else throw std::invalid_argument ("tuple must have length of 3"); return w; } template <class T> static Vec3<T> Vec3_rsubT(const Vec3<T> &v, T a) { MATH_EXC_ON; Vec3<T> w; w.setValue(a - v.x, a - v.y, a - v.z); return w; } template <class T, class BoostPyType> static Vec3<T> Vec3_rsubTuple(const Vec3<T> &v, const BoostPyType &t) { MATH_EXC_ON; Vec3<T> w; if(t.attr("__len__")() == 3) { w.x = extract<T>(t[0]) - v.x; w.y = extract<T>(t[1]) - v.y; w.z = extract<T>(t[2]) - v.z; } else throw std::invalid_argument ("tuple must have length of 3"); return w; } template <class T, class BoostPyType> static Vec3<T> Vec3_addTuple(const Vec3<T> &v, const BoostPyType &t) { MATH_EXC_ON; Vec3<T> w; if(t.attr("__len__")() == 3) { w.x = v.x + extract<T>(t[0]); w.y = v.y + extract<T>(t[1]); w.z = v.z + extract<T>(t[2]); } else throw std::invalid_argument ("tuple must have length of 3"); return w; } template <class T> static Vec3<T> Vec3_addT(const Vec3<T> &v, T a) { MATH_EXC_ON; Vec3<T> w; w.setValue(v.x + a, v.y + a, v.z + a); return w; } template <class T, class U> static Vec3<T> Vec3_addV(const Vec3<T> &v, const Vec3<U> &w) { MATH_EXC_ON; return v + w; } template <class T, class U> static const Vec3<T> & Vec3_iaddV(Vec3<T> &v, const Vec3<U> &w) { MATH_EXC_ON; return v += w; } template <class T, class U> static Vec3<T> Vec3_subV(const Vec3<T> &v, const Vec3<U> &w) { MATH_EXC_ON; return v - w; } template <class T, class U> static const Vec3<T> & Vec3_isubV(Vec3<T> &v, const Vec3<U> &w) { MATH_EXC_ON; return v -= w; } template <class T> static Vec3<T> mult(const Vec3<T> &v, tuple t) { MATH_EXC_ON; Vec3<T> w; if(t.attr("__len__")() == 1){ w.x = v.x*extract<T>(t[0]); w.y = v.y*extract<T>(t[0]); w.z = v.z*extract<T>(t[0]); } else if(t.attr("__len__")() == 3){ w.x = v.x*extract<T>(t[0]); w.y = v.y*extract<T>(t[1]); w.z = v.z*extract<T>(t[2]); } else throw std::invalid_argument ("tuple must have length of 1 or 3"); return w; } template <class T, class U> static const Vec3<T> & Vec3_imulM44 (Vec3<T> &v, const Matrix44<U> &m) { MATH_EXC_ON; return v *= m; } template <class T, class BoostPyType> static Vec3<T> Vec3_divTuple(const Vec3<T> &v, const BoostPyType &t) { if(t.attr("__len__")() == 3) { T x = extract<T>(t[0]); T y = extract<T>(t[1]); T z = extract<T>(t[2]); if(x != T(0) && y != T(0) && z != T(0)) return Vec3<T>(v.x / x, v.y / y, v.z / z); else throw std::domain_error ("Division by zero"); } else throw std::invalid_argument ("Vec3 expects tuple of length 3"); } template <class T, class BoostPyType> static Vec3<T> Vec3_rdivTuple(const Vec3<T> &v, const BoostPyType &t) { MATH_EXC_ON; Vec3<T> w; if(t.attr("__len__")() == 3) { T x = extract<T>(t[0]); T y = extract<T>(t[1]); T z = extract<T>(t[2]); if(v.x != T(0) && v.y != T(0) && v.z != T(0)){ w.setValue(x / v.x, y / v.y, z / v.z); } else throw std::domain_error ("Division by zero"); } else throw std::invalid_argument ("tuple must have length of 3"); return w; } template <class T> static Vec3<T> Vec3_divT(const Vec3<T> &v, T a) { MATH_EXC_ON; Vec3<T> w; if(a != T(0)){ w.setValue(v.x / a, v.y / a, v.z / a); } else throw std::domain_error ("Division by zero"); return w; } template <class T> static Vec3<T> Vec3_rdivT(const Vec3<T> &v, T a) { MATH_EXC_ON; Vec3<T> w; if(v.x != T(0) && v.y != T(0) && v.z != T(0)){ w.setValue(a / v.x, a / v.y, a / v.z); } else throw std::domain_error ("Division by zero"); return w; } template <class T> static Vec3<T> Vec3_Vec3_mulT(const Vec3<T>& v, const Vec3<T>& w) { MATH_EXC_ON; return v*w; } template <class T> static Vec3<T> Vec3_Vec3_divT(const Vec3<T>& v, const Vec3<T>& w) { MATH_EXC_ON; return v/w; } template <class T> static bool lessThan(const Vec3<T> &v, const object &obj) { extract<Vec3<T> > e1(obj); extract<tuple> e2(obj); Vec3<T> w; if(e1.check()) { w = e1(); } else if(e2.check()) { tuple t = e2(); T x = extract<T>(t[0]); T y = extract<T>(t[1]); T z = extract<T>(t[2]); w.setValue(x,y,z); } else throw std::invalid_argument ("invalid parameters passed to operator <"); bool isLessThan = (v.x <= w.x && v.y <= w.y && v.z <= w.z) && v != w; return isLessThan; } template <class T> static bool greaterThan(const Vec3<T> &v, const object &obj) { extract<Vec3<T> > e1(obj); extract<tuple> e2(obj); Vec3<T> w; if(e1.check()) { w = e1(); } else if(e2.check()) { tuple t = e2(); T x = extract<T>(t[0]); T y = extract<T>(t[1]); T z = extract<T>(t[2]); w.setValue(x,y,z); } else throw std::invalid_argument ("invalid parameters passed to operator >"); bool isGreaterThan = (v.x >= w.x && v.y >= w.y && v.z >= w.z) && v != w; return isGreaterThan; } template <class T> static bool lessThanEqual(const Vec3<T> &v, const object &obj) { extract<Vec3<T> > e1(obj); extract<tuple> e2(obj); Vec3<T> w; if(e1.check()) { w = e1(); } else if(e2.check()) { tuple t = e2(); T x = extract<T>(t[0]); T y = extract<T>(t[1]); T z = extract<T>(t[2]); w.setValue(x,y,z); } else throw std::invalid_argument ("invalid parameters passed to operator <="); bool isLessThanEqual = (v.x <= w.x && v.y <= w.y && v.z <= w.z); return isLessThanEqual; } template <class T> static bool greaterThanEqual(const Vec3<T> &v, const object &obj) { extract<Vec3<T> > e1(obj); extract<tuple> e2(obj); Vec3<T> w; if(e1.check()) { w = e1(); } else if(e2.check()) { tuple t = e2(); T x = extract<T>(t[0]); T y = extract<T>(t[1]); T z = extract<T>(t[2]); w.setValue(x,y,z); } else throw std::invalid_argument ("invalid parameters passed to operator >="); bool isGreaterThanEqual = (v.x >= w.x && v.y >= w.y && v.z >= w.z); return isGreaterThanEqual; } template <class T> static bool equalWithAbsErrorObj(const Vec3<T> &v, const object &obj1, const object &obj2) { extract<Vec3<int> > e1(obj1); extract<Vec3<float> > e2(obj1); extract<Vec3<double> > e3(obj1); extract<tuple> e4(obj1); extract<double> e5(obj2); Vec3<T> w; if(e1.check()) { w = e1(); } else if(e2.check()) { w = e2(); } else if(e3.check()) { w = e3(); } else if(e4.check()) { tuple t = e4(); if(t.attr("__len__")() == 3) { w.x = extract<T>(t[0]); w.y = extract<T>(t[1]); w.z = extract<T>(t[2]); } else throw std::invalid_argument ("tuple of length 3 expected"); } else throw std::invalid_argument ("invalid parameters passed to equalWithAbsError"); if(e5.check()) { return v.equalWithAbsError(w, e5()); } else throw std::invalid_argument ("invalid parameters passed to equalWithAbsError"); } template <class T> static bool equalWithRelErrorObj(const Vec3<T> &v, const object &obj1, const object &obj2) { extract<Vec3<int> > e1(obj1); extract<Vec3<float> > e2(obj1); extract<Vec3<double> > e3(obj1); extract<tuple> e4(obj1); extract<double> e5(obj2); Vec3<T> w; if(e1.check()) { w = e1(); } else if(e2.check()) { w = e2(); } else if(e3.check()) { w = e3(); } else if(e4.check()) { tuple t = e4(); if(t.attr("__len__")() == 3) { w.x = extract<T>(t[0]); w.y = extract<T>(t[1]); w.z = extract<T>(t[2]); } else throw std::invalid_argument ("tuple of length 3 expected"); } else throw std::invalid_argument ("invalid parameters passed to equalWithRelError"); if(e5.check()) { return v.equalWithRelError(w, e5()); } else throw std::invalid_argument ("invalid parameters passed to equalWithRelError"); } template <class T> static bool equal(const Vec3<T> &v, const tuple &t) { Vec3<T> w; if(t.attr("__len__")() == 3) { w.x = extract<T>(t[0]); w.y = extract<T>(t[1]); w.z = extract<T>(t[2]); return (v == w); } else throw std::invalid_argument ("tuple of length 3 expected"); } template <class T> static bool notequal(const Vec3<T> &v, const tuple &t) { Vec3<T> w; if(t.attr("__len__")() == 3) { w.x = extract<T>(t[0]); w.y = extract<T>(t[1]); w.z = extract<T>(t[2]); return (v != w); } else throw std::invalid_argument ("tuple of length 3 expected"); } // Trick to register methods for float-only-based vectors template <class T, IMATH_ENABLE_IF(!std::is_integral<T>::value)> void register_Vec3_floatonly(class_<Vec3<T>>& vec3_class) { vec3_class .def("length", &Vec3_length<T>,"length() magnitude of the vector") .def("normalize", &Vec3_normalize<T>,return_internal_reference<>(), "v.normalize() destructively normalizes v and returns a reference to it") .def("normalizeExc", &Vec3_normalizeExc<T>,return_internal_reference<>(), "v.normalizeExc() destructively normalizes V and returns a reference to it, throwing an exception if length() == 0") .def("normalizeNonNull", &Vec3_normalizeNonNull<T>,return_internal_reference<>(), "v.normalizeNonNull() destructively normalizes V and returns a reference to it, faster if lngth() != 0") .def("normalized", &Vec3_normalized<T>, "v.normalized() returns a normalized copy of v") .def("normalizedExc", &Vec3_normalizedExc<T>, "v.normalizedExc() returns a normalized copy of v, throwing an exception if length() == 0") .def("normalizedNonNull", &Vec3_normalizedNonNull<T>, "v.normalizedNonNull() returns a normalized copy of v, faster if lngth() != 0") .def("orthogonal", &orthogonal<T>) .def("project", &project<T>) .def("reflect", &reflect<T>) ; } template <class T, IMATH_ENABLE_IF(std::is_integral<T>::value)> void register_Vec3_floatonly(class_<Vec3<T>>& vec2_class) { } template <class T> class_<Vec3<T> > register_Vec3() { typedef PyImath::StaticFixedArray<Vec3<T>,T,3> Vec3_helper; class_<Vec3<T> > vec3_class(Vec3Name<T>::value(), Vec3Name<T>::value(),init<Vec3<T> >("copy construction")); vec3_class .def("__init__",make_constructor(Vec3_construct_default<T>),"initialize to (0,0,0)") .def("__init__",make_constructor(Vec3_object_constructor1<T>)) .def("__init__",make_constructor(Vec3_object_constructor2<T>)) .def_readwrite("x", &Vec3<T>::x) .def_readwrite("y", &Vec3<T>::y) .def_readwrite("z", &Vec3<T>::z) .def("baseTypeEpsilon", &Vec3<T>::baseTypeEpsilon,"baseTypeEpsilon() epsilon value of the base type of the vector") .staticmethod("baseTypeEpsilon") .def("baseTypeMax", &Vec3<T>::baseTypeMax,"baseTypeMax() max value of the base type of the vector") .staticmethod("baseTypeMax") .def("baseTypeLowest", &Vec3<T>::baseTypeLowest,"baseTypeLowest() largest negative value of the base type of the vector") .staticmethod("baseTypeLowest") .def("baseTypeSmallest", &Vec3<T>::baseTypeSmallest,"baseTypeSmallest() smallest value of the base type of the vector") .staticmethod("baseTypeSmallest") .def("cross", &Vec3_cross<T>,"v1.cross(v2) right handed cross product") .def("cross", &Vec3_cross_Vec3Array<T>,"v1.cross(v2) right handed array cross product") .def("dimensions", &Vec3<T>::dimensions,"dimensions() number of dimensions in the vector") .staticmethod("dimensions") .def("dot", &Vec3_dot<T>,"v1.dot(v2) inner product of the two vectors") .def("dot", &Vec3_dot_Vec3Array<T>,"v1.dot(v2) array inner product") .def("equalWithAbsError", &Vec3<T>::equalWithAbsError, "v1.equalWithAbsError(v2) true if the elements " "of v1 and v2 are the same with an absolute error of no more than e, " "i.e., abs(v1[i] - v2[i]) <= e") .def("equalWithAbsError", &equalWithAbsErrorObj<T>) .def("equalWithRelError", &Vec3<T>::equalWithRelError, "v1.equalWithAbsError(v2) true if the elements " "of v1 and v2 are the same with an absolute error of no more than e, " "i.e., abs(v1[i] - v2[i]) <= e * abs(v1[i])") .def("equalWithRelError", &equalWithRelErrorObj<T>) .def("length2", &Vec3_length2<T>,"length2() square magnitude of the vector") .def("__len__", Vec3_helper::len) .def("__getitem__", Vec3_helper::getitem,return_value_policy<copy_non_const_reference>()) .def("__setitem__", Vec3_helper::setitem) .def("closestVertex", &closestVertex<T>) .def("negate", &Vec3_negate<T>, return_internal_reference<>()) .def("setValue", &setValue<T>) .def("__neg__", &Vec3_neg<T>) .def("__mul__", &Vec3_mul<T, int>) .def("__mul__", &Vec3_mul<T, float>) .def("__mul__", &Vec3_mul<T, double>) .def("__mul__", &Vec3_mulT<T>) .def("__mul__", &Vec3_mulTArray<T>) .def("__rmul__", &Vec3_rmulT<T>) .def("__rmul__", &Vec3_rmulTArray<T>) .def("__imul__", &Vec3_imulV<T, int>,return_internal_reference<>()) .def("__imul__", &Vec3_imulV<T, float>,return_internal_reference<>()) .def("__imul__", &Vec3_imulV<T, double>,return_internal_reference<>()) .def("__imul__", &Vec3_imulT<T>,return_internal_reference<>()) .def("__div__", &Vec3_Vec3_divT<T>) .def("__truediv__", &Vec3_Vec3_divT<T>) .def("__mul__", &Vec3_mulM33<T, float>) .def("__mul__", &Vec3_mulM33<T, double>) .def("__mul__", &Vec3_mulM44<T, float>) .def("__mul__", &Vec3_mulM44<T, double>) .def("__mul__", &Vec3_Vec3_mulT<T>) .def("__div__", &Vec3_div<T,int>) .def("__div__", &Vec3_div<T,float>) .def("__div__", &Vec3_div<T,double>) .def("__div__", &Vec3_divTuple<T,tuple>) .def("__div__", &Vec3_divTuple<T,list>) .def("__div__", &Vec3_divT<T>) .def("__truediv__", &Vec3_div<T,int>) .def("__truediv__", &Vec3_div<T,float>) .def("__truediv__", &Vec3_div<T,double>) .def("__truediv__", &Vec3_divTuple<T,tuple>) .def("__truediv__", &Vec3_divTuple<T,list>) .def("__truediv__", &Vec3_divT<T>) .def("__rdiv__", &Vec3_rdivTuple<T,tuple>) .def("__rdiv__", &Vec3_rdivTuple<T,list>) .def("__rdiv__", &Vec3_rdivT<T>) .def("__rtruediv__", &Vec3_rdivTuple<T,tuple>) .def("__rtruediv__", &Vec3_rdivTuple<T,list>) .def("__rtruediv__", &Vec3_rdivT<T>) .def("__idiv__", &Vec3_idivObj<T>,return_internal_reference<>()) .def("__itruediv__", &Vec3_idivObj<T>,return_internal_reference<>()) .def("__xor__", &Vec3_dot<T>) .def("__mod__", &Vec3_cross<T>) .def(self == self) // NOSONAR - suppress SonarCloud bug report. .def(self != self) // NOSONAR - suppress SonarCloud bug report. .def("__add__", &Vec3_add<T>) .def("__add__", &Vec3_addV<T, int>) .def("__add__", &Vec3_addV<T, float>) .def("__add__", &Vec3_addV<T, double>) .def("__add__", &Vec3_addT<T>) .def("__add__", &Vec3_addTuple<T,tuple>) .def("__add__", &Vec3_addTuple<T,list>) .def("__radd__", &Vec3_addT<T>) .def("__radd__", &Vec3_addTuple<T,tuple>) .def("__radd__", &Vec3_addTuple<T,list>) .def("__radd__", &Vec3_add<T>) .def("__iadd__", &Vec3_iaddV<T, int>, return_internal_reference<>()) .def("__iadd__", &Vec3_iaddV<T, float>, return_internal_reference<>()) .def("__iadd__", &Vec3_iaddV<T, double>, return_internal_reference<>()) .def("__sub__", &Vec3_sub<T>) .def("__sub__", &Vec3_subV<T, int>) .def("__sub__", &Vec3_subV<T, float>) .def("__sub__", &Vec3_subV<T, double>) .def("__sub__", &Vec3_subT<T>) .def("__sub__", &Vec3_subTuple<T,tuple>) .def("__sub__", &Vec3_subTuple<T,list>) .def("__rsub__", &Vec3_rsubT<T>) .def("__rsub__", &Vec3_rsubTuple<T,tuple>) .def("__rsub__", &Vec3_rsubTuple<T,list>) .def("__isub__", &Vec3_isubV<T, int>, return_internal_reference<>()) .def("__isub__", &Vec3_isubV<T, float>, return_internal_reference<>()) .def("__isub__", &Vec3_isubV<T, double>, return_internal_reference<>()) .def("__mul__", &mult<T>) .def("__rmul__", &mult<T>) .def("__imul__", &Vec3_imulM44<T, float>, return_internal_reference<>()) .def("__imul__", &Vec3_imulM44<T, double>, return_internal_reference<>()) .def("__lt__", &lessThan<T>) .def("__gt__", &greaterThan<T>) .def("__le__", &lessThanEqual<T>) .def("__ge__", &greaterThanEqual<T>) .def("__eq__", &equal<T>) .def("__ne__", ¬equal<T>) //.def(self_ns::str(self)) .def("__str__",&Vec3_str<T>) .def("__repr__",&Vec3_repr<T>) ; register_Vec3_floatonly<T>(vec3_class); decoratecopy(vec3_class); //add_swizzle3_operators(v3f_class); return vec3_class; } } // namespace PyImath #endif // _PyImathVec3Impl_h_ ImathShear.h 0000644 00000042677 15125213144 0006760 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // A representation of a shear transformation // #ifndef INCLUDED_IMATHSHEAR_H #define INCLUDED_IMATHSHEAR_H #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathMath.h" #include "ImathVec.h" #include <iostream> IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// /// Shear6 class template. /// /// A shear matrix is technically defined as having a single nonzero /// off-diagonal element; more generally, a shear transformation is /// defined by those off-diagonal elements, so in 3D, that means there /// are 6 possible elements/coefficients: /// /// | X' | | 1 YX ZX 0 | | X | /// | Y' | | XY 1 ZY 0 | | Y | /// | Z' | = | XZ YZ 1 0 | = | Z | /// | 1 | | 0 0 0 1 | | 1 | /// /// X' = X + YX * Y + ZX * Z /// Y' = YX * X + Y + ZY * Z /// Z` = XZ * X + YZ * Y + Z /// /// See /// https://www.cs.drexel.edu/~david/Classes/CS430/Lectures/L-04_3DTransformations.6.pdf /// /// Those variable elements correspond to the 6 values in a Shear6. /// So, looking at those equations, "Shear YX", for example, means /// that for any point transformed by that matrix, its X values will /// have some of their Y values added. If you're talking /// about "Axis A has values from Axis B added to it", there are 6 /// permutations for A and B (XY, XZ, YX, YZ, ZX, ZY). /// /// Not that Maya has only three values, which represent the /// lower/upper (depending on column/row major) triangle of the /// matrix. Houdini is the same as Maya (see /// https://www.sidefx.com/docs/houdini/props/obj.html) in this /// respect. /// /// There's another way to look at it. A general affine transformation /// in 3D has 12 degrees of freedom - 12 "available" elements in the /// 4x4 matrix since a single row/column must be (0,0,0,1). If you /// add up the degrees of freedom from Maya: /// /// - 3 translation /// - 3 rotation /// - 3 scale /// - 3 shear /// /// You obviously get the full 12. So technically, the Shear6 option /// of having all 6 shear options is overkill; Imath/Shear6 has 15 /// values for a 12-degree-of-freedom transformation. This means that /// any nonzero values in those last 3 shear coefficients can be /// represented in those standard 12 degrees of freedom. Here's a /// python example of how to do that: /// /// /// >>> import imath /// >>> M = imath.M44f() /// >>> s = imath.V3f() /// >>> h = imath.V3f() /// >>> r = imath.V3f() /// >>> t = imath.V3f() /// # Use Shear.YX (index 3), which is an "extra" shear value /// >>> M.setShear((0,0,0,1,0,0)) /// M44f((1, 1, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1)) /// >>> M.extractSHRT(s, h, r, t) /// 1 /// >>> s /// V3f(1.41421354, 0.707106769, 1) /// >>> h /// V3f(1, 0, 0) /// >>> r /// V3f(0, -0, 0.785398185) /// >>> t /// V3f(0, 0, 0) /// /// That shows how to decompose a transform matrix with one of those /// "extra" shear coefficients into those standard 12 degrees of /// freedom. But it's not necessarily intuitive; in this case, a /// single non-zero shear coefficient resulted in a transform that has /// non-uniform scale, a single "standard" shear value, and some /// rotation. /// /// So, it would seem that any transform with those extra shear /// values set could be translated into Maya to produce the exact same /// transformation matrix; but doing this is probably pretty /// undesirable, since the result would have some surprising values on /// the other transformation attributes, despite being technically /// correct. /// /// This usage of "degrees of freedom" is a bit hand-wavey here; /// having a total of 12 inputs into the construction of a standard /// transformation matrix doesn't necessarily mean that the matrix has /// 12 true degrees of freedom, but the standard /// translation/rotation/scale/shear matrices have the right /// construction to ensure that. /// template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Shear6 { public: /// @{ /// @name Direct access to members T xy, xz, yz, yx, zx, zy; /// @} /// Element access IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int i); /// Element access IMATH_HOSTDEVICE constexpr const T& operator[] (int i) const; /// @{ /// @name Constructors and Assignment /// Initialize to 0 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Shear6(); /// Initialize to the given XY, XZ, YZ values IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Shear6 (T XY, T XZ, T YZ); /// Initialize to the given XY, XZ, YZ values held in (v.x, v.y, v.z) IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Shear6 (const Vec3<T>& v); /// Initialize to the given XY, XZ, YZ values held in (v.x, v.y, v.z) template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Shear6 (const Vec3<S>& v); /// Initialize to the given (XY XZ YZ YX ZX ZY) values IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Shear6 (T XY, T XZ, T YZ, T YX, T ZX, T ZY); /// Copy constructor IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Shear6 (const Shear6& h); /// Construct from a Shear6 object of another base type template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Shear6 (const Shear6<S>& h); /// Assignment IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Shear6& operator= (const Shear6& h); /// Assignment from vector template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Shear6& operator= (const Vec3<S>& v); /// Destructor ~Shear6() = default; /// @} /// @{ /// @name Compatibility with Sb /// Set the value template <class S> IMATH_HOSTDEVICE void setValue (S XY, S XZ, S YZ, S YX, S ZX, S ZY); /// Set the value template <class S> IMATH_HOSTDEVICE void setValue (const Shear6<S>& h); /// Return the values template <class S> IMATH_HOSTDEVICE void getValue (S& XY, S& XZ, S& YZ, S& YX, S& ZX, S& ZY) const; /// Return the value in `h` template <class S> IMATH_HOSTDEVICE void getValue (Shear6<S>& h) const; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE T* getValue(); /// Return a raw pointer to the array of values IMATH_HOSTDEVICE const T* getValue() const; /// @} /// @{ /// @name Arithmetic and Comparison /// Equality template <class S> IMATH_HOSTDEVICE constexpr bool operator== (const Shear6<S>& h) const; /// Inequality template <class S> IMATH_HOSTDEVICE constexpr bool operator!= (const Shear6<S>& h) const; /// Compare two shears and test if they are "approximately equal": /// @return True if the coefficients of this and h are the same with /// an absolute error of no more than e, i.e., for all i /// abs (this[i] - h[i]) <= e IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Shear6<T>& h, T e) const; /// Compare two shears and test if they are "approximately equal": /// @return True if the coefficients of this and h are the same with /// a relative error of no more than e, i.e., for all i /// abs (this[i] - h[i]) <= e * abs (this[i]) IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithRelError (const Shear6<T>& h, T e) const; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Shear6& operator+= (const Shear6& h); /// Component-wise addition IMATH_HOSTDEVICE constexpr Shear6 operator+ (const Shear6& h) const; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Shear6& operator-= (const Shear6& h); /// Component-wise subtraction IMATH_HOSTDEVICE constexpr Shear6 operator- (const Shear6& h) const; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE constexpr Shear6 operator-() const; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Shear6& negate(); /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Shear6& operator*= (const Shear6& h); /// Scalar multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Shear6& operator*= (T a); /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Shear6 operator* (const Shear6& h) const; /// Scalar multiplication IMATH_HOSTDEVICE constexpr Shear6 operator* (T a) const; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Shear6& operator/= (const Shear6& h); /// Scalar division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Shear6& operator/= (T a); /// Component-wise division IMATH_HOSTDEVICE constexpr Shear6 operator/ (const Shear6& h) const; /// Scalar division IMATH_HOSTDEVICE constexpr Shear6 operator/ (T a) const; /// @} /// @{ /// @name Numerical Limits /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits<T>::lowest(); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits<T>::max(); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits<T>::min(); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits<T>::epsilon(); } /// @} /// Return the number of dimensions, i.e. 6 IMATH_HOSTDEVICE constexpr static unsigned int dimensions() { return 6; } /// The base type: In templates that accept a parameter `V` (could /// be a Color4), you can refer to `T` as `V::BaseType` typedef T BaseType; }; /// Stream output, as "(xy xz yz yx zx zy)" template <class T> std::ostream& operator<< (std::ostream& s, const Shear6<T>& h); /// Reverse multiplication: scalar * Shear6<T> template <class S, class T> IMATH_HOSTDEVICE constexpr Shear6<T> operator* (S a, const Shear6<T>& h); /// 3D shear of type float typedef Vec3<float> Shear3f; /// 3D shear of type double typedef Vec3<double> Shear3d; /// Shear6 of type float typedef Shear6<float> Shear6f; /// Shear6 of type double typedef Shear6<double> Shear6d; //----------------------- // Implementation of Shear6 //----------------------- template <class T> IMATH_CONSTEXPR14 inline T& Shear6<T>::operator[] (int i) { return (&xy)[i]; // NOSONAR - suppress SonarCloud bug report. } template <class T> constexpr inline const T& Shear6<T>::operator[] (int i) const { return (&xy)[i]; // NOSONAR - suppress SonarCloud bug report. } template <class T> IMATH_CONSTEXPR14 inline Shear6<T>::Shear6() { xy = xz = yz = yx = zx = zy = 0; } template <class T> IMATH_CONSTEXPR14 inline Shear6<T>::Shear6 (T XY, T XZ, T YZ) { xy = XY; xz = XZ; yz = YZ; yx = 0; zx = 0; zy = 0; } template <class T> IMATH_CONSTEXPR14 inline Shear6<T>::Shear6 (const Vec3<T>& v) { xy = v.x; xz = v.y; yz = v.z; yx = 0; zx = 0; zy = 0; } template <class T> template <class S> IMATH_CONSTEXPR14 inline Shear6<T>::Shear6 (const Vec3<S>& v) { xy = T (v.x); xz = T (v.y); yz = T (v.z); yx = 0; zx = 0; zy = 0; } template <class T> IMATH_CONSTEXPR14 inline Shear6<T>::Shear6 (T XY, T XZ, T YZ, T YX, T ZX, T ZY) { xy = XY; xz = XZ; yz = YZ; yx = YX; zx = ZX; zy = ZY; } template <class T> IMATH_CONSTEXPR14 inline Shear6<T>::Shear6 (const Shear6& h) { xy = h.xy; xz = h.xz; yz = h.yz; yx = h.yx; zx = h.zx; zy = h.zy; } template <class T> template <class S> IMATH_CONSTEXPR14 inline Shear6<T>::Shear6 (const Shear6<S>& h) { xy = T (h.xy); xz = T (h.xz); yz = T (h.yz); yx = T (h.yx); zx = T (h.zx); zy = T (h.zy); } template <class T> IMATH_CONSTEXPR14 inline const Shear6<T>& Shear6<T>::operator= (const Shear6& h) { xy = h.xy; xz = h.xz; yz = h.yz; yx = h.yx; zx = h.zx; zy = h.zy; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Shear6<T>& Shear6<T>::operator= (const Vec3<S>& v) { xy = T (v.x); xz = T (v.y); yz = T (v.z); yx = 0; zx = 0; zy = 0; return *this; } template <class T> template <class S> inline void Shear6<T>::setValue (S XY, S XZ, S YZ, S YX, S ZX, S ZY) { xy = T (XY); xz = T (XZ); yz = T (YZ); yx = T (YX); zx = T (ZX); zy = T (ZY); } template <class T> template <class S> inline void Shear6<T>::setValue (const Shear6<S>& h) { xy = T (h.xy); xz = T (h.xz); yz = T (h.yz); yx = T (h.yx); zx = T (h.zx); zy = T (h.zy); } template <class T> template <class S> inline void Shear6<T>::getValue (S& XY, S& XZ, S& YZ, S& YX, S& ZX, S& ZY) const { XY = S (xy); XZ = S (xz); YZ = S (yz); YX = S (yx); ZX = S (zx); ZY = S (zy); } template <class T> template <class S> inline void Shear6<T>::getValue (Shear6<S>& h) const { h.xy = S (xy); h.xz = S (xz); h.yz = S (yz); h.yx = S (yx); h.zx = S (zx); h.zy = S (zy); } template <class T> inline T* Shear6<T>::getValue() { return (T*) &xy; } template <class T> inline const T* Shear6<T>::getValue() const { return (const T*) &xy; } template <class T> template <class S> constexpr inline bool Shear6<T>::operator== (const Shear6<S>& h) const { return xy == h.xy && xz == h.xz && yz == h.yz && yx == h.yx && zx == h.zx && zy == h.zy; } template <class T> template <class S> constexpr inline bool Shear6<T>::operator!= (const Shear6<S>& h) const { return xy != h.xy || xz != h.xz || yz != h.yz || yx != h.yx || zx != h.zx || zy != h.zy; } template <class T> IMATH_CONSTEXPR14 inline bool Shear6<T>::equalWithAbsError (const Shear6<T>& h, T e) const { for (int i = 0; i < 6; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i], h[i], e)) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline bool Shear6<T>::equalWithRelError (const Shear6<T>& h, T e) const { for (int i = 0; i < 6; i++) if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i], h[i], e)) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline const Shear6<T>& Shear6<T>::operator+= (const Shear6& h) { xy += h.xy; xz += h.xz; yz += h.yz; yx += h.yx; zx += h.zx; zy += h.zy; return *this; } template <class T> constexpr inline Shear6<T> Shear6<T>::operator+ (const Shear6& h) const { return Shear6 (xy + h.xy, xz + h.xz, yz + h.yz, yx + h.yx, zx + h.zx, zy + h.zy); } template <class T> IMATH_CONSTEXPR14 inline const Shear6<T>& Shear6<T>::operator-= (const Shear6& h) { xy -= h.xy; xz -= h.xz; yz -= h.yz; yx -= h.yx; zx -= h.zx; zy -= h.zy; return *this; } template <class T> constexpr inline Shear6<T> Shear6<T>::operator- (const Shear6& h) const { return Shear6 (xy - h.xy, xz - h.xz, yz - h.yz, yx - h.yx, zx - h.zx, zy - h.zy); } template <class T> constexpr inline Shear6<T> Shear6<T>::operator-() const { return Shear6 (-xy, -xz, -yz, -yx, -zx, -zy); } template <class T> IMATH_CONSTEXPR14 inline const Shear6<T>& Shear6<T>::negate() { xy = -xy; xz = -xz; yz = -yz; yx = -yx; zx = -zx; zy = -zy; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Shear6<T>& Shear6<T>::operator*= (const Shear6& h) { xy *= h.xy; xz *= h.xz; yz *= h.yz; yx *= h.yx; zx *= h.zx; zy *= h.zy; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Shear6<T>& Shear6<T>::operator*= (T a) { xy *= a; xz *= a; yz *= a; yx *= a; zx *= a; zy *= a; return *this; } template <class T> constexpr inline Shear6<T> Shear6<T>::operator* (const Shear6& h) const { return Shear6 (xy * h.xy, xz * h.xz, yz * h.yz, yx * h.yx, zx * h.zx, zy * h.zy); } template <class T> constexpr inline Shear6<T> Shear6<T>::operator* (T a) const { return Shear6 (xy * a, xz * a, yz * a, yx * a, zx * a, zy * a); } template <class T> IMATH_CONSTEXPR14 inline const Shear6<T>& Shear6<T>::operator/= (const Shear6& h) { xy /= h.xy; xz /= h.xz; yz /= h.yz; yx /= h.yx; zx /= h.zx; zy /= h.zy; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Shear6<T>& Shear6<T>::operator/= (T a) { xy /= a; xz /= a; yz /= a; yx /= a; zx /= a; zy /= a; return *this; } template <class T> constexpr inline Shear6<T> Shear6<T>::operator/ (const Shear6& h) const { return Shear6 (xy / h.xy, xz / h.xz, yz / h.yz, yx / h.yx, zx / h.zx, zy / h.zy); } template <class T> constexpr inline Shear6<T> Shear6<T>::operator/ (T a) const { return Shear6 (xy / a, xz / a, yz / a, yx / a, zx / a, zy / a); } //----------------------------- // Stream output implementation //----------------------------- template <class T> std::ostream& operator<< (std::ostream& s, const Shear6<T>& h) { return s << '(' << h.xy << ' ' << h.xz << ' ' << h.yz << h.yx << ' ' << h.zx << ' ' << h.zy << ')'; } //----------------------------------------- // Implementation of reverse multiplication //----------------------------------------- template <class S, class T> constexpr inline Shear6<T> operator* (S a, const Shear6<T>& h) { return Shear6<T> (a * h.xy, a * h.xz, a * h.yz, a * h.yx, a * h.zx, a * h.zy); } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHSHEAR_H ImathMatrix.h 0000644 00000376456 15125213144 0007167 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // 2x2, 3x3, and 4x4 transformation matrix templates // #ifndef INCLUDED_IMATHMATRIX_H #define INCLUDED_IMATHMATRIX_H #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathFun.h" #include "ImathPlatform.h" #include "ImathShear.h" #include "ImathVec.h" #include <cstring> #include <iomanip> #include <iostream> #include <limits> #include <string.h> #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER // suppress exception specification warnings # pragma warning(disable : 4290) #endif IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// Enum used to indicate uninitialized construction of Matrix22, /// Matrix33, Matrix44 enum IMATH_EXPORT_ENUM Uninitialized { UNINITIALIZED }; /// /// 2x2 transformation matrix /// template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Matrix22 { public: /// @{ /// @name Direct access to elements /// Matrix elements T x[2][2]; /// @} /// Row access IMATH_HOSTDEVICE T* operator[] (int i) IMATH_NOEXCEPT; /// Row access IMATH_HOSTDEVICE const T* operator[] (int i) const IMATH_NOEXCEPT; /// @{ /// @name Constructors and Assignment /// Uninitialized IMATH_HOSTDEVICE Matrix22 (Uninitialized) IMATH_NOEXCEPT {} /// Default constructor: initialize to identity /// /// 1 0 /// 0 1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22() IMATH_NOEXCEPT; /// Initialize to scalar constant: /// /// a a /// a a IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22 (T a) IMATH_NOEXCEPT; /// Construct from 2x2 array: /// /// a[0][0] a[0][1] /// a[1][0] a[1][1] IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22 (const T a[2][2]) IMATH_NOEXCEPT; /// Construct from given scalar values: /// /// a b /// c d IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22 (T a, T b, T c, T d) IMATH_NOEXCEPT; /// Copy constructor IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22 (const Matrix22& v) IMATH_NOEXCEPT; /// Construct from Matrix22 of another base type template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 explicit Matrix22 (const Matrix22<S>& v) IMATH_NOEXCEPT; /// Assignment IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator= (const Matrix22& v) IMATH_NOEXCEPT; /// Assignment from scalar IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator= (T a) IMATH_NOEXCEPT; /// Destructor ~Matrix22() IMATH_NOEXCEPT = default; /// @} #if IMATH_FOREIGN_VECTOR_INTEROP /// @{ /// @name Interoperability with other matrix types /// /// Construction and assignment are allowed from other classes that /// appear to be equivalent matrix types, provided that they support /// double-subscript (i.e., `m[j][i]`) giving the same type as the /// elements of this matrix, and their total size appears to be the /// right number of matrix elements. /// /// This functionality is disabled for gcc 4.x, which seems to have a /// compiler bug that results in spurious errors. It can also be /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to /// including any Imath header files. /// template<typename M, IMATH_ENABLE_IF(has_double_subscript<M,T,2,2>::value)> IMATH_HOSTDEVICE explicit Matrix22 (const M& m) : Matrix22(T(m[0][0]), T(m[0][1]), T(m[1][0]), T(m[1][1])) { } template<typename M, IMATH_ENABLE_IF(has_double_subscript<M,T,2,2>::value)> IMATH_HOSTDEVICE const Matrix22& operator= (const M& m) { *this = Matrix22(T(m[0][0]), T(m[0][1]), T(m[1][0]), T(m[1][1])); return *this; } /// @} #endif /// @{ /// @name Compatibility with Sb /// Return a raw pointer to the array of values IMATH_HOSTDEVICE T* getValue() IMATH_NOEXCEPT; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE const T* getValue() const IMATH_NOEXCEPT; /// Return the value in `v` template <class S> IMATH_HOSTDEVICE void getValue (Matrix22<S>& v) const IMATH_NOEXCEPT; /// Set the value template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22& setValue (const Matrix22<S>& v) IMATH_NOEXCEPT; /// Set the value template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22& setTheMatrix (const Matrix22<S>& v) IMATH_NOEXCEPT; /// @} /// @{ /// @name Arithmetic and Comparison /// Equality IMATH_HOSTDEVICE constexpr bool operator== (const Matrix22& v) const IMATH_NOEXCEPT; /// Inequality IMATH_HOSTDEVICE constexpr bool operator!= (const Matrix22& v) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and `m` are the same /// with an absolute error of no more than e, i.e., for all i, j: /// /// abs (this[i][j] - m[i][j]) <= e IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Matrix22<T>& v, T e) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and m are the same with /// a relative error of no more than e, i.e., for all i, j: /// /// abs (this[i] - v[i][j]) <= e * abs (this[i][j]) IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithRelError (const Matrix22<T>& v, T e) const IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator+= (const Matrix22& v) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator+= (T a) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE constexpr Matrix22 operator+ (const Matrix22& v) const IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator-= (const Matrix22& v) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator-= (T a) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE constexpr Matrix22 operator- (const Matrix22& v) const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE constexpr Matrix22 operator-() const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& negate() IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator*= (T a) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Matrix22 operator* (T a) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator/= (T a) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Matrix22 operator/ (T a) const IMATH_NOEXCEPT; /// Matrix-matrix multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& operator*= (const Matrix22& v) IMATH_NOEXCEPT; /// Matrix-matrix multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22 operator* (const Matrix22& v) const IMATH_NOEXCEPT; /// Vector * matrix multiplication /// @param[in] src Input vector /// @param[out] dst transformed vector template <class S> IMATH_HOSTDEVICE void multDirMatrix (const Vec2<S>& src, Vec2<S>& dst) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Maniplation /// Set to the identity IMATH_HOSTDEVICE void makeIdentity() IMATH_NOEXCEPT; /// Transpose IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& transpose() IMATH_NOEXCEPT; /// Return the transpose IMATH_HOSTDEVICE constexpr Matrix22 transposed() const IMATH_NOEXCEPT; /// Invert in place /// @param singExc If true, throw an exception if the matrix cannot be inverted. /// @return const reference to this IMATH_CONSTEXPR14 const Matrix22& invert (bool singExc); /// Invert in place /// @return const reference to this IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& invert() IMATH_NOEXCEPT; /// Return the inverse, leaving this unmodified. /// @param singExc If true, throw an exception if the matrix cannot be inverted. IMATH_CONSTEXPR14 Matrix22<T> inverse (bool singExc) const; /// Return the inverse, leaving this unmodified. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix22<T> inverse() const IMATH_NOEXCEPT; /// Determinant IMATH_HOSTDEVICE constexpr T determinant() const IMATH_NOEXCEPT; /// Set matrix to rotation by r (in radians) /// @return const referenced to this template <class S> IMATH_HOSTDEVICE const Matrix22& setRotation (S r) IMATH_NOEXCEPT; /// Rotate the given matrix by r (in radians) /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& rotate (S r) IMATH_NOEXCEPT; /// Set matrix to scale by given uniform factor /// @return const referenced to this IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& setScale (T s) IMATH_NOEXCEPT; /// Set matrix to scale by given vector /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& setScale (const Vec2<S>& s) IMATH_NOEXCEPT; // Scale the matrix by s /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix22& scale (const Vec2<S>& s) IMATH_NOEXCEPT; /// @} /// @{ /// @name Numeric Limits /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits<T>::lowest(); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits<T>::max(); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits<T>::min(); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits<T>::epsilon(); } /// @} /// Return the number of the row and column dimensions, i.e. 2. IMATH_HOSTDEVICE constexpr static unsigned int dimensions() IMATH_NOEXCEPT { return 2; } /// The base type: In templates that accept a parameter `V`, you /// can refer to `T` as `V::BaseType` typedef T BaseType; /// The base vector type typedef Vec2<T> BaseVecType; }; /// /// 3x3 transformation matrix /// template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Matrix33 { public: /// @{ /// @name Direct access to elements /// Matrix elements T x[3][3]; /// @} /// Row access IMATH_HOSTDEVICE T* operator[] (int i) IMATH_NOEXCEPT; /// Row access IMATH_HOSTDEVICE const T* operator[] (int i) const IMATH_NOEXCEPT; /// @{ /// @name Constructors and Assignment /// Uninitialized IMATH_HOSTDEVICE Matrix33 (Uninitialized) IMATH_NOEXCEPT {} /// Default constructor: initialize to identity /// 1 0 0 /// 0 1 0 /// 0 0 1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33() IMATH_NOEXCEPT; /// Initialize to scalar constant /// a a a /// a a a /// a a a IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33 (T a) IMATH_NOEXCEPT; /// Construct from 3x3 array /// a[0][0] a[0][1] a[0][2] /// a[1][0] a[1][1] a[1][2] /// a[2][0] a[2][1] a[2][2] IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33 (const T a[3][3]) IMATH_NOEXCEPT; /// Construct from given scalar values /// a b c /// d e f /// g h i IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33 (T a, T b, T c, T d, T e, T f, T g, T h, T i) IMATH_NOEXCEPT; /// Copy constructor IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33 (const Matrix33& v) IMATH_NOEXCEPT; /// Construct from Matrix33 of another base type template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 explicit Matrix33 (const Matrix33<S>& v) IMATH_NOEXCEPT; /// Assignment operator IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator= (const Matrix33& v) IMATH_NOEXCEPT; /// Assignment from scalar IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator= (T a) IMATH_NOEXCEPT; /// Destructor ~Matrix33() IMATH_NOEXCEPT = default; /// @} #if IMATH_FOREIGN_VECTOR_INTEROP /// @{ /// @name Interoperability with other matrix types /// /// Construction and assignment are allowed from other classes that /// appear to be equivalent matrix types, provided that they support /// double-subscript (i.e., `m[j][i]`) giving the same type as the /// elements of this matrix, and their total size appears to be the /// right number of matrix elements. /// /// This functionality is disabled for gcc 4.x, which seems to have a /// compiler bug that results in spurious errors. It can also be /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to /// including any Imath header files. /// template<typename M, IMATH_ENABLE_IF(has_double_subscript<M,T,3,3>::value)> IMATH_HOSTDEVICE explicit Matrix33 (const M& m) : Matrix33(T(m[0][0]), T(m[0][1]), T(m[0][2]), T(m[1][0]), T(m[1][1]), T(m[1][2]), T(m[2][0]), T(m[2][1]), T(m[2][2])) { } /// Interoperability assignment from another type that behaves as if it /// were an equivalent matrix. template<typename M, IMATH_ENABLE_IF(has_double_subscript<M,T,3,3>::value)> IMATH_HOSTDEVICE const Matrix33& operator= (const M& m) { *this = Matrix33(T(m[0][0]), T(m[0][1]), T(m[0][2]), T(m[1][0]), T(m[1][1]), T(m[1][2]), T(m[2][0]), T(m[2][1]), T(m[2][2])); return *this; } /// @} #endif /// @{ /// @name Compatibility with Sb /// Return a raw pointer to the array of values IMATH_HOSTDEVICE T* getValue() IMATH_NOEXCEPT; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE const T* getValue() const IMATH_NOEXCEPT; /// Return the value in `v` template <class S> IMATH_HOSTDEVICE void getValue (Matrix33<S>& v) const IMATH_NOEXCEPT; /// Set the value template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33& setValue (const Matrix33<S>& v) IMATH_NOEXCEPT; /// Set the value template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33& setTheMatrix (const Matrix33<S>& v) IMATH_NOEXCEPT; /// @} /// @{ /// @name Arithmetic and Comparison /// Equality IMATH_HOSTDEVICE constexpr bool operator== (const Matrix33& v) const IMATH_NOEXCEPT; /// Inequality IMATH_HOSTDEVICE constexpr bool operator!= (const Matrix33& v) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and `m` are the same /// with an absolute error of no more than e, i.e., for all i, j: /// /// abs (this[i][j] - m[i][j]) <= e IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Matrix33<T>& v, T e) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and m are the same with /// a relative error of no more than e, i.e., for all i, j: /// /// abs (this[i] - v[i][j]) <= e * abs (this[i][j]) IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithRelError (const Matrix33<T>& v, T e) const IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator+= (const Matrix33& v) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator+= (T a) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE constexpr Matrix33 operator+ (const Matrix33& v) const IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator-= (const Matrix33& v) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator-= (T a) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE constexpr Matrix33 operator- (const Matrix33& v) const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE constexpr Matrix33 operator-() const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& negate() IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator*= (T a) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Matrix33 operator* (T a) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator/= (T a) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Matrix33 operator/ (T a) const IMATH_NOEXCEPT; /// Matrix-matrix multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& operator*= (const Matrix33& v) IMATH_NOEXCEPT; /// Matrix-matrix multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33 operator* (const Matrix33& v) const IMATH_NOEXCEPT; /// Vector-matrix multiplication: a homogeneous transformation /// by computing Vec3 (src.x, src.y, 1) * m and dividing by the /// result's third element. /// @param[in] src The input vector /// @param[out] dst The output vector template <class S> IMATH_HOSTDEVICE void multVecMatrix (const Vec2<S>& src, Vec2<S>& dst) const IMATH_NOEXCEPT; /// Vector-matrix multiplication: multiply `src` by the upper left 2x2 /// submatrix, ignoring the rest of matrix. /// @param[in] src The input vector /// @param[out] dst The output vector template <class S> IMATH_HOSTDEVICE void multDirMatrix (const Vec2<S>& src, Vec2<S>& dst) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Maniplation /// Set to the identity matrix IMATH_HOSTDEVICE void makeIdentity() IMATH_NOEXCEPT; /// Transpose IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& transpose() IMATH_NOEXCEPT; /// Return the transpose IMATH_HOSTDEVICE constexpr Matrix33 transposed() const IMATH_NOEXCEPT; /// Invert in place using the determinant. /// @param singExc If true, throw an exception if the matrix cannot be inverted. /// @return const reference to this IMATH_CONSTEXPR14 const Matrix33& invert (bool singExc); /// Invert in place using the determinant. /// @return const reference to this IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& invert() IMATH_NOEXCEPT; /// Return the inverse using the determinant, leaving this unmodified. /// @param singExc If true, throw an exception if the matrix cannot be inverted. IMATH_CONSTEXPR14 Matrix33<T> inverse (bool singExc) const; /// Return the inverse using the determinant, leaving this unmodified. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix33<T> inverse() const IMATH_NOEXCEPT; /// Invert in place using the Gauss-Jordan method. Significantly slower /// but more accurate than invert(). /// @param singExc If true, throw an exception if the matrix cannot be inverted. /// @return const reference to this const Matrix33& gjInvert (bool singExc); /// Invert in place using the Gauss-Jordan method. Significantly slower /// but more accurate than invert(). /// @return const reference to this IMATH_HOSTDEVICE const Matrix33& gjInvert() IMATH_NOEXCEPT; /// Return the inverse using the Gauss-Jordan method, leaving this /// unmodified. Significantly slower but more accurate than inverse(). Matrix33<T> gjInverse (bool singExc) const; /// Return the inverse using the Gauss-Jordan method. Significantly slower, /// leaving this unmodified. Slower but more accurate than inverse(). IMATH_HOSTDEVICE Matrix33<T> gjInverse() const IMATH_NOEXCEPT; /// Calculate the matrix minor of the (r,c) element IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T minorOf (const int r, const int c) const IMATH_NOEXCEPT; /// Build a minor using the specified rows and columns IMATH_HOSTDEVICE constexpr T fastMinor (const int r0, const int r1, const int c0, const int c1) const IMATH_NOEXCEPT; /// Determinant IMATH_HOSTDEVICE constexpr T determinant() const IMATH_NOEXCEPT; /// Set matrix to rotation by r (in radians) /// @return const referenced to this template <class S> IMATH_HOSTDEVICE const Matrix33& setRotation (S r) IMATH_NOEXCEPT; // Rotate the given matrix by r (in radians) /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& rotate (S r) IMATH_NOEXCEPT; /// Set matrix to scale by given uniform factor /// @return const referenced to this IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& setScale (T s) IMATH_NOEXCEPT; /// Set matrix to scale by given vector /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& setScale (const Vec2<S>& s) IMATH_NOEXCEPT; /// Scale the matrix by s /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& scale (const Vec2<S>& s) IMATH_NOEXCEPT; /// Set matrix to translation by given vector /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& setTranslation (const Vec2<S>& t) IMATH_NOEXCEPT; /// Return the translation component IMATH_HOSTDEVICE constexpr Vec2<T> translation() const IMATH_NOEXCEPT; /// Translate the matrix by t /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& translate (const Vec2<S>& t) IMATH_NOEXCEPT; /// Set matrix to shear x for each y coord. by given factor xy /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& setShear (const S& h) IMATH_NOEXCEPT; /// Set matrix to shear x for each y coord. by given factor h[0] /// and to shear y for each x coord. by given factor h[1] /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& setShear (const Vec2<S>& h) IMATH_NOEXCEPT; /// Shear the matrix in x for each y coord. by given factor xy /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& shear (const S& xy) IMATH_NOEXCEPT; /// Shear the matrix in x for each y coord. by given factor xy /// and shear y for each x coord. by given factor yx /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix33& shear (const Vec2<S>& h) IMATH_NOEXCEPT; /// @} /// @{ /// @name Numeric Limits /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits<T>::lowest(); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits<T>::max(); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits<T>::min(); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits<T>::epsilon(); } /// @} /// Return the number of the row and column dimensions, i.e. 3. IMATH_HOSTDEVICE constexpr static unsigned int dimensions() IMATH_NOEXCEPT { return 3; } /// The base type: In templates that accept a parameter `V` (could be a Color4), you can refer to `T` as `V::BaseType` typedef T BaseType; /// The base vector type typedef Vec3<T> BaseVecType; }; /// /// 4x4 transformation matrix /// template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Matrix44 { public: /// @{ /// @name Direct access to elements /// Matrix elements T x[4][4]; /// @} /// Row access IMATH_HOSTDEVICE T* operator[] (int i) IMATH_NOEXCEPT; /// Row access IMATH_HOSTDEVICE const T* operator[] (int i) const IMATH_NOEXCEPT; /// @{ /// @name Constructors and Assignment /// Uninitialized IMATH_HOSTDEVICE constexpr Matrix44 (Uninitialized) IMATH_NOEXCEPT {} /// Default constructor: initialize to identity /// 1 0 0 0 /// 0 1 0 0 /// 0 0 1 0 /// 0 0 0 1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44() IMATH_NOEXCEPT; /// Initialize to scalar constant /// a a a a /// a a a a /// a a a a /// a a a a IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44 (T a) IMATH_NOEXCEPT; /// Construct from 4x4 array /// a[0][0] a[0][1] a[0][2] a[0][3] /// a[1][0] a[1][1] a[1][2] a[1][3] /// a[2][0] a[2][1] a[2][2] a[2][3] /// a[3][0] a[3][1] a[3][2] a[3][3] IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44 (const T a[4][4]) IMATH_NOEXCEPT; /// Construct from given scalar values /// a b c d /// e f g h /// i j k l /// m n o p IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44 (T a, T b, T c, T d, T e, T f, T g, T h, T i, T j, T k, T l, T m, T n, T o, T p) IMATH_NOEXCEPT; /// Construct from a 3x3 rotation matrix and a translation vector /// r r r 0 /// r r r 0 /// r r r 0 /// t t t 1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44 (Matrix33<T> r, Vec3<T> t) IMATH_NOEXCEPT; /// Copy constructor IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44 (const Matrix44& v) IMATH_NOEXCEPT; /// Construct from Matrix44 of another base type template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 explicit Matrix44 (const Matrix44<S>& v) IMATH_NOEXCEPT; /// Assignment operator IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator= (const Matrix44& v) IMATH_NOEXCEPT; /// Assignment from scalar IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator= (T a) IMATH_NOEXCEPT; /// Destructor ~Matrix44() IMATH_NOEXCEPT = default; /// @} #if IMATH_FOREIGN_VECTOR_INTEROP /// @{ /// @name Interoperability with other matrix types /// /// Construction and assignment are allowed from other classes that /// appear to be equivalent matrix types, provided that they support /// double-subscript (i.e., `m[j][i]`) giving the same type as the /// elements of this matrix, and their total size appears to be the /// right number of matrix elements. /// /// This functionality is disabled for gcc 4.x, which seems to have a /// compiler bug that results in spurious errors. It can also be /// disabled by defining IMATH_FOREIGN_VECTOR_INTEROP to be 0 prior to /// including any Imath header files. /// template<typename M, IMATH_ENABLE_IF(has_double_subscript<M,T,4,4>::value)> IMATH_HOSTDEVICE explicit Matrix44 (const M& m) : Matrix44(T(m[0][0]), T(m[0][1]), T(m[0][2]), T(m[0][3]), T(m[1][0]), T(m[1][1]), T(m[1][2]), T(m[1][3]), T(m[2][0]), T(m[2][1]), T(m[2][2]), T(m[2][3]), T(m[3][0]), T(m[3][1]), T(m[3][2]), T(m[3][3])) { } /// Interoperability assignment from another type that behaves as if it /// were an equivalent matrix. template<typename M, IMATH_ENABLE_IF(has_double_subscript<M,T,4,4>::value)> IMATH_HOSTDEVICE const Matrix44& operator= (const M& m) { *this = Matrix44(T(m[0][0]), T(m[0][1]), T(m[0][2]), T(m[0][3]), T(m[1][0]), T(m[1][1]), T(m[1][2]), T(m[1][3]), T(m[2][0]), T(m[2][1]), T(m[2][2]), T(m[2][3]), T(m[3][0]), T(m[3][1]), T(m[3][2]), T(m[3][3])); return *this; } /// @} #endif /// @{ /// @name Compatibility with Sb /// Return a raw pointer to the array of values IMATH_HOSTDEVICE T* getValue() IMATH_NOEXCEPT; /// Return a raw pointer to the array of values IMATH_HOSTDEVICE const T* getValue() const IMATH_NOEXCEPT; /// Return the value in `v` template <class S> IMATH_HOSTDEVICE void getValue (Matrix44<S>& v) const IMATH_NOEXCEPT; /// Set the value template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44& setValue (const Matrix44<S>& v) IMATH_NOEXCEPT; /// Set the value template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44& setTheMatrix (const Matrix44<S>& v) IMATH_NOEXCEPT; /// @} /// @{ /// @name Arithmetic and Comparison /// Equality IMATH_HOSTDEVICE constexpr bool operator== (const Matrix44& v) const IMATH_NOEXCEPT; /// Inequality IMATH_HOSTDEVICE constexpr bool operator!= (const Matrix44& v) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and `m` are the same /// with an absolute error of no more than e, i.e., for all i, j: /// /// abs (this[i][j] - m[i][j]) <= e IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithAbsError (const Matrix44<T>& v, T e) const IMATH_NOEXCEPT; /// Compare two matrices and test if they are "approximately equal": /// @return True if the coefficients of this and m are the same with /// a relative error of no more than e, i.e., for all i, j: /// /// abs (this[i] - v[i][j]) <= e * abs (this[i][j]) IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool equalWithRelError (const Matrix44<T>& v, T e) const IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator+= (const Matrix44& v) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator+= (T a) IMATH_NOEXCEPT; /// Component-wise addition IMATH_HOSTDEVICE constexpr Matrix44 operator+ (const Matrix44& v) const IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator-= (const Matrix44& v) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator-= (T a) IMATH_NOEXCEPT; /// Component-wise subtraction IMATH_HOSTDEVICE constexpr Matrix44 operator- (const Matrix44& v) const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE constexpr Matrix44 operator-() const IMATH_NOEXCEPT; /// Component-wise multiplication by -1 IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& negate() IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator*= (T a) IMATH_NOEXCEPT; /// Component-wise multiplication IMATH_HOSTDEVICE constexpr Matrix44 operator* (T a) const IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator/= (T a) IMATH_NOEXCEPT; /// Component-wise division IMATH_HOSTDEVICE constexpr Matrix44 operator/ (T a) const IMATH_NOEXCEPT; /// Matrix-matrix multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& operator*= (const Matrix44& v) IMATH_NOEXCEPT; /// Matrix-matrix multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44 operator* (const Matrix44& v) const IMATH_NOEXCEPT; /// Matrix-matrix multiplication: compute c = a * b IMATH_HOSTDEVICE static void multiply (const Matrix44& a, // assumes that const Matrix44& b, // &a != &c and Matrix44& c) IMATH_NOEXCEPT; // &b != &c. /// Matrix-matrix multiplication returning a result. IMATH_HOSTDEVICE static IMATH_CONSTEXPR14 Matrix44 multiply (const Matrix44& a, const Matrix44& b) noexcept; /// Vector-matrix multiplication: a homogeneous transformation /// by computing Vec3 (src.x, src.y, src.z, 1) * m and dividing by the /// result's third element. /// @param[in] src The input vector /// @param[out] dst The output vector template <class S> IMATH_HOSTDEVICE void multVecMatrix (const Vec3<S>& src, Vec3<S>& dst) const IMATH_NOEXCEPT; /// Vector-matrix multiplication: multiply `src` by the upper left 2x2 /// submatrix, ignoring the rest of matrix. /// @param[in] src The input vector /// @param[out] dst The output vector template <class S> IMATH_HOSTDEVICE void multDirMatrix (const Vec3<S>& src, Vec3<S>& dst) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Maniplation /// Set to the identity matrix IMATH_HOSTDEVICE void makeIdentity() IMATH_NOEXCEPT; /// Transpose IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& transpose() IMATH_NOEXCEPT; /// Return the transpose IMATH_HOSTDEVICE constexpr Matrix44 transposed() const IMATH_NOEXCEPT; /// Invert in place using the determinant. /// @param singExc If true, throw an exception if the matrix cannot be inverted. /// @return const reference to this IMATH_CONSTEXPR14 const Matrix44& invert (bool singExc); /// Invert in place using the determinant. /// @return const reference to this IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& invert() IMATH_NOEXCEPT; /// Return the inverse using the determinant, leaving this unmodified. /// @param singExc If true, throw an exception if the matrix cannot be inverted. IMATH_CONSTEXPR14 Matrix44<T> inverse (bool singExc) const; /// Return the inverse using the determinant, leaving this unmodified. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Matrix44<T> inverse() const IMATH_NOEXCEPT; /// Invert in place using the Gauss-Jordan method. Significantly slower /// but more accurate than invert(). /// @param singExc If true, throw an exception if the matrix cannot be inverted. /// @return const reference to this IMATH_CONSTEXPR14 const Matrix44& gjInvert (bool singExc); /// Invert in place using the Gauss-Jordan method. Significantly slower /// but more accurate than invert(). /// @return const reference to this IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& gjInvert() IMATH_NOEXCEPT; /// Return the inverse using the Gauss-Jordan method, leaving this /// unmodified. Significantly slower but more accurate than inverse(). Matrix44<T> gjInverse (bool singExc) const; /// Return the inverse using the Gauss-Jordan method, leaving this /// unmodified Significantly slower but more accurate than inverse(). IMATH_HOSTDEVICE Matrix44<T> gjInverse() const IMATH_NOEXCEPT; /// Calculate the matrix minor of the (r,c) element IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T minorOf (const int r, const int c) const IMATH_NOEXCEPT; /// Build a minor using the specified rows and columns IMATH_HOSTDEVICE constexpr T fastMinor (const int r0, const int r1, const int r2, const int c0, const int c1, const int c2) const IMATH_NOEXCEPT; /// Determinant IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T determinant() const IMATH_NOEXCEPT; /// Set matrix to rotation by XYZ euler angles (in radians) /// @return const referenced to this template <class S> IMATH_HOSTDEVICE const Matrix44& setEulerAngles (const Vec3<S>& r) IMATH_NOEXCEPT; /// Set matrix to rotation around given axis by given angle (in radians) /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& setAxisAngle (const Vec3<S>& ax, S ang) IMATH_NOEXCEPT; /// Rotate the matrix by XYZ euler angles in r (in radians) /// @return const referenced to this template <class S> IMATH_HOSTDEVICE const Matrix44& rotate (const Vec3<S>& r) IMATH_NOEXCEPT; /// Set matrix to scale by given uniform factor /// @return const referenced to this IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& setScale (T s) IMATH_NOEXCEPT; /// Set matrix to scale by given vector /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& setScale (const Vec3<S>& s) IMATH_NOEXCEPT; /// Scale the matrix by s /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& scale (const Vec3<S>& s) IMATH_NOEXCEPT; /// Set matrix to translation by given vector /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& setTranslation (const Vec3<S>& t) IMATH_NOEXCEPT; /// Return translation component IMATH_HOSTDEVICE constexpr const Vec3<T> translation() const IMATH_NOEXCEPT; /// Translate the matrix by t /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& translate (const Vec3<S>& t) IMATH_NOEXCEPT; /// Set matrix to shear by given vector h. The resulting matrix /// - will shear x for each y coord. by a factor of h[0] ; /// - will shear x for each z coord. by a factor of h[1] ; /// - will shear y for each z coord. by a factor of h[2] . /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& setShear (const Vec3<S>& h) IMATH_NOEXCEPT; /// Set matrix to shear by given factors. The resulting matrix /// - will shear x for each y coord. by a factor of h.xy ; /// - will shear x for each z coord. by a factor of h.xz ; /// - will shear y for each z coord. by a factor of h.yz ; /// - will shear y for each x coord. by a factor of h.yx ; /// - will shear z for each x coord. by a factor of h.zx ; /// - will shear z for each y coord. by a factor of h.zy . /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& setShear (const Shear6<S>& h) IMATH_NOEXCEPT; /// Shear the matrix by given vector. The composed matrix /// will be `shear` * `this`, where the shear matrix ... /// - will shear x for each y coord. by a factor of h[0] ; /// - will shear x for each z coord. by a factor of h[1] ; /// - will shear y for each z coord. by a factor of h[2] . /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& shear (const Vec3<S>& h) IMATH_NOEXCEPT; /// Shear the matrix by the given factors. The composed matrix /// will be `shear` * `this`, where the shear matrix ... /// - will shear x for each y coord. by a factor of h.xy ; /// - will shear x for each z coord. by a factor of h.xz ; /// - will shear y for each z coord. by a factor of h.yz ; /// - will shear y for each x coord. by a factor of h.yx ; /// - will shear z for each x coord. by a factor of h.zx ; /// - will shear z for each y coord. by a factor of h.zy . /// @return const referenced to this template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Matrix44& shear (const Shear6<S>& h) IMATH_NOEXCEPT; /// @} /// @{ /// @name Numeric Limits /// Largest possible negative value IMATH_HOSTDEVICE constexpr static T baseTypeLowest() IMATH_NOEXCEPT { return std::numeric_limits<T>::lowest(); } /// Largest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeMax() IMATH_NOEXCEPT { return std::numeric_limits<T>::max(); } /// Smallest possible positive value IMATH_HOSTDEVICE constexpr static T baseTypeSmallest() IMATH_NOEXCEPT { return std::numeric_limits<T>::min(); } /// Smallest possible e for which 1+e != 1 IMATH_HOSTDEVICE constexpr static T baseTypeEpsilon() IMATH_NOEXCEPT { return std::numeric_limits<T>::epsilon(); } /// @} /// Return the number of the row and column dimensions, i.e. 4 IMATH_HOSTDEVICE constexpr static unsigned int dimensions() IMATH_NOEXCEPT { return 4; } /// The base type: In templates that accept a parameter `V` (could be a Color4), you can refer to `T` as `V::BaseType` typedef T BaseType; /// The base vector type typedef Vec4<T> BaseVecType; }; /// Stream output, as: /// (m00 m01 /// m10 m11) template <class T> std::ostream& operator<< (std::ostream& s, const Matrix22<T>& m); /// Stream output, as: /// (m00 m01 m02 /// m10 m11 m12 /// m20 m21 m22) template <class T> std::ostream& operator<< (std::ostream& s, const Matrix33<T>& m); /// Stream output, as: /// /// (m00 m01 m02 m03 /// m10 m11 m12 m13 /// m20 m21 m22 m23 /// m30 m31 m32 m33) template <class T> std::ostream& operator<< (std::ostream& s, const Matrix44<T>& m); //--------------------------------------------- // Vector-times-matrix multiplication operators //--------------------------------------------- /// Vector-matrix multiplication: v *= m template <class S, class T> IMATH_HOSTDEVICE inline const Vec2<S>& operator*= (Vec2<S>& v, const Matrix22<T>& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: r = v * m template <class S, class T> IMATH_HOSTDEVICE inline Vec2<S> operator* (const Vec2<S>& v, const Matrix22<T>& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: v *= m template <class S, class T> IMATH_HOSTDEVICE inline const Vec2<S>& operator*= (Vec2<S>& v, const Matrix33<T>& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: r = v * m template <class S, class T> IMATH_HOSTDEVICE inline Vec2<S> operator* (const Vec2<S>& v, const Matrix33<T>& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: v *= m template <class S, class T> IMATH_HOSTDEVICE inline const Vec3<S>& operator*= (Vec3<S>& v, const Matrix33<T>& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: r = v * m template <class S, class T> IMATH_HOSTDEVICE inline Vec3<S> operator* (const Vec3<S>& v, const Matrix33<T>& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: v *= m template <class S, class T> IMATH_HOSTDEVICE inline const Vec3<S>& operator*= (Vec3<S>& v, const Matrix44<T>& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: r = v * m template <class S, class T> IMATH_HOSTDEVICE inline Vec3<S> operator* (const Vec3<S>& v, const Matrix44<T>& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: v *= m template <class S, class T> IMATH_HOSTDEVICE inline const Vec4<S>& operator*= (Vec4<S>& v, const Matrix44<T>& m) IMATH_NOEXCEPT; /// Vector-matrix multiplication: r = v * m template <class S, class T> IMATH_HOSTDEVICE inline Vec4<S> operator* (const Vec4<S>& v, const Matrix44<T>& m) IMATH_NOEXCEPT; //------------------------- // Typedefs for convenience //------------------------- /// 2x2 matrix of float typedef Matrix22<float> M22f; /// 2x2 matrix of double typedef Matrix22<double> M22d; /// 3x3 matrix of float typedef Matrix33<float> M33f; /// 3x3 matrix of double typedef Matrix33<double> M33d; /// 4x4 matrix of float typedef Matrix44<float> M44f; /// 4x4 matrix of double typedef Matrix44<double> M44d; //--------------------------- // Implementation of Matrix22 //--------------------------- template <class T> inline T* Matrix22<T>::operator[] (int i) IMATH_NOEXCEPT { return x[i]; } template <class T> inline const T* Matrix22<T>::operator[] (int i) const IMATH_NOEXCEPT { return x[i]; } template <class T> IMATH_CONSTEXPR14 inline Matrix22<T>::Matrix22() IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[1][0] = 0; x[1][1] = 1; } template <class T> IMATH_CONSTEXPR14 inline Matrix22<T>::Matrix22 (T a) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = a; x[1][0] = a; x[1][1] = a; } template <class T> IMATH_CONSTEXPR14 inline Matrix22<T>::Matrix22 (const T a[2][2]) IMATH_NOEXCEPT { // Function calls and aliasing issues can inhibit vectorization versus // straight assignment of data members, so instead of this: // memcpy (x, a, sizeof (x)); // we do this: x[0][0] = a[0][0]; x[0][1] = a[0][1]; x[1][0] = a[1][0]; x[1][1] = a[1][1]; } template <class T> IMATH_CONSTEXPR14 inline Matrix22<T>::Matrix22 (T a, T b, T c, T d) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = b; x[1][0] = c; x[1][1] = d; } template <class T> IMATH_CONSTEXPR14 inline Matrix22<T>::Matrix22 (const Matrix22& v) IMATH_NOEXCEPT { // Function calls and aliasing issues can inhibit vectorization versus // straight assignment of data members, so we don't do this: // memcpy (x, v.x, sizeof (x)); // we do this: x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; } template <class T> template <class S> IMATH_CONSTEXPR14 inline Matrix22<T>::Matrix22 (const Matrix22<S>& v) IMATH_NOEXCEPT { x[0][0] = T (v.x[0][0]); x[0][1] = T (v.x[0][1]); x[1][0] = T (v.x[1][0]); x[1][1] = T (v.x[1][1]); } template <class T> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::operator= (const Matrix22& v) IMATH_NOEXCEPT { // Function calls and aliasing issues can inhibit vectorization versus // straight assignment of data members, so we don't do this: // memcpy (x, v.x, sizeof (x)); // we do this: x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::operator= (T a) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = a; x[1][0] = a; x[1][1] = a; return *this; } template <class T> inline T* Matrix22<T>::getValue() IMATH_NOEXCEPT { return (T*) &x[0][0]; } template <class T> inline const T* Matrix22<T>::getValue() const IMATH_NOEXCEPT { return (const T*) &x[0][0]; } template <class T> template <class S> inline void Matrix22<T>::getValue (Matrix22<S>& v) const IMATH_NOEXCEPT { v.x[0][0] = x[0][0]; v.x[0][1] = x[0][1]; v.x[1][0] = x[1][0]; v.x[1][1] = x[1][1]; } template <class T> template <class S> IMATH_CONSTEXPR14 inline Matrix22<T>& Matrix22<T>::setValue (const Matrix22<S>& v) IMATH_NOEXCEPT { x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline Matrix22<T>& Matrix22<T>::setTheMatrix (const Matrix22<S>& v) IMATH_NOEXCEPT { x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; return *this; } template <class T> inline void Matrix22<T>::makeIdentity() IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[1][0] = 0; x[1][1] = 1; } template <class T> constexpr inline bool Matrix22<T>::operator== (const Matrix22& v) const IMATH_NOEXCEPT { return x[0][0] == v.x[0][0] && x[0][1] == v.x[0][1] && x[1][0] == v.x[1][0] && x[1][1] == v.x[1][1]; } template <class T> constexpr inline bool Matrix22<T>::operator!= (const Matrix22& v) const IMATH_NOEXCEPT { return x[0][0] != v.x[0][0] || x[0][1] != v.x[0][1] || x[1][0] != v.x[1][0] || x[1][1] != v.x[1][1]; } template <class T> IMATH_CONSTEXPR14 inline bool Matrix22<T>::equalWithAbsError (const Matrix22<T>& m, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i][j], m[i][j], e)) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline bool Matrix22<T>::equalWithRelError (const Matrix22<T>& m, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i][j], m[i][j], e)) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::operator+= (const Matrix22<T>& v) IMATH_NOEXCEPT { x[0][0] += v.x[0][0]; x[0][1] += v.x[0][1]; x[1][0] += v.x[1][0]; x[1][1] += v.x[1][1]; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::operator+= (T a) IMATH_NOEXCEPT { x[0][0] += a; x[0][1] += a; x[1][0] += a; x[1][1] += a; return *this; } template <class T> constexpr inline Matrix22<T> Matrix22<T>::operator+ (const Matrix22<T>& v) const IMATH_NOEXCEPT { return Matrix22 (x[0][0] + v.x[0][0], x[0][1] + v.x[0][1], x[1][0] + v.x[1][0], x[1][1] + v.x[1][1]); } template <class T> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::operator-= (const Matrix22<T>& v) IMATH_NOEXCEPT { x[0][0] -= v.x[0][0]; x[0][1] -= v.x[0][1]; x[1][0] -= v.x[1][0]; x[1][1] -= v.x[1][1]; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::operator-= (T a) IMATH_NOEXCEPT { x[0][0] -= a; x[0][1] -= a; x[1][0] -= a; x[1][1] -= a; return *this; } template <class T> constexpr inline Matrix22<T> Matrix22<T>::operator- (const Matrix22<T>& v) const IMATH_NOEXCEPT { return Matrix22 (x[0][0] - v.x[0][0], x[0][1] - v.x[0][1], x[1][0] - v.x[1][0], x[1][1] - v.x[1][1]); } template <class T> constexpr inline Matrix22<T> Matrix22<T>::operator-() const IMATH_NOEXCEPT { return Matrix22 (-x[0][0], -x[0][1], -x[1][0], -x[1][1]); } template <class T> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::negate() IMATH_NOEXCEPT { x[0][0] = -x[0][0]; x[0][1] = -x[0][1]; x[1][0] = -x[1][0]; x[1][1] = -x[1][1]; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::operator*= (T a) IMATH_NOEXCEPT { x[0][0] *= a; x[0][1] *= a; x[1][0] *= a; x[1][1] *= a; return *this; } template <class T> constexpr inline Matrix22<T> Matrix22<T>::operator* (T a) const IMATH_NOEXCEPT { return Matrix22 (x[0][0] * a, x[0][1] * a, x[1][0] * a, x[1][1] * a); } /// Matrix-scalar multiplication template <class T> inline Matrix22<T> operator* (T a, const Matrix22<T>& v) IMATH_NOEXCEPT { return v * a; } template <class T> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::operator*= (const Matrix22<T>& v) IMATH_NOEXCEPT { Matrix22 tmp (T (0)); for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) for (int k = 0; k < 2; k++) tmp.x[i][j] += x[i][k] * v.x[k][j]; *this = tmp; return *this; } template <class T> IMATH_CONSTEXPR14 inline Matrix22<T> Matrix22<T>::operator* (const Matrix22<T>& v) const IMATH_NOEXCEPT { Matrix22 tmp (T (0)); for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) for (int k = 0; k < 2; k++) tmp.x[i][j] += x[i][k] * v.x[k][j]; return tmp; } template <class T> template <class S> inline void Matrix22<T>::multDirMatrix (const Vec2<S>& src, Vec2<S>& dst) const IMATH_NOEXCEPT { S a, b; a = src.x * x[0][0] + src.y * x[1][0]; b = src.x * x[0][1] + src.y * x[1][1]; dst.x = a; dst.y = b; } template <class T> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::operator/= (T a) IMATH_NOEXCEPT { x[0][0] /= a; x[0][1] /= a; x[1][0] /= a; x[1][1] /= a; return *this; } template <class T> constexpr inline Matrix22<T> Matrix22<T>::operator/ (T a) const IMATH_NOEXCEPT { return Matrix22 (x[0][0] / a, x[0][1] / a, x[1][0] / a, x[1][1] / a); } template <class T> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::transpose() IMATH_NOEXCEPT { Matrix22 tmp (x[0][0], x[1][0], x[0][1], x[1][1]); *this = tmp; return *this; } template <class T> constexpr inline Matrix22<T> Matrix22<T>::transposed() const IMATH_NOEXCEPT { return Matrix22 (x[0][0], x[1][0], x[0][1], x[1][1]); } template <class T> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::invert (bool singExc) { *this = inverse (singExc); return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::invert() IMATH_NOEXCEPT { *this = inverse(); return *this; } template <class T> IMATH_CONSTEXPR14 inline Matrix22<T> Matrix22<T>::inverse (bool singExc) const { Matrix22 s (x[1][1], -x[0][1], -x[1][0], x[0][0]); T r = x[0][0] * x[1][1] - x[1][0] * x[0][1]; if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { s[i][j] /= r; } } } else { T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / std::numeric_limits<T>::min(); for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { if (mr > IMATH_INTERNAL_NAMESPACE::abs (s[i][j])) { s[i][j] /= r; } else { if (singExc) throw std::invalid_argument ("Cannot invert " "singular matrix."); return Matrix22(); } } } } return s; } template <class T> IMATH_CONSTEXPR14 inline Matrix22<T> Matrix22<T>::inverse() const IMATH_NOEXCEPT { Matrix22 s (x[1][1], -x[0][1], -x[1][0], x[0][0]); T r = x[0][0] * x[1][1] - x[1][0] * x[0][1]; if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { s[i][j] /= r; } } } else { T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / std::numeric_limits<T>::min(); for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { if (mr > IMATH_INTERNAL_NAMESPACE::abs (s[i][j])) { s[i][j] /= r; } else { return Matrix22(); } } } } return s; } template <class T> constexpr inline T Matrix22<T>::determinant() const IMATH_NOEXCEPT { return x[0][0] * x[1][1] - x[1][0] * x[0][1]; } template <class T> template <class S> inline const Matrix22<T>& Matrix22<T>::setRotation (S r) IMATH_NOEXCEPT { S cos_r, sin_r; cos_r = cos ((T) r); sin_r = sin ((T) r); x[0][0] = cos_r; x[0][1] = sin_r; x[1][0] = -sin_r; x[1][1] = cos_r; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::rotate (S r) IMATH_NOEXCEPT { *this *= Matrix22<T>().setRotation (r); return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::setScale (T s) IMATH_NOEXCEPT { // // Set the matrix to: // | s 0 | // | 0 s | // x[0][0] = s; x[0][1] = static_cast<T> (0); x[1][0] = static_cast<T> (0); x[1][1] = s; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::setScale (const Vec2<S>& s) IMATH_NOEXCEPT { // // Set the matrix to: // | s.x 0 | // | 0 s.y | // x[0][0] = s.x; x[0][1] = static_cast<T> (0); x[1][0] = static_cast<T> (0); x[1][1] = s.y; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix22<T>& Matrix22<T>::scale (const Vec2<S>& s) IMATH_NOEXCEPT { x[0][0] *= s.x; x[0][1] *= s.x; x[1][0] *= s.y; x[1][1] *= s.y; return *this; } //--------------------------- // Implementation of Matrix33 //--------------------------- template <class T> inline T* Matrix33<T>::operator[] (int i) IMATH_NOEXCEPT { return x[i]; } template <class T> inline const T* Matrix33<T>::operator[] (int i) const IMATH_NOEXCEPT { return x[i]; } template <class T> inline IMATH_CONSTEXPR14 Matrix33<T>::Matrix33() IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[0][2] = 0; x[1][0] = 0; x[1][1] = 1; x[1][2] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; } template <class T> IMATH_CONSTEXPR14 inline Matrix33<T>::Matrix33 (T a) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = a; x[0][2] = a; x[1][0] = a; x[1][1] = a; x[1][2] = a; x[2][0] = a; x[2][1] = a; x[2][2] = a; } template <class T> IMATH_CONSTEXPR14 inline Matrix33<T>::Matrix33 (const T a[3][3]) IMATH_NOEXCEPT { // Function calls and aliasing issues can inhibit vectorization versus // straight assignment of data members, so instead of this: // memcpy (x, a, sizeof (x)); // we do this: x[0][0] = a[0][0]; x[0][1] = a[0][1]; x[0][2] = a[0][2]; x[1][0] = a[1][0]; x[1][1] = a[1][1]; x[1][2] = a[1][2]; x[2][0] = a[2][0]; x[2][1] = a[2][1]; x[2][2] = a[2][2]; } template <class T> IMATH_CONSTEXPR14 inline Matrix33<T>::Matrix33 (T a, T b, T c, T d, T e, T f, T g, T h, T i) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = b; x[0][2] = c; x[1][0] = d; x[1][1] = e; x[1][2] = f; x[2][0] = g; x[2][1] = h; x[2][2] = i; } template <class T> IMATH_CONSTEXPR14 inline Matrix33<T>::Matrix33 (const Matrix33& v) IMATH_NOEXCEPT { // Function calls and aliasing issues can inhibit vectorization versus // straight assignment of data members, so instead of this: // memcpy (x, v.x, sizeof (x)); // we do this: x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[0][2] = v.x[0][2]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; x[1][2] = v.x[1][2]; x[2][0] = v.x[2][0]; x[2][1] = v.x[2][1]; x[2][2] = v.x[2][2]; } template <class T> template <class S> IMATH_CONSTEXPR14 inline Matrix33<T>::Matrix33 (const Matrix33<S>& v) IMATH_NOEXCEPT { x[0][0] = T (v.x[0][0]); x[0][1] = T (v.x[0][1]); x[0][2] = T (v.x[0][2]); x[1][0] = T (v.x[1][0]); x[1][1] = T (v.x[1][1]); x[1][2] = T (v.x[1][2]); x[2][0] = T (v.x[2][0]); x[2][1] = T (v.x[2][1]); x[2][2] = T (v.x[2][2]); } template <class T> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::operator= (const Matrix33& v) IMATH_NOEXCEPT { // Function calls and aliasing issues can inhibit vectorization versus // straight assignment of data members, so instead of this: // memcpy (x, v.x, sizeof (x)); // we do this: x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[0][2] = v.x[0][2]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; x[1][2] = v.x[1][2]; x[2][0] = v.x[2][0]; x[2][1] = v.x[2][1]; x[2][2] = v.x[2][2]; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::operator= (T a) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = a; x[0][2] = a; x[1][0] = a; x[1][1] = a; x[1][2] = a; x[2][0] = a; x[2][1] = a; x[2][2] = a; return *this; } template <class T> inline T* Matrix33<T>::getValue() IMATH_NOEXCEPT { return (T*) &x[0][0]; } template <class T> inline const T* Matrix33<T>::getValue() const IMATH_NOEXCEPT { return (const T*) &x[0][0]; } template <class T> template <class S> inline void Matrix33<T>::getValue (Matrix33<S>& v) const IMATH_NOEXCEPT { v.x[0][0] = x[0][0]; v.x[0][1] = x[0][1]; v.x[0][2] = x[0][2]; v.x[1][0] = x[1][0]; v.x[1][1] = x[1][1]; v.x[1][2] = x[1][2]; v.x[2][0] = x[2][0]; v.x[2][1] = x[2][1]; v.x[2][2] = x[2][2]; } template <class T> template <class S> IMATH_CONSTEXPR14 inline Matrix33<T>& Matrix33<T>::setValue (const Matrix33<S>& v) IMATH_NOEXCEPT { x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[0][2] = v.x[0][2]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; x[1][2] = v.x[1][2]; x[2][0] = v.x[2][0]; x[2][1] = v.x[2][1]; x[2][2] = v.x[2][2]; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline Matrix33<T>& Matrix33<T>::setTheMatrix (const Matrix33<S>& v) IMATH_NOEXCEPT { x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[0][2] = v.x[0][2]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; x[1][2] = v.x[1][2]; x[2][0] = v.x[2][0]; x[2][1] = v.x[2][1]; x[2][2] = v.x[2][2]; return *this; } template <class T> inline void Matrix33<T>::makeIdentity() IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[0][2] = 0; x[1][0] = 0; x[1][1] = 1; x[1][2] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; } template <class T> constexpr inline bool Matrix33<T>::operator== (const Matrix33& v) const IMATH_NOEXCEPT { return x[0][0] == v.x[0][0] && x[0][1] == v.x[0][1] && x[0][2] == v.x[0][2] && x[1][0] == v.x[1][0] && x[1][1] == v.x[1][1] && x[1][2] == v.x[1][2] && x[2][0] == v.x[2][0] && x[2][1] == v.x[2][1] && x[2][2] == v.x[2][2]; } template <class T> constexpr inline bool Matrix33<T>::operator!= (const Matrix33& v) const IMATH_NOEXCEPT { return x[0][0] != v.x[0][0] || x[0][1] != v.x[0][1] || x[0][2] != v.x[0][2] || x[1][0] != v.x[1][0] || x[1][1] != v.x[1][1] || x[1][2] != v.x[1][2] || x[2][0] != v.x[2][0] || x[2][1] != v.x[2][1] || x[2][2] != v.x[2][2]; } template <class T> IMATH_CONSTEXPR14 inline bool Matrix33<T>::equalWithAbsError (const Matrix33<T>& m, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i][j], m[i][j], e)) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline bool Matrix33<T>::equalWithRelError (const Matrix33<T>& m, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i][j], m[i][j], e)) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::operator+= (const Matrix33<T>& v) IMATH_NOEXCEPT { x[0][0] += v.x[0][0]; x[0][1] += v.x[0][1]; x[0][2] += v.x[0][2]; x[1][0] += v.x[1][0]; x[1][1] += v.x[1][1]; x[1][2] += v.x[1][2]; x[2][0] += v.x[2][0]; x[2][1] += v.x[2][1]; x[2][2] += v.x[2][2]; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::operator+= (T a) IMATH_NOEXCEPT { x[0][0] += a; x[0][1] += a; x[0][2] += a; x[1][0] += a; x[1][1] += a; x[1][2] += a; x[2][0] += a; x[2][1] += a; x[2][2] += a; return *this; } template <class T> constexpr inline Matrix33<T> Matrix33<T>::operator+ (const Matrix33<T>& v) const IMATH_NOEXCEPT { return Matrix33 (x[0][0] + v.x[0][0], x[0][1] + v.x[0][1], x[0][2] + v.x[0][2], x[1][0] + v.x[1][0], x[1][1] + v.x[1][1], x[1][2] + v.x[1][2], x[2][0] + v.x[2][0], x[2][1] + v.x[2][1], x[2][2] + v.x[2][2]); } template <class T> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::operator-= (const Matrix33<T>& v) IMATH_NOEXCEPT { x[0][0] -= v.x[0][0]; x[0][1] -= v.x[0][1]; x[0][2] -= v.x[0][2]; x[1][0] -= v.x[1][0]; x[1][1] -= v.x[1][1]; x[1][2] -= v.x[1][2]; x[2][0] -= v.x[2][0]; x[2][1] -= v.x[2][1]; x[2][2] -= v.x[2][2]; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::operator-= (T a) IMATH_NOEXCEPT { x[0][0] -= a; x[0][1] -= a; x[0][2] -= a; x[1][0] -= a; x[1][1] -= a; x[1][2] -= a; x[2][0] -= a; x[2][1] -= a; x[2][2] -= a; return *this; } template <class T> constexpr inline Matrix33<T> Matrix33<T>::operator- (const Matrix33<T>& v) const IMATH_NOEXCEPT { return Matrix33 (x[0][0] - v.x[0][0], x[0][1] - v.x[0][1], x[0][2] - v.x[0][2], x[1][0] - v.x[1][0], x[1][1] - v.x[1][1], x[1][2] - v.x[1][2], x[2][0] - v.x[2][0], x[2][1] - v.x[2][1], x[2][2] - v.x[2][2]); } template <class T> constexpr inline Matrix33<T> Matrix33<T>::operator-() const IMATH_NOEXCEPT { return Matrix33 (-x[0][0], -x[0][1], -x[0][2], -x[1][0], -x[1][1], -x[1][2], -x[2][0], -x[2][1], -x[2][2]); } template <class T> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::negate() IMATH_NOEXCEPT { x[0][0] = -x[0][0]; x[0][1] = -x[0][1]; x[0][2] = -x[0][2]; x[1][0] = -x[1][0]; x[1][1] = -x[1][1]; x[1][2] = -x[1][2]; x[2][0] = -x[2][0]; x[2][1] = -x[2][1]; x[2][2] = -x[2][2]; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::operator*= (T a) IMATH_NOEXCEPT { x[0][0] *= a; x[0][1] *= a; x[0][2] *= a; x[1][0] *= a; x[1][1] *= a; x[1][2] *= a; x[2][0] *= a; x[2][1] *= a; x[2][2] *= a; return *this; } template <class T> constexpr inline Matrix33<T> Matrix33<T>::operator* (T a) const IMATH_NOEXCEPT { return Matrix33 (x[0][0] * a, x[0][1] * a, x[0][2] * a, x[1][0] * a, x[1][1] * a, x[1][2] * a, x[2][0] * a, x[2][1] * a, x[2][2] * a); } /// Matrix-scalar multiplication template <class T> inline Matrix33<T> constexpr operator* (T a, const Matrix33<T>& v) IMATH_NOEXCEPT { return v * a; } template <class T> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::operator*= (const Matrix33<T>& v) IMATH_NOEXCEPT { // Avoid initializing with 0 values before immediately overwriting them, // and unroll all loops for the best autovectorization. Matrix33 tmp(Imath::UNINITIALIZED); tmp.x[0][0] = x[0][0] * v.x[0][0] + x[0][1] * v.x[1][0] + x[0][2] * v.x[2][0]; tmp.x[0][1] = x[0][0] * v.x[0][1] + x[0][1] * v.x[1][1] + x[0][2] * v.x[2][1]; tmp.x[0][2] = x[0][0] * v.x[0][2] + x[0][1] * v.x[1][2] + x[0][2] * v.x[2][2]; tmp.x[1][0] = x[1][0] * v.x[0][0] + x[1][1] * v.x[1][0] + x[1][2] * v.x[2][0]; tmp.x[1][1] = x[1][0] * v.x[0][1] + x[1][1] * v.x[1][1] + x[1][2] * v.x[2][1]; tmp.x[1][2] = x[1][0] * v.x[0][2] + x[1][1] * v.x[1][2] + x[1][2] * v.x[2][2]; tmp.x[2][0] = x[2][0] * v.x[0][0] + x[2][1] * v.x[1][0] + x[2][2] * v.x[2][0]; tmp.x[2][1] = x[2][0] * v.x[0][1] + x[2][1] * v.x[1][1] + x[2][2] * v.x[2][1]; tmp.x[2][2] = x[2][0] * v.x[0][2] + x[2][1] * v.x[1][2] + x[2][2] * v.x[2][2]; *this = tmp; return *this; } template <class T> IMATH_CONSTEXPR14 inline Matrix33<T> Matrix33<T>::operator* (const Matrix33<T>& v) const IMATH_NOEXCEPT { // Avoid initializing with 0 values before immediately overwriting them, // and unroll all loops for the best autovectorization. Matrix33 tmp(Imath::UNINITIALIZED); tmp.x[0][0] = x[0][0] * v.x[0][0] + x[0][1] * v.x[1][0] + x[0][2] * v.x[2][0]; tmp.x[0][1] = x[0][0] * v.x[0][1] + x[0][1] * v.x[1][1] + x[0][2] * v.x[2][1]; tmp.x[0][2] = x[0][0] * v.x[0][2] + x[0][1] * v.x[1][2] + x[0][2] * v.x[2][2]; tmp.x[1][0] = x[1][0] * v.x[0][0] + x[1][1] * v.x[1][0] + x[1][2] * v.x[2][0]; tmp.x[1][1] = x[1][0] * v.x[0][1] + x[1][1] * v.x[1][1] + x[1][2] * v.x[2][1]; tmp.x[1][2] = x[1][0] * v.x[0][2] + x[1][1] * v.x[1][2] + x[1][2] * v.x[2][2]; tmp.x[2][0] = x[2][0] * v.x[0][0] + x[2][1] * v.x[1][0] + x[2][2] * v.x[2][0]; tmp.x[2][1] = x[2][0] * v.x[0][1] + x[2][1] * v.x[1][1] + x[2][2] * v.x[2][1]; tmp.x[2][2] = x[2][0] * v.x[0][2] + x[2][1] * v.x[1][2] + x[2][2] * v.x[2][2]; return tmp; } template <class T> template <class S> inline void Matrix33<T>::multVecMatrix (const Vec2<S>& src, Vec2<S>& dst) const IMATH_NOEXCEPT { S a, b, w; a = src.x * x[0][0] + src.y * x[1][0] + x[2][0]; b = src.x * x[0][1] + src.y * x[1][1] + x[2][1]; w = src.x * x[0][2] + src.y * x[1][2] + x[2][2]; dst.x = a / w; dst.y = b / w; } template <class T> template <class S> inline void Matrix33<T>::multDirMatrix (const Vec2<S>& src, Vec2<S>& dst) const IMATH_NOEXCEPT { S a, b; a = src.x * x[0][0] + src.y * x[1][0]; b = src.x * x[0][1] + src.y * x[1][1]; dst.x = a; dst.y = b; } template <class T> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::operator/= (T a) IMATH_NOEXCEPT { x[0][0] /= a; x[0][1] /= a; x[0][2] /= a; x[1][0] /= a; x[1][1] /= a; x[1][2] /= a; x[2][0] /= a; x[2][1] /= a; x[2][2] /= a; return *this; } template <class T> constexpr inline Matrix33<T> Matrix33<T>::operator/ (T a) const IMATH_NOEXCEPT { return Matrix33 (x[0][0] / a, x[0][1] / a, x[0][2] / a, x[1][0] / a, x[1][1] / a, x[1][2] / a, x[2][0] / a, x[2][1] / a, x[2][2] / a); } template <class T> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::transpose() IMATH_NOEXCEPT { Matrix33 tmp (x[0][0], x[1][0], x[2][0], x[0][1], x[1][1], x[2][1], x[0][2], x[1][2], x[2][2]); *this = tmp; return *this; } template <class T> constexpr inline Matrix33<T> Matrix33<T>::transposed() const IMATH_NOEXCEPT { return Matrix33 (x[0][0], x[1][0], x[2][0], x[0][1], x[1][1], x[2][1], x[0][2], x[1][2], x[2][2]); } template <class T> const inline Matrix33<T>& Matrix33<T>::gjInvert (bool singExc) { *this = gjInverse (singExc); return *this; } template <class T> const inline Matrix33<T>& Matrix33<T>::gjInvert() IMATH_NOEXCEPT { *this = gjInverse(); return *this; } template <class T> inline Matrix33<T> Matrix33<T>::gjInverse (bool singExc) const { int i, j, k; Matrix33 s; Matrix33 t (*this); // Forward elimination for (i = 0; i < 2; i++) { int pivot = i; T pivotsize = t[i][i]; if (pivotsize < 0) pivotsize = -pivotsize; for (j = i + 1; j < 3; j++) { T tmp = t[j][i]; if (tmp < 0) tmp = -tmp; if (tmp > pivotsize) { pivot = j; pivotsize = tmp; } } if (pivotsize == 0) { if (singExc) throw std::invalid_argument ("Cannot invert singular matrix."); return Matrix33(); } if (pivot != i) { for (j = 0; j < 3; j++) { T tmp; tmp = t[i][j]; t[i][j] = t[pivot][j]; t[pivot][j] = tmp; tmp = s[i][j]; s[i][j] = s[pivot][j]; s[pivot][j] = tmp; } } for (j = i + 1; j < 3; j++) { T f = t[j][i] / t[i][i]; for (k = 0; k < 3; k++) { t[j][k] -= f * t[i][k]; s[j][k] -= f * s[i][k]; } } } // Backward substitution for (i = 2; i >= 0; --i) { T f; if ((f = t[i][i]) == 0) { if (singExc) throw std::invalid_argument ("Cannot invert singular matrix."); return Matrix33(); } for (j = 0; j < 3; j++) { t[i][j] /= f; s[i][j] /= f; } for (j = 0; j < i; j++) { f = t[j][i]; for (k = 0; k < 3; k++) { t[j][k] -= f * t[i][k]; s[j][k] -= f * s[i][k]; } } } return s; } template <class T> inline Matrix33<T> Matrix33<T>::gjInverse() const IMATH_NOEXCEPT { int i, j, k; Matrix33 s; Matrix33 t (*this); // Forward elimination for (i = 0; i < 2; i++) { int pivot = i; T pivotsize = t[i][i]; if (pivotsize < 0) pivotsize = -pivotsize; for (j = i + 1; j < 3; j++) { T tmp = t[j][i]; if (tmp < 0) tmp = -tmp; if (tmp > pivotsize) { pivot = j; pivotsize = tmp; } } if (pivotsize == 0) { return Matrix33(); } if (pivot != i) { for (j = 0; j < 3; j++) { T tmp; tmp = t[i][j]; t[i][j] = t[pivot][j]; t[pivot][j] = tmp; tmp = s[i][j]; s[i][j] = s[pivot][j]; s[pivot][j] = tmp; } } for (j = i + 1; j < 3; j++) { T f = t[j][i] / t[i][i]; for (k = 0; k < 3; k++) { t[j][k] -= f * t[i][k]; s[j][k] -= f * s[i][k]; } } } // Backward substitution for (i = 2; i >= 0; --i) { T f; if ((f = t[i][i]) == 0) { return Matrix33(); } for (j = 0; j < 3; j++) { t[i][j] /= f; s[i][j] /= f; } for (j = 0; j < i; j++) { f = t[j][i]; for (k = 0; k < 3; k++) { t[j][k] -= f * t[i][k]; s[j][k] -= f * s[i][k]; } } } return s; } template <class T> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::invert (bool singExc) { *this = inverse (singExc); return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::invert() IMATH_NOEXCEPT { *this = inverse(); return *this; } template <class T> IMATH_CONSTEXPR14 inline Matrix33<T> Matrix33<T>::inverse (bool singExc) const { if (x[0][2] != 0 || x[1][2] != 0 || x[2][2] != 1) { Matrix33 s (x[1][1] * x[2][2] - x[2][1] * x[1][2], x[2][1] * x[0][2] - x[0][1] * x[2][2], x[0][1] * x[1][2] - x[1][1] * x[0][2], x[2][0] * x[1][2] - x[1][0] * x[2][2], x[0][0] * x[2][2] - x[2][0] * x[0][2], x[1][0] * x[0][2] - x[0][0] * x[1][2], x[1][0] * x[2][1] - x[2][0] * x[1][1], x[2][0] * x[0][1] - x[0][0] * x[2][1], x[0][0] * x[1][1] - x[1][0] * x[0][1]); T r = x[0][0] * s[0][0] + x[0][1] * s[1][0] + x[0][2] * s[2][0]; if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { s[i][j] /= r; } } } else { T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / std::numeric_limits<T>::min(); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { if (mr > IMATH_INTERNAL_NAMESPACE::abs (s[i][j])) { s[i][j] /= r; } else { if (singExc) throw std::invalid_argument ("Cannot invert " "singular matrix."); return Matrix33(); } } } } return s; } else { Matrix33 s (x[1][1], -x[0][1], 0, -x[1][0], x[0][0], 0, 0, 0, 1); T r = x[0][0] * x[1][1] - x[1][0] * x[0][1]; if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { s[i][j] /= r; } } } else { T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / std::numeric_limits<T>::min(); for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { if (mr > IMATH_INTERNAL_NAMESPACE::abs (s[i][j])) { s[i][j] /= r; } else { if (singExc) throw std::invalid_argument ("Cannot invert " "singular matrix."); return Matrix33(); } } } } s[2][0] = -x[2][0] * s[0][0] - x[2][1] * s[1][0]; s[2][1] = -x[2][0] * s[0][1] - x[2][1] * s[1][1]; return s; } } template <class T> IMATH_CONSTEXPR14 inline Matrix33<T> Matrix33<T>::inverse() const IMATH_NOEXCEPT { if (x[0][2] != 0 || x[1][2] != 0 || x[2][2] != 1) { Matrix33 s (x[1][1] * x[2][2] - x[2][1] * x[1][2], x[2][1] * x[0][2] - x[0][1] * x[2][2], x[0][1] * x[1][2] - x[1][1] * x[0][2], x[2][0] * x[1][2] - x[1][0] * x[2][2], x[0][0] * x[2][2] - x[2][0] * x[0][2], x[1][0] * x[0][2] - x[0][0] * x[1][2], x[1][0] * x[2][1] - x[2][0] * x[1][1], x[2][0] * x[0][1] - x[0][0] * x[2][1], x[0][0] * x[1][1] - x[1][0] * x[0][1]); T r = x[0][0] * s[0][0] + x[0][1] * s[1][0] + x[0][2] * s[2][0]; if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { s[i][j] /= r; } } } else { T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / std::numeric_limits<T>::min(); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { if (mr > IMATH_INTERNAL_NAMESPACE::abs (s[i][j])) { s[i][j] /= r; } else { return Matrix33(); } } } } return s; } else { Matrix33 s (x[1][1], -x[0][1], 0, -x[1][0], x[0][0], 0, 0, 0, 1); T r = x[0][0] * x[1][1] - x[1][0] * x[0][1]; if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { s[i][j] /= r; } } } else { T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / std::numeric_limits<T>::min(); for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { if (mr > IMATH_INTERNAL_NAMESPACE::abs (s[i][j])) { s[i][j] /= r; } else { return Matrix33(); } } } } s[2][0] = -x[2][0] * s[0][0] - x[2][1] * s[1][0]; s[2][1] = -x[2][0] * s[0][1] - x[2][1] * s[1][1]; return s; } } template <class T> IMATH_CONSTEXPR14 inline T Matrix33<T>::minorOf (const int r, const int c) const IMATH_NOEXCEPT { int r0 = 0 + (r < 1 ? 1 : 0); int r1 = 1 + (r < 2 ? 1 : 0); int c0 = 0 + (c < 1 ? 1 : 0); int c1 = 1 + (c < 2 ? 1 : 0); return x[r0][c0] * x[r1][c1] - x[r1][c0] * x[r0][c1]; } template <class T> constexpr inline T Matrix33<T>::fastMinor (const int r0, const int r1, const int c0, const int c1) const IMATH_NOEXCEPT { return x[r0][c0] * x[r1][c1] - x[r0][c1] * x[r1][c0]; } template <class T> constexpr inline T Matrix33<T>::determinant() const IMATH_NOEXCEPT { return x[0][0] * (x[1][1] * x[2][2] - x[1][2] * x[2][1]) + x[0][1] * (x[1][2] * x[2][0] - x[1][0] * x[2][2]) + x[0][2] * (x[1][0] * x[2][1] - x[1][1] * x[2][0]); } template <class T> template <class S> inline const Matrix33<T>& Matrix33<T>::setRotation (S r) IMATH_NOEXCEPT { S cos_r, sin_r; cos_r = cos ((T) r); sin_r = sin ((T) r); x[0][0] = cos_r; x[0][1] = sin_r; x[0][2] = 0; x[1][0] = -sin_r; x[1][1] = cos_r; x[1][2] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::rotate (S r) IMATH_NOEXCEPT { *this *= Matrix33<T>().setRotation (r); return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::setScale (T s) IMATH_NOEXCEPT { // // Set the matrix to a 2D homogeneous transform scale: // | s 0 0 | // | 0 s 0 | // | 0 0 1 | // x[0][0] = s; x[0][1] = 0; x[0][2] = 0; x[1][0] = 0; x[1][1] = s; x[1][2] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::setScale (const Vec2<S>& s) IMATH_NOEXCEPT { // // Set the matrix to a 2D homogeneous transform scale: // | s.x 0 0 | // | 0 s.y 0 | // | 0 0 1 | // x[0][0] = s.x; x[0][1] = 0; x[0][2] = 0; x[1][0] = 0; x[1][1] = s.y; x[1][2] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::scale (const Vec2<S>& s) IMATH_NOEXCEPT { x[0][0] *= s.x; x[0][1] *= s.x; x[0][2] *= s.x; x[1][0] *= s.y; x[1][1] *= s.y; x[1][2] *= s.y; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::setTranslation (const Vec2<S>& t) IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[0][2] = 0; x[1][0] = 0; x[1][1] = 1; x[1][2] = 0; x[2][0] = t.x; x[2][1] = t.y; x[2][2] = 1; return *this; } template <class T> constexpr inline Vec2<T> Matrix33<T>::translation() const IMATH_NOEXCEPT { return Vec2<T> (x[2][0], x[2][1]); } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::translate (const Vec2<S>& t) IMATH_NOEXCEPT { x[2][0] += t.x * x[0][0] + t.y * x[1][0]; x[2][1] += t.x * x[0][1] + t.y * x[1][1]; x[2][2] += t.x * x[0][2] + t.y * x[1][2]; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::setShear (const S& xy) IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[0][2] = 0; x[1][0] = xy; x[1][1] = 1; x[1][2] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::setShear (const Vec2<S>& h) IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = h.y; x[0][2] = 0; x[1][0] = h.x; x[1][1] = 1; x[1][2] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::shear (const S& xy) IMATH_NOEXCEPT { // // In this case, we don't need a temp. copy of the matrix // because we never use a value on the RHS after we've // changed it on the LHS. // x[1][0] += xy * x[0][0]; x[1][1] += xy * x[0][1]; x[1][2] += xy * x[0][2]; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix33<T>& Matrix33<T>::shear (const Vec2<S>& h) IMATH_NOEXCEPT { Matrix33<T> P (*this); x[0][0] = P[0][0] + h.y * P[1][0]; x[0][1] = P[0][1] + h.y * P[1][1]; x[0][2] = P[0][2] + h.y * P[1][2]; x[1][0] = P[1][0] + h.x * P[0][0]; x[1][1] = P[1][1] + h.x * P[0][1]; x[1][2] = P[1][2] + h.x * P[0][2]; return *this; } //--------------------------- // Implementation of Matrix44 //--------------------------- template <class T> inline T* Matrix44<T>::operator[] (int i) IMATH_NOEXCEPT { return x[i]; } template <class T> inline const T* Matrix44<T>::operator[] (int i) const IMATH_NOEXCEPT { return x[i]; } template <class T> IMATH_CONSTEXPR14 inline Matrix44<T>::Matrix44() IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[0][2] = 0; x[0][3] = 0; x[1][0] = 0; x[1][1] = 1; x[1][2] = 0; x[1][3] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; x[2][3] = 0; x[3][0] = 0; x[3][1] = 0; x[3][2] = 0; x[3][3] = 1; } template <class T> IMATH_CONSTEXPR14 inline Matrix44<T>::Matrix44 (T a) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = a; x[0][2] = a; x[0][3] = a; x[1][0] = a; x[1][1] = a; x[1][2] = a; x[1][3] = a; x[2][0] = a; x[2][1] = a; x[2][2] = a; x[2][3] = a; x[3][0] = a; x[3][1] = a; x[3][2] = a; x[3][3] = a; } template <class T> IMATH_CONSTEXPR14 inline Matrix44<T>::Matrix44 (const T a[4][4]) IMATH_NOEXCEPT { x[0][0] = a[0][0]; x[0][1] = a[0][1]; x[0][2] = a[0][2]; x[0][3] = a[0][3]; x[1][0] = a[1][0]; x[1][1] = a[1][1]; x[1][2] = a[1][2]; x[1][3] = a[1][3]; x[2][0] = a[2][0]; x[2][1] = a[2][1]; x[2][2] = a[2][2]; x[2][3] = a[2][3]; x[3][0] = a[3][0]; x[3][1] = a[3][1]; x[3][2] = a[3][2]; x[3][3] = a[3][3]; } template <class T> IMATH_CONSTEXPR14 inline Matrix44< T>::Matrix44 (T a, T b, T c, T d, T e, T f, T g, T h, T i, T j, T k, T l, T m, T n, T o, T p) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = b; x[0][2] = c; x[0][3] = d; x[1][0] = e; x[1][1] = f; x[1][2] = g; x[1][3] = h; x[2][0] = i; x[2][1] = j; x[2][2] = k; x[2][3] = l; x[3][0] = m; x[3][1] = n; x[3][2] = o; x[3][3] = p; } template <class T> IMATH_CONSTEXPR14 inline Matrix44<T>::Matrix44 (Matrix33<T> r, Vec3<T> t) IMATH_NOEXCEPT { x[0][0] = r[0][0]; x[0][1] = r[0][1]; x[0][2] = r[0][2]; x[0][3] = 0; x[1][0] = r[1][0]; x[1][1] = r[1][1]; x[1][2] = r[1][2]; x[1][3] = 0; x[2][0] = r[2][0]; x[2][1] = r[2][1]; x[2][2] = r[2][2]; x[2][3] = 0; x[3][0] = t.x; x[3][1] = t.y; x[3][2] = t.z; x[3][3] = 1; } template <class T> IMATH_CONSTEXPR14 inline Matrix44<T>::Matrix44 (const Matrix44& v) IMATH_NOEXCEPT { x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[0][2] = v.x[0][2]; x[0][3] = v.x[0][3]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; x[1][2] = v.x[1][2]; x[1][3] = v.x[1][3]; x[2][0] = v.x[2][0]; x[2][1] = v.x[2][1]; x[2][2] = v.x[2][2]; x[2][3] = v.x[2][3]; x[3][0] = v.x[3][0]; x[3][1] = v.x[3][1]; x[3][2] = v.x[3][2]; x[3][3] = v.x[3][3]; } template <class T> template <class S> IMATH_CONSTEXPR14 inline Matrix44<T>::Matrix44 (const Matrix44<S>& v) IMATH_NOEXCEPT { x[0][0] = T (v.x[0][0]); x[0][1] = T (v.x[0][1]); x[0][2] = T (v.x[0][2]); x[0][3] = T (v.x[0][3]); x[1][0] = T (v.x[1][0]); x[1][1] = T (v.x[1][1]); x[1][2] = T (v.x[1][2]); x[1][3] = T (v.x[1][3]); x[2][0] = T (v.x[2][0]); x[2][1] = T (v.x[2][1]); x[2][2] = T (v.x[2][2]); x[2][3] = T (v.x[2][3]); x[3][0] = T (v.x[3][0]); x[3][1] = T (v.x[3][1]); x[3][2] = T (v.x[3][2]); x[3][3] = T (v.x[3][3]); } template <class T> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::operator= (const Matrix44& v) IMATH_NOEXCEPT { x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[0][2] = v.x[0][2]; x[0][3] = v.x[0][3]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; x[1][2] = v.x[1][2]; x[1][3] = v.x[1][3]; x[2][0] = v.x[2][0]; x[2][1] = v.x[2][1]; x[2][2] = v.x[2][2]; x[2][3] = v.x[2][3]; x[3][0] = v.x[3][0]; x[3][1] = v.x[3][1]; x[3][2] = v.x[3][2]; x[3][3] = v.x[3][3]; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::operator= (T a) IMATH_NOEXCEPT { x[0][0] = a; x[0][1] = a; x[0][2] = a; x[0][3] = a; x[1][0] = a; x[1][1] = a; x[1][2] = a; x[1][3] = a; x[2][0] = a; x[2][1] = a; x[2][2] = a; x[2][3] = a; x[3][0] = a; x[3][1] = a; x[3][2] = a; x[3][3] = a; return *this; } template <class T> inline T* Matrix44<T>::getValue() IMATH_NOEXCEPT { return (T*) &x[0][0]; } template <class T> inline const T* Matrix44<T>::getValue() const IMATH_NOEXCEPT { return (const T*) &x[0][0]; } template <class T> template <class S> inline void Matrix44<T>::getValue (Matrix44<S>& v) const IMATH_NOEXCEPT { v.x[0][0] = x[0][0]; v.x[0][1] = x[0][1]; v.x[0][2] = x[0][2]; v.x[0][3] = x[0][3]; v.x[1][0] = x[1][0]; v.x[1][1] = x[1][1]; v.x[1][2] = x[1][2]; v.x[1][3] = x[1][3]; v.x[2][0] = x[2][0]; v.x[2][1] = x[2][1]; v.x[2][2] = x[2][2]; v.x[2][3] = x[2][3]; v.x[3][0] = x[3][0]; v.x[3][1] = x[3][1]; v.x[3][2] = x[3][2]; v.x[3][3] = x[3][3]; } template <class T> template <class S> IMATH_CONSTEXPR14 inline Matrix44<T>& Matrix44<T>::setValue (const Matrix44<S>& v) IMATH_NOEXCEPT { x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[0][2] = v.x[0][2]; x[0][3] = v.x[0][3]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; x[1][2] = v.x[1][2]; x[1][3] = v.x[1][3]; x[2][0] = v.x[2][0]; x[2][1] = v.x[2][1]; x[2][2] = v.x[2][2]; x[2][3] = v.x[2][3]; x[3][0] = v.x[3][0]; x[3][1] = v.x[3][1]; x[3][2] = v.x[3][2]; x[3][3] = v.x[3][3]; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline Matrix44<T>& Matrix44<T>::setTheMatrix (const Matrix44<S>& v) IMATH_NOEXCEPT { x[0][0] = v.x[0][0]; x[0][1] = v.x[0][1]; x[0][2] = v.x[0][2]; x[0][3] = v.x[0][3]; x[1][0] = v.x[1][0]; x[1][1] = v.x[1][1]; x[1][2] = v.x[1][2]; x[1][3] = v.x[1][3]; x[2][0] = v.x[2][0]; x[2][1] = v.x[2][1]; x[2][2] = v.x[2][2]; x[2][3] = v.x[2][3]; x[3][0] = v.x[3][0]; x[3][1] = v.x[3][1]; x[3][2] = v.x[3][2]; x[3][3] = v.x[3][3]; return *this; } template <class T> inline void Matrix44<T>::makeIdentity() IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[0][2] = 0; x[0][3] = 0; x[1][0] = 0; x[1][1] = 1; x[1][2] = 0; x[1][3] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; x[2][3] = 0; x[3][0] = 0; x[3][1] = 0; x[3][2] = 0; x[3][3] = 1; } template <class T> constexpr inline bool Matrix44<T>::operator== (const Matrix44& v) const IMATH_NOEXCEPT { return x[0][0] == v.x[0][0] && x[0][1] == v.x[0][1] && x[0][2] == v.x[0][2] && x[0][3] == v.x[0][3] && x[1][0] == v.x[1][0] && x[1][1] == v.x[1][1] && x[1][2] == v.x[1][2] && x[1][3] == v.x[1][3] && x[2][0] == v.x[2][0] && x[2][1] == v.x[2][1] && x[2][2] == v.x[2][2] && x[2][3] == v.x[2][3] && x[3][0] == v.x[3][0] && x[3][1] == v.x[3][1] && x[3][2] == v.x[3][2] && x[3][3] == v.x[3][3]; } template <class T> constexpr inline bool Matrix44<T>::operator!= (const Matrix44& v) const IMATH_NOEXCEPT { return x[0][0] != v.x[0][0] || x[0][1] != v.x[0][1] || x[0][2] != v.x[0][2] || x[0][3] != v.x[0][3] || x[1][0] != v.x[1][0] || x[1][1] != v.x[1][1] || x[1][2] != v.x[1][2] || x[1][3] != v.x[1][3] || x[2][0] != v.x[2][0] || x[2][1] != v.x[2][1] || x[2][2] != v.x[2][2] || x[2][3] != v.x[2][3] || x[3][0] != v.x[3][0] || x[3][1] != v.x[3][1] || x[3][2] != v.x[3][2] || x[3][3] != v.x[3][3]; } template <class T> IMATH_CONSTEXPR14 inline bool Matrix44<T>::equalWithAbsError (const Matrix44<T>& m, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) if (!IMATH_INTERNAL_NAMESPACE::equalWithAbsError ((*this)[i][j], m[i][j], e)) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline bool Matrix44<T>::equalWithRelError (const Matrix44<T>& m, T e) const IMATH_NOEXCEPT { for (int i = 0; i < 4; i++) for (int j = 0; j < 4; j++) if (!IMATH_INTERNAL_NAMESPACE::equalWithRelError ((*this)[i][j], m[i][j], e)) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::operator+= (const Matrix44<T>& v) IMATH_NOEXCEPT { x[0][0] += v.x[0][0]; x[0][1] += v.x[0][1]; x[0][2] += v.x[0][2]; x[0][3] += v.x[0][3]; x[1][0] += v.x[1][0]; x[1][1] += v.x[1][1]; x[1][2] += v.x[1][2]; x[1][3] += v.x[1][3]; x[2][0] += v.x[2][0]; x[2][1] += v.x[2][1]; x[2][2] += v.x[2][2]; x[2][3] += v.x[2][3]; x[3][0] += v.x[3][0]; x[3][1] += v.x[3][1]; x[3][2] += v.x[3][2]; x[3][3] += v.x[3][3]; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::operator+= (T a) IMATH_NOEXCEPT { x[0][0] += a; x[0][1] += a; x[0][2] += a; x[0][3] += a; x[1][0] += a; x[1][1] += a; x[1][2] += a; x[1][3] += a; x[2][0] += a; x[2][1] += a; x[2][2] += a; x[2][3] += a; x[3][0] += a; x[3][1] += a; x[3][2] += a; x[3][3] += a; return *this; } template <class T> constexpr inline Matrix44<T> Matrix44<T>::operator+ (const Matrix44<T>& v) const IMATH_NOEXCEPT { return Matrix44 (x[0][0] + v.x[0][0], x[0][1] + v.x[0][1], x[0][2] + v.x[0][2], x[0][3] + v.x[0][3], x[1][0] + v.x[1][0], x[1][1] + v.x[1][1], x[1][2] + v.x[1][2], x[1][3] + v.x[1][3], x[2][0] + v.x[2][0], x[2][1] + v.x[2][1], x[2][2] + v.x[2][2], x[2][3] + v.x[2][3], x[3][0] + v.x[3][0], x[3][1] + v.x[3][1], x[3][2] + v.x[3][2], x[3][3] + v.x[3][3]); } template <class T> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::operator-= (const Matrix44<T>& v) IMATH_NOEXCEPT { x[0][0] -= v.x[0][0]; x[0][1] -= v.x[0][1]; x[0][2] -= v.x[0][2]; x[0][3] -= v.x[0][3]; x[1][0] -= v.x[1][0]; x[1][1] -= v.x[1][1]; x[1][2] -= v.x[1][2]; x[1][3] -= v.x[1][3]; x[2][0] -= v.x[2][0]; x[2][1] -= v.x[2][1]; x[2][2] -= v.x[2][2]; x[2][3] -= v.x[2][3]; x[3][0] -= v.x[3][0]; x[3][1] -= v.x[3][1]; x[3][2] -= v.x[3][2]; x[3][3] -= v.x[3][3]; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::operator-= (T a) IMATH_NOEXCEPT { x[0][0] -= a; x[0][1] -= a; x[0][2] -= a; x[0][3] -= a; x[1][0] -= a; x[1][1] -= a; x[1][2] -= a; x[1][3] -= a; x[2][0] -= a; x[2][1] -= a; x[2][2] -= a; x[2][3] -= a; x[3][0] -= a; x[3][1] -= a; x[3][2] -= a; x[3][3] -= a; return *this; } template <class T> constexpr inline Matrix44<T> Matrix44<T>::operator- (const Matrix44<T>& v) const IMATH_NOEXCEPT { return Matrix44 (x[0][0] - v.x[0][0], x[0][1] - v.x[0][1], x[0][2] - v.x[0][2], x[0][3] - v.x[0][3], x[1][0] - v.x[1][0], x[1][1] - v.x[1][1], x[1][2] - v.x[1][2], x[1][3] - v.x[1][3], x[2][0] - v.x[2][0], x[2][1] - v.x[2][1], x[2][2] - v.x[2][2], x[2][3] - v.x[2][3], x[3][0] - v.x[3][0], x[3][1] - v.x[3][1], x[3][2] - v.x[3][2], x[3][3] - v.x[3][3]); } template <class T> constexpr inline Matrix44<T> Matrix44<T>::operator-() const IMATH_NOEXCEPT { return Matrix44 (-x[0][0], -x[0][1], -x[0][2], -x[0][3], -x[1][0], -x[1][1], -x[1][2], -x[1][3], -x[2][0], -x[2][1], -x[2][2], -x[2][3], -x[3][0], -x[3][1], -x[3][2], -x[3][3]); } template <class T> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::negate() IMATH_NOEXCEPT { x[0][0] = -x[0][0]; x[0][1] = -x[0][1]; x[0][2] = -x[0][2]; x[0][3] = -x[0][3]; x[1][0] = -x[1][0]; x[1][1] = -x[1][1]; x[1][2] = -x[1][2]; x[1][3] = -x[1][3]; x[2][0] = -x[2][0]; x[2][1] = -x[2][1]; x[2][2] = -x[2][2]; x[2][3] = -x[2][3]; x[3][0] = -x[3][0]; x[3][1] = -x[3][1]; x[3][2] = -x[3][2]; x[3][3] = -x[3][3]; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::operator*= (T a) IMATH_NOEXCEPT { x[0][0] *= a; x[0][1] *= a; x[0][2] *= a; x[0][3] *= a; x[1][0] *= a; x[1][1] *= a; x[1][2] *= a; x[1][3] *= a; x[2][0] *= a; x[2][1] *= a; x[2][2] *= a; x[2][3] *= a; x[3][0] *= a; x[3][1] *= a; x[3][2] *= a; x[3][3] *= a; return *this; } template <class T> constexpr inline Matrix44<T> Matrix44<T>::operator* (T a) const IMATH_NOEXCEPT { return Matrix44 (x[0][0] * a, x[0][1] * a, x[0][2] * a, x[0][3] * a, x[1][0] * a, x[1][1] * a, x[1][2] * a, x[1][3] * a, x[2][0] * a, x[2][1] * a, x[2][2] * a, x[2][3] * a, x[3][0] * a, x[3][1] * a, x[3][2] * a, x[3][3] * a); } /// Matrix-scalar multiplication template <class T> inline Matrix44<T> operator* (T a, const Matrix44<T>& v) IMATH_NOEXCEPT { return v * a; } template <class T> inline IMATH_CONSTEXPR14 Matrix44<T> Matrix44<T>::multiply (const Matrix44 &a, const Matrix44 &b) noexcept { const auto a00 = a.x[0][0]; const auto a01 = a.x[0][1]; const auto a02 = a.x[0][2]; const auto a03 = a.x[0][3]; const auto c00 = a00 * b.x[0][0] + a01 * b.x[1][0] + a02 * b.x[2][0] + a03 * b.x[3][0]; const auto c01 = a00 * b.x[0][1] + a01 * b.x[1][1] + a02 * b.x[2][1] + a03 * b.x[3][1]; const auto c02 = a00 * b.x[0][2] + a01 * b.x[1][2] + a02 * b.x[2][2] + a03 * b.x[3][2]; const auto c03 = a00 * b.x[0][3] + a01 * b.x[1][3] + a02 * b.x[2][3] + a03 * b.x[3][3]; const auto a10 = a.x[1][0]; const auto a11 = a.x[1][1]; const auto a12 = a.x[1][2]; const auto a13 = a.x[1][3]; const auto c10 = a10 * b.x[0][0] + a11 * b.x[1][0] + a12 * b.x[2][0] + a13 * b.x[3][0]; const auto c11 = a10 * b.x[0][1] + a11 * b.x[1][1] + a12 * b.x[2][1] + a13 * b.x[3][1]; const auto c12 = a10 * b.x[0][2] + a11 * b.x[1][2] + a12 * b.x[2][2] + a13 * b.x[3][2]; const auto c13 = a10 * b.x[0][3] + a11 * b.x[1][3] + a12 * b.x[2][3] + a13 * b.x[3][3]; const auto a20 = a.x[2][0]; const auto a21 = a.x[2][1]; const auto a22 = a.x[2][2]; const auto a23 = a.x[2][3]; const auto c20 = a20 * b.x[0][0] + a21 * b.x[1][0] + a22 * b.x[2][0] + a23 * b.x[3][0]; const auto c21 = a20 * b.x[0][1] + a21 * b.x[1][1] + a22 * b.x[2][1] + a23 * b.x[3][1]; const auto c22 = a20 * b.x[0][2] + a21 * b.x[1][2] + a22 * b.x[2][2] + a23 * b.x[3][2]; const auto c23 = a20 * b.x[0][3] + a21 * b.x[1][3] + a22 * b.x[2][3] + a23 * b.x[3][3]; const auto a30 = a.x[3][0]; const auto a31 = a.x[3][1]; const auto a32 = a.x[3][2]; const auto a33 = a.x[3][3]; const auto c30 = a30 * b.x[0][0] + a31 * b.x[1][0] + a32 * b.x[2][0] + a33 * b.x[3][0]; const auto c31 = a30 * b.x[0][1] + a31 * b.x[1][1] + a32 * b.x[2][1] + a33 * b.x[3][1]; const auto c32 = a30 * b.x[0][2] + a31 * b.x[1][2] + a32 * b.x[2][2] + a33 * b.x[3][2]; const auto c33 = a30 * b.x[0][3] + a31 * b.x[1][3] + a32 * b.x[2][3] + a33 * b.x[3][3]; return Matrix44(c00, c01, c02, c03, c10, c11, c12, c13, c20, c21, c22, c23, c30, c31, c32, c33); } template <class T> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::operator*= (const Matrix44<T>& v) IMATH_NOEXCEPT { *this = multiply(*this, v); return *this; } template <class T> IMATH_CONSTEXPR14 inline Matrix44<T> Matrix44<T>::operator* (const Matrix44<T>& v) const IMATH_NOEXCEPT { return multiply(*this, v); } template <class T> inline void Matrix44<T>::multiply (const Matrix44<T>& a, const Matrix44<T>& b, Matrix44<T>& c) IMATH_NOEXCEPT { c = multiply(a, b); } template <class T> template <class S> inline void Matrix44<T>::multVecMatrix (const Vec3<S>& src, Vec3<S>& dst) const IMATH_NOEXCEPT { S a, b, c, w; a = src.x * x[0][0] + src.y * x[1][0] + src.z * x[2][0] + x[3][0]; b = src.x * x[0][1] + src.y * x[1][1] + src.z * x[2][1] + x[3][1]; c = src.x * x[0][2] + src.y * x[1][2] + src.z * x[2][2] + x[3][2]; w = src.x * x[0][3] + src.y * x[1][3] + src.z * x[2][3] + x[3][3]; dst.x = a / w; dst.y = b / w; dst.z = c / w; } template <class T> template <class S> inline void Matrix44<T>::multDirMatrix (const Vec3<S>& src, Vec3<S>& dst) const IMATH_NOEXCEPT { S a, b, c; a = src.x * x[0][0] + src.y * x[1][0] + src.z * x[2][0]; b = src.x * x[0][1] + src.y * x[1][1] + src.z * x[2][1]; c = src.x * x[0][2] + src.y * x[1][2] + src.z * x[2][2]; dst.x = a; dst.y = b; dst.z = c; } template <class T> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::operator/= (T a) IMATH_NOEXCEPT { x[0][0] /= a; x[0][1] /= a; x[0][2] /= a; x[0][3] /= a; x[1][0] /= a; x[1][1] /= a; x[1][2] /= a; x[1][3] /= a; x[2][0] /= a; x[2][1] /= a; x[2][2] /= a; x[2][3] /= a; x[3][0] /= a; x[3][1] /= a; x[3][2] /= a; x[3][3] /= a; return *this; } template <class T> constexpr inline Matrix44<T> Matrix44<T>::operator/ (T a) const IMATH_NOEXCEPT { return Matrix44 (x[0][0] / a, x[0][1] / a, x[0][2] / a, x[0][3] / a, x[1][0] / a, x[1][1] / a, x[1][2] / a, x[1][3] / a, x[2][0] / a, x[2][1] / a, x[2][2] / a, x[2][3] / a, x[3][0] / a, x[3][1] / a, x[3][2] / a, x[3][3] / a); } template <class T> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::transpose() IMATH_NOEXCEPT { Matrix44 tmp (x[0][0], x[1][0], x[2][0], x[3][0], x[0][1], x[1][1], x[2][1], x[3][1], x[0][2], x[1][2], x[2][2], x[3][2], x[0][3], x[1][3], x[2][3], x[3][3]); *this = tmp; return *this; } template <class T> constexpr inline Matrix44<T> Matrix44<T>::transposed() const IMATH_NOEXCEPT { return Matrix44 (x[0][0], x[1][0], x[2][0], x[3][0], x[0][1], x[1][1], x[2][1], x[3][1], x[0][2], x[1][2], x[2][2], x[3][2], x[0][3], x[1][3], x[2][3], x[3][3]); } template <class T> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::gjInvert (bool singExc) { *this = gjInverse (singExc); return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::gjInvert() IMATH_NOEXCEPT { *this = gjInverse(); return *this; } template <class T> inline Matrix44<T> Matrix44<T>::gjInverse (bool singExc) const { int i, j, k; Matrix44 s; Matrix44 t (*this); // Forward elimination for (i = 0; i < 3; i++) { int pivot = i; T pivotsize = t[i][i]; if (pivotsize < 0) pivotsize = -pivotsize; for (j = i + 1; j < 4; j++) { T tmp = t[j][i]; if (tmp < 0) tmp = -tmp; if (tmp > pivotsize) { pivot = j; pivotsize = tmp; } } if (pivotsize == 0) { if (singExc) throw std::invalid_argument ("Cannot invert singular matrix."); return Matrix44(); } if (pivot != i) { for (j = 0; j < 4; j++) { T tmp; tmp = t[i][j]; t[i][j] = t[pivot][j]; t[pivot][j] = tmp; tmp = s[i][j]; s[i][j] = s[pivot][j]; s[pivot][j] = tmp; } } for (j = i + 1; j < 4; j++) { T f = t[j][i] / t[i][i]; for (k = 0; k < 4; k++) { t[j][k] -= f * t[i][k]; s[j][k] -= f * s[i][k]; } } } // Backward substitution for (i = 3; i >= 0; --i) { T f; if ((f = t[i][i]) == 0) { if (singExc) throw std::invalid_argument ("Cannot invert singular matrix."); return Matrix44(); } for (j = 0; j < 4; j++) { t[i][j] /= f; s[i][j] /= f; } for (j = 0; j < i; j++) { f = t[j][i]; for (k = 0; k < 4; k++) { t[j][k] -= f * t[i][k]; s[j][k] -= f * s[i][k]; } } } return s; } template <class T> inline Matrix44<T> Matrix44<T>::gjInverse() const IMATH_NOEXCEPT { int i, j, k; Matrix44 s; Matrix44 t (*this); // Forward elimination for (i = 0; i < 3; i++) { int pivot = i; T pivotsize = t[i][i]; if (pivotsize < 0) pivotsize = -pivotsize; for (j = i + 1; j < 4; j++) { T tmp = t[j][i]; if (tmp < 0) tmp = -tmp; if (tmp > pivotsize) { pivot = j; pivotsize = tmp; } } if (pivotsize == 0) { return Matrix44(); } if (pivot != i) { for (j = 0; j < 4; j++) { T tmp; tmp = t[i][j]; t[i][j] = t[pivot][j]; t[pivot][j] = tmp; tmp = s[i][j]; s[i][j] = s[pivot][j]; s[pivot][j] = tmp; } } for (j = i + 1; j < 4; j++) { T f = t[j][i] / t[i][i]; for (k = 0; k < 4; k++) { t[j][k] -= f * t[i][k]; s[j][k] -= f * s[i][k]; } } } // Backward substitution for (i = 3; i >= 0; --i) { T f; if ((f = t[i][i]) == 0) { return Matrix44(); } for (j = 0; j < 4; j++) { t[i][j] /= f; s[i][j] /= f; } for (j = 0; j < i; j++) { f = t[j][i]; for (k = 0; k < 4; k++) { t[j][k] -= f * t[i][k]; s[j][k] -= f * s[i][k]; } } } return s; } template <class T> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::invert (bool singExc) { *this = inverse (singExc); return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::invert() IMATH_NOEXCEPT { *this = inverse(); return *this; } template <class T> IMATH_CONSTEXPR14 inline Matrix44<T> Matrix44<T>::inverse (bool singExc) const { if (x[0][3] != 0 || x[1][3] != 0 || x[2][3] != 0 || x[3][3] != 1) return gjInverse (singExc); Matrix44 s (x[1][1] * x[2][2] - x[2][1] * x[1][2], x[2][1] * x[0][2] - x[0][1] * x[2][2], x[0][1] * x[1][2] - x[1][1] * x[0][2], 0, x[2][0] * x[1][2] - x[1][0] * x[2][2], x[0][0] * x[2][2] - x[2][0] * x[0][2], x[1][0] * x[0][2] - x[0][0] * x[1][2], 0, x[1][0] * x[2][1] - x[2][0] * x[1][1], x[2][0] * x[0][1] - x[0][0] * x[2][1], x[0][0] * x[1][1] - x[1][0] * x[0][1], 0, 0, 0, 0, 1); T r = x[0][0] * s[0][0] + x[0][1] * s[1][0] + x[0][2] * s[2][0]; if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { s[i][j] /= r; } } } else { T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / std::numeric_limits<T>::min(); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { if (mr > IMATH_INTERNAL_NAMESPACE::abs (s[i][j])) { s[i][j] /= r; } else { if (singExc) throw std::invalid_argument ("Cannot invert singular matrix."); return Matrix44(); } } } } s[3][0] = -x[3][0] * s[0][0] - x[3][1] * s[1][0] - x[3][2] * s[2][0]; s[3][1] = -x[3][0] * s[0][1] - x[3][1] * s[1][1] - x[3][2] * s[2][1]; s[3][2] = -x[3][0] * s[0][2] - x[3][1] * s[1][2] - x[3][2] * s[2][2]; return s; } template <class T> IMATH_CONSTEXPR14 inline Matrix44<T> Matrix44<T>::inverse() const IMATH_NOEXCEPT { if (x[0][3] != 0 || x[1][3] != 0 || x[2][3] != 0 || x[3][3] != 1) return gjInverse(); Matrix44 s (x[1][1] * x[2][2] - x[2][1] * x[1][2], x[2][1] * x[0][2] - x[0][1] * x[2][2], x[0][1] * x[1][2] - x[1][1] * x[0][2], 0, x[2][0] * x[1][2] - x[1][0] * x[2][2], x[0][0] * x[2][2] - x[2][0] * x[0][2], x[1][0] * x[0][2] - x[0][0] * x[1][2], 0, x[1][0] * x[2][1] - x[2][0] * x[1][1], x[2][0] * x[0][1] - x[0][0] * x[2][1], x[0][0] * x[1][1] - x[1][0] * x[0][1], 0, 0, 0, 0, 1); T r = x[0][0] * s[0][0] + x[0][1] * s[1][0] + x[0][2] * s[2][0]; if (IMATH_INTERNAL_NAMESPACE::abs (r) >= 1) { for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { s[i][j] /= r; } } } else { T mr = IMATH_INTERNAL_NAMESPACE::abs (r) / std::numeric_limits<T>::min(); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { if (mr > IMATH_INTERNAL_NAMESPACE::abs (s[i][j])) { s[i][j] /= r; } else { return Matrix44(); } } } } s[3][0] = -x[3][0] * s[0][0] - x[3][1] * s[1][0] - x[3][2] * s[2][0]; s[3][1] = -x[3][0] * s[0][1] - x[3][1] * s[1][1] - x[3][2] * s[2][1]; s[3][2] = -x[3][0] * s[0][2] - x[3][1] * s[1][2] - x[3][2] * s[2][2]; return s; } template <class T> constexpr inline T Matrix44<T>::fastMinor (const int r0, const int r1, const int r2, const int c0, const int c1, const int c2) const IMATH_NOEXCEPT { return x[r0][c0] * (x[r1][c1] * x[r2][c2] - x[r1][c2] * x[r2][c1]) + x[r0][c1] * (x[r1][c2] * x[r2][c0] - x[r1][c0] * x[r2][c2]) + x[r0][c2] * (x[r1][c0] * x[r2][c1] - x[r1][c1] * x[r2][c0]); } template <class T> IMATH_CONSTEXPR14 inline T Matrix44<T>::minorOf (const int r, const int c) const IMATH_NOEXCEPT { int r0 = 0 + (r < 1 ? 1 : 0); int r1 = 1 + (r < 2 ? 1 : 0); int r2 = 2 + (r < 3 ? 1 : 0); int c0 = 0 + (c < 1 ? 1 : 0); int c1 = 1 + (c < 2 ? 1 : 0); int c2 = 2 + (c < 3 ? 1 : 0); Matrix33<T> working (x[r0][c0], x[r1][c0], x[r2][c0], x[r0][c1], x[r1][c1], x[r2][c1], x[r0][c2], x[r1][c2], x[r2][c2]); return working.determinant(); } template <class T> IMATH_CONSTEXPR14 inline T Matrix44<T>::determinant() const IMATH_NOEXCEPT { T sum = (T) 0; if (x[0][3] != 0.) sum -= x[0][3] * fastMinor (1, 2, 3, 0, 1, 2); if (x[1][3] != 0.) sum += x[1][3] * fastMinor (0, 2, 3, 0, 1, 2); if (x[2][3] != 0.) sum -= x[2][3] * fastMinor (0, 1, 3, 0, 1, 2); if (x[3][3] != 0.) sum += x[3][3] * fastMinor (0, 1, 2, 0, 1, 2); return sum; } template <class T> template <class S> inline const Matrix44<T>& Matrix44<T>::setEulerAngles (const Vec3<S>& r) IMATH_NOEXCEPT { S cos_rz, sin_rz, cos_ry, sin_ry, cos_rx, sin_rx; cos_rz = cos ((T) r.z); cos_ry = cos ((T) r.y); cos_rx = cos ((T) r.x); sin_rz = sin ((T) r.z); sin_ry = sin ((T) r.y); sin_rx = sin ((T) r.x); x[0][0] = cos_rz * cos_ry; x[0][1] = sin_rz * cos_ry; x[0][2] = -sin_ry; x[0][3] = 0; x[1][0] = -sin_rz * cos_rx + cos_rz * sin_ry * sin_rx; x[1][1] = cos_rz * cos_rx + sin_rz * sin_ry * sin_rx; x[1][2] = cos_ry * sin_rx; x[1][3] = 0; x[2][0] = sin_rz * sin_rx + cos_rz * sin_ry * cos_rx; x[2][1] = -cos_rz * sin_rx + sin_rz * sin_ry * cos_rx; x[2][2] = cos_ry * cos_rx; x[2][3] = 0; x[3][0] = 0; x[3][1] = 0; x[3][2] = 0; x[3][3] = 1; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::setAxisAngle (const Vec3<S>& axis, S angle) IMATH_NOEXCEPT { Vec3<S> unit (axis.normalized()); S sine = std::sin (angle); S cosine = std::cos (angle); x[0][0] = unit.x * unit.x * (1 - cosine) + cosine; x[0][1] = unit.x * unit.y * (1 - cosine) + unit.z * sine; x[0][2] = unit.x * unit.z * (1 - cosine) - unit.y * sine; x[0][3] = 0; x[1][0] = unit.x * unit.y * (1 - cosine) - unit.z * sine; x[1][1] = unit.y * unit.y * (1 - cosine) + cosine; x[1][2] = unit.y * unit.z * (1 - cosine) + unit.x * sine; x[1][3] = 0; x[2][0] = unit.x * unit.z * (1 - cosine) + unit.y * sine; x[2][1] = unit.y * unit.z * (1 - cosine) - unit.x * sine; x[2][2] = unit.z * unit.z * (1 - cosine) + cosine; x[2][3] = 0; x[3][0] = 0; x[3][1] = 0; x[3][2] = 0; x[3][3] = 1; return *this; } template <class T> template <class S> inline const Matrix44<T>& Matrix44<T>::rotate (const Vec3<S>& r) IMATH_NOEXCEPT { S cos_rz, sin_rz, cos_ry, sin_ry, cos_rx, sin_rx; S m00, m01, m02; S m10, m11, m12; S m20, m21, m22; cos_rz = cos ((S) r.z); cos_ry = cos ((S) r.y); cos_rx = cos ((S) r.x); sin_rz = sin ((S) r.z); sin_ry = sin ((S) r.y); sin_rx = sin ((S) r.x); m00 = cos_rz * cos_ry; m01 = sin_rz * cos_ry; m02 = -sin_ry; m10 = -sin_rz * cos_rx + cos_rz * sin_ry * sin_rx; m11 = cos_rz * cos_rx + sin_rz * sin_ry * sin_rx; m12 = cos_ry * sin_rx; m20 = -sin_rz * -sin_rx + cos_rz * sin_ry * cos_rx; m21 = cos_rz * -sin_rx + sin_rz * sin_ry * cos_rx; m22 = cos_ry * cos_rx; Matrix44<T> P (*this); x[0][0] = P[0][0] * m00 + P[1][0] * m01 + P[2][0] * m02; x[0][1] = P[0][1] * m00 + P[1][1] * m01 + P[2][1] * m02; x[0][2] = P[0][2] * m00 + P[1][2] * m01 + P[2][2] * m02; x[0][3] = P[0][3] * m00 + P[1][3] * m01 + P[2][3] * m02; x[1][0] = P[0][0] * m10 + P[1][0] * m11 + P[2][0] * m12; x[1][1] = P[0][1] * m10 + P[1][1] * m11 + P[2][1] * m12; x[1][2] = P[0][2] * m10 + P[1][2] * m11 + P[2][2] * m12; x[1][3] = P[0][3] * m10 + P[1][3] * m11 + P[2][3] * m12; x[2][0] = P[0][0] * m20 + P[1][0] * m21 + P[2][0] * m22; x[2][1] = P[0][1] * m20 + P[1][1] * m21 + P[2][1] * m22; x[2][2] = P[0][2] * m20 + P[1][2] * m21 + P[2][2] * m22; x[2][3] = P[0][3] * m20 + P[1][3] * m21 + P[2][3] * m22; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::setScale (T s) IMATH_NOEXCEPT { // // Set the matrix to a 3D homogeneous transform scale: // | s 0 0 0 | // | 0 s 0 0 | // | 0 0 s 0 | // | 0 0 0 1 | // x[0][0] = s; x[0][1] = 0; x[0][2] = 0; x[0][3] = 0; x[1][0] = 0; x[1][1] = s; x[1][2] = 0; x[1][3] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = s; x[2][3] = 0; x[3][0] = 0; x[3][1] = 0; x[3][2] = 0; x[3][3] = 1; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::setScale (const Vec3<S>& s) IMATH_NOEXCEPT { // // Set the matrix to a 3D homogeneous transform scale: // | s.x 0 0 0 | // | 0 s.y 0 0 | // | 0 0 s.z 0 | // | 0 0 0 1 | // x[0][0] = s.x; x[0][1] = 0; x[0][2] = 0; x[0][3] = 0; x[1][0] = 0; x[1][1] = s.y; x[1][2] = 0; x[1][3] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = s.z; x[2][3] = 0; x[3][0] = 0; x[3][1] = 0; x[3][2] = 0; x[3][3] = 1; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::scale (const Vec3<S>& s) IMATH_NOEXCEPT { x[0][0] *= s.x; x[0][1] *= s.x; x[0][2] *= s.x; x[0][3] *= s.x; x[1][0] *= s.y; x[1][1] *= s.y; x[1][2] *= s.y; x[1][3] *= s.y; x[2][0] *= s.z; x[2][1] *= s.z; x[2][2] *= s.z; x[2][3] *= s.z; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::setTranslation (const Vec3<S>& t) IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[0][2] = 0; x[0][3] = 0; x[1][0] = 0; x[1][1] = 1; x[1][2] = 0; x[1][3] = 0; x[2][0] = 0; x[2][1] = 0; x[2][2] = 1; x[2][3] = 0; x[3][0] = t.x; x[3][1] = t.y; x[3][2] = t.z; x[3][3] = 1; return *this; } template <class T> constexpr inline const Vec3<T> Matrix44<T>::translation() const IMATH_NOEXCEPT { return Vec3<T> (x[3][0], x[3][1], x[3][2]); } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::translate (const Vec3<S>& t) IMATH_NOEXCEPT { x[3][0] += t.x * x[0][0] + t.y * x[1][0] + t.z * x[2][0]; x[3][1] += t.x * x[0][1] + t.y * x[1][1] + t.z * x[2][1]; x[3][2] += t.x * x[0][2] + t.y * x[1][2] + t.z * x[2][2]; x[3][3] += t.x * x[0][3] + t.y * x[1][3] + t.z * x[2][3]; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::setShear (const Vec3<S>& h) IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = 0; x[0][2] = 0; x[0][3] = 0; x[1][0] = h.x; x[1][1] = 1; x[1][2] = 0; x[1][3] = 0; x[2][0] = h.y; x[2][1] = h.z; x[2][2] = 1; x[2][3] = 0; x[3][0] = 0; x[3][1] = 0; x[3][2] = 0; x[3][3] = 1; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::setShear (const Shear6<S>& h) IMATH_NOEXCEPT { x[0][0] = 1; x[0][1] = h.yx; x[0][2] = h.zx; x[0][3] = 0; x[1][0] = h.xy; x[1][1] = 1; x[1][2] = h.zy; x[1][3] = 0; x[2][0] = h.xz; x[2][1] = h.yz; x[2][2] = 1; x[2][3] = 0; x[3][0] = 0; x[3][1] = 0; x[3][2] = 0; x[3][3] = 1; return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::shear (const Vec3<S>& h) IMATH_NOEXCEPT { // // In this case, we don't need a temp. copy of the matrix // because we never use a value on the RHS after we've // changed it on the LHS. // for (int i = 0; i < 4; i++) { x[2][i] += h.y * x[0][i] + h.z * x[1][i]; x[1][i] += h.x * x[0][i]; } return *this; } template <class T> template <class S> IMATH_CONSTEXPR14 inline const Matrix44<T>& Matrix44<T>::shear (const Shear6<S>& h) IMATH_NOEXCEPT { Matrix44<T> P (*this); for (int i = 0; i < 4; i++) { x[0][i] = P[0][i] + h.yx * P[1][i] + h.zx * P[2][i]; x[1][i] = h.xy * P[0][i] + P[1][i] + h.zy * P[2][i]; x[2][i] = h.xz * P[0][i] + h.yz * P[1][i] + P[2][i]; } return *this; } //-------------------------------- // Implementation of stream output //-------------------------------- template <class T> std::ostream& operator<< (std::ostream& s, const Matrix22<T>& m) { std::ios_base::fmtflags oldFlags = s.flags(); int width; if (s.flags() & std::ios_base::fixed) { s.setf (std::ios_base::showpoint); width = static_cast<int> (s.precision()) + 5; } else { s.setf (std::ios_base::scientific); s.setf (std::ios_base::showpoint); width = static_cast<int> (s.precision()) + 8; } s << "(" << std::setw (width) << m[0][0] << " " << std::setw (width) << m[0][1] << "\n" << " " << std::setw (width) << m[1][0] << " " << std::setw (width) << m[1][1] << ")\n"; s.flags (oldFlags); return s; } template <class T> std::ostream& operator<< (std::ostream& s, const Matrix33<T>& m) { std::ios_base::fmtflags oldFlags = s.flags(); int width; if (s.flags() & std::ios_base::fixed) { s.setf (std::ios_base::showpoint); width = static_cast<int> (s.precision()) + 5; } else { s.setf (std::ios_base::scientific); s.setf (std::ios_base::showpoint); width = static_cast<int> (s.precision()) + 8; } s << "(" << std::setw (width) << m[0][0] << " " << std::setw (width) << m[0][1] << " " << std::setw (width) << m[0][2] << "\n" << " " << std::setw (width) << m[1][0] << " " << std::setw (width) << m[1][1] << " " << std::setw (width) << m[1][2] << "\n" << " " << std::setw (width) << m[2][0] << " " << std::setw (width) << m[2][1] << " " << std::setw (width) << m[2][2] << ")\n"; s.flags (oldFlags); return s; } template <class T> std::ostream& operator<< (std::ostream& s, const Matrix44<T>& m) { std::ios_base::fmtflags oldFlags = s.flags(); int width; if (s.flags() & std::ios_base::fixed) { s.setf (std::ios_base::showpoint); width = static_cast<int> (s.precision()) + 5; } else { s.setf (std::ios_base::scientific); s.setf (std::ios_base::showpoint); width = static_cast<int> (s.precision()) + 8; } s << "(" << std::setw (width) << m[0][0] << " " << std::setw (width) << m[0][1] << " " << std::setw (width) << m[0][2] << " " << std::setw (width) << m[0][3] << "\n" << " " << std::setw (width) << m[1][0] << " " << std::setw (width) << m[1][1] << " " << std::setw (width) << m[1][2] << " " << std::setw (width) << m[1][3] << "\n" << " " << std::setw (width) << m[2][0] << " " << std::setw (width) << m[2][1] << " " << std::setw (width) << m[2][2] << " " << std::setw (width) << m[2][3] << "\n" << " " << std::setw (width) << m[3][0] << " " << std::setw (width) << m[3][1] << " " << std::setw (width) << m[3][2] << " " << std::setw (width) << m[3][3] << ")\n"; s.flags (oldFlags); return s; } //--------------------------------------------------------------- // Implementation of vector-times-matrix multiplication operators //--------------------------------------------------------------- template <class S, class T> inline const Vec2<S>& operator*= (Vec2<S>& v, const Matrix22<T>& m) IMATH_NOEXCEPT { S x = S (v.x * m[0][0] + v.y * m[1][0]); S y = S (v.x * m[0][1] + v.y * m[1][1]); v.x = x; v.y = y; return v; } template <class S, class T> inline Vec2<S> operator* (const Vec2<S>& v, const Matrix22<T>& m) IMATH_NOEXCEPT { S x = S (v.x * m[0][0] + v.y * m[1][0]); S y = S (v.x * m[0][1] + v.y * m[1][1]); return Vec2<S> (x, y); } template <class S, class T> inline const Vec2<S>& operator*= (Vec2<S>& v, const Matrix33<T>& m) IMATH_NOEXCEPT { S x = S (v.x * m[0][0] + v.y * m[1][0] + m[2][0]); S y = S (v.x * m[0][1] + v.y * m[1][1] + m[2][1]); S w = S (v.x * m[0][2] + v.y * m[1][2] + m[2][2]); v.x = x / w; v.y = y / w; return v; } template <class S, class T> inline Vec2<S> operator* (const Vec2<S>& v, const Matrix33<T>& m) IMATH_NOEXCEPT { S x = S (v.x * m[0][0] + v.y * m[1][0] + m[2][0]); S y = S (v.x * m[0][1] + v.y * m[1][1] + m[2][1]); S w = S (v.x * m[0][2] + v.y * m[1][2] + m[2][2]); return Vec2<S> (x / w, y / w); } template <class S, class T> inline const Vec3<S>& operator*= (Vec3<S>& v, const Matrix33<T>& m) IMATH_NOEXCEPT { S x = S (v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0]); S y = S (v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1]); S z = S (v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2]); v.x = x; v.y = y; v.z = z; return v; } template <class S, class T> inline Vec3<S> operator* (const Vec3<S>& v, const Matrix33<T>& m) IMATH_NOEXCEPT { S x = S (v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0]); S y = S (v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1]); S z = S (v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2]); return Vec3<S> (x, y, z); } template <class S, class T> inline const Vec3<S>& operator*= (Vec3<S>& v, const Matrix44<T>& m) IMATH_NOEXCEPT { S x = S (v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0] + m[3][0]); S y = S (v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1] + m[3][1]); S z = S (v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2] + m[3][2]); S w = S (v.x * m[0][3] + v.y * m[1][3] + v.z * m[2][3] + m[3][3]); v.x = x / w; v.y = y / w; v.z = z / w; return v; } template <class S, class T> inline Vec3<S> operator* (const Vec3<S>& v, const Matrix44<T>& m) IMATH_NOEXCEPT { S x = S (v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0] + m[3][0]); S y = S (v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1] + m[3][1]); S z = S (v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2] + m[3][2]); S w = S (v.x * m[0][3] + v.y * m[1][3] + v.z * m[2][3] + m[3][3]); return Vec3<S> (x / w, y / w, z / w); } template <class S, class T> inline const Vec4<S>& operator*= (Vec4<S>& v, const Matrix44<T>& m) IMATH_NOEXCEPT { S x = S (v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0] + v.w * m[3][0]); S y = S (v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1] + v.w * m[3][1]); S z = S (v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2] + v.w * m[3][2]); S w = S (v.x * m[0][3] + v.y * m[1][3] + v.z * m[2][3] + v.w * m[3][3]); v.x = x; v.y = y; v.z = z; v.w = w; return v; } template <class S, class T> inline Vec4<S> operator* (const Vec4<S>& v, const Matrix44<T>& m) IMATH_NOEXCEPT { S x = S (v.x * m[0][0] + v.y * m[1][0] + v.z * m[2][0] + v.w * m[3][0]); S y = S (v.x * m[0][1] + v.y * m[1][1] + v.z * m[2][1] + v.w * m[3][1]); S z = S (v.x * m[0][2] + v.y * m[1][2] + v.z * m[2][2] + v.w * m[3][2]); S w = S (v.x * m[0][3] + v.y * m[1][3] + v.z * m[2][3] + v.w * m[3][3]); return Vec4<S> (x, y, z, w); } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHMATRIX_H PyImathAPI.h 0000644 00000004620 15125213144 0006622 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathAPI_h_ #define _PyImathAPI_h_ #include <patchlevel.h> #if PY_MAJOR_VERSION >= 3 // Big changes in Python3 with regard to PyClass. Most of these functions // are gone so the equivalent functionality is done this way... #define PyClass_Check(object) \ PyObject_IsInstance (object, reinterpret_cast<PyObject *> (&PyType_Type)) // Py_FindMethod is gone and so you must search for functions by searching // through an object's attributes. #define Py_FindMethod(methods, self, name) \ PyObject_GenericGetAttr(self, PyBytes_FromString(name)) // One of the biggest differences between 2&3 is use support for Unicode. // Working with strings at the C API level one has be careful that the // returned object will not be Unicode and thus need to be decoded before // being interpreted. These macros will return the PyBytes type of PyObject // pointer that replaces PyString. #define PyString_Check(str) PyBytes_Check(str) #define PyString_FromString(str) PyBytes_FromString(str) #define PyString_AsString(obj) PyBytes_AsString(obj) #define PyString_AsStringAndSize(obj, str, len) PyBytes_AsStringAndSize(obj, str, len) // Python3 interprets all integers as long types and has deprecated PyInt. #define PyInt_Check(x) PyLong_Check(x) #define PyInt_AsLong(x) PyLong_AsLong(x) #define PyInt_AS_LONG(x) PyLong_AsLong(x) #define PyInt_AsSsize_t(x) PyLong_AsSsize_t(x) #define PyInt_FromLong(x) PyLong_FromLong(x) // These flags are not present in Python3 and must be replaced with the // default set of flags so that OR'ing them together doesn't alter the // flags. #define Py_TPFLAGS_CHECKTYPES Py_TPFLAGS_DEFAULT #define Py_TPFLAGS_HAVE_RICHCOMPARE Py_TPFLAGS_DEFAULT // The __repr__ for a TypeObject will be encoded and needs to be // processed as a PyBytes object before it can be return as a string. #define PYUTIL_OBJECT_REPR(obj) PyObject_Str (PyObject_Repr (obj)) #else // Python2 code will need to access PyObject_Repr() via this macro so // that both 2&3 can compile without modification. #define PYUTIL_OBJECT_REPR(obj) PyObject_Repr (obj) #endif #endif // _PyImathAPI_h_ ImathConfig.h 0000644 00000012125 15125213144 0007104 0 ustar 00 // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // This file is auto-generated by the cmake configure step #ifndef INCLUDED_IMATH_CONFIG_H #define INCLUDED_IMATH_CONFIG_H 1 #pragma once // // Options / configuration based on O.S. / compiler // // // Define whether the half-to-float conversion should use the lookup // table method. Note that this is overriden by F16C compiler // flags. It is also overrided by the IMATH_HALF_NO_LOOKUP_TABLE // macro, if defined. // #define IMATH_HALF_USE_LOOKUP_TABLE // // Define if the target system has support for large // stack sizes. // /* #undef IMATH_HAVE_LARGE_STACK */ ////////////////////// // // C++ namespace configuration / options // Current (internal) library namepace name and corresponding public // client namespaces. #define IMATH_INTERNAL_NAMESPACE_CUSTOM 0 #define IMATH_INTERNAL_NAMESPACE Imath_3_1 #define IMATH_NAMESPACE_CUSTOM 0 #define IMATH_NAMESPACE Imath // // Version information // #define IMATH_VERSION_STRING "3.1.2" #define IMATH_PACKAGE_STRING "Imath 3.1.2" #define IMATH_VERSION_MAJOR 3 #define IMATH_VERSION_MINOR 1 #define IMATH_VERSION_PATCH 2 #define IMATH_VERSION_RELEASE_TYPE "" #define IMATH_VERSION_HEX ((uint32_t(IMATH_VERSION_MAJOR) << 24) | \ (uint32_t(IMATH_VERSION_MINOR) << 16) | \ (uint32_t(IMATH_VERSION_PATCH) << 8)) // IMATH_LIB_VERSION is the library API version: SOCURRENT.SOAGE.SOREVISION #define IMATH_LIB_VERSION_STRING "29.1.0" // // Code that depends on the v2 ExcMath mechanism of signal handlers // that throw exceptions is incompatible with noexcept, since // floating-point overflow and underflow can occur in a wide variety // of computations within Imath functions now marked with // noexcept. Code that needs to accomodate the exception-handling // behavior can build with the IMATH_USE_NOEXCEPT off. // #define IMATH_USE_NOEXCEPT 1 #if IMATH_USE_NOEXCEPT #define IMATH_NOEXCEPT noexcept #else #define IMATH_NOEXCEPT #endif // // By default, opt into the interoparability constructors and assignments. // If this causes problems, it can be disabled by defining this symbol to // be 0 prior to including any Imath headers. // // If no such definition is found, we enable automatically unless we are // using gcc 4.x, which appears to have bugs that prevent the interop // templates from compiling correctly. // #ifndef IMATH_FOREIGN_VECTOR_INTEROP # if defined(__GNUC__) && __GNUC__ == 4 && !defined(__clang__) # define IMATH_FOREIGN_VECTOR_INTEROP 0 # else # define IMATH_FOREIGN_VECTOR_INTEROP 1 # endif #endif // // Decorator that makes a function available for both CPU and GPU, when // compiling for Cuda. // #ifdef __CUDACC__ #define IMATH_HOSTDEVICE __host__ __device__ #else #define IMATH_HOSTDEVICE #endif // // Some compilers define a special intrinsic to use in conditionals that can // speed up extremely performance-critical spots if the conditional is // usually (or rarely) is true. You use it by replacing // if (x) ... // with // if (IMATH_LIKELY(x)) ... // if you think x will usually be true // or // if (IMATH_UNLIKELY(x)) ... // if you think x will rarely be true // // Caveat: Programmers are notoriously bad at guessing this, so it should be // used only with thorough benchmarking. // #if defined(__GNUC__) || defined(__clang__) || defined(__INTEL_COMPILER) # ifdef __cplusplus # define IMATH_LIKELY(x) (__builtin_expect(static_cast<bool>(x), true)) # define IMATH_UNLIKELY(x) (__builtin_expect(static_cast<bool>(x), false)) # else # define IMATH_LIKELY(x) (__builtin_expect((x), 1)) # define IMATH_UNLIKELY(x) (__builtin_expect((x), 0)) # endif #else # define IMATH_LIKELY(x) (x) # define IMATH_UNLIKELY(x) (x) #endif // // Simple way to mark things as deprecated. // When we are sure that C++14 is our true minimum, then we can just // directly use [[deprecated(msg)]]. // #if defined(_MSC_VER) # define IMATH_DEPRECATED(msg) __declspec(deprecated(msg)) #elif defined(__cplusplus) && __cplusplus >= 201402L # define IMATH_DEPRECATED(msg) [[deprecated(msg)]] #elif defined(__GNUC__) || defined(__clang__) # define IMATH_DEPRECATED(msg) __attribute__((deprecated(msg))) #else # define IMATH_DEPRECATED(msg) /* unsupported on this platform */ #endif // Whether the user configured the library to have symbol visibility // tagged #define IMATH_ENABLE_API_VISIBILITY // MSVC does not do the same visibility attributes, and when we are // compiling a static library we won't be in DLL mode, but just don't // define these and the export headers will work out #if ! defined(_MSC_VER) && defined(IMATH_ENABLE_API_VISIBILITY) # define IMATH_PUBLIC_SYMBOL_ATTRIBUTE __attribute__ ((__visibility__ ("default"))) # define IMATH_PRIVATE_SYMBOL_ATTRIBUTE __attribute__ ((__visibility__ ("hidden"))) // clang differs from gcc and has type visibility which is needed for enums and templates # if __has_attribute(__type_visibility__) # define IMATH_PUBLIC_TYPE_VISIBILITY_ATTRIBUTE __attribute__ ((__type_visibility__ ("default"))) # endif #endif #endif // INCLUDED_IMATH_CONFIG_H PyImathBasicTypes.h 0000644 00000000434 15125213144 0010256 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathBasicTypes_h_ #define _PyImathBasicTypes_h_ #include "PyImathExport.h" namespace PyImath { PYIMATH_EXPORT void register_basicTypes(); } #endif ImathBox.h 0000644 00000055413 15125213144 0006436 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // Axis-aligned bounding box // #ifndef INCLUDED_IMATHBOX_H #define INCLUDED_IMATHBOX_H #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathVec.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// /// The `Box<V>` template represents an axis-aligned bounding box defined by /// minimum and maximum values of type `V`. The `min` and `max` members are /// public. /// /// The type `V` is typically an Imath vector (i.e. `V2i`, `V3f`, etc) and must /// implement an index `operator[]` that returns a type (typically as scalar) /// that supports assignment, comparison, and arithmetic operators. /// /// `V` must also provide a constructor that takes a float and/or double for /// use in initializing the box. /// /// `V` must also provide a function `V::dimensions()` which returns the /// number of dimensions in the class (since its assumed its a vector) -- /// preferably, this returns a constant expression, typically 2 or 3. /// template <class V> class IMATH_EXPORT_TEMPLATE_TYPE Box { public: /// @{ /// @name Direct access to bounds /// The minimum value of the box. V min; /// The maximum value of the box. V max; /// @} /// @{ /// @name Constructors /// Construct an empty bounding box. This initializes the mimimum to /// `std::numeric_limits<V::baseType>::max()` and the maximum to /// `std::numeric_limits<V::baseType>::lowest()`. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Box() IMATH_NOEXCEPT; /// Construct a bounding box that contains a single point. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Box (const V& point) IMATH_NOEXCEPT; /// Construct a bounding box with the given minimum and maximum values. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Box (const V& minV, const V& maxV) IMATH_NOEXCEPT; /// @} /// @{ /// @name Comparison /// Equality IMATH_HOSTDEVICE constexpr bool operator== (const Box<V>& src) const IMATH_NOEXCEPT; /// Inequality IMATH_HOSTDEVICE constexpr bool operator!= (const Box<V>& src) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Manipulation /// Set the box to be empty. A box is empty if the mimimum is greater /// than the maximum. makeEmpty() sets the mimimum to `V::baseTypeMax()` /// and the maximum to `V::baseTypeLowest()`. IMATH_HOSTDEVICE void makeEmpty() IMATH_NOEXCEPT; /// Extend the box to include the given point. IMATH_HOSTDEVICE void extendBy (const V& point) IMATH_NOEXCEPT; /// Extend the box to include the given box. IMATH_HOSTDEVICE void extendBy (const Box<V>& box) IMATH_NOEXCEPT; /// Make the box include the entire range of `V`. IMATH_HOSTDEVICE void makeInfinite() IMATH_NOEXCEPT; /// @} /// @{ /// @name Query /// Return the size of the box. The size is of type `V`, defined /// as `(max-min)`. An empty box has a size of `V(0)`, i.e. 0 in /// each dimension. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 V size() const IMATH_NOEXCEPT; /// Return the center of the box. The center is defined as /// `(max+min)/2`. The center of an empty box is undefined. IMATH_HOSTDEVICE constexpr V center() const IMATH_NOEXCEPT; /// Return true if the given point is inside the box, false otherwise. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersects (const V& point) const IMATH_NOEXCEPT; /// Return true if the given box is inside the box, false otherwise. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersects (const Box<V>& box) const IMATH_NOEXCEPT; /// Return the major axis of the box. The major axis is the dimension with /// the greatest difference between maximum and minimum. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 unsigned int majorAxis() const IMATH_NOEXCEPT; /// Return true if the box is empty, false otherwise. An empty box's /// minimum is greater than its maximum. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool isEmpty() const IMATH_NOEXCEPT; /// Return true if the box is larger than a single point, false otherwise. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool hasVolume() const IMATH_NOEXCEPT; /// Return true if the box contains all points, false otherwise. /// An infinite box has a mimimum of`V::baseTypeLowest()` /// and a maximum of `V::baseTypeMax()`. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool isInfinite() const IMATH_NOEXCEPT; /// @} }; //-------------------- // Convenient typedefs //-------------------- /// 2D box of base type `short`. typedef Box<V2s> Box2s; /// 2D box of base type `int`. typedef Box<V2i> Box2i; /// 2D box of base type `int64_t`. typedef Box<V2i64> Box2i64; /// 2D box of base type `float`. typedef Box<V2f> Box2f; /// 2D box of base type `double`. typedef Box<V2d> Box2d; /// 3D box of base type `short`. typedef Box<V3s> Box3s; /// 3D box of base type `int`. typedef Box<V3i> Box3i; /// 3D box of base type `int64_t`. typedef Box<V3i64> Box3i64; /// 3D box of base type `float`. typedef Box<V3f> Box3f; /// 3D box of base type `double`. typedef Box<V3d> Box3d; template <class V> IMATH_CONSTEXPR14 inline Box<V>::Box() IMATH_NOEXCEPT { makeEmpty(); } template <class V> IMATH_CONSTEXPR14 inline Box<V>::Box (const V& point) IMATH_NOEXCEPT { min = point; max = point; } template <class V> IMATH_CONSTEXPR14 inline Box<V>::Box (const V& minV, const V& maxV) IMATH_NOEXCEPT { min = minV; max = maxV; } template <class V> constexpr inline bool Box<V>::operator== (const Box<V>& src) const IMATH_NOEXCEPT { return (min == src.min && max == src.max); } template <class V> constexpr inline bool Box<V>::operator!= (const Box<V>& src) const IMATH_NOEXCEPT { return (min != src.min || max != src.max); } template <class V> inline void Box<V>::makeEmpty() IMATH_NOEXCEPT { min = V (V::baseTypeMax()); max = V (V::baseTypeLowest()); } template <class V> inline void Box<V>::makeInfinite() IMATH_NOEXCEPT { min = V (V::baseTypeLowest()); max = V (V::baseTypeMax()); } template <class V> inline void Box<V>::extendBy (const V& point) IMATH_NOEXCEPT { for (unsigned int i = 0; i < min.dimensions(); i++) { if (point[i] < min[i]) min[i] = point[i]; if (point[i] > max[i]) max[i] = point[i]; } } template <class V> inline void Box<V>::extendBy (const Box<V>& box) IMATH_NOEXCEPT { for (unsigned int i = 0; i < min.dimensions(); i++) { if (box.min[i] < min[i]) min[i] = box.min[i]; if (box.max[i] > max[i]) max[i] = box.max[i]; } } template <class V> IMATH_CONSTEXPR14 inline bool Box<V>::intersects (const V& point) const IMATH_NOEXCEPT { for (unsigned int i = 0; i < min.dimensions(); i++) { if (point[i] < min[i] || point[i] > max[i]) return false; } return true; } template <class V> IMATH_CONSTEXPR14 inline bool Box<V>::intersects (const Box<V>& box) const IMATH_NOEXCEPT { for (unsigned int i = 0; i < min.dimensions(); i++) { if (box.max[i] < min[i] || box.min[i] > max[i]) return false; } return true; } template <class V> IMATH_CONSTEXPR14 inline V Box<V>::size() const IMATH_NOEXCEPT { if (isEmpty()) return V (0); return max - min; } template <class V> constexpr inline V Box<V>::center() const IMATH_NOEXCEPT { return (max + min) / 2; } template <class V> IMATH_CONSTEXPR14 inline bool Box<V>::isEmpty() const IMATH_NOEXCEPT { for (unsigned int i = 0; i < min.dimensions(); i++) { if (max[i] < min[i]) return true; } return false; } template <class V> IMATH_CONSTEXPR14 inline bool Box<V>::isInfinite() const IMATH_NOEXCEPT { for (unsigned int i = 0; i < min.dimensions(); i++) { if (min[i] != V::baseTypeLowest() || max[i] != V::baseTypeMax()) return false; } return true; } template <class V> IMATH_CONSTEXPR14 inline bool Box<V>::hasVolume() const IMATH_NOEXCEPT { for (unsigned int i = 0; i < min.dimensions(); i++) { if (max[i] <= min[i]) return false; } return true; } template <class V> IMATH_CONSTEXPR14 inline unsigned int Box<V>::majorAxis() const IMATH_NOEXCEPT { unsigned int major = 0; V s = size(); for (unsigned int i = 1; i < min.dimensions(); i++) { if (s[i] > s[major]) major = i; } return major; } //------------------------------------------------------------------- // // Partial class specializations for Imath::Vec2<T> and Imath::Vec3<T> // //------------------------------------------------------------------- template <typename V> class Box; /// /// The Box<Vec2<T>> template represents a 2D bounding box defined by /// minimum and maximum values of type Vec2<T>. The min and max members are /// public. /// template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Box<Vec2<T>> { public: /// @{ /// @name Direct access to bounds /// The minimum value of the box. Vec2<T> min; /// The maximum value of the box. Vec2<T> max; /// @} /// @{ /// @name Constructors and Assignment /// Empty by default IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Box() IMATH_NOEXCEPT; /// Construct a bounding box that contains a single point. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Box (const Vec2<T>& point) IMATH_NOEXCEPT; /// Construct a bounding box with the given minimum and maximum points IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Box (const Vec2<T>& minT, const Vec2<T>& maxT) IMATH_NOEXCEPT; /// @} /// @{ /// @name Comparison /// Equality IMATH_HOSTDEVICE constexpr bool operator== (const Box<Vec2<T>>& src) const IMATH_NOEXCEPT; /// Inequality IMATH_HOSTDEVICE constexpr bool operator!= (const Box<Vec2<T>>& src) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Manipulation /// Set the Box to be empty. A Box is empty if the mimimum is /// greater than the maximum. makeEmpty() sets the mimimum to /// `numeric_limits<T>::max()' and the maximum to /// `numeric_limits<T>::lowest()`. IMATH_HOSTDEVICE void makeEmpty() IMATH_NOEXCEPT; /// Extend the Box to include the given point. IMATH_HOSTDEVICE void extendBy (const Vec2<T>& point) IMATH_NOEXCEPT; /// Extend the Box to include the given box. IMATH_HOSTDEVICE void extendBy (const Box<Vec2<T>>& box) IMATH_NOEXCEPT; /// Make the box include the entire range of T. IMATH_HOSTDEVICE void makeInfinite() IMATH_NOEXCEPT; /// @} /// @{ /// @name Query /// Return the size of the box. The size is of type `V`, defined as /// `(max-min)`. An empty box has a size of `V(0)`, i.e. 0 in each dimension. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec2<T> size() const IMATH_NOEXCEPT; /// Return the center of the box. The center is defined as /// `(max+min)/2`. The center of an empty box is undefined. IMATH_HOSTDEVICE constexpr Vec2<T> center() const IMATH_NOEXCEPT; /// Return true if the given point is inside the box, false otherwise. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersects (const Vec2<T>& point) const IMATH_NOEXCEPT; /// Return true if the given box is inside the box, false otherwise. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersects (const Box<Vec2<T>>& box) const IMATH_NOEXCEPT; /// Return the major axis of the box. The major axis is the dimension with /// the greatest difference between maximum and minimum. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 unsigned int majorAxis() const IMATH_NOEXCEPT; /// Return true if the box is empty, false otherwise. An empty box's /// minimum is greater than its maximum. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool isEmpty() const IMATH_NOEXCEPT; /// Return true if the box is larger than a single point, false otherwise. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool hasVolume() const IMATH_NOEXCEPT; /// Return true if the box contains all points, false otherwise. /// An infinite box has a mimimum of `V::baseTypeMin()` /// and a maximum of `V::baseTypeMax()`. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool isInfinite() const IMATH_NOEXCEPT; /// @} }; //---------------- // Implementation //---------------- template <class T> IMATH_CONSTEXPR14 inline Box<Vec2<T>>::Box() IMATH_NOEXCEPT { makeEmpty(); } template <class T> IMATH_CONSTEXPR14 inline Box<Vec2<T>>::Box (const Vec2<T>& point) IMATH_NOEXCEPT { min = point; max = point; } template <class T> IMATH_CONSTEXPR14 inline Box<Vec2<T>>::Box (const Vec2<T>& minT, const Vec2<T>& maxT) IMATH_NOEXCEPT { min = minT; max = maxT; } template <class T> constexpr inline bool Box<Vec2<T>>::operator== (const Box<Vec2<T>>& src) const IMATH_NOEXCEPT { return (min == src.min && max == src.max); } template <class T> constexpr inline bool Box<Vec2<T>>::operator!= (const Box<Vec2<T>>& src) const IMATH_NOEXCEPT { return (min != src.min || max != src.max); } template <class T> inline void Box<Vec2<T>>::makeEmpty() IMATH_NOEXCEPT { min = Vec2<T> (Vec2<T>::baseTypeMax()); max = Vec2<T> (Vec2<T>::baseTypeLowest()); } template <class T> inline void Box<Vec2<T>>::makeInfinite() IMATH_NOEXCEPT { min = Vec2<T> (Vec2<T>::baseTypeLowest()); max = Vec2<T> (Vec2<T>::baseTypeMax()); } template <class T> inline void Box<Vec2<T>>::extendBy (const Vec2<T>& point) IMATH_NOEXCEPT { if (point[0] < min[0]) min[0] = point[0]; if (point[0] > max[0]) max[0] = point[0]; if (point[1] < min[1]) min[1] = point[1]; if (point[1] > max[1]) max[1] = point[1]; } template <class T> inline void Box<Vec2<T>>::extendBy (const Box<Vec2<T>>& box) IMATH_NOEXCEPT { if (box.min[0] < min[0]) min[0] = box.min[0]; if (box.max[0] > max[0]) max[0] = box.max[0]; if (box.min[1] < min[1]) min[1] = box.min[1]; if (box.max[1] > max[1]) max[1] = box.max[1]; } template <class T> IMATH_CONSTEXPR14 inline bool Box<Vec2<T>>::intersects (const Vec2<T>& point) const IMATH_NOEXCEPT { if (point[0] < min[0] || point[0] > max[0] || point[1] < min[1] || point[1] > max[1]) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline bool Box<Vec2<T>>::intersects (const Box<Vec2<T>>& box) const IMATH_NOEXCEPT { if (box.max[0] < min[0] || box.min[0] > max[0] || box.max[1] < min[1] || box.min[1] > max[1]) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline Vec2<T> Box<Vec2<T>>::size() const IMATH_NOEXCEPT { if (isEmpty()) return Vec2<T> (0); return max - min; } template <class T> constexpr inline Vec2<T> Box<Vec2<T>>::center() const IMATH_NOEXCEPT { return (max + min) / 2; } template <class T> IMATH_CONSTEXPR14 inline bool Box<Vec2<T>>::isEmpty() const IMATH_NOEXCEPT { if (max[0] < min[0] || max[1] < min[1]) return true; return false; } template <class T> IMATH_CONSTEXPR14 inline bool Box<Vec2<T>>::isInfinite() const IMATH_NOEXCEPT { if (min[0] != std::numeric_limits<T>::lowest() || max[0] != std::numeric_limits<T>::max() || min[1] != std::numeric_limits<T>::lowest() || max[1] != std::numeric_limits<T>::max()) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline bool Box<Vec2<T>>::hasVolume() const IMATH_NOEXCEPT { if (max[0] <= min[0] || max[1] <= min[1]) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline unsigned int Box<Vec2<T>>::majorAxis() const IMATH_NOEXCEPT { unsigned int major = 0; Vec2<T> s = size(); if (s[1] > s[major]) major = 1; return major; } /// /// The Box<Vec3> template represents a 3D bounding box defined by /// minimum and maximum values of type Vec3. /// template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Box<Vec3<T>> { public: /// @{ /// @name Direct access to bounds /// The minimum value of the box. Vec3<T> min; /// The maximum value of the box. Vec3<T> max; /// @} /// @{ /// @name Constructors /// Empty by default IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Box() IMATH_NOEXCEPT; /// Construct a bounding box that contains a single point. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Box (const Vec3<T>& point) IMATH_NOEXCEPT; /// Construct a bounding box with the given minimum and maximum points IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Box (const Vec3<T>& minT, const Vec3<T>& maxT) IMATH_NOEXCEPT; /// @} /// Equality IMATH_HOSTDEVICE constexpr bool operator== (const Box<Vec3<T>>& src) const IMATH_NOEXCEPT; /// Inequality IMATH_HOSTDEVICE constexpr bool operator!= (const Box<Vec3<T>>& src) const IMATH_NOEXCEPT; /// Set the Box to be empty. A Box is empty if the mimimum is /// greater than the maximum. makeEmpty() sets the mimimum to /// `numeric_limits<T>::max()` and the maximum to /// `numeric_limits<T>::lowest()`. IMATH_HOSTDEVICE void makeEmpty() IMATH_NOEXCEPT; /// Extend the Box to include the given point. IMATH_HOSTDEVICE void extendBy (const Vec3<T>& point) IMATH_NOEXCEPT; /// Extend the Box to include the given box. IMATH_HOSTDEVICE void extendBy (const Box<Vec3<T>>& box) IMATH_NOEXCEPT; /// Make the box include the entire range of T. IMATH_HOSTDEVICE void makeInfinite() IMATH_NOEXCEPT; /// Return the size of the box. The size is of type `V`, defined as /// (max-min). An empty box has a size of V(0), i.e. 0 in each dimension. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3<T> size() const IMATH_NOEXCEPT; /// Return the center of the box. The center is defined as /// (max+min)/2. The center of an empty box is undefined. IMATH_HOSTDEVICE constexpr Vec3<T> center() const IMATH_NOEXCEPT; /// Return true if the given point is inside the box, false otherwise. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersects (const Vec3<T>& point) const IMATH_NOEXCEPT; /// Return true if the given box is inside the box, false otherwise. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersects (const Box<Vec3<T>>& box) const IMATH_NOEXCEPT; /// Return the major axis of the box. The major axis is the dimension with /// the greatest difference between maximum and minimum. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 unsigned int majorAxis() const IMATH_NOEXCEPT; /// Return true if the box is empty, false otherwise. An empty box's /// minimum is greater than its maximum. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool isEmpty() const IMATH_NOEXCEPT; /// Return true if the box is larger than a single point, false otherwise. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool hasVolume() const IMATH_NOEXCEPT; /// Return true if the box contains all points, false otherwise. /// An infinite box has a mimimum of`V::baseTypeMin()` /// and a maximum of `V::baseTypeMax()`. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool isInfinite() const IMATH_NOEXCEPT; }; //---------------- // Implementation //---------------- template <class T> IMATH_CONSTEXPR14 inline Box<Vec3<T>>::Box() IMATH_NOEXCEPT { makeEmpty(); } template <class T> IMATH_CONSTEXPR14 inline Box<Vec3<T>>::Box (const Vec3<T>& point) IMATH_NOEXCEPT { min = point; max = point; } template <class T> IMATH_CONSTEXPR14 inline Box<Vec3<T>>::Box (const Vec3<T>& minT, const Vec3<T>& maxT) IMATH_NOEXCEPT { min = minT; max = maxT; } template <class T> constexpr inline bool Box<Vec3<T>>::operator== (const Box<Vec3<T>>& src) const IMATH_NOEXCEPT { return (min == src.min && max == src.max); } template <class T> constexpr inline bool Box<Vec3<T>>::operator!= (const Box<Vec3<T>>& src) const IMATH_NOEXCEPT { return (min != src.min || max != src.max); } template <class T> inline void Box<Vec3<T>>::makeEmpty() IMATH_NOEXCEPT { min = Vec3<T> (Vec3<T>::baseTypeMax()); max = Vec3<T> (Vec3<T>::baseTypeLowest()); } template <class T> inline void Box<Vec3<T>>::makeInfinite() IMATH_NOEXCEPT { min = Vec3<T> (Vec3<T>::baseTypeLowest()); max = Vec3<T> (Vec3<T>::baseTypeMax()); } template <class T> inline void Box<Vec3<T>>::extendBy (const Vec3<T>& point) IMATH_NOEXCEPT { if (point[0] < min[0]) min[0] = point[0]; if (point[0] > max[0]) max[0] = point[0]; if (point[1] < min[1]) min[1] = point[1]; if (point[1] > max[1]) max[1] = point[1]; if (point[2] < min[2]) min[2] = point[2]; if (point[2] > max[2]) max[2] = point[2]; } template <class T> inline void Box<Vec3<T>>::extendBy (const Box<Vec3<T>>& box) IMATH_NOEXCEPT { if (box.min[0] < min[0]) min[0] = box.min[0]; if (box.max[0] > max[0]) max[0] = box.max[0]; if (box.min[1] < min[1]) min[1] = box.min[1]; if (box.max[1] > max[1]) max[1] = box.max[1]; if (box.min[2] < min[2]) min[2] = box.min[2]; if (box.max[2] > max[2]) max[2] = box.max[2]; } template <class T> IMATH_CONSTEXPR14 inline bool Box<Vec3<T>>::intersects (const Vec3<T>& point) const IMATH_NOEXCEPT { if (point[0] < min[0] || point[0] > max[0] || point[1] < min[1] || point[1] > max[1] || point[2] < min[2] || point[2] > max[2]) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline bool Box<Vec3<T>>::intersects (const Box<Vec3<T>>& box) const IMATH_NOEXCEPT { if (box.max[0] < min[0] || box.min[0] > max[0] || box.max[1] < min[1] || box.min[1] > max[1] || box.max[2] < min[2] || box.min[2] > max[2]) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline Vec3<T> Box<Vec3<T>>::size() const IMATH_NOEXCEPT { if (isEmpty()) return Vec3<T> (0); return max - min; } template <class T> constexpr inline Vec3<T> Box<Vec3<T>>::center() const IMATH_NOEXCEPT { return (max + min) / 2; } template <class T> IMATH_CONSTEXPR14 inline bool Box<Vec3<T>>::isEmpty() const IMATH_NOEXCEPT { if (max[0] < min[0] || max[1] < min[1] || max[2] < min[2]) return true; return false; } template <class T> IMATH_CONSTEXPR14 inline bool Box<Vec3<T>>::isInfinite() const IMATH_NOEXCEPT { if (min[0] != std::numeric_limits<T>::lowest() || max[0] != std::numeric_limits<T>::max() || min[1] != std::numeric_limits<T>::lowest() || max[1] != std::numeric_limits<T>::max() || min[2] != std::numeric_limits<T>::lowest() || max[2] != std::numeric_limits<T>::max()) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline bool Box<Vec3<T>>::hasVolume() const IMATH_NOEXCEPT { if (max[0] <= min[0] || max[1] <= min[1] || max[2] <= min[2]) return false; return true; } template <class T> IMATH_CONSTEXPR14 inline unsigned int Box<Vec3<T>>::majorAxis() const IMATH_NOEXCEPT { unsigned int major = 0; Vec3<T> s = size(); if (s[1] > s[major]) major = 1; if (s[2] > s[major]) major = 2; return major; } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHBOX_H ImathQuat.h 0000644 00000061773 15125213144 0006626 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // A quaternion // // "Quaternions came from Hamilton ... and have been an unmixed // evil to those who have touched them in any way. Vector is a // useless survival ... and has never been of the slightest use // to any creature." // // - Lord Kelvin // #ifndef INCLUDED_IMATHQUAT_H #define INCLUDED_IMATHQUAT_H #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathMatrix.h" #include <iostream> IMATH_INTERNAL_NAMESPACE_HEADER_ENTER #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER // Disable MS VC++ warnings about conversion from double to float # pragma warning(push) # pragma warning(disable : 4244) #endif /// /// The Quat class implements the quaternion numerical type -- you /// will probably want to use this class to represent orientations /// in R3 and to convert between various euler angle reps. You /// should probably use Imath::Euler<> for that. /// template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Quat { public: /// @{ /// @name Direct access to elements /// The real part T r; /// The imaginary vector Vec3<T> v; /// @} /// Element access: q[0] is the real part, (q[1],q[2],q[3]) is the /// imaginary part. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T& operator[] (int index) IMATH_NOEXCEPT; // as 4D vector /// Element access: q[0] is the real part, (q[1],q[2],q[3]) is the /// imaginary part. IMATH_HOSTDEVICE constexpr T operator[] (int index) const IMATH_NOEXCEPT; /// @{ /// @name Constructors /// Default constructor is the identity quat IMATH_HOSTDEVICE constexpr Quat() IMATH_NOEXCEPT; /// Copy constructor IMATH_HOSTDEVICE constexpr Quat (const Quat& q) IMATH_NOEXCEPT; /// Construct from a quaternion of a another base type template <class S> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat (const Quat<S>& q) IMATH_NOEXCEPT; /// Initialize with real part `s` and imaginary vector 1(i,j,k)` IMATH_HOSTDEVICE constexpr Quat (T s, T i, T j, T k) IMATH_NOEXCEPT; /// Initialize with real part `s` and imaginary vector `d` IMATH_HOSTDEVICE constexpr Quat (T s, Vec3<T> d) IMATH_NOEXCEPT; /// The identity quaternion IMATH_HOSTDEVICE constexpr static Quat<T> identity() IMATH_NOEXCEPT; /// Assignment IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>& operator= (const Quat<T>& q) IMATH_NOEXCEPT; /// Destructor ~Quat() IMATH_NOEXCEPT = default; /// @} /// @{ /// @name Basic Algebra /// /// Note that the operator return values are *NOT* normalized // /// Quaternion multiplication IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>& operator*= (const Quat<T>& q) IMATH_NOEXCEPT; /// Scalar multiplication: multiply both real and imaginary parts /// by the given scalar. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>& operator*= (T t) IMATH_NOEXCEPT; /// Quaterion division, using the inverse() IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>& operator/= (const Quat<T>& q) IMATH_NOEXCEPT; /// Scalar division: multiply both real and imaginary parts /// by the given scalar. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>& operator/= (T t) IMATH_NOEXCEPT; /// Quaternion addition IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>& operator+= (const Quat<T>& q) IMATH_NOEXCEPT; /// Quaternion subtraction IMATH_HOSTDEVICE IMATH_CONSTEXPR14 const Quat<T>& operator-= (const Quat<T>& q) IMATH_NOEXCEPT; /// Equality template <class S> IMATH_HOSTDEVICE constexpr bool operator== (const Quat<S>& q) const IMATH_NOEXCEPT; /// Inequality template <class S> IMATH_HOSTDEVICE constexpr bool operator!= (const Quat<S>& q) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Query /// Return the R4 length IMATH_HOSTDEVICE constexpr T length() const IMATH_NOEXCEPT; // in R4 /// Return the angle of the axis/angle representation IMATH_HOSTDEVICE constexpr T angle() const IMATH_NOEXCEPT; /// Return the axis of the axis/angle representation IMATH_HOSTDEVICE constexpr Vec3<T> axis() const IMATH_NOEXCEPT; /// Return a 3x3 rotation matrix IMATH_HOSTDEVICE constexpr Matrix33<T> toMatrix33() const IMATH_NOEXCEPT; /// Return a 4x4 rotation matrix IMATH_HOSTDEVICE constexpr Matrix44<T> toMatrix44() const IMATH_NOEXCEPT; /// Return the logarithm of the quaterion IMATH_HOSTDEVICE Quat<T> log() const IMATH_NOEXCEPT; /// Return the exponent of the quaterion IMATH_HOSTDEVICE Quat<T> exp() const IMATH_NOEXCEPT; /// @} /// @{ /// @name Utility Methods /// Invert in place: this = 1 / this. /// @return const reference to this. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T>& invert() IMATH_NOEXCEPT; /// Return 1/this, leaving this unchanged. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T> inverse() const IMATH_NOEXCEPT; /// Normalize in place /// @return const reference to this. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T>& normalize() IMATH_NOEXCEPT; /// Return a normalized quaternion, leaving this unmodified. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T> normalized() const IMATH_NOEXCEPT; /// Rotate the given point by the quaterion. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3<T> rotateVector (const Vec3<T>& original) const IMATH_NOEXCEPT; /// Return the Euclidean inner product. IMATH_HOSTDEVICE constexpr T euclideanInnerProduct (const Quat<T>& q) const IMATH_NOEXCEPT; /// Set the quaterion to be a rotation around the given axis by the /// given angle. /// @return const reference to this. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T>& setAxisAngle (const Vec3<T>& axis, T radians) IMATH_NOEXCEPT; /// Set the quaternion to be a rotation that transforms the /// direction vector `fromDirection` to `toDirection` /// @return const reference to this. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Quat<T>& setRotation (const Vec3<T>& fromDirection, const Vec3<T>& toDirection) IMATH_NOEXCEPT; /// @} /// The base type: In templates that accept a parameter `V`, you /// can refer to `T` as `V::BaseType` typedef T BaseType; private: IMATH_HOSTDEVICE void setRotationInternal (const Vec3<T>& f0, const Vec3<T>& t0, Quat<T>& q) IMATH_NOEXCEPT; }; template <class T> IMATH_CONSTEXPR14 Quat<T> slerp (const Quat<T>& q1, const Quat<T>& q2, T t) IMATH_NOEXCEPT; template <class T> IMATH_CONSTEXPR14 Quat<T> slerpShortestArc (const Quat<T>& q1, const Quat<T>& q2, T t) IMATH_NOEXCEPT; template <class T> IMATH_CONSTEXPR14 Quat<T> squad (const Quat<T>& q1, const Quat<T>& q2, const Quat<T>& qa, const Quat<T>& qb, T t) IMATH_NOEXCEPT; /// /// From advanced Animation and Rendering Techniques by Watt and Watt, /// Page 366: /// /// computing the inner quadrangle points (qa and qb) to guarantee /// tangent continuity. template <class T> void intermediate (const Quat<T>& q0, const Quat<T>& q1, const Quat<T>& q2, const Quat<T>& q3, Quat<T>& qa, Quat<T>& qb) IMATH_NOEXCEPT; template <class T> constexpr Matrix33<T> operator* (const Matrix33<T>& M, const Quat<T>& q) IMATH_NOEXCEPT; template <class T> constexpr Matrix33<T> operator* (const Quat<T>& q, const Matrix33<T>& M) IMATH_NOEXCEPT; template <class T> std::ostream& operator<< (std::ostream& o, const Quat<T>& q); template <class T> constexpr Quat<T> operator* (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT; template <class T> constexpr Quat<T> operator/ (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT; template <class T> constexpr Quat<T> operator/ (const Quat<T>& q, T t) IMATH_NOEXCEPT; template <class T> constexpr Quat<T> operator* (const Quat<T>& q, T t) IMATH_NOEXCEPT; template <class T> constexpr Quat<T> operator* (T t, const Quat<T>& q) IMATH_NOEXCEPT; template <class T> constexpr Quat<T> operator+ (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT; template <class T> constexpr Quat<T> operator- (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT; template <class T> constexpr Quat<T> operator~ (const Quat<T>& q) IMATH_NOEXCEPT; template <class T> constexpr Quat<T> operator- (const Quat<T>& q) IMATH_NOEXCEPT; template <class T> IMATH_CONSTEXPR14 Vec3<T> operator* (const Vec3<T>& v, const Quat<T>& q) IMATH_NOEXCEPT; /// Quaternion of type float typedef Quat<float> Quatf; /// Quaternion of type double typedef Quat<double> Quatd; //--------------- // Implementation //--------------- template <class T> constexpr inline Quat<T>::Quat() IMATH_NOEXCEPT : r (1), v (0, 0, 0) { // empty } template <class T> template <class S> IMATH_CONSTEXPR14 inline Quat<T>::Quat (const Quat<S>& q) IMATH_NOEXCEPT : r (q.r), v (q.v) { // empty } template <class T> constexpr inline Quat<T>::Quat (T s, T i, T j, T k) IMATH_NOEXCEPT : r (s), v (i, j, k) { // empty } template <class T> constexpr inline Quat<T>::Quat (T s, Vec3<T> d) IMATH_NOEXCEPT : r (s), v (d) { // empty } template <class T> constexpr inline Quat<T>::Quat (const Quat<T>& q) IMATH_NOEXCEPT : r (q.r), v (q.v) { // empty } template <class T> constexpr inline Quat<T> Quat<T>::identity() IMATH_NOEXCEPT { return Quat<T>(); } template <class T> IMATH_CONSTEXPR14 inline const Quat<T>& Quat<T>::operator= (const Quat<T>& q) IMATH_NOEXCEPT { r = q.r; v = q.v; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Quat<T>& Quat<T>::operator*= (const Quat<T>& q) IMATH_NOEXCEPT { T rtmp = r * q.r - (v ^ q.v); v = r * q.v + v * q.r + v % q.v; r = rtmp; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Quat<T>& Quat<T>::operator*= (T t) IMATH_NOEXCEPT { r *= t; v *= t; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Quat<T>& Quat<T>::operator/= (const Quat<T>& q) IMATH_NOEXCEPT { *this = *this * q.inverse(); return *this; } template <class T> IMATH_CONSTEXPR14 inline const Quat<T>& Quat<T>::operator/= (T t) IMATH_NOEXCEPT { r /= t; v /= t; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Quat<T>& Quat<T>::operator+= (const Quat<T>& q) IMATH_NOEXCEPT { r += q.r; v += q.v; return *this; } template <class T> IMATH_CONSTEXPR14 inline const Quat<T>& Quat<T>::operator-= (const Quat<T>& q) IMATH_NOEXCEPT { r -= q.r; v -= q.v; return *this; } template <class T> IMATH_CONSTEXPR14 inline T& Quat<T>::operator[] (int index) IMATH_NOEXCEPT { return index ? v[index - 1] : r; } template <class T> constexpr inline T Quat<T>::operator[] (int index) const IMATH_NOEXCEPT { return index ? v[index - 1] : r; } template <class T> template <class S> constexpr inline bool Quat<T>::operator== (const Quat<S>& q) const IMATH_NOEXCEPT { return r == q.r && v == q.v; } template <class T> template <class S> constexpr inline bool Quat<T>::operator!= (const Quat<S>& q) const IMATH_NOEXCEPT { return r != q.r || v != q.v; } /// 4D dot product template <class T> IMATH_HOSTDEVICE constexpr inline T operator^ (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT { return q1.r * q2.r + (q1.v ^ q2.v); } template <class T> constexpr inline T Quat<T>::length() const IMATH_NOEXCEPT { return std::sqrt (r * r + (v ^ v)); } template <class T> IMATH_CONSTEXPR14 inline Quat<T>& Quat<T>::normalize() IMATH_NOEXCEPT { if (T l = length()) { r /= l; v /= l; } else { r = 1; v = Vec3<T> (0); } return *this; } template <class T> IMATH_CONSTEXPR14 inline Quat<T> Quat<T>::normalized() const IMATH_NOEXCEPT { if (T l = length()) return Quat (r / l, v / l); return Quat(); } template <class T> IMATH_CONSTEXPR14 inline Quat<T> Quat<T>::inverse() const IMATH_NOEXCEPT { // // 1 Q* // - = ---- where Q* is conjugate (operator~) // Q Q* Q and (Q* Q) == Q ^ Q (4D dot) // T qdot = *this ^ *this; return Quat (r / qdot, -v / qdot); } template <class T> IMATH_CONSTEXPR14 inline Quat<T>& Quat<T>::invert() IMATH_NOEXCEPT { T qdot = (*this) ^ (*this); r /= qdot; v = -v / qdot; return *this; } template <class T> IMATH_CONSTEXPR14 inline Vec3<T> Quat<T>::rotateVector (const Vec3<T>& original) const IMATH_NOEXCEPT { // // Given a vector p and a quaternion q (aka this), // calculate p' = qpq* // // Assumes unit quaternions (because non-unit // quaternions cannot be used to rotate vectors // anyway). // Quat<T> vec (0, original); // temporarily promote grade of original Quat<T> inv (*this); inv.v *= -1; // unit multiplicative inverse Quat<T> result = *this * vec * inv; return result.v; } template <class T> constexpr inline T Quat<T>::euclideanInnerProduct (const Quat<T>& q) const IMATH_NOEXCEPT { return r * q.r + v.x * q.v.x + v.y * q.v.y + v.z * q.v.z; } /// /// Compute the angle between two quaternions, /// interpreting the quaternions as 4D vectors. template <class T> IMATH_CONSTEXPR14 inline T angle4D (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT { Quat<T> d = q1 - q2; T lengthD = std::sqrt (d ^ d); Quat<T> s = q1 + q2; T lengthS = std::sqrt (s ^ s); return 2 * std::atan2 (lengthD, lengthS); } /// /// Spherical linear interpolation. /// Assumes q1 and q2 are normalized and that q1 != -q2. /// /// This method does *not* interpolate along the shortest /// arc between q1 and q2. If you desire interpolation /// along the shortest arc, and q1^q2 is negative, then /// consider calling slerpShortestArc(), below, or flipping /// the second quaternion explicitly. /// /// The implementation of squad() depends on a slerp() /// that interpolates as is, without the automatic /// flipping. /// /// Don Hatch explains the method we use here on his /// web page, The Right Way to Calculate Stuff, at /// http://www.plunk.org/~hatch/rightway.php template <class T> IMATH_CONSTEXPR14 inline Quat<T> slerp (const Quat<T>& q1, const Quat<T>& q2, T t) IMATH_NOEXCEPT { T a = angle4D (q1, q2); T s = 1 - t; Quat<T> q = sinx_over_x (s * a) / sinx_over_x (a) * s * q1 + sinx_over_x (t * a) / sinx_over_x (a) * t * q2; return q.normalized(); } /// /// Spherical linear interpolation along the shortest /// arc from q1 to either q2 or -q2, whichever is closer. /// Assumes q1 and q2 are unit quaternions. template <class T> IMATH_CONSTEXPR14 inline Quat<T> slerpShortestArc (const Quat<T>& q1, const Quat<T>& q2, T t) IMATH_NOEXCEPT { if ((q1 ^ q2) >= 0) return slerp (q1, q2, t); else return slerp (q1, -q2, t); } /// /// Spherical Cubic Spline Interpolation - from Advanced Animation and /// Rendering Techniques by Watt and Watt, Page 366: /// /// A spherical curve is constructed using three spherical linear /// interpolations of a quadrangle of unit quaternions: q1, qa, qb, /// q2. Given a set of quaternion keys: q0, q1, q2, q3, this routine /// does the interpolation between q1 and q2 by constructing two /// intermediate quaternions: qa and qb. The qa and qb are computed by /// the intermediate function to guarantee the continuity of tangents /// across adjacent cubic segments. The qa represents in-tangent for /// q1 and the qb represents the out-tangent for q2. /// /// The q1 q2 is the cubic segment being interpolated. /// /// The q0 is from the previous adjacent segment and q3 is from the /// next adjacent segment. The q0 and q3 are used in computing qa and /// qb. template <class T> IMATH_CONSTEXPR14 inline Quat<T> spline (const Quat<T>& q0, const Quat<T>& q1, const Quat<T>& q2, const Quat<T>& q3, T t) IMATH_NOEXCEPT { Quat<T> qa = intermediate (q0, q1, q2); Quat<T> qb = intermediate (q1, q2, q3); Quat<T> result = squad (q1, qa, qb, q2, t); return result; } /// /// Spherical Quadrangle Interpolation - from Advanced Animation and /// Rendering Techniques by Watt and Watt, Page 366: /// /// It constructs a spherical cubic interpolation as a series of three /// spherical linear interpolations of a quadrangle of unit /// quaternions. template <class T> IMATH_CONSTEXPR14 inline Quat<T> squad (const Quat<T>& q1, const Quat<T>& qa, const Quat<T>& qb, const Quat<T>& q2, T t) IMATH_NOEXCEPT { Quat<T> r1 = slerp (q1, q2, t); Quat<T> r2 = slerp (qa, qb, t); Quat<T> result = slerp (r1, r2, 2 * t * (1 - t)); return result; } /// Compute the intermediate point between three quaternions `q0`, `q1`, /// and `q2`. template <class T> IMATH_CONSTEXPR14 inline Quat<T> intermediate (const Quat<T>& q0, const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT { Quat<T> q1inv = q1.inverse(); Quat<T> c1 = q1inv * q2; Quat<T> c2 = q1inv * q0; Quat<T> c3 = (T) (-0.25) * (c2.log() + c1.log()); Quat<T> qa = q1 * c3.exp(); qa.normalize(); return qa; } template <class T> inline Quat<T> Quat<T>::log() const IMATH_NOEXCEPT { // // For unit quaternion, from Advanced Animation and // Rendering Techniques by Watt and Watt, Page 366: // T theta = std::acos (std::min (r, (T) 1.0)); if (theta == 0) return Quat<T> (0, v); T sintheta = std::sin (theta); T k; if (std::abs(sintheta) < 1 && std::abs(theta) >= std::numeric_limits<T>::max() * std::abs(sintheta)) k = 1; else k = theta / sintheta; return Quat<T> ((T) 0, v.x * k, v.y * k, v.z * k); } template <class T> inline Quat<T> Quat<T>::exp() const IMATH_NOEXCEPT { // // For pure quaternion (zero scalar part): // from Advanced Animation and Rendering // Techniques by Watt and Watt, Page 366: // T theta = v.length(); T sintheta = std::sin (theta); T k; if (abs (theta) < 1 && abs (sintheta) >= std::numeric_limits<T>::max() * abs (theta)) k = 1; else k = sintheta / theta; T costheta = std::cos (theta); return Quat<T> (costheta, v.x * k, v.y * k, v.z * k); } template <class T> constexpr inline T Quat<T>::angle() const IMATH_NOEXCEPT { return 2 * std::atan2 (v.length(), r); } template <class T> constexpr inline Vec3<T> Quat<T>::axis() const IMATH_NOEXCEPT { return v.normalized(); } template <class T> IMATH_CONSTEXPR14 inline Quat<T>& Quat<T>::setAxisAngle (const Vec3<T>& axis, T radians) IMATH_NOEXCEPT { r = std::cos (radians / 2); v = axis.normalized() * std::sin (radians / 2); return *this; } template <class T> IMATH_CONSTEXPR14 inline Quat<T>& Quat<T>::setRotation (const Vec3<T>& from, const Vec3<T>& to) IMATH_NOEXCEPT { // // Create a quaternion that rotates vector from into vector to, // such that the rotation is around an axis that is the cross // product of from and to. // // This function calls function setRotationInternal(), which is // numerically accurate only for rotation angles that are not much // greater than pi/2. In order to achieve good accuracy for angles // greater than pi/2, we split large angles in half, and rotate in // two steps. // // // Normalize from and to, yielding f0 and t0. // Vec3<T> f0 = from.normalized(); Vec3<T> t0 = to.normalized(); if ((f0 ^ t0) >= 0) { // // The rotation angle is less than or equal to pi/2. // setRotationInternal (f0, t0, *this); } else { // // The angle is greater than pi/2. After computing h0, // which is halfway between f0 and t0, we rotate first // from f0 to h0, then from h0 to t0. // Vec3<T> h0 = (f0 + t0).normalized(); if ((h0 ^ h0) != 0) { setRotationInternal (f0, h0, *this); Quat<T> q; setRotationInternal (h0, t0, q); *this *= q; } else { // // f0 and t0 point in exactly opposite directions. // Pick an arbitrary axis that is orthogonal to f0, // and rotate by pi. // r = T (0); Vec3<T> f02 = f0 * f0; if (f02.x <= f02.y && f02.x <= f02.z) v = (f0 % Vec3<T> (1, 0, 0)).normalized(); else if (f02.y <= f02.z) v = (f0 % Vec3<T> (0, 1, 0)).normalized(); else v = (f0 % Vec3<T> (0, 0, 1)).normalized(); } } return *this; } template <class T> inline void Quat<T>::setRotationInternal (const Vec3<T>& f0, const Vec3<T>& t0, Quat<T>& q) IMATH_NOEXCEPT { // // The following is equivalent to setAxisAngle(n,2*phi), // where the rotation axis, n, is orthogonal to the f0 and // t0 vectors, and 2*phi is the angle between f0 and t0. // // This function is called by setRotation(), above; it assumes // that f0 and t0 are normalized and that the angle between // them is not much greater than pi/2. This function becomes // numerically inaccurate if f0 and t0 point into nearly // opposite directions. // // // Find a normalized vector, h0, that is halfway between f0 and t0. // The angle between f0 and h0 is phi. // Vec3<T> h0 = (f0 + t0).normalized(); // // Store the rotation axis and rotation angle. // q.r = f0 ^ h0; // f0 ^ h0 == cos (phi) q.v = f0 % h0; // (f0 % h0).length() == sin (phi) } template <class T> constexpr inline Matrix33<T> Quat<T>::toMatrix33() const IMATH_NOEXCEPT { return Matrix33<T> (1 - 2 * (v.y * v.y + v.z * v.z), 2 * (v.x * v.y + v.z * r), 2 * (v.z * v.x - v.y * r), 2 * (v.x * v.y - v.z * r), 1 - 2 * (v.z * v.z + v.x * v.x), 2 * (v.y * v.z + v.x * r), 2 * (v.z * v.x + v.y * r), 2 * (v.y * v.z - v.x * r), 1 - 2 * (v.y * v.y + v.x * v.x)); } template <class T> constexpr inline Matrix44<T> Quat<T>::toMatrix44() const IMATH_NOEXCEPT { return Matrix44<T> (1 - 2 * (v.y * v.y + v.z * v.z), 2 * (v.x * v.y + v.z * r), 2 * (v.z * v.x - v.y * r), 0, 2 * (v.x * v.y - v.z * r), 1 - 2 * (v.z * v.z + v.x * v.x), 2 * (v.y * v.z + v.x * r), 0, 2 * (v.z * v.x + v.y * r), 2 * (v.y * v.z - v.x * r), 1 - 2 * (v.y * v.y + v.x * v.x), 0, 0, 0, 0, 1); } /// Transform the quaternion by the matrix /// @return M * q template <class T> constexpr inline Matrix33<T> operator* (const Matrix33<T>& M, const Quat<T>& q) IMATH_NOEXCEPT { return M * q.toMatrix33(); } /// Transform the matrix by the quaterion: /// @return q * M template <class T> constexpr inline Matrix33<T> operator* (const Quat<T>& q, const Matrix33<T>& M) IMATH_NOEXCEPT { return q.toMatrix33() * M; } /// Stream output as "(r x y z)" template <class T> std::ostream& operator<< (std::ostream& o, const Quat<T>& q) { return o << "(" << q.r << " " << q.v.x << " " << q.v.y << " " << q.v.z << ")"; } /// Quaterion multiplication template <class T> constexpr inline Quat<T> operator* (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT { return Quat<T> (q1.r * q2.r - (q1.v ^ q2.v), q1.r * q2.v + q1.v * q2.r + q1.v % q2.v); } /// Quaterion division template <class T> constexpr inline Quat<T> operator/ (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT { return q1 * q2.inverse(); } /// Quaterion division template <class T> constexpr inline Quat<T> operator/ (const Quat<T>& q, T t) IMATH_NOEXCEPT { return Quat<T> (q.r / t, q.v / t); } /// Quaterion*scalar multiplication /// @return q * t template <class T> constexpr inline Quat<T> operator* (const Quat<T>& q, T t) IMATH_NOEXCEPT { return Quat<T> (q.r * t, q.v * t); } /// Quaterion*scalar multiplication /// @return q * t template <class T> constexpr inline Quat<T> operator* (T t, const Quat<T>& q) IMATH_NOEXCEPT { return Quat<T> (q.r * t, q.v * t); } /// Quaterion addition template <class T> constexpr inline Quat<T> operator+ (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT { return Quat<T> (q1.r + q2.r, q1.v + q2.v); } /// Quaterion subtraction template <class T> constexpr inline Quat<T> operator- (const Quat<T>& q1, const Quat<T>& q2) IMATH_NOEXCEPT { return Quat<T> (q1.r - q2.r, q1.v - q2.v); } /// Compute the conjugate template <class T> constexpr inline Quat<T> operator~ (const Quat<T>& q) IMATH_NOEXCEPT { return Quat<T> (q.r, -q.v); } /// Negate the quaterion template <class T> constexpr inline Quat<T> operator- (const Quat<T>& q) IMATH_NOEXCEPT { return Quat<T> (-q.r, -q.v); } /// Quaterion*vector multiplcation /// @return v * q template <class T> IMATH_CONSTEXPR14 inline Vec3<T> operator* (const Vec3<T>& v, const Quat<T>& q) IMATH_NOEXCEPT { Vec3<T> a = q.v % v; Vec3<T> b = q.v % a; return v + T (2) * (q.r * a + b); } #if (defined _WIN32 || defined _WIN64) && defined _MSC_VER # pragma warning(pop) #endif IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHQUAT_H PyImathTask.h 0000644 00000001650 15125213144 0007113 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathTask_h_ #define _PyImathTask_h_ #include <cstddef> #include "PyImathExport.h" namespace PyImath { struct Task { PYIMATH_EXPORT virtual ~Task() {} PYIMATH_EXPORT virtual void execute(size_t start,size_t end) = 0; PYIMATH_EXPORT virtual void execute(size_t start,size_t end, int tid) {execute(start,end);} }; struct WorkerPool { PYIMATH_EXPORT virtual ~WorkerPool() {} PYIMATH_EXPORT virtual size_t workers() const = 0; PYIMATH_EXPORT virtual void dispatch(Task &task,size_t length) = 0; PYIMATH_EXPORT virtual bool inWorkerThread() const = 0; PYIMATH_EXPORT static WorkerPool *currentPool(); PYIMATH_EXPORT static void setCurrentPool(WorkerPool *pool); }; PYIMATH_EXPORT void dispatchTask(Task &task,size_t length); PYIMATH_EXPORT size_t workers(); } #endif PyImathColor4ArrayImpl.h 0000644 00000003154 15125213144 0011175 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathColor4ArrayImpl_h_ #define _PyImathColor4ArrayImpl_h_ // // This .C file was turned into a header file so that instantiations // of the various V3* types can be spread across multiple files in // order to work around MSVC limitations. // #include <Python.h> #include <boost/python.hpp> #include <boost/python/make_constructor.hpp> #include <boost/format.hpp> #include "PyImath.h" #include "PyImathMathExc.h" #include "PyImathDecorators.h" namespace PyImath { using namespace boost::python; using namespace IMATH_NAMESPACE; // XXX fixme - template this // really this should get generated automatically... template <class T,int index> static FixedArray<T> Color4Array_get(FixedArray<IMATH_NAMESPACE::Color4<T> > &ca) { return FixedArray<T>(&(ca.unchecked_index(0)[index]), ca.len(),4*ca.stride(),ca.handle(),ca.writable()); } // Currently we are only exposing the RGBA components. template <class T> class_<FixedArray<IMATH_NAMESPACE::Color4<T> > > register_Color4Array() { class_<FixedArray<IMATH_NAMESPACE::Color4<T> > > color4Array_class = FixedArray<IMATH_NAMESPACE::Color4<T> >::register_("Fixed length array of IMATH_NAMESPACE::Color4"); color4Array_class .add_property("r",&Color4Array_get<T,0>) .add_property("g",&Color4Array_get<T,1>) .add_property("b",&Color4Array_get<T,2>) .add_property("a",&Color4Array_get<T,3>) ; return color4Array_class; } } // namespace PyImath #endif // _PyImathColor4ArrayImpl_h_ PyImathShear.h 0000644 00000007367 15125213144 0007266 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathShear_h_ #define _PyImathShear_h_ #include <Python.h> #include <boost/python.hpp> #include <ImathShear.h> namespace PyImath { template <class T> boost::python::class_<IMATH_NAMESPACE::Shear6<T> > register_Shear(); // // Other code in the Zeno code base assumes the existance of a class with the // same name as the Imath class, and with static functions wrap() and // convert() to produce a PyImath object from an Imath object and vice-versa, // respectively. The class Boost generates from the Imath class does not // have these properties, so we define a companion class here. // The template argument, T, is the element type (e.g.,float, double). template <class T> class S6 { public: static PyObject * wrap (const IMATH_NAMESPACE::Shear6<T> &s); static int convert (PyObject *p, IMATH_NAMESPACE::Shear6<T> *s); }; template <class T> PyObject * S6<T>::wrap (const IMATH_NAMESPACE::Shear6<T> &s) { typename boost::python::return_by_value::apply < IMATH_NAMESPACE::Shear6<T> >::type converter; PyObject *p = converter (s); return p; } template <class T> int S6<T>::convert (PyObject *p, IMATH_NAMESPACE::Shear6<T> *s) { boost::python::extract <IMATH_NAMESPACE::Shear6f> extractorShear6f (p); if (extractorShear6f.check()) { IMATH_NAMESPACE::Shear6f s6f = extractorShear6f(); float xy, xz, yz, yx, zx, zy; s6f.getValue (xy, xz, yz, yx, zx, zy); s->setValue(T(xy), T(xz), T(yz), T(yx), T(zx), T(zy)); return 1; } boost::python::extract <IMATH_NAMESPACE::Shear6d> extractorShear6d (p); if (extractorShear6d.check()) { IMATH_NAMESPACE::Shear6d s6d = extractorShear6d(); double xy, xz, yz, yx, zx, zy; s6d.getValue (xy, xz, yz, yx, zx, zy); s->setValue(T(xy), T(xz), T(yz), T(yx), T(zx), T(zy)); return 1; } boost::python::extract <boost::python::tuple> extractorTuple (p); if (extractorTuple.check()) { boost::python::tuple t = extractorTuple(); if (t.attr ("__len__") () == 3) { double xy = boost::python::extract <double> (t[0]); double xz = boost::python::extract <double> (t[1]); double yz = boost::python::extract <double> (t[2]); s->setValue (T(xy), T(xz), T(yz), T(0), T(0), T(0)); return 1; } else if (t.attr ("__len__") () == 6) { double xy = boost::python::extract <double> (t[0]); double xz = boost::python::extract <double> (t[1]); double yz = boost::python::extract <double> (t[2]); double yx = boost::python::extract <double> (t[3]); double zx = boost::python::extract <double> (t[4]); double zy = boost::python::extract <double> (t[5]); s->setValue (T(xy), T(xz), T(yz), T(yx), T(zx), T(zy)); return 1; } } boost::python::extract <IMATH_NAMESPACE::V3i> extractorV3i (p); if (extractorV3i.check()) { IMATH_NAMESPACE::V3i v3i = extractorV3i(); s->setValue (T(v3i[0]), T(v3i[1]), T(v3i[2]), T(0), T(0), T(0)); return 1; } boost::python::extract <IMATH_NAMESPACE::V3f> extractorV3f (p); if (extractorV3f.check()) { IMATH_NAMESPACE::V3f v3f = extractorV3f(); s->setValue (T(v3f[0]), T(v3f[1]), T(v3f[2]), T(0), T(0), T(0)); return 1; } boost::python::extract <IMATH_NAMESPACE::V3d> extractorV3d (p); if (extractorV3d.check()) { IMATH_NAMESPACE::V3d v3d = extractorV3d(); s->setValue (T(v3d[0]), T(v3d[1]), T(v3d[2]), T(0), T(0), T(0)); return 1; } return 0; } typedef S6<float> Shear6f; typedef S6<double> Shear6d; } #endif PyImathOperators.h 0000644 00000024000 15125213144 0010161 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathOperators_h_ #define _PyImathOperators_h_ #include "PyImathFixedArray.h" #include "PyImathAutovectorize.h" namespace PyImath { template <class T1, class T2=T1, class Ret=T1> struct op_add { static inline Ret apply(const T1 &a, const T2 &b) { return a+b; } }; template <class T1, class T2=T1, class Ret=T1> struct op_sub { static inline Ret apply(const T1 &a, const T2 &b) { return a-b; } }; template <class T1, class T2=T1, class Ret=T1> struct op_rsub { static inline Ret apply(const T1 &a, const T2 &b) { return b-a; } }; template <class T1, class T2=T1, class Ret=T1> struct op_mul { static inline Ret apply(const T1 &a, const T2 &b) { return a*b; } }; template <class T1, class T2=T1, class Ret=T1> struct op_div { static inline Ret apply(const T1 &a, const T2 &b) { return a/b; } }; template <class T1, class T2=T1, class Ret=T1> struct op_mod { static inline Ret apply(const T1 &a, const T2 &b) { return a%b; } }; template <class T1, class T2=T1, class Ret=T1> struct op_pow { static inline Ret apply(const T1 &a, const T2 &b) { return std::pow(a,b); } }; template <class T1, class T2=T1, class Ret=T1> struct op_rpow { static inline Ret apply(const T1 &a, const T2 &b) { return std::pow(b,a); } }; template <class T1, class Ret=T1> struct op_neg { static inline Ret apply(const T1 &a) { return -a; } }; template <class T1, class Ret=T1> struct op_abs { static inline Ret apply(const T1 &a) { return std::abs(a); } }; template <class T1, class Ret=T1> struct op_inverse { static inline Ret apply(const T1 &a) { return ~a; } }; template <class T1, class T2=T1, class Ret=T1> struct op_lshift { static inline Ret apply(const T1 &a, const T2 &b) { return a << b; } }; template <class T1, class T2=T1, class Ret=T1> struct op_rshift { static inline Ret apply(const T1 &a, const T2 &b) { return a >> b; } }; template <class T1, class T2=T1, class Ret=T1> struct op_bitand { static inline Ret apply(const T1 &a, const T2 &b) { return a & b; } }; template <class T1, class T2=T1, class Ret=T1> struct op_xor { static inline Ret apply(const T1 &a, const T2 &b) { return a ^ b; } }; template <class T1, class T2=T1, class Ret=T1> struct op_bitor { static inline Ret apply(const T1 &a, const T2 &b) { return a | b; } }; template <class T1, class T2=T1> struct op_iadd { static inline void apply(T1 &a, const T2 &b) { a += b; } }; template <class T1, class T2=T1> struct op_isub { static inline void apply(T1 &a, const T2 &b) { a -= b; } }; template <class T1, class T2=T1> struct op_imul { static inline void apply(T1 &a, const T2 &b) { a *= b; } }; template <class T1, class T2=T1> struct op_idiv { static inline void apply(T1 &a, const T2 &b) { a /= b; } }; template <class T1, class T2=T1> struct op_imod { static inline void apply(T1 &a, const T2 &b) { a %= b; } }; template <class T1, class T2=T1> struct op_ipow { static inline void apply(T1 &a, const T2 &b) { a = std::pow(a,b); } }; template <class T1, class T2=T1> struct op_ilshift { static inline void apply(T1 &a, const T2 &b) { a <<= b; } }; template <class T1, class T2=T1> struct op_irshift { static inline void apply(T1 &a, const T2 &b) { a >>= b; } }; template <class T1, class T2=T1> struct op_ixor { static inline void apply(T1 &a, const T2 &b) { a ^= b; } }; template <class T1, class T2=T1> struct op_ibitand { static inline void apply(T1 &a, const T2 &b) { a &= b; } }; template <class T1, class T2=T1> struct op_ibitor { static inline void apply(T1 &a, const T2 &b) { a |= b; } }; // the logical function return values default to 'int' for use // as mask arrays. template <class T1, class T2=T1, class Ret=int> struct op_lt { static inline Ret apply(const T1 &a, const T2 &b) { return a < b; } }; template <class T1, class T2=T1, class Ret=int> struct op_gt { static inline Ret apply(const T1 &a, const T2 &b) { return a > b; } }; template <class T1, class T2=T1, class Ret=int> struct op_le { static inline Ret apply(const T1 &a, const T2 &b) { return a <= b; } }; template <class T1, class T2=T1, class Ret=int> struct op_ge { static inline Ret apply(const T1 &a, const T2 &b) { return a >= b; } }; template <class T1, class T2=T1, class Ret=int> struct op_eq { static inline Ret apply(const T1 &a, const T2 &b) { return a == b; } }; template <class T1, class T2=T1, class Ret=int> struct op_ne { static inline Ret apply(const T1 &a, const T2 &b) { return a != b; } }; template <class T> static T fa_reduce(const FixedArray<T> &a) { T tmp(T(0)); // should use default construction but V3f doens't initialize size_t len = a.len(); for (size_t i=0; i < len; ++i) tmp += a[i]; return tmp; } template <class T> static T fa_min(const FixedArray<T> &a) { T tmp(T(0)); size_t len = a.len(); if (len > 0) tmp = a[0]; for (size_t i=1; i < len; ++i) if (a[i] < tmp) tmp = a[i]; return tmp; } template <class T> static T fa_max(const FixedArray<T> &a) { T tmp(T(0)); size_t len = a.len(); if (len > 0) tmp = a[0]; for (size_t i=1; i < len; ++i) if (a[i] > tmp) tmp = a[i]; return tmp; } template <class T> static void add_arithmetic_math_functions(boost::python::class_<FixedArray<T> > &c) { using boost::mpl::true_; using boost::mpl::false_; generate_member_bindings<op_add<T>, true_ >(c,"__add__", "self+x", boost::python::args("x")); generate_member_bindings<op_add<T>, false_>(c,"__radd__","x+self", boost::python::args("x")); generate_member_bindings<op_sub<T>, true_ >(c,"__sub__", "self-x", boost::python::args("x")); generate_member_bindings<op_rsub<T>,false_>(c,"__rsub__","x-self", boost::python::args("x")); generate_member_bindings<op_mul<T>, true_ >(c,"__mul__", "self*x", boost::python::args("x")); generate_member_bindings<op_mul<T>, false_>(c,"__rmul__","x*self", boost::python::args("x")); generate_member_bindings<op_div<T>, true_ >(c,"__div__", "self/x", boost::python::args("x")); generate_member_bindings<op_div<T>, true_ >(c,"__truediv__", "self/x", boost::python::args("x")); generate_member_bindings<op_neg<T> >(c,"__neg__", "-x"); generate_member_bindings<op_iadd<T>,true_ >(c,"__iadd__","self+=x",boost::python::args("x")); generate_member_bindings<op_isub<T>,true_ >(c,"__isub__","self-=x",boost::python::args("x")); generate_member_bindings<op_imul<T>,true_ >(c,"__imul__","self*=x",boost::python::args("x")); generate_member_bindings<op_idiv<T>,true_ >(c,"__idiv__","self/=x",boost::python::args("x")); generate_member_bindings<op_idiv<T>,true_ >(c,"__itruediv__","self/=x",boost::python::args("x")); c.def("reduce",&fa_reduce<T>); } template <class T> static void add_reduction_functions(boost::python::class_<FixedArray<T> > &c) { c.def("min",&fa_min<T>); c.def("max",&fa_max<T>); } template <class T> static void add_pow_math_functions(boost::python::class_<FixedArray<T> > &c) { using boost::mpl::true_; using boost::mpl::false_; generate_member_bindings<op_pow<T>, true_ >(c,"__pow__", "self**x", boost::python::args("x")); generate_member_bindings<op_rpow<T>,false_>(c,"__rpow__","x**self", boost::python::args("x")); generate_member_bindings<op_ipow<T>,true_ >(c,"__ipow__","x**=self",boost::python::args("x")); } template <class T> static void add_mod_math_functions(boost::python::class_<FixedArray<T> > &c) { using boost::mpl::true_; generate_member_bindings<op_mod<T>, true_>(c,"__mod__", "self%x", boost::python::args("x")); generate_member_bindings<op_imod<T>,true_>(c,"__imod__","self%=x",boost::python::args("x")); } template <class T> static void add_shift_math_functions(boost::python::class_<FixedArray<T> > &c) { using boost::mpl::true_; generate_member_bindings<op_lshift<T>, true_>(c,"__lshift__", "self<<x", boost::python::args("x")); generate_member_bindings<op_ilshift<T>,true_>(c,"__ilshift__","self<<=x",boost::python::args("x")); generate_member_bindings<op_rshift<T>, true_>(c,"__rshift__", "self>>x", boost::python::args("x")); generate_member_bindings<op_irshift<T>,true_>(c,"__irshift__","self>>=x",boost::python::args("x")); } template <class T> static void add_bitwise_math_functions(boost::python::class_<FixedArray<T> > &c) { using boost::mpl::true_; generate_member_bindings<op_bitand<T>, true_>(c,"__and__", "self&x", boost::python::args("x")); generate_member_bindings<op_ibitand<T>,true_>(c,"__iand__","self&=x",boost::python::args("x")); generate_member_bindings<op_bitor<T>, true_>(c,"__or__", "self|x", boost::python::args("x")); generate_member_bindings<op_ibitor<T>, true_>(c,"__ior__", "self|=x",boost::python::args("x")); generate_member_bindings<op_xor<T>, true_>(c,"__xor__", "self^x", boost::python::args("x")); generate_member_bindings<op_ixor<T>, true_>(c,"__ixor__","self^=x",boost::python::args("x")); } template <class T> static void add_comparison_functions(boost::python::class_<FixedArray<T> > &c) { using boost::mpl::true_; generate_member_bindings<op_eq<T>, true_>(c,"__eq__","self==x",boost::python::args("x")); generate_member_bindings<op_ne<T>, true_>(c,"__ne__","self!=x",boost::python::args("x")); } template <class T> static void add_ordered_comparison_functions(boost::python::class_<FixedArray<T> > &c) { using boost::mpl::true_; generate_member_bindings<op_lt<T>, true_>(c,"__lt__","self<x", boost::python::args("x")); generate_member_bindings<op_le<T>, true_>(c,"__le__","self<=x",boost::python::args("x")); generate_member_bindings<op_gt<T>, true_>(c,"__gt__","self>x", boost::python::args("x")); generate_member_bindings<op_ge<T>, true_>(c,"__ge__","self>=x",boost::python::args("x")); } template <class S,class T> static void add_explicit_construction_from_type(boost::python::class_<FixedArray<T> > &c) { using namespace boost::python; c.def(init<FixedArray<S> >("copy contents of other array into this one")); } } #endif // _PyImathOperators_h_ halfFunction.h 0000644 00000007040 15125213144 0007334 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // //--------------------------------------------------------------------------- // // halfFunction<T> -- a class for fast evaluation // of half --> T functions // // The constructor for a halfFunction object, // // halfFunction (function, // domainMin, domainMax, // defaultValue, // posInfValue, negInfValue, // nanValue); // // evaluates the function for all finite half values in the interval // [domainMin, domainMax], and stores the results in a lookup table. // For finite half values that are not in [domainMin, domainMax], the // constructor stores defaultValue in the table. For positive infinity, // negative infinity and NANs, posInfValue, negInfValue and nanValue // are stored in the table. // // The tabulated function can then be evaluated quickly for arbitrary // half values by calling the the halfFunction object's operator() // method. // // Example: // // #include <math.h> // #include <halfFunction.h> // // halfFunction<half> hsin (sin); // // halfFunction<half> hsqrt (sqrt, // function // 0, HALF_MAX, // domain // half::qNan(), // sqrt(x) for x < 0 // half::posInf(), // sqrt(+inf) // half::qNan(), // sqrt(-inf) // half::qNan()); // sqrt(nan) // // half x = hsin (1); // half y = hsqrt (3.5); // //--------------------------------------------------------------------------- #ifndef _HALF_FUNCTION_H_ #define _HALF_FUNCTION_H_ /// @cond Doxygen_Suppress #include "half.h" #include "ImathConfig.h" #ifndef IMATH_HAVE_LARGE_STACK # include <string.h> // need this for memset #else #endif #include <float.h> template <class T> class halfFunction { public: //------------ // Constructor //------------ template <class Function> halfFunction (Function f, half domainMin = -HALF_MAX, half domainMax = HALF_MAX, T defaultValue = 0, T posInfValue = 0, T negInfValue = 0, T nanValue = 0); #ifndef IMATH_HAVE_LARGE_STACK ~halfFunction() { delete[] _lut; } halfFunction (const halfFunction&) = delete; halfFunction& operator= (const halfFunction&) = delete; halfFunction (halfFunction&&) = delete; halfFunction& operator= (halfFunction&&) = delete; #endif //----------- // Evaluation //----------- T operator() (half x) const; private: #ifdef IMATH_HAVE_LARGE_STACK T _lut[1 << 16]; #else T* _lut; #endif }; //--------------- // Implementation //--------------- template <class T> template <class Function> halfFunction<T>::halfFunction (Function f, half domainMin, half domainMax, T defaultValue, T posInfValue, T negInfValue, T nanValue) { #ifndef IMATH_HAVE_LARGE_STACK _lut = new T[1 << 16]; #endif for (int i = 0; i < (1 << 16); i++) { half x; x.setBits (i); if (x.isNan()) _lut[i] = nanValue; else if (x.isInfinity()) _lut[i] = x.isNegative() ? negInfValue : posInfValue; else if (x < domainMin || x > domainMax) _lut[i] = defaultValue; else _lut[i] = f (x); } } template <class T> inline T halfFunction<T>::operator() (half x) const { return _lut[x.bits()]; } /// @endcond #endif ImathExport.h 0000644 00000004124 15125213144 0007160 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // #ifndef INCLUDED_IMATHEXPORT_H #define INCLUDED_IMATHEXPORT_H #include "ImathConfig.h" /// \defgroup ExportMacros Macros to manage symbol visibility /// /// There is more information about the motivation for these macros /// documented in the OpenEXR source tree /// (https://github.com/AcademySoftwareFoundation/openexr) under /// docs/SymbolVisibility.md /// /// Imath only needs a couple of the possible macros outlined in the /// above document, and due to it largely being inline only, does not /// have much to do. /// /// @{ #if defined(IMATH_DLL) // when building Imath as a DLL for Windows, we have to control the // typical DLL export / import things. Luckily, the typeinfo is all // automatic there, so only have to deal with symbols, except Windows // has some weirdness with DLLs and extern const, so we have to // provide a macro to handle that. # if defined(IMATH_EXPORTS) # define IMATH_EXPORT __declspec(dllexport) # define IMATH_EXPORT_CONST extern __declspec(dllexport) # else # define IMATH_EXPORT __declspec(dllimport) # define IMATH_EXPORT_CONST extern __declspec(dllimport) # endif // DLLs don't support these types of visibility controls, just leave them as empty # define IMATH_EXPORT_TYPE # define IMATH_EXPORT_ENUM # define IMATH_EXPORT_TEMPLATE_TYPE #else # ifdef IMATH_PUBLIC_SYMBOL_ATTRIBUTE # define IMATH_EXPORT IMATH_PUBLIC_SYMBOL_ATTRIBUTE # define IMATH_EXPORT_CONST extern const IMATH_PUBLIC_SYMBOL_ATTRIBUTE # else # define IMATH_EXPORT # define IMATH_EXPORT_CONST extern const # endif # ifdef IMATH_PUBLIC_TYPE_VISIBILITY_ATTRIBUTE # define IMATH_EXPORT_ENUM IMATH_PUBLIC_TYPE_VISIBILITY_ATTRIBUTE # define IMATH_EXPORT_TEMPLATE_TYPE IMATH_PUBLIC_TYPE_VISIBILITY_ATTRIBUTE # define IMATH_EXPORT_TYPE IMATH_PUBLIC_TYPE_VISIBILITY_ATTRIBUTE # else # define IMATH_EXPORT_ENUM # define IMATH_EXPORT_TEMPLATE_TYPE IMATH_EXPORT # define IMATH_EXPORT_TYPE IMATH_EXPORT # endif #endif // IMATH_DLL /// @} #endif // INCLUDED_IMATHEXPORT_H ImathPlane.h 0000644 00000015366 15125213144 0006750 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // A 3D plane class template // #ifndef INCLUDED_IMATHPLANE_H #define INCLUDED_IMATHPLANE_H #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathLine.h" #include "ImathVec.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// /// The `Plane3` class represents a half space in 3D, so the normal /// may point either towards or away from origin. The plane `P` can /// be represented by Plane3 as either `p` or `-p` corresponding to /// the two half-spaces on either side of the plane. Any function /// which computes a distance will return either negative or positive /// values for the distance indicating which half-space the point is /// in. Note that reflection, and intersection functions will operate /// as expected. template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Plane3 { public: /// @{ /// @name Direct access to member fields /// The normal to the plane Vec3<T> normal; /// The distance from the origin to the plane T distance; /// @} /// @{ /// @name Constructors /// Uninitialized by default IMATH_HOSTDEVICE Plane3() IMATH_NOEXCEPT {} /// Initialize with a normal and distance IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Plane3 (const Vec3<T>& normal, T distance) IMATH_NOEXCEPT; /// Initialize with a point and a normal IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Plane3 (const Vec3<T>& point, const Vec3<T>& normal) IMATH_NOEXCEPT; /// Initialize with three points IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Plane3 (const Vec3<T>& point1, const Vec3<T>& point2, const Vec3<T>& point3) IMATH_NOEXCEPT; /// @} /// @{ /// @name Manipulation /// Set via a given normal and distance IMATH_HOSTDEVICE void set (const Vec3<T>& normal, T distance) IMATH_NOEXCEPT; /// Set via a given point and normal IMATH_HOSTDEVICE void set (const Vec3<T>& point, const Vec3<T>& normal) IMATH_NOEXCEPT; /// Set via three points IMATH_HOSTDEVICE void set (const Vec3<T>& point1, const Vec3<T>& point2, const Vec3<T>& point3) IMATH_NOEXCEPT; /// @} /// @{ /// @name Utility Methods /// Determine if a line intersects the plane. /// @param line The line /// @param[out] intersection The point of intersection /// @return True if the line intersects the plane. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersect (const Line3<T>& line, Vec3<T>& intersection) const IMATH_NOEXCEPT; /// Determine if a line intersects the plane. /// @param line The line /// @param[out] parameter The parametric value of the point of intersection /// @return True if the line intersects the plane. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersectT (const Line3<T>& line, T& parameter) const IMATH_NOEXCEPT; /// Return the distance from a point to the plane. IMATH_HOSTDEVICE constexpr T distanceTo (const Vec3<T>& point) const IMATH_NOEXCEPT; /// Reflect the given point around the plane. IMATH_HOSTDEVICE constexpr Vec3<T> reflectPoint (const Vec3<T>& point) const IMATH_NOEXCEPT; /// Reflect the direction vector around the plane IMATH_HOSTDEVICE constexpr Vec3<T> reflectVector (const Vec3<T>& vec) const IMATH_NOEXCEPT; /// @} }; /// Plane of type float typedef Plane3<float> Plane3f; /// Plane of type double typedef Plane3<double> Plane3d; //--------------- // Implementation //--------------- template <class T> IMATH_CONSTEXPR14 inline Plane3<T>::Plane3 (const Vec3<T>& p0, const Vec3<T>& p1, const Vec3<T>& p2) IMATH_NOEXCEPT { set (p0, p1, p2); } template <class T> IMATH_CONSTEXPR14 inline Plane3<T>::Plane3 (const Vec3<T>& n, T d) IMATH_NOEXCEPT { set (n, d); } template <class T> IMATH_CONSTEXPR14 inline Plane3<T>::Plane3 (const Vec3<T>& p, const Vec3<T>& n) IMATH_NOEXCEPT { set (p, n); } template <class T> inline void Plane3<T>::set (const Vec3<T>& point1, const Vec3<T>& point2, const Vec3<T>& point3) IMATH_NOEXCEPT { normal = (point2 - point1) % (point3 - point1); normal.normalize(); distance = normal ^ point1; } template <class T> inline void Plane3<T>::set (const Vec3<T>& point, const Vec3<T>& n) IMATH_NOEXCEPT { normal = n; normal.normalize(); distance = normal ^ point; } template <class T> inline void Plane3<T>::set (const Vec3<T>& n, T d) IMATH_NOEXCEPT { normal = n; normal.normalize(); distance = d; } template <class T> constexpr inline T Plane3<T>::distanceTo (const Vec3<T>& point) const IMATH_NOEXCEPT { return (point ^ normal) - distance; } template <class T> constexpr inline Vec3<T> Plane3<T>::reflectPoint (const Vec3<T>& point) const IMATH_NOEXCEPT { return normal * distanceTo (point) * -2.0 + point; } template <class T> constexpr inline Vec3<T> Plane3<T>::reflectVector (const Vec3<T>& v) const IMATH_NOEXCEPT { return normal * (normal ^ v) * 2.0 - v; } template <class T> IMATH_CONSTEXPR14 inline bool Plane3<T>::intersect (const Line3<T>& line, Vec3<T>& point) const IMATH_NOEXCEPT { T d = normal ^ line.dir; if (d == 0.0) return false; T t = -((normal ^ line.pos) - distance) / d; point = line (t); return true; } template <class T> IMATH_CONSTEXPR14 inline bool Plane3<T>::intersectT (const Line3<T>& line, T& t) const IMATH_NOEXCEPT { T d = normal ^ line.dir; if (d == 0.0) return false; t = -((normal ^ line.pos) - distance) / d; return true; } /// Stream output, as "(normal distance)" template <class T> std::ostream& operator<< (std::ostream& o, const Plane3<T>& plane) { return o << "(" << plane.normal << ", " << plane.distance << ")"; } /// Transform a plane by a matrix template <class T> IMATH_CONSTEXPR14 Plane3<T> operator* (const Plane3<T>& plane, const Matrix44<T>& M) IMATH_NOEXCEPT { // T // -1 // Could also compute M but that would suck. // Vec3<T> dir1 = Vec3<T> (1, 0, 0) % plane.normal; T dir1Len = dir1 ^ dir1; Vec3<T> tmp = Vec3<T> (0, 1, 0) % plane.normal; T tmpLen = tmp ^ tmp; if (tmpLen > dir1Len) { dir1 = tmp; dir1Len = tmpLen; } tmp = Vec3<T> (0, 0, 1) % plane.normal; tmpLen = tmp ^ tmp; if (tmpLen > dir1Len) { dir1 = tmp; } Vec3<T> dir2 = dir1 % plane.normal; Vec3<T> point = plane.distance * plane.normal; return Plane3<T> (point * M, (point + dir2) * M, (point + dir1) * M); } /// Reflect the pla template <class T> constexpr inline Plane3<T> operator- (const Plane3<T>& plane) IMATH_NOEXCEPT { return Plane3<T> (-plane.normal, -plane.distance); } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHPLANE_H ImathColorAlgo.h 0000644 00000017504 15125213144 0007566 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // Color conversion functions and general color algorithms // #ifndef INCLUDED_IMATHCOLORALGO_H #define INCLUDED_IMATHCOLORALGO_H #include "ImathNamespace.h" #include "ImathExport.h" #include "ImathColor.h" #include "ImathMath.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER // // Non-templated helper routines for color conversion. // These routines eliminate type warnings under g++. // /// /// Convert 3-channel hsv to rgb. Non-templated helper routine. IMATH_EXPORT Vec3<double> hsv2rgb_d (const Vec3<double>& hsv) IMATH_NOEXCEPT; /// /// Convert 4-channel hsv to rgb (with alpha). Non-templated helper routine. IMATH_EXPORT Color4<double> hsv2rgb_d (const Color4<double>& hsv) IMATH_NOEXCEPT; /// /// Convert 3-channel rgb to hsv. Non-templated helper routine. IMATH_EXPORT Vec3<double> rgb2hsv_d (const Vec3<double>& rgb) IMATH_NOEXCEPT; /// /// Convert 4-channel rgb to hsv. Non-templated helper routine. IMATH_EXPORT Color4<double> rgb2hsv_d (const Color4<double>& rgb) IMATH_NOEXCEPT; /// /// Convert 3-channel hsv to rgb. /// template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3<T> hsv2rgb (const Vec3<T>& hsv) IMATH_NOEXCEPT { if (std::numeric_limits<T>::is_integer) { Vec3<double> v = Vec3<double> (hsv.x / double (std::numeric_limits<T>::max()), hsv.y / double (std::numeric_limits<T>::max()), hsv.z / double (std::numeric_limits<T>::max())); Vec3<double> c = hsv2rgb_d (v); return Vec3<T> ((T) (c.x * std::numeric_limits<T>::max()), (T) (c.y * std::numeric_limits<T>::max()), (T) (c.z * std::numeric_limits<T>::max())); } else { Vec3<double> v = Vec3<double> (hsv.x, hsv.y, hsv.z); Vec3<double> c = hsv2rgb_d (v); return Vec3<T> ((T) c.x, (T) c.y, (T) c.z); } } /// /// Convert 4-channel hsv to rgb (with alpha). /// template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Color4<T> hsv2rgb (const Color4<T>& hsv) IMATH_NOEXCEPT { if (std::numeric_limits<T>::is_integer) { Color4<double> v = Color4<double> (hsv.r / float (std::numeric_limits<T>::max()), hsv.g / float (std::numeric_limits<T>::max()), hsv.b / float (std::numeric_limits<T>::max()), hsv.a / float (std::numeric_limits<T>::max())); Color4<double> c = hsv2rgb_d (v); return Color4<T> ((T) (c.r * std::numeric_limits<T>::max()), (T) (c.g * std::numeric_limits<T>::max()), (T) (c.b * std::numeric_limits<T>::max()), (T) (c.a * std::numeric_limits<T>::max())); } else { Color4<double> v = Color4<double> (hsv.r, hsv.g, hsv.b, hsv.a); Color4<double> c = hsv2rgb_d (v); return Color4<T> ((T) c.r, (T) c.g, (T) c.b, (T) c.a); } } /// /// Convert 3-channel rgb to hsv. /// template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Vec3<T> rgb2hsv (const Vec3<T>& rgb) IMATH_NOEXCEPT { if (std::numeric_limits<T>::is_integer) { Vec3<double> v = Vec3<double> (rgb.x / double (std::numeric_limits<T>::max()), rgb.y / double (std::numeric_limits<T>::max()), rgb.z / double (std::numeric_limits<T>::max())); Vec3<double> c = rgb2hsv_d (v); return Vec3<T> ((T) (c.x * std::numeric_limits<T>::max()), (T) (c.y * std::numeric_limits<T>::max()), (T) (c.z * std::numeric_limits<T>::max())); } else { Vec3<double> v = Vec3<double> (rgb.x, rgb.y, rgb.z); Vec3<double> c = rgb2hsv_d (v); return Vec3<T> ((T) c.x, (T) c.y, (T) c.z); } } /// /// Convert 4-channel rgb to hsv (with alpha). /// template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Color4<T> rgb2hsv (const Color4<T>& rgb) IMATH_NOEXCEPT { if (std::numeric_limits<T>::is_integer) { Color4<double> v = Color4<double> (rgb.r / float (std::numeric_limits<T>::max()), rgb.g / float (std::numeric_limits<T>::max()), rgb.b / float (std::numeric_limits<T>::max()), rgb.a / float (std::numeric_limits<T>::max())); Color4<double> c = rgb2hsv_d (v); return Color4<T> ((T) (c.r * std::numeric_limits<T>::max()), (T) (c.g * std::numeric_limits<T>::max()), (T) (c.b * std::numeric_limits<T>::max()), (T) (c.a * std::numeric_limits<T>::max())); } else { Color4<double> v = Color4<double> (rgb.r, rgb.g, rgb.b, rgb.a); Color4<double> c = rgb2hsv_d (v); return Color4<T> ((T) c.r, (T) c.g, (T) c.b, (T) c.a); } } /// /// Convert 3-channel rgb to PackedColor /// template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 PackedColor rgb2packed (const Vec3<T>& c) IMATH_NOEXCEPT { if (std::numeric_limits<T>::is_integer) { float x = c.x / float (std::numeric_limits<T>::max()); float y = c.y / float (std::numeric_limits<T>::max()); float z = c.z / float (std::numeric_limits<T>::max()); return rgb2packed (V3f (x, y, z)); } else { // clang-format off return ( (PackedColor) (c.x * 255) | (((PackedColor) (c.y * 255)) << 8) | (((PackedColor) (c.z * 255)) << 16) | 0xFF000000 ); // clang-format on } } /// /// Convert 4-channel rgb to PackedColor (with alpha) /// template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 PackedColor rgb2packed (const Color4<T>& c) IMATH_NOEXCEPT { if (std::numeric_limits<T>::is_integer) { float r = c.r / float (std::numeric_limits<T>::max()); float g = c.g / float (std::numeric_limits<T>::max()); float b = c.b / float (std::numeric_limits<T>::max()); float a = c.a / float (std::numeric_limits<T>::max()); return rgb2packed (C4f (r, g, b, a)); } else { // clang-format off return ( (PackedColor) (c.r * 255) | (((PackedColor) (c.g * 255)) << 8) | (((PackedColor) (c.b * 255)) << 16) | (((PackedColor) (c.a * 255)) << 24)); // clang-format on } } /// /// Convert PackedColor to 3-channel rgb. Return the result in the /// `out` parameter. /// template <class T> IMATH_HOSTDEVICE void packed2rgb (PackedColor packed, Vec3<T>& out) IMATH_NOEXCEPT { if (std::numeric_limits<T>::is_integer) { T f = std::numeric_limits<T>::max() / ((PackedColor) 0xFF); out.x = (packed & 0xFF) * f; out.y = ((packed & 0xFF00) >> 8) * f; out.z = ((packed & 0xFF0000) >> 16) * f; } else { T f = T (1) / T (255); out.x = (packed & 0xFF) * f; out.y = ((packed & 0xFF00) >> 8) * f; out.z = ((packed & 0xFF0000) >> 16) * f; } } /// /// Convert PackedColor to 4-channel rgb (with alpha). Return the /// result in the `out` parameter. /// template <class T> IMATH_HOSTDEVICE void packed2rgb (PackedColor packed, Color4<T>& out) IMATH_NOEXCEPT { if (std::numeric_limits<T>::is_integer) { T f = std::numeric_limits<T>::max() / ((PackedColor) 0xFF); out.r = (packed & 0xFF) * f; out.g = ((packed & 0xFF00) >> 8) * f; out.b = ((packed & 0xFF0000) >> 16) * f; out.a = ((packed & 0xFF000000) >> 24) * f; } else { T f = T (1) / T (255); out.r = (packed & 0xFF) * f; out.g = ((packed & 0xFF00) >> 8) * f; out.b = ((packed & 0xFF0000) >> 16) * f; out.a = ((packed & 0xFF000000) >> 24) * f; } } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHCOLORALGO_H ImathRoots.h 0000644 00000011703 15125213144 0007006 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // Functions to solve linear, quadratic or cubic equations // // Note: It is possible that an equation has real solutions, but that // the solutions (or some intermediate result) are not representable. // In this case, either some of the solutions returned are invalid // (nan or infinity), or, if floating-point exceptions have been // enabled, an exception is thrown. // #ifndef INCLUDED_IMATHROOTS_H #define INCLUDED_IMATHROOTS_H #include "ImathMath.h" #include "ImathNamespace.h" #include <complex> /// @cond Doxygen_Suppress #ifdef __CUDACC__ # include <thrust/complex.h> # define COMPLEX_NAMESPACE thrust #else # define COMPLEX_NAMESPACE std #endif /// @endcond IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// /// Solve for x in the linear equation: /// /// a * x + b == 0 /// /// @return 1 if the equation has a solution, 0 if there is no /// solution, and -1 if all real numbers are solutions. template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 int solveLinear (T a, T b, T& x); /// /// Solve for x in the quadratic equation: /// /// a * x*x + b * x + c == 0 /// /// @return 2 if the equation has two solutions, 1 if the equation has /// a single solution, 0 if there is no solution, and -1 if all real /// numbers are solutions. template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 int solveQuadratic (T a, T b, T c, T x[2]); template <class T> /// /// Solve for x in the normalized cubic equation: /// /// x*x*x + r * x*x + s * x + t == 0 /// /// The equation is solved using Cardano's Formula; even though only /// real solutions are produced, some intermediate results are complex /// (std::complex<T>). /// /// @return 0 if there is no solution, and -1 if all real /// numbers are solutions, otherwise return the number of solutions. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 int solveNormalizedCubic (T r, T s, T t, T x[3]); /// /// Solve for x in the cubic equation: /// /// a * x*x*x + b * x*x + c * x + d == 0 /// /// The equation is solved using Cardano's Formula; even though only /// real solutions are produced, some intermediate results are complex /// (std::complex<T>). /// /// @return 0 if there is no solution, and -1 if all real /// numbers are solutions, otherwise return the number of solutions. template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 int solveCubic (T a, T b, T c, T d, T x[3]); //--------------- // Implementation //--------------- template <class T> IMATH_CONSTEXPR14 int solveLinear (T a, T b, T& x) { if (a != 0) { x = -b / a; return 1; } else if (b != 0) { return 0; } else { return -1; } } template <class T> IMATH_CONSTEXPR14 int solveQuadratic (T a, T b, T c, T x[2]) { if (a == 0) { return solveLinear (b, c, x[0]); } else { T D = b * b - 4 * a * c; if (D > 0) { T s = std::sqrt (D); T q = -(b + (b > 0 ? 1 : -1) * s) / T (2); x[0] = q / a; x[1] = c / q; return 2; } if (D == 0) { x[0] = -b / (2 * a); return 1; } else { return 0; } } } template <class T> IMATH_CONSTEXPR14 int solveNormalizedCubic (T r, T s, T t, T x[3]) { T p = (3 * s - r * r) / 3; T q = 2 * r * r * r / 27 - r * s / 3 + t; T p3 = p / 3; T q2 = q / 2; T D = p3 * p3 * p3 + q2 * q2; if (D == 0 && p3 == 0) { x[0] = -r / 3; x[1] = -r / 3; x[2] = -r / 3; return 1; } COMPLEX_NAMESPACE::complex<T> u = COMPLEX_NAMESPACE::pow ( -q / 2 + COMPLEX_NAMESPACE::sqrt (COMPLEX_NAMESPACE::complex<T> (D)), T (1) / T (3)); COMPLEX_NAMESPACE::complex<T> v = -p / (T (3) * u); const T sqrt3 = T (1.73205080756887729352744634150587); // enough digits // for long double COMPLEX_NAMESPACE::complex<T> y0 (u + v); COMPLEX_NAMESPACE::complex<T> y1 (-(u + v) / T (2) + (u - v) / T (2) * COMPLEX_NAMESPACE::complex<T> (0, sqrt3)); COMPLEX_NAMESPACE::complex<T> y2 (-(u + v) / T (2) - (u - v) / T (2) * COMPLEX_NAMESPACE::complex<T> (0, sqrt3)); if (D > 0) { x[0] = y0.real() - r / 3; return 1; } else if (D == 0) { x[0] = y0.real() - r / 3; x[1] = y1.real() - r / 3; return 2; } else { x[0] = y0.real() - r / 3; x[1] = y1.real() - r / 3; x[2] = y2.real() - r / 3; return 3; } } template <class T> IMATH_CONSTEXPR14 int solveCubic (T a, T b, T c, T d, T x[3]) { if (a == 0) { return solveQuadratic (b, c, d, x); } else { return solveNormalizedCubic (b / a, c / a, d / a, x); } } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHROOTS_H PyImathStringArrayRegister.h 0000644 00000000457 15125213144 0012167 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathStringArrayRegister_h_ #define _PyImathStringArrayRegister_h_ #include "PyImathExport.h" namespace PyImath { PYIMATH_EXPORT void register_StringArrays(); } #endif ImathGLU.h 0000644 00000001164 15125213144 0006327 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // Convenience functions that call GLU with Imath types // #ifndef INCLUDED_IMATHGLU_H #define INCLUDED_IMATHGLU_H #include <GL/gl.h> #include <GL/glu.h> #include "ImathVec.h" /// Call gluLookAt with the given position, interest, and up-vector. inline void gluLookAt (const IMATH_INTERNAL_NAMESPACE::V3f& pos, const IMATH_INTERNAL_NAMESPACE::V3f& interest, const IMATH_INTERNAL_NAMESPACE::V3f& up) { gluLookAt (pos.x, pos.y, pos.z, interest.x, interest.y, interest.z, up.x, up.y, up.z); } #endif PyImathVecOperators.h 0000644 00000003434 15125213144 0010627 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef _PyImathVecOperators_h_ #define _PyImathVecOperators_h_ namespace PyImath { template <class T> struct op_vecDot { static inline typename T::BaseType apply(const T &a, const T &b) { return a.dot(b); } }; template <class T, IMATH_ENABLE_IF(!std::is_integral<typename T::BaseType>::value)> struct op_vecLength { static inline typename T::BaseType apply(const T &v) { return v.length(); } }; template <class T> struct op_vecLength2 { static inline typename T::BaseType apply(const T &v) { return v.length2(); } }; template <class T, IMATH_ENABLE_IF(!std::is_integral<typename T::BaseType>::value)> struct op_vecNormalize { static inline void apply(T &v) { v.normalize(); } }; template <class T, IMATH_ENABLE_IF(!std::is_integral<typename T::BaseType>::value)> struct op_vecNormalized { static inline T apply(const T &v) { return v.normalized(); } }; template <class T, IMATH_ENABLE_IF(!std::is_integral<typename T::BaseType>::value)> struct op_vecNormalizeExc { static inline void apply(T &v) { v.normalizeExc(); } }; template <class T, IMATH_ENABLE_IF(!std::is_integral<typename T::BaseType>::value)> struct op_vecNormalizedExc { static inline T apply(const T &v) { return v.normalizedExc(); } }; template <class T> struct op_vec3Cross { static inline IMATH_NAMESPACE::Vec3<T> apply(const IMATH_NAMESPACE::Vec3<T> &a, const IMATH_NAMESPACE::Vec3<T> &b) { return a.cross(b); } }; template <class T> struct op_vec2Cross { static inline T apply(const IMATH_NAMESPACE::Vec2<T> &a, const IMATH_NAMESPACE::Vec2<T> &b) { return a.cross(b); } }; } // namespace PyImath #endif // _PyImathVecOperators_h_ ImathInterval.h 0000644 00000014655 15125213144 0007475 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // // An interval class // #ifndef INCLUDED_IMATHINTERVAL_H #define INCLUDED_IMATHINTERVAL_H #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathVec.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER /// /// An Interval has a min and a max and some miscellaneous /// functions. It is basically a Box<T> that allows T to be a scalar. /// template <class T> class IMATH_EXPORT_TEMPLATE_TYPE Interval { public: /// @{ /// @name Direct access to bounds /// The minimum value of the interval T min; /// The minimum value of the interval T max; /// @} /// @{ /// @name Constructors /// Initialize to the empty interval IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Interval() IMATH_NOEXCEPT; /// Intitialize to a single point IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Interval (const T& point) IMATH_NOEXCEPT; /// Intitialize to a given (min,max) IMATH_HOSTDEVICE IMATH_CONSTEXPR14 Interval (const T& minT, const T& maxT) IMATH_NOEXCEPT; /// @} /// @{ /// @name Comparison /// Equality IMATH_HOSTDEVICE constexpr bool operator== (const Interval<T>& src) const IMATH_NOEXCEPT; /// Inequality IMATH_HOSTDEVICE constexpr bool operator!= (const Interval<T>& src) const IMATH_NOEXCEPT; /// @} /// @{ /// @name Manipulation /// Set the interval to be empty. An interval is empty if the /// minimum is greater than the maximum. IMATH_HOSTDEVICE void makeEmpty() IMATH_NOEXCEPT; /// Extend the interval to include the given point. IMATH_HOSTDEVICE void extendBy (const T& point) IMATH_NOEXCEPT; /// Extend the interval to include the given interval IMATH_HOSTDEVICE void extendBy (const Interval<T>& interval) IMATH_NOEXCEPT; /// Make the interval include the entire range of the base type. IMATH_HOSTDEVICE void makeInfinite() IMATH_NOEXCEPT; /// @} /// @{ /// @name Query /// Return the size of the interval. The size is (max-min). An empty box has a size of 0. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T size() const IMATH_NOEXCEPT; /// Return the center of the interval. The center is defined as /// (max+min)/2. The center of an empty interval is undefined. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 T center() const IMATH_NOEXCEPT; /// Return true if the given point is inside the interval, false otherwise. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersects (const T& point) const IMATH_NOEXCEPT; /// Return true if the given interval is inside the interval, false otherwise. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool intersects (const Interval<T>& interval) const IMATH_NOEXCEPT; /// Return true if the interval is empty, false otherwise. An /// empty interval's minimum is greater than its maximum. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool isEmpty() const IMATH_NOEXCEPT; /// Return true if the interval is larger than a single point, /// false otherwise. IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool hasVolume() const IMATH_NOEXCEPT; /// Return true if the interval contains all points, false /// otherwise. An infinite box has a mimimum of `numeric_limits<T>::lowest()` /// and a maximum of `numeric_limits<T>::max()` IMATH_HOSTDEVICE IMATH_CONSTEXPR14 bool isInfinite() const IMATH_NOEXCEPT; /// @} }; /// Stream output, as "(min max)" template <class T> std::ostream& operator<< (std::ostream& s, const Interval<T>& v); /// Interval of type float typedef Interval<float> Intervalf; /// Interval of type double typedef Interval<double> Intervald; /// Interval of type short typedef Interval<short> Intervals; /// Interval of type integer typedef Interval<int> Intervali; template <class T> inline IMATH_CONSTEXPR14 Interval<T>::Interval() IMATH_NOEXCEPT { makeEmpty(); } template <class T> IMATH_CONSTEXPR14 inline Interval<T>::Interval (const T& point) IMATH_NOEXCEPT { min = point; max = point; } template <class T> IMATH_CONSTEXPR14 inline Interval<T>::Interval (const T& minV, const T& maxV) IMATH_NOEXCEPT { min = minV; max = maxV; } template <class T> constexpr inline bool Interval<T>::operator== (const Interval<T>& src) const IMATH_NOEXCEPT { return (min == src.min && max == src.max); } template <class T> constexpr inline bool Interval<T>::operator!= (const Interval<T>& src) const IMATH_NOEXCEPT { return (min != src.min || max != src.max); } template <class T> inline void Interval<T>::makeEmpty() IMATH_NOEXCEPT { min = std::numeric_limits<T>::max(); max = std::numeric_limits<T>::lowest(); } template <class T> inline void Interval<T>::makeInfinite() IMATH_NOEXCEPT { min = std::numeric_limits<T>::lowest(); max = std::numeric_limits<T>::max(); } template <class T> inline void Interval<T>::extendBy (const T& point) IMATH_NOEXCEPT { if (point < min) min = point; if (point > max) max = point; } template <class T> inline void Interval<T>::extendBy (const Interval<T>& interval) IMATH_NOEXCEPT { if (interval.min < min) min = interval.min; if (interval.max > max) max = interval.max; } template <class T> IMATH_CONSTEXPR14 inline bool Interval<T>::intersects (const T& point) const IMATH_NOEXCEPT { return point >= min && point <= max; } template <class T> IMATH_CONSTEXPR14 inline bool Interval<T>::intersects (const Interval<T>& interval) const IMATH_NOEXCEPT { return interval.max >= min && interval.min <= max; } template <class T> IMATH_CONSTEXPR14 inline T Interval<T>::size() const IMATH_NOEXCEPT { if (isEmpty()) return T(0); return max - min; } template <class T> IMATH_CONSTEXPR14 inline T Interval<T>::center() const IMATH_NOEXCEPT { return (max + min) / 2; } template <class T> IMATH_CONSTEXPR14 inline bool Interval<T>::isEmpty() const IMATH_NOEXCEPT { return max < min; } template <class T> IMATH_CONSTEXPR14 inline bool Interval<T>::hasVolume() const IMATH_NOEXCEPT { return max > min; } template <class T> IMATH_CONSTEXPR14 inline bool Interval<T>::isInfinite() const IMATH_NOEXCEPT { if (min != std::numeric_limits<T>::lowest() || max != std::numeric_limits<T>::max()) return false; return true; } /// Stream output template <class T> std::ostream& operator<< (std::ostream& s, const Interval<T>& v) { return s << '(' << v.min << ' ' << v.max << ')'; } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHINTERVAL_H ImathFun.h 0000644 00000012365 15125213144 0006435 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // #ifndef INCLUDED_IMATHFUN_H #define INCLUDED_IMATHFUN_H //----------------------------------------------------------------------------- // // Miscellaneous utility functions // //----------------------------------------------------------------------------- #include <limits> #include <cstdint> #include "ImathExport.h" #include "ImathNamespace.h" #include "ImathPlatform.h" IMATH_INTERNAL_NAMESPACE_HEADER_ENTER template <class T> IMATH_HOSTDEVICE constexpr inline T abs (T a) IMATH_NOEXCEPT { return (a > T (0)) ? a : -a; } template <class T> IMATH_HOSTDEVICE constexpr inline int sign (T a) IMATH_NOEXCEPT { return (a > T (0)) ? 1 : ((a < T (0)) ? -1 : 0); } template <class T, class Q> IMATH_HOSTDEVICE constexpr inline T lerp (T a, T b, Q t) IMATH_NOEXCEPT { return (T) (a * (1 - t) + b * t); } template <class T, class Q> IMATH_HOSTDEVICE constexpr inline T ulerp (T a, T b, Q t) IMATH_NOEXCEPT { return (T) ((a > b) ? (a - (a - b) * t) : (a + (b - a) * t)); } template <class T> IMATH_HOSTDEVICE IMATH_CONSTEXPR14 inline T lerpfactor (T m, T a, T b) IMATH_NOEXCEPT { // // Return how far m is between a and b, that is return t such that // if: // t = lerpfactor(m, a, b); // then: // m = lerp(a, b, t); // // If a==b, return 0. // T d = b - a; T n = m - a; if (abs (d) > T (1) || abs (n) < std::numeric_limits<T>::max() * abs (d)) return n / d; return T (0); } template <class T> IMATH_HOSTDEVICE constexpr inline T clamp (T a, T l, T h) IMATH_NOEXCEPT { return (a < l) ? l : ((a > h) ? h : a); } template <class T> IMATH_HOSTDEVICE constexpr inline int cmp (T a, T b) IMATH_NOEXCEPT { return IMATH_INTERNAL_NAMESPACE::sign (a - b); } template <class T> IMATH_HOSTDEVICE constexpr inline int cmpt (T a, T b, T t) IMATH_NOEXCEPT { return (IMATH_INTERNAL_NAMESPACE::abs (a - b) <= t) ? 0 : cmp (a, b); } template <class T> IMATH_HOSTDEVICE constexpr inline bool iszero (T a, T t) IMATH_NOEXCEPT { return (IMATH_INTERNAL_NAMESPACE::abs (a) <= t) ? 1 : 0; } template <class T1, class T2, class T3> IMATH_HOSTDEVICE constexpr inline bool equal (T1 a, T2 b, T3 t) IMATH_NOEXCEPT { return IMATH_INTERNAL_NAMESPACE::abs (a - b) <= t; } template <class T> IMATH_HOSTDEVICE constexpr inline int floor (T x) IMATH_NOEXCEPT { return (x >= 0) ? int (x) : -(int (-x) + (-x > int (-x))); } template <class T> IMATH_HOSTDEVICE constexpr inline int ceil (T x) IMATH_NOEXCEPT { return -floor (-x); } template <class T> IMATH_HOSTDEVICE constexpr inline int trunc (T x) IMATH_NOEXCEPT { return (x >= 0) ? int (x) : -int (-x); } // // Integer division and remainder where the // remainder of x/y has the same sign as x: // // divs(x,y) == (abs(x) / abs(y)) * (sign(x) * sign(y)) // mods(x,y) == x - y * divs(x,y) // IMATH_HOSTDEVICE constexpr inline int divs (int x, int y) IMATH_NOEXCEPT { return (x >= 0) ? ((y >= 0) ? (x / y) : -(x / -y)) : ((y >= 0) ? -(-x / y) : (-x / -y)); } IMATH_HOSTDEVICE constexpr inline int mods (int x, int y) IMATH_NOEXCEPT { return (x >= 0) ? ((y >= 0) ? (x % y) : (x % -y)) : ((y >= 0) ? -(-x % y) : -(-x % -y)); } // // Integer division and remainder where the // remainder of x/y is always positive: // // divp(x,y) == floor (double(x) / double (y)) // modp(x,y) == x - y * divp(x,y) // IMATH_HOSTDEVICE constexpr inline int divp (int x, int y) IMATH_NOEXCEPT { return (x >= 0) ? ((y >= 0) ? (x / y) : -(x / -y)) : ((y >= 0) ? -((y - 1 - x) / y) : ((-y - 1 - x) / -y)); } IMATH_HOSTDEVICE constexpr inline int modp (int x, int y) IMATH_NOEXCEPT { return x - y * divp (x, y); } //---------------------------------------------------------- // Successor and predecessor for floating-point numbers: // // succf(f) returns float(f+e), where e is the smallest // positive number such that float(f+e) != f. // // predf(f) returns float(f-e), where e is the smallest // positive number such that float(f-e) != f. // // succd(d) returns double(d+e), where e is the smallest // positive number such that double(d+e) != d. // // predd(d) returns double(d-e), where e is the smallest // positive number such that double(d-e) != d. // // Exceptions: If the input value is an infinity or a nan, // succf(), predf(), succd(), and predd() all // return the input value without changing it. // //---------------------------------------------------------- IMATH_EXPORT float succf (float f) IMATH_NOEXCEPT; IMATH_EXPORT float predf (float f) IMATH_NOEXCEPT; IMATH_EXPORT double succd (double d) IMATH_NOEXCEPT; IMATH_EXPORT double predd (double d) IMATH_NOEXCEPT; // // Return true if the number is not a NaN or Infinity. // inline bool IMATH_HOSTDEVICE finitef (float f) IMATH_NOEXCEPT { union { float f; int i; } u; u.f = f; return (u.i & 0x7f800000) != 0x7f800000; } inline bool IMATH_HOSTDEVICE finited (double d) IMATH_NOEXCEPT { union { double d; uint64_t i; } u; u.d = d; return (u.i & 0x7ff0000000000000LL) != 0x7ff0000000000000LL; } IMATH_INTERNAL_NAMESPACE_HEADER_EXIT #endif // INCLUDED_IMATHFUN_H PyImathDecorators.h 0000644 00000001617 15125213144 0010321 0 ustar 00 // // SPDX-License-Identifier: BSD-3-Clause // Copyright Contributors to the OpenEXR Project. // // clang-format off #ifndef INCLUDED_PYIMATH_DECORATORS_H #define INCLUDED_PYIMATH_DECORATORS_H #include <boost/python.hpp> namespace PyImath { // These function add __copy__ and __deepcopy__ methods // to python classes by simply wrapping the copy constructors // This interface is needed for using these classes with // the python copy module. template <class T> static T copy(const T& x) { return T(x); } template <class T> static T deepcopy(const T& x, boost::python::dict&) { return copy(x); } template <class T, class X1, class X2, class X3> boost::python::class_<T,X1,X2,X3>& decoratecopy(boost::python::class_<T,X1,X2,X3>& cls) { cls.def("__copy__",©<T>); cls.def("__deepcopy__",&deepcopy<T>); return cls; } } // namespace PyImath #endif // INCLUDED_PYIMATH_DECORATORS_H ImathConfig.cmake 0000644 00000010670 15125646264 0007755 0 ustar 00 # Generated by CMake if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5) message(FATAL_ERROR "CMake >= 2.6.0 required") endif() cmake_policy(PUSH) cmake_policy(VERSION 2.6...3.18) #---------------------------------------------------------------- # Generated CMake target import file. #---------------------------------------------------------------- # Commands may need to know the format version. set(CMAKE_IMPORT_FILE_VERSION 1) # Protect against multiple inclusion, which would fail when already imported targets are added once more. set(_targetsDefined) set(_targetsNotDefined) set(_expectedTargets) foreach(_expectedTarget Imath::ImathConfig Imath::Imath Imath::PyImathConfig Imath::PyImath_Python3_9) list(APPEND _expectedTargets ${_expectedTarget}) if(NOT TARGET ${_expectedTarget}) list(APPEND _targetsNotDefined ${_expectedTarget}) endif() if(TARGET ${_expectedTarget}) list(APPEND _targetsDefined ${_expectedTarget}) endif() endforeach() if("${_targetsDefined}" STREQUAL "${_expectedTargets}") unset(_targetsDefined) unset(_targetsNotDefined) unset(_expectedTargets) set(CMAKE_IMPORT_FILE_VERSION) cmake_policy(POP) return() endif() if(NOT "${_targetsDefined}" STREQUAL "") message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n") endif() unset(_targetsDefined) unset(_targetsNotDefined) unset(_expectedTargets) # Compute the installation prefix relative to this file. get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) # Use original install prefix when loaded through a # cross-prefix symbolic link such as /lib -> /usr/lib. get_filename_component(_realCurr "${_IMPORT_PREFIX}" REALPATH) get_filename_component(_realOrig "/usr/lib64/cmake/Imath" REALPATH) if(_realCurr STREQUAL _realOrig) set(_IMPORT_PREFIX "/usr/lib64/cmake/Imath") endif() unset(_realOrig) unset(_realCurr) get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) if(_IMPORT_PREFIX STREQUAL "/") set(_IMPORT_PREFIX "") endif() # Create imported target Imath::ImathConfig add_library(Imath::ImathConfig INTERFACE IMPORTED) set_target_properties(Imath::ImathConfig PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include/Imath" ) # Create imported target Imath::Imath add_library(Imath::Imath SHARED IMPORTED) set_target_properties(Imath::Imath PROPERTIES INTERFACE_COMPILE_FEATURES "cxx_std_11" INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" INTERFACE_LINK_LIBRARIES "Imath::ImathConfig;m" ) # Create imported target Imath::PyImathConfig add_library(Imath::PyImathConfig INTERFACE IMPORTED) # Create imported target Imath::PyImath_Python3_9 add_library(Imath::PyImath_Python3_9 SHARED IMPORTED) set_target_properties(Imath::PyImath_Python3_9 PROPERTIES INTERFACE_COMPILE_FEATURES "cxx_std_14" INTERFACE_INCLUDE_DIRECTORIES "/usr/include" INTERFACE_LINK_LIBRARIES "Imath::Imath" ) if(CMAKE_VERSION VERSION_LESS 3.0.0) message(FATAL_ERROR "This file relies on consumers using CMake 3.0.0 or greater.") endif() # Load information for each installed configuration. get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) file(GLOB CONFIG_FILES "${_DIR}/ImathConfig-*.cmake") foreach(f ${CONFIG_FILES}) include(${f}) endforeach() # Cleanup temporary variables. set(_IMPORT_PREFIX) # Loop over all imported files and verify that they actually exist foreach(target ${_IMPORT_CHECK_TARGETS} ) foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} ) if(NOT EXISTS "${file}" ) message(FATAL_ERROR "The imported target \"${target}\" references the file \"${file}\" but this file does not exist. Possible reasons include: * The file was deleted, renamed, or moved to another location. * An install or uninstall procedure did not complete successfully. * The installation package was faulty and contained \"${CMAKE_CURRENT_LIST_FILE}\" but not all the files it references. ") endif() endforeach() unset(_IMPORT_CHECK_FILES_FOR_${target}) endforeach() unset(_IMPORT_CHECK_TARGETS) # This file does not depend on other imported targets which have # been exported from the same project but in a separate export set. # Commands beyond this point should not need to know the version. set(CMAKE_IMPORT_FILE_VERSION) cmake_policy(POP) ImathConfig-release.cmake 0000644 00000002674 15125646264 0011400 0 ustar 00 #---------------------------------------------------------------- # Generated CMake target import file for configuration "Release". #---------------------------------------------------------------- # Commands may need to know the format version. set(CMAKE_IMPORT_FILE_VERSION 1) # Import target "Imath::Imath" for configuration "Release" set_property(TARGET Imath::Imath APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) set_target_properties(Imath::Imath PROPERTIES IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib64/libImath-3_1.so.29.1.0" IMPORTED_SONAME_RELEASE "libImath-3_1.so.29" ) list(APPEND _IMPORT_CHECK_TARGETS Imath::Imath ) list(APPEND _IMPORT_CHECK_FILES_FOR_Imath::Imath "${_IMPORT_PREFIX}/lib64/libImath-3_1.so.29.1.0" ) # Import target "Imath::PyImath_Python3_9" for configuration "Release" set_property(TARGET Imath::PyImath_Python3_9 APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) set_target_properties(Imath::PyImath_Python3_9 PROPERTIES IMPORTED_LINK_DEPENDENT_LIBRARIES_RELEASE "Python3::Python" IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib64/libPyImath_Python3_9-3_1.so.29.1.0" IMPORTED_SONAME_RELEASE "libPyImath_Python3_9-3_1.so.29" ) list(APPEND _IMPORT_CHECK_TARGETS Imath::PyImath_Python3_9 ) list(APPEND _IMPORT_CHECK_FILES_FOR_Imath::PyImath_Python3_9 "${_IMPORT_PREFIX}/lib64/libPyImath_Python3_9-3_1.so.29.1.0" ) # Commands beyond this point should not need to know the version. set(CMAKE_IMPORT_FILE_VERSION) ImathTargets.cmake 0000644 00000010671 15125646264 0010162 0 ustar 00 # Generated by CMake if("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" LESS 2.5) message(FATAL_ERROR "CMake >= 2.6.0 required") endif() cmake_policy(PUSH) cmake_policy(VERSION 2.6...3.18) #---------------------------------------------------------------- # Generated CMake target import file. #---------------------------------------------------------------- # Commands may need to know the format version. set(CMAKE_IMPORT_FILE_VERSION 1) # Protect against multiple inclusion, which would fail when already imported targets are added once more. set(_targetsDefined) set(_targetsNotDefined) set(_expectedTargets) foreach(_expectedTarget Imath::ImathConfig Imath::Imath Imath::PyImathConfig Imath::PyImath_Python3_9) list(APPEND _expectedTargets ${_expectedTarget}) if(NOT TARGET ${_expectedTarget}) list(APPEND _targetsNotDefined ${_expectedTarget}) endif() if(TARGET ${_expectedTarget}) list(APPEND _targetsDefined ${_expectedTarget}) endif() endforeach() if("${_targetsDefined}" STREQUAL "${_expectedTargets}") unset(_targetsDefined) unset(_targetsNotDefined) unset(_expectedTargets) set(CMAKE_IMPORT_FILE_VERSION) cmake_policy(POP) return() endif() if(NOT "${_targetsDefined}" STREQUAL "") message(FATAL_ERROR "Some (but not all) targets in this export set were already defined.\nTargets Defined: ${_targetsDefined}\nTargets not yet defined: ${_targetsNotDefined}\n") endif() unset(_targetsDefined) unset(_targetsNotDefined) unset(_expectedTargets) # Compute the installation prefix relative to this file. get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH) # Use original install prefix when loaded through a # cross-prefix symbolic link such as /lib -> /usr/lib. get_filename_component(_realCurr "${_IMPORT_PREFIX}" REALPATH) get_filename_component(_realOrig "/usr/lib64/cmake/Imath" REALPATH) if(_realCurr STREQUAL _realOrig) set(_IMPORT_PREFIX "/usr/lib64/cmake/Imath") endif() unset(_realOrig) unset(_realCurr) get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH) if(_IMPORT_PREFIX STREQUAL "/") set(_IMPORT_PREFIX "") endif() # Create imported target Imath::ImathConfig add_library(Imath::ImathConfig INTERFACE IMPORTED) set_target_properties(Imath::ImathConfig PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include/Imath" ) # Create imported target Imath::Imath add_library(Imath::Imath SHARED IMPORTED) set_target_properties(Imath::Imath PROPERTIES INTERFACE_COMPILE_FEATURES "cxx_std_11" INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include" INTERFACE_LINK_LIBRARIES "Imath::ImathConfig;m" ) # Create imported target Imath::PyImathConfig add_library(Imath::PyImathConfig INTERFACE IMPORTED) # Create imported target Imath::PyImath_Python3_9 add_library(Imath::PyImath_Python3_9 SHARED IMPORTED) set_target_properties(Imath::PyImath_Python3_9 PROPERTIES INTERFACE_COMPILE_FEATURES "cxx_std_14" INTERFACE_INCLUDE_DIRECTORIES "/usr/include" INTERFACE_LINK_LIBRARIES "Imath::Imath" ) if(CMAKE_VERSION VERSION_LESS 3.0.0) message(FATAL_ERROR "This file relies on consumers using CMake 3.0.0 or greater.") endif() # Load information for each installed configuration. get_filename_component(_DIR "${CMAKE_CURRENT_LIST_FILE}" PATH) file(GLOB CONFIG_FILES "${_DIR}/ImathTargets-*.cmake") foreach(f ${CONFIG_FILES}) include(${f}) endforeach() # Cleanup temporary variables. set(_IMPORT_PREFIX) # Loop over all imported files and verify that they actually exist foreach(target ${_IMPORT_CHECK_TARGETS} ) foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} ) if(NOT EXISTS "${file}" ) message(FATAL_ERROR "The imported target \"${target}\" references the file \"${file}\" but this file does not exist. Possible reasons include: * The file was deleted, renamed, or moved to another location. * An install or uninstall procedure did not complete successfully. * The installation package was faulty and contained \"${CMAKE_CURRENT_LIST_FILE}\" but not all the files it references. ") endif() endforeach() unset(_IMPORT_CHECK_FILES_FOR_${target}) endforeach() unset(_IMPORT_CHECK_TARGETS) # This file does not depend on other imported targets which have # been exported from the same project but in a separate export set. # Commands beyond this point should not need to know the version. set(CMAKE_IMPORT_FILE_VERSION) cmake_policy(POP) ImathConfigVersion.cmake 0000644 00000005266 15125646264 0011330 0 ustar 00 # This is a basic version file for the Config-mode of find_package(). # It is used by write_basic_package_version_file() as input file for configure_file() # to create a version-file which can be installed along a config.cmake file. # # The created file sets PACKAGE_VERSION_EXACT if the current version string and # the requested version string are exactly the same and it sets # PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version, # but only if the requested major version is the same as the current one. # The variable CVF_VERSION must be set before calling configure_file(). set(PACKAGE_VERSION "3.1.2") if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) set(PACKAGE_VERSION_COMPATIBLE FALSE) else() if("3.1.2" MATCHES "^([0-9]+)\\.") set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") else() set(CVF_VERSION_MAJOR "3.1.2") endif() if(PACKAGE_FIND_VERSION_RANGE) # both endpoints of the range must have the expected major version math (EXPR CVF_VERSION_MAJOR_NEXT "${CVF_VERSION_MAJOR} + 1") if (NOT PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR OR ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX_MAJOR STREQUAL CVF_VERSION_MAJOR) OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND NOT PACKAGE_FIND_VERSION_MAX VERSION_LESS_EQUAL CVF_VERSION_MAJOR_NEXT))) set(PACKAGE_VERSION_COMPATIBLE FALSE) elseif(PACKAGE_FIND_VERSION_MIN_MAJOR STREQUAL CVF_VERSION_MAJOR AND ((PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "INCLUDE" AND PACKAGE_VERSION VERSION_LESS_EQUAL PACKAGE_FIND_VERSION_MAX) OR (PACKAGE_FIND_VERSION_RANGE_MAX STREQUAL "EXCLUDE" AND PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION_MAX))) set(PACKAGE_VERSION_COMPATIBLE TRUE) else() set(PACKAGE_VERSION_COMPATIBLE FALSE) endif() else() if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CVF_VERSION_MAJOR) set(PACKAGE_VERSION_COMPATIBLE TRUE) else() set(PACKAGE_VERSION_COMPATIBLE FALSE) endif() if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) set(PACKAGE_VERSION_EXACT TRUE) endif() endif() endif() # if the installed project requested no architecture check, don't perform the check if("FALSE") return() endif() # if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "") return() endif() # check that the installed version has the same 32/64bit-ness as the one which is currently searching: if(NOT CMAKE_SIZEOF_VOID_P STREQUAL "8") math(EXPR installedBits "8 * 8") set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") set(PACKAGE_VERSION_UNSUITABLE TRUE) endif() ImathTargets-release.cmake 0000644 00000002674 15125646264 0011604 0 ustar 00 #---------------------------------------------------------------- # Generated CMake target import file for configuration "Release". #---------------------------------------------------------------- # Commands may need to know the format version. set(CMAKE_IMPORT_FILE_VERSION 1) # Import target "Imath::Imath" for configuration "Release" set_property(TARGET Imath::Imath APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) set_target_properties(Imath::Imath PROPERTIES IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib64/libImath-3_1.so.29.1.0" IMPORTED_SONAME_RELEASE "libImath-3_1.so.29" ) list(APPEND _IMPORT_CHECK_TARGETS Imath::Imath ) list(APPEND _IMPORT_CHECK_FILES_FOR_Imath::Imath "${_IMPORT_PREFIX}/lib64/libImath-3_1.so.29.1.0" ) # Import target "Imath::PyImath_Python3_9" for configuration "Release" set_property(TARGET Imath::PyImath_Python3_9 APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) set_target_properties(Imath::PyImath_Python3_9 PROPERTIES IMPORTED_LINK_DEPENDENT_LIBRARIES_RELEASE "Python3::Python" IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib64/libPyImath_Python3_9-3_1.so.29.1.0" IMPORTED_SONAME_RELEASE "libPyImath_Python3_9-3_1.so.29" ) list(APPEND _IMPORT_CHECK_TARGETS Imath::PyImath_Python3_9 ) list(APPEND _IMPORT_CHECK_FILES_FOR_Imath::PyImath_Python3_9 "${_IMPORT_PREFIX}/lib64/libPyImath_Python3_9-3_1.so.29.1.0" ) # Commands beyond this point should not need to know the version. set(CMAKE_IMPORT_FILE_VERSION)
| ver. 1.6 |
Github
|
.
| PHP 8.2.30 | ??????????? ?????????: 0.09 |
proxy
|
phpinfo
|
???????????