1 module viva.math.vector;
2 
3 // Based on https://github.com/CosmoMyst/CosmoMyst.Math/blob/master/source/cosmomyst/math/vector.d
4 // thanks code :)
5 
6 alias Vector1 = Vector!1;
7 alias Vector2 = Vector!2;
8 alias Vector3 = Vector!3;
9 alias Vector4 = Vector!4;
10 
11 /++
12  +
13  +/
14 struct Vector(ulong n)
15 if (n >= 1)
16 {
17     union
18     {
19         ///
20         float[n] v;
21 
22         struct
23         {
24             static if (n >= 1)
25             {
26                 ///
27                 float x;
28             }
29 
30             static if (n >= 2)
31             {
32                 ///
33                 float y;
34             }
35 
36             static if (n >= 3)
37             {
38                 ///
39                 float z;
40             }
41 
42             static if (n >= 4)
43             {
44                 ///
45                 float w;
46             }
47         }
48     }
49 
50     /++
51      +
52      +/
53     this(T...)(T values) pure nothrow @nogc
54     {
55         import viva.types.number : isNumber;
56 
57         static foreach (value; values)
58         {
59             static assert(isNumber!(typeof(value)), "all values must be numeric");
60         }
61 
62         static assert(values.length > 0, "no values provided");
63         static assert(values.length == 1 || values.length == n, "number of values must be either 1 or number of components");
64 
65         static if (values.length == 1)
66         {
67             static foreach (i; 0..n)
68             {
69                 v[i] = values[0];
70             }
71         }
72         else
73         {
74             static foreach (i, value; values)
75             {
76                 v[i] = value;
77             }
78         }
79     }
80 
81     /++
82      +
83      +/
84     auto ptr() pure const nothrow @nogc
85     {
86         return v.ptr;
87     }
88 
89     /++
90      +
91      +/
92     float length() pure const nothrow @nogc
93     {
94         import std.math : sqrt;
95 
96         float sum = 0;
97         for (int i = 0; i < n; i++)
98         {
99             sum += v[i] * v[i];
100         }
101 
102         return sqrt(sum);
103     }
104 
105     /++
106      +
107      +/
108     void normalize() pure nothrow @nogc
109     {
110         this = normalized();
111     }
112 
113     /++
114      +
115      +/
116     Vector!n normalized() pure const nothrow @nogc
117     {
118         if (length() == 0)
119         {
120             return Vector!n(0f);
121         }
122 
123         return this / length();
124     }
125 
126     /++
127      +
128      +/
129     Vector!n opBinary(string op)(in float scalar) @nogc
130     const if (op == "/")
131     {
132         Vector!n res;
133 
134         for (int i = 0; i < n; i++)
135         {
136             res.v[i] = v[i] / scalar;
137         }
138 
139         return res;
140     }
141 
142     /++
143      +
144      +/
145     void opOpAssign(string op)(in float scalar) @nogc
146     const if (s == "/")
147     {
148         auto res = this / scalar;
149         this.v = res.v;
150     }
151 }