+/**
+ * Provide a general tensor class with an arbitrary rank, i.e. with
+ * an arbitrary number of indices. The Tensor class provides an
+ * indexing operator and a bit of infrastructure, but most
+ * functionality is recursively handed down to tensors of rank 1 or
+ * put into external templated functions, e.g. the #contract# family.
+ *
+ * Using this tensor class for objects of rank to has advantages over
+ * matrices in many cases since the dimension is known to the compiler
+ * as well as the location of the data. It is therefore possible to
+ * produce far more efficient code than for matrices with
+ * runtime-dependant dimension.
+ */
template <int rank_, int dim>
class Tensor {
public:
/**
- * Provide a way to get the dimension of
- * an object without explicit knowledge
- * of it's data type. Implementation is
- * this way instead of providing a function
- * #dimension()# because now it is possible
- * to get the dimension at compile time
- * without the expansion and preevaluation
- * of an inlined function; the compiler may
- * therefore produce more efficient code
- * and you may use this value to declare
- * other data types.
+ * Provide a way to get the
+ * dimension of an object without
+ * explicit knowledge of it's
+ * data type. Implementation is
+ * this way instead of providing
+ * a function #dimension()#
+ * because now it is possible to
+ * get the dimension at compile
+ * time without the expansion and
+ * preevaluation of an inlined
+ * function; the compiler may
+ * therefore produce more
+ * efficient code and you may use
+ * this value to declare other
+ * data types.
*/
static const unsigned int dimension = dim;
*/
const Tensor<rank_-1,dim> &operator [] (const unsigned int i) const;
+ /**
+ * Assignment operator.
+ */
+ Tensor & operator = (const Tensor<rank_,dim> &);
+
+ /**
+ * Test for equality of two points.
+ */
+ bool operator == (const Tensor<rank_,dim> &) const;
+
+ /**
+ * Test for inequality of two points.
+ */
+ bool operator != (const Tensor<rank_,dim> &) const;
+
/**
* Reset all values to zero.
*/
void clear ();
-
+
/**
* Exception
* Array of tensors holding the
* subelements.
*/
- Tensor<rank-1,dim> subtensor[dim];
+ Tensor<rank_-1,dim> subtensor[dim];
};
-
/*--------------------------- Inline functions -----------------------------*/
-template <int rank, int dim>
+template <int rank_, int dim>
inline
-Tensor<rank-1,dim> &
-Tensor<rank,dim>::operator[] (const unsigned int i) {
+Tensor<rank_-1,dim> &
+Tensor<rank_,dim>::operator[] (const unsigned int i) {
Assert (i<dim, ExcInvalidIndex(i));
return subtensor[i];
-template <int rank, int dim>
+template <int rank_, int dim>
inline
-const Tensor<rank-1,dim> &
-Tensor<rank,dim>::operator[] (const unsigned int i) const {
+const Tensor<rank_-1,dim> &
+Tensor<rank_,dim>::operator[] (const unsigned int i) const {
Assert (i<dim, ExcInvalidIndex(i));
return subtensor[i];
-template <int rank, int dim>
+template <int rank_, int dim>
+inline
+Tensor<rank_,dim> & Tensor<rank_,dim>::operator = (const Tensor<rank_,dim> &t) {
+ for (unsigned int i=0; i<dim; ++i)
+ values[i] = t.values[i];
+ return *this;
+};
+
+
+
+template <int rank_, int dim>
+inline
+bool Tensor<rank_,dim>::operator == (const Tensor<rank_,dim> &p) const {
+ for (unsigned int i=0; i<dim; ++i)
+ if (values[i] != p.values[i]) return false;
+ return true;
+};
+
+
+
+template <int rank_, int dim>
+inline
+bool Tensor<rank_,dim>::operator != (const Tensor<rank_,dim> &p) const {
+ return !((*this) == p);
+};
+
+
+
+template <int rank_, int dim>
inline
-void Tensor<rank,dim>::clear () {
+void Tensor<rank_,dim>::clear () {
for (unsigned int i=0; i<dim; ++i)
subtensor[i].clear();
};
// everytime we use a point.
#include <base/exceptions.h>
+#include <iostream>
template <int rank, int dim> class Tensor;
-
+/**
+ * This class is a specialized version of the #Tensor<rank,dim># class.
+ * It handles tensors with one index, i.e. vectors, of fixed dimension
+ * and offers the functionality needed for tensors of higher rank.
+ *
+ * In many cases, you will want to use the more specialized #Point# class
+ * which acts as a tensor of rank one but has more functionality.
+ */
template <int dim>
class Tensor<1,dim> {
public:
/**
- * Provide a way to get the dimension of
- * an object without explicit knowledge
- * of it's data type. Implementation is
- * this way instead of providing a function
- * #dimension()# because now it is possible
- * to get the dimension at compile time
- * without the expansion and preevaluation
- * of an inlined function; the compiler may
- * therefore produce more efficient code
- * and you may use this value to declare
- * other data types.
+ * Provide a way to get the
+ * dimension of an object without
+ * explicit knowledge of it's
+ * data type. Implementation is
+ * this way instead of providing
+ * a function #dimension()#
+ * because now it is possible to
+ * get the dimension at compile
+ * time without the expansion and
+ * preevaluation of an inlined
+ * function; the compiler may
+ * therefore produce more
+ * efficient code and you may use
+ * this value to declare other
+ * data types.
*/
static const unsigned int dimension = dim;
double & operator [] (const unsigned int index);
/**
- * Reset all values to zero.
+ * Assignment operator.
*/
- void clear ();
-
+ Tensor<1,dim> & operator = (const Tensor<1,dim> &);
+
/**
- * Exception
+ * Test for equality of two points.
+ */
+ bool operator == (const Tensor<1,dim> &) const;
+
+ /**
+ * Test for inequality of two points.
*/
- DeclException1 (ExcDimTooSmall,
- int,
- << "Given dimensions must be >= 1, but was " << arg1);
+ bool operator != (const Tensor<1,dim> &) const;
/**
- * Exception
+ * Reset all values to zero.
*/
- DeclException1 (ExcInvalidIndex,
- int,
- << "Invalid index " << arg1);
+ void clear ();
+
protected:
/**
* Stores the values in a simple array.
+DeclException1 (ExcDimTooSmall,
+ int,
+ << "Given dimensions must be >= 1, but was " << arg1);
+DeclException1 (ExcInvalidIndex,
+ int,
+ << "Invalid index " << arg1);
+
+
+
+
+ /**
+ * Prints the values of this point in the
+ * form #x1 x2 x3 etc#.
+ */
+template <int dim>
+ostream & operator << (ostream &out, const Tensor<1,dim> &p);
+
+
+
+
+
+
/*------------------------------- Inline functions: Tensor ---------------------------*/
+template <int dim>
+inline
+Tensor<1,dim> & Tensor<1,dim>::operator = (const Tensor<1,dim> &p) {
+ for (unsigned int i=0; i<dim; ++i)
+ values[i] = p.values[i];
+ return *this;
+};
+
+
+
+template <int dim>
+inline
+bool Tensor<1,dim>::operator == (const Tensor<1,dim> &p) const {
+ for (unsigned int i=0; i<dim; ++i)
+ if (values[i] != p.values[i]) return false;
+ return true;
+};
+
+
+
+template <int dim>
+inline
+bool Tensor<1,dim>::operator != (const Tensor<1,dim> &p) const {
+ return !((*this) == p);
+};
+
+
+
template <int dim>
inline
void Tensor<1,dim>::clear () {
+
+
+template <int dim>
+inline
+ostream & operator << (ostream &out, const Tensor<1,dim> &p) {
+ for (unsigned int i=0; i<dim-1; ++i)
+ out << p[i] << ' ';
+ out << p[dim-1];
+
+ if (!out)
+ throw GlobalExcIO ();
+
+ return out;
+};
+
+
+template <>
+inline
+ostream & operator << (ostream &out, const Tensor<1,1> &p) {
+ out << p[0];
+
+ if (!out)
+ throw GlobalExcIO ();
+
+ return out;
+};
+
+
+
+
+
+
/*---------------------------- tensor_base.h ---------------------------*/
/* end of #ifndef __tensor_base_H */
#endif