1 module math.linear._qv;
2 
3 import core.internal.traits : Unconst;
4 ////import std.traits : Unconst;
5 import std.traits;
6 public import math.linear.quaternion;
7 public import math.linear.vector;
8 
9 auto opBinaryImpl(string op:"*", T,U)(const Quat!T at, const Vec!(U,3) b) 
10 if (isNumeric!T && isNumeric!U)
11 {
12 	alias NT = Unconst!(typeof(rvalueOf!T*rvalueOf!U));
13 	static if (isFloatingPoint!T && !isFloatingPoint!U)
14 		auto a = at.castType!real;
15 	else
16 		alias a = at;
17 	
18 	auto ww	= a.w^^2;
19 	auto w2	= a.w * 2;
20 	auto wx2	= w2 * a.x;
21 	auto wy2	= w2 * a.y;
22 	auto wz2	= w2 * a.z;
23 	auto xx	= a.x^^2;
24 	auto x2	= a.x * 2;
25 	auto xy2	= x2 * a.y;
26 	auto xz2	= x2 * a.z;
27 	auto yy	= a.y^^2;
28 	auto yz2	= a.y * a.z * 2;
29 	auto zz	= a.z * a.z;
30 	
31 	return Vec!(NT,3)	(	ww * b.x	+	wy2 * b.z	-	wz2 * b.y	+	xx * b.x	+
32 			xy2 * b.y	+	xz2 * b.z	-	zz * b.x	-	yy * b.x
33 		,	xy2 * b.x	+	yy * b.y	+	yz2 * b.z	+	wz2 * b.x	-
34 			zz * b.y	+	ww * b.y	-	wx2 * b.z	-	xx * b.y
35 		,	xz2 * b.x	+	yz2 * b.y	+	zz * b.z	-	wy2 * b.x	-
36 			yy * b.z	+	wx2 * b.y	-	xx * b.z	+	ww * b.z
37 		).castType!U;
38 }
39 auto opBinaryImpl(string op:"*", T,U)(const Vec!(T,3) a, const Quat!U b) 
40 if (isNumeric!T && isNumeric!U)
41 {
42 	return b*a;
43 }
44 
45 
46 void opOpAssignImpl(string op:"*", T,U)(ref Vec!(T,3) a, const Quat!U b) 
47 if (isNumeric!T && isNumeric!U)
48 {
49 	T ww	= b.w^^2;
50 	T w2	= b.w * 2;
51 	T wx2	= w2 * b.x;
52 	T wy2	= w2 * b.y;
53 	T wz2	= w2 * b.z;
54 	T xx	= b.x^^2;
55 	T x2	= b.x * 2;
56 	T xy2	= x2 * b.y;
57 	T xz2	= x2 * b.z;
58 	T yy	= b.y^^2;
59 	T yz2	= b.y * b.z * 2;
60 	T zz	= b.z * b.z;
61 	
62 	a.x =	ww * a.x	+	wy2 * a.z	-	wz2 * a.y	+	xx * a.x	+
63 		xy2 * a.y	+	xz2 * a.z	-	zz * a.x	-	yy * a.x	;
64 	a.y =	xy2 * a.x	+	yy * a.y	+	yz2 * a.z	+	wz2 * a.x	-
65 		zz * a.y	+	ww * a.y	-	wx2 * a.z	-	xx * a.y	;
66 	a.z =	xz2 * a.x	+	yz2 * a.y	+	zz * a.z	-	wy2 * a.x	-
67 		yy * a.z	+	wx2 * a.y	-	xx * a.z	+	ww * a.z	;
68 }
69 
70 
71 unittest {
72 	void testValues(A,B)(A a1, A a2, A a3, A a4, B b1, B b2, B b3) {
73 		{
74 			Quat!A a = [a1,a2,a3,a4];
75 			Vec!(B,3) b = [b1,b2,b3];
76 			static assert(is(typeof(a*b) == Vec!(typeof(a1+b1),3)));
77 		}
78 		{
79 			const Quat!A a = [a1,a2,a3,a4];
80 			const Vec!(B,3) b = [b1,b2,b3];
81 			static assert(is(typeof(a*b) == Vec!(typeof(a1+b1),3)));
82 		}
83 		{
84 			Quat!A a = [a1,a2,a3,a4];
85 			const Vec!(B,3) b = [b1,b2,b3];
86 			static assert(is(typeof(a*b) == Vec!(typeof(a1+b1),3)));
87 		}
88 		{
89 			const Quat!A a = [a1,a2,a3,a4];
90 			Vec!(B,3) b = [b1,b2,b3];
91 			static assert(is(typeof(a*b) == Vec!(typeof(a1+b1),3)));
92 		}
93 	}
94 	testValues!(int,int)(1,2,3,4,2,3,4);
95 	testValues!(float,float)(1.5,2.5,3,4,2.5,3,4.5);
96 	testValues!(int,float)(1,2,3,4,2.5,3,4.5);
97 	testValues!(float,double)(1.5,2.5,3,4,2.5,3,4.5);
98 }
99