1 /* Copyright (c) 2013, Brandon Jones, Colin MacKenzie IV. All rights reserved.
3 Redistribution and use in source and binary forms, with or without modification,
4 are permitted provided that the following conditions are met:
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.
12 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
13 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
16 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19 ANY 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
21 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
23 describe("vec4", function() {
24 var out, vecA, vecB, result;
26 beforeEach(function() { vecA = [1, 2, 3, 4]; vecB = [5, 6, 7, 8]; out = [0, 0, 0, 0]; });
28 describe("create", function() {
29 beforeEach(function() { result = vec4.create(); });
30 it("should return a 4 element array initialized to 0s", function() { expect(result).toBeEqualish([0, 0, 0, 0]); });
33 describe("clone", function() {
34 beforeEach(function() { result = vec4.clone(vecA); });
35 it("should return a 4 element array initialized to the values in vecA", function() { expect(result).toBeEqualish(vecA); });
38 describe("fromValues", function() {
39 beforeEach(function() { result = vec4.fromValues(1, 2, 3, 4); });
40 it("should return a 4 element array initialized to the values passed", function() { expect(result).toBeEqualish([1, 2, 3, 4]); });
43 describe("copy", function() {
44 beforeEach(function() { result = vec4.copy(out, vecA); });
45 it("should place values into out", function() { expect(out).toBeEqualish([1, 2, 3, 4]); });
46 it("should return out", function() { expect(result).toBe(out); });
49 describe("set", function() {
50 beforeEach(function() { result = vec4.set(out, 1, 2, 3, 4); });
51 it("should place values into out", function() { expect(out).toBeEqualish([1, 2, 3, 4]); });
52 it("should return out", function() { expect(result).toBe(out); });
55 describe("add", function() {
56 describe("with a separate output vector", function() {
57 beforeEach(function() { result = vec4.add(out, vecA, vecB); });
59 it("should place values into out", function() { expect(out).toBeEqualish([6, 8, 10, 12]); });
60 it("should return out", function() { expect(result).toBe(out); });
61 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
62 it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
65 describe("when vecA is the output vector", function() {
66 beforeEach(function() { result = vec4.add(vecA, vecA, vecB); });
68 it("should place values into vecA", function() { expect(vecA).toBeEqualish([6, 8, 10, 12]); });
69 it("should return vecA", function() { expect(result).toBe(vecA); });
70 it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
73 describe("when vecB is the output vector", function() {
74 beforeEach(function() { result = vec4.add(vecB, vecA, vecB); });
76 it("should place values into vecB", function() { expect(vecB).toBeEqualish([6, 8, 10, 12]); });
77 it("should return vecB", function() { expect(result).toBe(vecB); });
78 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
82 describe("subtract", function() {
83 it("should have an alias called 'sub'", function() { expect(vec4.sub).toEqual(vec4.subtract); });
85 describe("with a separate output vector", function() {
86 beforeEach(function() { result = vec4.subtract(out, vecA, vecB); });
88 it("should place values into out", function() { expect(out).toBeEqualish([-4, -4, -4, -4]); });
89 it("should return out", function() { expect(result).toBe(out); });
90 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
91 it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
94 describe("when vecA is the output vector", function() {
95 beforeEach(function() { result = vec4.subtract(vecA, vecA, vecB); });
97 it("should place values into vecA", function() { expect(vecA).toBeEqualish([-4, -4, -4, -4]); });
98 it("should return vecA", function() { expect(result).toBe(vecA); });
99 it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
102 describe("when vecB is the output vector", function() {
103 beforeEach(function() { result = vec4.subtract(vecB, vecA, vecB); });
105 it("should place values into vecB", function() { expect(vecB).toBeEqualish([-4, -4, -4, -4]); });
106 it("should return vecB", function() { expect(result).toBe(vecB); });
107 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
111 describe("multiply", function() {
112 it("should have an alias called 'mul'", function() { expect(vec4.mul).toEqual(vec4.multiply); });
114 describe("with a separate output vector", function() {
115 beforeEach(function() { result = vec4.multiply(out, vecA, vecB); });
117 it("should place values into out", function() { expect(out).toBeEqualish([5, 12, 21, 32]); });
118 it("should return out", function() { expect(result).toBe(out); });
119 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
120 it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
123 describe("when vecA is the output vector", function() {
124 beforeEach(function() { result = vec4.multiply(vecA, vecA, vecB); });
126 it("should place values into vecA", function() { expect(vecA).toBeEqualish([5, 12, 21, 32]); });
127 it("should return vecA", function() { expect(result).toBe(vecA); });
128 it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
131 describe("when vecB is the output vector", function() {
132 beforeEach(function() { result = vec4.multiply(vecB, vecA, vecB); });
134 it("should place values into vecB", function() { expect(vecB).toBeEqualish([5, 12, 21, 32]); });
135 it("should return vecB", function() { expect(result).toBe(vecB); });
136 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
140 describe("divide", function() {
141 it("should have an alias called 'div'", function() { expect(vec4.div).toEqual(vec4.divide); });
143 describe("with a separate output vector", function() {
144 beforeEach(function() { result = vec4.divide(out, vecA, vecB); });
146 it("should place values into out", function() { expect(out).toBeEqualish([0.2, 0.333333, 0.428571, 0.5]); });
147 it("should return out", function() { expect(result).toBe(out); });
148 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
149 it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
152 describe("when vecA is the output vector", function() {
153 beforeEach(function() { result = vec4.divide(vecA, vecA, vecB); });
155 it("should place values into vecA", function() { expect(vecA).toBeEqualish([0.2, 0.333333, 0.428571, 0.5]); });
156 it("should return vecA", function() { expect(result).toBe(vecA); });
157 it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
160 describe("when vecB is the output vector", function() {
161 beforeEach(function() { result = vec4.divide(vecB, vecA, vecB); });
163 it("should place values into vecB", function() { expect(vecB).toBeEqualish([0.2, 0.333333, 0.428571, 0.5]); });
164 it("should return vecB", function() { expect(result).toBe(vecB); });
165 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
169 describe("min", function() {
170 beforeEach(function() { vecA = [1, 3, 1, 3]; vecB = [3, 1, 3, 1]; });
172 describe("with a separate output vector", function() {
173 beforeEach(function() { result = vec4.min(out, vecA, vecB); });
175 it("should place values into out", function() { expect(out).toBeEqualish([1, 1, 1, 1]); });
176 it("should return out", function() { expect(result).toBe(out); });
177 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 3, 1, 3]); });
178 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 1, 3, 1]); });
181 describe("when vecA is the output vector", function() {
182 beforeEach(function() { result = vec4.min(vecA, vecA, vecB); });
184 it("should place values into vecA", function() { expect(vecA).toBeEqualish([1, 1, 1, 1]); });
185 it("should return vecA", function() { expect(result).toBe(vecA); });
186 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 1, 3, 1]); });
189 describe("when vecB is the output vector", function() {
190 beforeEach(function() { result = vec4.min(vecB, vecA, vecB); });
192 it("should place values into vecB", function() { expect(vecB).toBeEqualish([1, 1, 1, 1]); });
193 it("should return vecB", function() { expect(result).toBe(vecB); });
194 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 3, 1, 3]); });
198 describe("max", function() {
199 beforeEach(function() { vecA = [1, 3, 1, 3]; vecB = [3, 1, 3, 1]; });
201 describe("with a separate output vector", function() {
202 beforeEach(function() { result = vec4.max(out, vecA, vecB); });
204 it("should place values into out", function() { expect(out).toBeEqualish([3, 3, 3, 3]); });
205 it("should return out", function() { expect(result).toBe(out); });
206 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 3, 1, 3]); });
207 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 1, 3, 1]); });
210 describe("when vecA is the output vector", function() {
211 beforeEach(function() { result = vec4.max(vecA, vecA, vecB); });
213 it("should place values into vecA", function() { expect(vecA).toBeEqualish([3, 3, 3, 3]); });
214 it("should return vecA", function() { expect(result).toBe(vecA); });
215 it("should not modify vecB", function() { expect(vecB).toBeEqualish([3, 1, 3, 1]); });
218 describe("when vecB is the output vector", function() {
219 beforeEach(function() { result = vec4.max(vecB, vecA, vecB); });
221 it("should place values into vecB", function() { expect(vecB).toBeEqualish([3, 3, 3, 3]); });
222 it("should return vecB", function() { expect(result).toBe(vecB); });
223 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 3, 1, 3]); });
227 describe("scale", function() {
228 describe("with a separate output vector", function() {
229 beforeEach(function() { result = vec4.scale(out, vecA, 2); });
231 it("should place values into out", function() { expect(out).toBeEqualish([2, 4, 6, 8]); });
232 it("should return out", function() { expect(result).toBe(out); });
233 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
236 describe("when vecA is the output vector", function() {
237 beforeEach(function() { result = vec4.scale(vecA, vecA, 2); });
239 it("should place values into vecA", function() { expect(vecA).toBeEqualish([2, 4, 6, 8]); });
240 it("should return vecA", function() { expect(result).toBe(vecA); });
244 describe("distance", function() {
245 it("should have an alias called 'dist'", function() { expect(vec4.dist).toEqual(vec4.distance); });
247 beforeEach(function() { result = vec4.distance(vecA, vecB); });
249 it("should return the distance", function() { expect(result).toBeCloseTo(8); });
252 describe("squaredDistance", function() {
253 it("should have an alias called 'sqrDist'", function() { expect(vec4.sqrDist).toEqual(vec4.squaredDistance); });
255 beforeEach(function() { result = vec4.squaredDistance(vecA, vecB); });
257 it("should return the squared distance", function() { expect(result).toEqual(64); });
260 describe("length", function() {
261 it("should have an alias called 'len'", function() { expect(vec4.len).toEqual(vec4.length); });
263 beforeEach(function() { result = vec4.length(vecA); });
265 it("should return the length", function() { expect(result).toBeCloseTo(5.477225); });
268 describe("squaredLength", function() {
269 it("should have an alias called 'sqrLen'", function() { expect(vec4.sqrLen).toEqual(vec4.squaredLength); });
271 beforeEach(function() { result = vec4.squaredLength(vecA); });
273 it("should return the squared length", function() { expect(result).toEqual(30); });
276 describe("negate", function() {
277 describe("with a separate output vector", function() {
278 beforeEach(function() { result = vec4.negate(out, vecA); });
280 it("should place values into out", function() { expect(out).toBeEqualish([-1, -2, -3, -4]); });
281 it("should return out", function() { expect(result).toBe(out); });
282 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
285 describe("when vecA is the output vector", function() {
286 beforeEach(function() { result = vec4.negate(vecA, vecA); });
288 it("should place values into vecA", function() { expect(vecA).toBeEqualish([-1, -2, -3, -4]); });
289 it("should return vecA", function() { expect(result).toBe(vecA); });
293 describe("normalize", function() {
294 beforeEach(function() { vecA = [5, 0, 0, 0]; });
296 describe("with a separate output vector", function() {
297 beforeEach(function() { result = vec4.normalize(out, vecA); });
299 it("should place values into out", function() { expect(out).toBeEqualish([1, 0, 0, 0]); });
300 it("should return out", function() { expect(result).toBe(out); });
301 it("should not modify vecA", function() { expect(vecA).toBeEqualish([5, 0, 0, 0]); });
304 describe("when vecA is the output vector", function() {
305 beforeEach(function() { result = vec4.normalize(vecA, vecA); });
307 it("should place values into vecA", function() { expect(vecA).toBeEqualish([1, 0, 0, 0]); });
308 it("should return vecA", function() { expect(result).toBe(vecA); });
312 describe("dot", function() {
313 beforeEach(function() { result = vec4.dot(vecA, vecB); });
315 it("should return the dot product", function() { expect(result).toEqual(70); });
316 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
317 it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
320 describe("lerp", function() {
321 describe("with a separate output vector", function() {
322 beforeEach(function() { result = vec4.lerp(out, vecA, vecB, 0.5); });
324 it("should place values into out", function() { expect(out).toBeEqualish([3, 4, 5, 6]); });
325 it("should return out", function() { expect(result).toBe(out); });
326 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
327 it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
330 describe("when vecA is the output vector", function() {
331 beforeEach(function() { result = vec4.lerp(vecA, vecA, vecB, 0.5); });
333 it("should place values into vecA", function() { expect(vecA).toBeEqualish([3, 4, 5, 6]); });
334 it("should return vecA", function() { expect(result).toBe(vecA); });
335 it("should not modify vecB", function() { expect(vecB).toBeEqualish([5, 6, 7, 8]); });
338 describe("when vecB is the output vector", function() {
339 beforeEach(function() { result = vec4.lerp(vecB, vecA, vecB, 0.5); });
341 it("should place values into vecB", function() { expect(vecB).toBeEqualish([3, 4, 5, 6]); });
342 it("should return vecB", function() { expect(result).toBe(vecB); });
343 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
347 describe("forEach", function() {
350 beforeEach(function() {
358 describe("when performing operations that take no extra arguments", function() {
359 beforeEach(function() { result = vec4.forEach(vecArray, 0, 0, 0, vec4.normalize); });
361 it("should update all values", function() {
362 expect(vecArray).toBeEqualish([
363 0.182574, 0.365148, 0.547722, 0.730296,
364 0.379049, 0.454858, 0.530668, 0.606478,
368 it("should return vecArray", function() { expect(result).toBe(vecArray); });
371 describe("when performing operations that takes one extra arguments", function() {
372 beforeEach(function() { result = vec4.forEach(vecArray, 0, 0, 0, vec4.add, vecA); });
374 it("should update all values", function() {
375 expect(vecArray).toBeEqualish([
381 it("should return vecArray", function() { expect(result).toBe(vecArray); });
382 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
385 describe("when specifying an offset", function() {
386 beforeEach(function() { result = vec4.forEach(vecArray, 0, 4, 0, vec4.add, vecA); });
388 it("should update all values except the first vector", function() {
389 expect(vecArray).toBeEqualish([
395 it("should return vecArray", function() { expect(result).toBe(vecArray); });
396 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
399 describe("when specifying a count", function() {
400 beforeEach(function() { result = vec4.forEach(vecArray, 0, 0, 2, vec4.add, vecA); });
402 it("should update all values except the last vector", function() {
403 expect(vecArray).toBeEqualish([
409 it("should return vecArray", function() { expect(result).toBe(vecArray); });
410 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
413 describe("when specifying a stride", function() {
414 beforeEach(function() { result = vec4.forEach(vecArray, 8, 0, 0, vec4.add, vecA); });
416 it("should update all values except the second vector", function() {
417 expect(vecArray).toBeEqualish([
423 it("should return vecArray", function() { expect(result).toBe(vecArray); });
424 it("should not modify vecA", function() { expect(vecA).toBeEqualish([1, 2, 3, 4]); });
427 describe("when calling a function that does not modify the out variable", function() {
428 beforeEach(function() {
429 result = vec3.forEach(vecArray, 0, 0, 0, function(out, vec) {});
432 it("values should remain unchanged", function() {
433 expect(vecArray).toBeEqualish([
439 it("should return vecArray", function() { expect(result).toBe(vecArray); });
443 describe("str", function() {
444 beforeEach(function() { result = vec4.str(vecA); });
446 it("should return a string representation of the vector", function() { expect(result).toEqual("vec4(1, 2, 3, 4)"); });