1 /**
2  * Type and dimension generic Vector backed by a static array.
3  */
4 module bettercmath.vector;
5 
6 import std.algorithm : among, copy, max, min, sum;
7 import std.meta;
8 import std.range;
9 import std.traits;
10 
11 import bettercmath.cmath;
12 import bettercmath.misc : FloatType;
13 /// `lerp` function for UFCS
14 public import bettercmath.misc : lerp;
15 
16 @safe @nogc nothrow:
17 
18 version (unittest)
19 {
20     private alias Vec1 = Vector!(float, 1);
21     private alias Vec2 = Vector!(float, 2);
22     private alias Vec2i = Vector!(int, 2);
23     private alias Vec2ub = Vector!(ubyte, 2);
24     private alias Vec3 = Vector!(float, 3);
25     private alias Vec4 = Vector!(float, 4);
26     private alias Vec4bool = Vector!(bool, 4);
27     private struct OtherVec2
28     {
29         float x;
30         float y;
31     }
32     private struct NotAVec2
33     {
34         float i;
35         string t;
36     }
37 }
38 
39 private template VectorStruct(U)
40 if (is(U == struct))
41 {
42     private alias FieldTypes = Fields!U;
43     alias ElementType = FieldTypes[0];
44     private enum isElementType(T) = is(T == ElementType);
45     enum isVectorStruct = allSatisfy!(isElementType, FieldTypes);
46     enum fieldNames = FieldNameTuple!U;
47     enum length = fieldNames.length;
48 }
49 
50 
51 /**
52  * Generic Vector backed by a static array.
53  * 
54  * Params:
55  *   T = Element type
56  *   N = Vector dimension, must be positive
57  */
58 struct Vector(T, uint N)
59 if (N > 0)
60 {
61     /// Alias for Vector element type.
62     alias ElementType = T;
63     /// Vector dimension.
64     enum dimension = N;
65     /// Element array.
66     T[N] elements = 0;
67     alias elements this;
68 
69     ref inout(T) _get(size_t i)() inout pure
70     in { assert(i < N, "Index out of bounds"); }
71     do
72     {
73         return elements[i];
74     }
75     ref inout(T[to - from]) _slice(size_t from, size_t to)() inout pure
76     in { assert(from <= N - 1 && to <= N, "Index out of bounds"); }
77     do
78     {
79         return elements[from .. to];
80     }
81 
82     /// Get a reference to first element.
83     alias x = _get!(0);
84     /// Ditto
85     alias r = x;
86     /// Ditto
87     alias u = x;
88     /// Ditto
89     alias s = x;
90     /// Ditto
91     alias width = x;
92 
93     static if (N >= 2)
94     {
95         /// Get a reference to second element.
96         alias y = _get!(1);
97         /// Ditto
98         alias g = y;
99         /// Ditto
100         alias v = y;
101         /// Ditto
102         alias t = y;
103         /// Ditto
104         alias height = y;
105 
106         /// Get a reference to the first and second elements.
107         alias xy = _slice!(0, 2);
108         /// Ditto
109         alias rg = xy;
110         /// Ditto
111         alias uv = xy;
112         /// Ditto
113         alias st = xy;
114     }
115     static if (N >= 3)
116     {
117         /// Get a reference to third element.
118         alias z = _get!(2);
119         /// Ditto
120         alias b = z;
121         /// Ditto
122         alias p = z;
123         /// Ditto
124         alias depth = z;
125 
126         /// Get a reference to the second and third elements.
127         alias yz = _slice!(1, 3);
128         /// Ditto
129         alias gb = yz;
130         /// Ditto
131         alias tp = yz;
132 
133         /// Get a reference to the first, second and third elements.
134         alias xyz = _slice!(0, 3);
135         /// Ditto
136         alias rgb = xyz;
137         /// Ditto
138         alias stp = xyz;
139     }
140     static if (N >= 4)
141     {
142         /// Get a reference to fourth element.
143         alias w = _get!(3);
144         /// Ditto
145         alias a = w;
146         /// Ditto
147         alias q = w;
148 
149         /// Get a reference to the third and fourth elements.
150         alias zw = _slice!(2, 4);
151         /// Ditto
152         alias ba = zw;
153         /// Ditto
154         alias pq = zw;
155 
156         /// Get a reference to the second, third and fourth elements.
157         alias yzw = _slice!(1, 4);
158         /// Ditto
159         alias gba = yzw;
160         /// Ditto
161         alias tpq = yzw;
162 
163         /// Get a reference to the first, second, third and fourth elements.
164         alias xyzw = _slice!(0, 4);
165         /// Ditto
166         alias rgba = xyzw;
167         /// Ditto
168         alias stpq = xyzw;
169     }
170 
171     unittest
172     {
173         Vec2 v = [1, 2];
174         assert(v.x == 1);
175         assert(v.x == v[0]);
176         assert(v.y == 2);
177         assert(v.y == v[1]);
178         v.x = 2;
179         assert(v.r == 2);
180 
181         Vec4 v2 = [1, 2, 3, 4];
182         assert(v2.xy == [1, 2]);
183         assert(v2.yz == [2, 3]);
184         assert(v2.zw == [3, 4]);
185         v2.xyz = 0;
186         assert(v2 == [0, 0, 0, 4]);
187     }
188 
189     /// Constructs a Vector with all elements equal to `scalar`
190     this(const T scalar) pure
191     {
192         elements[] = scalar;
193     }
194     ///
195     unittest
196     {
197         alias Vec2 = Vector!(float, 2);
198         Vec2 v;
199         v = Vec2(1);
200         assert(v == [1, 1]);
201         v = Vec2(2.0);
202         assert(v == [2, 2]);
203         v = Vec2(3.0f);
204         assert(v == [3, 3]);
205     }
206     /// Constructs a Vector from static array.
207     this()(const auto ref T[N] values) pure
208     {
209         elements = values;
210     }
211     ///
212     unittest
213     {
214         alias Vec2 = Vector!(float, 2);
215         Vec2 v;
216         v = Vec2([1, 2]);
217         assert(v == [1f, 2f]);
218         v = Vec2([2.0, 3.0]);
219         assert(v == [2f, 3f]);
220         v = Vec2([3.0f, 4.0f]);
221         assert(v == [3f, 4f]);
222     }
223     /// Constructs a Vector with elements from an Input Range.
224     /// Values not provided by `range` are initialized to 0,
225     /// while additional values are ignored.
226     this(R)(auto ref R range)
227     if (isInputRange!R)
228     {
229         auto remainder = range.take(N).copy(elements[]);
230         remainder[] = 0;
231     }
232     ///
233     unittest
234     {
235         float[] values = [1, 2];
236         assert(Vec4(values) == [1, 2, 0, 0]);
237 
238         import std.range : iota, stride;
239         assert(Vec4(iota(4)) == [0, 1, 2, 3]);
240         assert(Vec4(iota(8).stride(2)) == [0, 2, 4, 6]);
241         assert(Vec4(iota(6)) == [0, 1, 2, 3]);
242 
243         import std.algorithm : map;
244         auto isEven = iota(1024).map!(x => x % 2 == 0);
245         assert(Vec4bool(isEven) == [true, false, true, false]);
246     }
247     /// Constructs a Vector from a Vector-like struct.
248     this(U)(const auto ref U value)
249     if (is(U == struct) && VectorStruct!U.isVectorStruct)
250     {
251         alias vectorStruct = VectorStruct!U;
252         static foreach (i; 0 .. min(vectorStruct.length, N))
253         {
254             elements[i] = cast(T) mixin("value." ~ vectorStruct.fieldNames[i]);
255         }
256         static if (vectorStruct.length < N)
257         {
258             elements[vectorStruct.length .. N] = 0;
259         }
260     }
261     ///
262     unittest
263     {
264         Vec2 v = OtherVec2(2, 3);
265         assert(v == Vec2(2, 3));
266         Vec4 v4 = OtherVec2(4, 5);
267         assert(v4 == Vec4(4, 5, 0, 0));
268         assert(!__traits(compiles, { Vec2 v = NotAVec2(); }));
269     }
270     /// Constructs a Vector with all elements initialized separately
271     this(Args...)(const auto ref Args args)
272     if (args.length > 1 && args.length <= N)
273     {
274         foreach (i, value; args)
275         {
276             elements[i] = cast(T) value;
277         }
278         static if (Args.length < N)
279         {
280             elements[Args.length .. N] = 0;
281         }
282     }
283     ///
284     unittest
285     {
286         Vec3 v;
287         v = Vec3(1, 2);
288         assert(v == [1, 2, 0]);
289         v = Vec3(1, 2, 3);
290         assert(v == [1, 2, 3]);
291     }
292 
293 pure:
294     /// Vector with all zeros
295     enum Vector zeros = 0;
296     alias zeroes = zeros;
297     /// Vector with all ones
298     enum Vector ones = 1;
299 
300     /// Returns a new vector with unary operator applied to all elements
301     Vector opUnary(string op)() const
302     if (op.among("-", "+", "~"))
303     {
304         Vector result;
305         mixin(q{result =} ~ op ~ q{elements[];});
306         return result;
307     }
308     ///
309     unittest
310     {
311         assert(-Vec2(1, -2) == [-1, 2]);
312     }
313 
314     /// Returns a new vector with binary operator applied to all elements and `scalar`
315     Vector opBinary(string op)(const T scalar) const
316     if (!op.among("~", "<<", ">>", ">>>"))
317     {
318         Vector result;
319         mixin(q{result = elements[]} ~ op ~ q{scalar;});
320         return result;
321     }
322     /// Ditto
323     auto opBinary(string op, U)(const U scalar) const
324     if (!is(U : T) && !is(CommonType!(U, T) == void) && !op.among("~", "<<", ">>", ">>>"))
325     {
326         mixin(q{alias resultType = typeof(cast(T)(1) } ~ op ~ q{ cast(U)(1));});
327         Vector!(CommonType!(T, U), N) result;
328         foreach (i; 0 .. N)
329         {
330             result[i] = mixin(q{elements[i] } ~ op ~ q{ scalar});
331         }
332         return result;
333     }
334     ///
335     unittest
336     {
337         Vec2 a = [1, 2];
338         assert(a + 1 == [1f + 1f, 2f + 1f]);
339         assert(a - 1 == [1f - 1f, 2f - 1f]);
340         assert(a * 2 == [1f * 2f, 2f * 2f]);
341         assert(a / 2 == [1f / 2f, 2f / 2f]);
342         assert(a % 2 == [1f % 2f, 2f % 2f]);
343         assert(a ^^ 2 == [1f ^^ 2f, 2f ^^ 2f]);
344 
345         Vec2i b = [1, 2];
346         assert((b & 1) == [1 & 1, 2 & 1]);
347         assert((b | 1) == [1 | 1, 2 | 1]);
348         assert((b ^ 1) == [1 ^ 1, 2 ^ 1]);
349     }
350     // TODO: shift operations
351 
352     /// Returns a new vector with binary operator applied to all elements and `scalar`
353     Vector opBinaryRight(string op)(const T scalar) const
354     if (!op.among("~", "<<", ">>", ">>>"))
355     {
356         Vector result;
357         mixin(q{result = scalar} ~ op ~ q{elements[];});
358         return result;
359     }
360     /// Ditto
361     auto opBinaryRight(string op, U)(const U scalar) const
362     if (!is(U : T) && !is(CommonType!(U, T) == void) && !op.among("~", "<<", ">>", ">>>"))
363     {
364         mixin(q{alias resultType = typeof(cast(U)(1) } ~ op ~ q{ cast(T)(1));});
365         Vector!(CommonType!(T, U), N) result;
366         foreach (i; 0 .. N)
367         {
368             result[i] = mixin(q{scalar } ~ op ~ q{ elements[i]});
369         }
370         return result;
371     }
372     ///
373     unittest
374     {
375         Vec2 a = [1, 2];
376         assert(1 + a == [1f + 1f, 1f + 2f]);
377         assert(1 - a == [1f - 1f, 1f - 2f]);
378         assert(2 * a == [2f * 1f, 2f * 2f]);
379         assert(2 / a == [2f / 1f, 2f / 2f]);
380         assert(2 % a == [2f % 1f, 2f % 2f]);
381         assert(2 ^^ a == [2f ^^ 1f, 2f ^^ 2f]);
382 
383         Vec2i b = [1, 2];
384         assert((1 & b) == [1 & 1, 1 & 2]);
385         assert((1 | b) == [1 | 1, 1 | 2]);
386         assert((1 ^ b) == [1 ^ 1, 1 ^ 2]);
387     }
388 
389     /// Returns a new vector with the results of applying operator against elements of `other`.
390     /// If operands dimensions are unequal, copies the values from greater dimension vector.
391     Vector!(T, max(N, M)) opBinary(string op, uint M)(const auto ref T[M] other) const
392     if (op != "~")
393     {
394         enum minDimension = min(N, M);
395         typeof(return) result;
396         mixin(q{result[0 .. minDimension] = elements[0 .. minDimension]} ~ op ~ q{other[0 .. minDimension];});
397         static if (M < N)
398         {
399             result[minDimension .. N] = elements[minDimension .. N];
400         }
401         else static if (N < M)
402         {
403             result[minDimension .. M] = other[minDimension .. M];
404         }
405         return result;
406     }
407     /// Ditto
408     Vector!(CommonType!(U, T), max(N, M)) opBinary(string op, U, uint M)(const auto ref U[M] other) const
409     if (!is(CommonType!(U, T) == void) && op != "~")
410     {
411         enum minDimension = min(N, M);
412         typeof(return) result;
413         foreach (i; 0 .. minDimension)
414         {
415             mixin(q{result[i] = elements[i] } ~ op ~ q{ other[i];});
416         }
417         static if (M < N)
418         {
419             result[minDimension .. N] = elements[minDimension .. N];
420         }
421         else static if (N < M)
422         {
423             result[minDimension .. M] = other[minDimension .. M];
424         }
425         return result;
426     }
427     ///
428     unittest
429     {
430         assert(Vec2(1, 2) + Vec2(3, 4) == [1f+3f, 2f+4f]);
431         assert(Vec2(1, 2) - Vec2(3, 4) == [1f-3f, 2f-4f]);
432         assert(Vec2(1, 2) * Vec2(3, 4) == [1f*3f, 2f*4f]);
433         assert(Vec2(1, 2) / Vec2(3, 4) == [1f/3f, 2f/4f]);
434         assert(__traits(compiles, Vec2(1, 2) + [3, 4]));
435 
436         assert(Vec2(1, 2) + Vec1(3) == [1f+3f, 2f]);
437         assert(Vec2(1, 2) - Vec1(3) == [1f-3f, 2f]);
438         assert(Vec2(1, 2) * Vec1(3) == [1f*3f, 2f]);
439         assert(Vec2(1, 2) / Vec1(3) == [1f/3f, 2f]);
440 
441         assert(Vec2(1, 2) + Vec3(3, 4, 5) == [1f+3f, 2f+4f, 5f]);
442         assert(Vec2(1, 2) - Vec3(3, 4, 5) == [1f-3f, 2f-4f, 5f]);
443         assert(Vec2(1, 2) * Vec3(3, 4, 5) == [1f*3f, 2f*4f, 5f]);
444         assert(Vec2(1, 2) / Vec3(3, 4, 5) == [1f/3f, 2f/4f, 5f]);
445 
446         assert(Vec2i(1, 2) + Vec2(3, 4) == [1+3f, 2+4f]);
447     }
448 
449     /// Returns a new vector with the results of applying operator against elements of `other`.
450     /// If operands dimensions are unequal, copies the values from greater dimension vector.
451     Vector!(CommonType!(U, T), max(N, M)) opBinaryRight(string op, U, uint M)(const auto ref U[M] other) const
452     if (!is(CommonType!(U, T) == void) && op != "~")
453     {
454         enum minDimension = min(N, M);
455         typeof(return) result;
456         foreach (i; 0 .. minDimension)
457         {
458             mixin(q{result[i] = other[i] } ~ op ~ q{ elements[i];});
459         }
460         static if (M < N)
461         {
462             result[minDimension .. N] = elements[minDimension .. N];
463         }
464         else static if (N < M)
465         {
466             result[minDimension .. M] = other[minDimension .. M];
467         }
468         return result;
469     }
470 
471     /// Returns a new vector of greater dimension by copying elements and appending `scalar`.
472     Vector!(T, N + 1) opBinary(string op : "~")(const T scalar) const
473     {
474         typeof(return) result;
475         result[0 .. N] = elements[];
476         result[N] = scalar;
477         return result;
478     }
479     ///
480     unittest
481     {
482         Vec2 v = [1, 2];
483         assert(v ~ 3 == Vec3(1, 2, 3));
484     }
485     /// Returns a new vector of greater dimension by copying elements and prepending `scalar`.
486     Vector!(T, N + 1) opBinaryRight(string op : "~")(const T scalar) const
487     {
488         typeof(return) result;
489         result[0] = scalar;
490         result[1 .. N + 1] = elements[];
491         return result;
492     }
493     ///
494     unittest
495     {
496         Vec2 v = [1, 2];
497         Vec3 v2 = 0f ~ v;
498         assert(0 ~ v == Vec3(0, 1, 2));
499     }
500 
501     /// Returns a new vector of greater dimension by copying elements and appending values from `other`.
502     Vector!(T, N + M) opBinary(string op : "~", uint M)(const auto ref T[M] other) const
503     {
504         typeof(return) result = elements ~ other;
505         return result;
506     }
507     ///
508     unittest
509     {
510         Vec2 v1 = [1, 2];
511         assert(v1 ~ [3f, 4f] == Vec4(1, 2, 3, 4));
512         assert(v1 ~ Vec2(3f, 4f) == Vec4(1, 2, 3, 4));
513     }
514     /// Returns a new vector of greater dimension by copying elements and prepending values from `other`.
515     Vector!(T, N + M) opBinaryRight(string op : "~", uint M)(const auto ref T[M] other) const
516     {
517         typeof(return) result = other ~ elements;
518         return result;
519     }
520     ///
521     unittest
522     {
523         Vec2 v1 = [1, 2];
524         assert([3f, 4f] ~ v1 == Vec4(3, 4, 1, 2));
525         assert(Vec2(3f, 4f) ~ v1 == Vec4(3, 4, 1, 2));
526     }
527 
528     /// Cast to a static array of same dimension, but different element type.
529     U opCast(U : T2[N], T2)() const
530     {
531         typeof(return) result;
532         foreach (i; 0 .. N)
533         {
534             result[i] = cast(T2) elements[i];
535         }
536         return result;
537     }
538     ///
539     unittest
540     {
541         Vec2i intVec = [1, 2];
542         auto floatVec = cast(Vec2) intVec;
543         assert(floatVec == Vec2(1f, 2f));
544         assert(floatVec == intVec);
545 
546         auto floatArray = cast(float[2]) intVec;
547         assert(floatArray == [1f, 2f]);
548         assert(floatArray == intVec);
549     }
550 
551     /// Cast to a Vector-like struct.
552     U opCast(U)() const
553     if (is(U == struct) && VectorStruct!U.isVectorStruct)
554     {
555         alias vectorStruct = VectorStruct!U;
556         typeof(return) result;
557         static foreach (i; 0 .. min(vectorStruct.length, N))
558         {
559             mixin("result." ~ vectorStruct.fieldNames[i]) = cast(vectorStruct.ElementType) elements[i];
560         }
561         return result;
562     }
563     ///
564     unittest
565     {
566         immutable Vec2 five = 5;
567         OtherVec2 otherFive = cast(OtherVec2) five;
568         assert(otherFive == OtherVec2(5, 5));
569         assert(!__traits(compiles, { auto v = cast(NotAVec2) five; }));
570     }
571 
572     /// Assign result of applying operator with `scalar` to elements.
573     ref Vector opOpAssign(string op)(const T scalar) return
574     if (!op.among("~", "<<", ">>", ">>>"))
575     {
576         mixin(q{elements[] } ~ op ~ q{= scalar;});
577         return this;
578     }
579     ///
580     unittest
581     {
582         Vec2i v = [1, 2];
583         v += 5;
584         assert(v == [6, 7]);
585         v -= 4;
586         assert(v == [2, 3]);
587         v *= -1;
588         assert(v == [-2, -3]);
589         v %= 3;
590         assert(v == [-2, 0]);
591         v |= 1;
592         assert(v == [-1, 1]);
593         v /= 2;
594         assert(v == [0, 0]); // integer division
595     }
596     /// Assign result of applying operator with `other` to elements.
597     ref Vector opOpAssign(string op, uint M)(const auto ref T[M] other) return
598     if (!op.among("~", "<<", ">>", ">>>"))
599     {
600         enum minDimension = min(N, M);
601         mixin(q{elements[0 .. minDimension] } ~ op ~ q{= other[0 .. minDimension];});
602         return this;
603     }
604     ///
605     unittest
606     {
607         Vec3 v = [1, 2, 3];
608         v += Vec2(1, 2);
609         assert(v == [2, 4, 3]);
610 
611         v += Vec4(1, 2, 3, 4);
612         assert(v == [3, 6, 6]);
613     }
614 
615     unittest
616     {
617         assert(Vec2.sizeof == Vec2.elements.sizeof);
618         assert(Vec3.sizeof == Vec3.elements.sizeof);
619         assert(Vec4.sizeof == Vec4.elements.sizeof);
620 
621         alias Vec2_100 = Vec2[100];
622         assert(Vec2_100.sizeof == 100 * Vec2.elements.sizeof);
623 
624         auto v = Vec2(5);
625         v += 3;
626         assert(v == Vec2(8));
627     }
628 }
629 
630 /// True if `T` is some kind of Vector
631 enum isVector(T) = is(T : Vector!U, U...);
632 
633 /// Construct Vector directly from static array, inferring element type.
634 Vector!(T, N) vector(T, uint N)(const auto ref T[N] elements)
635 {
636     return typeof(return)(elements);
637 }
638 ///
639 unittest
640 {
641     auto v = [1, 2, 3].vector;
642     assert(v.elements == [1, 2, 3]);
643     assert(is(typeof(v) == Vector!(int, 3)));
644 }
645 
646 /// Construct Vector directly from elements, inferring element type.
647 Vector!(CommonType!Args, Args.length) vector(Args...)(const auto ref Args args)
648 if (!is(CommonType!Args == void))
649 {
650     return typeof(return)(args);
651 }
652 ///
653 unittest
654 {
655     auto v = vector(1f, 2, 3);
656     assert(is(typeof(v) == Vector!(float, 3)));
657     assert(v == [1f, 2f, 3f]);
658 }
659 
660 /// Returns the dot product between two Vectors.
661 T dot(T, uint N)(const auto ref Vector!(T, N) a, const auto ref Vector!(T, N) b) pure
662 {
663     auto multiplied = a * b;
664     return multiplied[].sum;
665 }
666 
667 /// Returns the cross product between two 3D Vectors.
668 Vector!(T, 3) cross(T)(const auto ref Vector!(T, 3) a, const auto ref Vector!(T, 3) b) pure
669 {
670     typeof(return) result = [
671         a.y * b.z - a.z * b.y,
672         a.z * b.x - a.x * b.z,
673         a.x * b.y - a.y * b.x,
674     ];
675     return result;
676 }
677 
678 /// Returns a Vector that is the reflection of `vec` against `normal`.
679 Vector!(T, N) reflect(T, uint N)(const auto ref Vector!(T, N) vec, const auto ref Vector!(T, N) normal) pure
680 {
681     return vec - (2 * normal * dot(vec, normal));
682 }
683 
684 /// Returns the squared magnitude (Euclidean length) of a Vector.
685 T magnitudeSquared(T, uint N)(const auto ref Vector!(T, N) vec) pure
686 out (r) { assert(r >= 0, "Vector squared magnitude should be non-negative!"); }
687 do
688 {
689     return dot(vec, vec);
690 }
691 ///
692 unittest
693 {
694     assert(Vec2(0, 0).magnitudeSquared() == 0);
695     assert(Vec2(1, 0).magnitudeSquared() == 1);
696     assert(Vec2(0, 1).magnitudeSquared() == 1);
697     assert(Vec2(1, 1).magnitudeSquared() == 2);
698     assert(Vec2(2, 0).magnitudeSquared() == 4);
699     assert(Vec2(1, 2).magnitudeSquared() == 5);
700 }
701 
702 /// Returns the magnitude (Euclidean length) of a Vector.
703 auto magnitude(T, uint N)(const auto ref Vector!(T, N) vec)
704 out (r) { assert(r >= 0, "Vector magnitude should be non-negative!"); }
705 do
706 {
707     return sqrt(vec.magnitudeSquared());
708 }
709 ///
710 unittest
711 {
712     assert(Vec2(0, 0).magnitude() == 0);
713     assert(Vec2(1, 0).magnitude() == 1);
714     assert(Vec2(0, 1).magnitude() == 1);
715     assert(Vec2(1, 1).magnitude() == sqrt(2f));
716     assert(Vec2(2, 0).magnitude() == 2);
717 }
718 
719 /// Normalize a Vector inplace.
720 ref Vector!(T, N) normalize(T, uint N)(ref return Vector!(T, N) vec)
721 {
722     auto sqMag = vec.magnitudeSquared();
723     if (sqMag != 0)
724     {
725         enum FloatType!T one = 1;
726         const auto inverseMag = one / sqrt(sqMag);
727         vec *= inverseMag;
728     }
729     return vec;
730 }
731 ///
732 unittest
733 {
734     Vec2 v = [5, 0];
735     v.normalize();
736     assert(v == Vec2(1, 0));
737 }
738 
739 /// Returns a normalized copy of Vector.
740 Vector!(T, N) normalized(T, uint N)(const auto ref Vector!(T, N) vec)
741 {
742     typeof(return) copy = vec;
743     return copy.normalize();
744 }
745 ///
746 unittest
747 {
748     Vec2 v = [200, 0];
749     assert(v.normalized() == Vec2(1, 0));
750     assert(v == Vec2(200, 0));
751 }
752 
753 unittest
754 {
755     Vec2 a = [1, 1];
756     Vec2 b = [2, 3];
757     assert(lerp(a, b, 0) == a);
758     assert(lerp(a, b, 0.5) == Vec2(1.5, 2));
759     assert(lerp(a, b, 1) == b);
760 
761     Vec2ub c1 = [0, 0];
762     Vec2ub c2 = [255, 255];
763     assert(lerp(c1, c2, 0) == c1);
764     assert(lerp(c1, c2, 1) == c2);
765     assert(lerp(c1, c2, 0.5) == Vec2ub(127, 127));
766 }