1#include "../trigonometric.hpp"
2#include "../exponential.hpp"
3#include "../ext/quaternion_geometric.hpp"
4#include <limits>
5
6namespace glm{
7namespace detail
8{
9	template <typename T>
10	struct genTypeTrait<qua<T> >
11	{
12		static const genTypeEnum GENTYPE = GENTYPE_QUAT;
13	};
14
15	template<typename T, qualifier Q, bool Aligned>
16	struct compute_dot<qua<T, Q>, T, Aligned>
17	{
18		GLM_FUNC_QUALIFIER GLM_CONSTEXPR static T call(qua<T, Q> const& a, qua<T, Q> const& b)
19		{
20			vec<4, T, Q> tmp(a.w * b.w, a.x * b.x, a.y * b.y, a.z * b.z);
21			return (tmp.x + tmp.y) + (tmp.z + tmp.w);
22		}
23	};
24
25	template<typename T, qualifier Q, bool Aligned>
26	struct compute_quat_add
27	{
28		GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, qua<T, Q> const& p)
29		{
30			return qua<T, Q>(q.w + p.w, q.x + p.x, q.y + p.y, q.z + p.z);
31		}
32	};
33
34	template<typename T, qualifier Q, bool Aligned>
35	struct compute_quat_sub
36	{
37		GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, qua<T, Q> const& p)
38		{
39			return qua<T, Q>(q.w - p.w, q.x - p.x, q.y - p.y, q.z - p.z);
40		}
41	};
42
43	template<typename T, qualifier Q, bool Aligned>
44	struct compute_quat_mul_scalar
45	{
46		GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, T s)
47		{
48			return qua<T, Q>(q.w * s, q.x * s, q.y * s, q.z * s);
49		}
50	};
51
52	template<typename T, qualifier Q, bool Aligned>
53	struct compute_quat_div_scalar
54	{
55		GLM_FUNC_QUALIFIER GLM_CONSTEXPR static qua<T, Q> call(qua<T, Q> const& q, T s)
56		{
57			return qua<T, Q>(q.w / s, q.x / s, q.y / s, q.z / s);
58		}
59	};
60
61	template<typename T, qualifier Q, bool Aligned>
62	struct compute_quat_mul_vec4
63	{
64		GLM_FUNC_QUALIFIER GLM_CONSTEXPR static vec<4, T, Q> call(qua<T, Q> const& q, vec<4, T, Q> const& v)
65		{
66			return vec<4, T, Q>(q * vec<3, T, Q>(v), v.w);
67		}
68	};
69}//namespace detail
70
71	// -- Component accesses --
72
73	template<typename T, qualifier Q>
74	GLM_FUNC_QUALIFIER GLM_CONSTEXPR T & qua<T, Q>::operator[](typename qua<T, Q>::length_type i)
75	{
76		assert(i >= 0 && i < this->length());
77#		ifdef GLM_FORCE_QUAT_DATA_WXYZ
78			return (&w)[i];
79#		else
80			return (&x)[i];
81#		endif
82	}
83
84	template<typename T, qualifier Q>
85	GLM_FUNC_QUALIFIER GLM_CONSTEXPR T const& qua<T, Q>::operator[](typename qua<T, Q>::length_type i) const
86	{
87		assert(i >= 0 && i < this->length());
88#		ifdef GLM_FORCE_QUAT_DATA_WXYZ
89			return (&w)[i];
90#		else
91			return (&x)[i];
92#		endif
93	}
94
95	// -- Implicit basic constructors --
96
97#	if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE
98		template<typename T, qualifier Q>
99		GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua()
100#			if GLM_CONFIG_CTOR_INIT != GLM_CTOR_INIT_DISABLE
101#				ifdef GLM_FORCE_QUAT_DATA_WXYZ
102					: w(1), x(0), y(0), z(0)
103#				else
104					: x(0), y(0), z(0), w(1)
105#				endif
106#			endif
107		{}
108
109		template<typename T, qualifier Q>
110		GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(qua<T, Q> const& q)
111#			ifdef GLM_FORCE_QUAT_DATA_WXYZ
112				: w(q.w), x(q.x), y(q.y), z(q.z)
113#			else
114				: x(q.x), y(q.y), z(q.z), w(q.w)
115#			endif
116		{}
117#	endif
118
119	template<typename T, qualifier Q>
120	template<qualifier P>
121	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(qua<T, P> const& q)
122#		ifdef GLM_FORCE_QUAT_DATA_WXYZ
123			: w(q.w), x(q.x), y(q.y), z(q.z)
124#		else
125			: x(q.x), y(q.y), z(q.z), w(q.w)
126#		endif
127	{}
128
129	// -- Explicit basic constructors --
130
131	template<typename T, qualifier Q>
132	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(T s, vec<3, T, Q> const& v)
133#		ifdef GLM_FORCE_QUAT_DATA_WXYZ
134			: w(s), x(v.x), y(v.y), z(v.z)
135#		else
136			: x(v.x), y(v.y), z(v.z), w(s)
137#		endif
138	{}
139
140	template <typename T, qualifier Q>
141	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(T _w, T _x, T _y, T _z)
142#		ifdef GLM_FORCE_QUAT_DATA_WXYZ
143			: w(_w), x(_x), y(_y), z(_z)
144#		else
145			: x(_x), y(_y), z(_z), w(_w)
146#		endif
147	{}
148
149	// -- Conversion constructors --
150
151	template<typename T, qualifier Q>
152	template<typename U, qualifier P>
153	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(qua<U, P> const& q)
154#		ifdef GLM_FORCE_QUAT_DATA_WXYZ
155			: w(static_cast<T>(q.w)), x(static_cast<T>(q.x)), y(static_cast<T>(q.y)), z(static_cast<T>(q.z))
156#		else
157			: x(static_cast<T>(q.x)), y(static_cast<T>(q.y)), z(static_cast<T>(q.z)), w(static_cast<T>(q.w))
158#		endif
159	{}
160
161	//template<typename valType>
162	//GLM_FUNC_QUALIFIER qua<valType>::qua
163	//(
164	//	valType const& pitch,
165	//	valType const& yaw,
166	//	valType const& roll
167	//)
168	//{
169	//	vec<3, valType> eulerAngle(pitch * valType(0.5), yaw * valType(0.5), roll * valType(0.5));
170	//	vec<3, valType> c = glm::cos(eulerAngle * valType(0.5));
171	//	vec<3, valType> s = glm::sin(eulerAngle * valType(0.5));
172	//
173	//	this->w = c.x * c.y * c.z + s.x * s.y * s.z;
174	//	this->x = s.x * c.y * c.z - c.x * s.y * s.z;
175	//	this->y = c.x * s.y * c.z + s.x * c.y * s.z;
176	//	this->z = c.x * c.y * s.z - s.x * s.y * c.z;
177	//}
178
179	template<typename T, qualifier Q>
180	GLM_FUNC_QUALIFIER qua<T, Q>::qua(vec<3, T, Q> const& u, vec<3, T, Q> const& v)
181	{
182		T norm_u_norm_v = sqrt(dot(u, u) * dot(v, v));
183		T real_part = norm_u_norm_v + dot(u, v);
184		vec<3, T, Q> t;
185
186		if(real_part < static_cast<T>(1.e-6f) * norm_u_norm_v)
187		{
188			// If u and v are exactly opposite, rotate 180 degrees
189			// around an arbitrary orthogonal axis. Axis normalisation
190			// can happen later, when we normalise the quaternion.
191			real_part = static_cast<T>(0);
192			t = abs(u.x) > abs(u.z) ? vec<3, T, Q>(-u.y, u.x, static_cast<T>(0)) : vec<3, T, Q>(static_cast<T>(0), -u.z, u.y);
193		}
194		else
195		{
196			// Otherwise, build quaternion the standard way.
197			t = cross(u, v);
198		}
199
200		*this = normalize(qua<T, Q>(real_part, t.x, t.y, t.z));
201	}
202
203	template<typename T, qualifier Q>
204	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q>::qua(vec<3, T, Q> const& eulerAngle)
205	{
206		vec<3, T, Q> c = glm::cos(eulerAngle * T(0.5));
207		vec<3, T, Q> s = glm::sin(eulerAngle * T(0.5));
208
209		this->w = c.x * c.y * c.z + s.x * s.y * s.z;
210		this->x = s.x * c.y * c.z - c.x * s.y * s.z;
211		this->y = c.x * s.y * c.z + s.x * c.y * s.z;
212		this->z = c.x * c.y * s.z - s.x * s.y * c.z;
213	}
214
215	template<typename T, qualifier Q>
216	GLM_FUNC_QUALIFIER qua<T, Q>::qua(mat<3, 3, T, Q> const& m)
217	{
218		*this = quat_cast(m);
219	}
220
221	template<typename T, qualifier Q>
222	GLM_FUNC_QUALIFIER qua<T, Q>::qua(mat<4, 4, T, Q> const& m)
223	{
224		*this = quat_cast(m);
225	}
226
227#	if GLM_HAS_EXPLICIT_CONVERSION_OPERATORS
228	template<typename T, qualifier Q>
229	GLM_FUNC_QUALIFIER qua<T, Q>::operator mat<3, 3, T, Q>() const
230	{
231		return mat3_cast(*this);
232	}
233
234	template<typename T, qualifier Q>
235	GLM_FUNC_QUALIFIER qua<T, Q>::operator mat<4, 4, T, Q>() const
236	{
237		return mat4_cast(*this);
238	}
239#	endif//GLM_HAS_EXPLICIT_CONVERSION_OPERATORS
240
241	// -- Unary arithmetic operators --
242
243#	if GLM_CONFIG_DEFAULTED_FUNCTIONS == GLM_DISABLE
244		template<typename T, qualifier Q>
245		GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator=(qua<T, Q> const& q)
246		{
247			this->w = q.w;
248			this->x = q.x;
249			this->y = q.y;
250			this->z = q.z;
251			return *this;
252		}
253#	endif
254
255	template<typename T, qualifier Q>
256	template<typename U>
257	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator=(qua<U, Q> const& q)
258	{
259		this->w = static_cast<T>(q.w);
260		this->x = static_cast<T>(q.x);
261		this->y = static_cast<T>(q.y);
262		this->z = static_cast<T>(q.z);
263		return *this;
264	}
265
266	template<typename T, qualifier Q>
267	template<typename U>
268	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator+=(qua<U, Q> const& q)
269	{
270		return (*this = detail::compute_quat_add<T, Q, detail::is_aligned<Q>::value>::call(*this, qua<T, Q>(q)));
271	}
272
273	template<typename T, qualifier Q>
274	template<typename U>
275	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator-=(qua<U, Q> const& q)
276	{
277		return (*this = detail::compute_quat_sub<T, Q, detail::is_aligned<Q>::value>::call(*this, qua<T, Q>(q)));
278	}
279
280	template<typename T, qualifier Q>
281	template<typename U>
282	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator*=(qua<U, Q> const& r)
283	{
284		qua<T, Q> const p(*this);
285		qua<T, Q> const q(r);
286
287		this->w = p.w * q.w - p.x * q.x - p.y * q.y - p.z * q.z;
288		this->x = p.w * q.x + p.x * q.w + p.y * q.z - p.z * q.y;
289		this->y = p.w * q.y + p.y * q.w + p.z * q.x - p.x * q.z;
290		this->z = p.w * q.z + p.z * q.w + p.x * q.y - p.y * q.x;
291		return *this;
292	}
293
294	template<typename T, qualifier Q>
295	template<typename U>
296	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator*=(U s)
297	{
298		return (*this = detail::compute_quat_mul_scalar<T, Q, detail::is_aligned<Q>::value>::call(*this, static_cast<U>(s)));
299	}
300
301	template<typename T, qualifier Q>
302	template<typename U>
303	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> & qua<T, Q>::operator/=(U s)
304	{
305		return (*this = detail::compute_quat_div_scalar<T, Q, detail::is_aligned<Q>::value>::call(*this, static_cast<U>(s)));
306	}
307
308	// -- Unary bit operators --
309
310	template<typename T, qualifier Q>
311	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator+(qua<T, Q> const& q)
312	{
313		return q;
314	}
315
316	template<typename T, qualifier Q>
317	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator-(qua<T, Q> const& q)
318	{
319		return qua<T, Q>(-q.w, -q.x, -q.y, -q.z);
320	}
321
322	// -- Binary operators --
323
324	template<typename T, qualifier Q>
325	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator+(qua<T, Q> const& q, qua<T, Q> const& p)
326	{
327		return qua<T, Q>(q) += p;
328	}
329
330	template<typename T, qualifier Q>
331	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator-(qua<T, Q> const& q, qua<T, Q> const& p)
332	{
333		return qua<T, Q>(q) -= p;
334	}
335
336	template<typename T, qualifier Q>
337	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator*(qua<T, Q> const& q, qua<T, Q> const& p)
338	{
339		return qua<T, Q>(q) *= p;
340	}
341
342	template<typename T, qualifier Q>
343	GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(qua<T, Q> const& q, vec<3, T, Q> const& v)
344	{
345		vec<3, T, Q> const QuatVector(q.x, q.y, q.z);
346		vec<3, T, Q> const uv(glm::cross(QuatVector, v));
347		vec<3, T, Q> const uuv(glm::cross(QuatVector, uv));
348
349		return v + ((uv * q.w) + uuv) * static_cast<T>(2);
350	}
351
352	template<typename T, qualifier Q>
353	GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<3, T, Q> operator*(vec<3, T, Q> const& v, qua<T, Q> const& q)
354	{
355		return glm::inverse(q) * v;
356	}
357
358	template<typename T, qualifier Q>
359	GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(qua<T, Q> const& q, vec<4, T, Q> const& v)
360	{
361		return detail::compute_quat_mul_vec4<T, Q, detail::is_aligned<Q>::value>::call(q, v);
362	}
363
364	template<typename T, qualifier Q>
365	GLM_FUNC_QUALIFIER GLM_CONSTEXPR vec<4, T, Q> operator*(vec<4, T, Q> const& v, qua<T, Q> const& q)
366	{
367		return glm::inverse(q) * v;
368	}
369
370	template<typename T, qualifier Q>
371	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator*(qua<T, Q> const& q, T const& s)
372	{
373		return qua<T, Q>(
374			q.w * s, q.x * s, q.y * s, q.z * s);
375	}
376
377	template<typename T, qualifier Q>
378	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator*(T const& s, qua<T, Q> const& q)
379	{
380		return q * s;
381	}
382
383	template<typename T, qualifier Q>
384	GLM_FUNC_QUALIFIER GLM_CONSTEXPR qua<T, Q> operator/(qua<T, Q> const& q, T const& s)
385	{
386		return qua<T, Q>(
387			q.w / s, q.x / s, q.y / s, q.z / s);
388	}
389
390	// -- Boolean operators --
391
392	template<typename T, qualifier Q>
393	GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator==(qua<T, Q> const& q1, qua<T, Q> const& q2)
394	{
395		return q1.x == q2.x && q1.y == q2.y && q1.z == q2.z && q1.w == q2.w;
396	}
397
398	template<typename T, qualifier Q>
399	GLM_FUNC_QUALIFIER GLM_CONSTEXPR bool operator!=(qua<T, Q> const& q1, qua<T, Q> const& q2)
400	{
401		return q1.x != q2.x || q1.y != q2.y || q1.z != q2.z || q1.w != q2.w;
402	}
403}//namespace glm
404
405#if GLM_CONFIG_SIMD == GLM_ENABLE
406#	include "type_quat_simd.inl"
407#endif
408
409