/* * Tensor1Expression.h * @brief Tensor expression templates based on http://www.gps.caltech.edu/~walter/FTensor/FTensor.pdf * Created on: Feb 10, 2010 * @author: Frank Dellaert */ #pragma once #include #include #include #include "tensors.h" namespace tensors { /** * Templated class to provide a rank 1 tensor interface to a class. * This class does not store any data but the result of an expression. * It is associated with an index. */ template class Tensor1Expression { private: A iter; typedef Tensor1Expression This; /** Helper class for multiplying with a double */ class TimesDouble_ { A iter; const double s; public: TimesDouble_(const A &a, double s_) : iter(a), s(s_) { } inline double operator()(int i) const { return iter(i) * s; } }; public: /** constructor */ Tensor1Expression(const A &a) : iter(a) { } /** Print */ void print(const std::string s = "") const { std::cout << s << "{"; std::cout << (*this)(0); for (int i = 1; i < I::dim; i++) std::cout << ", "<< (*this)(i); std::cout << "}" << std::endl; } template bool equals(const Tensor1Expression & q, double tol) const { for (int i = 0; i < I::dim; i++) if (fabs((*this)(i) - q(i)) > tol) return false; return true; } /** norm */ double norm() const { double sumsqr = 0.0; for (int i = 0; i < I::dim; i++) sumsqr += iter(i) * iter(i); return sqrt(sumsqr); } template bool equivalent(const Tensor1Expression & q, double tol = 1e-9) const { return ((*this) * (1.0 / norm())).equals(q * (1.0 / q.norm()), tol); } /** Check if two expressions are equal */ template bool operator==(const Tensor1Expression& e) const { for (int i = 0; i < I::dim; i++) if (iter(i) != e(i)) return false; return true; } /** element access */ double operator()(int i) const { return iter(i); } /** mutliply with a double. */ inline Tensor1Expression operator*(double s) const { return TimesDouble_(iter, s); } /** Class for contracting two rank 1 tensor expressions, yielding a double. */ template inline double operator*(const Tensor1Expression &b) const { double sum = 0.0; for (int i = 0; i < I::dim; i++) sum += (*this)(i) * b(i); return sum; } }; // Tensor1Expression /** Print a rank 1 expression */ template void print(const Tensor1Expression& T, const std::string s = "") { T.print(s); } /** norm */ template double norm(const Tensor1Expression& T) { return T.norm(); } /** * This template works for any two expressions */ template bool assert_equality(const Tensor1Expression& expected, const Tensor1Expression& actual, double tol = 1e-9) { if (actual.equals(expected, tol)) return true; std::cout << "Not equal:\n"; expected.print("expected:\n"); actual.print("actual:\n"); return false; } /** * This template works for any two expressions */ template bool assert_equivalent(const Tensor1Expression& expected, const Tensor1Expression& actual, double tol = 1e-9) { if (actual.equivalent(expected, tol)) return true; std::cout << "Not equal:\n"; expected.print("expected:\n"); actual.print("actual:\n"); return false; } } // namespace tensors