summaryrefslogtreecommitdiff
path: root/Runtime/Math/Simd/float4.h
diff options
context:
space:
mode:
Diffstat (limited to 'Runtime/Math/Simd/float4.h')
-rw-r--r--Runtime/Math/Simd/float4.h397
1 files changed, 397 insertions, 0 deletions
diff --git a/Runtime/Math/Simd/float4.h b/Runtime/Math/Simd/float4.h
new file mode 100644
index 0000000..7b653e6
--- /dev/null
+++ b/Runtime/Math/Simd/float4.h
@@ -0,0 +1,397 @@
+#ifndef SIMD_FLOAT4_H
+#define SIMD_FLOAT4_H
+
+#include "Runtime/Serialize/TransferFunctions/SerializeTransfer.h"
+
+#include "Runtime/Math/Simd/intrinsic.h"
+
+#include "Runtime/Math/Simd/bool4.h"
+#include "Runtime/Math/Simd/float1.h"
+
+namespace math
+{
+
+template<typename T> struct ATTRIBUTE_ALIGN(ALIGN4F) vecexp4 : T
+{
+ typedef T value_type;
+ typedef typename T::scalar_type scalar_type;
+ typedef typename T::packed_type packed_type;
+
+ MECANIM_FORCE_INLINE vecexp4() {}
+
+ MECANIM_FORCE_INLINE vecexp4(vecexp4 const& e):value_type(e) { }
+
+ template<typename R> MECANIM_FORCE_INLINE vecexp4(const vecexp4<R> &e):value_type(e){ }
+
+ MECANIM_FORCE_INLINE vecexp4(scalar_type const& x, scalar_type const& y, scalar_type const& z, scalar_type const& w):value_type(x,y,z,w) { }
+
+ MECANIM_FORCE_INLINE vecexp4(value_type const& r):value_type(r) { }
+
+ //template<typename R1, typename R2, typename R3, typename R4> MECANIM_FORCE_INLINE vecexp4(const vecexp1<R1> &x, const vecexp1<R2> &y, const vecexp1<R3> &z, const vecexp1<R4> &w) {
+ // value_type::v = Vcombine( x.eval(), y.eval(), z.eval(), w.eval() );
+ //}
+ MECANIM_FORCE_INLINE vecexp4(const float1 &x, const float1 &y, const float1 &z, const float1 &w) {
+ value_type::v = Vcombine( x.eval(), y.eval(), z.eval(), w.eval() );
+ }
+
+ MECANIM_FORCE_INLINE vecexp4 &operator=(const vecexp4 &l) { value_type::operator =(l); return *this; }
+
+ template<typename R> MECANIM_FORCE_INLINE vecexp4 &operator=(const vecexp4<R> &e) {
+ value_type::v = e.eval(); return *this;
+ }
+
+ template<typename R> MECANIM_FORCE_INLINE vecexp4 &operator=(const vecexp1<R> &e) {
+ value_type::v = e.eval(); return *this;
+ }
+
+ MECANIM_FORCE_INLINE const vecexp4 &operator+() const { return *this; }
+ MECANIM_FORCE_INLINE vecexp4 operator-() const { return vecexp4(Vneg( value_type::eval() )); }
+};
+
+template<typename SCALAR, typename RHS_VECTOR, typename LHS_VECTOR, int RHS_MASK, int LHS_MASK> struct ATTRIBUTE_ALIGN(ALIGN4F) swizzle1
+{
+ typedef SCALAR scalar_type;
+ typedef LHS_VECTOR packed_type;
+ typedef RHS_VECTOR rhs_packed_type;
+
+ enum{
+ RHS_SWZ = RHS_MASK,
+ LHS_SWZ = LHS_MASK
+ };
+
+
+ packed_type v;
+
+ MECANIM_FORCE_INLINE swizzle1(packed_type vector):v(vector) {}
+
+ MECANIM_FORCE_INLINE swizzle1 &operator=(const scalar_type &s) { v = Vswizzle<LHS_SWZ>::lhs(v, Vloadsf(s)); return *this; }
+
+ MECANIM_FORCE_INLINE scalar_type tofloat() { return Vstoresf( Vswizzle<RHS_SWZ>::rhs(v) ); }
+
+ MECANIM_FORCE_INLINE rhs_packed_type eval()const{ return Vswizzle<RHS_SWZ>::rhs(v); }
+private:
+
+
+ MECANIM_FORCE_INLINE swizzle1 &operator=(const swizzle1 &s) {return *this;}
+};
+
+template<typename SCALAR, typename VECTOR, int MASK> struct ATTRIBUTE_ALIGN(ALIGN4F) swizzle
+{
+ typedef SCALAR scalar_type;
+ typedef VECTOR packed_type;
+
+ enum{
+ RHS_SWZ = MASK
+ };
+
+ MECANIM_FORCE_INLINE swizzle(packed_type const& vector):v(vector) {}
+
+ MECANIM_FORCE_INLINE packed_type eval()const{ return Vswizzle<RHS_SWZ>::rhs(v); }
+
+protected:
+ packed_type v;
+};
+
+struct ATTRIBUTE_ALIGN(ALIGN4F) vec4
+{
+ typedef float scalar_type;
+ typedef vec4f packed_type;
+ typedef vec4f const& const_reference_packed_type;
+ typedef vec4f& reference_packed_type;
+
+ enum{
+ RHS_SWZ = kXYZW
+ };
+
+ MECANIM_FORCE_INLINE vec4() {}
+
+ MECANIM_FORCE_INLINE vec4(scalar_type x, scalar_type y, scalar_type z, scalar_type w):v(Vload4sf(x,y,z,w)) { }
+
+ MECANIM_FORCE_INLINE vec4(scalar_type s):v(Vloadsf(s)) { }
+
+ MECANIM_FORCE_INLINE vec4(packed_type vector):v(vector){ }
+
+ template<typename T> MECANIM_FORCE_INLINE vec4(const T& vector):v(vector.eval()){ }
+
+ MECANIM_FORCE_INLINE vec4 &operator=(const vec4 &l) {
+ SIMD_ASSERT_IF(!l.IsFinite());
+ v = l.v;
+ return *this;
+ }
+
+ MECANIM_FORCE_INLINE packed_type eval()const{ return v; }
+
+ inline bool IsFinite ()const
+ {
+ return ::IsFinite( x().tofloat() ) & ::IsFinite( y().tofloat() ) & ::IsFinite( z().tofloat() ) & ::IsFinite( w().tofloat() );
+ }
+
+ MECANIM_FORCE_INLINE vecexp1< swizzle1<scalar_type, packed_type, packed_type, kXXXX, kXYZW> > x()const { return vecexp1< swizzle1<scalar_type, packed_type, packed_type, kXXXX, kXYZW> >(v); }
+ MECANIM_FORCE_INLINE vecexp1< swizzle1<scalar_type, packed_type, packed_type, kYYYY, kYXZW> > y()const { return vecexp1< swizzle1<scalar_type, packed_type, packed_type, kYYYY, kYXZW> >(v); }
+ MECANIM_FORCE_INLINE vecexp1< swizzle1<scalar_type, packed_type, packed_type, kZZZZ, kZYXW> > z()const { return vecexp1< swizzle1<scalar_type, packed_type, packed_type, kZZZZ, kZYXW> >(v); }
+ MECANIM_FORCE_INLINE vecexp1< swizzle1<scalar_type, packed_type, packed_type, kWWWW, kWYZX> > w()const { return vecexp1< swizzle1<scalar_type, packed_type, packed_type, kWWWW, kWYZX> >(v); }
+
+ MECANIM_FORCE_INLINE vecexp1< swizzle1<scalar_type, packed_type, reference_packed_type, kXXXX, kXYZW> > x() { return vecexp1< swizzle1<scalar_type, packed_type, reference_packed_type, kXXXX, kXYZW> >(v); }
+ MECANIM_FORCE_INLINE vecexp1< swizzle1<scalar_type, packed_type, reference_packed_type, kYYYY, kYXZW> > y() { return vecexp1< swizzle1<scalar_type, packed_type, reference_packed_type, kYYYY, kYXZW> >(v); }
+ MECANIM_FORCE_INLINE vecexp1< swizzle1<scalar_type, packed_type, reference_packed_type, kZZZZ, kZYXW> > z() { return vecexp1< swizzle1<scalar_type, packed_type, reference_packed_type, kZZZZ, kZYXW> >(v); }
+ MECANIM_FORCE_INLINE vecexp1< swizzle1<scalar_type, packed_type, reference_packed_type, kWWWW, kWYZX> > w() { return vecexp1< swizzle1<scalar_type, packed_type, reference_packed_type, kWWWW, kWYZX> >(v); }
+
+ MECANIM_FORCE_INLINE vecexp4< swizzle<scalar_type, packed_type, kWXZY> > wxzy()const { return vecexp4< swizzle<scalar_type, packed_type, kWXZY> >(v); }
+ MECANIM_FORCE_INLINE vecexp4< swizzle<scalar_type, packed_type, kXZWY> > xzwy()const { return vecexp4< swizzle<scalar_type, packed_type, kXZWY> >(v); }
+ MECANIM_FORCE_INLINE vecexp4< swizzle<scalar_type, packed_type, kXWYZ> > xwyz()const { return vecexp4< swizzle<scalar_type, packed_type, kXWYZ> >(v); }
+ MECANIM_FORCE_INLINE vecexp4< swizzle<scalar_type, packed_type, kWYXZ> > wyxz()const { return vecexp4< swizzle<scalar_type, packed_type, kWYXZ> >(v); }
+ MECANIM_FORCE_INLINE vecexp4< swizzle<scalar_type, packed_type, kZYWX> > zywx()const { return vecexp4< swizzle<scalar_type, packed_type, kZYWX> >(v); }
+ MECANIM_FORCE_INLINE vecexp4< swizzle<scalar_type, packed_type, kYWZX> > ywzx()const { return vecexp4< swizzle<scalar_type, packed_type, kYWZX> >(v); }
+ MECANIM_FORCE_INLINE vecexp4< swizzle<scalar_type, packed_type, kYZXW> > yzxw()const { return vecexp4< swizzle<scalar_type, packed_type, kYZXW> >(v); }
+ MECANIM_FORCE_INLINE vecexp4< swizzle<scalar_type, packed_type, kZXYW> > zxyw()const { return vecexp4< swizzle<scalar_type, packed_type, kZXYW> >(v); }
+ MECANIM_FORCE_INLINE vecexp4< swizzle<scalar_type, packed_type, kZWXY> > zwxy()const { return vecexp4< swizzle<scalar_type, packed_type, kZWXY> >(v); }
+ MECANIM_FORCE_INLINE vecexp4< swizzle<scalar_type, packed_type, kWWWZ> > wwwz()const { return vecexp4< swizzle<scalar_type, packed_type, kWWWZ> >(v); }
+ MECANIM_FORCE_INLINE vecexp4< swizzle<scalar_type, packed_type, kWWZZ> > wwzz()const { return vecexp4< swizzle<scalar_type, packed_type, kWWZZ> >(v); }
+ MECANIM_FORCE_INLINE vecexp4< swizzle<scalar_type, packed_type, kWZYX> > wzyx()const { return vecexp4< swizzle<scalar_type, packed_type, kWZYX> >(v); }
+ MECANIM_FORCE_INLINE vecexp4< swizzle<scalar_type, packed_type, kYXWZ> > yxwz()const { return vecexp4< swizzle<scalar_type, packed_type, kYXWZ> >(v); }
+
+protected:
+ packed_type v;
+};
+
+struct ATTRIBUTE_ALIGN(ALIGN4F) float4 : vecexp4<vec4>
+{
+ DEFINE_GET_TYPESTRING(float4)
+
+ typedef vec4 value_type;
+ typedef vec4::scalar_type scalar_type;
+ typedef vec4::packed_type packed_type;
+
+ MECANIM_FORCE_INLINE float4() {}
+
+ MECANIM_FORCE_INLINE float4(float4 const& vector):vecexp4<value_type>(vector.v) { }
+
+ explicit MECANIM_FORCE_INLINE float4(scalar_type s):vecexp4<value_type>(s) { }
+
+ explicit MECANIM_FORCE_INLINE float4(packed_type const& vector):vecexp4<value_type>(vector) { }
+
+ template<typename R> MECANIM_FORCE_INLINE float4(const vecexp4<R> &r):vecexp4<value_type>(r) { }
+
+ MECANIM_FORCE_INLINE float4(scalar_type x, scalar_type y, scalar_type z, scalar_type w):vecexp4<value_type>(x,y,z,w) { }
+
+ MECANIM_FORCE_INLINE float4(const float1 &x, const float1 &y, const float1 &z, const float1 &w):vecexp4<value_type>(x,y,z,w) { }
+
+ MECANIM_FORCE_INLINE float4 &operator=(const float4 &r) { vecexp4<vec4>::operator =(r); return *this; }
+
+ template<typename R> MECANIM_FORCE_INLINE float4 &operator=(const vecexp4<R> &r) { vecexp4<vec4>::operator =(r); return *this; }
+ template<typename R> MECANIM_FORCE_INLINE float4 &operator=(const vecexp1<R> &r) { vecexp4<vec4>::operator =(r); return *this; }
+
+ template<typename R> MECANIM_FORCE_INLINE float4 &operator+=(const vecexp4<R> &r) { value_type::v = Vadd(value_type::v, r.eval()); return *this; }
+ template<typename R> MECANIM_FORCE_INLINE float4 &operator+=(const vecexp1<R> &r) { value_type::v = Vadd(value_type::v, r.eval()); return *this; }
+ MECANIM_FORCE_INLINE float4 &operator+=(float r) { value_type::v = Vadd(value_type::v, Vloadsf(r)); return *this; }
+
+ template<typename R> MECANIM_FORCE_INLINE float4 &operator-=(const vecexp4<R> &r) { value_type::v = Vsub(value_type::v, r.eval()); return *this; }
+ template<typename R> MECANIM_FORCE_INLINE float4 &operator-=(const vecexp1<R> &r) { value_type::v = Vsub(value_type::v, r.eval()); return *this; }
+ MECANIM_FORCE_INLINE float4 &operator-=(float r) { value_type::v = Vsub(value_type::v, Vloadsf(r)); return *this; }
+
+ template<typename R> MECANIM_FORCE_INLINE float4 &operator*=(const vecexp4<R> &r) { value_type::v = Vmul(value_type::v, r.eval()); return *this; }
+ template<typename R> MECANIM_FORCE_INLINE float4 &operator*=(const vecexp1<R> &r) { value_type::v = Vmul(value_type::v, r.eval()); return *this; }
+ MECANIM_FORCE_INLINE float4 &operator*=(float r) { value_type::v = Vmul(value_type::v, Vloadsf(r)); return *this; }
+
+
+ template<typename R> MECANIM_FORCE_INLINE float4 &operator/=(const vecexp4<R> &r) { value_type::v = Vdiv(value_type::v, r.eval()); return *this; }
+ template<typename R> MECANIM_FORCE_INLINE float4 &operator/=(const vecexp1<R> &r) { value_type::v = Vdiv(value_type::v, r.eval()); return *this; }
+ MECANIM_FORCE_INLINE float4 &operator/=(float r) { value_type::v = Vdiv(value_type::v, Vloadsf(r)); return *this; }
+
+ // prefix decrement
+ MECANIM_FORCE_INLINE float4 &operator++() { value_type::v = Vinc(value_type::v); return *this; }
+ // postfix increment
+ MECANIM_FORCE_INLINE float4 operator++(int) { float4 r = *this; value_type::v = Vinc(value_type::eval() ); return r; }
+
+ // prefix decrement
+ MECANIM_FORCE_INLINE float4 &operator--() { value_type::v = Vdec(value_type::v); return *this; }
+ // postfix decrement
+ MECANIM_FORCE_INLINE float4 operator--(int) { float4 r = *this; value_type::v = Vdec(value_type::eval() ); return r; }
+
+
+ static float4 zero() {return float4(Vzero()); } // 0
+ static float4 one() {return float4(Vone());} // 1
+
+
+ template<class TransferFunction>
+ MECANIM_FORCE_INLINE void Transfer (TransferFunction& transfer)
+ {
+ /////@TODO: This is wrong. It will not work for SafeBinaryRead
+ /////// Probably other places in the code too!
+
+ float ATTRIBUTE_ALIGN(ALIGN4F) buf[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ if(transfer.IsReading())
+ {
+ transfer.Transfer(buf[0], "x");
+ transfer.Transfer(buf[1], "y");
+ transfer.Transfer(buf[2], "z");
+ transfer.Transfer(buf[3], "w");
+
+ v = Vloadpf(buf, 0);
+ }
+ else if(transfer.IsWriting())
+ {
+ Vstorepf(v, buf, 0);
+
+ transfer.Transfer(buf[0], "x");
+ transfer.Transfer(buf[1], "y");
+ transfer.Transfer(buf[2], "z");
+ transfer.Transfer(buf[3], "w");
+ }
+ else
+ {
+ transfer.Transfer(buf[0], "x");
+ transfer.Transfer(buf[1], "y");
+ transfer.Transfer(buf[2], "z");
+ transfer.Transfer(buf[3], "w");
+ }
+ }
+};
+
+// vecexp4 Arithemtic
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE vecexp4<vec4> operator+(const vecexp4<LHS> &l, const vecexp4<RHS> &r)
+{
+ return vecexp4<vec4>( Vadd( l.eval(), r.eval() ));
+}
+
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE vecexp4<vec4> operator+(const vecexp4<LHS> &l, const vecexp1<RHS> &r)
+{
+ return vecexp4<vec4>( Vadd( l.eval(), r.eval() ));
+}
+
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE vecexp4<vec4> operator+(const vecexp1<LHS> &l, const vecexp4<RHS> &r)
+{
+ return vecexp4<vec4>( Vadd( l.eval(), r.eval() ));
+}
+
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE vecexp4<vec4> operator-(const vecexp4<LHS> &l, const vecexp4<RHS> &r)
+{
+ return vecexp4<vec4>( Vsub( l.eval(), r.eval() ));
+}
+
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE vecexp4<vec4> operator-(const vecexp4<LHS> &l, const vecexp1<RHS> &r)
+{
+ return vecexp4<vec4>( Vsub( l.eval(), r.eval() ));
+}
+
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE vecexp4<vec4> operator-(const vecexp1<LHS> &l, const vecexp4<RHS> &r)
+{
+ return vecexp4<vec4>( Vsub( l.eval(), r.eval() ));
+}
+
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE vecexp4<vec4> operator*(const vecexp4<LHS> &l, const vecexp4<RHS> &r)
+{
+ return vecexp4<vec4>( Vmul( l.eval(), r.eval() ));
+}
+
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE vecexp4<vec4> operator*(const vecexp4<LHS> &l,const vecexp1<RHS> &r)
+{
+ return vecexp4<vec4>( Vmul( l.eval(), r.eval() ));
+}
+
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE vecexp4<vec4> operator*(const vecexp1<LHS> &l, const vecexp4<RHS> &r)
+{
+ return vecexp4<vec4>( Vmul( l.eval(), r.eval() ));
+}
+
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE vecexp4<vec4> operator/(const vecexp4<LHS> &l, const vecexp4<RHS> &r)
+{
+ return vecexp4<vec4>( Vdiv( l.eval(), r.eval() ));
+}
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE vecexp4<vec4> operator/(const vecexp4<LHS> &l, const vecexp1<RHS> &r)
+{
+ return vecexp4<vec4>( Vdiv( l.eval(), r.eval() ));
+}
+
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE vecexp4<vec4> operator/(const vecexp1<LHS> &l, const vecexp4<RHS> &r)
+{
+ return vecexp4<vec4>( Vdiv( l.eval(), r.eval() ));
+}
+
+
+// vecexp4 logic
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE bool4 operator<(const vecexp4<LHS> &l, const vecexp4<RHS> &r)
+{
+ return bool4(Vcmplt(l.eval(), r.eval()));
+}
+template<typename LHS> static MECANIM_FORCE_INLINE bool4 operator<(const vecexp4<LHS> &l, const float1 &r)
+{
+ return bool4(Vcmplt(l.eval(), r.eval()));
+}
+template<typename RHS> static MECANIM_FORCE_INLINE bool4 operator<(const float1 &l, const vecexp4<RHS> &r)
+{
+ return bool4(Vcmplt(l.eval(), r.eval()));
+}
+
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE bool4 operator<=(const vecexp4<LHS> &l, const vecexp4<RHS> &r)
+{
+ return bool4(Vcmple(l.eval(), r.eval()));
+}
+template<typename LHS> static MECANIM_FORCE_INLINE bool4 operator<=(const vecexp4<LHS> &l, const float1 &r)
+{
+ return bool4(Vcmple(l.eval(), r.eval()));
+}
+template<typename RHS> static MECANIM_FORCE_INLINE bool4 operator<=(const float1 &l, const vecexp4<RHS> &r)
+{
+ return bool4(Vcmple(l.eval(), r.eval()));
+}
+
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE bool4 operator==(const vecexp4<LHS> &l, const vecexp4<RHS> &r)
+{
+ return bool4( Vcmpeq(l.eval(), r.eval()) );
+}
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE bool4 operator==(const vecexp4<LHS> &l, const vecexp1<RHS> &r)
+{
+ return bool4( Vcmpeq(l.eval(), r.eval()) );
+}
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE bool4 operator==(const vecexp1<LHS> &l, const vecexp4<RHS> &r)
+{
+ return bool4( Vcmpeq(l.eval(), r.eval()) );
+}
+
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE bool4 operator!=(const vecexp4<LHS> &l, const vecexp4<RHS> &r)
+{
+ return bool4( Vcmpneq(l.eval(), r.eval()) );
+}
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE bool4 operator!=(const vecexp1<LHS> &l, const vecexp4<RHS> &r)
+{
+ return bool4( Vcmpneq(l.eval(), r.eval()) );
+}
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE bool4 operator!=(const vecexp4<LHS> &l, const vecexp1<RHS> &r)
+{
+ return bool4( Vcmpneq(l.eval(), r.eval()) );
+}
+
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE bool4 operator>=(const vecexp4<LHS> &l, const vecexp4<RHS> &r)
+{
+ return bool4( Vcmpge(l.eval(), r.eval()) );
+}
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE bool4 operator>=(const vecexp1<LHS> &l, const vecexp4<RHS> &r)
+{
+ return bool4( Vcmpge(l.eval(), r.eval()) );
+}
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE bool4 operator>=(const vecexp4<LHS> &l, const vecexp1<RHS> &r)
+{
+ return bool4( Vcmpge(l.eval(), r.eval()) );
+}
+
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE bool4 operator>(const vecexp4<LHS> &l, const vecexp4<RHS> &r)
+{
+ return bool4( Vcmpgt(l.eval(), r.eval()) );
+}
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE bool4 operator>(const vecexp4<LHS> &l, const vecexp1<RHS> &r)
+{
+ return bool4( Vcmpgt(l.eval(), r.eval()) );
+}
+template<typename LHS, typename RHS> static MECANIM_FORCE_INLINE bool4 operator>(const vecexp1<LHS> &l, const vecexp4<RHS> &r)
+{
+ return bool4( Vcmpgt(l.eval(), r.eval()) );
+}
+
+#define constant_float4(name, x,y,z,w) \
+ cvec4f(c##name, x,y,z,w); \
+ math::float4 const name(c##name); \
+
+}
+
+#endif