1 module matrix_2d;
2 
3 import Math = math;
4 import MemUtil = mem_util;
5 
6 import matrix_3d;
7 import matrix_3x2d;
8 
9 import vector_2d;
10 
11 
12 /*
13  * The MIT License
14  *
15  * Copyright (c) 2020-2021 JOML
16  %%$%# translated by jordan4ibanez
17  *
18  * Permission is hereby granted, free of charge, to any person obtaining a copy
19  * of this software and associated documentation files (the "Software"), to deal
20  * in the Software without restriction, including without limitation the rights
21  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22  * copies of the Software, and to permit persons to whom the Software is
23  * furnished to do so, subject to the following conditions:
24  *
25  * The above copyright notice and this permission notice shall be included in
26  * all copies or substantial portions of the Software.
27  *
28  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
34  * THE SOFTWARE.
35  */
36 
37 
38 /**
39  * Contains the definition of a 2x2 matrix of doubles, and associated functions to transform
40  * it. The matrix is column-major to match OpenGL's interpretation, and it looks like this:
41  * <p>
42  *      m00  m10<br>
43  *      m01  m11<br>
44  *
45  * @author Joseph Burton
46  */
47 public struct Matrix2d {
48 
49     // Defaults to identity
50     double m00 = 1.0;
51     double m01 = 0.0;
52     double m10 = 0.0;
53     double m11 = 1.0;
54 
55 
56     /**
57      * Create a new {@link Matrix2d} and make it a copy of the given matrix.
58      *
59      * @param mat
60      *          the {@link Matrix2d} to copy the values from
61      */
62     this(Matrix2d mat) {
63         setMatrix2d(mat);
64     }
65 
66 
67     /**
68      * Create a new {@link Matrix2d} and make it a copy of the upper left 2x2 of the given {@link Matrix3d}.
69      *
70      * @param mat
71      *          the {@link Matrix3d} to copy the values from
72      */
73     this(Matrix3d mat) {
74         setMatrix3d(mat);
75     }
76 
77 
78     /**
79      * Create a new 2x2 matrix using the supplied double values. The order of the parameter is column-major,
80      * so the first two parameters specify the two elements of the first column.
81      *
82      * @param m00
83      *          the value of m00
84      * @param m01
85      *          the value of m01
86      * @param m10
87      *          the value of m10
88      * @param m11
89      *          the value of m11
90      */
91     this(double m00, double m01,
92                     double m10, double m11) {
93         this.m00 = m00;
94         this.m01 = m01;
95         this.m10 = m10;
96         this.m11 = m11;
97     }
98 
99     /**
100      * Create a new {@link Matrix2d} and initialize its two columns using the supplied vectors.
101      *
102      * @param col0
103      *          the first column
104      * @param col1
105      *          the second column
106      */
107     this(Vector2d col0, Vector2d col1) {
108         m00 = col0.x;
109         m01 = col0.y;
110         m10 = col1.x;
111         m11 = col1.y;
112     }
113 
114     /**
115      * Set the value of the matrix element at column 0 and row 0.
116      *
117      * @param m00
118      *          the new value
119      * @return this
120      */
121     ref public Matrix2d setm00(double m00) return {
122         this.m00 = m00;
123         return this;
124     }
125     /**
126      * Set the value of the matrix element at column 0 and row 1.
127      *
128      * @param m01
129      *          the new value
130      * @return this
131      */
132     ref public Matrix2d setm01(double m01) return {
133         this.m01 = m01;
134         return this;
135     }
136     /**
137      * Set the value of the matrix element at column 1 and row 0.
138      *
139      * @param m10
140      *          the new value
141      * @return this
142      */
143     ref public Matrix2d setm10(double m10) return {
144         this.m10 = m10;
145         return this;
146     }
147     /**
148      * Set the value of the matrix element at column 1 and row 1.
149      *
150      * @param m11
151      *          the new value
152      * @return this
153      */
154     ref public Matrix2d setm11(double m11) return {
155         this.m11 = m11;
156         return this;
157     }
158 
159     /**
160      * Set the value of the matrix element at column 0 and row 0.
161      *
162      * @param m00
163      *          the new value
164      * @return this
165      */
166     ref Matrix2d _m00(double m00) return {
167         this.m00 = m00;
168         return this;
169     }
170     /**
171      * Set the value of the matrix element at column 0 and row 1.
172      *
173      * @param m01
174      *          the new value
175      * @return this
176      */
177     ref Matrix2d _m01(double m01) return {
178         this.m01 = m01;
179         return this;
180     }
181     /**
182      * Set the value of the matrix element at column 1 and row 0.
183      *
184      * @param m10
185      *          the new value
186      * @return this
187      */
188     ref Matrix2d _m10(double m10) return {
189         this.m10 = m10;
190         return this;
191     }
192     /**
193      * Set the value of the matrix element at column 1 and row 1.
194      *
195      * @param m11
196      *          the new value
197      * @return this
198      */
199     ref Matrix2d _m11(double m11) return {
200         this.m11 = m11;
201         return this;
202     }
203 
204     /**
205      * Set the elements of this matrix to the ones in <code>m</code>.
206      *
207      * @param m
208      *          the matrix to copy the elements from
209      * @return this
210      */
211     ref public Matrix2d set(Matrix2d m) return {
212         setMatrix2d(m);
213         return this;
214     }
215     private void setMatrix2d(Matrix2d mat) {
216         m00 = mat.m00;
217         m01 = mat.m01;
218         m10 = mat.m10;
219         m11 = mat.m11;
220     }
221 
222 
223     /**
224      * Set the elements of this matrix to the left 2x2 submatrix of <code>m</code>.
225      *
226      * @param m
227      *          the matrix to copy the elements from
228      * @return this
229      */
230     ref public Matrix2d set(Matrix3x2d m) return {
231         setMatrix3x2d(m);
232         return this;
233     }
234     private void setMatrix3x2d(Matrix3x2d mat) {
235         m00 = mat.m00;
236         m01 = mat.m01;
237         m10 = mat.m10;
238         m11 = mat.m11;
239     }
240 
241     /**
242      * Set the elements of this matrix to the upper left 2x2 of the given {@link Matrix3d}.
243      *
244      * @param m
245      *          the {@link Matrix3d} to copy the values from
246      * @return this
247      */
248     ref public Matrix2d set(Matrix3d m) return {
249         setMatrix3d(m);
250         return this;
251     }
252     private void setMatrix3d(Matrix3d mat) {
253         m00 = mat.m00;
254         m01 = mat.m01;
255         m10 = mat.m10;
256         m11 = mat.m11;
257     }
258 
259 
260     /**
261      * Multiply this matrix by the supplied <code>right</code> matrix.
262      * <p>
263      * If <code>M</code> is <code>this</code> matrix and <code>R</code> the <code>right</code> matrix,
264      * then the new matrix will be <code>M * R</code>. So when transforming a
265      * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the
266      * transformation of the right matrix will be applied first!
267      *
268      * @param right
269      *          the right operand of the matrix multiplication
270      * @return this
271      */
272     ref public Matrix2d mul(Matrix2d right) return {
273         this.mul(right, this);
274         return this;
275     }
276 
277     public Matrix2d mul(Matrix2d right, ref Matrix2d dest) {
278         double nm00 = m00 * right.m00 + m10 * right.m01;
279         double nm01 = m01 * right.m00 + m11 * right.m01;
280         double nm10 = m00 * right.m10 + m10 * right.m11;
281         double nm11 = m01 * right.m10 + m11 * right.m11;
282         dest.m00 = nm00;
283         dest.m01 = nm01;
284         dest.m10 = nm10;
285         dest.m11 = nm11;
286         return dest;
287     }
288 
289     /**
290      * Pre-multiply this matrix by the supplied <code>left</code> matrix and store the result in <code>this</code>.
291      * <p>
292      * If <code>M</code> is <code>this</code> matrix and <code>L</code> the <code>left</code> matrix,
293      * then the new matrix will be <code>L * M</code>. So when transforming a
294      * vector <code>v</code> with the new matrix by using <code>L * M * v</code>, the
295      * transformation of <code>this</code> matrix will be applied first!
296      *
297      * @param left
298      *          the left operand of the matrix multiplication
299      * @return this
300      */
301     ref public Matrix2d mulLocal(Matrix2d left) return {
302         this.mulLocal(left, this);
303         return this;
304     }
305 
306     public Matrix2d mulLocal(Matrix2d left, ref Matrix2d dest) {
307         double nm00 = left.m00 * m00 + left.m10 * m01;
308         double nm01 = left.m01 * m00 + left.m11 * m01;
309         double nm10 = left.m00 * m10 + left.m10 * m11;
310         double nm11 = left.m01 * m10 + left.m11 * m11;
311         dest.m00 = nm00;
312         dest.m01 = nm01;
313         dest.m10 = nm10;
314         dest.m11 = nm11;
315         return dest;
316     }
317 
318     /**
319      * Set the values within this matrix to the supplied double values. The result looks like this:
320      * <p>
321      * m00, m10<br>
322      * m01, m11<br>
323      *
324      * @param m00
325      *          the new value of m00
326      * @param m01
327      *          the new value of m01
328      * @param m10
329      *          the new value of m10
330      * @param m11
331      *          the new value of m11
332      * @return this
333      */
334     ref public Matrix2d set(double m00, double m01,
335                         double m10, double m11) return {
336         this.m00 = m00;
337         this.m01 = m01;
338         this.m10 = m10;
339         this.m11 = m11;
340         return this;
341     }
342     /**
343      * Set the two columns of this matrix to the supplied vectors, respectively.
344      *
345      * @param col0
346      *          the first column
347      * @param col1
348      *          the second column
349      * @return this
350      */
351     ref public Matrix2d set(Vector2d col0, Vector2d col1) return {
352         m00 = col0.x;
353         m01 = col0.y;
354         m10 = col1.x;
355         m11 = col1.y;
356         return this;
357     }
358 
359     public double determinant() {
360         return m00 * m11 - m10 * m01;
361     }
362 
363     /**
364      * Invert this matrix.
365      *
366      * @return this
367      */
368     ref public Matrix2d invert() return {
369         this.invert(this);
370         return this;
371     }
372 
373     public Matrix2d invert(ref Matrix2d dest) {
374         double s = 1.0 / determinant();
375         double nm00 = m11 * s;
376         double nm01 = -m01 * s;
377         double nm10 = -m10 * s;
378         double nm11 = m00 * s;
379         dest.m00 = nm00;
380         dest.m01 = nm01;
381         dest.m10 = nm10;
382         dest.m11 = nm11;
383         return dest;
384     }
385 
386     /**
387      * Transpose this matrix.
388      *
389      * @return this
390      */
391     ref public Matrix2d transpose() return {
392         this.transpose(this);
393         return this;
394     }
395 
396     public Matrix2d transpose(ref Matrix2d dest) {
397         dest.set(m00, m10,
398                 m01, m11);
399         return dest;
400     }
401 
402    
403     /**
404      * Get the current values of <code>this</code> matrix and store them into
405      * <code>dest</code>.
406      * <p>
407      * This is the reverse method of {@link #set(Matrix2d)} and allows to obtain
408      * intermediate calculation results when chaining multiple transformations.
409      *
410      * @see #set(Matrix2d)
411      *
412      * @param dest
413      *          the destination matrix
414      * @return the passed in destination
415      */
416     public Matrix2d get(ref Matrix2d dest) {
417         return dest.set(this);
418     }
419 
420     public Matrix3x2d get(ref Matrix3x2d dest) {
421         return dest.set(this);
422     }
423 
424     public Matrix3d get(ref Matrix3d dest) {
425         return dest.set(this);
426     }
427 
428     public double getRotation() {
429         return cast(double) Math.atan2(m01, m11);
430     }
431 
432     /**
433      * Set all values within this matrix to zero.
434      *
435      * @return this
436      */
437     ref public Matrix2d zero() return {
438         MemUtil.zero(this);
439         return this;
440     }
441 
442     /**
443      * Set this matrix to the identity.
444      *
445      * @return this
446      */
447     ref public Matrix2d identity() return {
448         m00 = 1.0;
449         m01 = 0.0;
450         m10 = 0.0;
451         m11 = 1.0;
452         return this;
453     }
454 
455     public Matrix2d scale(Vector2d xy, ref Matrix2d dest) {
456         return scale(xy.x, xy.y, dest);
457     }
458 
459     /**
460      * Apply scaling to this matrix by scaling the base axes by the given <code>xy.x</code> and
461      * <code>xy.y</code> factors, respectively.
462      * <p>
463      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
464      * then the new matrix will be <code>M * S</code>. So when transforming a
465      * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the
466      * scaling will be applied first!
467      *
468      * @param xy
469      *            the factors of the x and y component, respectively
470      * @return this
471      */
472     ref public Matrix2d scale(Vector2d xy) return {
473         this.scale(xy.x, xy.y, this);
474         return this;
475     }
476 
477     public Matrix2d scale(double x, double y, ref Matrix2d dest) {
478         // scale matrix elements:
479         // m00 = x, m11 = y
480         // all others = 0
481         dest.m00 = m00 * x;
482         dest.m01 = m01 * x;
483         dest.m10 = m10 * y;
484         dest.m11 = m11 * y;
485         return dest;
486     }
487 
488     /**
489      * Apply scaling to this matrix by scaling the base axes by the given x and
490      * y factors.
491      * <p>
492      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
493      * then the new matrix will be <code>M * S</code>. So when transforming a
494      * vector <code>v</code> with the new matrix by using <code>M * S * v</code>
495      * , the scaling will be applied first!
496      *
497      * @param x
498      *            the factor of the x component
499      * @param y
500      *            the factor of the y component
501      * @return this
502      */
503     ref public Matrix2d scale(double x, double y) return {
504         this.scale(x, y, this);
505         return this;
506     }
507 
508     public Matrix2d scale(double xy, ref Matrix2d dest) {
509         return scale(xy, xy, dest);
510     }
511 
512     /**
513      * Apply scaling to this matrix by uniformly scaling all base axes by the given <code>xy</code> factor.
514      * <p>
515      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
516      * then the new matrix will be <code>M * S</code>. So when transforming a
517      * vector <code>v</code> with the new matrix by using <code>M * S * v</code>
518      * , the scaling will be applied first!
519      *
520      * @see #scale(double, double)
521      *
522      * @param xy
523      *            the factor for all components
524      * @return this
525      */
526     ref public Matrix2d scale(double xy) return {
527         return scale(xy, xy);
528     }
529 
530     public Matrix2d scaleLocal(double x, double y, ref Matrix2d dest) {
531         dest.m00 = x * m00;
532         dest.m01 = y * m01;
533         dest.m10 = x * m10;
534         dest.m11 = y * m11;
535         return dest;
536     }
537 
538     /**
539      * Pre-multiply scaling to this matrix by scaling the base axes by the given x and
540      * y factors.
541      * <p>
542      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
543      * then the new matrix will be <code>S * M</code>. So when transforming a
544      * vector <code>v</code> with the new matrix by using <code>S * M * v</code>, the
545      * scaling will be applied last!
546      *
547      * @param x
548      *            the factor of the x component
549      * @param y
550      *            the factor of the y component
551      * @return this
552      */
553     ref public Matrix2d scaleLocal(double x, double y) return {
554         this.scaleLocal(x, y, this);
555         return this;
556     }
557 
558     /**
559      * Set this matrix to be a simple scale matrix, which scales all axes uniformly by the given factor.
560      * <p>
561      * The resulting matrix can be multiplied against another transformation
562      * matrix to obtain an additional scaling.
563      * <p>
564      * In order to post-multiply a scaling transformation directly to a
565      * matrix, use {@link #scale(double) scale()} instead.
566      *
567      * @see #scale(double)
568      *
569      * @param factor
570      *             the scale factor in x and y
571      * @return this
572      */
573     ref public Matrix2d scaling(double factor) return {
574         MemUtil.zero(this);
575         m00 = factor;
576         m11 = factor;
577         return this;
578     }
579 
580     /**
581      * Set this matrix to be a simple scale matrix.
582      *
583      * @param x
584      *             the scale in x
585      * @param y
586      *             the scale in y
587      * @return this
588      */
589     ref public Matrix2d scaling(double x, double y) return {
590         MemUtil.zero(this);
591         m00 = x;
592         m11 = y;
593         return this;
594     }
595 
596     /**
597      * Set this matrix to be a simple scale matrix which scales the base axes by <code>xy.x</code> and <code>xy.y</code> respectively.
598      * <p>
599      * The resulting matrix can be multiplied against another transformation
600      * matrix to obtain an additional scaling.
601      * <p>
602      * In order to post-multiply a scaling transformation directly to a
603      * matrix use {@link #scale(Vector2d) scale()} instead.
604      *
605      * @see #scale(Vector2d)
606      *
607      * @param xy
608      *             the scale in x and y respectively
609      * @return this
610      */
611     ref public Matrix2d scaling(Vector2d xy) return {
612         return scaling(xy.x, xy.y);
613     }
614 
615     /**
616      * Set this matrix to a rotation matrix which rotates the given radians about the origin.
617      * <p>
618      * The produced rotation will rotate a vector counter-clockwise around the origin.
619      * <p>
620      * The resulting matrix can be multiplied against another transformation
621      * matrix to obtain an additional rotation.
622      * <p>
623      * In order to post-multiply a rotation transformation directly to a
624      * matrix, use {@link #rotate(double) rotate()} instead.
625      *
626      * @see #rotate(double)
627      *
628      * @param angle
629      *          the angle in radians
630      * @return this
631      */
632     ref public Matrix2d rotation(double angle) return {
633         double sin = Math.sin(angle);
634         double cos = Math.cosFromSin(sin, angle);
635         m00 = cos;
636         m01 = sin;
637         m10 = -sin;
638         m11 = cos;
639         return this;
640     }
641 
642     public Vector2d transform(Vector2d v) {
643         return v.mul(this);
644     }
645 
646     public Vector2d transform(Vector2d v, ref Vector2d dest) {
647         v.mul(this, dest);
648         return dest;
649     }
650 
651     public Vector2d transform(double x, double y, ref Vector2d dest) {
652         dest.set(m00 * x + m10 * y,
653                 m01 * x + m11 * y);
654         return dest;
655     }
656 
657     public Vector2d transformTranspose(Vector2d v) {
658         return v.mulTranspose(this);
659     }
660 
661     public Vector2d transformTranspose(Vector2d v, ref Vector2d dest) {
662         v.mulTranspose(this, dest);
663         return dest;
664     }
665 
666     public Vector2d transformTranspose(double x, double y, ref Vector2d dest) {
667         dest.set(m00 * x + m01 * y,
668                 m10 * x + m11 * y);
669         return dest;
670     }
671 
672     /**
673      * Apply rotation about the origin to this matrix by rotating the given amount of radians.
674      * <p>
675      * The produced rotation will rotate a vector counter-clockwise around the origin.
676      * <p>
677      * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
678      * then the new matrix will be <code>M * R</code>. So when transforming a
679      * vector <code>v</code> with the new matrix by using <code>M * R * v</code>
680      * , the rotation will be applied first!
681      * <p>
682      * Reference: <a href="https://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions">http://en.wikipedia.org</a>
683      *
684      * @param angle
685      *            the angle in radians
686      * @return this
687      */
688     ref public Matrix2d rotate(double angle) return {
689         this.rotate(angle, this);
690         return this;
691     }
692 
693     public Matrix2d rotate(double angle, ref Matrix2d dest) {
694         double s = Math.sin(angle);
695         double c = Math.cosFromSin(s, angle);
696         // rotation matrix elements:
697         // m00 = c, m01 = s, m10 = -s, m11 = c
698         double nm00 = m00 * c + m10 * s;
699         double nm01 = m01 * c + m11 * s;
700         double nm10 = m10 * c - m00 * s;
701         double nm11 = m11 * c - m01 * s;
702         dest.m00 = nm00;
703         dest.m01 = nm01;
704         dest.m10 = nm10;
705         dest.m11 = nm11;
706         return dest;
707     }
708 
709     /**
710      * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the origin.
711      * <p>
712      * The produced rotation will rotate a vector counter-clockwise around the origin.
713      * <p>
714      * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
715      * then the new matrix will be <code>R * M</code>. So when transforming a
716      * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the
717      * rotation will be applied last!
718      * <p>
719      * In order to set the matrix to a rotation matrix without pre-multiplying the rotation
720      * transformation, use {@link #rotation(double) rotation()}.
721      * <p>
722      * Reference: <a href="https://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions">http://en.wikipedia.org</a>
723      *
724      * @see #rotation(double)
725      *
726      * @param angle
727      *            the angle in radians to rotate about the X axis
728      * @return this
729      */
730     ref public Matrix2d rotateLocal(double angle) return {
731         this.rotateLocal(angle, this);
732         return this;
733     }
734 
735     public Matrix2d rotateLocal(double angle, ref Matrix2d dest) {
736         double s = Math.sin(angle);
737         double c = Math.cosFromSin(s, angle);
738         // rotation matrix elements:
739         // m00 = c, m01 = s, m10 = -s, m11 = c
740         double nm00 = c * m00 - s * m01;
741         double nm01 = s * m00 + c * m01;
742         double nm10 = c * m10 - s * m11;
743         double nm11 = s * m10 + c * m11;
744         dest.m00 = nm00;
745         dest.m01 = nm01;
746         dest.m10 = nm10;
747         dest.m11 = nm11;
748         return dest;
749     }
750 
751     public Vector2d getRow(int row, ref Vector2d dest) {
752         switch (row) {
753             case 0:
754                 dest.x = m00;
755                 dest.y = m10;
756                 break;
757             case 1:
758                 dest.x = m01;
759                 dest.y = m11;
760                 break;
761             default: {}
762         }
763         return dest;
764     }
765 
766     /**
767      * Set the row at the given <code>row</code> index, starting with <code>0</code>.
768      *
769      * @param row
770      *          the row index in <code>[0..1]</code>
771      * @param src
772      *          the row components to set
773      * @return this
774      * @throws IndexOutOfBoundsException if <code>row</code> is not in <code>[0..1]</code>
775      */
776     ref public Matrix2d setRow(int row, Vector2d src) return {
777         return setRow(row, src.x, src.y);
778     }
779 
780     /**
781      * Set the row at the given <code>row</code> index, starting with <code>0</code>.
782      *
783      * @param row
784      *          the row index in <code>[0..1]</code>
785      * @param x
786      *          the first element in the row
787      * @param y
788      *          the second element in the row
789      * @return this
790      * @throws IndexOutOfBoundsException if <code>row</code> is not in <code>[0..1]</code>
791      */
792     ref public Matrix2d setRow(int row, double x, double y) return {
793         switch (row) {
794             case 0:
795                 this.m00 = x;
796                 this.m10 = y;
797                 break;
798             case 1:
799                 this.m01 = x;
800                 this.m11 = y;
801                 break;
802             default:{}
803         }
804         return this;
805     }
806 
807     public Vector2d getColumn(int column, ref Vector2d dest){
808         switch (column) {
809             case 0:
810                 dest.x = m00;
811                 dest.y = m01;
812                 break;
813             case 1:
814                 dest.x = m10;
815                 dest.y = m11;
816                 break;
817             default:{}
818         }
819         return dest;
820     }
821 
822     /**
823      * Set the column at the given <code>column</code> index, starting with <code>0</code>.
824      *
825      * @param column
826      *          the column index in <code>[0..1]</code>
827      * @param src
828      *          the column components to set
829      * @return this
830      * @throws IndexOutOfBoundsException if <code>column</code> is not in <code>[0..1]</code>
831      */
832     ref public Matrix2d setColumn(int column, Vector2d src) return {
833         return setColumn(column, src.x, src.y);
834     }
835 
836     /**
837      * Set the column at the given <code>column</code> index, starting with <code>0</code>.
838      *
839      * @param column
840      *          the column index in <code>[0..1]</code>
841      * @param x
842      *          the first element in the column
843      * @param y
844      *          the second element in the column
845      * @return this
846      * @throws IndexOutOfBoundsException if <code>column</code> is not in <code>[0..1]</code>
847      */
848     ref public Matrix2d setColumn(int column, double x, double y) return {
849         switch (column) {
850             case 0:
851                 this.m00 = x;
852                 this.m01 = y;
853                 break;
854             case 1:
855                 this.m10 = x;
856                 this.m11 = y;
857                 break;
858             default: {}
859         }
860         return this;
861     }
862 
863     public double get(int column, int row) {
864         switch (column) {
865             case 0:
866                 switch (row) {
867                     case 0:
868                         return m00;
869                     case 1:
870                         return m01;
871                     default:
872                         break;
873                 }
874                 break;
875             case 1:
876                 switch (row) {
877                     case 0:
878                         return m10;
879                     case 1:
880                         return m11;
881                     default:
882                         break;
883                 }
884                 break;
885             default:{}
886         }
887         return 0;
888     }
889 
890     /**
891      * Set the matrix element at the given column and row to the specified value.
892      *
893      * @param column
894      *          the colum index in <code>[0..1]</code>
895      * @param row
896      *          the row index in <code>[0..1]</code>
897      * @param value
898      *          the value
899      * @return this
900      */
901     ref public Matrix2d set(int column, int row, double value) return {
902         switch (column) {
903             case 0:
904                 switch (row) {
905                     case 0:
906                         this.m00 = value;
907                         return this;
908                     case 1:
909                         this.m01 = value;
910                         return this;
911                     default:
912                         break;
913                 }
914                 break;
915             case 1:
916                 switch (row) {
917                     case 0:
918                         this.m10 = value;
919                         return this;
920                     case 1:
921                         this.m11 = value;
922                         return this;
923                     default:
924                         break;
925                 }
926                 break;
927             default:{}
928         }
929         return this;
930     }
931 
932     /**
933      * Set <code>this</code> matrix to its own normal matrix.
934      * <p>
935      * Please note that, if <code>this</code> is an orthogonal matrix or a matrix whose columns are orthogonal vectors,
936      * then this method <i>need not</i> be invoked, since in that case <code>this</code> itself is its normal matrix.
937      * In this case, use {@link #set(Matrix2d)} to set a given Matrix2d to this matrix.
938      *
939      * @see #set(Matrix2d)
940      *
941      * @return this
942      */
943     ref public Matrix2d normal() return {
944         this.normal(this);
945         return this;
946     }
947 
948     /**
949      * Compute a normal matrix from <code>this</code> matrix and store it into <code>dest</code>.
950      * <p>
951      * Please note that, if <code>this</code> is an orthogonal matrix or a matrix whose columns are orthogonal vectors,
952      * then this method <i>need not</i> be invoked, since in that case <code>this</code> itself is its normal matrix.
953      * In this case, use {@link #set(Matrix2d)} to set a given Matrix2d to this matrix.
954      *
955      * @see #set(Matrix2d)
956      *
957      * @param dest
958      *             will hold the result
959      * @return dest
960      */
961     public Matrix2d normal(ref Matrix2d dest) {
962         double det = m00 * m11 - m10 * m01;
963         double s = 1.0 / det;
964         /* Invert and transpose in one go */
965         double nm00 = m11 * s;
966         double nm01 = -m10 * s;
967         double nm10 = -m01 * s;
968         double nm11 = m00 * s;
969         dest.m00 = nm00;
970         dest.m01 = nm01;
971         dest.m10 = nm10;
972         dest.m11 = nm11;
973         return dest;
974     }
975 
976     public Vector2d getScale(ref Vector2d dest) {
977         dest.x = Math.sqrt(m00 * m00 + m01 * m01);
978         dest.y = Math.sqrt(m10 * m10 + m11 * m11);
979         return dest;
980     }
981 
982     public Vector2d positiveX(Vector2d dir) {
983         if (m00 * m11 < m01 * m10) { // negative determinant?
984             dir.x = -m11;
985             dir.y = m01;
986         } else {
987             dir.x = m11;
988             dir.y = -m01;
989         }
990         return dir.normalize(dir);
991     }
992 
993     public Vector2d normalizedPositiveX(Vector2d dir) {
994         if (m00 * m11 < m01 * m10) { // negative determinant?
995             dir.x = -m11;
996             dir.y = m01;
997         } else {
998             dir.x = m11;
999             dir.y = -m01;
1000         }
1001         return dir;
1002     }
1003 
1004     public Vector2d positiveY(Vector2d dir) {
1005         if (m00 * m11 < m01 * m10) { // negative determinant?
1006             dir.x = m10;
1007             dir.y = -m00;
1008         } else {
1009             dir.x = -m10;
1010             dir.y = m00;
1011         }
1012         return dir.normalize(dir);
1013     }
1014 
1015     public Vector2d normalizedPositiveY(Vector2d dir) {
1016         if (m00 * m11 < m01 * m10) { // negative determinant?
1017             dir.x = m10;
1018             dir.y = -m00;
1019         } else {
1020             dir.x = -m10;
1021             dir.y = m00;
1022         }
1023         return dir;
1024     }
1025 
1026     public int hashCode() {
1027         immutable int prime = 31;
1028         int result = 1;
1029         long temp;
1030         temp = Math.doubleToLongBits(m00);
1031         result = prime * result + cast(int) ((temp >>> 32) ^ temp);
1032         temp = Math.doubleToLongBits(m01);
1033         result = prime * result + cast(int) ((temp >>> 32) ^ temp);
1034         temp = Math.doubleToLongBits(m10);
1035         result = prime * result + cast(int) ((temp >>> 32) ^ temp);
1036         temp = Math.doubleToLongBits(m11);
1037         result = prime * result + cast(int) ((temp >>> 32) ^ temp);
1038         return result;
1039     }
1040 
1041     public bool equals(Matrix2d m, double delta) {
1042         if (this == m)
1043             return true;
1044         if (!Math.equals(m00, m.m00, delta))
1045             return false;
1046         if (!Math.equals(m01, m.m01, delta))
1047             return false;
1048         if (!Math.equals(m10, m.m10, delta))
1049             return false;
1050         if (!Math.equals(m11, m.m11, delta))
1051             return false;
1052         return true;
1053     }
1054 
1055     /**
1056      * Exchange the values of <code>this</code> matrix with the given <code>other</code> matrix.
1057      *
1058      * @param other
1059      *          the other matrix to exchange the values with
1060      * @return this
1061      */
1062     ref public Matrix2d swap(ref Matrix2d other) return {
1063         MemUtil.swap(this, other);
1064         return this;
1065     }
1066 
1067     /**
1068      * Component-wise add <code>this</code> and <code>other</code>.
1069      *
1070      * @param other
1071      *          the other addend
1072      * @return this
1073      */
1074     ref public Matrix2d add(Matrix2d other) return {
1075         this.add(other, this);
1076         return this;
1077     }
1078 
1079     public Matrix2d add(Matrix2d other, ref Matrix2d dest) {
1080         dest.m00 = m00 + other.m00;
1081         dest.m01 = m01 + other.m01;
1082         dest.m10 = m10 + other.m10;
1083         dest.m11 = m11 + other.m11;
1084         return dest;
1085     }
1086 
1087     /**
1088      * Component-wise subtract <code>subtrahend</code> from <code>this</code>.
1089      *
1090      * @param subtrahend
1091      *          the subtrahend
1092      * @return this
1093      */
1094     ref public Matrix2d sub(Matrix2d subtrahend) return {
1095         this.sub(subtrahend, this);
1096         return this;
1097     }
1098 
1099     public Matrix2d sub(Matrix2d other, ref Matrix2d dest) {
1100         dest.m00 = m00 - other.m00;
1101         dest.m01 = m01 - other.m01;
1102         dest.m10 = m10 - other.m10;
1103         dest.m11 = m11 - other.m11;
1104         return dest;
1105     }
1106 
1107     /**
1108      * Component-wise multiply <code>this</code> by <code>other</code>.
1109      *
1110      * @param other
1111      *          the other matrix
1112      * @return this
1113      */
1114     public Matrix2d mulComponentWise(Matrix2d other) {
1115         return sub(other, this);
1116     }
1117 
1118     public Matrix2d mulComponentWise(Matrix2d other, ref Matrix2d dest) {
1119         dest.m00 = m00 * other.m00;
1120         dest.m01 = m01 * other.m01;
1121         dest.m10 = m10 * other.m10;
1122         dest.m11 = m11 * other.m11;
1123         return dest;
1124     }
1125 
1126     /**
1127      * Linearly interpolate <code>this</code> and <code>other</code> using the given interpolation factor <code>t</code>
1128      * and store the result in <code>this</code>.
1129      * <p>
1130      * If <code>t</code> is <code>0.0</code> then the result is <code>this</code>. If the interpolation factor is <code>1.0</code>
1131      * then the result is <code>other</code>.
1132      *
1133      * @param other
1134      *          the other matrix
1135      * @param t
1136      *          the interpolation factor between 0.0 and 1.0
1137      * @return this
1138      */
1139     public Matrix2d lerp(Matrix2d other, double t) {
1140         return lerp(other, t, this);
1141     }
1142 
1143     public Matrix2d lerp(Matrix2d other, double t, ref Matrix2d dest) {
1144         dest.m00 = Math.fma(other.m00 - m00, t, m00);
1145         dest.m01 = Math.fma(other.m01 - m01, t, m01);
1146         dest.m10 = Math.fma(other.m10 - m10, t, m10);
1147         dest.m11 = Math.fma(other.m11 - m11, t, m11);
1148         return dest;
1149     }
1150 
1151     public bool isFinite() {
1152         return Math.isFinite(m00) && Math.isFinite(m01) &&
1153                Math.isFinite(m10) && Math.isFinite(m11);
1154     }
1155 }