diff --git a/dune/xt/la/container/common.hh b/dune/xt/la/container/common.hh
index 8ae76d14a15e9e31f9b4a51d97dde0ac9067d9c8..01dbb6ede6c2d0912dc2655a33a03c671d7988f6 100644
--- a/dune/xt/la/container/common.hh
+++ b/dune/xt/la/container/common.hh
@@ -632,6 +632,11 @@ public:
 
   /// \}
 
+  using MatrixInterfaceType::operator+;
+  using MatrixInterfaceType::operator-;
+  using MatrixInterfaceType::operator+=;
+  using MatrixInterfaceType::operator-=;
+
 protected:
   /**
    * \see ContainerInterface
@@ -944,6 +949,18 @@ public:
 
   /// \}
 
+  using MatrixInterfaceType::operator+;
+  using MatrixInterfaceType::operator-;
+  using MatrixInterfaceType::operator+=;
+  using MatrixInterfaceType::operator-=;
+
+protected:
+  inline void ensure_uniqueness()
+  {
+    if (!entries_.unique())
+      entries_ = std::make_shared<EntriesVectorType>(*entries_);
+  } // ... ensure_uniqueness(...)
+
 private:
   size_t get_entry_index(const size_t rr, const size_t cc, const bool throw_if_not_in_pattern = true) const
   {
@@ -959,14 +976,6 @@ private:
     return size_t(-1);
   }
 
-protected:
-  inline void ensure_uniqueness()
-  {
-    if (!entries_.unique())
-      entries_ = std::make_shared<EntriesVectorType>(*entries_);
-  } // ... ensure_uniqueness(...)
-
-private:
   size_t num_rows_, num_cols_;
   std::shared_ptr<EntriesVectorType> entries_;
   std::shared_ptr<IndexVectorType> row_pointers_;
diff --git a/dune/xt/la/container/eigen/dense.hh b/dune/xt/la/container/eigen/dense.hh
index 5f261be8f732a43f20450ef49fb4fd93faae0023..cf926cff3a67c07281514b5a18766d3cffe5e462 100644
--- a/dune/xt/la/container/eigen/dense.hh
+++ b/dune/xt/la/container/eigen/dense.hh
@@ -647,6 +647,11 @@ public:
    * \}
    */
 
+  using MatrixInterfaceType::operator+;
+  using MatrixInterfaceType::operator-;
+  using MatrixInterfaceType::operator+=;
+  using MatrixInterfaceType::operator-=;
+
 protected:
   inline void ensure_uniqueness()
   {
diff --git a/dune/xt/la/container/eigen/sparse.hh b/dune/xt/la/container/eigen/sparse.hh
index 281f7fbbb98e8b7a9d7bcbf94fe24f2ab3f13a3e..799b42bb5dced8e0325568385043e057e3afc397 100644
--- a/dune/xt/la/container/eigen/sparse.hh
+++ b/dune/xt/la/container/eigen/sparse.hh
@@ -434,6 +434,11 @@ public:
 
   /// \}
 
+  using MatrixInterfaceType::operator+;
+  using MatrixInterfaceType::operator-;
+  using MatrixInterfaceType::operator+=;
+  using MatrixInterfaceType::operator-=;
+
 private:
   bool these_are_valid_indices(const size_t ii, const size_t jj) const
   {
diff --git a/dune/xt/la/container/istl.hh b/dune/xt/la/container/istl.hh
index fae0045618124f4f13e88013803aff2667bf358f..fac0a369c96a617c2c3e644a9fa63a38671b74f1 100644
--- a/dune/xt/la/container/istl.hh
+++ b/dune/xt/la/container/istl.hh
@@ -690,6 +690,11 @@ public:
 
   /// \}
 
+  using MatrixInterfaceType::operator+;
+  using MatrixInterfaceType::operator-;
+  using MatrixInterfaceType::operator+=;
+  using MatrixInterfaceType::operator-=;
+
 private:
   void build_sparse_matrix(const size_t rr, const size_t cc, const SparsityPatternDefault& patt)
   {
diff --git a/dune/xt/la/container/matrix-interface.hh b/dune/xt/la/container/matrix-interface.hh
index a3c4b6bcc1effaca089131706675f85d785cf8fb..62c1037cf88c5b71a735d025b4d0e6c5cd893075 100644
--- a/dune/xt/la/container/matrix-interface.hh
+++ b/dune/xt/la/container/matrix-interface.hh
@@ -114,6 +114,36 @@ public:
     CHECK_AND_CALL_CRTP(this->as_imp().unit_col(jj));
   }
 
+  template <class MM>
+  derived_type operator*(const MatrixInterface<MM, ScalarType>& other) const
+  {
+    return multiply(other);
+  }
+
+  template <class MM>
+  derived_type operator+(const MatrixInterface<MM, ScalarType>& other) const
+  {
+    return add(other);
+  }
+
+  template <class MM>
+  derived_type operator-(const MatrixInterface<MM, ScalarType>& other) const
+  {
+    return subtract(other);
+  }
+
+  template <class MM>
+  derived_type& operator+=(const MatrixInterface<MM, ScalarType>& other)
+  {
+    return add_assign(other);
+  }
+
+  template <class MM>
+  derived_type& operator-=(const MatrixInterface<MM, ScalarType>& other)
+  {
+    return subtract_assign(other);
+  }
+
   /**
    * \brief  Checks entries for inf or nan.
    * \return false if any entry is inf or nan, else true
@@ -148,6 +178,15 @@ public:
     return ret;
   } // ... sup_norm(...)
 
+  derived_type transposed() const
+  {
+    derived_type yy(rows(), cols(), 0.);
+    for (size_t rr = 0; rr < rows(); ++rr)
+      for (size_t cc = 0; cc < cols(); ++cc)
+        yy.set_entry(rr, cc, get_entry(cc, rr));
+    return yy;
+  }
+
   /**
    * \brief Returns the number of entries in the sparsity pattern of the matrix.
    *
@@ -243,6 +282,78 @@ public:
   } // ... almost_equal(...)
   /// \}
 
+protected:
+  template <class MM>
+  derived_type multiply(const MatrixInterface<MM, ScalarType>& other) const
+  {
+    if (other.rows() != cols())
+      DUNE_THROW(XT::Common::Exceptions::shapes_do_not_match, "Dimensions of matrices to be multiplied do not match!");
+    derived_type yy(rows(), other.cols(), 0.);
+    for (size_t rr = 0; rr < rows(); ++rr)
+      for (size_t cc = 0; cc < other.cols(); ++cc)
+        for (size_t kk = 0; kk < cols(); ++kk)
+          yy.add_to_entry(rr, cc, get_entry(rr, kk) * other.get_entry(kk, cc));
+    return yy;
+  }
+
+  template <class MM>
+  derived_type add(const MatrixInterface<MM, ScalarType>& other) const
+  {
+    if (other.rows() != rows() || other.cols() != cols())
+      DUNE_THROW(XT::Common::Exceptions::shapes_do_not_match, "Dimensions of matrices to be added do not match!");
+    auto new_pattern = pattern() + other.pattern();
+    derived_type yy(rows(), other.cols(), new_pattern);
+    for (size_t rr = 0; rr < rows(); ++rr)
+      for (const auto& cc : new_pattern[rr])
+        yy.set_entry(rr, cc, get_entry(rr, cc) + other.get_entry(rr, cc));
+    return yy;
+  }
+
+  template <class MM>
+  derived_type subtract(const MatrixInterface<MM, ScalarType>& other) const
+  {
+    if (other.rows() != rows() || other.cols() != cols())
+      DUNE_THROW(XT::Common::Exceptions::shapes_do_not_match, "Dimensions of matrices to be added do not match!");
+    auto new_pattern = pattern() + other.pattern();
+    derived_type yy(rows(), other.cols(), new_pattern);
+    for (size_t rr = 0; rr < rows(); ++rr)
+      for (const auto& cc : new_pattern[rr])
+        yy.set_entry(rr, cc, get_entry(rr, cc) - other.get_entry(rr, cc));
+    return yy;
+  }
+
+  template <class MM>
+  derived_type& add_assign(const MatrixInterface<MM, ScalarType>& other) const
+  {
+    if (other.rows() != rows() || other.cols() != cols())
+      DUNE_THROW(XT::Common::Exceptions::shapes_do_not_match, "Dimensions of matrices to be added do not match!");
+    const auto this_pattern = pattern();
+    auto new_pattern = this_pattern + other.pattern();
+    if (new_pattern != this_pattern)
+      DUNE_THROW(XT::Common::Exceptions::shapes_do_not_match,
+                 "The matrix to be added contains entries that are not in this' pattern!");
+    for (size_t rr = 0; rr < rows(); ++rr)
+      for (const auto& cc : this_pattern[rr])
+        add_to_entry(rr, cc, other.get_entry(rr, cc));
+    return this->as_imp();
+  }
+
+  template <class MM>
+  derived_type& subtract_assign(const MatrixInterface<MM, ScalarType>& other) const
+  {
+    if (other.rows() != rows() || other.cols() != cols())
+      DUNE_THROW(XT::Common::Exceptions::shapes_do_not_match, "Dimensions of matrices to be added do not match!");
+    const auto this_pattern = pattern();
+    auto new_pattern = this_pattern + other.pattern();
+    if (new_pattern != this_pattern)
+      DUNE_THROW(XT::Common::Exceptions::shapes_do_not_match,
+                 "The matrix to be added contains entries that are not in this' pattern!");
+    for (size_t rr = 0; rr < rows(); ++rr)
+      for (const auto& cc : this_pattern[rr])
+        add_to_entry(rr, cc, -other.get_entry(rr, cc));
+    return this->as_imp();
+  }
+
 private:
   template <class T, class S>
   friend std::ostream& operator<<(std::ostream& /*out*/, const MatrixInterface<T, S>& /*matrix*/);
diff --git a/dune/xt/la/container/pattern.cc b/dune/xt/la/container/pattern.cc
index edeb185c93f2931eeac87f2ce84f853e935bed96..a9ea0030169d9bcde457317a4495991af652d6d0 100644
--- a/dune/xt/la/container/pattern.cc
+++ b/dune/xt/la/container/pattern.cc
@@ -63,6 +63,17 @@ bool SparsityPatternDefault::operator!=(const SparsityPatternDefault& other) con
   return vector_of_vectors_ != other.vector_of_vectors_;
 }
 
+SparsityPatternDefault operator+(const SparsityPatternDefault& other) const
+{
+  assert(other.size() == size() && "SparsityPatterns must have the same number of rows for addition!");
+  SparsityPatternDefault ret = *this;
+  for (size_t rr = 0; rr < size(); ++rr)
+    for (const auto& cc : vector_of_vectors_[rr])
+      ret.insert(rr, cc);
+  ret.sort();
+  return ret;
+}
+
 void SparsityPatternDefault::insert(const size_t outer_index, const size_t inner_index)
 {
   assert(outer_index < size() && "Wrong index requested!");
diff --git a/dune/xt/la/container/pattern.hh b/dune/xt/la/container/pattern.hh
index 0a0e84873595ed90358f5ed17ad05eb8788a9d8f..aa36343a3eaaae6988c503d522758e028c420b75 100644
--- a/dune/xt/la/container/pattern.hh
+++ b/dune/xt/la/container/pattern.hh
@@ -45,6 +45,8 @@ public:
 
   bool operator!=(const SparsityPatternDefault& other) const;
 
+  SparsityPatternDefault operator+(const SparsityPatternDefault& other) const;
+
   void insert(const size_t outer_index, const size_t inner_index);
 
   void sort(const size_t outer_index);