// Copyright (c) 2014 // INRIA Saclay-Ile de France (France) // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 3 of the License, // or (at your option) any later version. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // // Author(s) : Marc Glisse #ifndef CGAL_LA_EIGEN_H #define CGAL_LA_EIGEN_H #include #ifndef CGAL_EIGEN3_ENABLED #error Requires Eigen #endif #include #include #include #include #include #include namespace CGAL { //FIXME: where could we use Matrix_base instead of Matrix? // Dim_ real dimension // Max_dim_ upper bound on the dimension template struct LA_eigen { typedef NT_ NT; typedef Dim_ Dimension; typedef Max_dim_ Max_dimension; enum { dimension = Eigen_dimension::value }; enum { max_dimension = Eigen_dimension::value }; template< class D2, class D3=D2 > struct Rebind_dimension { typedef LA_eigen< NT, D2, D3 > Other; }; template struct Property : boost::false_type {}; template struct Property : boost::true_type {}; template struct Property : boost::true_type {}; template struct Property : boost::true_type {}; typedef Eigen::Matrix::value,1,Eigen::ColMajor|Eigen::AutoAlign,Eigen_dimension::value,1> Vector; typedef Eigen::Matrix Dynamic_vector; typedef Construct_eigen Construct_vector; #if (EIGEN_WORLD_VERSION>=3) typedef NT const* Vector_const_iterator; #else typedef Iterator_from_indices Vector_const_iterator; #endif templatestatic Vector_const_iterator vector_begin(Vec_ const&a){ #if (EIGEN_WORLD_VERSION>=3) return &a[0]; #else return Vector_const_iterator(a,0); #endif } templatestatic Vector_const_iterator vector_end(Vec_ const&a){ #if (EIGEN_WORLD_VERSION>=3) // FIXME: Isn't that dangerous if a is an expression and not a concrete vector? return &a[0]+a.size(); #else return Vector_const_iterator(a,a.size()); #endif } typedef Eigen::Matrix Square_matrix; typedef Eigen::Matrix Dynamic_matrix; //TODO: don't pass on the values of Max_* for an expensive NT // typedef ... Constructor // typedef ... Accessor #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: #endif templatestatic int size_of_vector(Vec_ const&v){ return (int)v.size(); } templatestatic NT dot_product(Vec_ const&a,Vec_ const&b){ return a.dot(b); } template static int rows(Vec_ const&v) { return (int)v.rows(); } template static int columns(Vec_ const&v) { return (int)v.cols(); } template static NT determinant(Mat_ const&m,bool=false){ return m.determinant(); } template static typename Same_uncertainty_nt::type sign_of_determinant(Mat_ const&m,bool=false) { return CGAL::sign(m.determinant()); } template static int rank(Mat_ const&m){ // return m.rank(); // This one uses sqrt so cannot be used with Gmpq // TODO: use different algo for different NT? // Eigen::ColPivHouseholderQR decomp(m); Eigen::FullPivLU decomp(m); // decomp.setThreshold(0); return static_cast(decomp.rank()); } // m*a==b template static void solve(DV&a, DM const&m, V const& b){ //a = m.colPivHouseholderQr().solve(b); a = m.fullPivLu().solve(b); } template static bool solve_and_check(DV&a, DM const&m, V const& b){ //a = m.colPivHouseholderQr().solve(b); a = m.fullPivLu().solve(b); return b.isApprox(m*a); } static Dynamic_matrix basis(Dynamic_matrix const&m){ return m.fullPivLu().image(m); } template static Vector homogeneous_add(Vec1 const&a,Vec2 const&b){ //TODO: use compile-time size when available int d=a.size(); Vector 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 Vector homogeneous_sub(Vec1 const&a,Vec2 const&b){ int d=a.size(); Vector 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