Skip to content
Snippets Groups Projects
math_details.h 24.3 KiB
Newer Older
/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2011-2014, Willow Garage, Inc.
 *  Copyright (c) 2014-2015, Open Source Robotics Foundation
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of Open Source Robotics Foundation nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

/** \author Joseph Mirabel */

#ifndef FCL_EIGEN_DETAILS_H
#define FCL_EIGEN_DETAILS_H

#include <Eigen/Dense>
#include <Eigen/Geometry>

namespace fcl
{

namespace details
{

template <typename T>
struct eigen_wrapper_v3
{
  typedef T meta_type;
  typedef Eigen::Matrix <T, 3, 1> vector_type;

  vector_type v;

  eigen_wrapper_v3() { setValue(0); }

  template <typename Derived>
    eigen_wrapper_v3(const Eigen::MatrixBase <Derived>& value) :
      v (value)
  {}

  eigen_wrapper_v3(T x) :
    v (vector_type::Constant (x))
  {}

  eigen_wrapper_v3(T* x) :
    v (vector_type::Constant (*x))
  {}

  eigen_wrapper_v3(T x, T y, T z) :
    v (x, y, z)
  {}

  inline void setValue(T x, T y, T z)
  {
    v << x, y, z;
  }

  inline void setValue(T x)
  {
    v.setConstant (x);
  }

  inline void negate()
  {
    v *= -1;
  }

  inline eigen_wrapper_v3<T>& ubound(const eigen_wrapper_v3<T>& u)
  {
    v = v.cwiseMin (u.v);
    return *this;
  }

  inline eigen_wrapper_v3<T>& lbound(const eigen_wrapper_v3<T>& l)
  {
    v = v.cwiseMax (l.v);
    return *this;
  }

  T operator [] (size_t i) const { return v[i]; }
  T& operator [] (size_t i) { return v[i]; }

  inline eigen_wrapper_v3<T> operator + (const eigen_wrapper_v3<T>& other) const { return eigen_wrapper_v3<T>(v + other.v); }
  inline eigen_wrapper_v3<T> operator - (const eigen_wrapper_v3<T>& other) const { return eigen_wrapper_v3<T>(v - other.v); }
  inline eigen_wrapper_v3<T> operator * (const eigen_wrapper_v3<T>& other) const { return eigen_wrapper_v3<T>(v.cwiseProduct (other.v)); }
  inline eigen_wrapper_v3<T> operator / (const eigen_wrapper_v3<T>& other) const { return (eigen_wrapper_v3<T>(v) /= other); }
  inline eigen_wrapper_v3<T>& operator += (const eigen_wrapper_v3<T>& other) { v += other.v; return *this; }
  inline eigen_wrapper_v3<T>& operator -= (const eigen_wrapper_v3<T>& other) { v -= other.v; return *this; }
  inline eigen_wrapper_v3<T>& operator *= (const eigen_wrapper_v3<T>& other) { v = v.cwiseProduct  (other.v); return *this; }
  inline eigen_wrapper_v3<T>& operator /= (const eigen_wrapper_v3<T>& other) { v = v.cwiseQuotient (other.v); return *this; }
  inline eigen_wrapper_v3<T> operator + (T t) const { return eigen_wrapper_v3<T>((v.array() + t).matrix()); }
  inline eigen_wrapper_v3<T> operator - (T t) const { return eigen_wrapper_v3<T>((v.array() - t).matrix()); }
  inline eigen_wrapper_v3<T> operator * (T t) const { return eigen_wrapper_v3<T>(v * t); }
  inline eigen_wrapper_v3<T> operator / (T t) const { return eigen_wrapper_v3<T>(v / t); }
  inline eigen_wrapper_v3<T>& operator += (T t) { v.array() += t; return *this; }
  inline eigen_wrapper_v3<T>& operator -= (T t) { v.array() -= t; return *this; }
  inline eigen_wrapper_v3<T>& operator *= (T t) { v.array() *= t; return *this; }
  inline eigen_wrapper_v3<T>& operator /= (T t) { v.array() /= t; return *this; }
  inline eigen_wrapper_v3<T> operator - () const { return eigen_wrapper_v3<T>(-v); }
};


template <typename T>
static inline eigen_wrapper_v3<T> cross_prod(const eigen_wrapper_v3<T>& l, const eigen_wrapper_v3<T>& r)
{
  return eigen_wrapper_v3<T>(l.v.cross (r.v));
}

template <typename T>
static inline T dot_prod3(const eigen_wrapper_v3<T>& l, const eigen_wrapper_v3<T>& r)
{
  return l.v.dot(r.v);
}

template <typename T>
static inline eigen_wrapper_v3<T> min(const eigen_wrapper_v3<T>& x, const eigen_wrapper_v3<T>& y)
{
  return eigen_wrapper_v3<T>(x.v.cwiseMin (y.v));
}

template <typename T>
static inline eigen_wrapper_v3<T> max(const eigen_wrapper_v3<T>& x, const eigen_wrapper_v3<T>& y)
{
  return eigen_wrapper_v3<T>(x.v.cwiseMax(y.v));
}

template <typename T>
static inline eigen_wrapper_v3<T> abs(const eigen_wrapper_v3<T>& x)
{
  return eigen_wrapper_v3<T>(x.v.cwiseAbs());
}

template <typename T>
static inline bool equal(const eigen_wrapper_v3<T>& x, const eigen_wrapper_v3<T>& y, T epsilon)
{
  return ((x.v - y.v).cwiseAbs ().array () < epsilon).all();
}

namespace internal {
  template <typename Derived, int Size> struct assign {
    static Eigen::Matrix<typename Derived::Scalar, 4, 1> run (const Eigen::MatrixBase <Derived>& value)
    {
      assert (false);
    }
  };

  template <typename Derived> struct assign <Derived, 3> {
    static Eigen::Matrix<typename Derived::Scalar, 4, 1> run (const Eigen::MatrixBase <Derived>& value)
    {
      return (Eigen::Matrix<typename Derived::Scalar, 4, 1> () << value, 0).finished ();
    }
  };

  template <typename Derived> struct assign <Derived, 4> {
    static Eigen::Matrix<typename Derived::Scalar, 4, 1> run (const Eigen::MatrixBase <Derived>& value)
    {
      return value;
    }
  };
}

template <typename T>
struct eigen_wrapper_v4
{
  typedef T meta_type;
  typedef Eigen::Matrix <T, 4, 1> vector_type;

  vector_type v;

  eigen_wrapper_v4() { setValue(0); }

  template <typename Derived>
    eigen_wrapper_v4(const Eigen::MatrixBase <Derived>& value) :
      v (internal::assign <Derived, Derived::SizeAtCompileTime>::run (value))
  {}

  eigen_wrapper_v4(T x) :
    v (vector_type::Constant (x))
  {
    v[3] = 0;
  }

  eigen_wrapper_v4(T* x) :
    v (vector_type::Constant (*x))
  {
    v[3] = 0;
  }

  eigen_wrapper_v4(T x, T y, T z) :
    v (x, y, z, 0)
  {}

  inline typename vector_type::template FixedSegmentReturnType<3>::Type d () { return v.template head <3> (); }

  inline typename vector_type::template ConstFixedSegmentReturnType<3>::Type d () const { return v.template head <3> (); }

  inline void setValue(T x, T y, T z, T w = 0)
  {
    v << x, y, z, w;
  }

  inline void setValue(T x)
  {
    d().setConstant (x);
    v[3] = 0;
  }

  inline void negate()
  {
    v *= -1;
  }

  inline eigen_wrapper_v4<T>& ubound(const eigen_wrapper_v4<T>& u)
  {
    v = v.cwiseMin (u.v);
    return *this;
  }

  inline eigen_wrapper_v4<T>& lbound(const eigen_wrapper_v4<T>& l)
  {
    v = v.cwiseMax (l.v);
    return *this;
  }

  T operator [] (size_t i) const { return v[i]; }
  T& operator [] (size_t i) { return v[i]; }

  inline eigen_wrapper_v4<T> operator + (const eigen_wrapper_v4<T>& other) const { return eigen_wrapper_v4<T>(v + other.v); }
  inline eigen_wrapper_v4<T> operator - (const eigen_wrapper_v4<T>& other) const { return eigen_wrapper_v4<T>(v - other.v); }
  inline eigen_wrapper_v4<T> operator * (const eigen_wrapper_v4<T>& other) const { return eigen_wrapper_v4<T>(v.cwiseProduct (other.v)); }
  inline eigen_wrapper_v4<T> operator / (const eigen_wrapper_v4<T>& other) const { return (eigen_wrapper_v4<T>(v) /= other); }
  inline eigen_wrapper_v4<T>& operator += (const eigen_wrapper_v4<T>& other) { v += other.v; return *this; }
  inline eigen_wrapper_v4<T>& operator -= (const eigen_wrapper_v4<T>& other) { v -= other.v; return *this; }
  inline eigen_wrapper_v4<T>& operator *= (const eigen_wrapper_v4<T>& other) { v = v.cwiseProduct  (other.v); return *this; }
  inline eigen_wrapper_v4<T>& operator /= (const eigen_wrapper_v4<T>& other) { d() = d().cwiseQuotient (other.d()); return *this; }
  inline eigen_wrapper_v4<T> operator + (T t) const { return eigen_wrapper_v4<T>((d().array() + t).matrix()); }
  inline eigen_wrapper_v4<T> operator - (T t) const { return eigen_wrapper_v4<T>((d().array() - t).matrix()); }
  inline eigen_wrapper_v4<T> operator * (T t) const { return eigen_wrapper_v4<T>(v * t); }
  inline eigen_wrapper_v4<T> operator / (T t) const { return eigen_wrapper_v4<T>(v / t); }
  inline eigen_wrapper_v4<T>& operator += (T t) { d().array() += t; return *this; }
  inline eigen_wrapper_v4<T>& operator -= (T t) { d().array() -= t; return *this; }
  inline eigen_wrapper_v4<T>& operator *= (T t) { v.array() *= t; return *this; }
  inline eigen_wrapper_v4<T>& operator /= (T t) { v.array() /= t; return *this; }
  inline eigen_wrapper_v4<T> operator - () const { return eigen_wrapper_v4<T>(-v); }
} __attribute__ ((aligned));


template <typename T>
static inline eigen_wrapper_v4<T> cross_prod(const eigen_wrapper_v4<T>& l, const eigen_wrapper_v4<T>& r)
{
  return eigen_wrapper_v4<T>(l.v.cross3 (r.v));
}

template <typename T>
static inline T dot_prod3(const eigen_wrapper_v4<T>& l, const eigen_wrapper_v4<T>& r)
{
  return l.v.dot(r.v);
}

template <typename T>
static inline eigen_wrapper_v4<T> min(const eigen_wrapper_v4<T>& x, const eigen_wrapper_v4<T>& y)
{
  return eigen_wrapper_v4<T>(x.v.cwiseMin (y.v));
}

template <typename T>
static inline eigen_wrapper_v4<T> max(const eigen_wrapper_v4<T>& x, const eigen_wrapper_v4<T>& y)
{
  return eigen_wrapper_v4<T>(x.v.cwiseMax(y.v));
}

template <typename T>
static inline eigen_wrapper_v4<T> abs(const eigen_wrapper_v4<T>& x)
{
  return eigen_wrapper_v4<T>(x.v.cwiseAbs());
}

template <typename T>
static inline bool equal(const eigen_wrapper_v4<T>& x, const eigen_wrapper_v4<T>& y, T epsilon)
{
  return ((x.v - y.v).cwiseAbs ().array () < epsilon).all();
}

template <typename T>
struct eigen_v3 :
  Eigen::Matrix <T, 3, 1>
{
  typedef T meta_type;
  typedef Eigen::Matrix <T, 3, 1> Base;

  eigen_v3(void): Base () { this->setZero (); }

  // This constructor allows you to construct MyVectorType from Eigen expressions
  template<typename OtherDerived>
    eigen_v3(const Eigen::MatrixBase<OtherDerived>& other)
    : Base(other)
  {}

  // This method allows you to assign Eigen expressions to MyVectorType
  template<typename OtherDerived>
    eigen_v3& operator= (const Eigen::MatrixBase <OtherDerived>& other)
    {
      this->Base::operator=(other);
      return *this;
    }

  eigen_v3(T x) :
    Base (x, x, x)
  {}

  eigen_v3(T* x) :
    Base (*x, *x, *x)
  {}

  eigen_v3(T x, T y, T z) :
    Base (x, y, z)
  {}

  inline void setValue(T x, T y, T z)
  {
    this->operator[] (0) = x;
    this->operator[] (1) = y;
    this->operator[] (2) = z;
  }

  inline void setValue(T x)
  {
    this->setConstant (x);
  }

  inline void negate()
  {
    this->operator*= (-1);
  }

  template<typename OtherDerived>
  inline eigen_v3<T>& ubound(const Eigen::MatrixBase<OtherDerived>& u)
  {
    *this = this->cwiseMin (u);
    return *this;
  }

  template<typename OtherDerived>
  inline eigen_v3<T>& lbound(const Eigen::MatrixBase<OtherDerived>& l)
  {
    *this = this->cwiseMax (l);
    return *this;
  }

  // T operator [] (size_t i) const { return v[i]; }
  // T& operator [] (size_t i) { return v[i]; }

  // inline eigen_wrapper_v3<T> operator + (const eigen_wrapper_v3<T>& other) const { return eigen_wrapper_v3<T>(v + other.v); }
  // inline eigen_wrapper_v3<T> operator - (const eigen_wrapper_v3<T>& other) const { return eigen_wrapper_v3<T>(v[0] - other.v[0], v[1] - other.v[1], v[2] - other.v[2]); }
  // inline eigen_wrapper_v3<T> operator * (const eigen_wrapper_v3<T>& other) const { return eigen_wrapper_v3<T>(v[0] * other.v[0], v[1] * other.v[1], v[2] * other.v[2]); }
  // inline eigen_v3<T> operator / (const eigen_v3<T>& other) const { return eigen_v3<T>(this->array().cwiseQuotient (other)); }
  inline eigen_v3<T>& operator += (const eigen_v3<T>& other) { return static_cast<eigen_v3<T>&>(this->Base::operator+= (other)); }
  inline eigen_v3<T>& operator -= (const eigen_v3<T>& other) { return static_cast<eigen_v3<T>&>(this->Base::operator-= (other)); }
  inline eigen_v3<T>& operator *= (const eigen_v3<T>& other) { return static_cast<eigen_v3<T>&>(this->array().operator*=(other)); }
  inline eigen_v3<T>& operator /= (const eigen_v3<T>& other) { return static_cast<eigen_v3<T>&>(this->array().operator/=(other)); }
  // inline eigen_wrapper_v4<T>& operator /= (const eigen_wrapper_v4<T>& other) {  = d().cwiseQuotient (other.d()); return *this; }
  // inline eigen_wrapper_v3<T>& operator *= (const eigen_wrapper_v3<T>& other) { return this->Base::operator*= (other); }
  // inline eigen_wrapper_v3<T>& operator /= (const eigen_wrapper_v3<T>& other) { return this->Base::operator/= (other); }
  // inline eigen_wrapper_v3<T> operator + (T t) const { return eigen_wrapper_v3<T>(v + t); }
  // inline eigen_wrapper_v3<T> operator - (T t) const { return eigen_wrapper_v3<T>(v - t); }
  // inline eigen_wrapper_v3<T> operator * (T t) const { return eigen_wrapper_v3<T>(v * t); }
  // inline eigen_wrapper_v3<T> operator / (T t) const { return eigen_wrapper_v3<T>(v / t); }
  inline eigen_v3<T>& operator += (T t) { this->array() += t; return *this; }
  inline eigen_v3<T>& operator -= (T t) { this->array() -= t; return *this; }
  inline eigen_v3<T>& operator *= (T t) { this->array() *= t; return *this; }
  inline eigen_v3<T>& operator /= (T t) { this->array() /= t; return *this; }
  // inline eigen_wrapper_v3<T> operator - () const { return eigen_wrapper_v3<T>(-v); }
};


template <typename T>
static inline eigen_v3<T> cross_prod(const eigen_v3<T>& l, const eigen_v3<T>& r)
{
  return l.cross (r);
}

template <typename T>
static inline T dot_prod3(const eigen_v3<T>& l, const eigen_v3<T>& r)
{
  return l.dot(r);
}

template <typename T>
static inline eigen_v3<T> min(const eigen_v3<T>& x, const eigen_v3<T>& y)
{
  return x.cwiseMin (y);
}

template <typename T>
static inline eigen_v3<T> max(const eigen_v3<T>& x, const eigen_v3<T>& y)
{
  return x.cwiseMax(y);
}

template <typename T>
static inline eigen_v3<T> abs(const eigen_v3<T>& x)
{
  return x.cwiseAbs();
}

template <typename T>
static inline bool equal(const eigen_v3<T>& x, const eigen_v3<T>& y, T epsilon)
{
  return ((x - y).cwiseAbs ().array () < epsilon).all();
}

template<typename T>
struct eigen_wrapper_m3
{
Joseph Mirabel's avatar
Joseph Mirabel committed
  typedef T meta_type;
  typedef eigen_wrapper_v3<T> vector_type;
  typedef Eigen::Matrix <T, 3, 3, Eigen::RowMajor> matrix_type;
  typedef Eigen::Matrix <T, 3, 1> inner_col_type;
  typedef typename matrix_type::ConstRowXpr ConstRowXpr;

  matrix_type m;
  eigen_wrapper_m3() {};

  template <typename Derived>
    eigen_wrapper_m3(const Eigen::MatrixBase <Derived>& matrix) :
      m (matrix)
  {}

  eigen_wrapper_m3(T xx, T xy, T xz,
                   T yx, T yy, T yz,
                   T zx, T zy, T zz)
  {
    setValue(xx, xy, xz,
             yx, yy, yz,
             zx, zy, zz);
  }

  eigen_wrapper_m3(const vector_type& v1, const vector_type& v2, const vector_type& v3)
  {
    m << v1.v, v2.v, v3.v;
  }

  eigen_wrapper_m3(const eigen_wrapper_m3<T>& other) { m = other.m; }

  inline inner_col_type getColumn(size_t i) const { return m.col (i); }
  inline ConstRowXpr getRow(size_t i) const { return m.row (i); }

  inline T operator() (size_t i, size_t j) const { return m(i, j); }
  inline T& operator() (size_t i, size_t j) { return m(i, j); }

  inline vector_type operator * (const vector_type& v) const { return vector_type(m * v.v); }

  inline eigen_wrapper_m3<T> operator * (const eigen_wrapper_m3<T>& other) const { return eigen_wrapper_m3<T>(m * other.m); }
  inline eigen_wrapper_m3<T> operator + (const eigen_wrapper_m3<T>& other) const { return eigen_wrapper_m3<T>(m + other.m); }
  inline eigen_wrapper_m3<T> operator - (const eigen_wrapper_m3<T>& other) const { return eigen_wrapper_m3<T>(m - other.m); }

Joseph Mirabel's avatar
Joseph Mirabel committed
  inline eigen_wrapper_m3<T> operator + (T c) const { return eigen_wrapper_m3<T>(m + c); }
  inline eigen_wrapper_m3<T> operator - (T c) const { return eigen_wrapper_m3<T>(m - c); }
  inline eigen_wrapper_m3<T> operator * (T c) const { return eigen_wrapper_m3<T>(m * c); }
  inline eigen_wrapper_m3<T> operator / (T c) const { return eigen_wrapper_m3<T>(m / c); }

  inline eigen_wrapper_m3<T>& operator *= (const eigen_wrapper_m3<T>& other) { m *= other.m; return *this; }
  inline eigen_wrapper_m3<T>& operator += (const eigen_wrapper_m3<T>& other) { m += other.m; return *this; }
  inline eigen_wrapper_m3<T>& operator -= (const eigen_wrapper_m3<T>& other) { m -= other.m; return *this; }

Joseph Mirabel's avatar
Joseph Mirabel committed
  inline eigen_wrapper_m3<T>& operator += (T c) { m.array() += c; return *this; }
  inline eigen_wrapper_m3<T>& operator -= (T c) { m.array() -= c; return *this; }
  inline eigen_wrapper_m3<T>& operator *= (T c) { m.array() *= c; return *this; }
  inline eigen_wrapper_m3<T>& operator /= (T c) { m.array() /= c; return *this; }


  void setIdentity() { m.setIdentity (); }

  void setZero() { m.setZero(); }

  static const eigen_wrapper_m3<T>& getIdentity()
  {
    static const eigen_wrapper_m3<T> I(matrix_type::Identity ());
    return I;
  }

  T determinant() const { return m.determinant (); }

  eigen_wrapper_m3<T>& transpose()
  {
    m.transposeInPlace ();
    return *this;
  }

  eigen_wrapper_m3<T>& inverse()
  {
    m = m.inverse().eval();
    return *this;
  }

  eigen_wrapper_m3<T> transposeTimes(const eigen_wrapper_m3<T>& other) const
  {
    return eigen_wrapper_m3<T>(m.transpose () * other.m);
  }

  eigen_wrapper_m3<T> timesTranspose(const eigen_wrapper_m3<T>& other) const
  {
    return eigen_wrapper_m3<T>(m * other.transpose ());
  }

  vector_type transposeTimes(const vector_type& other) const
  {
    return vector_type(m.transpose () * other.v);
  }

  inline T transposeDotX(const vector_type& other) const
  {
    return m.col(0).dot(other.v);
  }

  inline T transposeDotY(const vector_type& other) const
  {
    return m.col(1).dot(other.v);
  }

  inline T transposeDotZ(const vector_type& other) const
  {
    return m.col(2).dot(other.v);
  }

  inline T transposeDot(size_t i, const vector_type& other) const
  {
    return m.col (i).dot(other.v);
  }

  inline T dotX(const vector_type& other) const
  {
    return m.row (0).dot (other.v);
  }

  inline T dotY(const vector_type& other) const
  {
    return m.row (1).dot (other.v);
  }

  inline T dotZ(const vector_type& other) const
  {
    return m.row (2).dot (other.v);
  }

  inline T dot(size_t i, const vector_type& other) const
  {
    return m.row (i).dot (other.v);
  }

  inline void setValue(T xx, T xy, T xz,
                       T yx, T yy, T yz,
                       T zx, T zy, T zz)
  {
    m << xx, xy, xz,
         yx, yy, yz,
         zx, zy, zz;
  }

  inline void setValue(T x) { m.setConstant (x); }
};


template<typename T>
eigen_wrapper_m3<T> abs(const eigen_wrapper_m3<T>& m)
{
  return eigen_wrapper_m3<T>(m.m.cwiseAbs ());
}

template<typename T>
eigen_wrapper_m3<T> transpose(const eigen_wrapper_m3<T>& m)
{
  return eigen_wrapper_m3<T>(m.m.transpose ());
}


template<typename T>
eigen_wrapper_m3<T> inverse(const eigen_wrapper_m3<T>& m)
{
  return eigen_wrapper_m3<T> (m.m.inverse().eval ());
}

template<typename T>
struct eigen_m3 :
  Eigen::Matrix <T, 3, 3>
{
  typedef T meta_type;
  typedef eigen_v3<T> vector_type;
  typedef Eigen::Matrix <T, 3, 3> Base;

  typedef typename Base::ColXpr ColXpr;
  typedef typename Base::ConstColXpr ConstColXpr;
  typedef typename Base::RowXpr RowXpr;
  typedef typename Base::ConstRowXpr ConstRowXpr;

  eigen_m3(void): Base () { }

  // This constructor allows you to construct MyVectorType from Eigen expressions
  template<typename OtherDerived>
    eigen_m3(const Eigen::MatrixBase<OtherDerived>& other)
    : Base(other)
  {}

  // This method allows you to assign Eigen expressions to MyVectorType
  template<typename OtherDerived>
    eigen_m3& operator= (const Eigen::MatrixBase <OtherDerived>& other)
    {
      this->Base::operator=(other);
      return *this;
    }

  eigen_m3(T xx, T xy, T xz,
           T yx, T yy, T yz,
           T zx, T zy, T zz)
  {
    setValue(xx, xy, xz,
             yx, yy, yz,
             zx, zy, zz);
  }

  eigen_m3(const vector_type& v1, const vector_type& v2, const vector_type& v3)
  {
    this->row(1) = v1;
    this->row(2) = v2;
    this->row(3) = v3;
  }

  inline ColXpr getColumn(size_t i) { return this->col (i); }
  inline RowXpr getRow(size_t i)    { return this->row (i); }
  inline ConstColXpr getColumn(size_t i) const { return this->col (i); }
  inline ConstRowXpr getRow(size_t i) const    { return this->row (i); }

  inline eigen_m3<T>& operator *= (const eigen_m3<T>& other) { return static_cast<eigen_m3<T>&>(this->operator*=(other)); }
  inline eigen_m3<T>& operator += (const eigen_m3<T>& other) { return static_cast<eigen_m3<T>&>(this->operator+=(other)); }
  inline eigen_m3<T>& operator -= (const eigen_m3<T>& other) { return static_cast<eigen_m3<T>&>(this->operator-=(other)); }

  inline eigen_m3<T>& operator += (T c) { return static_cast<eigen_m3<T>&>(this->operator+=(c)); }
  inline eigen_m3<T>& operator -= (T c) { return static_cast<eigen_m3<T>&>(this->operator-=(c)); }
  inline eigen_m3<T>& operator *= (T c) { return static_cast<eigen_m3<T>&>(this->operator*=(c)); }
  inline eigen_m3<T>& operator /= (T c) { return static_cast<eigen_m3<T>&>(this->operator/=(c)); }

  static const eigen_m3<T>& getIdentity()
  {
    static const eigen_m3<T> I(Base::Identity ());
    return I;
  }

  eigen_m3<T>& transpose() { this->transposeInPlace (); return *this; }

  eigen_m3<T>& inverse()
  {
    this->Base::operator=(this->inverse ().eval());
    // m = m.inverse().eval();
    return *this;
  }

  template <typename OtherDerived>
Joseph Mirabel's avatar
Joseph Mirabel committed
    const typename Eigen::ProductReturnType<eigen_m3<T>, OtherDerived>::Type
    transposeTimes(const Eigen::MatrixBase<OtherDerived>& other) const
  {
    return this->Base::transpose() * other;
  }

  template <typename OtherDerived>
Joseph Mirabel's avatar
Joseph Mirabel committed
    const typename Eigen::ProductReturnType<eigen_m3<T>, OtherDerived>::Type
    timesTranspose(const Eigen::MatrixBase<OtherDerived>& other) const
  {
    return this->operator* (other.Base::transpose());
  }

  template <typename OtherDerived>
  inline T transposeDotX(const Eigen::MatrixBase<OtherDerived>& other) const
  {
    return this->col(0).dot(other);
  }

  template <typename OtherDerived>
  inline T transposeDotY(const Eigen::MatrixBase<OtherDerived>& other) const
  {
    return this->col(1).dot(other);
  }

  template <typename OtherDerived>
  inline T transposeDotZ(const Eigen::MatrixBase<OtherDerived>& other) const
  {
    return this->col(2).dot(other);
  }

  template <typename OtherDerived>
  inline T transposeDot(size_t i, const Eigen::MatrixBase<OtherDerived>& other) const
  {
    return this->col(i).dot(other);
  }

  template <typename OtherDerived>
  inline T dotX(const Eigen::MatrixBase<OtherDerived>& other) const
  {
    return this->row(0).dot(other);
  }

  template <typename OtherDerived>
  inline T dotY(const Eigen::MatrixBase<OtherDerived>& other) const
  {
    return this->row(1).dot(other);
  }

  template <typename OtherDerived>
  inline T dotZ(const Eigen::MatrixBase<OtherDerived>& other) const
  {
    return this->row(2).dot(other);
  }

  template <typename OtherDerived>
  inline T dot(size_t i, const Eigen::MatrixBase<OtherDerived>& other) const
  {
    return this->row(i).dot(other);
  }

  inline void setValue(T xx, T xy, T xz,
                       T yx, T yy, T yz,
                       T zx, T zy, T zz)
  {
    *this << xx, xy, xz,
             yx, yy, yz,
             zx, zy, zz;
  }

  inline void setValue(T x)
  {
    this->setConstant (x);
  }
};


template<typename T>
eigen_m3<T> abs(const eigen_m3<T>& m)
{
  return eigen_m3<T>(m.cwiseAbs ());
}

template<typename T>
eigen_m3<T> transpose(const eigen_m3<T>& m)
{
  return eigen_m3<T>(m.eigen_m3<T>::Base::transpose ());
}


template<typename T>
eigen_m3<T> inverse(const eigen_m3<T>& m)
{
  return eigen_m3<T> (m.eigen_m3<T>::Base::inverse().eval ());
}