// Copyright (c) 2002 // Utrecht University (The Netherlands), // ETH Zurich (Switzerland), // INRIA Sophia-Antipolis (France), // Max-Planck-Institute Saarbruecken (Germany), // and Tel-Aviv University (Israel). All rights reserved. // // This file is part of CGAL (www.cgal.org) // // $URL: https://github.com/CGAL/cgal/blob/v5.1/Number_types/include/CGAL/to_rational.h $ // $Id: to_rational.h 0779373 2020-03-26T13:31:46+01:00 Sébastien Loriot // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Andreas Fabri, Susan Hert, Sylvain Pion #ifndef CGAL_TO_RATIONAL_H #define CGAL_TO_RATIONAL_H #include #include #include namespace CGAL { template Rational to_rational(double x) { typedef Fraction_traits FT; typedef typename FT::Is_fraction Is_fraction; typedef typename FT::Numerator_type Numerator_type; typedef typename FT::Denominator_type Denominator_type; typename FT::Compose compose; CGAL_static_assertion((::boost::is_same::value)); CGAL_USE_TYPE(Is_fraction); CGAL_static_assertion((::boost::is_same::value)); CGAL_USE_TYPE(Denominator_type); Numerator_type num(0),den(1); if (x != 0.0) { bool neg = (x < 0); if (neg) x = -x; const unsigned shift = 15; // a safe shift per step const int shift_pow = 32768; // = 2^shift const double width = 32768; // = 2^shift const int maxiter = 20; // ought not be necessary, but just in // case, max 300 bits of precision int expt; double mantissa = std::frexp(x, &expt); long exponent = expt; double intpart; int k = 0; while (mantissa != 0.0 && k++ < maxiter) { mantissa *= width; // shift double mantissa mantissa = std::modf(mantissa, &intpart); num *= shift_pow; num += (int)intpart; exponent -= shift; } int expsign = (exponent>0 ? +1 : (exponent<0 ? -1 : 0)); exponent *= expsign; Numerator_type twopot(2); Numerator_type exppot(1); while (exponent!=0) { if (exponent & 1) exppot *= twopot; exponent >>= 1; twopot *= twopot; } if (expsign > 0) num *= exppot; else if (expsign < 0) den *= exppot; if (neg) num = -num; } return compose(num,den); } } //namespace CGAL #endif // CGAL_TO_RATIONAL_H