From c5f816a82f6b9c5ab0b81cbc6dc7fa53c2e6c904 Mon Sep 17 00:00:00 2001
From: Christian Engwer <christi@dune-project.org>
Date: Thu, 7 Feb 2008 21:37:43 +0000
Subject: [PATCH] as a present for markus I implemented an assignment for
 FieldMatrix.

example:

FieldMatrix<2,3> A;

A <<= 1,2,3, nextRow,
             3,4,5;

[[Imported from SVN: r5080]]
---
 common/fassign.hh          | 138 ++++++++++++++++++++++++++++++++++++-
 common/test/Makefile.am    |  32 +++++++--
 common/test/testfassign.cc |  44 ++++++++++--
 3 files changed, 200 insertions(+), 14 deletions(-)

diff --git a/common/fassign.hh b/common/fassign.hh
index c0da21209..efe7778bc 100644
--- a/common/fassign.hh
+++ b/common/fassign.hh
@@ -4,6 +4,7 @@
 #define DUNE_ASSIGN_HH
 
 #include <dune/common/fvector.hh>
+#include <dune/common/fmatrix.hh>
 
 namespace Dune {
 
@@ -11,10 +12,11 @@ namespace Dune {
    * Emtpy namespace make this class and the object local to one object file
    */
   namespace {
+
     /**
      *  @brief Initializer class for
      *
-     *  overload operator <<= for fvector assignment from Dune::Zero
+     *  overload operator <<= for FieldVector assignment from Dune::Zero
      */
     class Zero {
       /** \brief Conversion operator to double */
@@ -22,6 +24,14 @@ namespace Dune {
       /** \brief Conversion operator to int */
       operator int () { return 0; }
     } zero;
+
+    /**
+     *  @brief Marker class for next row
+     *
+     *  overload operator <<= for FiledMatrix assignment
+     */
+    class NextRow {} nextRow;
+
   } // end empty namespace
 
   /**
@@ -125,6 +135,132 @@ namespace Dune {
     return fvector_assigner<T,s>(v,true).append(z);
   }
 
+  /**
+   *  @brief fvector assignment operator
+   *
+   *  overload operator <<= for fvector assignment from Dune::Zero
+   *
+   *  after including fassing.hh you can easily assign data to a FieldVector
+   *  using
+   *
+   *  @code
+   *  FieldVector<double, 4> x; x <<= 1.0, 4.0, 10.0, 11.0;
+   *  @endcode
+   *
+   *  The operator checks that the whole vector is initalized.
+   *  In case you know that all following entries will be zero padded, you can use
+   *
+   *  @code
+   *  FieldVector<double, 40> x; x <<= 1.0, 4.0, 10.0, 11.0, zero;
+   *  @endcode
+   *
+   */
+  template <class T, int n, int m>
+  class fmatrix_assigner
+  {
+  private:
+    FieldMatrix<T,n,m> & A;
+    int c;
+    int r;
+    bool temporary;
+    void end_row()
+    {
+      if (!temporary && c!=m)
+        DUNE_THROW(MathError, "Trying to assign " << c <<
+                   " entries to a FieldMatrix row of size " << m);
+      c=0;
+    }
+  public:
+    /*! @brief Copy Constructor */
+    fmatrix_assigner(fmatrix_assigner & a) : A(a.A), c(a.c), r(a.r), temporary(false)
+    {}
+    /*! @brief Constructor from matrix and temporary flag
+       \param v matrix which should be initialized
+       \param t bool indicating, that this is a temporary object (see ~fmatrix_assigner)
+     */
+    fmatrix_assigner(FieldMatrix<T,n,m> & _A, bool t) : A(_A), c(0), r(0), temporary(t)
+    {};
+    /*! @brief Destructor
+       checks for complete initialization of the matrix.
+       The check is skipped, if this object is marked temporary.
+     */
+    ~fmatrix_assigner()
+    {
+      end_row();
+      if (!temporary && r!=n-1)
+        DUNE_THROW(MathError, "Trying to assign " << r <<
+                   " rows to a FieldMatrix of size " << n << " x " << m);
+    }
+    /*! @brief append data to this matrix */
+    fmatrix_assigner & append (const T & t)
+    {
+      A[r][c++] = t;
+      return *this;
+    }
+    /*! @brief append zeros to this matrix
+     */
+    fmatrix_assigner & append (Zero z)
+    {
+      while (c!=m) A[r][c++] = 0;
+      return *this;
+    }
+    /*! @brief append zeros to this matrix
+     */
+    fmatrix_assigner & append (NextRow nr)
+    {
+      end_row();
+      r++;
+      return *this;
+    }
+    /*! @brief append data to this matrix
+       the overloaded comma operator is used to assign a comma seperated list
+       of values to the matrix
+     */
+    fmatrix_assigner & operator , (const T & t)
+    {
+      return append(t);
+    }
+    /*! @brief append zeros to this matrix
+       the overloaded comma operator is used to stop the assign of values
+       to the matrix, all remaining entries are assigned 0.
+     */
+    fmatrix_assigner & operator , (Zero z)
+    {
+      return append(z);
+    }
+    /*! @brief append zeros to this matrix
+       the overloaded comma operator is used to stop the assign of values
+       to the matrix, all remaining entries are assigned 0.
+     */
+    fmatrix_assigner & operator , (NextRow nr)
+    {
+      return append(nr);
+    }
+  };
+
+  /**
+   *  @brief FieldMatrix assignment operator
+   *
+   *  overload operator <<= for FieldMatrix assignment
+   *  from comma seperated list of values
+   */
+  template <class T, int n, int m>
+  fmatrix_assigner<T,n,m> operator <<= (FieldMatrix<T,n,m> & v, const T & t)
+  {
+    return fmatrix_assigner<T,n,m>(v,true).append(t);
+  }
+
+  /**
+   *  @brief fFileMatrix assignment operator
+   *
+   *  overload operator <<= for FieldMatrix row assignment from Dune::Zero
+   */
+  template <class T, int n, int m>
+  fmatrix_assigner<T,n,m> operator <<= (FieldMatrix<T,n,m> & v, Zero z)
+  {
+    return fmatrix_assigner<T,n,m>(v,true).append(z);
+  }
+
 } // end namespace Dune
 
 #endif // DUNE_ASSIGN_HH
diff --git a/common/test/Makefile.am b/common/test/Makefile.am
index ba503917a..aa7596fc9 100644
--- a/common/test/Makefile.am
+++ b/common/test/Makefile.am
@@ -6,13 +6,16 @@ TESTPROGS = parsetest test-stack arraylisttest smartpointertest \
 	bigunsignedinttest mpihelpertest singletontest mpicollcomm \
 	utilitytest lrutest \
 	testfassign1 testfassign2 testfassign3 \
-    testfassign_fail1 testfassign_fail2
+	testfassign4 \
+    testfassign_fail1 testfassign_fail2 testfassign_fail3\
+    testfassign_fail4 testfassign_fail5 testfassign_fail6
 
 
 # which tests to run
 TESTS = $(TESTPROGS)
 
-XFAIL_TESTS = testfassign_fail1 testfassign_fail2
+XFAIL_TESTS = testfassign_fail1 testfassign_fail2 testfassign_fail3\
+    testfassign_fail4 testfassign_fail5 testfassign_fail6
 
 # programs just to build when "make check" is used
 check_PROGRAMS = $(TESTPROGS)
@@ -82,19 +85,34 @@ utilitytest_SOURCES = utilitytest.cc
 utilitytest_LDFLAGS = $(LOCAL_LIBS)
 
 testfassign1_SOURCES = testfassign.cc testfassign2.cc
-testfassign1_CPPFLAGS = $(AM_CPPFLAGS) -D_SIZE=3 -D_VALUES="1,2,3"
+testfassign1_CPPFLAGS = $(AM_CPPFLAGS) -D_N=3 -D_VALUES="1,2,3"
 
 testfassign2_SOURCES = testfassign.cc
-testfassign2_CPPFLAGS = $(AM_CPPFLAGS) -D_SIZE=3 -D_VALUES="1,Dune::zero"
+testfassign2_CPPFLAGS = $(AM_CPPFLAGS) -D_N=3 -D_VALUES="1,zero"
 
 testfassign3_SOURCES = testfassign.cc
-testfassign3_CPPFLAGS = $(AM_CPPFLAGS) -D_SIZE=3 -D_VALUES="Dune::zero"
+testfassign3_CPPFLAGS = $(AM_CPPFLAGS) -D_N=3 -D_VALUES="zero"
+
+testfassign4_SOURCES = testfassign.cc
+testfassign4_CPPFLAGS = $(AM_CPPFLAGS) -D_N=2 -D_M=3 -D_VALUES="1, zero, nextRow, 2, 3, 4"
 
 testfassign_fail1_SOURCES = testfassign.cc
-testfassign_fail1_CPPFLAGS = $(AM_CPPFLAGS) -D_SIZE=3 -D_VALUES="1,2"
+testfassign_fail1_CPPFLAGS = $(AM_CPPFLAGS) -D_N=3 -D_VALUES="1,2"
 
 testfassign_fail2_SOURCES = testfassign.cc
-testfassign_fail2_CPPFLAGS = $(AM_CPPFLAGS) -D_SIZE=3 -D_VALUES="1,2,3,4"
+testfassign_fail2_CPPFLAGS = $(AM_CPPFLAGS) -D_N=3 -D_VALUES="1,2,3,4"
+
+testfassign_fail3_SOURCES = testfassign.cc
+testfassign_fail3_CPPFLAGS = $(AM_CPPFLAGS) -D_N=2 -D_M=2 -D_VALUES="1, nextRow, 2, 3"
+
+testfassign_fail4_SOURCES = testfassign.cc
+testfassign_fail4_CPPFLAGS = $(AM_CPPFLAGS) -D_N=2 -D_M=2 -D_VALUES="1, 2, 3, nextRow, 2, 3"
+
+testfassign_fail5_SOURCES = testfassign.cc
+testfassign_fail5_CPPFLAGS = $(AM_CPPFLAGS) -D_N=2 -D_M=2 -D_VALUES="1, 2"
+
+testfassign_fail6_SOURCES = testfassign.cc
+testfassign_fail6_CPPFLAGS = $(AM_CPPFLAGS) -D_N=2 -D_M=2 -D_VALUES="1, 2, nextRow, 2, 3, nextRow, 4, 5"
 
 sourcescheck_NOSOURCES = exprtmpl.cc timing.cc
 
diff --git a/common/test/testfassign.cc b/common/test/testfassign.cc
index ce2c5863c..ae5a18891 100644
--- a/common/test/testfassign.cc
+++ b/common/test/testfassign.cc
@@ -5,17 +5,49 @@
 #include <dune/common/fvector.hh>
 #include <dune/common/fassign.hh>
 
+using Dune::zero;
+using Dune::nextRow;
+
+template<class T> struct Print {};
+
+template<int s>
+struct Print< Dune::FieldVector<int,s> >
+{
+  static void print(Dune::FieldVector<int,s> & v)
+  {
+    for (int i=0; i<s; i++)
+      std::cout << "value[" << i << "] = " << v[i] << "\n";
+  }
+};
+
+template<int n, int m>
+struct Print< Dune::FieldMatrix<int,n,m> >
+{
+  static void print(Dune::FieldMatrix<int,n,m> & A)
+  {
+    for (int i=0; i<n; i++)
+      for (int j=0; j<m; j++)
+        std::cout << "value[" << i << "][" << j << "] = " << A[i][j] << "\n";
+  }
+};
+
+template<class T>
+void print(T & t) {
+  Print<T>::print(t);
+}
+
 int main ()
 {
   try
   {
-    static const int sz = _SIZE;
-    Dune::FieldVector<int,sz> v;
-
-    v <<= _VALUES;
+#ifdef _M
+    Dune::FieldMatrix<int,_N,_M> x;
+#else
+    Dune::FieldVector<int,_N> x;
+#endif
 
-    for (int i=0; i<sz; i++)
-      std::cout << "value[" << i << "] = " << v[i] << "\n";
+    x <<= _VALUES;
+    print(x);
 
     return 0;
   }
-- 
GitLab