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

275 lines
8.1 KiB
C
Raw Normal View History

2020-10-13 12:44:25 +00:00
// Copyright (c) 1999,2007
// Utrecht University (The Netherlands),
// ETH Zurich (Switzerland),
// INRIA Sophia-Antipolis (France),
// Max-Planck-Institute Saarbruecken (Germany),
2020-10-13 12:44:25 +00:00
// and Tel-Aviv University (Israel). All rights reserved.
//
2020-10-13 12:44:25 +00:00
// This file is part of CGAL (www.cgal.org)
//
2020-10-13 12:44:25 +00:00
// $URL: https://github.com/CGAL/cgal/blob/v5.1/Number_types/include/CGAL/leda_rational.h $
// $Id: leda_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, Michael Hemmer
#ifndef CGAL_LEDA_RATIONAL_H
#define CGAL_LEDA_RATIONAL_H
#include <CGAL/IO/io.h>
#include <CGAL/number_type_basic.h>
#include <CGAL/leda_coercion_traits.h>
#include <CGAL/Interval_nt.h>
#include <CGAL/Needs_parens_as_product.h>
#include <utility>
#include <limits>
#include <CGAL/LEDA_basic.h>
#include <LEDA/numbers/rational.h>
#if defined( _MSC_VER )
# pragma push_macro("ERROR")
# undef ERROR
#endif // _MSC_VER
#include <LEDA/numbers/interval.h>
#if defined( _MSC_VER )
# pragma pop_macro("ERROR")
#endif
#include <CGAL/leda_integer.h> // for GCD in Fraction_traits
namespace CGAL {
template <> class Algebraic_structure_traits< leda_rational >
: public Algebraic_structure_traits_base< leda_rational,
Field_tag > {
public:
typedef Tag_true Is_exact;
typedef Tag_false Is_numerical_sensitive;
// TODO: How to implement this without having sqrt?
// typedef INTERN_AST::Is_square_per_sqrt< Type >
// Is_square;
class Simplify
: public CGAL::cpp98::unary_function< Type&, void > {
public:
void operator()( Type& x) const {
x.normalize();
}
};
};
template <> class Real_embeddable_traits< leda_rational >
: public INTERN_RET::Real_embeddable_traits_base< leda_rational , CGAL::Tag_true > {
public:
2020-10-13 12:44:25 +00:00
class Abs
: public CGAL::cpp98::unary_function< Type, Type > {
public:
Type operator()( const Type& x ) const {
return CGAL_LEDA_SCOPE::abs( x );
}
};
class Sgn
: public CGAL::cpp98::unary_function< Type, ::CGAL::Sign > {
public:
::CGAL::Sign operator()( const Type& x ) const {
return (::CGAL::Sign) CGAL_LEDA_SCOPE::sign( x );
}
};
class Compare
: public CGAL::cpp98::binary_function< Type, Type,
Comparison_result > {
public:
Comparison_result operator()( const Type& x,
const Type& y ) const {
return (Comparison_result) CGAL_LEDA_SCOPE::compare( x, y );
}
CGAL_IMPLICIT_INTEROPERABLE_BINARY_OPERATOR_WITH_RT(Type,Comparison_result)
};
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 {
CGAL_LEDA_SCOPE::interval temp(x);
std::pair<double, double> result(temp.lower_bound(),temp.upper_bound());
CGAL_assertion_code( double infinity=std::numeric_limits<double>::infinity(); )
CGAL_postcondition(result.first == -infinity || Type(result.first)<=x);
CGAL_postcondition(result.second == infinity || Type(result.second)>=x);
return result;
// Original CGAL to_interval (seemed to be inferior)
// // There's no guarantee about the error of to_double(), so I add
// // 3 ulps...
// Protect_FPU_rounding<true> P (CGAL_FE_TONEAREST);
// Interval_nt_advanced approx (z.to_double());
// FPU_set_cw(CGAL_FE_UPWARD);
//
// approx += Interval_nt<false>::smallest();
// approx += Interval_nt<false>::smallest();
// approx += Interval_nt<false>::smallest();
// return approx.pair();
}
};
};
/*! \ingroup NiX_Fraction_traits_spec
* \brief Specialization of Fraction_traits for ::leda::rational
*/
template <>
class Fraction_traits< leda_rational > {
public:
typedef leda_rational Type;
typedef ::CGAL::Tag_true Is_fraction;
typedef leda_integer Numerator_type;
typedef Numerator_type Denominator_type;
typedef Algebraic_structure_traits< Numerator_type >::Gcd Common_factor;
class Decompose {
public:
typedef Type first_argument_type;
typedef Numerator_type& second_argument_type;
typedef Numerator_type& third_argument_type;
void operator () (
const Type& rat,
Numerator_type& num,
Numerator_type& den) {
num = rat.numerator();
den = rat.denominator();
}
};
class Compose {
public:
typedef Numerator_type first_argument_type;
typedef Numerator_type second_argument_type;
typedef Type result_type;
Type operator ()(
const Numerator_type& num ,
const Numerator_type& den ) {
Type result(num, den);
result.normalize();
return result;
}
};
};
template <class F>
class Output_rep< leda_rational, F> : public IO_rep_is_specialized {
const leda_rational& t;
public:
//! initialize with a const reference to \a t.
Output_rep( const leda_rational& tt) : t(tt) {}
//! perform the output, calls \c operator\<\< by default.
std::ostream& operator()( std::ostream& out) const {
switch (get_mode(out)) {
case IO::PRETTY:{
if(t.denominator() == leda_integer(1))
return out <<t.numerator();
else
return out << t.numerator()
<< "/"
<< t.denominator();
break;
}
default:
return out << t.numerator()
<< "/"
<< t.denominator();
}
}
};
template <>
struct Needs_parens_as_product< leda_rational >{
bool operator()( leda_rational t){
if (t.denominator() != 1 )
return true;
else
return needs_parens_as_product(t.numerator()) ;
}
};
template <>
class Output_rep< leda_rational, Parens_as_product_tag >
: public IO_rep_is_specialized
{
const leda_rational& t;
public:
// Constructor
Output_rep( const leda_rational& tt) : t(tt) {}
// operator
std::ostream& operator()( std::ostream& out) const {
Needs_parens_as_product< leda_rational > needs_parens_as_product;
if (needs_parens_as_product(t))
return out <<"("<< oformat(t) <<")";
else
return out << oformat(t);
}
};
template < >
class Benchmark_rep< leda_rational > {
const leda_rational& t;
public:
//! initialize with a const reference to \a t.
Benchmark_rep( const leda_rational& tt) : t(tt) {}
//! perform the output, calls \c operator\<\< by default.
2020-10-13 12:44:25 +00:00
std::ostream& operator()( std::ostream& out) const {
return
out << "Rational(" << t.numerator() << ","
<< t.denominator() << ")";
}
static std::string get_benchmark_name() {
return "Rational";
}
};
namespace internal {
// See: Stream_support/include/CGAL/IO/io.h
template <typename ET>
void read_float_or_quotient(std::istream & is, ET& et);
template <>
inline void read_float_or_quotient(std::istream & is, leda_rational& et)
{
internal::read_float_or_quotient<leda_integer,leda_rational>(is, et);
}
} // namespace internal
} //namespace CGAL
// Unary + is missing for leda::rational
namespace leda{
inline rational operator+( const rational& i) { return i; }
}
//since types are included by LEDA_coercion_traits.h:
#include <CGAL/leda_integer.h>
#include <CGAL/leda_bigfloat.h>
#include <CGAL/leda_real.h>
#include <CGAL/LEDA_arithmetic_kernel.h>
#endif // CGAL_LEDA_RATIONAL_H