#ifndef CGAL_VECTOR_EIGEN_H #define CGAL_VECTOR_EIGEN_H #ifndef CGAL_USE_EIGEN #error Requires Eigen #endif #include #include #include #include #include #include #include #include #include namespace CGAL { // Dim_ real dimension // Max_dim_ upper bound on the dimension template struct Eigen_vector { typedef NT_ NT; typedef Eigen::Matrix::value,1,Eigen::ColMajor|Eigen::AutoAlign,Eigen_dimension::value,1> type; struct Constructor { private: static void check_dim(int d){ int m = Eigen_dimension::value; CGAL_assertion((m == Eigen::Dynamic) || (d <= m)); } public: struct Dimension { // Initialize with NaN if possible? type operator()(int d) const { check_dim(d); return type(d); } }; struct Iterator { template type operator()(int d,Iter const& f,Iter const& e) const { check_dim(d); CGAL_assertion(d==std::distance(f,e)); type a(d); // TODO: check the right way to do this std::copy(f,e,&a[0]); return a; } }; #if 0 struct Iterator_add_one { template type operator()(int d,Iter const& f,Iter const& e) const { check_dim(d); CGAL_assertion(d==std::distance(f,e)+1); type a(d); std::copy(f,e,&a[0]); a[d-1]=1; return a; } }; #endif struct Iterator_and_last { template type operator()(int d,Iter const& f,Iter const& e,CGAL_FORWARDABLE(T) t) const { check_dim(d); CGAL_assertion(d==std::distance(f,e)+1); type a(d); std::copy(f,e,&a[0]); a[d-1]=CGAL_FORWARD(T,t); return a; } }; #ifdef CGAL_CXX0X struct Initializer_list { // Fix T==NT? template type operator()(std::initializer_list l) const { return Iterator()(l.size(),l.begin(),l.end()); } }; #endif struct Values { #ifdef CGAL_CXX0X // TODO avoid going through Initializer_list which may cause extra copies. Possibly use forward_as_tuple. template type operator()(U&&...u) const { check_dim(sizeof...(U)); // use static_assert return Initializer_list()({forward_safe(u)...}); } #else #define CODE(Z,N,_) type operator()(BOOST_PP_ENUM_PARAMS(N,NT const& t)) const { \ check_dim(N); \ type a(N); \ a << BOOST_PP_ENUM_PARAMS(N,t); \ return a; \ } BOOST_PP_REPEAT_FROM_TO(1, 11, CODE, _ ) #undef CODE #endif }; struct Values_divide { #ifdef CGAL_CXX0X template type operator()(H const&h,U&&...u) const { check_dim(sizeof...(U)); // use static_assert return Initializer_list()({Rational_traits().make_rational(std::forward(u),h)...}); } #else #define VAR(Z,N,_) ( Rational_traits().make_rational( t##N ,h) ) #define CODE(Z,N,_) template type \ operator()(H const&h, BOOST_PP_ENUM_PARAMS(N,NT const& t)) const { \ CGAL_assertion(N<=std::min(type::SizeAtCompileTime,type::MaxSizeAtCompileTime)); \ type a(N); \ a << BOOST_PP_ENUM(N,VAR,); \ return a; \ } BOOST_PP_REPEAT_FROM_TO(1, 11, CODE, _ ) #undef CODE #undef VAR #endif }; }; #if (EIGEN_WORLD_VERSION>=3) typedef NT const* const_iterator; #else typedef Iterator_from_indices const_iterator; #endif templatestatic const_iterator vector_begin(Vec_ const&a){ #if (EIGEN_WORLD_VERSION>=3) return &a[0]; #else return const_iterator(a,0); #endif } templatestatic const_iterator vector_end(Vec_ const&a){ #if (EIGEN_WORLD_VERSION>=3) return &a[0]+a.size(); #else return const_iterator(a,a.size()); #endif } // Really needed? templatestatic int size_of_vector(Vec_ const&v){ return v.size(); } // This complicates matter for little benefice #if 0 private: template class Canonicalize_vector { typedef typename Dimension_eigen::type S1; typedef typename Dimension_eigen::type S2; public: typedef typename Vector::type type; }; public: templatestatic NT dot_product(Vec_ const&a,Vec_ const&b){ return a.dot(b); } template static typename Canonicalize_vector::type homogeneous_add(Vec1 const&a,Vec2 const&b){ //TODO: use compile-time size when available int d=a.size(); typename Canonicalize_vector::type v(d); v << b[d-1]*a.topRows(d-1)+a[d-1]*b.topRows(d-1), a[d-1]*b[d-1]; return v; } template static typename Canonicalize_vector::type homogeneous_sub(Vec1 const&a,Vec2 const&b){ int d=a.size(); typename Canonicalize_vector::type v(d); v << b[d-1]*a.topRows(d-1)-a[d-1]*b.topRows(d-1), a[d-1]*b[d-1]; return v; } template static std::pair homogeneous_dot_product(Vec1 const&a,Vec2 const&b){ int d=a.size(); return make_pair(a.topRows(d-1).dot(b.topRows(d-1)), a[d-1]*b[d-1]); } #endif }; } #endif