Created
April 5, 2018 17:16
-
-
Save run-dlang/0f97f0181c4efbbdc76e257311ed53a2 to your computer and use it in GitHub Desktop.
Code shared from run.dlang.io.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| void main() | |
| { | |
| import std.stdio; | |
| (vec2(1,5)-ivec2(9,9)).writeln; | |
| } | |
| struct Vector(T, int N) | |
| { | |
| import std.traits : CommonType, isNumeric; | |
| T[N] data; | |
| this(Args...)(Args args) | |
| { | |
| static foreach (i, arg; args) | |
| data[i] = cast(T)arg; | |
| } | |
| template opDispatch(string swizzle) | |
| { | |
| @property @safe pure: | |
| enum len = swizzle.length; | |
| enum ubyte[len+1] indicies = swizzleIndicies!len(swizzle); | |
| static assert(indicies[len] == 1, "'" ~ swizzle ~ "' is invalid swizzling"); | |
| ref T opDispatch()() if (len == 1) { | |
| return data[indicies[0]]; | |
| } | |
| auto opDispatch()() if (len > 1) { | |
| Vector!(T, len) result; | |
| static foreach (i, elemIndex; indicies[0..$-1]) | |
| result.data[i] = data[elemIndex]; | |
| return result; | |
| } | |
| auto opDispatch()(Vector!(T, len) other) if (len > 1) { | |
| Vector!(T, len) result; | |
| static foreach (i, elemIndex; indicies[0..$-1]) | |
| result.data[i] = data[elemIndex] = other.data[i]; | |
| return result; | |
| } | |
| } | |
| Vector!(T, N) opUnary(string op)() if (op != "++" && op != "--" && op != "*") | |
| { | |
| Vector!(T, N) result; | |
| foreach(i; 0..N) result.data[i] = mixin(op~"data[i]"); | |
| return result; | |
| } | |
| Vector!(T, N) opUnary(string op)() if (op == "++" || op == "--") | |
| { | |
| Vector!(T, N) result; | |
| foreach(i; 0..N) result.data[i] = mixin(op~"data[i]"); | |
| return result; | |
| } | |
| template opBinary(string op, T2 : Vector!(T3, N), T3) { | |
| alias RetT = CommonType!(T, T3); | |
| Vector!(RetT, N) opBinary(T2 rhs) | |
| { | |
| Vector!(RetT, N) result; | |
| foreach(i; 0..N) result.data[i] = mixin("data[i] "~op~" rhs.data[i]"); | |
| return result; | |
| } | |
| } | |
| template opBinary(string op, T2) if (isNumeric!T2) { | |
| alias RetT = CommonType!(T, T2); | |
| Vector!(RetT, N) opBinary(T2 rhs) | |
| { | |
| Vector!(RetT, N) result; | |
| foreach(i; 0..N) result.data[i] = mixin("data[i] "~op~" rhs"); | |
| return result; | |
| } | |
| } | |
| template opOpAssign(string op, T2 : Vector!(T3, N), T3) { | |
| alias RetT = CommonType!(T, T3); | |
| Vector!(RetT, N) opOpAssign(T2 rhs) | |
| { | |
| Vector!(RetT, N) result; | |
| foreach(i; 0..N) mixin("data[i] "~op~"= rhs.data[i];"); | |
| return this; | |
| } | |
| } | |
| template opOpAssign(string op, T2) if (isNumeric!T2) { | |
| alias RetT = CommonType!(T, T2); | |
| Vector!(RetT, N) opOpAssign(T2 rhs) | |
| { | |
| Vector!(RetT, N) result; | |
| foreach(i; 0..N) mixin("data[i] "~op~"= rhs;"); | |
| return this; | |
| } | |
| } | |
| template opBinaryRight(string op, T2) if (isNumeric!T2) { | |
| alias RetT = CommonType!(T, T2); | |
| Vector!(RetT, N) opBinaryRight(T2 rhs) | |
| { | |
| Vector!(RetT, N) result; | |
| foreach(i; 0..N) result.data[i] = mixin("rhs "~op~" data[i]"); | |
| return result; | |
| } | |
| } | |
| void toString(Sink)(Sink sink) | |
| { | |
| import std.format : formattedWrite; | |
| formattedWrite(sink, "%s%s(%(%s, %))", T.stringof, N, data); | |
| } | |
| } | |
| alias ivec2 = Vector!(int, 2); | |
| alias ivec3 = Vector!(int, 3); | |
| alias ivec4 = Vector!(int, 4); | |
| alias vec2 = Vector!(float, 2); | |
| alias vec3 = Vector!(float, 3); | |
| alias vec4 = Vector!(float, 4); | |
| unittest | |
| { | |
| ivec4 v = ivec4(0, 1, 2, 3); | |
| assert(v == ivec4(0, 1, 2, 3)); | |
| assert(v.xyzw == ivec4(0, 1, 2, 3)); | |
| assert(v.stpq == ivec4(0, 1, 2, 3)); | |
| assert(v.rgba == ivec4(0, 1, 2, 3)); | |
| assert(v.x == 0); | |
| assert(v.y == 1); | |
| assert(v.z == 2); | |
| assert(v.w == 3); | |
| assert(v.xy == ivec2(0,1)); | |
| assert(v.wwzx == ivec4(3,3,2,0)); | |
| v.xy = ivec2(7,8); | |
| assert(v.xy == ivec2(7,8)); | |
| v.xy = v.yx; | |
| assert(v.xy == ivec2(8,7)); | |
| v.x = 1; | |
| assert(v == ivec4(1, 7, 2, 3)); | |
| immutable binOps = ["+","-","*","/","%","^^","&","|","^","<<",">>",">>>"]; | |
| static foreach (op; binOps) {{ | |
| enum test1 = "(ivec2(8, 2) "~op~" ivec2(3, 5)) == ivec2(8"~op~"3, 2"~op~"5)"; | |
| enum test2 = "(ivec2(8, 2) "~op~" 5) == ivec2(8"~op~"5, 2"~op~"5)"; | |
| enum test3 = "(5 "~op~" ivec2(8, 2)) == ivec2(5"~op~"8, 5"~op~"2)"; | |
| assert(mixin(test1), test1); | |
| assert(mixin(test2), test2); | |
| assert(mixin(test3), test3); | |
| ivec2 v4 = ivec2(8, 2); | |
| enum test4 = "v4 "~op~"= ivec2(3, 5);"; | |
| mixin(test4); | |
| assert(v4 == mixin("ivec2(8, 2) "~op~" ivec2(3, 5)"), test4); | |
| ivec2 v5 = ivec2(8, 2); | |
| enum test5 = "v5 "~op~"= 5;"; | |
| mixin(test5); | |
| assert(v5 == mixin("ivec2(8, 2) "~op~" 5"), test5); | |
| }} | |
| static foreach (op; ["-","+","~"]) {{ | |
| enum test1 = op~"ivec2(8, 2) == ivec2("~op~"8, "~op~"2)"; | |
| assert(mixin(test1), test1); | |
| }} | |
| static foreach (op; ["~","in"]) {{ | |
| static assert(!__traits(compiles, mixin("ivec2(8, 2) "~op~" ivec2(3, 5)"))); | |
| }} | |
| assert(swizzleIndicies!4("xvzw")[4] == 0); | |
| assert(swizzleIndicies!4("xyzw") == [0,1,2,3,1]); | |
| } | |
| static assert(!__traits(compiles, ivec4(0, 1, 2, 3).ccc)); | |
| /// last elem is 0 if invalid, 1 if valid | |
| ubyte[N+1] swizzleIndicies(size_t N)(string swizzle) | |
| { | |
| ubyte[N+1] result; | |
| swizzleIndicies(swizzle, result[]); | |
| return result; | |
| } | |
| /// ditto | |
| void swizzleIndicies(string swizzle, ubyte[] result) | |
| { | |
| size_t N = swizzle.length; | |
| assert(N+1 == result.length); | |
| // 0 xyzw, 1 stpq, 2 rgba | |
| // [a b]c d e f[g]h i j k l m n o[p q r s t]u v[w x y z] | |
| immutable ubyte[26] indicies = [3,2,4,4,4,4,1,4,4,4,4,4,4,4,4,2,3,0,0,1,4,4,3,0,1,2]; // 4 is invalid | |
| immutable ubyte[26] groups = [2,2,3,3,3,3,2,3,3,3,3,3,3,3,3,1,1,2,1,1,3,3,0,0,0,0]; // 3 is invalid | |
| ubyte prevGroup = groups[swizzle[0]-'a']; | |
| foreach (i, char elem; swizzle) | |
| { | |
| if (elem >= 'a' && elem <= 'z') // xyzw | |
| { | |
| ubyte index = indicies[elem-'a']; | |
| ubyte group = groups[elem-'a']; | |
| bool hasInvalidElement = index == 4; | |
| bool hasMultipleGroups = group != prevGroup; | |
| if (hasInvalidElement || hasMultipleGroups) return; | |
| prevGroup = group; | |
| result[i] = index; | |
| } | |
| else | |
| { | |
| return; | |
| } | |
| } | |
| result[N] = 1; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment