HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PyImathFixedArray2D.h
Go to the documentation of this file.
1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright Contributors to the OpenEXR Project.
4 //
5 
6 // clang-format off
7 
8 #ifndef _PyImathFixedArray2D_h_
9 #define _PyImathFixedArray2D_h_
10 
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>
16 #include <iostream>
17 #include <ImathVec.h>
18 #include "PyImathFixedArray.h"
19 #include "PyImathOperators.h"
20 
21 namespace PyImath {
22 
23 template <class T>
25 {
26  T * _ptr;
27  IMATH_NAMESPACE::Vec2<size_t> _length;
28  IMATH_NAMESPACE::Vec2<size_t> _stride;
29  size_t _size; //flattened size of the array
30 
31  // this handle optionally stores a shared_array to allocated array data
32  // so that everything is freed properly on exit.
33  hboost::any _handle;
34 
35  public:
36 
37  FixedArray2D(T *ptr, Py_ssize_t lengthX, Py_ssize_t lengthY, Py_ssize_t strideX = 1)
38  : _ptr(ptr), _length(lengthX, lengthY), _stride(strideX, lengthX), _handle()
39  {
40  if (lengthX < 0 || lengthY < 0)
41  throw std::domain_error("Fixed array 2d lengths must be non-negative");
42  if (strideX <= 0)
43  throw std::domain_error("Fixed array 2d strides must be positive");
45  //std::cout << "fixed array external construct" << std::endl;
46  // nothing
47  }
48 
49  FixedArray2D(T *ptr, Py_ssize_t lengthX, Py_ssize_t lengthY, Py_ssize_t strideX, Py_ssize_t strideY)
50  : _ptr(ptr), _length(lengthX, lengthY), _stride(strideX, strideY), _handle()
51  {
52  if (lengthX < 0 || lengthY < 0)
53  throw std::domain_error("Fixed array 2d lengths must be non-negative");
54  if (strideX <= 0 || strideY < 0)
55  throw std::domain_error("Fixed array 2d strides must be positive");
57  //std::cout << "fixed array external construct" << std::endl;
58  // nothing
59  }
60 
61  FixedArray2D(T *ptr, Py_ssize_t lengthX, Py_ssize_t lengthY, Py_ssize_t strideX, Py_ssize_t strideY, hboost::any handle)
62  : _ptr(ptr), _length(lengthX, lengthY), _stride(strideX, strideY), _handle(handle)
63  {
65  //std::cout << "fixed array external construct with handle" << std::endl;
66  // nothing
67  }
68 
69  explicit FixedArray2D(Py_ssize_t lengthX, Py_ssize_t lengthY)
70  : _ptr(0), _length(lengthX, lengthY), _stride(1, lengthX), _handle()
71  {
72  if (lengthX < 0 || lengthY < 0)
73  throw std::domain_error("Fixed array 2d lengths must be non-negative");
76  hboost::shared_array<T> a(new T[_size]);
77  for (size_t i=0; i<_size; ++i) a[i] = tmp;
78  _handle = a;
79  _ptr = a.get();
80  }
81 
83  : _ptr(0), _length(length), _stride(1, length.x), _handle()
84  {
85  if (length.x < 0 || length.y < 0)
86  throw std::domain_error("Fixed array 2d lengths must be non-negative");
89  hboost::shared_array<T> a(new T[_size]);
90  for (size_t i=0; i<_size; ++i) a[i] = tmp;
91  _handle = a;
92  _ptr = a.get();
93  }
94 
95  FixedArray2D(const T &initialValue, Py_ssize_t lengthX, Py_ssize_t lengthY)
96  : _ptr(0), _length(lengthX, lengthY), _stride(1, lengthX), _handle()
97  {
98  if (lengthX < 0 || lengthY < 0)
99  throw std::domain_error("Fixed array 2d lengths must be non-negative");
100  initializeSize();
101  hboost::shared_array<T> a(new T[_size]);
102  for (size_t i=0; i<_size; ++i) a[i] = initialValue;
103  _handle = a;
104  _ptr = a.get();
105  }
107  {
108  _size = _length.x*_length.y;
109  }
110 
111  template <class S>
112  explicit FixedArray2D(const FixedArray2D<S> &other)
113  : _ptr(0), _length(other.len()), _stride(1, other.len().x), _handle()
114  {
115  initializeSize();
116  hboost::shared_array<T> a(new T[_size]);
117  size_t z = 0;
118  for (size_t j = 0; j < _length.y; ++j)
119  for (size_t i = 0; i < _length.x; ++i)
120  a[z++] = T(other(i,j));
121  _handle = a;
122  _ptr = a.get();
123  }
124 
126  : _ptr(other._ptr), _length(other._length), _stride(other._stride), _size(other._size), _handle(other._handle)
127  {
128  //std::cout << "fixed array copy consturct construct" << std::endl;
129  // nothing
130  }
131 
132  const FixedArray2D &
133  operator = (const FixedArray2D &other)
134  {
135  if (&other == this) return *this;
136 
137  //std::cout << "fixed array assign" << std::endl;
138 
139  _ptr = other._ptr;
140  _length = other._length;
141  _stride = other._stride;
142  _handle = other._handle;
143 
144  _size = _length.x*_length.y;
145 
146  return *this;
147  }
148 
150  {
151  //std::cout << "fixed array delete" << std::endl;
152  }
153 
154  const hboost::any & handle() { return _handle; }
155 
156  size_t canonical_index(Py_ssize_t index, size_t length) const
157  {
158  if (index < 0) index += length;
159  if ((size_t) index >= length || index < 0) {
160  PyErr_SetString(PyExc_IndexError, "Index out of range");
161  hboost::python::throw_error_already_set();
162  }
163  return index;
164  }
165 
166  void extract_slice_indices(PyObject *index, size_t length, size_t &start, size_t &end, Py_ssize_t &step, size_t &slicelength) const
167  {
168  if (PySlice_Check(index)) {
169 #if PY_MAJOR_VERSION > 2
170  PyObject *slice = index;
171 #else
172  PySliceObject *slice = reinterpret_cast<PySliceObject *>(index);
173 #endif
174  Py_ssize_t s, e, sl;
175  if (PySlice_GetIndicesEx(slice,length,&s,&e,&step,&sl) == -1) {
176  hboost::python::throw_error_already_set();
177  }
178  if (s < 0 || e < 0 || sl < 0) {
179  throw std::domain_error("Slice extraction produced invalid start, end, or length indices");
180  }
181  start = s;
182  end = e;
183  slicelength = sl;
184  } else if (PyInt_Check(index)) {
185  size_t i = canonical_index(PyInt_AsSsize_t(index), length);
186  start = i; end = i+1; step = 1; slicelength = 1;
187  } else {
188  PyErr_SetString(PyExc_TypeError, "Object is not a slice");
189  hboost::python::throw_error_already_set();
190  }
191  //std::cout << "Slice indices are " << start << " " << end << " " << step << " " << slicelength << std::endl;
192  }
193 
194  // return_internal_reference doesn't seem to work with non-class types
195  typedef typename hboost::mpl::if_<hboost::is_class<T>,T&,T>::type get_type;
196 // get_type getitem(Py_ssize_t index) const { return _ptr[canonical_index(index)*_stride]; }
197  //FIXME: const does not work here with at least IMATH_NAMESPACE::Color4, why it works for V3fArray?
198  get_type getitem(Py_ssize_t i, Py_ssize_t j) //const
199  {
200  return (*this)(canonical_index(i, _length.x), canonical_index(j, _length.y));
201  }
202 
203  //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
204  FixedArray2D getslice(PyObject *index) const
205  {
206  if (PyTuple_Check(index) && PyTuple_Size(index) == 2)
207  {
208  size_t startx=0, endx=0, slicelengthx=0;
209  size_t starty=0, endy=0, slicelengthy=0;
210  Py_ssize_t stepx=0;
211  Py_ssize_t stepy=0;
212  extract_slice_indices(PyTuple_GetItem(index, 0),_length.x,startx,endx,stepx,slicelengthx);
213  extract_slice_indices(PyTuple_GetItem(index, 1),_length.y,starty,endy,stepy,slicelengthy);
214  FixedArray2D f(slicelengthx, slicelengthy);
215  for (size_t j=0,z=0; j<slicelengthy; j++)
216  for (size_t i=0; i<slicelengthx; ++i)
217  f._ptr[z++] = (*this)(startx+i*stepx, starty+j*stepy);
218  return f;
219  }
220  else
221  {
222  PyErr_SetString(PyExc_TypeError, "Slice syntax error");
223  hboost::python::throw_error_already_set();
224  }
225  return FixedArray2D(0,0);
226  }
227 
228  //FIXME: for 2D array, cannot reduce the size, or maybe returning 1D array?
230  {
231 // size_t len = match_dimension(mask);
232 // size_t slicelength = 0;
233 // for (size_t i=0; i<len; ++i) if (mask[i]) slicelength++;
234 // FixedArray2D f(slicelength, _length.y);
235 // for (size_t i=0,z=0; i<len; ++i) {
236 // if (mask[i]) {
237 // for (size_t j = 0; j < _length.y; j++)
238 // f._ptr[z++] = (*this)(i,j);
239 // }
240 // }
241 // return f;
242  IMATH_NAMESPACE::Vec2<size_t> len = match_dimension(mask);
243  FixedArray2D f(len);
244  for (size_t j=0; j<len.y; j++)
245  for (size_t i=0; i<len.x; i++)
246  if (mask(i,j))
247  f(i,j) = (*this)(i,j);
248  return f;
249  }
250 
251 // void setitem(const hboost::python::tuple& index, const T &data)
252 // {
253 // Py_ssize_t i = hboost::python::extract<Py_ssize_t>(index[0]);
254 // Py_ssize_t j = hboost::python::extract<Py_ssize_t>(index[1]);
255 // (*this)(i,j) = data;
256 // }
257  void
258  setitem_scalar(PyObject *index, const T &data)
259  {
260  if (!PyTuple_Check(index) || PyTuple_Size(index) != 2)
261  {
262  PyErr_SetString(PyExc_TypeError, "Slice syntax error");
263  hboost::python::throw_error_already_set();
264  }
265 
266  size_t startx=0, endx=0, slicelengthx=0;
267  size_t starty=0, endy=0, slicelengthy=0;
268  Py_ssize_t stepx=0;
269  Py_ssize_t stepy=0;
270  extract_slice_indices(PyTuple_GetItem(index, 0),_length.x,startx,endx,stepx,slicelengthx);
271  extract_slice_indices(PyTuple_GetItem(index, 1),_length.y,starty,endy,stepy,slicelengthy);
272  for (size_t j=0; j<slicelengthy; j++)
273  for (size_t i=0; i<slicelengthx; ++i)
274  (*this)(startx+i*stepx, starty+j*stepy) = data;
275  }
276 
277  void
279  {
280  IMATH_NAMESPACE::Vec2<size_t> len = match_dimension(mask);
281  for (size_t j = 0; j < len.y; j++)
282  for (size_t i=0; i<len.x; ++i)
283  if (mask(i,j))
284  (*this)(i,j) = data;
285  }
286 
287  void
289  {
290  //TODO:sanity check
291  size_t startx=0, endx=0, slicelengthx=0;
292  size_t starty=0, endy=0, slicelengthy=0;
293  Py_ssize_t stepx=0;
294  Py_ssize_t stepy=0;
295  extract_slice_indices(PyTuple_GetItem(index, 0),_length.x,startx,endx,stepx,slicelengthx);
296  extract_slice_indices(PyTuple_GetItem(index, 1),_length.y,starty,endy,stepy,slicelengthy);
297  // we have a valid range of indices
298  if (data.len() != IMATH_NAMESPACE::Vec2<size_t>(slicelengthx, slicelengthy)) {
299  PyErr_SetString(PyExc_IndexError, "Dimensions of source do not match destination");
300  hboost::python::throw_error_already_set();
301  }
302  for (size_t i=0; i<slicelengthx; ++i)
303  for (size_t j=0; j<slicelengthy; ++j)
304  (*this)(startx+i*stepx, starty+j*stepy) = data(i,j);
305  }
306 
307  void
309  {
310  IMATH_NAMESPACE::Vec2<size_t> len = match_dimension(mask);
311  if (data.len() == len) {
312  for (size_t j = 0; j < len.y; j++)
313  for (size_t i=0; i<len.x; ++i)
314  if (mask(i,j))
315  (*this)(i,j) = data(i,j);
316  } else {
317  PyErr_SetString(PyExc_IndexError, "Dimensions of source data do not match destination");
318  hboost::python::throw_error_already_set();
319  }
320  }
321 
322  void
324  {
325  IMATH_NAMESPACE::Vec2<size_t> len = match_dimension(mask);
326  if ((size_t) data.len() == len.x*len.y) {
327  for (size_t j = 0, z = 0; j < len.y; j++)
328  for (size_t i=0; i<len.x; ++i, ++z)
329  if (mask(i,j))
330  (*this)(i,j) = data[z];
331  } else {
332  size_t count = 0;
333  for (size_t j = 0, z = 0; j < len.y; j++)
334  for (size_t i=0; i<len.x; ++i, ++z)
335  if (mask(i,j)) count++;
336 
337  if ((size_t) data.len() != count) {
338  PyErr_SetString(PyExc_IndexError, "Dimensions of source data do not match destination either masked or unmasked");
339  hboost::python::throw_error_already_set();
340  }
341 
342  for (size_t j = 0, z = 0; j < len.y; j++)
343  for (size_t i=0; i<len.x; ++i)
344  if (mask(i,j))
345  (*this)(i,j) = data[z++];
346  }
347  }
348 
349  void
351  {
352  //TODO:sanity check
353  size_t startx=0, endx=0, slicelengthx=0;
354  size_t starty=0, endy=0, slicelengthy=0;
355  Py_ssize_t stepx=0;
356  Py_ssize_t stepy=0;
357  extract_slice_indices(PyTuple_GetItem(index, 0),_length.x,startx,endx,stepx,slicelengthx);
358  extract_slice_indices(PyTuple_GetItem(index, 1),_length.y,starty,endy,stepy,slicelengthy);
359  // we have a valid range of indices
360  if ((size_t) data.len() != slicelengthx*slicelengthy) {
361  PyErr_SetString(PyExc_IndexError, "Dimensions of source data do not match destination");
362  hboost::python::throw_error_already_set();
363  }
364  for (size_t j=0, z=0; j<slicelengthy; ++j)
365  for (size_t i=0; i<slicelengthx; ++i, ++z)
366  (*this)(startx+i*stepx, starty+j*stepy) = data[z];
367  }
368 
369  IMATH_NAMESPACE::Vec2<size_t> len() const { return _length; }
370  IMATH_NAMESPACE::Vec2<size_t> stride() const { return _stride; }
371  T & operator () (size_t i, size_t j) { return _ptr[_stride.x*(j*_stride.y + i)]; }
372  const T & operator () (size_t i, size_t j) const { return _ptr[_stride.x*(j*_stride.y + i)]; }
373  size_t totalLen() const { return _size; }
374  hboost::python::tuple size() const
375  {
376  return hboost::python::make_tuple(_length.x, _length.y);
377  }
378 
379  static hboost::python::class_<FixedArray2D<T> > register_(const char *name, const char *doc)
380  {
381  // a little tricky, but here we go - class types return internal references
382  // but fundemental types just get copied. this typedef sets up the appropriate
383  // call policy for each type.
384  typedef typename hboost::mpl::if_<
385  hboost::is_class<T>,
386  hboost::python::return_internal_reference<>,
387  hboost::python::default_call_policies>::type call_policy;
388 
389  hboost::python::class_<FixedArray2D<T> > c(name,doc, hboost::python::init<size_t, size_t>(
390  "construct an array of the specified length initialized to the default value for the type"));
391  c
392  .def(hboost::python::init<const FixedArray2D<T> &>("construct an array with the same values as the given array"))
393  .def(hboost::python::init<const T &,size_t,size_t>("construct an array of the specified length initialized to the specified default value"))
394  .def("__getitem__", &FixedArray2D<T>::getslice)
395  .def("__getitem__", &FixedArray2D<T>::getslice_mask)
396 // .def("__getitem__", &FixedArray2D<T>::getitem, call_policy())
397  .def("item", &FixedArray2D<T>::getitem, call_policy())
398 // .def("__setitem__", &FixedArray2D<T>::setitem)
399  .def("__setitem__", &FixedArray2D<T>::setitem_scalar)
400  .def("__setitem__", &FixedArray2D<T>::setitem_scalar_mask)
401  .def("__setitem__", &FixedArray2D<T>::setitem_vector)
402  .def("__setitem__", &FixedArray2D<T>::setitem_vector_mask)
403  .def("__setitem__", &FixedArray2D<T>::setitem_array1d)
404  .def("__setitem__", &FixedArray2D<T>::setitem_array1d_mask)
405  .def("__len__",&FixedArray2D<T>::totalLen)
406  .def("size",&FixedArray2D<T>::size)
407  .def("ifelse",&FixedArray2D<T>::ifelse_scalar)
408  .def("ifelse",&FixedArray2D<T>::ifelse_vector)
409  ;
410  return c;
411  }
412 
413 // template <class T2>
414 // size_t match_dimension(const FixedArray<T2> &a1) const
415 // {
416 // if (_length.x != a1.len()) {
417 // PyErr_SetString(PyExc_IndexError, "Dimensions of source do not match destination");
418 // hboost::python::throw_error_already_set();
419 // }
420 // return _length.x;
421 // }
422 
423  template <class T2>
424  IMATH_NAMESPACE::Vec2<size_t> match_dimension(const FixedArray2D<T2> &a1) const
425  {
426  if (len() != a1.len()) {
427  PyErr_SetString(PyExc_IndexError, "Dimensions of source do not match destination");
428  hboost::python::throw_error_already_set();
429  }
430  return len();
431  }
432 
434  IMATH_NAMESPACE::Vec2<size_t> len = match_dimension(choice);
435  match_dimension(other);
436  FixedArray2D<T> tmp(len); // should use default construction but V3f doens't initialize
437  for (size_t j = 0; j < len.y; ++j)
438  for (size_t i = 0; i < len.x; ++i)
439  tmp(i,j) = choice(i,j) ? (*this)(i,j) : other(i,j);
440  return tmp;
441  }
442 
443  FixedArray2D<T> ifelse_scalar(const FixedArray2D<int> &choice, const T &other) {
444  IMATH_NAMESPACE::Vec2<size_t> len = match_dimension(choice);
445  FixedArray2D<T> tmp(len); // should use default construction but V3f doens't initialize
446  for (size_t j = 0; j < len.y; ++j)
447  for (size_t i = 0; i < len.x; ++i)
448  tmp(i,j) = choice(i,j) ? (*this)(i,j) : other;
449  return tmp;
450  }
451 
452 };
453 
454 // unary operation application
455 template <template <class,class> class Op, class T1, class Ret>
457 {
458  IMATH_NAMESPACE::Vec2<size_t> len = a1.len();
459  FixedArray2D<Ret> retval(len.x,len.y);
460  for (size_t j=0; j<len.y; ++j) {
461  for (size_t i=0;i<len.x;++i) {
462  retval(i,j) = Op<T1,Ret>::apply(a1(i,j));
463  }
464  }
465  return retval;
466 }
467 
468 // binary operation application
469 template <template <class,class,class> class Op, class T1, class T2, class Ret>
471 {
472  IMATH_NAMESPACE::Vec2<size_t> len = a1.match_dimension(a2);
473  FixedArray2D<Ret> retval(len.x,len.y);
474  for (size_t j=0; j<len.y; ++j) {
475  for (size_t i=0;i<len.x;++i) {
476  retval(i,j) = Op<T1,T2,Ret>::apply(a1(i,j),a2(i,j));
477  }
478  }
479  return retval;
480 }
481 
482 template <template <class,class,class> class Op, class T1, class T2, class Ret>
484 {
485  IMATH_NAMESPACE::Vec2<size_t> len = a1.len();
486  FixedArray2D<Ret> retval(len.x,len.y);
487  for (size_t j=0; j<len.y; ++j) {
488  for (size_t i=0;i<len.x;++i) {
489  retval(i,j) = Op<T1,T2,Ret>::apply(a1(i,j),a2);
490  }
491  }
492  return retval;
493 }
494 
495 template <template <class,class,class> class Op, class T1, class T2, class Ret>
497 {
498  IMATH_NAMESPACE::Vec2<size_t> len = a1.len();
499  FixedArray2D<Ret> retval(len.x,len.y);
500  for (size_t j=0; j<len.y; ++j) {
501  for (size_t i=0;i<len.x;++i) {
502  retval(i,j) = Op<T2,T1,Ret>::apply(a2,a1(i,j));
503  }
504  }
505  return retval;
506 }
507 
508 // in-place binary operation application
509 template <template <class,class> class Op, class T1, class T2>
511 {
512  IMATH_NAMESPACE::Vec2<size_t> len = a1.match_dimension(a2);
513  for (size_t j=0; j<len.y; ++j) {
514  for (size_t i=0;i<len.x;++i) {
515  Op<T1,T2>::apply(a1(i,j),a2(i,j));
516  }
517  }
518  return a1;
519 }
520 
521 // in-place binary operation application
522 template <template <class,class> class Op, class T1, class T2>
524 {
525  IMATH_NAMESPACE::Vec2<size_t> len = a1.len();
526  for (size_t j=0; j<len.y; ++j) {
527  for (size_t i=0;i<len.x;++i) {
528  Op<T1,T2>::apply(a1(i,j),a2);
529  }
530  }
531  return a1;
532 }
533 
534 
535 // PyObject* PyNumber_Add( PyObject *o1, PyObject *o2)
536 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); }
537 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); }
538 template <class T> static FixedArray2D<T> operator + (const T &v1, const FixedArray2D<T> &a0) { return a0+v1; }
539 
540 // PyObject* PyNumber_Subtract( PyObject *o1, PyObject *o2)
541 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); }
542 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); }
543 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); }
544 
545 // PyObject* PyNumber_Multiply( PyObject *o1, PyObject *o2)
546 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); }
547 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); }
548 template <class T> static FixedArray2D<T> operator * (const T &v1, const FixedArray2D<T> &a0) { return a0*v1; }
549 
550 // PyObject* PyNumber_Divide( PyObject *o1, PyObject *o2)
551 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); }
552 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); }
553 // no reversed scalar/array2d divide - no meaning
554 
555 // PyObject* PyNumber_FloorDivide( PyObject *o1, PyObject *o2)
556 // PyObject* PyNumber_TrueDivide( PyObject *o1, PyObject *o2)
557 // PyObject* PyNumber_Remainder( PyObject *o1, PyObject *o2)
558 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); }
559 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); }
560 // no reversed scalar%array2d remainder - no meaning
561 
562 // PyObject* PyNumber_Divmod( PyObject *o1, PyObject *o2)
563 
564 // PyObject* PyNumber_Power( PyObject *o1, PyObject *o2, PyObject *o3)
565 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); }
566 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); }
567 // no reversed scalar/array2d pow - no meaning
568 
569 // PyObject* PyNumber_Negative( PyObject *o)
570 template <class T> static FixedArray2D<T> operator - (const FixedArray2D<T> &a0) { return apply_array2d_unary_op<op_neg,T,T>(a0); }
571 
572 // PyObject* PyNumber_Positive( PyObject *o)
573 
574 // PyObject* PyNumber_Absolute( PyObject *o)
575 template <class T> static FixedArray2D<T> abs (const FixedArray2D<T> &a0) { return apply_array2d_unary_op<op_abs,T,T>(a0); }
576 
577 // PyObject* PyNumber_Invert( PyObject *o)
578 template <class T> static FixedArray2D<T> operator ~ (const FixedArray2D<T> &a0) { return apply_array2d_unary_op<op_inverse,T,T>(a0); }
579 
580 // PyObject* PyNumber_Lshift( PyObject *o1, PyObject *o2)
581 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); }
582 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); }
583 // no reversed
584 
585 // PyObject* PyNumber_Rshift( PyObject *o1, PyObject *o2)
586 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); }
587 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); }
588 // no reversed
589 
590 // PyObject* PyNumber_And( PyObject *o1, PyObject *o2)
591 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); }
592 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); }
593 template <class T> static FixedArray2D<T> operator & (const T &v1, const FixedArray2D<T> &a0) { return a0&v1; }
594 
595 // PyObject* PyNumber_Xor( PyObject *o1, PyObject *o2)
596 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); }
597 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); }
598 template <class T> static FixedArray2D<T> operator ^ (const T &v1, const FixedArray2D<T> &a0) { return a0^v1; }
599 
600 // PyObject* PyNumber_Or( PyObject *o1, PyObject *o2)
601 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); }
602 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); }
603 template <class T> static FixedArray2D<T> operator | (const T &v1, const FixedArray2D<T> &a0) { return a0|v1; }
604 
605 
606 // PyObject* PyNumber_InPlaceAdd( PyObject *o1, PyObject *o2)
607 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); }
608 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); }
609 
610 // PyObject* PyNumber_InPlaceSubtract( PyObject *o1, PyObject *o2)
611 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); }
612 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); }
613 
614 // PyObject* PyNumber_InPlaceMultiply( PyObject *o1, PyObject *o2)
615 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); }
616 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); }
617 
618 // PyObject* PyNumber_InPlaceDivide( PyObject *o1, PyObject *o2)
619 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); }
620 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); }
621 
622 // PyObject* PyNumber_InPlaceFloorDivide( PyObject *o1, PyObject *o2)
623 // not implemented
624 
625 // PyObject* PyNumber_InPlaceTrueDivide( PyObject *o1, PyObject *o2)
626 // not implemented
627 
628 // PyObject* PyNumber_InPlaceRemainder( PyObject *o1, PyObject *o2)
629 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); }
630 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); }
631 
632 // PyObject* PyNumber_InPlacePower( PyObject *o1, PyObject *o2, PyObject *o3)
633 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); }
634 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); }
635 
636 // PyObject* PyNumber_InPlaceLshift( PyObject *o1, PyObject *o2)
637 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); }
638 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); }
639 
640 // PyObject* PyNumber_InPlaceRshift( PyObject *o1, PyObject *o2)
641 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); }
642 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); }
643 
644 // PyObject* PyNumber_InPlaceAnd( PyObject *o1, PyObject *o2)
645 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); }
646 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); }
647 
648 // PyObject* PyNumber_InPlaceXor( PyObject *o1, PyObject *o2)
649 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); }
650 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); }
651 
652 // PyObject* PyNumber_InPlaceOr( PyObject *o1, PyObject *o2)
653 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); }
654 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); }
655 
656 template <class T>
657 static void add_arithmetic_math_functions(hboost::python::class_<FixedArray2D<T> > &c) {
658  using namespace hboost::python;
659  c
660  .def("__add__",&apply_array2d_array2d_binary_op<op_add,T,T,T>)
661  .def("__add__",&apply_array2d_scalar_binary_op<op_add,T,T,T>)
662  .def("__radd__",&apply_array2d_scalar_binary_rop<op_add,T,T,T>)
663  .def("__sub__",&apply_array2d_array2d_binary_op<op_sub,T,T,T>)
664  .def("__sub__",&apply_array2d_scalar_binary_op<op_sub,T,T,T>)
665  .def("__rsub__",&apply_array2d_scalar_binary_op<op_rsub,T,T,T>)
666  .def("__mul__",&apply_array2d_array2d_binary_op<op_mul,T,T,T>)
667  .def("__mul__",&apply_array2d_scalar_binary_op<op_mul,T,T,T>)
668  .def("__rmul__",&apply_array2d_scalar_binary_rop<op_mul,T,T,T>)
669  .def("__div__",&apply_array2d_array2d_binary_op<op_div,T,T,T>)
670  .def("__div__",&apply_array2d_scalar_binary_op<op_div,T,T,T>)
671  .def("__truediv__",&apply_array2d_array2d_binary_op<op_div,T,T,T>)
672  .def("__truediv__",&apply_array2d_scalar_binary_op<op_div,T,T,T>)
673  .def("__neg__",&apply_array2d_unary_op<op_neg,T,T>)
674  .def("__iadd__",&apply_array2d_array2d_ibinary_op<op_iadd,T,T>,return_internal_reference<>())
675  .def("__iadd__",&apply_array2d_scalar_ibinary_op<op_iadd,T,T>,return_internal_reference<>())
676  .def("__isub__",&apply_array2d_array2d_ibinary_op<op_isub,T,T>,return_internal_reference<>())
677  .def("__isub__",&apply_array2d_scalar_ibinary_op<op_isub,T,T>,return_internal_reference<>())
678  .def("__imul__",&apply_array2d_array2d_ibinary_op<op_imul,T,T>,return_internal_reference<>())
679  .def("__imul__",&apply_array2d_scalar_ibinary_op<op_imul,T,T>,return_internal_reference<>())
680  .def("__idiv__",&apply_array2d_array2d_ibinary_op<op_idiv,T,T>,return_internal_reference<>())
681  .def("__idiv__",&apply_array2d_scalar_ibinary_op<op_idiv,T,T>,return_internal_reference<>())
682  .def("__itruediv__",&apply_array2d_array2d_ibinary_op<op_idiv,T,T>,return_internal_reference<>())
683  .def("__itruediv__",&apply_array2d_scalar_ibinary_op<op_idiv,T,T>,return_internal_reference<>())
684  ;
685 }
686 
687 
688 template <class T>
689 static void add_pow_math_functions(hboost::python::class_<FixedArray2D<T> > &c) {
690  using namespace hboost::python;
691  c
692  .def("__pow__",&apply_array2d_array2d_binary_op<op_pow,T,T,T>)
693  .def("__pow__",&apply_array2d_scalar_binary_op<op_pow,T,T,T>)
694  .def("__rpow__",&apply_array2d_scalar_binary_rop<op_rpow,T,T,T>)
695  .def("__ipow__",&apply_array2d_array2d_ibinary_op<op_ipow,T,T>,return_internal_reference<>())
696  .def("__ipow__",&apply_array2d_scalar_ibinary_op<op_ipow,T,T>,return_internal_reference<>())
697  ;
698 }
699 
700 template <class T>
701 static void add_mod_math_functions(hboost::python::class_<FixedArray2D<T> > &c) {
702  using namespace hboost::python;
703  c
704  .def("__mod__",&apply_array2d_array2d_binary_op<op_mod,T,T,T>)
705  .def("__mod__",&apply_array2d_scalar_binary_op<op_mod,T,T,T>)
706  .def("__imod__",&apply_array2d_array2d_ibinary_op<op_imod,T,T>,return_internal_reference<>())
707  .def("__imod__",&apply_array2d_scalar_ibinary_op<op_imod,T,T>,return_internal_reference<>())
708  ;
709 }
710 
711 template <class T>
712 static void add_shift_math_functions(hboost::python::class_<FixedArray2D<T> > &c) {
713  using namespace hboost::python;
714  c
715  .def("__lshift__",&apply_array2d_array2d_binary_op<op_lshift,T,T,T>)
716  .def("__lshift__",&apply_array2d_scalar_binary_op<op_lshift,T,T,T>)
717  .def("__ilshift__",&apply_array2d_array2d_ibinary_op<op_ilshift,T,T>,return_internal_reference<>())
718  .def("__ilshift__",&apply_array2d_scalar_ibinary_op<op_ilshift,T,T>,return_internal_reference<>())
719  .def("__rshift__",&apply_array2d_array2d_binary_op<op_rshift,T,T,T>)
720  .def("__rshift__",&apply_array2d_scalar_binary_op<op_rshift,T,T,T>)
721  .def("__irshift__",&apply_array2d_array2d_ibinary_op<op_irshift,T,T>,return_internal_reference<>())
722  .def("__irshift__",&apply_array2d_scalar_ibinary_op<op_irshift,T,T>,return_internal_reference<>())
723  ;
724 }
725 
726 template <class T>
727 static void add_bitwise_math_functions(hboost::python::class_<FixedArray2D<T> > &c) {
728  using namespace hboost::python;
729  c
730  .def("__and__",&apply_array2d_array2d_binary_op<op_bitand,T,T,T>)
731  .def("__and__",&apply_array2d_scalar_binary_op<op_bitand,T,T,T>)
732  .def("__iand__",&apply_array2d_array2d_ibinary_op<op_ibitand,T,T>,return_internal_reference<>())
733  .def("__iand__",&apply_array2d_scalar_ibinary_op<op_ibitand,T,T>,return_internal_reference<>())
734  .def("__or__",&apply_array2d_array2d_binary_op<op_bitor,T,T,T>)
735  .def("__or__",&apply_array2d_scalar_binary_op<op_bitor,T,T,T>)
736  .def("__ior__",&apply_array2d_array2d_ibinary_op<op_ibitor,T,T>,return_internal_reference<>())
737  .def("__ior__",&apply_array2d_scalar_ibinary_op<op_ibitor,T,T>,return_internal_reference<>())
738  .def("__xor__",&apply_array2d_array2d_binary_op<op_xor,T,T,T>)
739  .def("__xor__",&apply_array2d_scalar_binary_op<op_xor,T,T,T>)
740  .def("__ixor__",&apply_array2d_array2d_ibinary_op<op_ixor,T,T>,return_internal_reference<>())
741  .def("__ixor__",&apply_array2d_scalar_ibinary_op<op_ixor,T,T>,return_internal_reference<>())
742  ;
743 }
744 
745 template <class T>
746 static void add_comparison_functions(hboost::python::class_<FixedArray2D<T> > &c) {
747  using namespace hboost::python;
748  c
749  .def("__eq__",&apply_array2d_array2d_binary_op<op_eq,T,T,int>)
750  .def("__eq__",&apply_array2d_scalar_binary_op<op_eq,T,T,int>)
751  .def("__ne__",&apply_array2d_array2d_binary_op<op_ne,T,T,int>)
752  .def("__ne__",&apply_array2d_scalar_binary_op<op_ne,T,T,int>)
753  ;
754 }
755 
756 template <class T>
757 static void add_ordered_comparison_functions(hboost::python::class_<FixedArray2D<T> > &c) {
758  using namespace hboost::python;
759  c
760  .def("__lt__",&apply_array2d_array2d_binary_op<op_lt,T,T,int>)
761  .def("__lt__",&apply_array2d_scalar_binary_op<op_lt,T,T,int>)
762  .def("__gt__",&apply_array2d_array2d_binary_op<op_gt,T,T,int>)
763  .def("__gt__",&apply_array2d_scalar_binary_op<op_gt,T,T,int>)
764  .def("__le__",&apply_array2d_array2d_binary_op<op_le,T,T,int>)
765  .def("__le__",&apply_array2d_scalar_binary_op<op_le,T,T,int>)
766  .def("__ge__",&apply_array2d_array2d_binary_op<op_ge,T,T,int>)
767  .def("__ge__",&apply_array2d_scalar_binary_op<op_ge,T,T,int>)
768  ;
769 }
770 
771 template <class S,class T>
772 static void add_explicit_construction_from_type(hboost::python::class_<FixedArray2D<T> > &c) {
773  using namespace hboost::python;
774  c.def(hboost::python::init<FixedArray2D<S> >("copy contents of other array into this one"));
775 }
776 
777 }
778 
779 #endif
const FixedArray2D & operator=(const FixedArray2D &other)
Py_ssize_t len() const
const hboost::any & handle()
FixedArray2D(T *ptr, Py_ssize_t lengthX, Py_ssize_t lengthY, Py_ssize_t strideX, Py_ssize_t strideY, hboost::any handle)
GLboolean * data
Definition: glcorearb.h:131
GLuint start
Definition: glcorearb.h:475
FixedArray2D(T *ptr, Py_ssize_t lengthX, Py_ssize_t lengthY, Py_ssize_t strideX=1)
GLdouble GLdouble GLdouble z
Definition: glcorearb.h:848
Vec2< int > V2i
Vec2 of integer.
Definition: ImathVec.h:1040
GLboolean GLboolean GLboolean GLboolean a
Definition: glcorearb.h:1222
GLdouble s
Definition: glad.h:3009
GLuint GLsizei GLsizei * length
Definition: glcorearb.h:795
FixedArray2D< Ret > apply_array2d_scalar_binary_rop(const FixedArray2D< T1 > &a1, const T2 &a2)
void setitem_array1d_mask(const FixedArray2D< int > &mask, const FixedArray< T > &data)
FixedArray2D(const FixedArray2D< S > &other)
FixedArray2D(T *ptr, Py_ssize_t lengthX, Py_ssize_t lengthY, Py_ssize_t strideX, Py_ssize_t strideY)
FixedArray2D(const T &initialValue, Py_ssize_t lengthX, Py_ssize_t lengthY)
FixedArray2D< Ret > apply_array2d_scalar_binary_op(const FixedArray2D< T1 > &a1, const T2 &a2)
GLfloat f
Definition: glcorearb.h:1926
GLint GLint GLsizei GLint GLenum GLenum type
Definition: glcorearb.h:108
T & operator()(size_t i, size_t j)
FixedArray2D< Ret > apply_array2d_array2d_binary_op(const FixedArray2D< T1 > &a1, const FixedArray2D< T2 > &a2)
bool any(const vbool4 &v)
Definition: simd.h:3600
FixedArray2D< T1 > & apply_array2d_scalar_ibinary_op(FixedArray2D< T1 > &a1, const T2 &a2)
FixedArray2D getslice_mask(const FixedArray2D< int > &mask) const
void setitem_scalar_mask(const FixedArray2D< int > &mask, const T &data)
GLuint GLuint end
Definition: glcorearb.h:475
GLint GLuint mask
Definition: glcorearb.h:124
hboost::python::tuple size() const
GLuint const GLchar * name
Definition: glcorearb.h:786
GLint GLenum GLint x
Definition: glcorearb.h:409
static hboost::python::class_< FixedArray2D< T > > register_(const char *name, const char *doc)
size_t canonical_index(Py_ssize_t index, size_t length) const
hboost::mpl::if_< hboost::is_class< T >, T &, T >::type get_type
FixedArray2D< T1 > & apply_array2d_array2d_ibinary_op(FixedArray2D< T1 > &a1, const FixedArray2D< T2 > &a2)
GLint j
Definition: glad.h:2733
void setitem_scalar(PyObject *index, const T &data)
FixedArray2D< T > ifelse_vector(const FixedArray2D< int > &choice, const FixedArray2D< T > &other)
FixedArray2D(const IMATH_NAMESPACE::V2i &length)
GLuint index
Definition: glcorearb.h:786
GLfloat GLfloat v1
Definition: glcorearb.h:817
auto ptr(T p) -> const void *
Definition: format.h:4331
IMATH_NAMESPACE::Vec2< size_t > stride() const
IMATH_NAMESPACE::Vec2< size_t > match_dimension(const FixedArray2D< T2 > &a1) const
get_type getitem(Py_ssize_t i, Py_ssize_t j)
IMATH_INTERNAL_NAMESPACE_HEADER_ENTER IMATH_HOSTDEVICE constexpr T abs(T a) IMATH_NOEXCEPT
Definition: ImathFun.h:26
void extract_slice_indices(PyObject *index, size_t length, size_t &start, size_t &end, Py_ssize_t &step, size_t &slicelength) const
FixedArray2D(Py_ssize_t lengthX, Py_ssize_t lengthY)
void setitem_array1d(PyObject *index, const FixedArray< T > &data)
IMATH_NAMESPACE::Vec2< size_t > len() const
FixedArray2D< Ret > apply_array2d_unary_op(const FixedArray2D< T1 > &a1)
FixedArray2D(const FixedArray2D &other)
void setitem_vector(PyObject *index, const FixedArray2D &data)
void setitem_vector_mask(const FixedArray2D< int > &mask, const FixedArray2D &data)
FixedArray2D< T > ifelse_scalar(const FixedArray2D< int > &choice, const T &other)
GLint GLsizei count
Definition: glcorearb.h:405
Definition: format.h:1821
FixedArray2D getslice(PyObject *index) const