/////////////////////////////////////////////////////////////////////////// // // Copyright (c) 2007-2011, Industrial Light & Magic, a division of Lucas // Digital Ltd. LLC // // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Industrial Light & Magic nor the names of // its contributors may be used to endorse or promote products derived // from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // /////////////////////////////////////////////////////////////////////////// #ifndef _PyImathFixedMatrix_h_ #define _PyImathFixedMatrix_h_ #include #include #include "PyImathFixedArray.h" #include "PyImathOperators.h" namespace PyImath { // // Utility class for a runtime-specified fixed sized matrix type in python // template 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(); } int 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 { if (PySlice_Check(index)) { PySliceObject *slice = reinterpret_cast(index); if (PySlice_GetIndicesEx(slice,_rows,&start,&end,&step,&slicelength) == -1) { boost::python::throw_error_already_set(); } } else if (PyInt_Check(index)) { int 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 * getitem(int index) const { return new FixedArray(const_cast(&_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 &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 operator [] (int i) { return FixedArray(&_ptr[i*_rowStride*_cols*_colStride],_cols,_colStride); } const FixedArray operator [] (int i) const { return FixedArray(const_cast(&_ptr[i*_rowStride*_cols*_colStride]),_cols,_colStride); } static boost::python::class_ > register_(const char *name, const char *doc) { boost::python::class_ > c(name,doc, boost::python::init("return an unitialized array of the specified rows and cols")); c .def("__getitem__", &FixedMatrix::getslice) .def("__getitem__", &FixedMatrix::getitem, boost::python::return_internal_reference<>()) .def("__setitem__", &FixedMatrix::setitem_scalar) .def("__setitem__", &FixedMatrix::setitem_vector) .def("__setitem__", &FixedMatrix::setitem_matrix) .def("__len__",&FixedMatrix::rows) .def("rows",&FixedMatrix::rows) .def("columns",&FixedMatrix::cols) ; return c; } template int match_dimension(const FixedMatrix &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