// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Benoit Jacob <jacob.benoit.1@gmail.com>
// Copyright (C) 2010 Hauke Heibel <hauke.heibel@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "main.h"

#include <Eigen/StdList>
#include <Eigen/Geometry>

EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Vector4f)

EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Matrix2f)
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Matrix4f)
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Matrix4d)

EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Affine3f)
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Affine3d)

EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Quaternionf)
EIGEN_DEFINE_STL_LIST_SPECIALIZATION(Quaterniond)

template <class Container, class Position>
typename Container::iterator get(Container & c, Position position)
{
  typename Container::iterator it = c.begin();
  std::advance(it, position);
  return it;
}

template <class Container, class Position, class Value>
void set(Container & c, Position position, const Value & value)
{
  typename Container::iterator it = c.begin();
  std::advance(it, position);
  *it = value;
}

template<typename MatrixType>
void check_stdlist_matrix(const MatrixType& m)
{
  Index rows = m.rows();
  Index cols = m.cols();
  MatrixType x = MatrixType::Random(rows,cols), y = MatrixType::Random(rows,cols);
  std::list<MatrixType> v(10, MatrixType::Zero(rows,cols)), w(20, y);
  typename std::list<MatrixType>::iterator itv = get(v, 5);
  typename std::list<MatrixType>::iterator itw = get(w, 6);
  *itv = x;
  *itw = *itv;
  VERIFY_IS_APPROX(*itw, *itv);
  v = w;
  itv = v.begin();
  itw = w.begin();
  for(int i = 0; i < 20; i++)
  {
    VERIFY_IS_APPROX(*itw, *itv);
    ++itv;
    ++itw;
  }

  v.resize(21);
  set(v, 20, x);
  VERIFY_IS_APPROX(*get(v, 20), x);
  v.resize(22,y);
  VERIFY_IS_APPROX(*get(v, 21), y);
  v.push_back(x);
  VERIFY_IS_APPROX(*get(v, 22), x);

  // do a lot of push_back such that the list gets internally resized
  // (with memory reallocation)
  MatrixType* ref = &(*get(w, 0));
  for(int i=0; i<30 || ((ref==&(*get(w, 0))) && i<300); ++i)
    v.push_back(*get(w, i%w.size()));
  for(unsigned int i=23; i<v.size(); ++i)
  {
    VERIFY((*get(v, i))==(*get(w, (i-23)%w.size())));
  }
}

template<typename TransformType>
void check_stdlist_transform(const TransformType&)
{
  typedef typename TransformType::MatrixType MatrixType;
  TransformType x(MatrixType::Random()), y(MatrixType::Random()), ti=TransformType::Identity();
  std::list<TransformType> v(10,ti), w(20, y);
  typename std::list<TransformType>::iterator itv = get(v, 5);
  typename std::list<TransformType>::iterator itw = get(w, 6);
  *itv = x;
  *itw = *itv;
  VERIFY_IS_APPROX(*itw, *itv);
  v = w;
  itv = v.begin();
  itw = w.begin();
  for(int i = 0; i < 20; i++)
  {
    VERIFY_IS_APPROX(*itw, *itv);
    ++itv;
    ++itw;
  }

  v.resize(21, ti);
  set(v, 20, x);
  VERIFY_IS_APPROX(*get(v, 20), x);
  v.resize(22,y);
  VERIFY_IS_APPROX(*get(v, 21), y);
  v.push_back(x);
  VERIFY_IS_APPROX(*get(v, 22), x);

  // do a lot of push_back such that the list gets internally resized
  // (with memory reallocation)
  TransformType* ref = &(*get(w, 0));
  for(int i=0; i<30 || ((ref==&(*get(w, 0))) && i<300); ++i)
    v.push_back(*get(w, i%w.size()));
  for(unsigned int i=23; i<v.size(); ++i)
  {
    VERIFY(get(v, i)->matrix()==get(w, (i-23)%w.size())->matrix());
  }
}

template<typename QuaternionType>
void check_stdlist_quaternion(const QuaternionType&)
{
  typedef typename QuaternionType::Coefficients Coefficients;
  QuaternionType x(Coefficients::Random()), y(Coefficients::Random()), qi=QuaternionType::Identity();
  std::list<QuaternionType> v(10,qi), w(20, y);
  typename std::list<QuaternionType>::iterator itv = get(v, 5);
  typename std::list<QuaternionType>::iterator itw = get(w, 6);
  *itv = x;
  *itw = *itv;
  VERIFY_IS_APPROX(*itw, *itv);
  v = w;
  itv = v.begin();
  itw = w.begin();
  for(int i = 0; i < 20; i++)
  {
    VERIFY_IS_APPROX(*itw, *itv);
    ++itv;
    ++itw;
  }

  v.resize(21,qi);
  set(v, 20, x);
  VERIFY_IS_APPROX(*get(v, 20), x);
  v.resize(22,y);
  VERIFY_IS_APPROX(*get(v, 21), y);
  v.push_back(x);
  VERIFY_IS_APPROX(*get(v, 22), x);

  // do a lot of push_back such that the list gets internally resized
  // (with memory reallocation)
  QuaternionType* ref = &(*get(w, 0));
  for(int i=0; i<30 || ((ref==&(*get(w, 0))) && i<300); ++i)
    v.push_back(*get(w, i%w.size()));
  for(unsigned int i=23; i<v.size(); ++i)
  {
    VERIFY(get(v, i)->coeffs()==get(w, (i-23)%w.size())->coeffs());
  }
}

EIGEN_DECLARE_TEST(stdlist_overload)
{
  // some non vectorizable fixed sizes
  CALL_SUBTEST_1(check_stdlist_matrix(Vector2f()));
  CALL_SUBTEST_1(check_stdlist_matrix(Matrix3f()));
  CALL_SUBTEST_2(check_stdlist_matrix(Matrix3d()));

  // some vectorizable fixed sizes
  CALL_SUBTEST_1(check_stdlist_matrix(Matrix2f()));
  CALL_SUBTEST_1(check_stdlist_matrix(Vector4f()));
  CALL_SUBTEST_1(check_stdlist_matrix(Matrix4f()));
  CALL_SUBTEST_2(check_stdlist_matrix(Matrix4d()));

  // some dynamic sizes
  CALL_SUBTEST_3(check_stdlist_matrix(MatrixXd(1,1)));
  CALL_SUBTEST_3(check_stdlist_matrix(VectorXd(20)));
  CALL_SUBTEST_3(check_stdlist_matrix(RowVectorXf(20)));
  CALL_SUBTEST_3(check_stdlist_matrix(MatrixXcf(10,10)));

  // some Transform
  CALL_SUBTEST_4(check_stdlist_transform(Affine2f())); // does not need the specialization (2+1)^2 = 9
  CALL_SUBTEST_4(check_stdlist_transform(Affine3f()));
  CALL_SUBTEST_4(check_stdlist_transform(Affine3d()));

  // some Quaternion
  CALL_SUBTEST_5(check_stdlist_quaternion(Quaternionf()));
  CALL_SUBTEST_5(check_stdlist_quaternion(Quaterniond()));
}
