1 /*
2 Copyright (c) 2011-2021 Timur Gafarov
3 
4 Boost Software License - Version 1.0 - August 17th, 2003
5 
6 Permission is hereby granted, free of charge, to any person or organization
7 obtaining a copy of the software and accompanying documentation covered by
8 this license (the "Software") to use, reproduce, display, distribute,
9 execute, and transmit the Software, and to prepare derivative works of the
10 Software, and to permit third-parties to whom the Software is furnished to
11 do so, all subject to the following:
12 
13 The copyright notices in the Software and this entire statement, including
14 the above license grant, this restriction and the following disclaimer,
15 must be included in all copies of the Software, in whole or in part, and
16 all derivative works of the Software, unless such copies or derivative
17 works are solely in the form of machine-executable object code generated by
18 a source language processor.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
23 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
24 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
25 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 DEALINGS IN THE SOFTWARE.
27 */
28 
29 /**
30  * Vectors of Euclidean space
31  *
32  * Copyright: Timur Gafarov 2011-2021.
33  * License: $(LINK2 boost.org/LICENSE_1_0.txt, Boost License 1.0).
34  * Authors: Timur Gafarov
35  */
36 module dlib.math.vector;
37 
38 import std.conv;
39 import std.math;
40 import std.random;
41 import std.range;
42 import std.format;
43 import std.traits;
44 import dlib.core.tuple;
45 import dlib.math.utils;
46 import dlib.math.matrix;
47 
48 /**
49  * Vector representation
50  */
51 struct Vector(T, int size)
52 {
53     public:
54 
55    /**
56     * Vector constructor.
57     * Supports initializing from vector of arbitrary length and type
58     */
59     this (T2, int size2)(Vector!(T2, size2) v)
60     {
61         if (v.arrayof.length >= size)
62         {
63             foreach(i; 0..size)
64                 arrayof[i] = cast(T)v.arrayof[i];
65         }
66         else
67         {
68             foreach(i; 0..v.arrayof.length)
69                 arrayof[i] = cast(T)v.arrayof[i];
70         }
71     }
72 
73    /**
74     * Array constructor
75     */
76     this (A)(A components) if (isDynamicArray!A && !isSomeString!A)
77     {
78         if (components.length >= size)
79         {
80             foreach(i; 0..size)
81                 arrayof[i] = cast(T)components[i];
82         }
83         else
84         {
85             foreach(i; 0..components.length)
86                 arrayof[i] = cast(T)components[i];
87         }
88     }
89 
90    /**
91     * Static array constructor
92     */
93     this (T2, size_t arrSize)(T2[arrSize] components)
94     {
95         if (components.length >= size)
96         {
97             foreach(i; 0..size)
98                 arrayof[i] = cast(T)components[i];
99         }
100         else
101         {
102             foreach(i; 0..components.length)
103                 arrayof[i] = cast(T)components[i];
104         }
105     }
106 
107    /**
108     * Tuple constructor
109     */
110     this (F...)(F components)
111     {
112         foreach(i; RangeTuple!(0, size))
113         {
114             static if (i < components.length)
115                 arrayof[i] = cast(T)components[i];
116             else
117                 arrayof[i] = cast(T)components[$-1];
118         }
119     }
120 
121    /**
122     * String constructor
123     */
124     this (S)(S str) if (isSomeString!S)
125     {
126         arrayof = parse!(T[size])(str);
127     }
128 
129    /**
130     * Vector!(T,size) = Vector!(T,size2)
131     */
132     void opAssign(T2, int size2)(Vector!(T2,size2) v)
133     {
134         if (v.arrayof.length >= size)
135         {
136             foreach(i; 0..size)
137                 arrayof[i] = cast(T)v.arrayof[i];
138         }
139         else
140         {
141             foreach(i; 0..v.arrayof.length)
142                 arrayof[i] = cast(T)v.arrayof[i];
143         }
144     }
145 
146    /**
147     * Vector!(T,size) = Vector!(T,size2) for enums
148     */
149     void opAssign(T2)(T2 ev) if (is(T2 == enum))
150     {
151         opAssign(cast(OriginalType!T2)ev);
152     }
153 
154    /**
155     * -Vector!(T,size)
156     */
157     Vector!(T,size) opUnary(string s) () const if (s == "-")
158     do
159     {
160         Vector!(T,size) res;
161         foreach(i; RangeTuple!(0, size))
162             res.arrayof[i] = -arrayof[i];
163         return res;
164     }
165 
166    /**
167     * +Vector!(T,size)
168     */
169     Vector!(T,size) opUnary(string s) () const if (s == "+")
170     do
171     {
172         return Vector!(T,size)(this);
173     }
174 
175    /**
176     * Vector!(T,size) + Vector!(T,size)
177     */
178     Vector!(T,size) opBinary(string op)(Vector!(T,size) v) const if (op == "+")
179     do
180     {
181         Vector!(T,size) res;
182         foreach(i; RangeTuple!(0, size))
183             res.arrayof[i] = cast(T)(arrayof[i] + v.arrayof[i]);
184         return res;
185     }
186 
187    /**
188     * Vector!(T,size) - Vector!(T,size)
189     */
190     Vector!(T,size) opBinary(string op)(Vector!(T,size) v) const if (op == "-")
191     do
192     {
193         Vector!(T,size) res;
194         foreach(i; RangeTuple!(0, size))
195             res.arrayof[i] = cast(T)(arrayof[i] - v.arrayof[i]);
196         return res;
197     }
198 
199    /**
200     * Vector!(T,size) * Vector!(T,size)
201     */
202     Vector!(T,size) opBinary(string op)(Vector!(T,size) v) const if (op == "*")
203     do
204     {
205         Vector!(T,size) res;
206         foreach(i; RangeTuple!(0, size))
207             res.arrayof[i] = cast(T)(arrayof[i] * v.arrayof[i]);
208         return res;
209     }
210 
211    /**
212     * Vector!(T,size) / Vector!(T,size)
213     */
214     Vector!(T,size) opBinary(string op)(Vector!(T,size) v) const if (op == "/")
215     do
216     {
217         Vector!(T,size) res;
218         foreach(i; RangeTuple!(0, size))
219             res.arrayof[i] = cast(T)(arrayof[i] / v.arrayof[i]);
220         return res;
221     }
222 
223    /**
224     * Vector!(T,size) + T
225     */
226     Vector!(T,size) opBinary(string op)(T t) const if (op == "+")
227     do
228     {
229         Vector!(T,size) res;
230         foreach(i; RangeTuple!(0, size))
231             res.arrayof[i] = cast(T)(arrayof[i] + t);
232         return res;
233     }
234 
235    /**
236     * Vector!(T,size) - T
237     */
238     Vector!(T,size) opBinary(string op)(T t) const if (op == "-")
239     do
240     {
241         Vector!(T,size) res;
242         foreach(i; RangeTuple!(0, size))
243             res.arrayof[i] = cast(T)(arrayof[i] - t);
244         return res;
245     }
246 
247    /**
248     * Vector!(T,size) * T
249     */
250     Vector!(T,size) opBinary(string op)(T t) const if (op == "*")
251     do
252     {
253         Vector!(T,size) res;
254         foreach(i; RangeTuple!(0, size))
255             res.arrayof[i] = cast(T)(arrayof[i] * t);
256         return res;
257     }
258 
259    /**
260     * T * Vector!(T,size)
261     */
262     Vector!(T,size) opBinaryRight(string op) (T t) const
263         if (op == "*" && isNumeric!T)
264     do
265     {
266         Vector!(T,size) res;
267         foreach(i; RangeTuple!(0, size))
268             res.arrayof[i] = cast(T)(arrayof[i] * t);
269         return res;
270     }
271 
272    /**
273     * Vector!(T,size) / T
274     */
275     Vector!(T,size) opBinary(string op)(T t) const if (op == "/")
276     do
277     {
278         Vector!(T,size) res;
279         foreach(i; RangeTuple!(0, size))
280             res.arrayof[i] = cast(T)(arrayof[i] / t);
281         return res;
282     }
283 
284    /**
285     * Vector!(T,size) % T
286     */
287     Vector!(T,size) opBinary(string op, T2) (T2 t) const if (op == "%")
288     do
289     {
290         Vector!(T,size) res;
291         foreach(i; RangeTuple!(0, size))
292             res.arrayof[i] = cast(T)(arrayof[i] % t);
293         return res;
294     }
295 
296    /**
297     * Vector!(T,size) += Vector!(T,size)
298     */
299     Vector!(T,size) opOpAssign(string op)(Vector!(T,size) v) if (op == "+")
300     do
301     {
302         foreach(i; RangeTuple!(0, size))
303             arrayof[i] += v.arrayof[i];
304         return this;
305     }
306 
307    /**
308     * Vector!(T,size) -= Vector!(T,size)
309     */
310     Vector!(T,size) opOpAssign(string op)(Vector!(T,size) v) if (op == "-")
311     do
312     {
313         foreach(i; RangeTuple!(0, size))
314             arrayof[i] -= v.arrayof[i];
315         return this;
316     }
317 
318    /**
319     * Vector!(T,size) *= Vector!(T,size)
320     */
321     Vector!(T,size) opOpAssign(string op)(Vector!(T,size) v) if (op == "*")
322     do
323     {
324         foreach(i; RangeTuple!(0, size))
325             arrayof[i] *= v.arrayof[i];
326         return this;
327     }
328 
329    /**
330     * Vector!(T,size) /= Vector!(T,size)
331     */
332     Vector!(T,size) opOpAssign(string op)(Vector!(T,size) v) if (op == "/")
333     do
334     {
335         foreach(i; RangeTuple!(0, size))
336             arrayof[i] /= v.arrayof[i];
337         return this;
338     }
339 
340    /**
341     * Vector!(T,size) += T
342     */
343     Vector!(T,size) opOpAssign(string op)(T t) if (op == "+")
344     do
345     {
346         foreach(i; RangeTuple!(0, size))
347             arrayof[i] += t;
348         return this;
349     }
350 
351    /**
352     * Vector!(T,size) -= T
353     */
354     Vector!(T,size) opOpAssign(string op)(T t) if (op == "-")
355     do
356     {
357         foreach(i; RangeTuple!(0, size))
358             arrayof[i] -= t;
359         return this;
360     }
361 
362    /**
363     * Vector!(T,size) *= T
364     */
365     Vector!(T,size) opOpAssign(string op)(T t) if (op == "*")
366     do
367     {
368         foreach(i; RangeTuple!(0, size))
369             arrayof[i] *= t;
370         return this;
371     }
372 
373    /**
374     * Vector!(T,size) /= T
375     */
376     Vector!(T,size) opOpAssign(string op)(T t) if (op == "/")
377     do
378     {
379         foreach(i; RangeTuple!(0, size))
380             arrayof[i] /= t;
381         return this;
382     }
383 
384    /**
385     * Vector!(T,size) %= T
386     */
387     Vector!(T,size) opOpAssign(string op, T2)(T2 t) if (op == "%")
388     do
389     {
390         foreach(i; RangeTuple!(0, size))
391             arrayof[i] %= t;
392         return this;
393     }
394 
395    /**
396     * T = Vector!(T,size)[index]
397     */
398     auto ref T opIndex(this X)(size_t index)
399     in
400     {
401         assert ((0 <= index) && (index < size),
402             "Vector!(T,size).opIndex(int index): array index out of bounds");
403     }
404     do
405     {
406         return arrayof[index];
407     }
408 
409    /**
410     * Vector!(T,size)[index] = T
411     */
412     void opIndexAssign(T n, size_t index)
413     in
414     {
415         assert ((0 <= index) && (index < size),
416             "Vector!(T,size).opIndexAssign(int index): array index out of bounds");
417     }
418     do
419     {
420         arrayof[index] = n;
421     }
422 
423    /**
424     * T[] = Vector!(T,size)[index1..index2]
425     */
426     auto opSlice(this X)(size_t index1, size_t index2)
427     in
428     {
429         assert ((0 <= index1) || (index1 < 3) || (0 <= index2) || (index2 < 3) || (index1 < index2),
430             "Vector!(T,size).opSlice(int index1, int index2): array index out of bounds");
431     }
432     do
433     {
434         return arrayof[index1..index2];
435     }
436 
437    /**
438     * Vector!(T,size)[index1..index2] = T
439     */
440     T opSliceAssign(T t, size_t index1, size_t index2)
441     in
442     {
443         assert ((0 <= index1) || (index1 < 3) || (0 <= index2) || (index2 < 3) || (index1 < index2),
444             "Vector!(T,size).opSliceAssign(T t, int index1, int index2): array index out of bounds");
445     }
446     do
447     {
448         arrayof[index1..index2] = t;
449         return t;
450     }
451 
452    /**
453     * T = Vector!(T,size)[]
454     */
455     auto opSlice(this X)()
456     do
457     {
458         return arrayof[];
459     }
460 
461    /**
462     * Vector!(T,size)[] = T
463     */
464     T opSliceAssign(T t)
465     do
466     {
467         foreach(i; RangeTuple!(0, size))
468             arrayof[i] = t;
469         return t;
470     }
471 
472     static if (isNumeric!(T))
473     {
474        /**
475         * Get vector length squared
476         */
477         @property T lengthsqr() const
478         do
479         {
480             T res = 0;
481             foreach (component; arrayof)
482                 res += component * component;
483             return res;
484         }
485 
486        /**
487         * Get vector length
488         */
489         @property T length() const
490         do
491         {
492             static if (isFloatingPoint!T)
493             {
494                 T t = 0;
495                 foreach (component; arrayof)
496                     t += component * component;
497                 return sqrt(t);
498             }
499             else
500             {
501                 T t = 0;
502                 foreach (component; arrayof)
503                     t += component * component;
504                 return cast(T)sqrt(cast(float)t);
505             }
506         }
507 
508        /**
509         * Set vector length to 1
510         */
511         void normalize()
512         do
513         {
514             static if (isFloatingPoint!T)
515             {
516                 T lensqr = lengthsqr();
517                 if (lensqr > 0)
518                 {
519                     T coef = 1.0 / sqrt(lensqr);
520                     foreach (ref component; arrayof)
521                         component *= coef;
522                 }
523             }
524             else
525             {
526                 T lensqr = lengthsqr();
527                 if (lensqr > 0)
528                 {
529                     float coef = 1.0 / sqrt(cast(float)lensqr);
530                     foreach (ref component; arrayof)
531                         component = cast(T)(component * coef);
532                 }
533             }
534         }
535 
536        /**
537         * Return normalized copy
538         */
539         @property Vector!(T,size) normalized() const
540         do
541         {
542             Vector!(T,size) res = this;
543             res.normalize();
544             return res;
545         }
546 
547        /**
548         * Return true if all components are zero
549         */
550         @property bool isZero() const
551         do
552         {
553             foreach(i; RangeTuple!(0, size))
554                 if (arrayof[i] != 0)
555                     return false;
556             return true;
557         }
558 
559        /**
560         * Clamp components to min/max value
561         */
562         void clamp(T minv, T maxv)
563         {
564             foreach (ref v; arrayof)
565                 v = .clamp(v, minv, maxv);
566         }
567     }
568 
569    /**
570     * Convert to string
571     */
572     @property string toString() const
573     do
574     {
575         auto writer = appender!string();
576         formattedWrite(writer, "%s", arrayof);
577         return writer.data;
578     }
579 
580    /**
581     * Swizzling
582     */
583     template opDispatch(string s) if (valid(s))
584     {
585         static if (s.length <= 4)
586         {
587             private static auto extend(string s)
588             {
589                 while (s.length < 4)
590                     s ~= s[$-1];
591                 return s;
592             }
593 
594             unittest
595             {
596                 assert(extend("x") == "xxxx");
597             }
598 
599             @property auto ref opDispatch(this X)()
600             {
601                 enum p = extend(s);
602                 enum i = (char c) => ['x':0, 'y':1, 'z':2, 'w':3,
603                                       'r':0, 'g':1, 'b':2, 'a':3,
604                                       's':0, 't':1, 'p':2, 'q':3][c];
605                 enum i0 = i(p[0]),
606                      i1 = i(p[1]),
607                      i2 = i(p[2]),
608                      i3 = i(p[3]);
609 
610                 static if (s.length == 4)
611                     return Vector!(T,4)(arrayof[i0], arrayof[i1], arrayof[i2], arrayof[i3]);
612                 else static if (s.length == 3)
613                     return Vector!(T,3)(arrayof[i0], arrayof[i1], arrayof[i2]);
614                 else static if (s.length == 2)
615                     return Vector!(T,2)(arrayof[i0], arrayof[i1]);
616             }
617         }
618     }
619 
620     private static bool valid(string s)
621     {
622         if (s.length < 2)
623             return false;
624 
625         foreach(c; s)
626         {
627             switch(c)
628             {
629                 case 'w', 'a', 'q':
630                     if (size < 4) return false;
631                     else break;
632                 case 'z', 'b', 'p':
633                     if (size < 3) return false;
634                     else break;
635                 case 'y', 'g', 't':
636                     if (size < 2) return false;
637                     else break;
638                 case 'x', 'r', 's':
639                     if (size < 1) return false;
640                     else break;
641                 default:
642                     return false;
643             }
644         }
645         return true;
646     }
647 
648     unittest
649     {
650         static if (size == 3)
651         {
652             assert(valid("xyz"));
653             assert(valid("rgb"));
654             assert(valid("stp"));
655             assert(!valid("m"));
656             assert(!valid("km"));
657         }
658         else static if (size == 3)
659         {
660             assert(valid("xyzw"));
661             assert(valid("rgba"));
662             assert(valid("stpq"));
663         }
664     }
665 
666    /**
667     * Symbolic element access
668     */
669     private static string elements(string[4] letters) @property
670     do
671     {
672         string res;
673         foreach (i; 0..size)
674         {
675             res ~= "T " ~ letters[i] ~ "; ";
676         }
677         return res;
678     }
679 
680     unittest
681     {
682         static if (size == 3)
683         {
684             assert(elements(["x", "y", "z", "w"]) == "T x; T y; T z; ");
685         }
686     }
687 
688    /**
689     * Vector components
690     */
691     union
692     {
693         // Elements as static array
694         T[size] arrayof;
695 
696         static if (size < 5)
697         {
698             /// Elements as x, y, z, w
699             struct { mixin(elements(["x", "y", "z", "w"])); }
700 
701             /// Elements as r, g, b, a
702             struct { mixin(elements(["r", "g", "b", "a"])); }
703 
704             /// Elements as s, t, p, q
705             struct { mixin(elements(["s", "t", "p", "q"])); }
706         }
707     }
708 }
709 
710 ///
711 unittest
712 {
713     {
714         const vec3 a = vec3(10.5f, 20.0f, 33.12345f);
715         const vec3 b = -a;
716         const vec3 c = +a - b;
717         const vec3 d = a * b / c;
718 
719         assert(isAlmostZero(to!vec3(c.toString()) - c));
720 
721         const vec3 v = vec3(10, 10, 10);
722         const vec3 vRes = (v / 10) * 2 - 1 + 5;
723         assert(isAlmostZero(vRes - vec3(6, 6, 6)));
724         assert(!vRes.isZero);
725 
726         ivec2 ab = ivec2(5, 15);
727         ab += ivec2(20, 30);
728         ab *= 3;
729 
730         assert(ab[0] == 75 && ab[1] == 135);
731 
732         auto len = c.length();
733         auto lensqr = c.lengthsqr();
734         auto dist = distance(a, b);
735 
736         auto xy = a[0..1];
737         auto n = a[];
738 
739         vec3 v1 = vec3(2.0f, 0.0f, 1.0f);
740         ivec3 v2 = v1;
741         assert(ivec3(v1) == ivec3(2, 0, 1));
742 
743         vec3 v3 = [0, 2, 3.5];
744         assert(v3 == vec3(0.0f, 2.0f, 3.5f));
745 
746         ivec3 v4 = [7, 8, 3];
747         v4 %= 2;
748         assert(v4 == ivec3(1, 0, 1));
749     }
750 
751     {
752         Vector3f a = Vector3f(1, 2, 3);
753         Vector2f b = Vector2f(a);
754         assert(b == Vector2f(1, 2));
755     }
756 
757     {
758         Vector3f a = Vector3f([0, 1]);
759         assert(isNaN(a.z));
760     }
761 
762     {
763         Vector3f a = Vector3f(0, 1, 2);
764         a += 1;
765         assert(a == Vector3f(1, 2, 3));
766         a *= 2;
767         assert(a == Vector3f(2, 4, 6));
768         a -= 1;
769         assert(a == Vector3f(1, 3, 5));
770         a /= 3;
771         assert(a.y == 1);
772     }
773 
774     {
775         Vector3f a;
776         a[1] = 3;
777         assert(a.y == 3);
778 
779         a[0..3] = 1;
780         assert(a == Vector3f(1, 1, 1));
781 
782         a[] = 0;
783         assert(a == Vector3f(0, 0, 0));
784     }
785 
786     {
787         Vector3i a = Vector3i(0, 0, 3);
788         a = a.normalized;
789         assert(a == Vector3i(0, 0, 1));
790         assert(a.length == 1);
791     }
792 
793     {
794         Vector3f a = Vector3f(0, 0, 0);
795         assert(a.isZero);
796     }
797 
798     {
799         Vector3f a = Vector3f(2, -3, 0);
800         a.clamp(-1, 1);
801         assert(a == Vector3f(1, -1, 0));
802     }
803     
804     {
805         Vector3f a = Vector3f(2, 5, 7);
806         Vector4f b = Vector4f(a);
807         assert(b == Vector4f(2, 5, 7, float.nan));
808     }
809     
810     {
811         Vector3f a = Vector3f([0, 1]);
812         assert(a == Vector3f(0, 1, float.nan));
813         
814         Vector4f b = a.xyy;
815         assert(b == Vector4f(0, 1, 1, float.nan));
816     }
817     
818     {
819         Vector3f a = Vector3f(1, 2, 3);
820         a = a + 1;
821         assert(a == Vector3f(2, 3, 4));
822         a = a * 2;
823         assert(a == Vector3f(4, 6, 8));
824         a = a - 2;
825         assert(a == Vector3f(2, 4, 6));
826         a = a / 2;
827         assert(a == Vector3f(1, 2, 3));
828         
829         Vector3f b = Vector3f(3, 2, 1);
830         b += a;
831         assert(b == Vector3f(4, 4, 4));
832         b *= b;
833         assert(b == Vector3f(16, 16, 16));
834         b /= Vector3f(8, 4, 2);
835         assert(b == Vector3f(2, 4, 8));
836         b -= a;
837         assert(b == Vector3f(1, 2, 5));
838     }
839     
840     {
841         Vector3f v = Vector3f(0, 0, 0);
842         v[0] = 5;
843         v[1] = 2;
844         assert(v == Vector3f(5, 2, 0));
845         v[1..3] = 12;
846         assert(v == Vector3f(5, 12, 12));
847         v[] = 0;
848         assert(v == Vector3f(0, 0, 0));
849     }
850     
851     {
852         Vector4f a = Vector4f(2, 4, 6, 8);
853         Vector4f b = a.wxyz;
854         assert(b == Vector4f(8, 2, 4, 6));
855         float d = dot(a, b);
856         assert(d == 96.0f);
857     }
858     
859     {
860         Vector2f a = Vector2f(1, 2);
861         Vector2f b = Vector2f(2, 1);
862         float d = dot(a, b);
863         assert(d == 4.0f);
864     }
865 }
866 
867 /**
868  * Dot product
869  */
870 T dot(T, int size) (Vector!(T,size) a, Vector!(T,size) b)
871 do
872 {
873     static if (size == 1)
874     {
875         return a.x * b.x;
876     }
877     else
878     static if (size == 2)
879     {
880         return ((a.x * b.x) + (a.y * b.y));
881     }
882     else
883     static if (size == 3)
884     {
885         return ((a.x * b.x) + (a.y * b.y) + (a.z * b.z));
886     }
887     else
888     {
889         T d = 0;
890         //foreach (i; 0..size)
891         foreach(i; RangeTuple!(0, size))
892             d += a[i] * b[i];
893         return d;
894     }
895 }
896 
897 ///
898 unittest
899 {
900     Vector3f v = Vector3f(1, 0, 0);
901     assert(dot(v, v) == 1);
902 
903     Vector3f a = Vector3f(1, 2, 3, 4);
904     assert(dot(a, a) == 14);
905 }
906 
907 /**
908  * Cross product
909  */
910 Vector!(T,size) cross(T, int size) (Vector!(T,size) a, Vector!(T,size) b) if (size == 3)
911 do
912 {
913     return Vector!(T,size)
914     (
915         (a.y * b.z) - (a.z * b.y),
916         (a.z * b.x) - (a.x * b.z),
917         (a.x * b.y) - (a.y * b.x)
918     );
919 }
920 
921 /**
922  * Cross product for 4-vectors
923  */
924 Vector!(T,size) cross(T, int size) (Vector!(T,size) a, Vector!(T,size) b, Vector!(T,size) c) if (size == 4)
925 do
926 {
927     return Vector!(T,size)
928     (
929         (a.y * b.z * c.w) - (a.y * b.w * c.z)
930       + (a.z * b.w * c.y) - (a.z * b.y * c.w)
931       + (a.w * b.y * c.z) - (a.w * b.z * c.y),
932 
933         (a.z * b.w * c.x) - (a.z * b.x * c.w)
934       + (a.w * b.x * c.z) - (a.w * b.z * c.x)
935       + (a.x * b.z * c.w) - (a.x * b.w * c.z),
936 
937         (a.w * b.x * c.y) - (a.w * b.y * c.x)
938       + (a.x * b.y * c.w) - (a.x * b.w * c.y)
939       + (a.y * b.w * c.x) - (a.y * b.x * c.w),
940 
941         (a.x * b.y * c.z) - (a.x * b.z * c.y)
942       + (a.y * b.z * c.x) - (a.y * b.x * c.z)
943       + (a.z * b.x * c.y) - (a.z * b.y * c.x)
944     );
945 }
946 
947 /**
948  * Tensor product
949  */
950 Matrix!(T,N) tensorProduct(T, size_t N) (Vector!(T,N) u, Vector!(T,N) v)
951 do
952 {
953     Matrix!(T,N) res;
954     foreach(i; 0..N)
955     foreach(j; 0..N)
956     {
957         res[i, j] = u[i] * v[j];
958     }
959     return res;
960 }
961 
962 alias outerProduct = tensorProduct;
963 
964 /**
965  * Compute normal of a plane from three points
966  */
967 Vector!(T,3) planeNormal(T) (Vector!(T,3) p1, Vector!(T,3) p2, Vector!(T,3) p3)
968 do
969 {
970     Vector!(T,3) vec1 = Vector!(T,3)(p1 - p2);
971     Vector!(T,3) vec2 = Vector!(T,3)(p1 - p3);
972 
973     Vector!(T,3) result = Vector!(T,3)(cross(vec1,vec2));
974     result.normalize();
975 
976     return result;
977 }
978 
979 ///
980 unittest
981 {
982     Vector3f n = planeNormal(
983         Vector3f(0, 0, 0),
984         Vector3f(0, 0, 1),
985         Vector3f(1, 0, 0)
986     );
987     assert(isAlmostZero(n - Vector3f(0, 1, 0)));
988 }
989 
990 /**
991  *
992  */
993 void rotateAroundAxis(T) (ref Vector!(T,3) V, Vector!(T,3) P, Vector!(T,3) D, T angle)
994 {
995     T axx,axy,axz,ax1;
996     T ayx,ayy,ayz,ay1;
997     T azx,azy,azz,az1;
998 
999     T u,v,w;
1000     T u2,v2,w2;
1001     T a,b,c;
1002 
1003     T sa,ca;
1004 
1005     sa = sin(angle);
1006     ca = cos(angle);
1007 
1008     u = D.x;
1009     v = D.y;
1010     w = D.z;
1011 
1012     u2 = u * u;
1013     v2 = v * v;
1014     w2 = w * w;
1015 
1016     a = P.x;
1017     b = P.y;
1018     c = P.z;
1019 
1020     axx = u2+(v2+w2)*ca;
1021     axy = u*v*(1-ca)-w*sa;
1022     axz = u*w*(1-ca)+v*sa;
1023     ax1 = a*(v2+w2)-u*(b*v+c*w)+(u*(b*v+c*w)-a*(v2+w2))*ca+(b*w-c*v)*sa;
1024 
1025     ayx = u*v*(1-ca)+w*sa;
1026     ayy = v2+(u2+w2)*ca;
1027     ayz = v*w*(1-ca)-u*sa;
1028     ay1 = b*(u2+w2)-v*(a*u+c*w)+(v*(a*u+c*w)-b*(u2+w2))*ca+(c*u-a*w)*sa;
1029 
1030     azx = u*w*(1-ca)-v*sa;
1031     azy = v*w*(1-ca)+u*sa;
1032     azz = w2+(u2+v2)*ca;
1033 
1034     az1 = c*(u2+v2)-w*(a*u+b*v)+(w*(a*u+b*v)-c*(u2+v2))*ca+(a*v-b*u)*sa;
1035 
1036     Vector!(T,3) W;
1037     W.x = axx * V.x + axy * V.y + axz * V.z + ax1;
1038     W.y = ayx * V.x + ayy * V.y + ayz * V.z + ay1;
1039     W.z = azx * V.x + azy * V.y + azz * V.z + az1;
1040 
1041     V = W;
1042 }
1043 
1044 /**
1045  * Compute distance between two 2D points
1046  */
1047 T distance(T) (Vector!(T,2) a, Vector!(T,2) b)
1048 do
1049 {
1050     T dx = a.x - b.x;
1051     T dy = a.y - b.y;
1052     return sqrt((dx * dx) + (dy * dy));
1053 }
1054 
1055 /**
1056  * Compute squared distance between two 2D points
1057  */
1058 T distancesqr(T) (Vector!(T,2) a, Vector!(T,2) b)
1059 do
1060 {
1061     T dx = a.x - b.x;
1062     T dy = a.y - b.y;
1063     return ((dx * dx) + (dy * dy));
1064 }
1065 
1066 /**
1067  * Compute distance between two 3D points
1068  */
1069 T distance(T) (Vector!(T,3) a, Vector!(T,3) b)
1070 do
1071 {
1072     T dx = a.x - b.x;
1073     T dy = a.y - b.y;
1074     T dz = a.z - b.z;
1075     return sqrt((dx * dx) + (dy * dy) + (dz * dz));
1076 }
1077 
1078 /**
1079  * Compute squared distance between two 3D points
1080  */
1081 T distancesqr(T) (Vector!(T,3) a, Vector!(T,3) b)
1082 do
1083 {
1084     T dx = a.x - b.x;
1085     T dy = a.y - b.y;
1086     T dz = a.z - b.z;
1087     return ((dx * dx) + (dy * dy) + (dz * dz));
1088 }
1089 
1090 /**
1091  * Random unit length 2-vector
1092  */
1093 Vector!(T,2) randomUnitVector2(T)()
1094 {
1095     float azimuth = uniform(0.0, 1.0) * 2 * PI;
1096     return Vector!(T,2)(cos(azimuth), sin(azimuth));
1097 }
1098 
1099 /**
1100  * Random unit length 3-vector
1101  */
1102 Vector!(T,3) randomUnitVector3(T)()
1103 {
1104     float z = (2 * uniform(0.0, 1.0)) - 1;
1105     Vector!(T,2) planar = randomUnitVector2!(T)() * sqrt(1 - z * z);
1106     return Vector!(T,3)(planar.x, planar.y, z);
1107 }
1108 
1109 /**
1110  * Spherical linear interpolation
1111  * (simple lerp is in dlib.math.interpolation)
1112  */
1113 Vector!(T,3) slerp(T) (Vector!(T,3) a, Vector!(T,3) b, T t)
1114 {
1115     T dp = dot(a, b);
1116     dp = clamp(dp, -1.0, 1.0);
1117     T theta = acos(dp) * t;
1118     Vector!(T,3) relativeVec = b - a * dp;
1119     relativeVec.normalize();
1120     return ((a * cos(theta)) + (relativeVec * sin(theta)));
1121 }
1122 
1123 /**
1124  * Gradually decrease vector to zero length
1125  */
1126 Vector!(T,3) vectorDecreaseToZero(T) (Vector!(T,3) vector, T step)
1127 {
1128     foreach (ref component; vector.arrayof)
1129     {
1130         if (component > 0.0)
1131             component -= step;
1132         if (component < 0.0)
1133             component += step;
1134     }
1135     return vector;
1136 }
1137 
1138 /**
1139  * Is all elements almost zero
1140  */
1141 bool isAlmostZero(Vector3f v)
1142 {
1143     return (isConsiderZero(v.x) &&
1144             isConsiderZero(v.y) &&
1145             isConsiderZero(v.z));
1146 }
1147 
1148 /**
1149  *
1150  */
1151 Vector!(T,3) reflect(T)(Vector!(T,3) I, Vector!(T,3) N)
1152 {
1153     return I - N * dot(N, I) * 2.0;
1154 }
1155 
1156 /**
1157  *
1158  */
1159 Vector!(T,3) refract(T)(Vector!(T,3) I, Vector!(T,3) N, T r)
1160 {
1161     T d = 1.0 - r * r * (1.0 - dot(N, I) * dot(N, I));
1162     if (d < 0.0)
1163         return Vector!(T,3)(0.0, 0.0, 0.0);
1164     return I * r - N * (r * dot(N, I) + sqrt(d));
1165 }
1166 
1167 /**
1168  *
1169  */
1170 Vector!(T,3) faceforward(T)(Vector!(T,3) N, Vector!(T,3) I, Vector!(T,3) Nref)
1171 {
1172     return dot(Nref, I) < 0.0 ? N : -N;
1173 }
1174 
1175 /**
1176  * Predefined vector types
1177  */
1178 /// Alias for 2-vector of ints
1179 alias Vector2i = Vector!(int, 2);
1180 /// Alias for 2-vector of uints
1181 alias Vector2u = Vector!(uint, 2);
1182 /// Alias for 2-vector of floats
1183 alias Vector2f = Vector!(float, 2);
1184 /// Alias for 2-vector of doubles
1185 alias Vector2d = Vector!(double, 2);
1186 
1187 /// Alias for 3-vector of ints
1188 alias Vector3i = Vector!(int, 3);
1189 /// Alias for 3-vector of uints
1190 alias Vector3u = Vector!(uint, 3);
1191 /// Alias for 3-vector of floats
1192 alias Vector3f = Vector!(float, 3);
1193 /// Alias for 2-vector of doubles
1194 alias Vector3d = Vector!(double, 3);
1195 
1196 /// Alias for 4-vector of ints
1197 alias Vector4i = Vector!(int, 4);
1198 /// Alias for 4-vector of uints
1199 alias Vector4u = Vector!(uint, 4);
1200 /// Alias for 4-vector of floats
1201 alias Vector4f = Vector!(float, 4);
1202 /// Alias for 4-vector of doubles
1203 alias Vector4d = Vector!(double, 4);
1204 
1205 /**
1206  * GLSL-like short aliases
1207  */
1208 alias ivec2 = Vector2i;
1209 alias uvec2 = Vector2u;
1210 alias vec2 = Vector2f;
1211 alias dvec2 = Vector2d;
1212 
1213 alias ivec3 = Vector3i;
1214 alias uvec3 = Vector3u;
1215 alias vec3 = Vector3f;
1216 alias dvec3 = Vector3d;
1217 
1218 alias ivec4 = Vector4i;
1219 alias uvec4 = Vector4u;
1220 alias vec4 = Vector4f;
1221 alias dvec4 = Vector4d;
1222 
1223 /**
1224  * Axis vectors
1225  */
1226 static struct AxisVector
1227 {
1228     Vector3f x = Vector3f(1.0f, 0.0f, 0.0f);
1229     Vector3f y = Vector3f(0.0f, 1.0f, 0.0f);
1230     Vector3f z = Vector3f(0.0f, 0.0f, 1.0f);
1231 }
1232 
1233 /**
1234  * Vector factory function
1235  */
1236 auto vectorf(T...)(T t) if (t.length > 0)
1237 {
1238     return Vector!(float, t.length)(t);
1239 }
1240 
1241 /**
1242  * L-value pseudovector for assignment purposes.
1243  *
1244  * Examples:
1245  * --------------------
1246  * float a, b, c;
1247  * lvector(a, b, c) = Vector3f(10, 4, 2);
1248  * --------------------
1249  */
1250 auto lvector(T...)(ref T x)
1251 {
1252     struct Result(T, uint size)
1253     {
1254         T*[size] arrayof;
1255 
1256         void opAssign(int size2)(Vector!(T,size2) v)
1257         {
1258             if (v.arrayof.length >= size)
1259                 foreach(i; 0..size)
1260                     *arrayof[i] = v.arrayof[i];
1261             else
1262                 foreach(i; 0..v.arrayof.length)
1263                     *arrayof[i] = v.arrayof[i];
1264         }
1265     }
1266 
1267     auto res = Result!(typeof(x[0]), x.length)();
1268 
1269     foreach(i, ref v; x)
1270         res.arrayof[i] = &v;
1271 
1272     return res;
1273 }