dust3d/thirdparty/cgal/CGAL-5.1/include/CGAL/Gmpz.h

250 lines
6.8 KiB
C++

// Copyright (c) 2006-2008 Max-Planck-Institute Saarbruecken (Germany),
// INRIA Sophia-Antipolis (France).
// 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/Gmpz.h $
// $Id: Gmpz.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) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
// Sylvain Pion
#ifndef CGAL_GMPZ_H
#define CGAL_GMPZ_H
#include <CGAL/config.h>
#if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable:4800) // complaint about performance in std::map where we can't do anything
#endif
#include <CGAL/number_type_basic.h>
#include <CGAL/Gmp_coercion_traits.h>
#include <CGAL/Quotient.h> // spec of AST for Quotient<Gmpz>
#include <string>
#include <locale>
#include <CGAL/Modular_traits.h>
namespace CGAL {
// Algebraic structure traits
template <> class Algebraic_structure_traits< Gmpz >
: public Algebraic_structure_traits_base< Gmpz,
Euclidean_ring_tag > {
public:
typedef Tag_true Is_exact;
typedef Tag_false Is_numerical_sensitive;
typedef INTERN_AST::Is_square_per_sqrt< Type >
Is_square;
class Integral_division
: public CGAL::cpp98::binary_function< Type, Type,
Type > {
public:
Type operator()( const Type& x,
const Type& y ) const {
Gmpz result;
mpz_divexact(result.mpz(), x.mpz(), y.mpz());
CGAL_postcondition_msg(result * y == x, "exact_division failed\n");
return result;
}
};
class Gcd
: public CGAL::cpp98::binary_function< Type, Type,
Type > {
public:
Type operator()( const Type& x,
const Type& y ) const {
Gmpz result;
mpz_gcd(result.mpz(), x.mpz(), y.mpz());
return result;
}
Type operator()( const Type& x,
const int& y ) const {
if (y > 0)
{
Gmpz Res;
mpz_gcd_ui(Res.mpz(), x.mpz(), y);
return Res;
}
return CGAL_NTS gcd(x, Gmpz(y));
}
Type operator()( const int& x,
const Type& y ) const {
return CGAL_NTS gcd(Gmpz(x), y );
}
};
typedef INTERN_AST::Div_per_operator< Type > Div;
typedef INTERN_AST::Mod_per_operator< Type > Mod;
class Sqrt
: public CGAL::cpp98::unary_function< Type, Type > {
public:
Type operator()( const Type& x ) const {
Gmpz result;
mpz_sqrt(result.mpz(), x.mpz());
return result;
}
};
};
template <> class Real_embeddable_traits< Gmpz >
: public INTERN_RET::Real_embeddable_traits_base< Gmpz , CGAL::Tag_true > {
public:
class Sgn
: public CGAL::cpp98::unary_function< Type, ::CGAL::Sign > {
public:
::CGAL::Sign operator()( const Type& x ) const {
return x.sign();
}
};
class To_double
: public CGAL::cpp98::unary_function< Type, double > {
public:
double operator()( const Type& x ) const {
return x.to_double();
}
};
class To_interval
: public CGAL::cpp98::unary_function< Type, std::pair< double, double > > {
public:
std::pair<double, double> operator()( const Type& x ) const {
#if MPFR_VERSION_MAJOR >= 3
MPFR_DECL_INIT (y, 53); /* Assume IEEE-754 */
int r = mpfr_set_z (y, x.mpz(), MPFR_RNDA);
double i = mpfr_get_d (y, MPFR_RNDA); /* EXACT but can overflow */
if (r == 0 && is_finite (i))
return std::pair<double, double>(i, i);
else
{
double s = nextafter (i, 0);
if (i < 0)
return std::pair<double, double>(i, s);
else
return std::pair<double, double>(s, i);
}
#else
mpfr_t y;
mpfr_init2 (y, 53); /* Assume IEEE-754 */
mpfr_set_z (y, x.mpz(), GMP_RNDD);
double i = mpfr_get_d (y, GMP_RNDD); /* EXACT but can overflow */
mpfr_set_z (y, x.mpz(), GMP_RNDU);
double s = mpfr_get_d (y, GMP_RNDU); /* EXACT but can overflow */
mpfr_clear (y);
return std::pair<double, double>(i, s);
#endif
}
};
};
template<> class Algebraic_structure_traits< Quotient<Gmpz> >
: public INTERN_QUOTIENT::Algebraic_structure_traits_quotient_base<Quotient<Gmpz> >{
// specialization of to double functor
public:
typedef Quotient<Gmpz> Type;
struct To_double: public CGAL::cpp98::unary_function<Quotient<Gmpz>, double>{
double operator()(const Quotient<Gmpz>& quot){
mpq_t mpQ;
mpq_init(mpQ);
const Gmpz& n = quot.numerator();
const Gmpz& d = quot.denominator();
mpz_set(mpq_numref(mpQ), n.mpz());
mpz_set(mpq_denref(mpQ), d.mpz());
mpq_canonicalize(mpQ);
double ret = mpq_get_d(mpQ);
mpq_clear(mpQ);
return ret;
}
};
};
//
// Needs_parens_as_product
//
template <>
struct Needs_parens_as_product<Gmpz> {
bool operator()(const Gmpz& x) {
return CGAL_NTS is_negative(x);
}
};
/*! \ingroup NiX_Modular_traits_spec
* \brief a model of concept ModularTraits,
* specialization of NiX::Modular_traits.
*/
template<>
class Modular_traits< Gmpz > {
typedef Residue RES;
public:
typedef Gmpz NT;
typedef CGAL::Tag_true Is_modularizable;
typedef Residue Residue_type;
struct Modular_image{
Residue_type operator()(const NT& a){
NT tmp_1(a % NT(RES::get_current_prime()));
return CGAL::Residue(int(mpz_get_si(tmp_1.mpz())));
}
};
struct Modular_image_representative{
NT operator()(const Residue_type& x){
return NT(x.get_value());
}
};
};
} //namespace CGAL
#if defined(BOOST_MSVC)
# pragma warning(pop)
#endif
namespace Eigen {
template<class> struct NumTraits;
template<> struct NumTraits<CGAL::Gmpz>
{
typedef CGAL::Gmpz Real;
typedef CGAL::Gmpq NonInteger;
typedef CGAL::Gmpz Nested;
typedef CGAL::Gmpz Literal;
static inline Real epsilon() { return 0; }
static inline Real dummy_precision() { return 0; }
enum {
IsInteger = 1,
IsSigned = 1,
IsComplex = 0,
RequireInitialization = 1,
ReadCost = 6,
AddCost = 30,
MulCost = 50
};
};
}
//since types are included by Gmp_coercion_traits.h:
#include <CGAL/Gmpz.h>
#include <CGAL/Gmpq.h>
#include <CGAL/Gmpzf.h>
#include <CGAL/GMP_arithmetic_kernel.h>
#endif // CGAL_GMPZ_H