8 #ifndef _PyImathFixedArray_h_
9 #define _PyImathFixedArray_h_
11 #define HBOOST_BIND_GLOBAL_PLACEHOLDERS
12 #include <hboost/python.hpp>
13 #include <hboost/operators.hpp>
14 #include <hboost/shared_array.hpp>
15 #include <hboost/any.hpp>
29 #define PY_IMATH_LEAVE_PYTHON PyImath::PyReleaseLock pyunlock;
30 #define PY_IMATH_RETURN_PYTHON
41 struct ReturnReference
55 static bool isReferenceWrap () {
return true; }
69 return applyReadOnly (val);
72 static bool isReferenceWrap () {
return false; }
100 hboost::shared_array<size_t> _indices;
101 size_t _unmaskedLength;
108 : _ptr(ptr), _length(length), _stride(
stride), _writable(
writable),
109 _handle(), _unmaskedLength(0)
113 throw std::domain_error (
"Fixed array length must be non-negative");
117 throw std::domain_error (
"Fixed array stride must be positive");
124 : _ptr(ptr), _length(length), _stride(stride), _writable(
writable),
125 _handle(handle), _unmaskedLength(0)
129 throw std::domain_error(
"Fixed array length must be non-negative");
133 throw std::domain_error(
"Fixed array stride must be positive");
139 : _ptr(const_cast<
T *>(ptr)), _length(length), _stride(
stride),
140 _writable(false), _handle(), _unmaskedLength(0)
144 throw std::logic_error(
"Fixed array length must be non-negative");
148 throw std::logic_error(
"Fixed array stride must be positive");
154 : _ptr(const_cast<
T *>(ptr)), _length(length), _stride(stride), _writable(false),
155 _handle(handle), _unmaskedLength(0)
159 throw std::logic_error(
"Fixed array length must be non-negative");
163 throw std::logic_error(
"Fixed array stride must be positive");
169 : _ptr(0), _length(length), _stride(1), _writable(true),
170 _handle(), _unmaskedLength(0)
173 throw std::domain_error(
"Fixed array length must be non-negative");
175 hboost::shared_array<T>
a(
new T[length]);
177 for (Py_ssize_t i=0; i<
length; ++i) a[i] = tmp;
183 : _ptr(0), _length(length), _stride(1), _writable(true),
184 _handle(), _unmaskedLength(0)
187 throw std::domain_error(
"Fixed array length must be non-negative");
189 hboost::shared_array<T>
a(
new T[length]);
195 : _ptr(0), _length(length), _stride(1), _writable(true),
196 _handle(), _unmaskedLength(0)
199 throw std::domain_error(
"Fixed array length must be non-negative");
201 hboost::shared_array<T>
a(
new T[length]);
202 for (Py_ssize_t i=0; i<
length; ++i) a[i] = initialValue;
207 template <
typename MaskArrayType>
209 : _ptr(f._ptr), _stride(f._stride), _writable(f._writable), _handle(f._handle), _unmaskedLength(0)
213 throw std::invalid_argument(
"Masking an already-masked FixedArray not supported yet (SQ27000)");
217 _unmaskedLength =
len;
219 size_t reduced_len = 0;
220 for (
size_t i = 0; i <
len; ++i)
224 _indices.reset(
new size_t[reduced_len]);
226 for (
size_t i = 0,
j = 0; i <
len; ++i)
235 _length = reduced_len;
238 template <
typename MaskArrayType>
240 : _ptr(f._ptr), _stride(f._stride), _writable(false), _handle(f._handle), _unmaskedLength(0)
244 throw std::invalid_argument(
"Masking an already-masked FixedArray not supported yet (SQ27000)");
248 _unmaskedLength =
len;
250 size_t reduced_len = 0;
251 for (
size_t i = 0; i <
len; ++i)
255 _indices.reset(
new size_t[reduced_len]);
257 for (
size_t i = 0,
j = 0; i <
len; ++i)
266 _length = reduced_len;
271 : _ptr(0), _length(other.
len()), _stride(1), _writable(true),
274 hboost::shared_array<T>
a(
new T[_length]);
275 for (
size_t i=0; i<_length; ++i) a[i] =
T(other[i]);
281 _indices.reset(
new size_t[_length]);
283 for (
size_t i = 0; i < _length; ++i)
289 : _ptr(other._ptr), _length(other._length), _stride(other._stride),
290 _writable(other._writable),
291 _handle(other._handle),
292 _indices(other._indices),
293 _unmaskedLength(other._unmaskedLength)
300 if (&other ==
this)
return *
this;
303 _length = other._length;
304 _stride = other._stride;
305 _writable = other._writable;
306 _handle = other._handle;
307 _unmaskedLength = other._unmaskedLength;
308 _indices = other._indices;
318 explicit operator bool()
const {
return _ptr !=
nullptr;}
329 if (index < 0) index +=
len();
330 if (index >=
len() || index < 0) {
331 PyErr_SetString(PyExc_IndexError,
"Index out of range");
332 hboost::python::throw_error_already_set();
339 if (PySlice_Check(index)) {
340 #if PY_MAJOR_VERSION > 2
341 PyObject *slice = index;
343 PySliceObject *slice =
reinterpret_cast<PySliceObject *
>(index);
346 if (PySlice_GetIndicesEx(slice,_length,&s,&e,&step,&sl) == -1) {
347 hboost::python::throw_error_already_set();
350 if (s < 0 || e < -1 || sl < 0) {
351 throw std::domain_error(
"Slice extraction produced invalid start, end, or length indices");
356 }
else if (PyInt_Check(index)) {
358 start = i; end = i+1; step = 1; slicelength = 1;
360 PyErr_SetString(PyExc_TypeError,
"Object is not a slice");
361 hboost::python::throw_error_already_set();
378 typedef typename hboost::mpl::if_<hboost::is_class<T>,
380 ReturnByValue<T> >
::type convertType;
383 int referenceMode = 0;
390 retval = convertType::applyWritable (val);
392 if (convertType::isReferenceWrap())
399 retval = convertType::applyReadOnly (val);
401 if (convertType::isReferenceWrap())
407 return hboost::python::make_tuple (referenceMode, retval);
412 typedef typename hboost::mpl::if_<hboost::is_class<T>,
414 ReturnByValue<T> >
::type convertType;
417 int referenceMode = 1;
422 retval = convertType::applyReadOnly (val);
424 if (convertType::isReferenceWrap())
429 return hboost::python::make_tuple (referenceMode, retval);
434 size_t start=0,
end=0, slicelength=0;
441 for (
size_t i=0; i<slicelength; ++i)
446 for (
size_t i=0; i<slicelength; ++i)
447 f._ptr[i] = _ptr[(start+i*step)*_stride];
452 template <
typename MaskArrayType>
464 throw std::invalid_argument(
"Fixed array is read-only.");
466 size_t start=0,
end=0, slicelength=0;
472 for (
size_t i=0; i<slicelength; ++i)
477 for (
size_t i=0; i<slicelength; ++i)
478 _ptr[(start+i*step)*_stride] =
data;
482 template <
typename MaskArrayType>
487 throw std::invalid_argument(
"Fixed array is read-only.");
493 for (
size_t i = 0; i <
len; ++i)
498 for (
size_t i=0; i<
len; ++i)
499 if (mask[i]) _ptr[i*_stride] =
data;
503 template <
typename ArrayType>
508 throw std::invalid_argument(
"Fixed array is read-only.");
510 size_t start=0,
end=0, slicelength=0;
515 if ((
size_t)data.len() != slicelength) {
516 PyErr_SetString(PyExc_IndexError,
"Dimensions of source do not match destination");
517 hboost::python::throw_error_already_set();
522 for (
size_t i=0; i<slicelength; ++i)
527 for (
size_t i=0; i<slicelength; ++i)
528 _ptr[(start+i*step)*_stride] = data[i];
532 template <
typename MaskArrayType,
typename ArrayType>
537 throw std::invalid_argument(
"Fixed array is read-only.");
544 throw std::invalid_argument(
"We don't support setting item masks for masked reference arrays.");
548 if ((
size_t)data.len() ==
len)
550 for (
size_t i = 0; i <
len; ++i)
551 if (mask[i]) _ptr[i*_stride] = data[i];
555 Py_ssize_t
count = 0;
556 for (
size_t i = 0; i <
len; ++i)
557 if (mask[i]) count++;
559 if (data.len() != count) {
560 throw std::invalid_argument(
"Dimensions of source data do not match destination either masked or unmasked");
563 Py_ssize_t dataIndex = 0;
564 for (
size_t i = 0; i <
len; ++i)
568 _ptr[i*_stride] = data[dataIndex];
576 Py_ssize_t
len()
const {
return _length; }
577 size_t stride()
const {
return _stride; }
590 throw std::invalid_argument(
"Fixed array is read-only.");
605 throw std::invalid_argument(
"Fixed array is read-only.");
607 return _ptr[i*_stride];
613 return _ptr[i*_stride];
625 return _ptr[i*_stride];
638 assert(_indices[i] >= 0 && _indices[i] < _unmaskedLength);
642 static hboost::python::class_<FixedArray<T> >
register_(
const char *doc)
656 hboost::python::class_<FixedArray<T> >
c(
name(),doc, hboost::python::init<size_t>(
"construct an array of the specified length initialized to the default value for the type"));
658 .def(hboost::python::init<
const FixedArray<T> &>(
"construct an array with the same values as the given array"))
659 .def(hboost::python::init<const T &,size_t>(
"construct an array of the specified length initialized to the specified default value"))
662 .def(
"__getitem__", const_getobject,
664 hboost::python::with_custodian_and_ward_postcall<0,1>,
665 hboost::python::return_value_policy<hboost::python::copy_const_reference>,
666 hboost::python::default_call_policies>())
667 .def(
"__getitem__", nonconst_getobject,
669 hboost::python::with_custodian_and_ward_postcall<0,1>,
670 hboost::python::return_value_policy<hboost::python::copy_const_reference>,
671 hboost::python::default_call_policies>())
685 template <
typename ArrayType>
688 if (
len() == a1.len())
691 bool throwExc =
false;
692 if (strictComparison)
696 if (static_cast<Py_ssize_t>(_unmaskedLength) != a1.len())
704 throw std::invalid_argument(
"Dimensions of source do not match destination");
714 for (
size_t i=0; i <
len; ++i) tmp[i] = choice[i] ? (*
this)[i] : other[i];
721 for (
size_t i=0; i <
len; ++i) tmp[i] = choice[i] ? (*
this)[i] : other;
726 static const char *
name();
738 throw std::invalid_argument (
"Fixed array is masked. ReadOnlyDirectAccess not granted.");
760 throw std::invalid_argument (
"Fixed array is read-only. WritableDirectAccess not granted.");
784 throw std::invalid_argument (
"Fixed array is not masked. ReadOnlyMaskedAccess not granted.");
809 std::invalid_argument (
"Fixed array is read-only. WritableMaskedAccess not granted.");
830 template <
class Container,
class Data>
833 static Data &
apply(Container &
c,
size_t i) {
return c[i]; }
836 template <
class Data>
843 template <
class Data>
850 template <
class Data>
857 template <
class Container,
class Data,
int Length,
class IndexAccess = IndexAccessDefault<Container,Data> >
860 static Py_ssize_t
len(
const Container &) {
return Length; }
865 if (index < 0) index += Length;
867 PyErr_SetString(PyExc_IndexError,
"Index out of range");
868 hboost::python::throw_error_already_set();
876 #endif // _PyImathFixedArray_h_
FixedArray(const T *ptr, Py_ssize_t length, Py_ssize_t stride, hboost::any handle)
void setitem_vector_mask(const MaskArrayType &mask, const ArrayType &data)
IMATH_INTERNAL_NAMESPACE::Vec2< Data > Container
size_t match_dimension(const ArrayType &a1, bool strictComparison=true) const
bool isMaskedReference() const
ReadOnlyDirectAccess(const FixedArray< T > &array)
get_type getitem(Py_ssize_t index)
FixedArray(const FixedArray< S > &other)
WritableMaskedAccess(FixedArray< T > &array)
#define IMATH_INTERNAL_NAMESPACE
WritableDirectAccess(FixedArray< T > &array)
static hboost::python::class_< FixedArray< T > > register_(const char *doc)
FixedArray< T > ifelse_scalar(const FixedArray< int > &choice, const T &other)
FixedArray(const T &initialValue, Py_ssize_t length)
FixedArray(const FixedArray &other)
static Data & apply(Container &c, size_t i)
FixedArray(const FixedArray &f, const MaskArrayType &mask)
const T & operator[](size_t i) const
hboost::mpl::if_< hboost::is_class< T >, const T &, T >::type get_type_const
GLboolean GLboolean GLboolean GLboolean a
GLuint GLsizei GLsizei * length
static Data & apply(Container &c, size_t i)
static Data & apply(Container &c, size_t i)
IMATH_INTERNAL_NAMESPACE::Vec3< Data > Container
WritableDirectAccess(const WritableDirectAccess &other)
WritableMaskedAccess(const WritableMaskedAccess &other)
static const char * name()
IMATH_INTERNAL_NAMESPACE::Vec4< Data > Container
size_t raw_ptr_index(size_t i) const
const T & direct_index(size_t i) const
ReadOnlyDirectAccess(const ReadOnlyDirectAccess &other)
T & direct_index(size_t i)
hboost::shared_array< size_t > _indices
hboost::mpl::if_< hboost::is_class< T >, T &, T >::type get_type
FixedArray(const T *ptr, Py_ssize_t length, Py_ssize_t stride=1)
GLint GLint GLsizei GLint GLenum GLenum type
void setitem_vector(::PyObject *index, const ArrayType &data)
bool any(const vbool4 &v)
size_t canonical_index(Py_ssize_t index) const
FixedArray(Py_ssize_t length, Uninitialized)
FixedArray(Py_ssize_t length)
const hboost::any & handle()
GLint GLenum GLboolean GLsizei stride
hboost::python::object getobjectTuple(Py_ssize_t index) const
void setitem_scalar(PyObject *index, const T &data)
size_t unmaskedLength() const
FixedArray< T > ifelse_vector(const FixedArray< int > &choice, const FixedArray< T > &other)
T & unchecked_index(size_t i)
void setitem_scalar_mask(const MaskArrayType &mask, const T &data)
const T & operator[](size_t i) const
const FixedArray & operator=(const FixedArray &other)
FixedArray getslice(::PyObject *index) const
FixedArray(T *ptr, Py_ssize_t length, Py_ssize_t stride=1, bool writable=true)
T & unchecked_direct_index(size_t i)
ReadOnlyMaskedAccess(const ReadOnlyMaskedAccess &other)
static IndexAccess::result_type getitem(Container &c, Py_ssize_t index)
FixedArray(T *ptr, Py_ssize_t length, Py_ssize_t stride, hboost::any handle, bool writable=true)
FixedArray getslice_mask(const MaskArrayType &mask)
static Data & apply(Container &c, size_t i)
static void setitem(Container &c, Py_ssize_t index, const Data &data)
static Py_ssize_t len(const Container &)
ReadOnlyMaskedAccess(const FixedArray< T > &array)
void extract_slice_indices(PyObject *index, size_t &start, size_t &end, Py_ssize_t &step, size_t &slicelength) const
FixedArray(FixedArray &f, const MaskArrayType &mask)
hboost::python::object getobjectTuple(Py_ssize_t index)
get_type_const getitem(Py_ssize_t index) const
static size_t canonical_index(Py_ssize_t index)