1/* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
2
3Redistribution and use in source and binary forms, with or without modification,
4are permitted provided that the following conditions are met:
5
6  * Redistributions of source code must retain the above copyright notice, this
7    list of conditions and the following disclaimer.
8  * Redistributions in binary form must reproduce the above copyright notice,
9    this list of conditions and the following disclaimer in the documentation
10    and/or other materials provided with the distribution.
11
12THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
13ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
16ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
22
23describe("mat2", function() {
24    var out, matA, matB, identity, result;
25
26    beforeEach(function() {
27        matA = [1, 2,
28                3, 4];
29
30        matB = [5, 6,
31                7, 8];
32
33        out =  [0, 0,
34                0, 0];
35
36        identity = [1, 0,
37                    0, 1];
38    });
39
40    describe("create", function() {
41        beforeEach(function() { result = mat2.create(); });
42        it("should return a 4 element array initialized to a 2x2 identity matrix", function() { expect(result).toBeEqualish(identity); });
43    });
44
45    describe("clone", function() {
46        beforeEach(function() { result = mat2.clone(matA); });
47        it("should return a 4 element array initialized to the values in matA", function() { expect(result).toBeEqualish(matA); });
48    });
49
50    describe("copy", function() {
51        beforeEach(function() { result = mat2.copy(out, matA); });
52        it("should place values into out", function() { expect(out).toBeEqualish(matA); });
53        it("should return out", function() { expect(result).toBe(out); });
54    });
55
56    describe("identity", function() {
57        beforeEach(function() { result = mat2.identity(out); });
58        it("should place values into out", function() { expect(result).toBeEqualish(identity); });
59        it("should return out", function() { expect(result).toBe(out); });
60    });
61
62    describe("transpose", function() {
63        describe("with a separate output matrix", function() {
64            beforeEach(function() { result = mat2.transpose(out, matA); });
65
66            it("should place values into out", function() { expect(out).toBeEqualish([1, 3, 2, 4]); });
67            it("should return out", function() { expect(result).toBe(out); });
68            it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); });
69        });
70
71        describe("when matA is the output matrix", function() {
72            beforeEach(function() { result = mat2.transpose(matA, matA); });
73
74            it("should place values into matA", function() { expect(matA).toBeEqualish([1, 3, 2, 4]); });
75            it("should return matA", function() { expect(result).toBe(matA); });
76        });
77    });
78
79    describe("invert", function() {
80        describe("with a separate output matrix", function() {
81            beforeEach(function() { result = mat2.invert(out, matA); });
82
83            it("should place values into out", function() { expect(out).toBeEqualish([-2, 1, 1.5, -0.5]); });
84            it("should return out", function() { expect(result).toBe(out); });
85            it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); });
86        });
87
88        describe("when matA is the output matrix", function() {
89            beforeEach(function() { result = mat2.invert(matA, matA); });
90
91            it("should place values into matA", function() { expect(matA).toBeEqualish([-2, 1, 1.5, -0.5]); });
92            it("should return matA", function() { expect(result).toBe(matA); });
93        });
94    });
95
96    describe("adjoint", function() {
97        describe("with a separate output matrix", function() {
98            beforeEach(function() { result = mat2.adjoint(out, matA); });
99
100            it("should place values into out", function() { expect(out).toBeEqualish([4, -2, -3, 1]); });
101            it("should return out", function() { expect(result).toBe(out); });
102            it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); });
103        });
104
105        describe("when matA is the output matrix", function() {
106            beforeEach(function() { result = mat2.adjoint(matA, matA); });
107
108            it("should place values into matA", function() { expect(matA).toBeEqualish([4, -2, -3, 1]); });
109            it("should return matA", function() { expect(result).toBe(matA); });
110        });
111    });
112
113    describe("determinant", function() {
114        beforeEach(function() { result = mat2.determinant(matA); });
115
116        it("should return the determinant", function() { expect(result).toEqual(-2); });
117    });
118
119    describe("multiply", function() {
120        it("should have an alias called 'mul'", function() { expect(mat2.mul).toEqual(mat2.multiply); });
121
122        describe("with a separate output matrix", function() {
123            beforeEach(function() { result = mat2.multiply(out, matA, matB); });
124
125            it("should place values into out", function() { expect(out).toBeEqualish([19, 22, 43, 50]); });
126            it("should return out", function() { expect(result).toBe(out); });
127            it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); });
128            it("should not modify matB", function() { expect(matB).toBeEqualish([5, 6, 7, 8]); });
129        });
130
131        describe("when matA is the output matrix", function() {
132            beforeEach(function() { result = mat2.multiply(matA, matA, matB); });
133
134            it("should place values into matA", function() { expect(matA).toBeEqualish([19, 22, 43, 50]); });
135            it("should return matA", function() { expect(result).toBe(matA); });
136            it("should not modify matB", function() { expect(matB).toBeEqualish([5, 6, 7, 8]); });
137        });
138
139        describe("when matB is the output matrix", function() {
140            beforeEach(function() { result = mat2.multiply(matB, matA, matB); });
141
142            it("should place values into matB", function() { expect(matB).toBeEqualish([19, 22, 43, 50]); });
143            it("should return matB", function() { expect(result).toBe(matB); });
144            it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); });
145        });
146    });
147
148    describe("rotate", function() {
149        describe("with a separate output matrix", function() {
150            beforeEach(function() { result = mat2.rotate(out, matA, Math.PI * 0.5); });
151
152            it("should place values into out", function() { expect(out).toBeEqualish([2, -1, 4, -3]); });
153            it("should return out", function() { expect(result).toBe(out); });
154            it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); });
155        });
156
157        describe("when matA is the output matrix", function() {
158            beforeEach(function() { result = mat2.rotate(matA, matA, Math.PI * 0.5); });
159
160            it("should place values into matA", function() { expect(matA).toBeEqualish([2, -1, 4, -3]); });
161            it("should return matA", function() { expect(result).toBe(matA); });
162        });
163    });
164
165    describe("scale", function() {
166        var vecA;
167        beforeEach(function() { vecA = [2, 3]; });
168
169        describe("with a separate output matrix", function() {
170            beforeEach(function() { result = mat2.scale(out, matA, vecA); });
171
172            it("should place values into out", function() { expect(out).toBeEqualish([2, 6, 6, 12]); });
173            it("should return out", function() { expect(result).toBe(out); });
174            it("should not modify matA", function() { expect(matA).toBeEqualish([1, 2, 3, 4]); });
175        });
176
177        describe("when matA is the output matrix", function() {
178            beforeEach(function() { result = mat2.scale(matA, matA, vecA); });
179
180            it("should place values into matA", function() { expect(matA).toBeEqualish([2, 6, 6, 12]); });
181            it("should return matA", function() { expect(result).toBe(matA); });
182        });
183    });
184
185    describe("str", function() {
186        beforeEach(function() { result = mat2.str(matA); });
187
188        it("should return a string representation of the matrix", function() { expect(result).toEqual("mat2(1, 2, 3, 4)"); });
189    });
190});