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 }