1 
2 module ws.math.vector;
3 
4 import
5 	std.algorithm,
6 	std.range,
7 	std.math,
8 	std.traits,
9 	std.conv,
10 	ws.string;
11 
12 
13 T asqrt(T)(T n){
14 	static if(is(T == int))
15 		return cast(int)sqrt(cast(float)n);
16 	else
17 		return sqrt(n);
18 }
19 
20 ref T x(T)(T[] array){
21 	return array[0];
22 }
23 alias w = x;
24 
25 ref T y(T)(T[] array){
26 	return array[1];
27 }
28 alias h = y;
29 
30 ref T z(T)(T[] array){
31 	return array[2];
32 }
33 
34 
35 auto length(T)(T array) if(isStaticArray!T) {
36 	return asqrt(array[].map!"a^^2".sum);
37 }
38 
39 alias len = length;
40 
41 T normal(T)(T array) if(isStaticArray!T) {
42 	auto len = array.length;
43 	if(1/len == 1.0f/0.0f)
44 		len = 1;
45 	T res;
46 	foreach(i, n; array)
47 		res[i] = n/len;
48 	return res;
49 }
50 
51 
52 T dot(int N, T)(T[N] data, T[N] other){
53 	T result = 0;
54 	foreach(i, n; data)
55 		result += n*other[i];
56 	return result;
57 }
58 
59 T add(T)(T data, T other) if(isStaticArray!T) {
60 	T res;
61 	foreach(i, n; data)
62 		res[i] = n - other[i];
63 	return res;
64 }
65 
66 T sub(T)(T data, T other) if(isStaticArray!T) {
67 	T res;
68 	foreach(i, n; data)
69 		res[i] = n - other[i];
70 	return res;
71 }
72 
73 T[N] mul(int N, T)(T[N] data, T val){
74 	T[N] res;
75 	foreach(i, n; data)
76 		res[i] = n*val;
77 	return res;
78 }
79 
80 T[N] div(int N, T)(T[N] data, T val){
81 	T[N] res;
82 	foreach(i,d; data)
83 		res[i] = d/val;
84 	return res;
85 }
86 
87 
88 auto vec(Args...)(Args args){
89 	float[Args.length] data;
90 	foreach(i, a; args)
91 		data[i] = a;
92 	return Vector!(Args.length)(data);
93 }
94 
95 Vector!Size vec(size_t Size, Type)(Type[Size] data){
96 	return Vector!Size.from(data);
97 }
98 
99 
100 struct Vector(size_t Size = 3, Type = float) {
101 	
102 	this(Type[Size] data){
103 		this.data = data;
104 	}
105 	
106 	this(Type[] data){
107 		assert(data.length == Size);
108 		this.data = data;
109 	}
110 
111 	static Vector from(T)(T arg) if(isStaticArray!T) {
112 		Vector res;
113 		foreach(i, d; arg)
114 			res[i] = cast(Type)d;
115 		return res;
116 	}
117 
118 	static Vector from(T)(T arg) if(!isStaticArray!T) {
119 		Vector vec;
120 		vec.data = arg;
121 		return vec;
122 	}
123 
124 	auto opAssign(Type[Size] data){
125 		this.data = data;
126 	}
127 
128 	static if(Size==2){
129 		Type[Size] data = [0, 0];
130 		this(Type a, Type b){
131 			data = [a,b];
132 		}
133 	}
134 	
135 	static if(Size==3){
136 		Type[Size] data = [0, 0, 0];
137 		this(Type a, Type b, Type c){
138 			data = [a,b,c];
139 		}
140 	}
141 
142 	static if(Size==4){
143 		Type[Size] data = [0, 0, 0, 0];
144 		this(Type a, Type b, Type c, Type d){
145 			data = [a,b,c,d];
146 		}
147 	}
148 
149 	Type distance(Vector other){
150 		Type l = 0;
151 		for(size_t i=0; i<Size; ++i)
152 			l += (data[i]-other.data[i])*(data[i]-other.data[i]);
153 		return asqrt(l);
154 	}
155 	
156 	@property Type length(){
157 		Type f = 0;
158 		foreach(n; data)
159 			f += n*n;
160 		return asqrt(f);
161 	}
162 	
163 	static if(Size > 0)
164 	@property ref Type x(){
165 		return data[0];
166 	}
167 	
168 	static if(Size > 1)
169 	@property ref Type y(){
170 		return data[1];
171 	}
172 	
173 	static if(Size > 2)
174 	@property ref Type z(){
175 		return data[2];
176 	}
177 
178 	bool nan(){
179 		static if(is(Type == int))
180 			return false;
181 		else {
182 			foreach(n; data)
183 				if(!isFinite(n))
184 					return true;
185 			return false;
186 		}
187 	}
188 
189 	Type dot()(Vector other){
190 		Type result = 0;
191 		foreach(i, n; data)
192 			result += n*other[i];
193 		return result;
194 	}
195 	
196 	
197 	static Ttype dot(Ttype, Tsize)(Ttype[Tsize] a, Ttype[Tsize] b){
198 		Type r = 0;
199 		foreach(i, n; a)
200 			r += n*b[i];
201 		return r;
202 	}
203 	
204 	
205 	Vector cross()(Vector other) if(Size==3){
206 		return Vector(
207 			y*other.z - z*other.y,
208 			z*other.x - x*other.z,
209 			x*other.y - y*other.x
210 		);
211 	}
212 
213 	@property Vector normal(){
214 		auto len = length;
215 		if(len)
216 			return this / len;
217 		else
218 			return Vector();
219 	}
220 	
221 	ref Type opIndex(size_t idx){
222 		return data[idx];
223 	}
224 	
225 	Vector opUnary(string op)(){
226 		Vector o;
227 		foreach(i, n; data)
228 			mixin("o.data[i] = " ~ op ~ "n;");
229 		return o;
230 	}
231 	
232 	Type opBinary(string op: "*")(Vector other){
233 		return dot(other);
234 	}
235 	
236 	Vector!(Size+1) opBinary(string op: "~")(Type n){
237 		return Vector!(Size+1)(data ~ n);
238 	}
239 
240 	Vector opBinary(string op)(Vector other){
241 		Vector o;
242 		foreach(i, ref n; data)
243 			mixin("o[i] = n" ~ op ~ "other[i];");
244 		return o;
245 	}
246 	
247 	Vector opBinary(string op)(Type s){
248 		Vector o;
249 		foreach(i, ref n; data)
250 			mixin("o[i] = n" ~ op ~ "s;");
251 		return o;
252 	}
253 	
254 	Vector opOpAssign(string op, T)(T other){
255 		mixin("this = this " ~ op ~ " other;");
256 		return this;
257 	}
258 	
259 	
260 	string toString(){
261 		string s = "Vector!%(".tostring(Size);
262 		foreach(i, n; data)
263 			s ~= n.tostring(i==data.length-1 ? "": ", ");
264 		s ~= ")";
265 		return s;
266 	}
267 
268 	string to(T: string)(){
269 		return "Vector(" ~ data.to!string[1..$-2] ~ ")";
270 	}
271 
272 	Vector!(Size, T) to(T)(){
273 		Vector!(Size, T) r;
274 		foreach(i, n; data)
275 			r.data[i] = cast(T)n;
276 		return r;
277 	}
278 
279 
280 	alias data this;
281 
282 	
283 }