// 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_VECTOR_2INT_H #define CGAL_VECTOR_2INT_H #include #include #include #include #include #include #include #include #include #include // What are the pros and cons of having NT be int vs double? namespace CGAL { struct Vector_2_int_prop1 { typedef double NT; // try lying a bit typedef int32_t NT1; // what is really stored typedef int32_t NT1b; // slightly longer typedef int_fast64_t NT2; // longer type for computations typedef int_fast64_t NT2b; // slightly longer bool check_limits(int32_t x){return std::abs(x)<(1<<30);} // TODO: find nice bounds }; #ifdef __SIZEOF_INT128__ struct Vector_2_int_prop2 { typedef double NT; typedef int32_t NT1; typedef int_fast64_t NT1b; typedef int_fast64_t NT2; typedef __int128 NT2b; bool check_limits(int32_t){return true;} // take a template/int64_t input and still check the limits? }; struct Vector_2_int_prop3 { typedef long double NT; typedef int64_t NT1; typedef int64_t NT1b; typedef __int128 NT2; typedef __int128 NT2b; enum { has_limit=true }; bool check_limits(int32_t x){return std::abs(x)<(1L<<62);} // TODO: find nice bounds }; #endif template struct Vector_2_int : Prop { using typename Prop::NT; using typename Prop::NT1; using typename Prop::NT1b; using typename Prop::NT2; using typename Prop::NT2b; using Prop::check_limits; typedef Dimension_tag<2> Dimension; typedef Dimension_tag<2> Max_dimension; // No Rebind_dimension, this is a building block template struct Property : boost::false_type {}; //template struct Property // : boost::true_type {}; template struct Property : boost::true_type {}; //template struct Property // : boost::true_type {}; // Advertise somehow that the sign_of_determinant* are exact? typedef cpp0x::array Vector; struct Construct_vector { struct Dimension { Vector operator()(unsigned d) const { CGAL_assertion(d==2); return Vector(); } }; // TODO (for all constructors): check that input fits in NT1... struct Iterator { template Vector operator()(unsigned d,Iter const& f,Iter const& e) const { CGAL_assertion(d==2); NT1 x0 = *f; NT1 x1 = *++f; CGAL_assertion (++f == e); CGAL_assertion (check_limits(x0) && check_limits(x1)); Vector a = { x0, x1 }; return a; } }; struct Iterator_and_last { template Vector operator()(unsigned d,Iter const& f,Iter const& e,double t) const { CGAL_assertion(d==2); NT1 x = *f; CGAL_assertion (++f == e); CGAL_assertion (check_limits(x) && check_limits(t)); Vector a = { x, t }; return a; } }; struct Values { Vector operator()(NT1 a,NT1 b) const { CGAL_assertion (check_limits(a) && check_limits(b)); Vector r = { a, b }; return r; } }; /* // Maybe safer not to provide it struct Values_divide { Vector operator()(double h,double a,double b) const { Vector r = { a/h, b/h }; return r; } }; */ }; // Since we lie about NT, be consistent about it typedef transforming_iterator,NT1 const*> Vector_const_iterator; static inline Vector_const_iterator vector_begin(Vector const&a){ return Vector_const_iterator(a.begin()); } static inline Vector_const_iterator vector_end(Vector const&a){ return Vector_const_iterator(a.end()); } static inline unsigned size_of_vector(Vector){ return 2; } // for unsigned NT1, check what changes to do. // return NT or NT2? static NT determinant_of_vectors(Vector a, Vector b) { return CGAL::determinant_of_vectors(a,b); } static CGAL::Sign sign_of_determinant_of_vectors(Vector a, Vector b) { return CGAL::sign_of_determinant_of_vectors(a,b); } static NT determinant_of_points(Vector a, Vector b, Vector c) { // could be faster to convert to NT directly NT1b a0=a[0]; NT1b a1=a[1]; NT1b x0=b[0]-a0; NT1b x1=b[1]-a1; NT1b y0=c[0]-a0; NT1b y1=c[1]-a1; return CGAL::determinant(x0,x1,y0,y1); } static CGAL::Sign sign_of_determinant_of_points(Vector a, Vector b, Vector c) { NT1b a0=a[0]; NT1b a1=a[1]; NT1b x0=b[0]-a0; NT1b x1=b[1]-a1; NT2b y0=c[0]-a0; NT2b y1=c[1]-a1; return CGAL::compare(x0*y1,x1*y0); } }; } #endif