1///////////////////////////////////////////////////////////////////////////////////
2/// OpenGL Mathematics (glm.g-truc.net)
3///
4/// Copyright (c) 2005 - 2014 G-Truc Creation (www.g-truc.net)
5/// Permission is hereby granted, free of charge, to any person obtaining a copy
6/// of this software and associated documentation files (the "Software"), to deal
7/// in the Software without restriction, including without limitation the rights
8/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9/// copies of the Software, and to permit persons to whom the Software is
10/// furnished to do so, subject to the following conditions:
11///
12/// The above copyright notice and this permission notice shall be included in
13/// all copies or substantial portions of the Software.
14///
15/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21/// THE SOFTWARE.
22///
23/// @ref core
24/// @file glm/core/type_mat4x4.inl
25/// @date 2005-01-27 / 2011-06-15
26/// @author Christophe Riccio
27///////////////////////////////////////////////////////////////////////////////////
28
29namespace glm{
30namespace detail
31{
32	template <typename T, precision P>
33	GLM_FUNC_QUALIFIER GLM_CONSTEXPR length_t tmat4x4<T, P>::length() const
34	{
35		return 4;
36	}
37
38	//////////////////////////////////////
39	// Accesses
40
41	template <typename T, precision P>
42	GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::col_type &
43	tmat4x4<T, P>::operator[]
44	(
45		length_t i
46	)
47	{
48		assert(i < this->length());
49		return this->value[i];
50	}
51
52	template <typename T, precision P>
53	GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::col_type const &
54	tmat4x4<T, P>::operator[]
55	(
56		length_t i
57	) const
58	{
59		assert(i < this->length());
60		return this->value[i];
61	}
62
63	//////////////////////////////////////////////////////////////
64	// Constructors
65
66	template <typename T, precision P>
67	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4()
68	{
69		T Zero(0);
70		T One(1);
71		this->value[0] = col_type(One, Zero, Zero, Zero);
72		this->value[1] = col_type(Zero, One, Zero, Zero);
73		this->value[2] = col_type(Zero, Zero, One, Zero);
74		this->value[3] = col_type(Zero, Zero, Zero, One);
75	}
76
77	template <typename T, precision P>
78	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
79	(
80		tmat4x4<T, P> const & m
81	)
82	{
83		this->value[0] = m[0];
84		this->value[1] = m[1];
85		this->value[2] = m[2];
86		this->value[3] = m[3];
87	}
88
89	template <typename T, precision P>
90	template <precision Q>
91	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
92	(
93		tmat4x4<T, Q> const & m
94	)
95	{
96		this->value[0] = m[0];
97		this->value[1] = m[1];
98		this->value[2] = m[2];
99		this->value[3] = m[3];
100	}
101
102	template <typename T, precision P>
103	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
104	(
105		ctor
106	)
107	{}
108
109	template <typename T, precision P>
110	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
111	(
112		T const & s
113	)
114	{
115		value_type const Zero(0);
116		this->value[0] = col_type(s, Zero, Zero, Zero);
117		this->value[1] = col_type(Zero, s, Zero, Zero);
118		this->value[2] = col_type(Zero, Zero, s, Zero);
119		this->value[3] = col_type(Zero, Zero, Zero, s);
120	}
121
122	template <typename T, precision P>
123	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
124	(
125		T const & x0, T const & y0, T const & z0, T const & w0,
126		T const & x1, T const & y1, T const & z1, T const & w1,
127		T const & x2, T const & y2, T const & z2, T const & w2,
128		T const & x3, T const & y3, T const & z3, T const & w3
129	)
130	{
131		this->value[0] = col_type(x0, y0, z0, w0);
132		this->value[1] = col_type(x1, y1, z1, w1);
133		this->value[2] = col_type(x2, y2, z2, w2);
134		this->value[3] = col_type(x3, y3, z3, w3);
135	}
136
137	template <typename T, precision P>
138	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
139	(
140		col_type const & v0,
141		col_type const & v1,
142		col_type const & v2,
143		col_type const & v3
144	)
145	{
146		this->value[0] = v0;
147		this->value[1] = v1;
148		this->value[2] = v2;
149		this->value[3] = v3;
150	}
151
152	template <typename T, precision P>
153	template <typename U, precision Q>
154	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
155	(
156		tmat4x4<U, Q> const & m
157	)
158	{
159		this->value[0] = col_type(m[0]);
160		this->value[1] = col_type(m[1]);
161		this->value[2] = col_type(m[2]);
162		this->value[3] = col_type(m[3]);
163	}
164
165	//////////////////////////////////////
166	// Conversion constructors
167	template <typename T, precision P>
168	template <
169		typename X1, typename Y1, typename Z1, typename W1,
170		typename X2, typename Y2, typename Z2, typename W2,
171		typename X3, typename Y3, typename Z3, typename W3,
172		typename X4, typename Y4, typename Z4, typename W4>
173	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
174	(
175		X1 const & x1, Y1 const & y1, Z1 const & z1, W1 const & w1,
176		X2 const & x2, Y2 const & y2, Z2 const & z2, W2 const & w2,
177		X3 const & x3, Y3 const & y3, Z3 const & z3, W3 const & w3,
178		X4 const & x4, Y4 const & y4, Z4 const & z4, W4 const & w4
179	)
180	{
181		GLM_STATIC_ASSERT(std::numeric_limits<X1>::is_iec559 || std::numeric_limits<X1>::is_integer, "*mat4x4 constructor only takes float and integer types, 1st parameter type invalid.");
182		GLM_STATIC_ASSERT(std::numeric_limits<Y1>::is_iec559 || std::numeric_limits<Y1>::is_integer, "*mat4x4 constructor only takes float and integer types, 2nd parameter type invalid.");
183		GLM_STATIC_ASSERT(std::numeric_limits<Z1>::is_iec559 || std::numeric_limits<Z1>::is_integer, "*mat4x4 constructor only takes float and integer types, 3rd parameter type invalid.");
184		GLM_STATIC_ASSERT(std::numeric_limits<W1>::is_iec559 || std::numeric_limits<W1>::is_integer, "*mat4x4 constructor only takes float and integer types, 4th parameter type invalid.");
185
186		GLM_STATIC_ASSERT(std::numeric_limits<X2>::is_iec559 || std::numeric_limits<X2>::is_integer, "*mat4x4 constructor only takes float and integer types, 5th parameter type invalid.");
187		GLM_STATIC_ASSERT(std::numeric_limits<Y2>::is_iec559 || std::numeric_limits<Y2>::is_integer, "*mat4x4 constructor only takes float and integer types, 6th parameter type invalid.");
188		GLM_STATIC_ASSERT(std::numeric_limits<Z2>::is_iec559 || std::numeric_limits<Z2>::is_integer, "*mat4x4 constructor only takes float and integer types, 7th parameter type invalid.");
189		GLM_STATIC_ASSERT(std::numeric_limits<W2>::is_iec559 || std::numeric_limits<W2>::is_integer, "*mat4x4 constructor only takes float and integer types, 8th parameter type invalid.");
190
191		GLM_STATIC_ASSERT(std::numeric_limits<X3>::is_iec559 || std::numeric_limits<X3>::is_integer, "*mat4x4 constructor only takes float and integer types, 9th parameter type invalid.");
192		GLM_STATIC_ASSERT(std::numeric_limits<Y3>::is_iec559 || std::numeric_limits<Y3>::is_integer, "*mat4x4 constructor only takes float and integer types, 10th parameter type invalid.");
193		GLM_STATIC_ASSERT(std::numeric_limits<Z3>::is_iec559 || std::numeric_limits<Z3>::is_integer, "*mat4x4 constructor only takes float and integer types, 11th parameter type invalid.");
194		GLM_STATIC_ASSERT(std::numeric_limits<W3>::is_iec559 || std::numeric_limits<W3>::is_integer, "*mat4x4 constructor only takes float and integer types, 12th parameter type invalid.");
195
196		GLM_STATIC_ASSERT(std::numeric_limits<X4>::is_iec559 || std::numeric_limits<X4>::is_integer, "*mat4x4 constructor only takes float and integer types, 13th parameter type invalid.");
197		GLM_STATIC_ASSERT(std::numeric_limits<Y4>::is_iec559 || std::numeric_limits<Y4>::is_integer, "*mat4x4 constructor only takes float and integer types, 14th parameter type invalid.");
198		GLM_STATIC_ASSERT(std::numeric_limits<Z4>::is_iec559 || std::numeric_limits<Z4>::is_integer, "*mat4x4 constructor only takes float and integer types, 15th parameter type invalid.");
199		GLM_STATIC_ASSERT(std::numeric_limits<W4>::is_iec559 || std::numeric_limits<W4>::is_integer, "*mat4x4 constructor only takes float and integer types, 16th parameter type invalid.");
200
201		this->value[0] = col_type(static_cast<T>(x1), value_type(y1), value_type(z1), value_type(w1));
202		this->value[1] = col_type(static_cast<T>(x2), value_type(y2), value_type(z2), value_type(w2));
203		this->value[2] = col_type(static_cast<T>(x3), value_type(y3), value_type(z3), value_type(w3));
204		this->value[3] = col_type(static_cast<T>(x4), value_type(y4), value_type(z4), value_type(w4));
205	}
206
207	template <typename T, precision P>
208	template <typename V1, typename V2, typename V3, typename V4>
209	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
210	(
211		tvec4<V1, P> const & v1,
212		tvec4<V2, P> const & v2,
213		tvec4<V3, P> const & v3,
214		tvec4<V4, P> const & v4
215	)
216	{
217		GLM_STATIC_ASSERT(std::numeric_limits<V1>::is_iec559 || std::numeric_limits<V1>::is_integer, "*mat4x4 constructor only takes float and integer types, 1st parameter type invalid.");
218		GLM_STATIC_ASSERT(std::numeric_limits<V2>::is_iec559 || std::numeric_limits<V2>::is_integer, "*mat4x4 constructor only takes float and integer types, 2nd parameter type invalid.");
219		GLM_STATIC_ASSERT(std::numeric_limits<V3>::is_iec559 || std::numeric_limits<V3>::is_integer, "*mat4x4 constructor only takes float and integer types, 3rd parameter type invalid.");
220		GLM_STATIC_ASSERT(std::numeric_limits<V4>::is_iec559 || std::numeric_limits<V4>::is_integer, "*mat4x4 constructor only takes float and integer types, 4th parameter type invalid.");
221
222		this->value[0] = col_type(v1);
223		this->value[1] = col_type(v2);
224		this->value[2] = col_type(v3);
225		this->value[3] = col_type(v4);
226	}
227
228	//////////////////////////////////////
229	// Matrix convertion constructors
230	template <typename T, precision P>
231	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
232	(
233		tmat2x2<T, P> const & m
234	)
235	{
236		this->value[0] = col_type(m[0], detail::tvec2<T, P>(0));
237		this->value[1] = col_type(m[1], detail::tvec2<T, P>(0));
238		this->value[2] = col_type(static_cast<T>(0));
239		this->value[3] = col_type(static_cast<T>(0), value_type(0), value_type(0), value_type(1));
240	}
241
242	template <typename T, precision P>
243	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
244	(
245		tmat3x3<T, P> const & m
246	)
247	{
248		this->value[0] = col_type(m[0], value_type(0));
249		this->value[1] = col_type(m[1], value_type(0));
250		this->value[2] = col_type(m[2], value_type(0));
251		this->value[3] = col_type(static_cast<T>(0), value_type(0), value_type(0), value_type(1));
252	}
253
254	template <typename T, precision P>
255	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
256	(
257		tmat2x3<T, P> const & m
258	)
259	{
260		this->value[0] = col_type(m[0], value_type(0));
261		this->value[1] = col_type(m[1], value_type(0));
262		this->value[2] = col_type(static_cast<T>(0));
263		this->value[3] = col_type(static_cast<T>(0), value_type(0), value_type(0), value_type(1));
264	}
265
266	template <typename T, precision P>
267	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
268	(
269		tmat3x2<T, P> const & m
270	)
271	{
272		this->value[0] = col_type(m[0], detail::tvec2<T, P>(0));
273		this->value[1] = col_type(m[1], detail::tvec2<T, P>(0));
274		this->value[2] = col_type(m[2], detail::tvec2<T, P>(0));
275		this->value[3] = col_type(static_cast<T>(0), value_type(0), value_type(0), value_type(1));
276	}
277
278	template <typename T, precision P>
279	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
280	(
281		tmat2x4<T, P> const & m
282	)
283	{
284		this->value[0] = m[0];
285		this->value[1] = m[1];
286		this->value[2] = col_type(T(0));
287		this->value[3] = col_type(T(0), T(0), T(0), T(1));
288	}
289
290	template <typename T, precision P>
291	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
292	(
293		tmat4x2<T, P> const & m
294	)
295	{
296		this->value[0] = col_type(m[0], detail::tvec2<T, P>(0));
297		this->value[1] = col_type(m[1], detail::tvec2<T, P>(0));
298		this->value[2] = col_type(T(0));
299		this->value[3] = col_type(T(0), T(0), T(0), T(1));
300	}
301
302	template <typename T, precision P>
303	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
304	(
305		tmat3x4<T, P> const & m
306	)
307	{
308		this->value[0] = m[0];
309		this->value[1] = m[1];
310		this->value[2] = m[2];
311		this->value[3] = col_type(T(0), T(0), T(0), T(1));
312	}
313
314	template <typename T, precision P>
315	GLM_FUNC_QUALIFIER tmat4x4<T, P>::tmat4x4
316	(
317		tmat4x3<T, P> const & m
318	)
319	{
320		this->value[0] = col_type(m[0], T(0));
321		this->value[1] = col_type(m[1], T(0));
322		this->value[2] = col_type(m[2], T(0));
323		this->value[3] = col_type(m[3], T(1));
324	}
325
326	//////////////////////////////////////////////////////////////
327	// Operators
328
329	template <typename T, precision P>
330	GLM_FUNC_QUALIFIER tmat4x4<T, P>& tmat4x4<T, P>::operator=
331	(
332		tmat4x4<T, P> const & m
333	)
334	{
335		//memcpy could be faster
336		//memcpy(&this->value, &m.value, 16 * sizeof(valType));
337		this->value[0] = m[0];
338		this->value[1] = m[1];
339		this->value[2] = m[2];
340		this->value[3] = m[3];
341		return *this;
342	}
343
344	template <typename T, precision P>
345	template <typename U>
346	GLM_FUNC_QUALIFIER tmat4x4<T, P>& tmat4x4<T, P>::operator=
347	(
348		tmat4x4<U, P> const & m
349	)
350	{
351		//memcpy could be faster
352		//memcpy(&this->value, &m.value, 16 * sizeof(valType));
353		this->value[0] = m[0];
354		this->value[1] = m[1];
355		this->value[2] = m[2];
356		this->value[3] = m[3];
357		return *this;
358	}
359
360	template <typename T, precision P>
361	template <typename U>
362	GLM_FUNC_QUALIFIER tmat4x4<T, P>& tmat4x4<T, P>::operator+= (U s)
363	{
364		this->value[0] += s;
365		this->value[1] += s;
366		this->value[2] += s;
367		this->value[3] += s;
368		return *this;
369	}
370
371	template <typename T, precision P>
372	template <typename U>
373	GLM_FUNC_QUALIFIER tmat4x4<T, P>& tmat4x4<T, P>::operator+= (tmat4x4<U, P> const & m)
374	{
375		this->value[0] += m[0];
376		this->value[1] += m[1];
377		this->value[2] += m[2];
378		this->value[3] += m[3];
379		return *this;
380	}
381
382	template <typename T, precision P>
383	template <typename U>
384	GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator-= (U s)
385	{
386		this->value[0] -= s;
387		this->value[1] -= s;
388		this->value[2] -= s;
389		this->value[3] -= s;
390		return *this;
391	}
392
393	template <typename T, precision P>
394	template <typename U>
395	GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator-= (tmat4x4<U, P> const & m)
396	{
397		this->value[0] -= m[0];
398		this->value[1] -= m[1];
399		this->value[2] -= m[2];
400		this->value[3] -= m[3];
401		return *this;
402	}
403
404	template <typename T, precision P>
405	template <typename U>
406	GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator*= (U s)
407	{
408		this->value[0] *= s;
409		this->value[1] *= s;
410		this->value[2] *= s;
411		this->value[3] *= s;
412		return *this;
413	}
414
415	template <typename T, precision P>
416	template <typename U>
417	GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator*= (tmat4x4<U, P> const & m)
418	{
419		return (*this = *this * m);
420	}
421
422	template <typename T, precision P>
423	template <typename U>
424	GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator/= (U s)
425	{
426		this->value[0] /= s;
427		this->value[1] /= s;
428		this->value[2] /= s;
429		this->value[3] /= s;
430		return *this;
431	}
432
433	template <typename T, precision P>
434	template <typename U>
435	GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator/= (tmat4x4<U, P> const & m)
436	{
437		return (*this = *this * detail::compute_inverse<detail::tmat4x4, T, P>::call(m));
438	}
439
440	template <typename T, precision P>
441	GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator++ ()
442	{
443		++this->value[0];
444		++this->value[1];
445		++this->value[2];
446		++this->value[3];
447		return *this;
448	}
449
450	template <typename T, precision P>
451	GLM_FUNC_QUALIFIER tmat4x4<T, P> & tmat4x4<T, P>::operator-- ()
452	{
453		--this->value[0];
454		--this->value[1];
455		--this->value[2];
456		--this->value[3];
457		return *this;
458	}
459
460	template <typename T, precision P>
461	GLM_FUNC_QUALIFIER tmat4x4<T, P> tmat4x4<T, P>::operator++(int)
462	{
463		tmat4x4<T, P> Result(*this);
464		++*this;
465		return Result;
466	}
467
468	template <typename T, precision P>
469	GLM_FUNC_QUALIFIER tmat4x4<T, P> tmat4x4<T, P>::operator--(int)
470	{
471		tmat4x4<T, P> Result(*this);
472		--*this;
473		return Result;
474	}
475
476	template <typename T, precision P>
477	struct compute_inverse<detail::tmat4x4, T, P>
478	{
479		static detail::tmat4x4<T, P> call(detail::tmat4x4<T, P> const & m)
480		{
481			T Coef00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
482			T Coef02 = m[1][2] * m[3][3] - m[3][2] * m[1][3];
483			T Coef03 = m[1][2] * m[2][3] - m[2][2] * m[1][3];
484
485			T Coef04 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
486			T Coef06 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
487			T Coef07 = m[1][1] * m[2][3] - m[2][1] * m[1][3];
488
489			T Coef08 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
490			T Coef10 = m[1][1] * m[3][2] - m[3][1] * m[1][2];
491			T Coef11 = m[1][1] * m[2][2] - m[2][1] * m[1][2];
492
493			T Coef12 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
494			T Coef14 = m[1][0] * m[3][3] - m[3][0] * m[1][3];
495			T Coef15 = m[1][0] * m[2][3] - m[2][0] * m[1][3];
496
497			T Coef16 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
498			T Coef18 = m[1][0] * m[3][2] - m[3][0] * m[1][2];
499			T Coef19 = m[1][0] * m[2][2] - m[2][0] * m[1][2];
500
501			T Coef20 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
502			T Coef22 = m[1][0] * m[3][1] - m[3][0] * m[1][1];
503			T Coef23 = m[1][0] * m[2][1] - m[2][0] * m[1][1];
504
505			detail::tvec4<T, P> Fac0(Coef00, Coef00, Coef02, Coef03);
506			detail::tvec4<T, P> Fac1(Coef04, Coef04, Coef06, Coef07);
507			detail::tvec4<T, P> Fac2(Coef08, Coef08, Coef10, Coef11);
508			detail::tvec4<T, P> Fac3(Coef12, Coef12, Coef14, Coef15);
509			detail::tvec4<T, P> Fac4(Coef16, Coef16, Coef18, Coef19);
510			detail::tvec4<T, P> Fac5(Coef20, Coef20, Coef22, Coef23);
511
512			detail::tvec4<T, P> Vec0(m[1][0], m[0][0], m[0][0], m[0][0]);
513			detail::tvec4<T, P> Vec1(m[1][1], m[0][1], m[0][1], m[0][1]);
514			detail::tvec4<T, P> Vec2(m[1][2], m[0][2], m[0][2], m[0][2]);
515			detail::tvec4<T, P> Vec3(m[1][3], m[0][3], m[0][3], m[0][3]);
516
517			detail::tvec4<T, P> Inv0(Vec1 * Fac0 - Vec2 * Fac1 + Vec3 * Fac2);
518			detail::tvec4<T, P> Inv1(Vec0 * Fac0 - Vec2 * Fac3 + Vec3 * Fac4);
519			detail::tvec4<T, P> Inv2(Vec0 * Fac1 - Vec1 * Fac3 + Vec3 * Fac5);
520			detail::tvec4<T, P> Inv3(Vec0 * Fac2 - Vec1 * Fac4 + Vec2 * Fac5);
521
522			detail::tvec4<T, P> SignA(+1, -1, +1, -1);
523			detail::tvec4<T, P> SignB(-1, +1, -1, +1);
524			detail::tmat4x4<T, P> Inverse(Inv0 * SignA, Inv1 * SignB, Inv2 * SignA, Inv3 * SignB);
525
526			detail::tvec4<T, P> Row0(Inverse[0][0], Inverse[1][0], Inverse[2][0], Inverse[3][0]);
527
528			detail::tvec4<T, P> Dot0(m[0] * Row0);
529			T Dot1 = (Dot0.x + Dot0.y) + (Dot0.z + Dot0.w);
530
531			T OneOverDeterminant = static_cast<T>(1) / Dot1;
532
533			return Inverse * OneOverDeterminant;
534		}
535	};
536
537	// Binary operators
538	template <typename T, precision P>
539	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator+
540	(
541		tmat4x4<T, P> const & m,
542		T const & s
543	)
544	{
545		return tmat4x4<T, P>(
546			m[0] + s,
547			m[1] + s,
548			m[2] + s,
549			m[3] + s);
550	}
551
552	template <typename T, precision P>
553	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator+
554	(
555		T const & s,
556		tmat4x4<T, P> const & m
557	)
558	{
559		return tmat4x4<T, P>(
560			m[0] + s,
561			m[1] + s,
562			m[2] + s,
563			m[3] + s);
564	}
565
566	template <typename T, precision P>
567	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator+
568	(
569		tmat4x4<T, P> const & m1,
570		tmat4x4<T, P> const & m2
571	)
572	{
573		return tmat4x4<T, P>(
574			m1[0] + m2[0],
575			m1[1] + m2[1],
576			m1[2] + m2[2],
577			m1[3] + m2[3]);
578	}
579
580	template <typename T, precision P>
581	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator-
582	(
583		tmat4x4<T, P> const & m,
584		T const & s
585	)
586	{
587		return tmat4x4<T, P>(
588			m[0] - s,
589			m[1] - s,
590			m[2] - s,
591			m[3] - s);
592	}
593
594	template <typename T, precision P>
595	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator-
596	(
597		T const & s,
598		tmat4x4<T, P> const & m
599	)
600	{
601		return tmat4x4<T, P>(
602			s - m[0],
603			s - m[1],
604			s - m[2],
605			s - m[3]);
606	}
607
608	template <typename T, precision P>
609	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator-
610	(
611		tmat4x4<T, P> const & m1,
612		tmat4x4<T, P> const & m2
613	)
614	{
615		return tmat4x4<T, P>(
616			m1[0] - m2[0],
617			m1[1] - m2[1],
618			m1[2] - m2[2],
619			m1[3] - m2[3]);
620	}
621
622	template <typename T, precision P>
623	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator*
624	(
625		tmat4x4<T, P> const & m,
626		T const  & s
627	)
628	{
629		return tmat4x4<T, P>(
630			m[0] * s,
631			m[1] * s,
632			m[2] * s,
633			m[3] * s);
634	}
635
636	template <typename T, precision P>
637	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator*
638	(
639		T const & s,
640		tmat4x4<T, P> const & m
641	)
642	{
643		return tmat4x4<T, P>(
644			m[0] * s,
645			m[1] * s,
646			m[2] * s,
647			m[3] * s);
648	}
649
650	template <typename T, precision P>
651	GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::col_type operator*
652	(
653		tmat4x4<T, P> const & m,
654		typename tmat4x4<T, P>::row_type const & v
655	)
656	{
657/*
658		__m128 v0 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(0, 0, 0, 0));
659		__m128 v1 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(1, 1, 1, 1));
660		__m128 v2 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(2, 2, 2, 2));
661		__m128 v3 = _mm_shuffle_ps(v.data, v.data, _MM_SHUFFLE(3, 3, 3, 3));
662
663		__m128 m0 = _mm_mul_ps(m[0].data, v0);
664		__m128 m1 = _mm_mul_ps(m[1].data, v1);
665		__m128 a0 = _mm_add_ps(m0, m1);
666
667		__m128 m2 = _mm_mul_ps(m[2].data, v2);
668		__m128 m3 = _mm_mul_ps(m[3].data, v3);
669		__m128 a1 = _mm_add_ps(m2, m3);
670
671		__m128 a2 = _mm_add_ps(a0, a1);
672
673		return typename tmat4x4<T, P>::col_type(a2);
674*/
675
676		typename tmat4x4<T, P>::col_type const Mov0(v[0]);
677		typename tmat4x4<T, P>::col_type const Mov1(v[1]);
678		typename tmat4x4<T, P>::col_type const Mul0 = m[0] * Mov0;
679		typename tmat4x4<T, P>::col_type const Mul1 = m[1] * Mov1;
680		typename tmat4x4<T, P>::col_type const Add0 = Mul0 + Mul1;
681		typename tmat4x4<T, P>::col_type const Mov2(v[2]);
682		typename tmat4x4<T, P>::col_type const Mov3(v[3]);
683		typename tmat4x4<T, P>::col_type const Mul2 = m[2] * Mov2;
684		typename tmat4x4<T, P>::col_type const Mul3 = m[3] * Mov3;
685		typename tmat4x4<T, P>::col_type const Add1 = Mul2 + Mul3;
686		typename tmat4x4<T, P>::col_type const Add2 = Add0 + Add1;
687		return Add2;
688
689/*
690		return typename tmat4x4<T, P>::col_type(
691			m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0] * v[3],
692			m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1] * v[3],
693			m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2] * v[3],
694			m[0][3] * v[0] + m[1][3] * v[1] + m[2][3] * v[2] + m[3][3] * v[3]);
695*/
696	}
697
698	template <typename T, precision P>
699	GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::row_type operator*
700	(
701		typename tmat4x4<T, P>::col_type const & v,
702		tmat4x4<T, P> const & m
703	)
704	{
705		return typename tmat4x4<T, P>::row_type(
706			m[0][0] * v[0] + m[0][1] * v[1] + m[0][2] * v[2] + m[0][3] * v[3],
707			m[1][0] * v[0] + m[1][1] * v[1] + m[1][2] * v[2] + m[1][3] * v[3],
708			m[2][0] * v[0] + m[2][1] * v[1] + m[2][2] * v[2] + m[2][3] * v[3],
709			m[3][0] * v[0] + m[3][1] * v[1] + m[3][2] * v[2] + m[3][3] * v[3]);
710	}
711
712	template <typename T, precision P>
713	GLM_FUNC_QUALIFIER tmat2x4<T, P> operator*
714	(
715		tmat4x4<T, P> const & m1,
716		tmat2x4<T, P> const & m2
717	)
718	{
719		return tmat2x4<T, P>(
720			m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3],
721			m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3],
722			m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2] + m1[3][2] * m2[0][3],
723			m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1] + m1[2][3] * m2[0][2] + m1[3][3] * m2[0][3],
724			m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3],
725			m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3],
726			m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2] + m1[3][2] * m2[1][3],
727			m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1] + m1[2][3] * m2[1][2] + m1[3][3] * m2[1][3]);
728	}
729
730	template <typename T, precision P>
731	GLM_FUNC_QUALIFIER tmat3x4<T, P> operator*
732	(
733		tmat4x4<T, P> const & m1,
734		tmat3x4<T, P> const & m2
735	)
736	{
737		return tmat3x4<T, P>(
738			m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1] + m1[2][0] * m2[0][2] + m1[3][0] * m2[0][3],
739			m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1] + m1[2][1] * m2[0][2] + m1[3][1] * m2[0][3],
740			m1[0][2] * m2[0][0] + m1[1][2] * m2[0][1] + m1[2][2] * m2[0][2] + m1[3][2] * m2[0][3],
741			m1[0][3] * m2[0][0] + m1[1][3] * m2[0][1] + m1[2][3] * m2[0][2] + m1[3][3] * m2[0][3],
742			m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1] + m1[2][0] * m2[1][2] + m1[3][0] * m2[1][3],
743			m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1] + m1[2][1] * m2[1][2] + m1[3][1] * m2[1][3],
744			m1[0][2] * m2[1][0] + m1[1][2] * m2[1][1] + m1[2][2] * m2[1][2] + m1[3][2] * m2[1][3],
745			m1[0][3] * m2[1][0] + m1[1][3] * m2[1][1] + m1[2][3] * m2[1][2] + m1[3][3] * m2[1][3],
746			m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1] + m1[2][0] * m2[2][2] + m1[3][0] * m2[2][3],
747			m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1] + m1[2][1] * m2[2][2] + m1[3][1] * m2[2][3],
748			m1[0][2] * m2[2][0] + m1[1][2] * m2[2][1] + m1[2][2] * m2[2][2] + m1[3][2] * m2[2][3],
749			m1[0][3] * m2[2][0] + m1[1][3] * m2[2][1] + m1[2][3] * m2[2][2] + m1[3][3] * m2[2][3]);
750	}
751
752	template <typename T, precision P>
753	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator*
754	(
755		tmat4x4<T, P> const & m1,
756		tmat4x4<T, P> const & m2
757	)
758	{
759		typename tmat4x4<T, P>::col_type const SrcA0 = m1[0];
760		typename tmat4x4<T, P>::col_type const SrcA1 = m1[1];
761		typename tmat4x4<T, P>::col_type const SrcA2 = m1[2];
762		typename tmat4x4<T, P>::col_type const SrcA3 = m1[3];
763
764		typename tmat4x4<T, P>::col_type const SrcB0 = m2[0];
765		typename tmat4x4<T, P>::col_type const SrcB1 = m2[1];
766		typename tmat4x4<T, P>::col_type const SrcB2 = m2[2];
767		typename tmat4x4<T, P>::col_type const SrcB3 = m2[3];
768
769		tmat4x4<T, P> Result(tmat4x4<T, P>::_null);
770		Result[0] = SrcA0 * SrcB0[0] + SrcA1 * SrcB0[1] + SrcA2 * SrcB0[2] + SrcA3 * SrcB0[3];
771		Result[1] = SrcA0 * SrcB1[0] + SrcA1 * SrcB1[1] + SrcA2 * SrcB1[2] + SrcA3 * SrcB1[3];
772		Result[2] = SrcA0 * SrcB2[0] + SrcA1 * SrcB2[1] + SrcA2 * SrcB2[2] + SrcA3 * SrcB2[3];
773		Result[3] = SrcA0 * SrcB3[0] + SrcA1 * SrcB3[1] + SrcA2 * SrcB3[2] + SrcA3 * SrcB3[3];
774		return Result;
775	}
776
777	template <typename T, precision P>
778	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator/
779	(
780		tmat4x4<T, P> const & m,
781		T const & s
782	)
783	{
784		return tmat4x4<T, P>(
785			m[0] / s,
786			m[1] / s,
787			m[2] / s,
788			m[3] / s);
789	}
790
791	template <typename T, precision P>
792	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator/
793	(
794		T const & s,
795		tmat4x4<T, P> const & m
796	)
797	{
798		return tmat4x4<T, P>(
799			s / m[0],
800			s / m[1],
801			s / m[2],
802			s / m[3]);
803	}
804
805	template <typename T, precision P>
806	GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::col_type operator/
807	(
808		tmat4x4<T, P> const & m,
809		typename tmat4x4<T, P>::row_type const & v
810	)
811	{
812		return detail::compute_inverse<detail::tmat4x4, T, P>::call(m) * v;
813	}
814
815	template <typename T, precision P>
816	GLM_FUNC_QUALIFIER typename tmat4x4<T, P>::row_type operator/
817	(
818		typename tmat4x4<T, P>::col_type const & v,
819		tmat4x4<T, P> const & m
820	)
821	{
822		return v * detail::compute_inverse<detail::tmat4x4, T, P>::call(m);
823	}
824
825	template <typename T, precision P>
826	GLM_FUNC_QUALIFIER tmat4x4<T, P> operator/
827	(
828		tmat4x4<T, P> const & m1,
829		tmat4x4<T, P> const & m2
830	)
831	{
832		tmat4x4<T, P> m1_copy(m1);
833		return m1_copy /= m2;
834	}
835
836	// Unary constant operators
837	template <typename T, precision P>
838	GLM_FUNC_QUALIFIER tmat4x4<T, P> const operator-
839	(
840		tmat4x4<T, P> const & m
841	)
842	{
843		return tmat4x4<T, P>(
844			-m[0],
845			-m[1],
846			-m[2],
847			-m[3]);
848	}
849
850	template <typename T, precision P>
851	GLM_FUNC_QUALIFIER tmat4x4<T, P> const operator++
852	(
853		tmat4x4<T, P> const & m,
854		int
855	)
856	{
857		return tmat4x4<T, P>(
858			m[0] + static_cast<T>(1),
859			m[1] + static_cast<T>(1),
860			m[2] + static_cast<T>(1),
861			m[3] + static_cast<T>(1));
862	}
863
864	template <typename T, precision P>
865	GLM_FUNC_QUALIFIER tmat4x4<T, P> const operator--
866	(
867		tmat4x4<T, P> const & m,
868		int
869	)
870	{
871		return tmat4x4<T, P>(
872			m[0] - static_cast<T>(1),
873			m[1] - static_cast<T>(1),
874			m[2] - static_cast<T>(1),
875			m[3] - static_cast<T>(1));
876	}
877
878	//////////////////////////////////////
879	// Boolean operators
880
881	template <typename T, precision P>
882	GLM_FUNC_QUALIFIER bool operator==
883	(
884		tmat4x4<T, P> const & m1,
885		tmat4x4<T, P> const & m2
886	)
887	{
888		return (m1[0] == m2[0]) && (m1[1] == m2[1]) && (m1[2] == m2[2]) && (m1[3] == m2[3]);
889	}
890
891	template <typename T, precision P>
892	GLM_FUNC_QUALIFIER bool operator!=
893	(
894		tmat4x4<T, P> const & m1,
895		tmat4x4<T, P> const & m2
896	)
897	{
898		return (m1[0] != m2[0]) || (m1[1] != m2[1]) || (m1[2] != m2[2]) || (m1[3] != m2[3]);
899	}
900
901} //namespace detail
902} //namespace glm
903