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