//=====================================================
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//=====================================================
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
#ifndef EIGEN3_INTERFACE_HH
#define EIGEN3_INTERFACE_HH

#include <Eigen/Eigen>
#include <vector>
#include "btl.hh"

using namespace Eigen;

template<class real, int SIZE=Dynamic>
class eigen3_interface
{

public :

  enum {IsFixedSize = (SIZE!=Dynamic)};

  typedef real real_type;

  typedef std::vector<real> stl_vector;
  typedef std::vector<stl_vector> stl_matrix;

  typedef Eigen::Matrix<real,SIZE,SIZE> gene_matrix;
  typedef Eigen::Matrix<real,SIZE,1> gene_vector;

  static inline std::string name( void )
  {
    return EIGEN_MAKESTRING(BTL_PREFIX);
  }

  static void free_matrix(gene_matrix & A, int N) {}

  static void free_vector(gene_vector & B) {}

  static BTL_DONT_INLINE void matrix_from_stl(gene_matrix & A, stl_matrix & A_stl){
    A.resize(A_stl[0].size(), A_stl.size());

    for (int j=0; j<A_stl.size() ; j++){
      for (int i=0; i<A_stl[j].size() ; i++){
        A.coeffRef(i,j) = A_stl[j][i];
      }
    }
  }

  static BTL_DONT_INLINE  void vector_from_stl(gene_vector & B, stl_vector & B_stl){
    B.resize(B_stl.size(),1);

    for (int i=0; i<B_stl.size() ; i++){
      B.coeffRef(i) = B_stl[i];
    }
  }

  static BTL_DONT_INLINE  void vector_to_stl(gene_vector & B, stl_vector & B_stl){
    for (int i=0; i<B_stl.size() ; i++){
      B_stl[i] = B.coeff(i);
    }
  }

  static BTL_DONT_INLINE  void matrix_to_stl(gene_matrix & A, stl_matrix & A_stl){
    int N=A_stl.size();

    for (int j=0;j<N;j++){
      A_stl[j].resize(N);
      for (int i=0;i<N;i++){
        A_stl[j][i] = A.coeff(i,j);
      }
    }
  }

  static inline void matrix_matrix_product(const gene_matrix & A, const gene_matrix & B, gene_matrix & X, int N){
    X.noalias() = A*B;
  }

  static inline void transposed_matrix_matrix_product(const gene_matrix & A, const gene_matrix & B, gene_matrix & X, int N){
    X.noalias() = A.transpose()*B.transpose();
  }

  static inline void ata_product(const gene_matrix & A, gene_matrix & X, int N){
    X.noalias() = A.transpose()*A;
  }

  static inline void aat_product(const gene_matrix & A, gene_matrix & X, int N){
    X.noalias() = A*A.transpose();
  }

  static inline void matrix_vector_product(const gene_matrix & A, const gene_vector & B, gene_vector & X, int N){
    X.noalias() = A*B;
  }

  static inline void symv(const gene_matrix & A, const gene_vector & B, gene_vector & X, int N){
    X.noalias() = (A.template selfadjointView<Lower>() * B);
//     internal::product_selfadjoint_vector<real,0,LowerTriangularBit,false,false>(N,A.data(),N, B.data(), 1, X.data(), 1);
  }

  template<typename Dest, typename Src> static void triassign(Dest& dst, const Src& src)
  {
    typedef typename Dest::Scalar Scalar;
    typedef typename internal::packet_traits<Scalar>::type Packet;
    const int PacketSize = sizeof(Packet)/sizeof(Scalar);
    int size = dst.cols();
    for(int j=0; j<size; j+=1)
    {
//       const int alignedEnd = alignedStart + ((innerSize-alignedStart) & ~packetAlignedMask);
      Scalar* A0 = dst.data() + j*dst.stride();
      int starti = j;
      int alignedEnd = starti;
      int alignedStart = (starti) + internal::first_aligned(&A0[starti], size-starti);
      alignedEnd = alignedStart + ((size-alignedStart)/(2*PacketSize))*(PacketSize*2);

      // do the non-vectorizable part of the assignment
      for (int index = starti; index<alignedStart ; ++index)
      {
        if(Dest::Flags&RowMajorBit)
          dst.copyCoeff(j, index, src);
        else
          dst.copyCoeff(index, j, src);
      }

      // do the vectorizable part of the assignment
      for (int index = alignedStart; index<alignedEnd; index+=PacketSize)
      {
        if(Dest::Flags&RowMajorBit)
          dst.template copyPacket<Src, Aligned, Unaligned>(j, index, src);
        else
          dst.template copyPacket<Src, Aligned, Unaligned>(index, j, src);
      }

      // do the non-vectorizable part of the assignment
      for (int index = alignedEnd; index<size; ++index)
      {
        if(Dest::Flags&RowMajorBit)
          dst.copyCoeff(j, index, src);
        else
          dst.copyCoeff(index, j, src);
      }
      //dst.col(j).tail(N-j) = src.col(j).tail(N-j);
    }
  }

  static EIGEN_DONT_INLINE void syr2(gene_matrix & A,  gene_vector & X, gene_vector & Y, int N){
    // internal::product_selfadjoint_rank2_update<real,0,LowerTriangularBit>(N,A.data(),N, X.data(), 1, Y.data(), 1, -1);
    for(int j=0; j<N; ++j)
      A.col(j).tail(N-j) += X[j] * Y.tail(N-j) + Y[j] * X.tail(N-j);
  }

  static EIGEN_DONT_INLINE void ger(gene_matrix & A,  gene_vector & X, gene_vector & Y, int N){
    for(int j=0; j<N; ++j)
      A.col(j) += X * Y[j];
  }

  static EIGEN_DONT_INLINE void rot(gene_vector & A,  gene_vector & B, real c, real s, int N){
    internal::apply_rotation_in_the_plane(A, B, JacobiRotation<real>(c,s));
  }

  static inline void atv_product(gene_matrix & A, gene_vector & B, gene_vector & X, int N){
    X.noalias() = (A.transpose()*B);
  }

  static inline void axpy(real coef, const gene_vector & X, gene_vector & Y, int N){
    Y += coef * X;
  }

  static inline void axpby(real a, const gene_vector & X, real b, gene_vector & Y, int N){
    Y = a*X + b*Y;
  }

  static EIGEN_DONT_INLINE void copy_matrix(const gene_matrix & source, gene_matrix & cible, int N){
    cible = source;
  }

  static EIGEN_DONT_INLINE void copy_vector(const gene_vector & source, gene_vector & cible, int N){
    cible = source;
  }

  static inline void trisolve_lower(const gene_matrix & L, const gene_vector& B, gene_vector& X, int N){
    X = L.template triangularView<Lower>().solve(B);
  }

  static inline void trisolve_lower_matrix(const gene_matrix & L, const gene_matrix& B, gene_matrix& X, int N){
    X = L.template triangularView<Lower>().solve(B);
  }

  static inline void trmm(const gene_matrix & L, const gene_matrix& B, gene_matrix& X, int N){
    X = L.template triangularView<Lower>() * B;
  }

  static inline void cholesky(const gene_matrix & X, gene_matrix & C, int N){
    C = X;
    internal::llt_inplace<Lower>::blocked(C);
    //C = X.llt().matrixL();
//     C = X;
//     Cholesky<gene_matrix>::computeInPlace(C);
//     Cholesky<gene_matrix>::computeInPlaceBlock(C);
  }

  static inline void lu_decomp(const gene_matrix & X, gene_matrix & C, int N){
    C = X.fullPivLu().matrixLU();
  }

  static inline void partial_lu_decomp(const gene_matrix & X, gene_matrix & C, int N){
    Matrix<DenseIndex,1,Dynamic> piv(N);
    DenseIndex nb;
    C = X;
    internal::partial_lu_inplace(C,piv,nb);
//     C = X.partialPivLu().matrixLU();
  }

  static inline void tridiagonalization(const gene_matrix & X, gene_matrix & C, int N){
    typename Tridiagonalization<gene_matrix>::CoeffVectorType aux(N-1);
    C = X;
    internal::tridiagonalization_inplace(C, aux);
  }

  static inline void hessenberg(const gene_matrix & X, gene_matrix & C, int N){
    C = HessenbergDecomposition<gene_matrix>(X).packedMatrix();
  }



};

#endif
