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_mat2x2.inl
25/// @date 2005-01-16 / 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 tmat2x2<T, P>::length() const
34	{
35		return 2;
36	}
37
38	//////////////////////////////////////
39	// Accesses
40
41	template <typename T, precision P>
42	GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::col_type &
43	tmat2x2<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 tmat2x2<T, P>::col_type const &
54	tmat2x2<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 tmat2x2<T, P>::tmat2x2()
68	{
69		this->value[0] = col_type(1, 0);
70		this->value[1] = col_type(0, 1);
71	}
72
73	template <typename T, precision P>
74	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2
75	(
76		tmat2x2<T, P> const & m
77	)
78	{
79		this->value[0] = m.value[0];
80		this->value[1] = m.value[1];
81	}
82
83	template <typename T, precision P>
84	template <precision Q>
85	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2(
86		tmat2x2<T, Q> const & m)
87	{
88		this->value[0] = m.value[0];
89		this->value[1] = m.value[1];
90	}
91
92	template <typename T, precision P>
93	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2
94	(
95		ctor
96	)
97	{}
98
99	template <typename T, precision P>
100	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2
101	(
102		T const & s
103	)
104	{
105		value_type const Zero(0);
106		this->value[0] = col_type(s, Zero);
107		this->value[1] = col_type(Zero, s);
108	}
109
110	template <typename T, precision P>
111	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2
112	(
113		T const & x0, T const & y0,
114		T const & x1, T const & y1
115	)
116	{
117		this->value[0] = col_type(x0, y0);
118		this->value[1] = col_type(x1, y1);
119	}
120
121	template <typename T, precision P>
122	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2
123	(
124		col_type const & v0,
125		col_type const & v1
126	)
127	{
128		this->value[0] = v0;
129		this->value[1] = v1;
130	}
131
132	//////////////////////////////////////
133	// Conversion constructors
134	template <typename T, precision P>
135	template <typename X1, typename Y1, typename X2, typename Y2>
136	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2
137	(
138		X1 const & x1, Y1 const & y1,
139		X2 const & x2, Y2 const & y2
140	)
141	{
142		this->value[0] = col_type(static_cast<T>(x1), value_type(y1));
143		this->value[1] = col_type(static_cast<T>(x2), value_type(y2));
144	}
145
146	template <typename T, precision P>
147	template <typename V1, typename V2>
148	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2
149	(
150		tvec2<V1, P> const & v1,
151		tvec2<V2, P> const & v2
152	)
153	{
154		this->value[0] = col_type(v1);
155		this->value[1] = col_type(v2);
156	}
157
158	//////////////////////////////////////////////////////////////
159	// mat2x2 matrix conversions
160
161	template <typename T, precision P>
162	template <typename U, precision Q>
163	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2
164	(
165		tmat2x2<U, Q> const & m
166	)
167	{
168		this->value[0] = col_type(m[0]);
169		this->value[1] = col_type(m[1]);
170	}
171
172	template <typename T, precision P>
173	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2
174	(
175		tmat3x3<T, P> const & m
176	)
177	{
178		this->value[0] = col_type(m[0]);
179		this->value[1] = col_type(m[1]);
180	}
181
182	template <typename T, precision P>
183	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2
184	(
185		tmat4x4<T, P> const & m
186	)
187	{
188		this->value[0] = col_type(m[0]);
189		this->value[1] = col_type(m[1]);
190	}
191
192	template <typename T, precision P>
193	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2
194	(
195		tmat2x3<T, P> const & m
196	)
197	{
198		this->value[0] = col_type(m[0]);
199		this->value[1] = col_type(m[1]);
200	}
201
202	template <typename T, precision P>
203	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2
204	(
205		tmat3x2<T, P> const & m
206	)
207	{
208		this->value[0] = m[0];
209		this->value[1] = m[1];
210	}
211
212	template <typename T, precision P>
213	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2
214	(
215		tmat2x4<T, P> const & m
216	)
217	{
218		this->value[0] = col_type(m[0]);
219		this->value[1] = col_type(m[1]);
220	}
221
222	template <typename T, precision P>
223	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2
224	(
225		tmat4x2<T, P> const & m
226	)
227	{
228		this->value[0] = m[0];
229		this->value[1] = m[1];
230	}
231
232	template <typename T, precision P>
233	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2
234	(
235		tmat3x4<T, P> const & m
236	)
237	{
238		this->value[0] = col_type(m[0]);
239		this->value[1] = col_type(m[1]);
240	}
241
242	template <typename T, precision P>
243	GLM_FUNC_QUALIFIER tmat2x2<T, P>::tmat2x2
244	(
245		tmat4x3<T, P> const & m
246	)
247	{
248		this->value[0] = col_type(m[0]);
249		this->value[1] = col_type(m[1]);
250	}
251
252	//////////////////////////////////////////////////////////////
253	// mat2x2 operators
254
255	// This function shouldn't required but it seems that VC7.1 have an optimisation bug if this operator wasn't declared
256	template <typename T, precision P>
257	GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator= (tmat2x2<T, P> const & m)
258	{
259		this->value[0] = m[0];
260		this->value[1] = m[1];
261		return *this;
262	}
263
264	template <typename T, precision P>
265	template <typename U>
266	GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator= (tmat2x2<U, P> const & m)
267	{
268		this->value[0] = m[0];
269		this->value[1] = m[1];
270		return *this;
271	}
272
273	template <typename T, precision P>
274	template <typename U>
275	GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator+= (U s)
276	{
277		this->value[0] += s;
278		this->value[1] += s;
279		return *this;
280	}
281
282	template <typename T, precision P>
283	template <typename U>
284	GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator+= (tmat2x2<U, P> const & m)
285	{
286		this->value[0] += m[0];
287		this->value[1] += m[1];
288		return *this;
289	}
290
291	template <typename T, precision P>
292	template <typename U>
293	GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator-= (U s)
294	{
295		this->value[0] -= s;
296		this->value[1] -= s;
297		return *this;
298	}
299
300	template <typename T, precision P>
301	template <typename U>
302	GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator-= (tmat2x2<U, P> const & m)
303	{
304		this->value[0] -= m[0];
305		this->value[1] -= m[1];
306		return *this;
307	}
308
309	template <typename T, precision P>
310	template <typename U>
311	GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator*= (U s)
312	{
313		this->value[0] *= s;
314		this->value[1] *= s;
315		return *this;
316	}
317
318	template <typename T, precision P>
319	template <typename U>
320	GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator*= (tmat2x2<U, P> const & m)
321	{
322		return (*this = *this * m);
323	}
324
325	template <typename T, precision P>
326	template <typename U>
327	GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator/= (U s)
328	{
329		this->value[0] /= s;
330		this->value[1] /= s;
331		return *this;
332	}
333
334	template <typename T, precision P>
335	template <typename U>
336	GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator/= (tmat2x2<U, P> const & m)
337	{
338		return (*this = *this * detail::compute_inverse<detail::tmat2x2, T, P>::call(m));
339	}
340
341	template <typename T, precision P>
342	GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator++()
343	{
344		++this->value[0];
345		++this->value[1];
346		return *this;
347	}
348
349	template <typename T, precision P>
350	GLM_FUNC_QUALIFIER tmat2x2<T, P>& tmat2x2<T, P>::operator--()
351	{
352		--this->value[0];
353		--this->value[1];
354		return *this;
355	}
356
357	template <typename T, precision P>
358	GLM_FUNC_QUALIFIER tmat2x2<T, P> tmat2x2<T, P>::operator++(int)
359	{
360		tmat2x2<T, P> Result(*this);
361		++*this;
362		return Result;
363	}
364
365	template <typename T, precision P>
366	GLM_FUNC_QUALIFIER tmat2x2<T, P> tmat2x2<T, P>::operator--(int)
367	{
368		tmat2x2<T, P> Result(*this);
369		--*this;
370		return Result;
371	}
372
373	template <typename T, precision P>
374	struct compute_inverse<detail::tmat2x2, T, P>
375	{
376		GLM_FUNC_QUALIFIER static detail::tmat2x2<T, P> call(detail::tmat2x2<T, P> const & m)
377		{
378			T OneOverDeterminant = static_cast<T>(1) / (
379				+ m[0][0] * m[1][1]
380				- m[1][0] * m[0][1]);
381
382			detail::tmat2x2<T, P> Inverse(
383				+ m[1][1] * OneOverDeterminant,
384				- m[0][1] * OneOverDeterminant,
385				- m[1][0] * OneOverDeterminant,
386				+ m[0][0] * OneOverDeterminant);
387
388			return Inverse;
389		}
390	};
391
392	//////////////////////////////////////////////////////////////
393	// Binary operators
394
395	template <typename T, precision P>
396	GLM_FUNC_QUALIFIER tmat2x2<T, P> operator+
397	(
398		tmat2x2<T, P> const & m,
399		T const & s
400	)
401	{
402		return tmat2x2<T, P>(
403			m[0] + s,
404			m[1] + s);
405	}
406
407	template <typename T, precision P>
408	GLM_FUNC_QUALIFIER tmat2x2<T, P> operator+
409	(
410		T const & s,
411		tmat2x2<T, P> const & m
412	)
413	{
414		return tmat2x2<T, P>(
415			m[0] + s,
416			m[1] + s);
417	}
418
419	template <typename T, precision P>
420	GLM_FUNC_QUALIFIER tmat2x2<T, P> operator+
421	(
422		tmat2x2<T, P> const & m1,
423		tmat2x2<T, P> const & m2
424	)
425	{
426		return tmat2x2<T, P>(
427			m1[0] + m2[0],
428			m1[1] + m2[1]);
429	}
430
431	template <typename T, precision P>
432	GLM_FUNC_QUALIFIER tmat2x2<T, P> operator-
433	(
434		tmat2x2<T, P> const & m,
435		T const & s
436	)
437	{
438		return tmat2x2<T, P>(
439			m[0] - s,
440			m[1] - s);
441	}
442
443	template <typename T, precision P>
444	GLM_FUNC_QUALIFIER tmat2x2<T, P> operator-
445	(
446		T const & s,
447		tmat2x2<T, P> const & m
448	)
449	{
450		return tmat2x2<T, P>(
451			s - m[0],
452			s - m[1]);
453	}
454
455	template <typename T, precision P>
456	GLM_FUNC_QUALIFIER tmat2x2<T, P> operator-
457	(
458		tmat2x2<T, P> const & m1,
459		tmat2x2<T, P> const & m2
460	)
461	{
462		return tmat2x2<T, P>(
463			m1[0] - m2[0],
464			m1[1] - m2[1]);
465	}
466
467	template <typename T, precision P>
468	GLM_FUNC_QUALIFIER tmat2x2<T, P> operator*
469	(
470		tmat2x2<T, P> const & m,
471		T const & s
472	)
473	{
474		return tmat2x2<T, P>(
475			m[0] * s,
476			m[1] * s);
477	}
478
479	template <typename T, precision P>
480	GLM_FUNC_QUALIFIER tmat2x2<T, P> operator*
481	(
482		T const & s,
483		tmat2x2<T, P> const & m
484	)
485	{
486		return tmat2x2<T, P>(
487			m[0] * s,
488			m[1] * s);
489	}
490
491	template <typename T, precision P>
492	GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::col_type operator*
493	(
494		tmat2x2<T, P> const & m,
495		typename tmat2x2<T, P>::row_type const & v
496	)
497	{
498		return detail::tvec2<T, P>(
499			m[0][0] * v.x + m[1][0] * v.y,
500			m[0][1] * v.x + m[1][1] * v.y);
501	}
502
503	template <typename T, precision P>
504	GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::row_type operator*
505	(
506		typename tmat2x2<T, P>::col_type const & v,
507		tmat2x2<T, P> const & m
508	)
509	{
510		return detail::tvec2<T, P>(
511			v.x * m[0][0] + v.y * m[0][1],
512			v.x * m[1][0] + v.y * m[1][1]);
513	}
514
515	template <typename T, precision P>
516	GLM_FUNC_QUALIFIER tmat2x2<T, P> operator*
517	(
518		tmat2x2<T, P> const & m1,
519		tmat2x2<T, P> const & m2
520	)
521	{
522		return tmat2x2<T, P>(
523			m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1],
524			m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1],
525			m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1],
526			m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1]);
527	}
528
529	template <typename T, precision P>
530	GLM_FUNC_QUALIFIER tmat3x2<T, P> operator*
531	(
532		tmat2x2<T, P> const & m1,
533		tmat3x2<T, P> const & m2
534	)
535	{
536		return tmat3x2<T, P>(
537			m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1],
538			m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1],
539			m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1],
540			m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1],
541			m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1],
542			m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1]);
543	}
544
545	template <typename T, precision P>
546	GLM_FUNC_QUALIFIER tmat4x2<T, P> operator*
547	(
548		tmat2x2<T, P> const & m1,
549		tmat4x2<T, P> const & m2
550	)
551	{
552		return tmat4x2<T, P>(
553			m1[0][0] * m2[0][0] + m1[1][0] * m2[0][1],
554			m1[0][1] * m2[0][0] + m1[1][1] * m2[0][1],
555			m1[0][0] * m2[1][0] + m1[1][0] * m2[1][1],
556			m1[0][1] * m2[1][0] + m1[1][1] * m2[1][1],
557			m1[0][0] * m2[2][0] + m1[1][0] * m2[2][1],
558			m1[0][1] * m2[2][0] + m1[1][1] * m2[2][1],
559			m1[0][0] * m2[3][0] + m1[1][0] * m2[3][1],
560			m1[0][1] * m2[3][0] + m1[1][1] * m2[3][1]);
561	}
562
563	template <typename T, precision P>
564	GLM_FUNC_QUALIFIER tmat2x2<T, P> operator/
565	(
566		tmat2x2<T, P> const & m,
567		T const & s
568	)
569	{
570		return tmat2x2<T, P>(
571			m[0] / s,
572			m[1] / s);
573	}
574
575	template <typename T, precision P>
576	GLM_FUNC_QUALIFIER tmat2x2<T, P> operator/
577	(
578		T const & s,
579		tmat2x2<T, P> const & m
580	)
581	{
582		return tmat2x2<T, P>(
583			s / m[0],
584			s / m[1]);
585	}
586
587	template <typename T, precision P>
588	GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::col_type operator/
589	(
590		tmat2x2<T, P> const & m,
591		typename tmat2x2<T, P>::row_type & v
592	)
593	{
594		return detail::compute_inverse<detail::tmat2x2, T, P>::call(m) * v;
595	}
596
597	template <typename T, precision P>
598	GLM_FUNC_QUALIFIER typename tmat2x2<T, P>::row_type operator/
599	(
600		typename tmat2x2<T, P>::col_type const & v,
601		tmat2x2<T, P> const & m
602	)
603	{
604		return v * detail::compute_inverse<detail::tmat2x2, T, P>::call(m);
605	}
606
607	template <typename T, precision P>
608	GLM_FUNC_QUALIFIER tmat2x2<T, P> operator/
609	(
610		tmat2x2<T, P> const & m1,
611		tmat2x2<T, P> const & m2
612	)
613	{
614		tmat2x2<T, P> m1_copy(m1);
615		return m1_copy /= m2;
616	}
617
618	// Unary constant operators
619	template <typename T, precision P>
620	GLM_FUNC_QUALIFIER tmat2x2<T, P> const operator-
621	(
622		tmat2x2<T, P> const & m
623	)
624	{
625		return tmat2x2<T, P>(
626			-m[0],
627			-m[1]);
628	}
629
630	//////////////////////////////////////
631	// Boolean operators
632
633	template <typename T, precision P>
634	GLM_FUNC_QUALIFIER bool operator==
635	(
636		tmat2x2<T, P> const & m1,
637		tmat2x2<T, P> const & m2
638	)
639	{
640		return (m1[0] == m2[0]) && (m1[1] == m2[1]);
641	}
642
643	template <typename T, precision P>
644	GLM_FUNC_QUALIFIER bool operator!=
645	(
646		tmat2x2<T, P> const & m1,
647		tmat2x2<T, P> const & m2
648	)
649	{
650		return (m1[0] != m2[0]) || (m1[1] != m2[1]);
651	}
652
653} //namespace detail
654} //namespace glm
655