diff --git a/src/debug/quad.cpp b/src/debug/quad.cpp
index eacd6d9b..1e4d7c8d 100644
--- a/src/debug/quad.cpp
+++ b/src/debug/quad.cpp
@@ -200,7 +200,7 @@ void DebugQuad::TickDraw(float deltams)
 
     /* Prepare our quad coordinates */
     ivec2 const layout(7, 5);
-    data->step = vec2(2.0f, -2.0f) / (4 * layout + ivec2(1));
+    data->step = vec2(2.0f, -2.0f) / vec2(4 * layout + ivec2(1));
     data->orig = vec2(-1.0f, 1.0f) + data->step;
     data->aa = data->orig;
     data->bb = data->orig + 3.0f * data->step;
diff --git a/src/input.cpp b/src/input.cpp
index b9c4a555..c759e283 100644
--- a/src/input.cpp
+++ b/src/input.cpp
@@ -134,7 +134,7 @@ void Input::SetMousePos(ivec2 coord)
     {
         if (data->entities[n] == top)
         {
-            data->entities[n]->mousepos = coord - top->bbox[0].xy();
+            data->entities[n]->mousepos = coord - (ivec2)top->bbox[0].xy();
             if (top != data->lastfocus)
                 data->entities[n]->pressed = data->buttons;
             else
diff --git a/src/lol/math/matrix.h b/src/lol/math/matrix.h
index 66d2b563..eb80e403 100644
--- a/src/lol/math/matrix.h
+++ b/src/lol/math/matrix.h
@@ -49,78 +49,10 @@ VECTOR_TYPES(Vec4, vec4)
 VECTOR_TYPES(Quat, quat)
 VECTOR_TYPES(Mat4, mat4)
 
-#define VECTOR_OP(op) \
-    inline type_t operator op(type_t const &val) const \
-    { \
-        type_t ret; \
-        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
-            ret[n] = (*this)[n] op val[n]; \
-        return ret; \
-    } \
-    \
-    inline type_t operator op##=(type_t const &val) \
-    { \
-        return *this = (*this) op val; \
-    }
-
-#define BOOL_OP(op, op2, ret) \
-    inline bool operator op(type_t const &val) const \
-    { \
-        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
-            if (!((*this)[n] op2 val[n])) \
-                return !ret; \
-        return ret; \
-    }
-
-#define SCALAR_OP(op) \
-    inline type_t operator op(T const &val) const \
-    { \
-        type_t ret; \
-        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
-            ret[n] = (*this)[n] op val; \
-        return ret; \
-    } \
-    \
-    inline type_t operator op##=(T const &val) \
-    { \
-        return *this = (*this) op val; \
-    }
-
-#define LINEAR_OPS() \
+#define MEMBER_OPS() \
     inline T& operator[](int n) { return *(&x + n); } \
     inline T const& operator[](int n) const { return *(&x + n); } \
     \
-    VECTOR_OP(-) \
-    VECTOR_OP(+) \
-    \
-    BOOL_OP(==, ==, true) \
-    BOOL_OP(!=, ==, false) \
-    \
-    SCALAR_OP(*) \
-    SCALAR_OP(/) \
-    \
-    inline type_t operator -() const \
-    { \
-        type_t ret; \
-        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
-            ret[n] = -(*this)[n]; \
-        return ret; \
-    } \
-    \
-    inline T sqlen() const \
-    { \
-        T acc = 0; \
-        for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
-            acc += (*this)[n] * (*this)[n]; \
-        return acc; \
-    } \
-    \
-    inline double len() const \
-    { \
-        using namespace std; \
-        return sqrt((double)sqlen()); \
-    } \
-    \
     void printf() const;
 
 #define COMPLEX_OPS() \
@@ -139,7 +71,7 @@ VECTOR_TYPES(Mat4, mat4)
         return type_t(x, -y); \
     } \
     \
-    inline T norm() const { return len(); }
+    inline T norm() const { return len(*this); }
 
 #define QUATERNION_OPS() \
     inline type_t operator *(type_t const &val) const \
@@ -167,19 +99,9 @@ VECTOR_TYPES(Mat4, mat4)
             ret[n] = -(*this)[n]; \
         ret[3] = (*this)[3]; \
         return ret; \
-    } \
-    \
-    inline T norm() const { return sqlen(); }
+    }
 
-#define OTHER_OPS(tname) \
-    VECTOR_OP(*) \
-    VECTOR_OP(/) \
-    \
-    BOOL_OP(<=, <=, true) \
-    BOOL_OP(>=, >=, true) \
-    BOOL_OP(<, <, true) \
-    BOOL_OP(>, >, true) \
-    \
+#define OTHER_MEMBER_OPS(tname) \
     template<typename U> \
     inline operator tname<U>() const \
     { \
@@ -187,10 +109,7 @@ VECTOR_TYPES(Mat4, mat4)
         for (size_t n = 0; n < sizeof(*this) / sizeof(T); n++) \
             ret[n] = static_cast<U>((*this)[n]); \
         return ret; \
-    } \
-    \
-    template<typename U> \
-    friend U dot(tname<U>, tname<U>);
+    }
 
 #define SWIZZLE2(e1, e2) \
     inline Vec2<T> e1##e2() const \
@@ -265,8 +184,8 @@ template <typename T> struct Vec2
     explicit inline Vec2(T val) { x = y = val; }
     inline Vec2(T _x, T _y) { x = _x; y = _y; }
 
-    LINEAR_OPS()
-    OTHER_OPS(Vec2)
+    MEMBER_OPS()
+    OTHER_MEMBER_OPS(Vec2)
 
     SWIZZLE22(x); SWIZZLE22(y);
     SWIZZLE322(x); SWIZZLE322(y);
@@ -297,7 +216,8 @@ template <typename T> struct Cmplx
     inline Cmplx(T val) : x(val), y(0) { }
     inline Cmplx(T _x, T _y) : x(_x), y(_y) { }
 
-    LINEAR_OPS()
+    MEMBER_OPS()
+
     COMPLEX_OPS()
 
 #if !defined __ANDROID__
@@ -311,21 +231,39 @@ template <typename T> struct Cmplx
 template<typename T>
 static inline Cmplx<T> re(Cmplx<T> const &val)
 {
-    return ~val / val.sqlen();
+    return ~val / sqlen(val);
 }
 
 template<typename T>
-static inline Cmplx<T> operator /(T x, Cmplx<T> const &y)
+static inline Cmplx<T> operator /(T a, Cmplx<T> const &b)
 {
-    return x * re(y);
+    return a * re(b);
 }
 
 template<typename T>
-static inline Cmplx<T> operator /(Cmplx<T> x, Cmplx<T> const &y)
+static inline Cmplx<T> operator /(Cmplx<T> a, Cmplx<T> const &b)
 {
-    return x * re(y);
+    return a * re(b);
 }
 
+template<typename T>
+static inline bool operator ==(Cmplx<T> const &a, T b)
+{
+    return (a.x == b) && !a.y;
+}
+
+template<typename T>
+static inline bool operator !=(Cmplx<T> const &a, T b)
+{
+    return (a.x != b) || a.y;
+}
+
+template<typename T>
+static inline bool operator ==(T a, Cmplx<T> const &b) { return b == a; }
+
+template<typename T>
+static inline bool operator !=(T a, Cmplx<T> const &b) { return b != a; }
+
 /*
  * 3-element vectors
  */
@@ -340,8 +278,8 @@ template <typename T> struct Vec3
     inline Vec3(Vec2<T> _xy, T _z) { x = _xy.x; y = _xy.y; z = _z; }
     inline Vec3(T _x, Vec2<T> _yz) { x = _x; y = _yz.x; z = _yz.y; }
 
-    LINEAR_OPS()
-    OTHER_OPS(Vec3)
+    MEMBER_OPS()
+    OTHER_MEMBER_OPS(Vec3)
 
     SWIZZLE23(x); SWIZZLE23(y); SWIZZLE23(z);
     SWIZZLE333(x); SWIZZLE333(y); SWIZZLE333(z);
@@ -381,8 +319,8 @@ template <typename T> struct Vec4
     inline Vec4(Vec3<T> _xyz, T _w) : x(_xyz.x), y(_xyz.y), z(_xyz.z), w(_w) { }
     inline Vec4(T _x, Vec3<T> _yzw) : x(_x), y(_yzw.x), z(_yzw.y), w(_yzw.z) { }
 
-    LINEAR_OPS()
-    OTHER_OPS(Vec4)
+    MEMBER_OPS()
+    OTHER_MEMBER_OPS(Vec4)
 
     SWIZZLE24(x); SWIZZLE24(y); SWIZZLE24(z); SWIZZLE24(w);
     SWIZZLE344(x); SWIZZLE344(y); SWIZZLE344(z); SWIZZLE344(w);
@@ -415,7 +353,8 @@ template <typename T> struct Quat
 
     Quat(Mat4<T> const &m);
 
-    LINEAR_OPS()
+    MEMBER_OPS()
+
     QUATERNION_OPS()
 
 #if !defined __ANDROID__
@@ -426,10 +365,16 @@ template <typename T> struct Quat
     T x, y, z, w;
 };
 
+template<typename T>
+inline T norm(Quat<T> const &val)
+{
+    return sqlen(val);
+}
+
 template<typename T>
 static inline Quat<T> re(Quat<T> const &val)
 {
-    return ~val / val.norm();
+    return ~val / norm(val);
 }
 
 template<typename T>
@@ -448,29 +393,107 @@ static inline Quat<T> operator /(Quat<T> x, Quat<T> const &y)
  * Common operators for all vector types, including quaternions
  */
 
-#define SCALAR_GLOBAL(tname, op, U) \
+#define VECTOR_OP(tname, op) \
     template<typename T> \
-    static inline tname<U> operator op(U const &val, tname<T> const &that) \
+    inline tname<T> operator op(tname<T> const &a, tname<T> const &b) \
     { \
-        tname<U> ret; \
-        for (size_t n = 0; n < sizeof(that) / sizeof(that[0]); n++) \
-            ret[n] = val op that[n]; \
+        tname<T> ret; \
+        for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \
+            ret[n] = a[n] op b[n]; \
+        return ret; \
+    } \
+    \
+    template<typename T> \
+    inline tname<T> operator op##=(tname<T> &a, tname<T> const &b) \
+    { \
+        return a = a op b; \
+    }
+
+#define BOOL_OP(tname, op, op2, ret) \
+    template<typename T> \
+    inline bool operator op(tname<T> const &a, tname<T> const &b) \
+    { \
+        for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \
+            if (!(a[n] op2 b[n])) \
+                return !ret; \
         return ret; \
     }
 
-#define SCALAR_GLOBAL2(tname, op) \
-    SCALAR_GLOBAL(tname, op, int) \
-    SCALAR_GLOBAL(tname, op, float) \
-    SCALAR_GLOBAL(tname, op, double)
+#define SCALAR_OP(tname, op) \
+    template<typename T> \
+    inline tname<T> operator op##=(tname<T> &a, T const &val) \
+    { \
+        return a = a op val; \
+    } \
+    \
+    template<typename T> \
+    static inline tname<T> operator op(tname<T> const &a, T const &val) \
+    { \
+        tname<T> ret; \
+        for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \
+            ret[n] = a[n] op val; \
+        return ret; \
+    }
+
+#define SCALAR_PROMOTE_OP(tname, op, U) \
+    template<typename T> \
+    static inline tname<U> operator op(U const &val, tname<T> const &a) \
+    { \
+        tname<U> ret; \
+        for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \
+            ret[n] = val op a[n]; \
+        return ret; \
+    }
 
 #define GLOBALS(tname) \
-    SCALAR_GLOBAL2(tname, *) \
+    SCALAR_OP(tname, *) \
+    SCALAR_OP(tname, /) \
+    \
+    SCALAR_PROMOTE_OP(tname, *, int) \
+    SCALAR_PROMOTE_OP(tname, *, float) \
+    SCALAR_PROMOTE_OP(tname, *, double) \
+    \
+    VECTOR_OP(tname, -) \
+    VECTOR_OP(tname, +) \
+    \
+    BOOL_OP(tname, ==, ==, true) \
+    BOOL_OP(tname, !=, ==, false) \
+    \
+    template<typename T> \
+    inline tname<T> operator -(tname<T> const &a) \
+    { \
+        tname<T> ret; \
+        for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \
+            ret[n] = -a[n]; \
+        return ret; \
+    } \
+    \
+    template<typename T> \
+    inline T sqlen(tname<T> const &a) \
+    { \
+        T acc = 0; \
+        for (size_t n = 0; n < sizeof(a) / sizeof(T); n++) \
+            acc += a[n] * a[n]; \
+        return acc; \
+    } \
+    \
+    template<typename T> \
+    inline double len(tname<T> const &a) \
+    { \
+        using namespace std; \
+        return sqrt((double)sqlen(a)); \
+    } \
+    \
+    /* dot() does not take const refs because the function is not inlined, \
+     * so we try to avoid carrying a shitty pointer around. */ \
+    template<typename T> \
+    T dot(tname<T> a, tname<T> b); \
     \
     template<typename T> \
     static inline tname<T> normalize(tname<T> const &val) \
     { \
-        T norm = val.len(); \
-        return norm ? val / norm : val * 0; \
+        T norm = len(val); \
+        return norm ? val / norm : val * (T)0; \
     }
 
 GLOBALS(Vec2)
@@ -479,6 +502,19 @@ GLOBALS(Vec3)
 GLOBALS(Vec4)
 GLOBALS(Quat)
 
+#define OTHER_OPS(tname) \
+    VECTOR_OP(tname, *) \
+    VECTOR_OP(tname, /) \
+    \
+    BOOL_OP(tname, <=, <=, true) \
+    BOOL_OP(tname, >=, >=, true) \
+    BOOL_OP(tname, <, <, true) \
+    BOOL_OP(tname, >, >, true)
+
+OTHER_OPS(Vec2)
+OTHER_OPS(Vec3)
+OTHER_OPS(Vec4)
+
 /*
  * 4×4-element matrices
  */
diff --git a/src/matrix.cpp b/src/matrix.cpp
index 6110e325..bee608a9 100644
--- a/src/matrix.cpp
+++ b/src/matrix.cpp
@@ -276,7 +276,7 @@ template<> mat4 mat4::rotate(float angle, vec3 v)
 template<> mat4 mat4::rotate(quat q)
 {
     mat4 ret(1.0f);
-    float n = q.norm();
+    float n = norm(q);
 
     if (!n)
         return ret;
diff --git a/test/tutorial/tut03.cpp b/test/tutorial/tut03.cpp
index 408d55cd..030f7b62 100644
--- a/test/tutorial/tut03.cpp
+++ b/test/tutorial/tut03.cpp
@@ -71,7 +71,8 @@ public:
             m_window2world = 0.5 / m_window_size.y;
         else
             m_window2world = 0.5 / m_window_size.x;
-        m_texel2world = (vec2)m_window_size / (vec2)m_size * m_window2world;
+        m_texel2world = (vec2)m_window_size / (vec2)m_size
+                                            * (vec2)m_window2world;
 
         m_oldmouse = ivec2(0, 0);
 
@@ -368,7 +369,7 @@ public:
                 z2 = z1 * z1 + r0;
                 z3 = z2 * z2 + r0;
                 z0 = z3 * z3 + r0;
-                if (z0.sqlen() >= maxsqlen)
+                if (sqlen(z0) >= maxsqlen)
                     break;
                 iter -= 4;
                 if (iter < 4)
@@ -377,11 +378,11 @@ public:
 
             if (iter)
             {
-                double n = z0.sqlen();
+                double n = sqlen(z0);
 
-                if (z1.sqlen() >= maxsqlen) { iter += 3; n = z1.sqlen(); }
-                else if (z2.sqlen() >= maxsqlen) { iter += 2; n = z2.sqlen(); }
-                else if (z3.sqlen() >= maxsqlen) { iter += 1; n = z3.sqlen(); }
+                if (sqlen(z1) >= maxsqlen) { iter += 3; n = sqlen(z1); }
+                else if (sqlen(z2) >= maxsqlen) { iter += 2; n = sqlen(z2); }
+                else if (sqlen(z3) >= maxsqlen) { iter += 1; n = sqlen(z3); }
 
                 if (n > maxsqlen * maxsqlen)
                     n = maxsqlen * maxsqlen;
diff --git a/test/unit/quat.cpp b/test/unit/quat.cpp
index 403da31b..ee6cbb90 100644
--- a/test/unit/quat.cpp
+++ b/test/unit/quat.cpp
@@ -67,16 +67,16 @@ LOLUNIT_FIXTURE(QuaternionTest)
     {
         quat a(2.0f, -2.0f, -8.0f, 3.0f);
 
-        LOLUNIT_ASSERT_EQUAL(a.norm(), 81.0f);
+        LOLUNIT_ASSERT_EQUAL(norm(a), 81.0f);
 
         quat b = a * ~a;
-        quat c(0.0f, 0.0f, 0.0f, a.norm());
+        quat c(0.0f, 0.0f, 0.0f, norm(a));
 
         LOLUNIT_ASSERT_EQUAL(b, c);
 
         quat d(2.0f, 3.0f, -4.0f, -1.0f);
 
-        LOLUNIT_ASSERT_EQUAL((a * d).norm(), a.norm() * d.norm());
+        LOLUNIT_ASSERT_EQUAL(norm(a * d), norm(a) * norm(d));
     }
 
     LOLUNIT_TEST(Base)
@@ -86,10 +86,10 @@ LOLUNIT_FIXTURE(QuaternionTest)
         quat k(0.0f, 0.0f, 1.0f, 0.0f);
         quat one(0.0f, 0.0f, 0.0f, 1.0f);
 
-        LOLUNIT_ASSERT_EQUAL(i.norm(), 1.0f);
-        LOLUNIT_ASSERT_EQUAL(j.norm(), 1.0f);
-        LOLUNIT_ASSERT_EQUAL(k.norm(), 1.0f);
-        LOLUNIT_ASSERT_EQUAL(one.norm(), 1.0f);
+        LOLUNIT_ASSERT_EQUAL(norm(i), 1.0f);
+        LOLUNIT_ASSERT_EQUAL(norm(j), 1.0f);
+        LOLUNIT_ASSERT_EQUAL(norm(k), 1.0f);
+        LOLUNIT_ASSERT_EQUAL(norm(one), 1.0f);
 
         LOLUNIT_ASSERT_EQUAL(i * i, -one);
         LOLUNIT_ASSERT_EQUAL(j * j, -one);
@@ -109,7 +109,7 @@ LOLUNIT_FIXTURE(QuaternionTest)
         quat a(2.0f, -2.0f, -8.0f, 3.0f);
         quat b = normalize(a);
 
-        LOLUNIT_ASSERT_DOUBLES_EQUAL(b.norm(), 1.0, 1e-8);
+        LOLUNIT_ASSERT_DOUBLES_EQUAL(norm(b), 1.0, 1e-8);
     }
 
     LOLUNIT_TEST(Reciprocal)