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);
+    }
+}
