diff --git a/src/lol/math/bigint.h b/src/lol/math/bigint.h
index 8866bb81..a512d222 100644
--- a/src/lol/math/bigint.h
+++ b/src/lol/math/bigint.h
@@ -41,8 +41,8 @@ namespace lol
 template<unsigned int N = 16, typename T = uint32_t>
 class bigint
 {
-    int const bits_per_digit = sizeof(T) * 8 - 1;
-    T const digit_mask = ~((T)1 << bits_per_digit);
+    static int const bits_per_digit = sizeof(T) * 8 - 1;
+    static T const digit_mask = ~((T)1 << bits_per_digit);
 
 public:
     inline bigint()
@@ -123,6 +123,7 @@ public:
     {
         for (unsigned int i = 0; i < N; ++i)
             m_digits[i] &= x.m_digits[i];
+        return *this;
     }
 
     inline bigint<N,T> operator &(bigint<N,T> const &x) const
@@ -137,6 +138,7 @@ public:
     {
         for (unsigned int i = 0; i < N; ++i)
             m_digits[i] |= x.m_digits[i];
+        return *this;
     }
 
     inline bigint<N,T> operator |(bigint<N,T> const &x) const
@@ -151,6 +153,7 @@ public:
     {
         for (unsigned int i = 0; i < N; ++i)
             m_digits[i] ^= x.m_digits[i];
+        return *this;
     }
 
     inline bigint<N,T> operator ^(bigint<N,T> const &x) const
@@ -234,36 +237,7 @@ public:
     template<unsigned int M>
     bigint<N + M, T> operator *(bigint<M,T> const &x) const
     {
-        /* FIXME: other digit sizes are not supported */
-        static_assert(sizeof(T) == sizeof(uint32_t), "ensure T is uint32_t");
-
-        if (x.is_negative())
-            return -(*this * -x);
-        if (is_negative())
-            return -(-*this * x);
-
-        bigint<N + M> ret(0);
-        for (unsigned int i = 0; i < N; ++i)
-        {
-            T carry(0);
-            for (unsigned int j = 0; j < M; ++j)
-            {
-                uint64_t digit = ret.m_digits[i + j]
-                               + (uint64_t)m_digits[i] * x.m_digits[j]
-                               + carry;
-                ret.m_digits[i + j] = (T)digit & digit_mask;
-                carry = (digit >> bits_per_digit) & digit_mask;
-            }
-
-            for (unsigned int j = M; i + j < M + N && carry != 0; ++i)
-            {
-                T digit = ret.m_digits[i + j] + carry;
-                ret.m_digits[i + j] = (T)digit & digit_mask;
-                carry = (digit & ~digit_mask) ? T(1) : T(0);
-            }
-        }
-
-        return ret;
+        return mul_naive(*this, x);
     }
 
     /*
@@ -356,6 +330,37 @@ private:
         return ret;
     }
 
+    template<unsigned int M>
+    static inline bigint<N + M, T> mul_naive(bigint<N,T> const &a,
+                                             bigint<M,T> const &b)
+    {
+        /* FIXME: other digit sizes are not supported */
+        static_assert(sizeof(T) == sizeof(uint32_t), "ensure T is uint32_t");
+
+        bigint<N + M> ret(0);
+        for (unsigned int i = 0; i < N; ++i)
+        {
+            T carry(0);
+            for (unsigned int j = 0; j < M; ++j)
+            {
+                uint64_t digit = ret.m_digits[i + j]
+                               + (uint64_t)a.m_digits[i] * b.m_digits[j]
+                               + carry;
+                ret.m_digits[i + j] = (T)digit & a.digit_mask;
+                carry = (digit >> a.bits_per_digit) & a.digit_mask;
+            }
+
+            for (unsigned int j = M; i + j < M + N && carry != 0; ++i)
+            {
+                T digit = ret.m_digits[i + j] + carry;
+                ret.m_digits[i + j] = (T)digit & a.digit_mask;
+                carry = (digit & ~digit_mask) ? T(1) : T(0);
+            }
+        }
+
+        return ret;
+    }
+
     T m_digits[N];
 };
 
diff --git a/src/t/math/bigint.cpp b/src/t/math/bigint.cpp
index 94651b92..cf6590dc 100644
--- a/src/t/math/bigint.cpp
+++ b/src/t/math/bigint.cpp
@@ -219,6 +219,23 @@ lolunit_declare_fixture(bigint_test)
         lolunit_assert(e >= d);
         lolunit_assert(e >= e);
     }
+
+    lolunit_declare_test(multiply)
+    {
+        bigint<> a(-10), b(0), c(10);
+
+        lolunit_assert_equal((int32_t)(a * a), 100);
+        lolunit_assert_equal((int32_t)(a * b), 0);
+        lolunit_assert_equal((int32_t)(a * c), -100);
+
+        lolunit_assert_equal((int32_t)(b * a), 0);
+        lolunit_assert_equal((int32_t)(b * b), 0);
+        lolunit_assert_equal((int32_t)(b * c), 0);
+
+        lolunit_assert_equal((int32_t)(c * a), -100);
+        lolunit_assert_equal((int32_t)(c * b), 0);
+        lolunit_assert_equal((int32_t)(c * c), 100);
+    }
 };
 
 } /* namespace lol */