Skip to content

Instantly share code, notes, and snippets.

@run-dlang
Created April 5, 2018 17:16
Show Gist options
  • Select an option

  • Save run-dlang/0f97f0181c4efbbdc76e257311ed53a2 to your computer and use it in GitHub Desktop.

Select an option

Save run-dlang/0f97f0181c4efbbdc76e257311ed53a2 to your computer and use it in GitHub Desktop.
Code shared from run.dlang.io.
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