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 }