diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 4eff7bbdfa88c402b238c94acddb1ab8e80002ae..714479919d1c6eed6d8ef3511694f966143d2b54 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -98,6 +98,7 @@ add_executable (unit_tests
   test_PugsUtils.cpp
   test_RevisionInfo.cpp
   test_SmallArray.cpp
+  test_SmallVector.cpp
   test_SymbolTable.cpp
   test_Table.cpp
   test_Timer.cpp
diff --git a/tests/test_SmallVector.cpp b/tests/test_SmallVector.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3b499c3ab3e984247b7f20f96b626f8ee413763a
--- /dev/null
+++ b/tests/test_SmallVector.cpp
@@ -0,0 +1,472 @@
+#include <catch2/catch_test_macros.hpp>
+#include <catch2/matchers/catch_matchers_all.hpp>
+
+#include <utils/PugsAssert.hpp>
+
+#include <algebra/SmallVector.hpp>
+#include <algebra/TinyVector.hpp>
+
+// Instantiate to ensure full coverage is performed
+template class SmallVector<int>;
+
+// clazy:excludeall=non-pod-global-static
+
+TEST_CASE("SmallVector", "[algebra]")
+{
+  SECTION("size")
+  {
+    SmallVector<int> x{5};
+    REQUIRE(x.size() == 5);
+  }
+
+  SECTION("write access")
+  {
+    SmallVector<int> x{5};
+    x[0] = 0;
+    x[1] = 1;
+    x[2] = 2;
+    x[3] = 3;
+    x[4] = 4;
+
+    REQUIRE(x[0] == 0);
+    REQUIRE(x[1] == 1);
+    REQUIRE(x[2] == 2);
+    REQUIRE(x[3] == 3);
+    REQUIRE(x[4] == 4);
+  }
+
+  SECTION("fill")
+  {
+    SmallVector<int> x{5};
+    x.fill(2);
+
+    REQUIRE(x[0] == 2);
+    REQUIRE(x[1] == 2);
+    REQUIRE(x[2] == 2);
+    REQUIRE(x[3] == 2);
+    REQUIRE(x[4] == 2);
+  }
+
+  SECTION("copy constructor (shallow)")
+  {
+    SmallVector<int> x{5};
+    x[0] = 0;
+    x[1] = 1;
+    x[2] = 2;
+    x[3] = 3;
+    x[4] = 4;
+
+    const SmallVector<int> y = x;
+    REQUIRE(y[0] == 0);
+    REQUIRE(y[1] == 1);
+    REQUIRE(y[2] == 2);
+    REQUIRE(y[3] == 3);
+    REQUIRE(y[4] == 4);
+  }
+
+  SECTION("copy constructor (move)")
+  {
+    SmallVector<int> x{5};
+    x[0] = 0;
+    x[1] = 1;
+    x[2] = 2;
+    x[3] = 3;
+    x[4] = 4;
+
+    const SmallVector<int> y = std::move(x);
+    REQUIRE(y[0] == 0);
+    REQUIRE(y[1] == 1);
+    REQUIRE(y[2] == 2);
+    REQUIRE(y[3] == 3);
+    REQUIRE(y[4] == 4);
+  }
+
+  SECTION("copy (shallow)")
+  {
+    SmallVector<int> x{5};
+    x[0] = 0;
+    x[1] = 1;
+    x[2] = 2;
+    x[3] = 3;
+    x[4] = 4;
+
+    SmallVector<int> y{5};
+    y = x;
+    REQUIRE(y[0] == 0);
+    REQUIRE(y[1] == 1);
+    REQUIRE(y[2] == 2);
+    REQUIRE(y[3] == 3);
+    REQUIRE(y[4] == 4);
+
+    x[0] = 14;
+    x[1] = 13;
+    x[2] = 12;
+    x[3] = 11;
+    x[4] = 10;
+
+    REQUIRE(x[0] == 14);
+    REQUIRE(x[1] == 13);
+    REQUIRE(x[2] == 12);
+    REQUIRE(x[3] == 11);
+    REQUIRE(x[4] == 10);
+
+    REQUIRE(y[0] == 14);
+    REQUIRE(y[1] == 13);
+    REQUIRE(y[2] == 12);
+    REQUIRE(y[3] == 11);
+    REQUIRE(y[4] == 10);
+  }
+
+  SECTION("copy (deep)")
+  {
+    SmallVector<int> x{5};
+    x[0] = 0;
+    x[1] = 1;
+    x[2] = 2;
+    x[3] = 3;
+    x[4] = 4;
+
+    SmallVector<int> y{5};
+    y = copy(x);
+
+    x[0] = 14;
+    x[1] = 13;
+    x[2] = 12;
+    x[3] = 11;
+    x[4] = 10;
+
+    REQUIRE(y[0] == 0);
+    REQUIRE(y[1] == 1);
+    REQUIRE(y[2] == 2);
+    REQUIRE(y[3] == 3);
+    REQUIRE(y[4] == 4);
+
+    REQUIRE(x[0] == 14);
+    REQUIRE(x[1] == 13);
+    REQUIRE(x[2] == 12);
+    REQUIRE(x[3] == 11);
+    REQUIRE(x[4] == 10);
+  }
+
+  SECTION("copy to const (shallow)")
+  {
+    SmallVector<int> x{5};
+    x[0] = 0;
+    x[1] = 1;
+    x[2] = 2;
+    x[3] = 3;
+    x[4] = 4;
+
+    SmallVector<const int> y;
+    y = x;
+    REQUIRE(y[0] == 0);
+    REQUIRE(y[1] == 1);
+    REQUIRE(y[2] == 2);
+    REQUIRE(y[3] == 3);
+    REQUIRE(y[4] == 4);
+
+    SmallVector<int> z{5};
+    z[0] = 14;
+    z[1] = 13;
+    z[2] = 12;
+    z[3] = 11;
+    z[4] = 10;
+
+    y = z;
+    REQUIRE(z[0] == 14);
+    REQUIRE(z[1] == 13);
+    REQUIRE(z[2] == 12);
+    REQUIRE(z[3] == 11);
+    REQUIRE(z[4] == 10);
+
+    REQUIRE(y[0] == 14);
+    REQUIRE(y[1] == 13);
+    REQUIRE(y[2] == 12);
+    REQUIRE(y[3] == 11);
+    REQUIRE(y[4] == 10);
+  }
+
+  SECTION("self scalar multiplication")
+  {
+    SmallVector<int> x{5};
+    x[0] = 0;
+    x[1] = 1;
+    x[2] = 2;
+    x[3] = 3;
+    x[4] = 4;
+
+    x *= 2;
+
+    REQUIRE(x[0] == 0);
+    REQUIRE(x[1] == 2);
+    REQUIRE(x[2] == 4);
+    REQUIRE(x[3] == 6);
+    REQUIRE(x[4] == 8);
+  }
+
+  SECTION("left scalar multiplication")
+  {
+    SmallVector<int> x{5};
+    x[0] = 0;
+    x[1] = 1;
+    x[2] = 2;
+    x[3] = 3;
+    x[4] = 4;
+
+    const SmallVector<int> y = 2 * x;
+
+    REQUIRE(y[0] == 0);
+    REQUIRE(y[1] == 2);
+    REQUIRE(y[2] == 4);
+    REQUIRE(y[3] == 6);
+    REQUIRE(y[4] == 8);
+  }
+
+  SECTION("dot product")
+  {
+    SmallVector<int> x{5};
+    x[0] = 0;
+    x[1] = 1;
+    x[2] = 2;
+    x[3] = 3;
+    x[4] = 4;
+
+    SmallVector<int> y{5};
+    y[0] = 7;
+    y[1] = 3;
+    y[2] = 4;
+    y[3] = 2;
+    y[4] = 8;
+
+    const int s = dot(x, y);
+    REQUIRE(s == 49);
+  }
+
+  SECTION("self scalar division")
+  {
+    SmallVector<int> x{5};
+    x[0] = 2;
+    x[1] = 3;
+    x[2] = 5;
+    x[3] = 7;
+    x[4] = 8;
+
+    x /= 2;
+
+    REQUIRE(x[0] == 1);
+    REQUIRE(x[1] == 1);
+    REQUIRE(x[2] == 2);
+    REQUIRE(x[3] == 3);
+    REQUIRE(x[4] == 4);
+  }
+
+  SECTION("self minus")
+  {
+    SmallVector<int> x{5};
+    x[0] = 2;
+    x[1] = 3;
+    x[2] = 5;
+    x[3] = 7;
+    x[4] = 8;
+
+    SmallVector<int> y{5};
+    y[0] = 3;
+    y[1] = 8;
+    y[2] = 6;
+    y[3] = 2;
+    y[4] = 4;
+
+    x -= y;
+
+    REQUIRE(x[0] == -1);
+    REQUIRE(x[1] == -5);
+    REQUIRE(x[2] == -1);
+    REQUIRE(x[3] == 5);
+    REQUIRE(x[4] == 4);
+  }
+
+  SECTION("self sum")
+  {
+    SmallVector<int> x{5};
+    x[0] = 2;
+    x[1] = 3;
+    x[2] = 5;
+    x[3] = 7;
+    x[4] = 8;
+
+    SmallVector<int> y{5};
+    y[0] = 3;
+    y[1] = 8;
+    y[2] = 6;
+    y[3] = 2;
+    y[4] = 4;
+
+    x += y;
+
+    REQUIRE(x[0] == 5);
+    REQUIRE(x[1] == 11);
+    REQUIRE(x[2] == 11);
+    REQUIRE(x[3] == 9);
+    REQUIRE(x[4] == 12);
+  }
+
+  SECTION("sum")
+  {
+    SmallVector<int> x{5};
+    x[0] = 2;
+    x[1] = 3;
+    x[2] = 5;
+    x[3] = 7;
+    x[4] = 8;
+
+    SmallVector<int> y{5};
+    y[0] = 3;
+    y[1] = 8;
+    y[2] = 6;
+    y[3] = 2;
+    y[4] = 4;
+
+    SmallVector z = x + y;
+
+    REQUIRE(z[0] == 5);
+    REQUIRE(z[1] == 11);
+    REQUIRE(z[2] == 11);
+    REQUIRE(z[3] == 9);
+    REQUIRE(z[4] == 12);
+  }
+
+  SECTION("difference")
+  {
+    SmallVector<int> x{5};
+    x[0] = 2;
+    x[1] = 3;
+    x[2] = 5;
+    x[3] = 7;
+    x[4] = 8;
+
+    SmallVector<int> y{5};
+    y[0] = 3;
+    y[1] = 8;
+    y[2] = 6;
+    y[3] = 2;
+    y[4] = 4;
+
+    SmallVector z = x - y;
+
+    REQUIRE(z[0] == -1);
+    REQUIRE(z[1] == -5);
+    REQUIRE(z[2] == -1);
+    REQUIRE(z[3] == 5);
+    REQUIRE(z[4] == 4);
+  }
+
+  SECTION("output")
+  {
+    SmallVector<int> x{5};
+    x[0] = 3;
+    x[1] = 7;
+    x[2] = 2;
+    x[3] = 1;
+    x[4] = -4;
+
+    std::ostringstream vector_ost;
+    vector_ost << x;
+    std::ostringstream ref_ost;
+    ref_ost << 0 << ':' << x[0];
+    for (size_t i = 1; i < x.size(); ++i) {
+      ref_ost << ' ' << i << ':' << x[i];
+    }
+    REQUIRE(vector_ost.str() == ref_ost.str());
+  }
+
+  SECTION("SmallVector from TinyVector")
+  {
+    TinyVector<5> tiny_vector{1, 3, 5, 7, 9};
+
+    SmallVector vector{tiny_vector};
+
+    REQUIRE(vector[0] == 1);
+    REQUIRE(vector[1] == 3);
+    REQUIRE(vector[2] == 5);
+    REQUIRE(vector[3] == 7);
+    REQUIRE(vector[4] == 9);
+
+    SECTION("ensures deep copy")
+    {
+      tiny_vector = zero;
+
+      REQUIRE(tiny_vector[0] == 0);
+      REQUIRE(tiny_vector[1] == 0);
+      REQUIRE(tiny_vector[2] == 0);
+      REQUIRE(tiny_vector[3] == 0);
+      REQUIRE(tiny_vector[4] == 0);
+
+      REQUIRE(vector[0] == 1);
+      REQUIRE(vector[1] == 3);
+      REQUIRE(vector[2] == 5);
+      REQUIRE(vector[3] == 7);
+      REQUIRE(vector[4] == 9);
+    }
+  }
+
+#ifndef NDEBUG
+
+  SECTION("output with signaling NaN")
+  {
+    SmallVector<double> x{5};
+    x[0] = 3;
+    x[2] = 2;
+
+    std::ostringstream vector_ost;
+    vector_ost << x;
+    std::ostringstream ref_ost;
+    ref_ost << 0 << ':' << 3 << ' ';
+    ref_ost << 1 << ":nan ";
+    ref_ost << 2 << ':' << 2 << ' ';
+    ref_ost << 3 << ":nan ";
+    ref_ost << 4 << ":nan";
+    REQUIRE(vector_ost.str() == ref_ost.str());
+  }
+
+  SECTION("invalid dot product")
+  {
+    SmallVector<int> x{5};
+    SmallVector<int> y{4};
+
+    REQUIRE_THROWS_WITH(dot(x, y), "cannot compute dot product: incompatible vector sizes");
+  }
+
+  SECTION("invalid substract")
+  {
+    SmallVector<int> x{5};
+    SmallVector<int> y{4};
+
+    REQUIRE_THROWS_WITH(x -= y, "cannot substract vector: incompatible sizes");
+  }
+
+  SECTION("invalid add")
+  {
+    SmallVector<int> x{5};
+    SmallVector<int> y{4};
+
+    REQUIRE_THROWS_WITH(x += y, "cannot add vector: incompatible sizes");
+  }
+
+  SECTION("invalid difference")
+  {
+    SmallVector<int> x{5};
+    SmallVector<int> y{4};
+
+    REQUIRE_THROWS_WITH(x - y, "cannot compute vector difference: incompatible sizes");
+  }
+
+  SECTION("invalid sum")
+  {
+    SmallVector<int> x{5};
+    SmallVector<int> y{4};
+
+    REQUIRE_THROWS_WITH(x + y, "cannot compute vector sum: incompatible sizes");
+  }
+
+#endif   // NDEBUG
+}