Index: nchmark/vector/vec2.cfa
===================================================================
--- benchmark/vector/vec2.cfa	(revision 11881953ca54519ac6075af439004447ec006cda)
+++ 	(revision )
@@ -1,53 +1,0 @@
-#include "../../libcfa/src/vector.hfa"
-/* #include <fstream.hfa> */
-#define BENCH_N 1000000000
-#include "../bench.h"
-
-int main(int argc, char* argv[]) {
-    volatile vec2 v1 = {1,2};
-    volatile vec2 v2 = {20.5, 30.2};
-
-    {
-        BENCH(
-            for (n) {
-                volatile float res = dot(v1, v2);
-                asm volatile ("":::"memory");
-            },
-            dot_b
-        );
-        printf("dot: %g\n", dot_b);
-    }
-
-    {
-        BENCH(
-            for (n) {
-                volatile vec2 res = v1 + v2;
-                asm volatile ("":::"memory");
-            },
-            add_b
-        );
-        printf("vector addition: %g\n", add_b);
-    }
-
-    {
-        BENCH(
-            for (n) {
-                volatile vec2 res = normalize(v1);
-                asm volatile ("":::"memory");
-            },
-            normalize_b
-        );
-        printf("normalize: %g\n", normalize_b);
-    }
-
-    {
-        BENCH(
-            for (n) {
-                volatile vec2 res = reflect(v1, v2);
-                asm volatile ("":::"memory");
-            },
-            reflect_b
-        );
-        printf("reflect : %g\n", reflect_b);
-    }
-}
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);
+    }
+}
Index: bcfa/src/vector.hfa
===================================================================
--- libcfa/src/vector.hfa	(revision 11881953ca54519ac6075af439004447ec006cda)
+++ 	(revision )
@@ -1,155 +1,0 @@
-#pragma once
-#include <math.hfa>
-#include <iostream.hfa>
-
-struct vec2 {
-    float x, y;
-};
-
-static inline {
-
-// Constructors
-
-void ?{}(vec2& v, float x, float y) {
-    v.[x, y] = [x, y];
-}
-void ?{}(vec2& vec, zero_t) with (vec) {
-    x = y = 0;
-}
-void ?{}(vec2& vec, float val) with (vec) {
-    x = y = val;
-}
-void ?{}(vec2& vec, const vec2& other) with (vec) {
-    [x,y] = other.[x,y];
-}
-
-// Assignment
-void ?=?(vec2& vec, const vec2& other) with (vec) {
-    [x,y] = other.[x,y];
-}
-void ?=?(vec2& vec, zero_t) with (vec) {
-    [x,y] = [0,0];
-}
-
-// Primitive mathematical operations
-
-// Subtraction
-vec2 ?-?(const vec2& u, const vec2& v) {
-    return [u.x - v.x, u.y - v.y];
-}
-vec2& ?-=?(vec2& u, const vec2& v) {
-    u = u - v;
-    return u;
-}
-vec2 -?(const vec2& v) with (v) {
-    return [-x, -y];
-}
-
-// Addition
-vec2 ?+?(const vec2& u, const vec2& v) {
-    return [u.x + v.x, u.y + v.y];
-}
-vec2& ?+=?(vec2& u, const vec2& v) {
-    u = u + v;
-    return u;
-}
-
-// Scalar Multiplication
-vec2 ?*?(const vec2& v, float scalar) with (v) {
-    return [x * scalar, y * scalar];
-}
-vec2 ?*?(float scalar, const vec2& v) {
-    return v * scalar;
-}
-vec2& ?*=?(vec2& v, float scalar) with (v) {
-    v = v * scalar;
-    return v;
-}
-
-
-// Scalar Division
-vec2 ?/?(const vec2& v, float scalar) with (v) {
-    return [x / scalar, y / scalar];
-}
-vec2& ?/=?(vec2& v, float scalar) with (v) {
-    v = v / scalar;
-    return v;
-}
-
-// Relational Operators
-bool ?==?(const vec2& u, const vec2& v) with (u) {
-    return x == v.x && y == v.y;
-}
-bool ?!=?(const vec2& u, const vec2& v) {
-    return !(u == v);
-}
-
-// Printing the vector (ostream)
-forall( dtype ostype | ostream( ostype ) ) {
-    ostype & ?|?( ostype & os, const vec2& v) with (v) {
-        if ( sepPrt( os ) ) fmt( os, "%s", sepGetCur( os ) );
-        fmt( os, "<%g,%g>", x, y);
-        return os;
-    }
-    void ?|?( ostype & os, const vec2& v ) {
-        (ostype &)(os | v); ends( os );
-    }
-}
-
-/* //---------------------- Geometric Functions ---------------------- */
-/* // These functions implement the Geometric Functions section of GLSL for 2D vectors*/
-
-float dot(const vec2& u, const vec2& v) {
-    return u.x * v.x + u.y * v.y;
-}
-
-float length(const vec2& v) {
-   return sqrt(dot(v, v));
-}
-
-float length_squared(const vec2& v) {
-   return dot(v, v);
-}
-
-float distance(const vec2& v1, const vec2& v2) {
-    return length(v1 - v2);
-}
-
-vec2 normalize(const vec2& v) {
-    return v / sqrt(dot(v, v));
-}
-
-// Project vector u onto vector v
-vec2 project(const vec2& u, const vec2& v) {
-    vec2 v_norm = normalize(v);
-    return v_norm * dot(u, v_norm);
-}
-
-// Reflect incident vector v with respect to surface with normal n
-vec2 reflect(const vec2& v, const vec2& 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 refract(const vec2& v, const vec2& 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 faceforward(const vec2& n, const vec2& i, const vec2& ng) {
-    return dot(ng, i) < 0 ? n : -n;
-}
-
-}
Index: in.cfa
===================================================================
--- main.cfa	(revision 11881953ca54519ac6075af439004447ec006cda)
+++ 	(revision )
@@ -1,33 +1,0 @@
-/* #include <iostream.hfa> */
-#include <fstream.hfa>
-#include "libcfa/src/vector.hfa"
-
-/* [float, float] tuple(const vec2& v) { */
-/*     return [v.x, v.y]; */
-/* } */
-
-
-
-
-
-int main() {
-    vec2 v1 = {1,2};
-    sout | true;
-    sout | v1;
-    sout | "wot";
-    sout | ((vec2){1,2} - (vec2){3,2});
-    sout | "a" | "b";
-    /* sout | nlOff; */
-    /* sout | sepOff; */
-    /* sout | nlOff; */
-    /* #<{(| sout | nlOff; |)}># */
-    /*  */
-    /* vec2 v1 = {1,2}; */
-    /* sout | "w" | 2.2 | "at" | v1; */
-    /* sout | length(v1); */
-    /*  */
-    /* vec2 v2 = {1,1}; */
-    /* sout | dot(v1, v2); */
-    /*  */
-    /* sout | (v2 - v1) | " " | (v1 - v2); */
-}
Index: sts/vector/.expect/vec2.txt
===================================================================
--- tests/vector/.expect/vec2.txt	(revision 11881953ca54519ac6075af439004447ec006cda)
+++ 	(revision )
@@ -1,31 +1,0 @@
-ctor(x,y):<1,2>
-copy ctor:<1,2>
-assignment:<3,4.2>
-move assignment:<1,2>
-zero-init:<0,0>
-zero-assign:<0,0>
-fill-ctor:<1.23,1.23>
-?-?:<0.02,0.43>
-?-=?:<3.23,-6.57>
--?:<-3.23,6.57>
-?+?:<2.3,2.45>
-?+=?:<2.3,2.45>
-v*s:<4.5,8.25>
-s*v:<4.5,8.25>
-?*=?:<4.5,8.25>
-?/?:<0.666667,-0.0333333>
-?/=?:<0.666667,-0.0333333>
-dot_1:0.
-dot_2:8.6
-length:5.
-length_squared:25.
-distance:6.5146
-normalize:<0.882353,-0.470588>
-normalize_2:<1,0>
-project:<5,0>
-project_2:<5.5,5.5>
-reflect:<-5,6>
-refract:<5,6>
-refract:<3.7594,4.5592>
-faceforward_nochange:<4,5.5>
-faceforward_flip:<-4,-5.5>
Index: tests/vector/.expect/vec3_float.txt
===================================================================
--- tests/vector/.expect/vec3_float.txt	(revision 9ec35db6a499e60a80f6b8a9a1732b678c8fa11e)
+++ tests/vector/.expect/vec3_float.txt	(revision 9ec35db6a499e60a80f6b8a9a1732b678c8fa11e)
@@ -0,0 +1,30 @@
+ctor(x,y):<1.,2.,3.>
+copy ctor:<1.,2.,3.>
+assignment:<3.,4.2,-2.>
+move assignment:<1.,2.,3.>
+zero-init:<0.,0.,0.>
+zero-assign:<0.,0.,0.>
+fill-ctor:<1.23,1.23,1.23>
+?-?:<0.02,0.43,-0.999998>
+?-=?:<0.,0.,0.>
+-?:<-0.,-0.,-0.>
+?+?:<2.3,2.45,-9.2>
+?+=?:<2.3,2.45,-9.2>
+v*s:<4.5,8.25,300.9>
+s*v:<4.5,8.25,300.9>
+?*=?:<4.5,8.25,300.9>
+?/?:<0.666667,-0.0333333,15.>
+?/=?:<0.666667,-0.0333333,15.>
+dot_1:0.
+dot_2:37.8
+length:3.74166
+length_squared:14.
+distance:7.48599
+normalize:<0.872964,-0.465581,0.145494>
+project:<0.,0.,0.>
+project_2:<5.88034,0.588034,2.35214>
+reflect:<5.28917,6.,-1.57084>
+refract:<0.613403,0.736083,0.286214>
+refract:<0.461205,0.82471,-0.327329>
+faceforward_nochange:<4.,5.5,2.>
+faceforward_flip:<-4.,-5.5,-2.>
Index: tests/vector/glm_equivalents/vec2_float.cc
===================================================================
--- tests/vector/glm_equivalents/vec2_float.cc	(revision 9ec35db6a499e60a80f6b8a9a1732b678c8fa11e)
+++ tests/vector/glm_equivalents/vec2_float.cc	(revision 9ec35db6a499e60a80f6b8a9a1732b678c8fa11e)
@@ -0,0 +1,28 @@
+#include <glm/glm.hpp>
+#include <iostream>
+
+using namespace glm;
+
+std::ostream& operator<<(std::ostream& os, glm::tvec2<float>& v) {
+    os << "<" << v.x << "," << v.y << ">";
+    return os;
+}
+std::ostream& operator<<(std::ostream& os, glm::tvec2<float>&& v) {
+    os << "<" << v.x << "," << v.y << ">";
+    return os;
+}
+
+float length_squared(glm::tvec2<float> v) {
+    return glm::length(v) * glm::length(v);
+}
+
+tvec2<float> project(glm::tvec2<float> u, glm::tvec2<float> v) {
+    return normalize(v) * dot(u, normalize(v));
+}
+
+int main() {
+    tvec2<float> v1 = {5.f,6.f};
+    tvec2<float> v2 = {0.f,-1.f};
+    std::cout << "refract:" << refract(v1,normalize(v2),1.f) << std::endl;
+    std::cout << "refract:" << refract(v1,normalize(v2),1.f/1.33f) << std::endl;
+}
Index: tests/vector/glm_equivalents/vec3_float.cc
===================================================================
--- tests/vector/glm_equivalents/vec3_float.cc	(revision 9ec35db6a499e60a80f6b8a9a1732b678c8fa11e)
+++ tests/vector/glm_equivalents/vec3_float.cc	(revision 9ec35db6a499e60a80f6b8a9a1732b678c8fa11e)
@@ -0,0 +1,117 @@
+#include <glm/glm.hpp>
+#include <iostream>
+#include <ostream>
+
+using namespace glm;
+
+std::ostream& operator<<(std::ostream& os, glm::tvec3<float>& v) {
+    os << "<" << v.x << "," << v.y << "," << v.z << ">";
+    return os;
+}
+std::ostream& operator<<(std::ostream& os, glm::tvec3<float>&& v) {
+    os << "<" << v.x << "," << v.y << "," << v.z << ">";
+    return os;
+}
+
+float length_squared(glm::tvec3<float> v) {
+    return glm::length(v) * glm::length(v);
+}
+
+tvec3<float> project(glm::tvec3<float> u, glm::tvec3<float> v) {
+    return normalize(v) * dot(u, normalize(v));
+}
+
+int main(void) {
+    tvec3<float> v1 = {1.f,2.f,3.f};
+    std::cout << "ctor(x,y):" << v1 << std::endl;
+
+    tvec3<float> v2 = v1;
+    std::cout << "copy ctor:" << v2 << std::endl;
+
+    v2 = (tvec3<float>){3.f, 4.2f, -2.f};
+    std::cout << "assignment:" << v2 << std::endl;
+
+    v2 = v1;
+    std::cout << "move assignment:" << v2 << std::endl;
+
+    // tvec3<float> v3 = 0;
+    // std::cout << "zero-init:" << v3 << std::endl;
+
+    // v1 = 0;
+    // std::cout << "zero-assign:" << v1 << std::endl;
+    //
+    // tvec3<float> v4 = {1.23f};
+    // std::cout << "fill-ctor:" << v4 << std::endl;
+    //
+    v1 = (tvec3<float>){1.23f, 3.43f, 0.000002f};
+    std::cout << "?-?:" << (v1 - (tvec3<float>){1.21f,3,1}) << std::endl;
+
+    v1 -= (tvec3<float>){1.23f, 3.43f, 0.000002f};
+    std::cout << "?-=?:" << v1 << std::endl;
+
+    v1 = -v1;
+    std::cout << "-?:" << v1 << std::endl;
+
+
+
+
+
+    v1 = (tvec3<float>){1.5f, 2.75f, -14.2f};
+    std::cout << "?+?:" << (v1 + (tvec3<float>){0.8f, -0.3f, 5}) << std::endl;
+
+    v1 += (tvec3<float>){0.8f, -0.3f, 5};
+    std::cout << "?+=?:" << v1 << std::endl;
+
+    v1 = (tvec3<float>){1.5f, 2.75f, 100.3f};
+    std::cout << "v*s:" << v1 * 3.f << std::endl;
+
+    std::cout << "s*v:" << 3.f * v1 << std::endl;
+
+    v1 *= 3;
+    std::cout << "?*=?:" << v1 << std::endl;
+
+    v1 = (tvec3<float>){2, -0.1f, 45};
+    std::cout << "?/?:" << (v1 / 3.f) << std::endl;
+
+    v1 /= 3.f;
+    std::cout << "?/=?:" << v1 << std::endl;
+
+
+    v1 = (tvec3<float>){4,2,3};
+    v2 = (tvec3<float>){0,-3,2};
+    std::cout << "dot_1:" << dot(v1, v2) << std::endl;
+
+    v2 = (tvec3<float>){1.3f, -2, 12.2};
+    std::cout << "dot_2:" << dot(v1, v2) << std::endl;
+
+
+    v1 = (tvec3<float>){1,2,3};
+    std::cout << "length:" << length(v1) << std::endl;
+
+    std::cout << "length_squared:" << length_squared(v1) << std::endl;
+
+    v2 = (tvec3<float>){6, -3.2f, 1};
+    std::cout << "distance:" << distance(v1, v2) << std::endl;
+
+    std::cout << "normalize:" << normalize(v2) << std::endl;
+
+    std::cout << "project:" << project((tvec3<float>){5,6,0}, (tvec3<float>){0, 0, 1}) << std::endl;
+    std::cout << "project_2:" << project((tvec3<float>){5,6,3.2f}, (tvec3<float>){10, 1, 4}) << std::endl;
+
+    v1 = (tvec3<float>){5,6,2.333f};
+    v2 = (tvec3<float>){1,0,-13.5f};
+    std::cout << "reflect:" << reflect(v1,normalize(v2)) << std::endl;
+
+    v2 = (tvec3<float>){0,-1,2};
+    std::cout << "refract:" << refract(normalize(v1),normalize(v2),1.f) << std::endl;
+    std::cout << "refract:" << refract(normalize(v1),normalize(v2),1.f/1.33f) << std::endl;
+
+    tvec3<float> geometric_normal = {5,6,1};
+    tvec3<float> perturbed_normal = {4,5.5f,2};
+    tvec3<float> eyeline = {-1,0.002f,-1.0345f};
+    std::cout << "faceforward_nochange:" << faceforward(perturbed_normal, eyeline, geometric_normal) << std::endl;
+
+    eyeline = (tvec3<float>){1,0.002f,-1.0345f};
+    std::cout << "faceforward_flip:" << faceforward(perturbed_normal, eyeline, geometric_normal) << std::endl;
+}
+
Index: sts/vector/vec2.cfa
===================================================================
--- tests/vector/vec2.cfa	(revision 11881953ca54519ac6075af439004447ec006cda)
+++ 	(revision )
@@ -1,93 +1,0 @@
-#include "../../libcfa/src/vector.hfa"
-#include <fstream.hfa>
-
-int main(void) {
-    vec2 v1 = {1.,2.};
-    sout | "ctor(x,y):" | v1;
-
-    vec2 v2 = v1;
-    sout | "copy ctor:" | v2;
-
-    v2 = (vec2){3., 4.2};
-    sout | "assignment:" | v2;
-
-    v2 = v1;
-    sout | "move assignment:" | v2;
-
-    vec2 v3 = 0;
-    sout | "zero-init:" | v3;
-
-    v1 = 0;
-    sout | "zero-assign:" | v1;
-
-    vec2 v4 = {1.23};
-    sout | "fill-ctor:" | v4;
-
-    v1 = (vec2){1.23, 3.43};
-    sout | "?-?:" | (v1 - (vec2){1.21,3});
-
-    v1 -= (vec2){-2, 10};
-    sout | "?-=?:" | v1;
-
-    v1 = -v1;
-    sout | "-?:" | v1;
-
-    v1 = (vec2){1.5, 2.75};
-    sout | "?+?:" | (v1 + (vec2){0.8, -0.3});
-
-    v1 += (vec2){0.8, -0.3};
-    sout | "?+=?:" | v1;
-
-    v1 = (vec2){1.5, 2.75};
-    sout | "v*s:" | v1 * 3;
-
-    sout | "s*v:" | 3 * v1;
-
-    v1 *= 3;
-    sout | "?*=?:" | v1;
-
-    v1 = (vec2){2, -0.1};
-    sout | "?/?:" | (v1 / 3);
-
-    v1 /= 3;
-    sout | "?/=?:" | v1;
-
-    v1 = (vec2){2, 3};
-    v2 = (vec2){-3, 2};
-    sout | "dot_1:" | dot(v1, v2);
-
-    v2 = (vec2){1.3, 2};
-    sout | "dot_2:" | dot(v1, v2);
-
-    v1 = (vec2){4, 3};
-    sout | "length:" | length(v1);
-
-    sout | "length_squared:" | length_squared(v1);
-
-    v2 = (vec2){6, -3.2};
-    sout | "distance:" | distance(v1, v2);
-
-    sout | "normalize:" | normalize(v2);
-
-    v1 = (vec2){1,0};
-    sout | "normalize_2:" | normalize(v1);
-
-    sout | "project:" | project((vec2){5,6}, (vec2){1, 0});
-    sout | "project_2:" | project((vec2){5,6}, (vec2){1, 1});
-
-    v1 = (vec2){5,6};
-    v2 = (vec2){1,0};
-    sout | "reflect:" | reflect(v1,v2);
-
-    v2 = (vec2){0,-1};
-    sout | "refract:" | refract(v1,v2,1);
-    sout | "refract:" | refract(v1,v2,1./1.33);
-
-    vec2 geometric_normal = {5,6};
-    vec2 perturbed_normal = {4,5.5};
-    vec2 eyeline = {-1,0.002f};
-    sout | "faceforward_nochange:" | faceforward(perturbed_normal, eyeline, geometric_normal);
-
-    eyeline = (vec2){1,0.002f};
-    sout | "faceforward_flip:" | faceforward(perturbed_normal, eyeline, geometric_normal);
-}
Index: tests/vector/vec2_float.cfa
===================================================================
--- tests/vector/vec2_float.cfa	(revision 11881953ca54519ac6075af439004447ec006cda)
+++ tests/vector/vec2_float.cfa	(revision 9ec35db6a499e60a80f6b8a9a1732b678c8fa11e)
@@ -81,6 +81,6 @@
 
     v2 = (vec2(float)){0,-1};
-    sout | "refract:" | refract(v1,v2,1);
-    sout | "refract:" | refract(v1,v2,1.f/1.33f);
+    sout | "refract:" | refract(v1,normalize(v2),1);
+    sout | "refract:" | refract(v1,normalize(v2),1.f/1.33f);
 
     vec2(float) geometric_normal = {5,6};
