1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright Contributors to the OpenEXR Project.
4 //
5 
6 // clang-format off
7 
8 #include <Python.h>
9 #include <boost/python.hpp>
10 #include <boost/python/make_constructor.hpp>
11 #include <boost/format.hpp>
12 #include "PyImath.h"
13 #include "PyImathMathExc.h"
14 #include "PyImathShear.h"
15 #include "PyImathPlane.h"
16 #include "PyImathDecorators.h"
17 #include "PyImathExport.h"
18 
19 
20 namespace PyImath{
21 using namespace boost::python;
22 using namespace IMATH_NAMESPACE;
23 
24 template <class T> struct ShearName {static const char *value;};
25 template <> const char *ShearName<float>::value = "Shear6f";
26 template <> const char *ShearName<double>::value = "Shear6d";
27 
28 template <class T>
Shear_str(const Shear6<T> & v)29 static std::string Shear_str(const Shear6<T> &v)
30 {
31     std::stringstream stream;
32     stream << ShearName<T>::value << "("
33            << v[0] << ", " << v[1] << ", " << v[2] << ", "
34            << v[3] << ", " << v[4] << ", " << v[5] << ")";
35     return stream.str();
36 }
37 
38 // Non-specialized repr is same as str
39 template <class T>
Shear_repr(const Shear6<T> & v)40 static std::string Shear_repr(const Shear6<T> &v)
41 {
42     return Shear_str(v);
43 }
44 
45 // Specialization for float to full precision
46 template <>
Shear_repr(const Shear6<float> & v)47 std::string Shear_repr(const Shear6<float> &v)
48 {
49     return (boost::format("%s(%.9g, %.9g, %.9g, %.9g, %.9g, %.9g)")
50                         % ShearName<float>::value
51                         % v[0] % v[1] % v[2]
52                         % v[3] % v[4] % v[5]).str();
53 }
54 
55 // Specialization for double to full precision
56 template <>
Shear_repr(const Shear6<double> & v)57 std::string Shear_repr(const Shear6<double> &v)
58 {
59     return (boost::format("%s(%.17g, %.17g, %.17g, %.17g, %.17g, %.17g)")
60                         % ShearName<double>::value
61                         % v[0] % v[1] % v[2]
62                         % v[3] % v[4] % v[5]).str();
63 }
64 
65 template <class T>
shearTupleConstructor(tuple t)66 static Shear6<T> * shearTupleConstructor(tuple t)
67 {
68     if(t.attr("__len__")() == 3){
69         return new Shear6<T>(extract<T>(t[0]), extract<T>(t[1]), extract<T>(t[2]),
70                              T(0), T(0), T(0));
71     }
72     else if(t.attr("__len__")() == 6){
73         return new Shear6<T>(extract<T>(t[0]), extract<T>(t[1]), extract<T>(t[2]),
74                              extract<T>(t[3]), extract<T>(t[4]), extract<T>(t[5]));
75     }
76     else
77       throw std::invalid_argument ("Shear6 expects tuple of length 3 or 6");
78 }
79 
80 template <class T>
shearConstructor1(T a)81 static Shear6<T> * shearConstructor1(T a)
82 {
83     return new Shear6<T>(a, a, a, a, a, a);
84 }
85 
86 template <class T, class S>
shearConversionConstructor(const Shear6<S> & shear)87 static Shear6<T> * shearConversionConstructor(const Shear6<S> &shear)
88 {
89     Shear6<T> *s = new Shear6<T>;
90     *s = shear;
91     return s;
92 }
93 
94 template <class T>
95 static const Shear6<T> &
iadd(Shear6<T> & shear,const Shear6<T> & other)96 iadd(Shear6<T> &shear, const Shear6<T> &other)
97 {
98     MATH_EXC_ON;
99     return shear += other;
100 }
101 
102 template <class T>
103 static Shear6<T>
add(const Shear6<T> & shear,const Shear6<T> & other)104 add(const Shear6<T> &shear, const Shear6<T> &other)
105 {
106     MATH_EXC_ON;
107     return shear + other;
108 }
109 
110 template <class T>
111 static const Shear6<T> &
isub(Shear6<T> & shear,const Shear6<T> & other)112 isub(Shear6<T> &shear, const Shear6<T> &other)
113 {
114     MATH_EXC_ON;
115     return shear -= other;
116 }
117 
118 template <class T>
119 static Shear6<T>
sub(const Shear6<T> & shear,const Shear6<T> & other)120 sub(const Shear6<T> &shear, const Shear6<T> &other)
121 {
122     MATH_EXC_ON;
123     return shear - other;
124 }
125 
126 template <class T>
127 static Shear6<T>
neg(const Shear6<T> & shear)128 neg(const Shear6<T> &shear)
129 {
130     MATH_EXC_ON;
131     return -shear;
132 }
133 
134 template <class T>
135 static const Shear6<T> &
imul(Shear6<T> & shear,const Shear6<T> & other)136 imul(Shear6<T> &shear, const Shear6<T> &other)
137 {
138     MATH_EXC_ON;
139     return shear *= other;
140 }
141 
142 template <class T>
143 static const Shear6<T> &
imulT(Shear6<T> & shear,T t)144 imulT(Shear6<T> &shear, T t)
145 {
146     MATH_EXC_ON;
147     return shear *= t;
148 }
149 
150 template <class T>
151 static Shear6<T>
mul(const Shear6<T> & shear,const Shear6<T> & other)152 mul(const Shear6<T> &shear, const Shear6<T> &other)
153 {
154     MATH_EXC_ON;
155     return shear * other;
156 }
157 
158 template <class T>
159 static Shear6<T>
mulT(const Shear6<T> & shear,T t)160 mulT(const Shear6<T> &shear, T t)
161 {
162     MATH_EXC_ON;
163     return shear * t;
164 }
165 
166 template <class T>
167 static const Shear6<T> &
idiv(Shear6<T> & shear,const Shear6<T> & other)168 idiv(Shear6<T> &shear, const Shear6<T> &other)
169 {
170     MATH_EXC_ON;
171     return shear /= other;
172 }
173 
174 template <class T>
175 static const Shear6<T> &
idivT(Shear6<T> & shear,T t)176 idivT(Shear6<T> &shear, T t)
177 {
178     MATH_EXC_ON;
179     return shear /= t;
180 }
181 
182 template <class T>
183 static Shear6<T>
div(const Shear6<T> & shear,const Shear6<T> & other)184 div(const Shear6<T> &shear, const Shear6<T> &other)
185 {
186     MATH_EXC_ON;
187     return shear / other;
188 }
189 
190 template <class T>
191 static Shear6<T>
divT(const Shear6<T> & shear,T t)192 divT(const Shear6<T> &shear, T t)
193 {
194     MATH_EXC_ON;
195     return shear / t;
196 }
197 
198 template <class T>
199 static Shear6<T>
subtract1(Shear6<T> & v,tuple t)200 subtract1(Shear6<T> &v, tuple t)
201 {
202     MATH_EXC_ON;
203     Shear6<T> w;
204 
205     if(t.attr("__len__")() == 6){
206         w[0] = v[0] - extract<T>(t[0]);
207         w[1] = v[1] - extract<T>(t[1]);
208         w[2] = v[2] - extract<T>(t[2]);
209         w[3] = v[3] - extract<T>(t[3]);
210         w[4] = v[4] - extract<T>(t[4]);
211         w[5] = v[5] - extract<T>(t[5]);
212     }
213     else
214         throw std::domain_error ("tuple must have length of 6");
215 
216     return w;
217 }
218 
219 template <class T>
220 static Shear6<T>
subtract2(Shear6<T> & v,tuple t)221 subtract2(Shear6<T> &v, tuple t)
222 {
223     MATH_EXC_ON;
224     Shear6<T> w;
225 
226     if(t.attr("__len__")() == 6){
227         w[0] = extract<T>(t[0]) - v[0];
228         w[1] = extract<T>(t[1]) - v[1];
229         w[2] = extract<T>(t[2]) - v[2];
230         w[3] = extract<T>(t[3]) - v[3];
231         w[4] = extract<T>(t[4]) - v[4];
232         w[5] = extract<T>(t[5]) - v[5];
233     }
234     else
235         throw std::domain_error ("tuple must have length of 6");
236 
237     return w;
238 }
239 
240 template <class T>
241 static Shear6<T>
subtractT1(Shear6<T> & v,T a)242 subtractT1(Shear6<T> &v, T a)
243 {
244     MATH_EXC_ON;
245     Shear6<T> w;
246 
247     w[0] = v[0] - a;
248     w[1] = v[1] - a;
249     w[2] = v[2] - a;
250     w[3] = v[3] - a;
251     w[4] = v[4] - a;
252     w[5] = v[5] - a;
253 
254     return w;
255 }
256 
257 template <class T>
258 static Shear6<T>
subtractT2(Shear6<T> & v,T a)259 subtractT2(Shear6<T> &v, T a)
260 {
261     MATH_EXC_ON;
262     Shear6<T> w;
263 
264      w[0] = a - v[0];
265      w[1] = a - v[1];
266      w[2] = a - v[2];
267      w[3] = a - v[3];
268      w[4] = a - v[4];
269      w[5] = a - v[5];
270 
271     return w;
272 }
273 
274 
275 template <class T>
276 static Shear6<T>
addTuple(Shear6<T> & v,tuple t)277 addTuple(Shear6<T> &v, tuple t)
278 {
279     MATH_EXC_ON;
280     Shear6<T> w;
281 
282     if(t.attr("__len__")() == 6){
283         w[0] = v[0] + extract<T>(t[0]);
284         w[1] = v[1] + extract<T>(t[1]);
285         w[2] = v[2] + extract<T>(t[2]);
286         w[3] = v[3] + extract<T>(t[3]);
287         w[4] = v[4] + extract<T>(t[4]);
288         w[5] = v[5] + extract<T>(t[5]);
289     }
290     else
291         throw std::domain_error ("tuple must have length of 6");
292 
293     return w;
294 }
295 
296 template <class T>
297 static Shear6<T>
addT(Shear6<T> & v,T a)298 addT(Shear6<T> &v, T a)
299 {
300     MATH_EXC_ON;
301     Shear6<T> w;
302 
303      w[0] = v[0] + a;
304      w[1] = v[1] + a;
305      w[2] = v[2] + a;
306      w[3] = v[3] + a;
307      w[4] = v[4] + a;
308      w[5] = v[5] + a;
309 
310     return w;
311 }
312 
313 template <class T>
314 static Shear6<T>
multTuple(Shear6<T> & v,tuple t)315 multTuple(Shear6<T> &v, tuple t)
316 {
317     MATH_EXC_ON;
318     Shear6<T> w;
319 
320     if(t.attr("__len__")() == 6){
321         w[0] = v[0] * extract<T>(t[0]);
322         w[1] = v[1] * extract<T>(t[1]);
323         w[2] = v[2] * extract<T>(t[2]);
324         w[3] = v[3] * extract<T>(t[3]);
325         w[4] = v[4] * extract<T>(t[4]);
326         w[5] = v[5] * extract<T>(t[5]);
327     }
328     else
329         throw std::domain_error ("tuple must have length of 6");
330 
331     return w;
332 }
333 
334 template <class T>
335 static Shear6<T>
rdiv(Shear6<T> & v,T a)336 rdiv(Shear6<T> &v, T a)
337 {
338     MATH_EXC_ON;
339     Shear6<T> w;
340 
341     if(v != Shear6<T>()){
342         w[0] = a/v[0];
343         w[1] = a/v[1];
344         w[2] = a/v[2];
345         w[3] = a/v[3];
346         w[4] = a/v[4];
347         w[5] = a/v[5];
348     }
349     else
350         throw std::domain_error ("Division by Zero");
351 
352     return w;
353 }
354 
355 template <class T>
356 static Shear6<T>
divTuple(Shear6<T> & v,const tuple & t)357 divTuple(Shear6<T> &v, const tuple &t)
358 {
359     MATH_EXC_ON;
360     if(t.attr("__len__")() != 6)
361         throw std::domain_error ("Shear6 expects tuple of length 6");
362 
363     Shear6<T> w;
364     for(int i = 0; i < 6; ++i)
365     {
366         T a = extract<T>(t[i]);
367         if(a != T (0))
368             w[i] = v[i] / a;
369         else
370             throw std::domain_error ("Division by Zero");
371     }
372 
373     return w;
374 }
375 
376 template <class T>
377 static Shear6<T>
rdivTuple(Shear6<T> & v,const tuple & t)378 rdivTuple(Shear6<T> &v, const tuple &t)
379 {
380     MATH_EXC_ON;
381     if(t.attr("__len__")() != 6)
382         throw std::domain_error ("Shear6 expects tuple of length 6");
383 
384     Shear6<T> w;
385     for(int i = 0; i < 6; ++i)
386     {
387         T a = extract<T>(t[i]);
388         if(v[i] != T (0))
389             w[i] = a / v[i];
390         else
391             throw std::domain_error ("Division by Zero");
392     }
393 
394     return w;
395 }
396 
397 template <class T>
398 static bool
lessThan(Shear6<T> & v,const Shear6<T> & w)399 lessThan(Shear6<T> &v, const Shear6<T> &w)
400 {
401     bool isLessThan = (v[0] <= w[0] && v[1] <= w[1] && v[2] <= w[2]
402                     && v[3] <= w[3] && v[4] <= w[4] && v[5] <= w[5])
403                     && v != w;
404 
405    return isLessThan;
406 }
407 
408 template <class T>
409 static bool
greaterThan(Shear6<T> & v,const Shear6<T> & w)410 greaterThan(Shear6<T> &v, const Shear6<T> &w)
411 {
412     bool isGreaterThan = (v[0] >= w[0] && v[1] >= w[1] && v[2] >= w[2]
413                        && v[3] >= w[3] && v[4] >= w[4] && v[5] >= w[5])
414                        && v != w;
415 
416    return isGreaterThan;
417 }
418 
419 template <class T>
420 static bool
lessThanEqual(Shear6<T> & v,const Shear6<T> & w)421 lessThanEqual(Shear6<T> &v, const Shear6<T> &w)
422 {
423     bool isLessThanEqual = (v[0] <= w[0] && v[1] <= w[1] && v[2] <= w[2]
424                          && v[3] <= w[3] && v[4] <= w[4] && v[5] <= w[5]);
425 
426    return isLessThanEqual;
427 }
428 
429 template <class T>
430 static bool
greaterThanEqual(Shear6<T> & v,const Shear6<T> & w)431 greaterThanEqual(Shear6<T> &v, const Shear6<T> &w)
432 {
433     bool isGreaterThanEqual = (v[0] >= w[0] && v[1] >= w[1] && v[2] >= w[2]
434                             && v[3] >= w[3] && v[4] >= w[4] && v[5] >= w[5]);
435 
436    return isGreaterThanEqual;
437 }
438 
439 template <class T>
440 static T
getitem(Shear6<T> & shear,int i)441 getitem(Shear6<T> &shear, int i)
442 {
443     return shear[i];
444 }
445 
446 template <class T>
447 static void
setitem(Shear6<T> & shear,int i,T a)448 setitem(Shear6<T> &shear, int i, T a)
449 {
450     if(i < 0 || i > 5)
451         throw std::domain_error ("Index out of range");
452 
453     shear[i] = a;
454 }
455 
456 template <class T>
457 static int
len(Shear6<T> & shear)458 len(Shear6<T> &shear)
459 {
460     return 6;
461 }
462 
463 
464 
465 template <class T>
466 class_<Shear6<T> >
register_Shear()467 register_Shear()
468 {
469     const char *name = ShearName<T>::value;
470 
471     void (IMATH_NAMESPACE::Shear6<T>::*setValue1)(T,T,T,T,T,T) = &IMATH_NAMESPACE::Shear6<T>::setValue;
472     void (IMATH_NAMESPACE::Shear6<T>::*setValue2)(const Shear6<T> &) = &IMATH_NAMESPACE::Shear6<T>::setValue;
473     void (IMATH_NAMESPACE::Shear6<T>::*getValue1)(Shear6<T> &) const = &IMATH_NAMESPACE::Shear6<T>::getValue;
474 
475     class_<Shear6<T> > shear_class(name, name, init<Shear6<T> >("copy construction"));
476     shear_class
477         .def(init<>("default construction: (0 0 0 0 0 0)"))
478         .def(init<T,T,T>("Shear(XY,XZ,YZ) construction: (XY XZ YZ 0 0 0)"))
479         .def(init<const Vec3<float> &>("Shear(v) construction: (v.x v.y v.z 0 0 0)"))
480         .def(init<const Vec3<double> &>("Shear(v) construction: (v.x v.y v.z 0 0 0)"))
481         .def(init<const Vec3<int> &>("Shear(v) construction: (v.x v.y v.z 0 0 0)"))
482         .def(init<T,T,T,T,T,T>("Shear(XY, XZ, YZ, YX, ZX, ZY) construction"))
483         .def("__init__", make_constructor(shearConstructor1<T>))
484         .def("__init__", make_constructor(shearTupleConstructor<T>),"Construction from tuple")
485         .def("__init__", make_constructor(shearConversionConstructor<T,float>))
486         .def("__init__", make_constructor(shearConversionConstructor<T,double>))
487         .def("__init__", make_constructor(shearConversionConstructor<T,int>))
488         .def("__iadd__",&iadd<T>,return_internal_reference<>())
489         .def("__add__",&add<T>)
490         .def("__isub__",&isub<T>,return_internal_reference<>())
491         .def("__sub__",&sub<T>)
492         .def("__neg__",&neg<T>)
493         .def("__imul__",&imul<T>,return_internal_reference<>())
494         .def("__imul__",&imulT<T>,return_internal_reference<>())
495         .def("__mul__",&mul<T>)
496         .def("__mul__",&mulT<T>)
497         .def("__rmul__",&mulT<T>)
498         .def("__idiv__",&idiv<T>,return_internal_reference<>())
499         .def("__idiv__",&idivT<T>,return_internal_reference<>())
500         .def("__itruediv__",&idiv<T>,return_internal_reference<>())
501         .def("__itruediv__",&idivT<T>,return_internal_reference<>())
502         .def("__div__",&div<T>)
503         .def("__div__",&divT<T>)
504         .def("__truediv__",&div<T>)
505         .def("__truediv__",&divT<T>)
506         .def(self == self) // NOSONAR - suppress SonarCloud bug report.
507         .def(self != self) // NOSONAR - suppress SonarCloud bug report.
508         .def("__str__",&Shear_str<T>)
509         .def("__repr__",&Shear_repr<T>)
510         .def("setValue", setValue1)
511         .def("setValue", setValue2)
512         .def("getValue", getValue1)
513         .def("negate", &Shear6<T>::negate, return_internal_reference<>())
514         .def("baseTypeLowest", &Shear6<T>::baseTypeLowest)
515         .staticmethod("baseTypeLowest")
516         .def("baseTypeMax", &Shear6<T>::baseTypeMax)
517         .staticmethod("baseTypeMax")
518         .def("baseTypeSmallest", &Shear6<T>::baseTypeSmallest)
519         .staticmethod("baseTypeSmallest")
520         .def("baseTypeEpsilon", &Shear6<T>::baseTypeEpsilon)
521         .staticmethod("baseTypeEpsilon")
522         .def("equalWithAbsError", &Shear6<T>::equalWithAbsError)
523         .def("equalWithRelError", &Shear6<T>::equalWithRelError)
524         .def("__sub__", &subtract1<T>)
525         .def("__sub__", &subtractT1<T>)
526         .def("__rsub__", &subtract2<T>)
527         .def("__rsub__", &subtractT2<T>)
528         .def("__add__", &addTuple<T>)
529         .def("__add__", &addT<T>)
530         .def("__radd__", &addTuple<T>)
531         .def("__radd__", &addT<T>)
532         .def("__mul__", &multTuple<T>)
533         .def("__rmul__", &multTuple<T>)
534         .def("__div__", &divTuple<T>)
535         .def("__truediv__", &divTuple<T>)
536         .def("__rdiv__", &rdiv<T>)
537         .def("__rdiv__", &rdivTuple<T>)
538         .def("__rtruediv__", &rdiv<T>)
539         .def("__rtruediv__", &rdivTuple<T>)
540         .def("__lt__", &lessThan<T>)
541         .def("__gt__", &greaterThan<T>)
542         .def("__le__", &lessThanEqual<T>)
543         .def("__ge__", &greaterThanEqual<T>)
544         .def("__getitem__", &getitem<T>)
545         .def("__setitem__", &setitem<T>)
546         .def("__len__", &len<T>)
547         ;
548 
549     decoratecopy(shear_class);
550 
551     return shear_class;
552 }
553 
554 template PYIMATH_EXPORT class_<Shear6<float> > register_Shear();
555 template PYIMATH_EXPORT class_<Shear6<double> > register_Shear();
556 
557 }//namespace PyIMath
558