Index: libcfa/src/vec/README.md
===================================================================
--- libcfa/src/vec/README.md	(revision 9ec35db6a499e60a80f6b8a9a1732b678c8fa11e)
+++ libcfa/src/vec/README.md	(revision 9ec35db6a499e60a80f6b8a9a1732b678c8fa11e)
@@ -0,0 +1,4 @@
+
+vector_f.hfa contains the non-templated float specialization of the 2D vector type,
+used for benchmarking purposes
+
Index: libcfa/src/vec/vec2.hfa
===================================================================
--- libcfa/src/vec/vec2.hfa	(revision 9ec35db6a499e60a80f6b8a9a1732b678c8fa11e)
+++ libcfa/src/vec/vec2.hfa	(revision 9ec35db6a499e60a80f6b8a9a1732b678c8fa11e)
@@ -0,0 +1,181 @@
+#pragma once
+#include <math.hfa>
+#include <iostream.hfa>
+
+trait vec2_t(otype T) {
+    void ?{}(T&, int);
+    T ?=?(T&, zero_t);
+    T ?-?(T, T);
+    T -?(T);
+    T ?+?(T, T);
+    T ?*?(T, T);
+    T ?/?(T, T);
+    int ?==?(T, T);
+    int ?<?(T, T);
+    T sqrt(T);
+};
+
+static inline {
+// int
+int ?=?(int& n, zero_t) { return n = 0.f; }
+int sqrt(int a) { return sqrt((float)a); }
+/* float */
+void ?{}(float& a, int b) { a = b; }
+float ?=?(float& n, zero_t) { return n = 0.f; }
+/* double */
+void ?{}(double& a, int b) { a = b; }
+double ?=?(double& n, zero_t) { return n = 0L; }
+// long double
+void ?{}(long double& a, int b) { a = b; }
+long double ?=?(long double& n, zero_t) { return n = 0L; }
+}
+
+forall(otype T | vec2_t(T)) {
+    struct vec2 {
+        T x, y;
+    };
+}
+
+/* static inline { */
+forall(otype T | vec2_t(T)) {
+    static inline {
+
+    // Constructors
+
+    void ?{}(vec2(T)& v, T x, T y) {
+        v.[x, y] = [x, y];
+    }
+    void ?{}(vec2(T)& vec, zero_t) with (vec) {
+        x = y = 0;
+    }
+    void ?{}(vec2(T)& vec, T val) with (vec) {
+        x = y = val;
+    }
+    void ?{}(vec2(T)& vec, vec2(T) other) with (vec) {
+        [x,y] = other.[x,y];
+    }
+
+    // Assignment
+    void ?=?(vec2(T)& vec, vec2(T) other) with (vec) {
+        [x,y] = other.[x,y];
+    }
+    void ?=?(vec2(T)& vec, zero_t) with (vec) {
+        x = y = 0;
+    }
+
+    // Primitive mathematical operations
+
+    // Subtraction
+    vec2(T) ?-?(vec2(T) u, vec2(T) v) { // TODO( can't make this const ref )
+        return [u.x - v.x, u.y - v.y];
+    }
+    vec2(T)& ?-=?(vec2(T)& u, vec2(T) v) {
+        u = u - v;
+        return u;
+    }
+    vec2(T) -?(vec2(T)& v) with (v) {
+        return [-x, -y];
+    }
+
+    // Addition
+    vec2(T) ?+?(vec2(T) u, vec2(T) v) { // TODO( can't make this const ref )
+        return [u.x + v.x, u.y + v.y];
+    }
+    vec2(T)& ?+=?(vec2(T)& u, vec2(T) v) {
+        u = u + v;
+        return u;
+    }
+
+    // Scalar Multiplication
+    vec2(T) ?*?(vec2(T) v, T scalar) with (v) { // TODO (can't make this const ref)
+        return [x * scalar, y * scalar];
+    }
+    vec2(T) ?*?(T scalar, vec2(T) v) { // TODO (can't make this const ref)
+        return v * scalar;
+    }
+    vec2(T)& ?*=?(vec2(T)& v, T scalar) {
+        v = v * scalar;
+        return v;
+    }
+
+
+    // Scalar Division
+    vec2(T) ?/?(vec2(T) v, T scalar) with (v) {
+        return [x / scalar, y / scalar];
+    }
+    vec2(T)& ?/=?(vec2(T)& v, T scalar) with (v) {
+        v = v / scalar;
+        return v;
+    }
+    // Relational Operators
+    bool ?==?(vec2(T) u, vec2(T) v) with (u) {
+        return x == v.x && y == v.y;
+    }
+    bool ?!=?(vec2(T) u, vec2(T) v) {
+        return !(u == v);
+    }
+
+    T dot(vec2(T) u, vec2(T) v) {
+        return u.x * v.x + u.y * v.y;
+    }
+
+    T length(vec2(T) v) {
+       return sqrt(dot(v, v));
+    }
+
+    T length_squared(vec2(T) v) {
+       return dot(v, v);
+    }
+
+    T distance(vec2(T) v1, vec2(T) v2) {
+        return length(v1 - v2);
+    }
+
+    vec2(T) normalize(vec2(T) v) {
+        return v / sqrt(dot(v, v));
+    }
+
+    // Project vector u onto vector v
+    vec2(T) project(vec2(T) u, vec2(T) v) {
+        vec2(T) v_norm = normalize(v);
+        return v_norm * dot(u, v_norm);
+    }
+
+    // Reflect incident vector v with respect to surface with normal n
+    vec2(T) reflect(vec2(T) v, vec2(T) n) {
+        return v - (T){2} * project(v, n);
+    }
+
+    // Refract incident vector v with respect to surface with normal n
+    // eta is the ratio of indices of refraction between starting material and
+    // entering material (i.e., from air to water, eta = 1/1.33)
+    // v and n must already be normalized
+    vec2(T) refract(vec2(T) v, vec2(T) n, T eta) {
+        T dotValue = dot(n, v);
+        T k = (T){1} - eta * eta * ((T){1} - dotValue * dotValue);
+        if (k < (T){0}) {
+            return 0;
+        }
+        return eta * v - (eta * dotValue + sqrt(k)) * n;
+    }
+
+    // Given a perturbed normal and a geometric normal,
+    // flip the perturbed normal if the geometric normal is pointing away
+    // from the observer.
+    // n is the perturbed vector that we want to align
+    // i is the incident vector
+    // ng is the geometric normal of the surface
+    vec2(T) faceforward(vec2(T) n, vec2(T) i, vec2(T) ng) {
+        return dot(ng, i) < (T){0} ? n : -n;
+    }
+    }
+}
+
+forall(dtype ostype, otype T | writeable(T, ostype) | vec2_t(T)) {
+    ostype & ?|?( ostype & os, vec2(T) v) with (v) {
+        return os | '<' | x | ',' | y | '>';
+    }
+    void ?|?( ostype & os, vec2(T) v ) with (v) {
+        (ostype &)(os | v); ends(os);
+    }
+}
Index: libcfa/src/vec/vec2_f.hfa
===================================================================
--- libcfa/src/vec/vec2_f.hfa	(revision 9ec35db6a499e60a80f6b8a9a1732b678c8fa11e)
+++ libcfa/src/vec/vec2_f.hfa	(revision 9ec35db6a499e60a80f6b8a9a1732b678c8fa11e)
@@ -0,0 +1,155 @@
+#pragma once
+#include <math.hfa>
+/* #include <iostream.hfa> */
+
+struct vec2_f {
+    float x, y;
+};
+
+static inline {
+
+// Constructors
+
+void ?{}(vec2_f& v, float x, float y) {
+    v.[x, y] = [x, y];
+}
+void ?{}(vec2_f& vec, zero_t) with (vec) {
+    x = y = 0;
+}
+void ?{}(vec2_f& vec, float val) with (vec) {
+    x = y = val;
+}
+void ?{}(vec2_f& vec, const vec2_f& other) with (vec) {
+    [x,y] = other.[x,y];
+}
+
+// Assignment
+void ?=?(vec2_f& vec, const vec2_f& other) with (vec) {
+    [x,y] = other.[x,y];
+}
+void ?=?(vec2_f& vec, zero_t) with (vec) {
+    [x,y] = [0,0];
+}
+
+// Primitive mathematical operations
+
+// Subtraction
+vec2_f ?-?(const vec2_f& u, const vec2_f& v) {
+    return [u.x - v.x, u.y - v.y];
+}
+vec2_f& ?-=?(vec2_f& u, const vec2_f& v) {
+    u = u - v;
+    return u;
+}
+vec2_f -?(const vec2_f& v) with (v) {
+    return [-x, -y];
+}
+
+// Addition
+vec2_f ?+?(const vec2_f& u, const vec2_f& v) {
+    return [u.x + v.x, u.y + v.y];
+}
+vec2_f& ?+=?(vec2_f& u, const vec2_f& v) {
+    u = u + v;
+    return u;
+}
+
+// Scalar Multiplication
+vec2_f ?*?(const vec2_f& v, float scalar) with (v) {
+    return [x * scalar, y * scalar];
+}
+vec2_f ?*?(float scalar, const vec2_f& v) {
+    return v * scalar;
+}
+vec2_f& ?*=?(vec2_f& v, float scalar) with (v) {
+    v = v * scalar;
+    return v;
+}
+
+
+// Scalar Division
+vec2_f ?/?(const vec2_f& v, float scalar) with (v) {
+    return [x / scalar, y / scalar];
+}
+vec2_f& ?/=?(vec2_f& v, float scalar) with (v) {
+    v = v / scalar;
+    return v;
+}
+
+// Relational Operators
+bool ?==?(const vec2_f& u, const vec2_f& v) with (u) {
+    return x == v.x && y == v.y;
+}
+bool ?!=?(const vec2_f& u, const vec2_f& v) {
+    return !(u == v);
+}
+
+/* // Printing the vector (ostream) */
+/* forall( dtype ostype | ostream( ostype ) ) { */
+/*     ostype & ?|?( ostype & os, const vec2_f& v) with (v) { */
+/*         if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) ); */
+/*         fmt( os, "<%g,%g>", x, y); */
+/*         return os; */
+/*     } */
+/*     void ?|?( ostype & os, const vec2_f& v ) { */
+/*         (ostype &)(os | v); ends( os ); */
+/*     } */
+/* } */
+
+//---------------------- Geometric Functions ----------------------
+// These functions implement the Geometric Functions section of GLSL for 2D vectors
+
+float dot(const vec2_f& u, const vec2_f& v) {
+    return u.x * v.x + u.y * v.y;
+}
+
+float length(const vec2_f& v) {
+   return sqrt(dot(v, v));
+}
+
+float length_squared(const vec2_f& v) {
+   return dot(v, v);
+}
+
+float distance(const vec2_f& v1, const vec2_f& v2) {
+    return length(v1 - v2);
+}
+
+vec2_f normalize(const vec2_f& v) {
+    return v / sqrt(dot(v, v));
+}
+
+// Project vector u onto vector v
+vec2_f project(const vec2_f& u, const vec2_f& v) {
+    vec2_f v_norm = normalize(v);
+    return v_norm * dot(u, v_norm);
+}
+
+// Reflect incident vector v with respect to surface with normal n
+vec2_f reflect(const vec2_f& v, const vec2_f& n) {
+    return v - 2 * project(v, n);
+}
+
+// Refract incident vector v with respect to surface with normal n
+// eta is the ratio of indices of refraction between starting material and
+// entering material (i.e., from air to water, eta = 1/1.33)
+vec2_f refract(const vec2_f& v, const vec2_f& n, float eta) {
+    float dotValue = dot(n, v);
+    float k = 1 - eta \ 2 * (1 - dotValue \ 2);
+    if (k < 0) {
+        return 0;
+    }
+    return eta * v - (eta * dotValue + sqrt(k)) * n;
+}
+
+// Given a perturbed normal and a geometric normal,
+// flip the perturbed normal if the geometric normal is pointing away
+// from the observer.
+// n is the perturbed vector that we want to align
+// i is the incident vector
+// ng is the geometric normal of the surface
+vec2_f faceforward(const vec2_f& n, const vec2_f& i, const vec2_f& ng) {
+    return dot(ng, i) < 0 ? n : -n;
+}
+
+}
Index: libcfa/src/vec/vec3.hfa
===================================================================
--- libcfa/src/vec/vec3.hfa	(revision 9ec35db6a499e60a80f6b8a9a1732b678c8fa11e)
+++ libcfa/src/vec/vec3.hfa	(revision 9ec35db6a499e60a80f6b8a9a1732b678c8fa11e)
@@ -0,0 +1,187 @@
+#pragma once
+#include <math.hfa>
+#include <iostream.hfa>
+
+trait vec3_t(otype T) {
+    void ?{}(T&, int);
+    T ?=?(T&, zero_t);
+    T ?-?(T, T);
+    T -?(T);
+    T ?+?(T, T);
+    T ?*?(T, T);
+    T ?/?(T, T);
+    int ?==?(T, T);
+    int ?<?(T, T);
+    T sqrt(T);
+};
+
+static inline {
+// int
+int ?=?(int& n, zero_t) { return n = 0.f; }
+int sqrt(int a) { return sqrt((float)a); }
+/* float */
+void ?{}(float& a, int b) { a = b; }
+float ?=?(float& n, zero_t) { return n = 0.f; }
+/* double */
+void ?{}(double& a, int b) { a = b; }
+double ?=?(double& n, zero_t) { return n = 0L; }
+// long double
+void ?{}(long double& a, int b) { a = b; }
+long double ?=?(long double& n, zero_t) { return n = 0L; }
+}
+
+forall(otype T | vec3_t(T)) {
+    struct vec3 {
+        T x, y, z;
+    };
+}
+
+/* static inline { */
+forall(otype T | vec3_t(T)) {
+    static inline {
+
+    // Constructors
+
+    void ?{}(vec3(T)& v, T x, T y, T z) {
+        v.[x, y, z] = [x, y, z];
+    }
+    void ?{}(vec3(T)& vec, zero_t) with (vec) {
+        x = y = z = 0;
+    }
+    void ?{}(vec3(T)& vec, T val) with (vec) {
+        x = y = z = val;
+    }
+    void ?{}(vec3(T)& vec, vec3(T) other) with (vec) {
+        [x,y,z] = other.[x,y,z];
+    }
+
+    // Assignment
+    void ?=?(vec3(T)& vec, vec3(T) other) with (vec) {
+        [x,y,z] = other.[x,y,z];
+    }
+    void ?=?(vec3(T)& vec, zero_t) with (vec) {
+        x = y = z = 0;
+    }
+
+    // Primitive mathematical operations
+
+    // Subtraction
+    vec3(T) ?-?(vec3(T) u, vec3(T) v) { // TODO( can't make this const ref )
+        return [u.x - v.x, u.y - v.y, u.z - v.z];
+    }
+    vec3(T)& ?-=?(vec3(T)& u, vec3(T) v) {
+        u = u - v;
+        return u;
+    }
+    vec3(T) -?(vec3(T)& v) with (v) {
+        return [-x, -y, -z];
+    }
+
+    // Addition
+    vec3(T) ?+?(vec3(T) u, vec3(T) v) { // TODO( can't make this const ref )
+        return [u.x + v.x, u.y + v.y, u.z + v.z];
+    }
+    vec3(T)& ?+=?(vec3(T)& u, vec3(T) v) {
+        u = u + v;
+        return u;
+    }
+
+    // Scalar Multiplication
+    vec3(T) ?*?(vec3(T) v, T scalar) with (v) { // TODO (can't make this const ref)
+        return [x * scalar, y * scalar, z * scalar];
+    }
+    vec3(T) ?*?(T scalar, vec3(T) v) { // TODO (can't make this const ref)
+        return v * scalar;
+    }
+    vec3(T)& ?*=?(vec3(T)& v, T scalar) {
+        v = v * scalar;
+        return v;
+    }
+
+
+    // Scalar Division
+    vec3(T) ?/?(vec3(T) v, T scalar) with (v) {
+        return [x / scalar, y / scalar, z / scalar];
+    }
+    vec3(T)& ?/=?(vec3(T)& v, T scalar) with (v) {
+        v = v / scalar;
+        return v;
+    }
+    // Relational Operators
+    bool ?==?(vec3(T) u, vec3(T) v) with (u) {
+        return x == v.x && y == v.y && z == v.z;
+    }
+    bool ?!=?(vec3(T) u, vec3(T) v) {
+        return !(u == v);
+    }
+
+    T dot(vec3(T) u, vec3(T) v) {
+        return u.x * v.x + u.y * v.y + u.z * v.z;
+    }
+
+    T length(vec3(T) v) {
+       return sqrt(dot(v, v));
+    }
+
+    T length_squared(vec3(T) v) {
+       return dot(v, v);
+    }
+
+    T distance(vec3(T) v1, vec3(T) v2) {
+        return length(v1 - v2);
+    }
+
+    vec3(T) normalize(vec3(T) v) {
+        return v / sqrt(dot(v, v));
+    }
+
+    // Project vector u onto vector v
+    vec3(T) project(vec3(T) u, vec3(T) v) {
+        vec3(T) v_norm = normalize(v);
+        return v_norm * dot(u, v_norm);
+    }
+
+    // Reflect incident vector v with respect to surface with normal n
+    vec3(T) reflect(vec3(T) v, vec3(T) n) {
+        return v - (T){2} * project(v, n);
+    }
+
+    // Refract incident vector v with respect to surface with normal n
+    // eta is the ratio of indices of refraction between starting material and
+    // entering material (i.e., from air to water, eta = 1/1.33)
+    // v and n must already be normalized
+    vec3(T) refract(vec3(T) v, vec3(T) n, T eta) {
+        T dotValue = dot(n, v);
+        T k = (T){1} - eta * eta * ((T){1} - dotValue * dotValue);
+        if (k < (T){0}) {
+            return 0;
+        }
+        return eta * v - (eta * dotValue + sqrt(k)) * n;
+    }
+
+    // Given a perturbed normal and a geometric normal,
+    // flip the perturbed normal if the geometric normal is pointing away
+    // from the observer.
+    // n is the perturbed vector that we want to align
+    // i is the incident vector
+    // ng is the geometric normal of the surface
+    vec3(T) faceforward(vec3(T) n, vec3(T) i, vec3(T) ng) {
+        return dot(ng, i) < (T){0} ? n : -n;
+    }
+
+    vec3(T) cross(vec3(T) u, vec3(T) v) {
+        return (vec3(T)){ u.y * v.z - v.y * u.z,
+                          u.z * v.x - v.z * u.x,
+                          u.x * v.y - v.x * u.y };
+    }
+    }
+}
+
+forall(dtype ostype, otype T | writeable(T, ostype) | vec3_t(T)) {
+    ostype & ?|?( ostype & os, vec3(T) v) with (v) {
+        return os | '<' | x | ',' | y | ',' | z | '>';
+    }
+    void ?|?( ostype & os, vec3(T) v ) with (v) {
+        (ostype &)(os | v); ends(os);
+    }
+}
