diff --git a/src/utils/Array.hpp b/src/utils/Array.hpp
index 7535b673565fa04aadba3935420f6946f5ad5544..3ee64824a650e18714a9b4b8523afb78cc89f643 100644
--- a/src/utils/Array.hpp
+++ b/src/utils/Array.hpp
@@ -24,6 +24,18 @@ class [[nodiscard]] Array
     const size_t m_size;
 
    public:
+    friend std::ostream&
+    operator<<(std::ostream& os, const UnsafeArrayView& x)
+    {
+      if (x.size() > 0) {
+        os << 0 << ':' << NaNHelper(x[0]);
+      }
+      for (size_t i = 1; i < x.size(); ++i) {
+        os << ' ' << i << ':' << NaNHelper(x[i]);
+      }
+      return os;
+    }
+
     [[nodiscard]] PUGS_INLINE size_t
     size() const
     {
diff --git a/src/utils/Table.hpp b/src/utils/Table.hpp
index 6972ea1030dedbdd30c039e0880a3773024603dc..a4a134dfd1d5838766b062eb429c725eb66bbb33 100644
--- a/src/utils/Table.hpp
+++ b/src/utils/Table.hpp
@@ -63,6 +63,19 @@ class [[nodiscard]] Table
       Assert(row < table.numberOfRows(), "required row view is not contained in the Table");
     }
 
+    friend std::ostream&
+    operator<<(std::ostream& os, const UnsafeRowView& x)
+    {
+      if (x.size() > 0) {
+        os << 0 << ':' << NaNHelper(x[0]);
+      }
+      for (size_t i = 1; i < x.size(); ++i) {
+        os << ' ' << i << ':' << NaNHelper(x[i]);
+      }
+
+      return os;
+    }
+
     // To try to keep these views close to the initial array one
     // forbids copy constructor and take benefits of C++-17 copy
     // elisions.
@@ -113,6 +126,19 @@ class [[nodiscard]] Table
         }
       }
 
+      friend std::ostream&
+      operator<<(std::ostream& os, const RowView& x)
+      {
+        if (x.size() > 0) {
+          os << 0 << ':' << NaNHelper(x[0]);
+        }
+        for (size_t i = 1; i < x.size(); ++i) {
+          os << ' ' << i << ':' << NaNHelper(x[i]);
+        }
+
+        return os;
+      }
+
       RowView(const UnsafeTableView& table_view, index_type row) : m_table_view{table_view}, m_row{row}
       {
         Assert(row < m_table_view.numberOfRows(), "required row view is not contained in the Table view");
@@ -155,6 +181,19 @@ class [[nodiscard]] Table
       return m_table(m_row_begin + i, m_column_begin + j);
     }
 
+    friend std::ostream&
+    operator<<(std::ostream& os, const UnsafeTableView& t)
+    {
+      for (size_t i = 0; i < t.numberOfRows(); ++i) {
+        os << i << '|';
+        for (size_t j = 0; j < t.numberOfColumns(); ++j) {
+          os << ' ' << j << ':' << NaNHelper(t(i, j));
+        }
+        os << '\n';
+      }
+      return os;
+    }
+
     PUGS_INLINE void
     fill(const DataType& data) const
     {