Imported Upstream version 3.1.9
[platform/upstream/Imath.git] / src / python / PyImath / PyImathVec4Impl.h
1 //
2 // SPDX-License-Identifier: BSD-3-Clause
3 // Copyright Contributors to the OpenEXR Project.
4 //
5
6 // clang-format off
7
8 #ifndef _PyImathVec3Impl_h_
9 #define _PyImathVec3Impl_h_
10
11 //
12 // This .C file was turned into a header file so that instantiations
13 // of the various V3* types can be spread across multiple files in
14 // order to work around MSVC limitations.
15 //
16
17 #include <Python.h>
18 #define BOOST_BIND_GLOBAL_PLACEHOLDERS
19 #include <boost/python.hpp>
20 #include <boost/python/make_constructor.hpp>
21 #include <boost/format.hpp>
22 #include <ImathVec.h>
23 #include <ImathVecAlgo.h>
24 #include "PyImath.h"
25 #include "PyImathVec.h"
26 #include "PyImathDecorators.h"
27 #include "PyImathMathExc.h"
28
29 namespace PyImath {
30 using namespace boost::python;
31 using namespace IMATH_NAMESPACE;
32
33 template <class T> struct Vec4Name      { static const char *value(); };
34
35 // create a new default constructor that initializes Vec3<T> to zero.
36 template <class T>
37 static Vec4<T> * Vec4_construct_default()
38 {
39     return new Vec4<T>(T(0),T(0),T(0),T(0));
40 }
41
42 template <class T>
43 static Vec4<T> * Vec4_object_constructor1(const object &obj)
44 {
45     Vec4<T> res;
46     extract<Vec4<int> >     e1(obj);
47     extract<Vec4<float> >   e2(obj);
48     extract<Vec4<double> >  e3(obj);
49     extract<tuple>          e4(obj);
50     extract<double>         e5(obj);
51     extract<list>           e6(obj);
52     
53     if(e1.check())      { res = e1(); }
54     else if(e2.check()) { res = e2(); }
55     else if(e3.check()) { res = e3(); }
56     else if(e4.check())
57     {
58         tuple t = e4();
59         if(t.attr("__len__")() == 4)
60         {
61             res.x = extract<T>(t[0]);
62             res.y = extract<T>(t[1]);
63             res.z = extract<T>(t[2]);
64             res.w = extract<T>(t[3]);
65         }
66         else
67             throw std::invalid_argument ("tuple must have length of 4");
68         
69     }
70     else if(e5.check()) { T a = (T) e5(); res = IMATH_NAMESPACE::Vec4<T>(a, a, a, a); }
71     else if(e6.check())
72     {
73         list l = e6();
74         if(l.attr("__len__")() == 4)
75         {
76             res.x = extract<T>(l[0]);
77             res.y = extract<T>(l[1]);
78             res.z = extract<T>(l[2]);
79             res.w = extract<T>(l[3]);
80         }
81         else
82             throw std::invalid_argument ("list must have length of 4");
83     }
84     else
85         throw std::invalid_argument ("invalid parameters passed to Vec4 constructor");
86     
87     Vec4<T> *v = new Vec4<T>;
88     *v = res;
89     
90     return v;
91
92 }
93
94 template <class T>
95 static Vec4<T> * Vec4_object_constructor2(const object &obj1, const object &obj2, const object &obj3, const object& obj4)
96 {
97     extract<double>    e1(obj1);
98     extract<double>    e2(obj2);
99     extract<double>    e3(obj3);
100     extract<double>    e4(obj4);
101     Vec4<T> *v = new Vec4<T>;
102     
103     if(e1.check()) { v->x = (T) e1();}
104     else { throw std::invalid_argument ("invalid parameters passed to Vec4 constructor"); }
105     
106     if(e2.check()) { v->y = (T) e2();}
107     else { throw std::invalid_argument ("invalid parameters passed to Vec4 constructor"); }    
108
109     if(e3.check()) { v->z = (T) e3();}
110     else { throw std::invalid_argument ("invalid parameters passed to Vec4 constructor"); } 
111
112     if(e4.check()) { v->w = (T) e4();}
113     else { throw std::invalid_argument ("invalid parameters passed to Vec4 constructor"); } 
114     
115     return v;
116 }
117
118
119
120 // Implementations of str and repr are same here,
121 // but we'll specialize repr for float and double to make them exact.
122 template <class T>
123 static std::string Vec4_str(const Vec4<T> &v)
124 {
125     std::stringstream stream;
126     stream << Vec4Name<T>::value() << "(" << v.x << ", " << v.y << ", " << v.z << ", " << v.w << ")";
127     return stream.str();
128 }
129 template <class T>
130 static std::string Vec4_repr(const Vec4<T> &v)
131 {
132     std::stringstream stream;
133     stream << Vec4Name<T>::value() << "(" << v.x << ", " << v.y << ", " << v.z << ", " << v.w << ")";
134     return stream.str();
135 }
136
137 template <class T>
138 static T
139 Vec4_dot(const IMATH_NAMESPACE::Vec4<T> &v, const IMATH_NAMESPACE::Vec4<T> &other) 
140
141     MATH_EXC_ON;
142     return v.dot(other);
143 }
144
145 template <class T>
146 static FixedArray<T>
147 Vec4_dot_Vec4Array(const IMATH_NAMESPACE::Vec4<T> &va, const FixedArray<IMATH_NAMESPACE::Vec4<T> > &vb) 
148
149     PY_IMATH_LEAVE_PYTHON;
150     size_t len = vb.len(); 
151     FixedArray<T> f(len); 
152     for (size_t i = 0; i < len; ++i) 
153         f[i] = va.dot(vb[i]); 
154     return f; 
155 }
156
157 template <class T>
158 static T
159 Vec4_length(const IMATH_NAMESPACE::Vec4<T> &v) 
160
161     MATH_EXC_ON;
162     return v.length();
163 }
164
165 template <class T>
166 static T
167 Vec4_length2(const IMATH_NAMESPACE::Vec4<T> &v) 
168
169     MATH_EXC_ON;
170     return v.length2();
171 }
172
173 template <class T>
174 static const Vec4<T> &
175 Vec4_normalize(IMATH_NAMESPACE::Vec4<T> &v) 
176
177     MATH_EXC_ON;
178     return v.normalize();
179 }
180
181 template <class T>
182 static const Vec4<T> &
183 Vec4_normalizeExc(IMATH_NAMESPACE::Vec4<T> &v) 
184
185     MATH_EXC_ON;
186     return v.normalizeExc();
187 }
188
189 template <class T>
190 static const Vec4<T> &
191 Vec4_normalizeNonNull(IMATH_NAMESPACE::Vec4<T> &v) 
192
193     MATH_EXC_ON;
194     return v.normalizeNonNull();
195 }
196
197 template <class T>
198 static Vec4<T>
199 Vec4_normalized(const IMATH_NAMESPACE::Vec4<T> &v) 
200
201     MATH_EXC_ON;
202     return v.normalized();
203 }
204
205 template <class T>
206 static Vec4<T>
207 Vec4_normalizedExc(const IMATH_NAMESPACE::Vec4<T> &v) 
208
209     MATH_EXC_ON;
210     return v.normalizedExc();
211 }
212
213 template <class T>
214 static Vec4<T>
215 Vec4_normalizedNonNull(const IMATH_NAMESPACE::Vec4<T> &v) 
216
217     MATH_EXC_ON;
218     return v.normalizedNonNull();
219 }
220
221 template <class T>
222 static const Vec4<T> &
223 Vec4_negate(IMATH_NAMESPACE::Vec4<T> &v) 
224
225     MATH_EXC_ON;
226     return v.negate();
227 }
228
229 template <class T>
230 static Vec4<T>
231 orthogonal(const Vec4<T> &v, const Vec4<T> &v0)
232 {
233     MATH_EXC_ON;
234     return IMATH_NAMESPACE::orthogonal(v, v0);
235 }
236
237 template <class T>
238 static Vec4<T>
239 project(const Vec4<T> &v, const Vec4<T> &v0)
240 {
241     MATH_EXC_ON;
242     return IMATH_NAMESPACE::project(v0, v);
243 }
244
245 template <class T>
246 static Vec4<T>
247 reflect(const Vec4<T> &v, const Vec4<T> &v0)
248 {
249     MATH_EXC_ON;
250     return IMATH_NAMESPACE::reflect(v, v0);
251 }
252
253 template <class T>
254 static void
255 setValue(Vec4<T> &v, T a, T b, T c, T d)
256 {
257     v.x = a;
258     v.y = b;
259     v.z = c;
260     v.w = d;
261 }
262
263 template <class T>
264 static Vec4<T>
265 Vec4_add (const Vec4<T> &v, const Vec4<T> &w)
266 {
267     MATH_EXC_ON;
268     return v + w;
269 }
270
271 template <class T>
272 static Vec4<T>
273 Vec4_sub (const Vec4<T> &v, const Vec4<T> &w)
274 {
275     MATH_EXC_ON;
276     return v - w;
277 }
278
279 template <class T>
280 static Vec4<T>
281 Vec4_neg (const Vec4<T> &v)
282 {
283     MATH_EXC_ON;
284     return -v;
285 }
286
287 template <class T, class U>
288 static Vec4<T>
289 Vec4_mul (const Vec4<T> &v, Vec4<U> &w)
290 {
291     MATH_EXC_ON;
292     Vec4<T> w2 (w);
293     return v * w2;
294 }
295
296 template <class T>
297 static Vec4<T>
298 Vec4_mulT (const Vec4<T> &v, T t)
299 {
300     MATH_EXC_ON;
301     return v * t;
302 }
303
304 template <class T>
305 static FixedArray<IMATH_NAMESPACE::Vec4<T> >
306 Vec4_mulTArray (const Vec4<T> &v, const FixedArray<T> &t)
307 {
308     PY_IMATH_LEAVE_PYTHON;
309     size_t len = t.len();
310     FixedArray<IMATH_NAMESPACE::Vec4<T> > retval(len);
311     for (size_t i=0; i<len; ++i) retval[i] = v*t[i];
312     return retval;
313 }
314
315 template <class T>
316 static FixedArray<IMATH_NAMESPACE::Vec4<T> >
317 Vec4_rmulTArray (const Vec4<T> &v, const FixedArray<T> &t)
318 {
319     return Vec4_mulTArray(v,t);
320 }
321
322 template <class T,class S>
323 static Vec4<T>
324 Vec4_div (Vec4<T> &v, Vec4<S> &w)
325 {
326     MATH_EXC_ON;
327     return v / w;
328 }
329
330 template <class T>
331 static Vec4<T>
332 Vec4_rmulT (Vec4<T> &v, T t)
333 {
334     MATH_EXC_ON;
335     return t * v;
336 }
337
338 template <class T, class U>
339 static const Vec4<T> &
340 Vec4_imulV(Vec4<T> &v, const Vec4<U> &w)
341 {
342     MATH_EXC_ON;
343     return v *= w;
344 }
345
346 template <class T>
347 static const Vec4<T> &
348 Vec4_imulT(IMATH_NAMESPACE::Vec4<T> &v, T t) 
349
350     MATH_EXC_ON;
351     return v *= t;
352 }
353
354 template <class T, class U>
355 static Vec4<T>
356 Vec4_mulM44 (Vec4<T> &v, const Matrix44<U> &m)
357 {
358     MATH_EXC_ON;
359     return v * m;
360 }
361
362 template <class T>
363 static const Vec4<T> &
364 Vec4_idivObj(IMATH_NAMESPACE::Vec4<T> &v, const object &o) 
365
366     MATH_EXC_ON;
367     Vec4<T> v2;
368     if (PyImath::V4<T>::convert (o.ptr(), &v2))
369     {
370         return v /= v2;
371     }
372     else
373     {
374         extract<double> e(o);
375         if (e.check())
376             return v /= (T) e();
377         else
378             throw std::invalid_argument ("V4 division expects an argument "
379                    "convertible to a V4");
380     }
381 }
382
383 template <class T>
384 static Vec4<T>
385 Vec4_subT(const Vec4<T> &v, T a)
386 {
387     MATH_EXC_ON;
388     Vec4<T> w;
389     setValue(w, (T) (v.x - a), (T) (v.y - a), (T) (v.z - a), (T) (v.w - a));
390     return w;
391 }
392
393 template <class T,class BoostPyType>
394 static Vec4<T>
395 Vec4_subTuple(const Vec4<T> &v, const BoostPyType &t)
396 {
397     MATH_EXC_ON;
398     Vec4<T> w;
399     
400     if(t.attr("__len__")() == 4)
401     {
402         w.x = v.x - extract<T>(t[0]);
403         w.y = v.y - extract<T>(t[1]);
404         w.z = v.z - extract<T>(t[2]);
405         w.w = v.w - extract<T>(t[3]);
406     }
407     else
408         throw std::invalid_argument ("tuple must have length of 4");
409     
410     return w;
411 }
412
413 template <class T>
414 static Vec4<T>
415 Vec4_rsubT(const Vec4<T> &v, T a)
416 {
417     MATH_EXC_ON;
418     Vec4<T> w(a - v.x, a - v.y, a - v.z, a - v.w);
419     return w;
420 }
421
422 template <class T, class BoostPyType>
423 static Vec4<T>
424 Vec4_rsubTuple(const Vec4<T> &v, const BoostPyType &t)
425 {
426     MATH_EXC_ON;
427     Vec4<T> w;
428     
429     if(t.attr("__len__")() == 4)
430     {
431         w.x = extract<T>(t[0]) - v.x;
432         w.y = extract<T>(t[1]) - v.y;
433         w.z = extract<T>(t[2]) - v.z;
434         w.w = extract<T>(t[3]) - v.w;
435     }
436     else
437         throw std::invalid_argument ("tuple must have length of 4");
438     
439     return w;
440 }
441
442 template <class T, class BoostPyType>
443 static Vec4<T>
444 Vec4_addTuple(const Vec4<T> &v, const BoostPyType &t)
445 {
446     MATH_EXC_ON;
447     Vec4<T> w;
448     
449     if(t.attr("__len__")() == 4)
450     {
451         w.x = v.x + extract<T>(t[0]);
452         w.y = v.y + extract<T>(t[1]);
453         w.z = v.z + extract<T>(t[2]);
454         w.w = v.w + extract<T>(t[3]);
455     }
456     else
457         throw std::invalid_argument ("tuple must have length of 4");
458     
459     return w;
460 }
461
462 template <class T>
463 static Vec4<T>
464 Vec4_addT(const Vec4<T> &v, T a)
465 {
466     MATH_EXC_ON;
467     Vec4<T> w;
468     setValue(w, (T) (v.x + a), (T) (v.y + a), (T) (v.z + a), (T) (v.w + a));
469     return w;
470 }
471
472 template <class T, class U>
473 static Vec4<T>
474 Vec4_addV(const Vec4<T> &v, const Vec4<U> &w)
475 {
476     MATH_EXC_ON;
477     return v + w;
478 }
479
480 template <class T, class U>
481 static const Vec4<T> &
482 Vec4_iaddV(Vec4<T> &v, const Vec4<U> &w)
483 {
484     MATH_EXC_ON;
485     return v += w;
486 }
487
488 template <class T, class U>
489 static Vec4<T>
490 Vec4_subV(const Vec4<T> &v, const Vec4<U> &w)
491 {
492     MATH_EXC_ON;
493     return v - w;
494 }
495
496 template <class T, class U>
497 static const Vec4<T> &
498 Vec4_isubV(Vec4<T> &v, const Vec4<U> &w)
499 {
500     MATH_EXC_ON;
501     return v -= w;
502 }
503
504 template <class T>
505 static Vec4<T>
506 mult(const Vec4<T> &v, tuple t)
507 {
508     MATH_EXC_ON;
509     Vec4<T> w;
510     
511     if(t.attr("__len__")() == 1){
512         w.x = v.x*extract<T>(t[0]);
513         w.y = v.y*extract<T>(t[0]);
514         w.z = v.z*extract<T>(t[0]);
515         w.w = v.w*extract<T>(t[0]);
516     }        
517     else if(t.attr("__len__")() == 4){
518         w.x = v.x*extract<T>(t[0]);
519         w.y = v.y*extract<T>(t[1]);
520         w.z = v.z*extract<T>(t[2]);
521         w.w = v.w*extract<T>(t[3]);
522     }
523     else
524         throw std::invalid_argument ("tuple must have length of 1 or 4");
525     
526     return w;
527 }
528
529 template <class T, class U>
530 static const Vec4<T> &
531 Vec4_imulM44 (Vec4<T> &v, const Matrix44<U> &m)
532 {
533     MATH_EXC_ON;
534     return v *= m;
535 }
536
537 template <class T, class BoostPyType>
538 static Vec4<T>
539 Vec4_divTuple(const Vec4<T> &v, const BoostPyType &t)
540 {
541     if(t.attr("__len__")() == 4)
542     {
543         T x = extract<T>(t[0]);
544         T y = extract<T>(t[1]);
545         T z = extract<T>(t[2]);
546         T w = extract<T>(t[3]);
547         if(x != T(0) && y != T(0) && z != T(0) && w != T(0))
548             return Vec4<T>(v.x / x, v.y / y, v.z / z, v.w / w);
549         else
550             throw std::domain_error ("Division by zero");
551     }
552     else
553         throw std::invalid_argument ("Vec4 expects tuple of length 4");
554 }
555
556 template <class T, class BoostPyType>
557 static Vec4<T>
558 Vec4_rdivTuple(const Vec4<T> &v, const BoostPyType &t)
559 {
560     MATH_EXC_ON;
561     Vec4<T> res;
562     if(t.attr("__len__")() == 4)
563     {
564         T x = extract<T>(t[0]);
565         T y = extract<T>(t[1]);
566         T z = extract<T>(t[2]);
567         T w = extract<T>(t[3]);
568             
569         if(v.x != T(0) && v.y != T(0) && v.z != T(0) && v.w != T(0)){
570             setValue(res, (T) (x / v.x), (T) (y / v.y), (T) (z / v.z), (T) (w / v.w));
571         }
572         else
573             throw std::domain_error ("Division by zero");
574     }
575     else
576         throw std::invalid_argument ("tuple must have length of 4");
577     
578     return res;
579 }
580
581 template <class T>
582 static Vec4<T>
583 Vec4_divT(const Vec4<T> &v, T a)
584 {
585     MATH_EXC_ON;
586     Vec4<T> res;
587     if(a != T(0)){
588         setValue(res, (T) (v.x / a), (T) (v.y / a), (T) (v.z / a), (T) (v.w / a));
589     }
590     else
591         throw std::domain_error ("Division by zero");
592
593     return res;
594 }
595
596 template <class T>
597 static Vec4<T>
598 Vec4_rdivT(const Vec4<T> &v, T a)
599 {
600     MATH_EXC_ON;
601     Vec4<T> res;
602     if(v.x != T(0) && v.y != T(0) && v.z != T(0) && v.w != T(0)){
603         setValue(res, (T) (a / v.x), (T) (a / v.y), (T) (a / v.z), (T) (a / v.w));
604     }
605     else
606         throw std::domain_error ("Division by zero");
607
608     return res;
609 }
610
611 template <class T>
612 static Vec4<T>
613 Vec4_Vec4_mulT(const Vec4<T>& v, const Vec4<T>& w)
614 {
615     MATH_EXC_ON;
616     return v*w;
617 }
618
619 template <class T>
620 static Vec4<T>
621 Vec4_Vec4_divT(const Vec4<T>& v, const Vec4<T>& w)
622 {
623     MATH_EXC_ON;
624     return v/w;
625 }
626
627 template <class T>
628 static bool
629 lessThan(const Vec4<T> &v, const object &obj)
630 {
631     extract<Vec4<T> > e1(obj);
632     extract<tuple> e2(obj);
633     
634     Vec4<T> res;
635     if(e1.check())
636     {
637         res = e1();
638     }
639     else if(e2.check())
640     {
641         tuple t = e2();
642         T x = extract<T>(t[0]);
643         T y = extract<T>(t[1]);
644         T z = extract<T>(t[2]);
645         T w = extract<T>(t[3]);
646         setValue(res,x,y,z,w);
647     }
648     else
649         throw std::invalid_argument ("invalid parameters passed to operator <");
650     
651     bool isLessThan = (v.x <= res.x && v.y <= res.y && v.z <= res.z && v.w <= res.w)
652                     && v != res;
653     
654     return isLessThan;
655 }
656
657 template <class T>
658 static bool
659 greaterThan(const Vec4<T> &v, const object &obj)
660 {
661     extract<Vec4<T> > e1(obj);
662     extract<tuple> e2(obj);
663     
664     Vec4<T> res;
665     if(e1.check())
666     {
667         res = e1();
668     }
669     else if(e2.check())
670     {
671         tuple t = e2();
672         T x = extract<T>(t[0]);
673         T y = extract<T>(t[1]);
674         T z = extract<T>(t[2]);
675         T w = extract<T>(t[3]);
676         setValue(res,x,y,z,w);
677     }
678     else
679         throw std::invalid_argument ("invalid parameters passed to operator >");
680     
681     bool isGreaterThan = (v.x >= res.x && v.y >= res.y && v.z >= res.z && v.w >= res.w)
682                        && v != res;
683
684     return isGreaterThan;
685 }
686
687 template <class T>
688 static bool
689 lessThanEqual(const Vec4<T> &v, const object &obj)
690 {
691     extract<Vec4<T> > e1(obj);
692     extract<tuple> e2(obj);
693     
694     Vec4<T> res;
695     if(e1.check())
696     {
697         res = e1();
698     }
699     else if(e2.check())
700     {
701         tuple t = e2();
702         T x = extract<T>(t[0]);
703         T y = extract<T>(t[1]);
704         T z = extract<T>(t[2]);
705         T w = extract<T>(t[2]);
706         setValue(res,x,y,z,w);
707     }
708     else
709         throw std::invalid_argument ("invalid parameters passed to operator <=");
710     
711     bool isLessThanEqual = (v.x <= res.x && v.y <= res.y && v.z <= res.z && v.w <= res.w);
712                    
713     return isLessThanEqual;
714 }
715
716 template <class T>
717 static bool
718 greaterThanEqual(const Vec4<T> &v, const object &obj)
719 {
720     extract<Vec4<T> > e1(obj);
721     extract<tuple> e2(obj);
722     
723     Vec4<T> res;
724     if(e1.check())
725     {
726         res = e1();
727     }
728     else if(e2.check())
729     {
730         tuple t = e2();
731         T x = extract<T>(t[0]);
732         T y = extract<T>(t[1]);
733         T z = extract<T>(t[2]);
734         T w = extract<T>(t[3]);
735         setValue(res,x,y,z,w);
736     }
737     else
738         throw std::invalid_argument ("invalid parameters passed to operator >=");
739     
740     bool isGreaterThanEqual = (v.x >= res.x && v.y >= res.y && v.z >= res.z && v.w >= res.w);
741
742     return isGreaterThanEqual;
743 }
744
745
746 template <class T>
747 static bool
748 equalWithAbsErrorObj(const Vec4<T> &v, const object &obj1, const object &obj2)
749 {    
750     extract<Vec4<int> >    e1(obj1);
751     extract<Vec4<float> >  e2(obj1);
752     extract<Vec4<double> > e3(obj1);
753     
754     extract<tuple>         e4(obj1);
755     extract<double>        e5(obj2);
756     
757     Vec4<T> res;
758     if(e1.check())      { res = e1(); }
759     else if(e2.check()) { res = e2(); }
760     else if(e3.check()) { res = e3(); }
761     else if(e4.check())
762     {    
763         tuple t = e4();
764         if(t.attr("__len__")() == 4)
765         {
766             res.x = extract<T>(t[0]);
767             res.y = extract<T>(t[1]);
768             res.z = extract<T>(t[2]);
769             res.z = extract<T>(t[3]);
770         }
771         else
772             throw std::invalid_argument ("tuple of length 4 expected");
773     }
774     else
775         throw std::invalid_argument ("invalid parameters passed to equalWithAbsError");
776     
777     if(e5.check())      { return v.equalWithAbsError(res, (T) e5()); }
778     else
779         throw std::invalid_argument ("invalid parameters passed to equalWithAbsError");
780 }
781
782 template <class T>
783 static bool
784 equalWithRelErrorObj(const Vec4<T> &v, const object &obj1, const object &obj2)
785 {    
786     extract<Vec4<int> >    e1(obj1);
787     extract<Vec4<float> >  e2(obj1);
788     extract<Vec4<double> > e3(obj1);
789     
790     extract<tuple>         e4(obj1);    
791     extract<double>        e5(obj2);
792     
793     Vec4<T> res;
794     if(e1.check())      { res = e1(); }
795     else if(e2.check()) { res = e2(); }
796     else if(e3.check()) { res = e3(); }
797     else if(e4.check())
798     {    
799         tuple t = e4();
800         if(t.attr("__len__")() == 4)
801         {
802             res.x = extract<T>(t[0]);
803             res.y = extract<T>(t[1]);
804             res.z = extract<T>(t[2]);
805             res.w = extract<T>(t[3]);
806         }
807         else
808             throw std::invalid_argument ("tuple of length 4 expected");
809     }
810     else
811         throw std::invalid_argument ("invalid parameters passed to equalWithRelError");
812     
813     if(e5.check())      { return v.equalWithRelError(res, (T) e5()); }
814     else
815         throw std::invalid_argument ("invalid parameters passed to equalWithRelError");    
816     
817 }
818
819
820 template <class T>
821 static bool
822 equal(const Vec4<T> &v, const tuple &t)
823 {
824     Vec4<T> res;
825     if(t.attr("__len__")() == 4)
826     {
827         res.x = extract<T>(t[0]);
828         res.y = extract<T>(t[1]);
829         res.z = extract<T>(t[2]);
830         res.w = extract<T>(t[3]);
831         
832         return (v == res);
833     }
834     else
835         throw std::invalid_argument ("tuple of length 4 expected");    
836 }
837
838 template <class T>
839 static bool
840 notequal(const Vec4<T> &v, const tuple &t)
841 {
842     Vec4<T> res;
843     if(t.attr("__len__")() == 4)
844     {
845         res.x = extract<T>(t[0]);
846         res.y = extract<T>(t[1]);
847         res.z = extract<T>(t[2]);
848         res.w = extract<T>(t[3]);
849         
850         return (v != res);
851     }
852     else
853         throw std::invalid_argument ("tuple of length 4 expected");    
854 }
855
856 // Trick to register methods for float-only-based vectors
857 template <class T, IMATH_ENABLE_IF(!std::is_integral<T>::value)>
858 void register_Vec4_floatonly(class_<Vec4<T>>& vec4_class)
859 {
860    vec4_class
861         .def("length", &Vec4_length<T>,"length() magnitude of the vector")
862         .def("normalize", &Vec4_normalize<T>,return_internal_reference<>(),
863              "v.normalize() destructively normalizes v and returns a reference to it")
864         .def("normalizeExc", &Vec4_normalizeExc<T>,return_internal_reference<>(),
865              "v.normalizeExc() destructively normalizes V and returns a reference to it, throwing an exception if length() == 0")
866         .def("normalizeNonNull", &Vec4_normalizeNonNull<T>,return_internal_reference<>(),
867              "v.normalizeNonNull() destructively normalizes V and returns a reference to it, faster if lngth() != 0")
868         .def("normalized", &Vec4_normalized<T>, "v.normalized() returns a normalized copy of v")
869         .def("normalizedExc", &Vec4_normalizedExc<T>, "v.normalizedExc() returns a normalized copy of v, throwing an exception if length() == 0")
870         .def("normalizedNonNull", &Vec4_normalizedNonNull<T>, "v.normalizedNonNull() returns a normalized copy of v, faster if lngth() != 0")
871         .def("orthogonal", &orthogonal<T>)
872         .def("project", &project<T>)
873         .def("reflect", &reflect<T>)
874         ;
875 }
876
877 template <class T, IMATH_ENABLE_IF(std::is_integral<T>::value)>
878 void register_Vec4_floatonly(class_<Vec4<T>>& vec4_class)
879 {
880 }
881
882 template <class T>
883 class_<Vec4<T> >
884 register_Vec4()
885 {
886     typedef PyImath::StaticFixedArray<Vec4<T>,T,4> Vec4_helper;
887     class_<Vec4<T> > vec4_class(Vec4Name<T>::value(), Vec4Name<T>::value(),init<Vec4<T> >("copy construction"));
888     vec4_class
889         .def("__init__",make_constructor(Vec4_construct_default<T>),"initialize to (0,0,0,0)")
890         .def("__init__",make_constructor(Vec4_object_constructor1<T>))
891         .def("__init__",make_constructor(Vec4_object_constructor2<T>))
892         .def_readwrite("x", &Vec4<T>::x)
893         .def_readwrite("y", &Vec4<T>::y)
894         .def_readwrite("z", &Vec4<T>::z)
895         .def_readwrite("w", &Vec4<T>::w)
896         .def("baseTypeEpsilon", &Vec4<T>::baseTypeEpsilon,"baseTypeEpsilon() epsilon value of the base type of the vector")
897         .staticmethod("baseTypeEpsilon")
898         .def("baseTypeMax", &Vec4<T>::baseTypeMax,"baseTypeMax() max value of the base type of the vector")
899         .staticmethod("baseTypeMax")
900         .def("baseTypeLowest", &Vec4<T>::baseTypeLowest,"baseTypeLowest() largest negative value of the base type of the vector")
901         .staticmethod("baseTypeLowest")
902         .def("baseTypeSmallest", &Vec4<T>::baseTypeSmallest,"baseTypeSmallest() smallest value of the base type of the vector")
903         .staticmethod("baseTypeSmallest")
904         .def("dimensions", &Vec4<T>::dimensions,"dimensions() number of dimensions in the vector")
905         .staticmethod("dimensions")
906         .def("dot", &Vec4_dot<T>,"v1.dot(v2) inner product of the two vectors")
907         .def("dot", &Vec4_dot_Vec4Array<T>,"v1.dot(v2) array inner product")
908     
909         .def("equalWithAbsError", &Vec4<T>::equalWithAbsError,
910          "v1.equalWithAbsError(v2) true if the elements "
911          "of v1 and v2 are the same with an absolute error of no more than e, "
912          "i.e., abs(v1[i] - v2[i]) <= e")
913         .def("equalWithAbsError", &equalWithAbsErrorObj<T>)
914              
915         .def("equalWithRelError", &Vec4<T>::equalWithRelError,
916          "v1.equalWithAbsError(v2) true if the elements "
917          "of v1 and v2 are the same with an absolute error of no more than e, "
918          "i.e., abs(v1[i] - v2[i]) <= e * abs(v1[i])")
919         .def("equalWithRelError", &equalWithRelErrorObj<T>)
920          
921         .def("length2", &Vec4_length2<T>,"length2() square magnitude of the vector")
922         .def("__len__", Vec4_helper::len)
923         .def("__getitem__", Vec4_helper::getitem,return_value_policy<copy_non_const_reference>())
924         .def("__setitem__", Vec4_helper::setitem)
925         .def("negate", &Vec4_negate<T>, return_internal_reference<>())
926         .def("setValue", &setValue<T>)    
927         .def("__neg__", &Vec4_neg<T>)
928         .def("__mul__", &Vec4_mul<T, int>)
929         .def("__mul__", &Vec4_mul<T, float>)
930         .def("__mul__", &Vec4_mul<T, double>)
931         .def("__mul__", &Vec4_mulT<T>)
932         .def("__mul__", &Vec4_mulTArray<T>)
933         .def("__rmul__", &Vec4_rmulT<T>)
934         .def("__rmul__", &Vec4_rmulTArray<T>)
935         .def("__imul__", &Vec4_imulV<T, int>,return_internal_reference<>())
936         .def("__imul__", &Vec4_imulV<T, float>,return_internal_reference<>())
937         .def("__imul__", &Vec4_imulV<T, double>,return_internal_reference<>())
938         .def("__imul__", &Vec4_imulT<T>,return_internal_reference<>())
939         .def("__div__", &Vec4_Vec4_divT<T>)
940         .def("__truediv__", &Vec4_Vec4_divT<T>)
941         .def("__mul__", &Vec4_mulM44<T, float>)
942         .def("__mul__", &Vec4_mulM44<T, double>)
943         .def("__mul__", &Vec4_Vec4_mulT<T>)
944         .def("__div__", &Vec4_div<T,int>)
945         .def("__div__", &Vec4_div<T,float>)
946         .def("__div__", &Vec4_div<T,double>)
947         .def("__div__", &Vec4_divTuple<T,tuple>)
948         .def("__div__", &Vec4_divTuple<T,list>)
949         .def("__div__", &Vec4_divT<T>)
950         .def("__truediv__", &Vec4_div<T,int>)
951         .def("__truediv__", &Vec4_div<T,float>)
952         .def("__truediv__", &Vec4_div<T,double>)
953         .def("__truediv__", &Vec4_divTuple<T,tuple>)
954         .def("__truediv__", &Vec4_divTuple<T,list>)
955         .def("__truediv__", &Vec4_divT<T>)
956         .def("__rdiv__", &Vec4_rdivTuple<T,tuple>)
957         .def("__rdiv__", &Vec4_rdivTuple<T,list>)
958         .def("__rdiv__", &Vec4_rdivT<T>)
959         .def("__rtruediv__", &Vec4_rdivTuple<T,tuple>)
960         .def("__rtruediv__", &Vec4_rdivTuple<T,list>)
961         .def("__rtruediv__", &Vec4_rdivT<T>)
962         .def("__idiv__", &Vec4_idivObj<T>,return_internal_reference<>())
963         .def("__itruediv__", &Vec4_idivObj<T>,return_internal_reference<>())
964         .def("__xor__", &Vec4_dot<T>)
965         .def(self == self) // NOSONAR - suppress SonarCloud bug report.
966         .def(self != self) // NOSONAR - suppress SonarCloud bug report.
967         .def("__add__", &Vec4_add<T>)
968         .def("__add__", &Vec4_addV<T, int>)
969         .def("__add__", &Vec4_addV<T, float>)
970         .def("__add__", &Vec4_addV<T, double>)
971         .def("__add__", &Vec4_addT<T>)
972         .def("__add__", &Vec4_addTuple<T,tuple>)
973         .def("__add__", &Vec4_addTuple<T,list>)
974         .def("__radd__", &Vec4_addT<T>)
975         .def("__radd__", &Vec4_addTuple<T,tuple>)
976         .def("__radd__", &Vec4_addTuple<T,list>)
977         .def("__radd__", &Vec4_add<T>)
978         .def("__iadd__", &Vec4_iaddV<T, int>, return_internal_reference<>())
979         .def("__iadd__", &Vec4_iaddV<T, float>, return_internal_reference<>())
980         .def("__iadd__", &Vec4_iaddV<T, double>, return_internal_reference<>())
981         .def("__sub__", &Vec4_sub<T>)
982         .def("__sub__", &Vec4_subV<T, int>)
983         .def("__sub__", &Vec4_subV<T, float>)
984         .def("__sub__", &Vec4_subV<T, double>)
985         .def("__sub__", &Vec4_subT<T>)
986         .def("__sub__", &Vec4_subTuple<T,tuple>)
987         .def("__sub__", &Vec4_subTuple<T,list>)
988         .def("__rsub__", &Vec4_rsubT<T>)
989         .def("__rsub__", &Vec4_rsubTuple<T,tuple>)
990         .def("__rsub__", &Vec4_rsubTuple<T,list>)
991         .def("__isub__", &Vec4_isubV<T, int>, return_internal_reference<>())
992         .def("__isub__", &Vec4_isubV<T, float>, return_internal_reference<>())
993         .def("__isub__", &Vec4_isubV<T, double>, return_internal_reference<>())
994         .def("__mul__", &mult<T>)
995         .def("__rmul__", &mult<T>)
996         .def("__imul__", &Vec4_imulM44<T, float>, return_internal_reference<>())
997         .def("__imul__", &Vec4_imulM44<T, double>, return_internal_reference<>())
998         .def("__lt__", &lessThan<T>)
999         .def("__gt__", &greaterThan<T>)
1000         .def("__le__", &lessThanEqual<T>)
1001         .def("__ge__", &greaterThanEqual<T>)
1002         .def("__eq__", &equal<T>)
1003         .def("__ne__", &notequal<T>)
1004         //.def(self_ns::str(self))
1005         .def("__str__",&Vec4_str<T>)
1006         .def("__repr__",&Vec4_repr<T>)
1007         ;
1008
1009     register_Vec4_floatonly<T>(vec4_class);
1010
1011     decoratecopy(vec4_class);
1012
1013     //add_swizzle3_operators(v3f_class);
1014     return vec4_class;
1015 }
1016
1017
1018
1019 }  // namespace PyImath
1020
1021 #endif    // _PyImathVec4Impl_h_