Merge pull request #6035 from afabri/CORE-boost_mp_number-GF

CORE: Use boost::multiprecision::number API
This commit is contained in:
Laurent Rineau 2024-03-26 10:04:54 +01:00
commit 54c5d19121
125 changed files with 1598 additions and 3563 deletions

View File

@ -2,6 +2,7 @@ Advancing_front_surface_reconstruction
Algebraic_foundations
Arithmetic_kernel
BGL
CGAL_Core
Cartesian_kernel
Circulator
Distance_2

View File

@ -53,7 +53,7 @@ struct Rational_traits_base<Rational, true>
{
private:
typedef Fraction_traits<Rational> FT;
typedef typename FT::Decompose Decomose;
typedef typename FT::Decompose Decompose;
typedef typename FT::Compose Compose;
public:
@ -61,13 +61,13 @@ public:
RT numerator (const Rational& r) const {
RT num,den;
Decomose()(r,num,den);
Decompose()(r,num,den);
return num;
}
RT denominator (const Rational& r) const {
RT num,den;
Decomose()(r,num,den);
Decompose()(r,num,den);
return den;
}

View File

@ -303,7 +303,7 @@ public:
Integer alpha_num = Integer(1), int log_denom = 1
) : alpha_num_(alpha_num),
beta_num_((Integer(1) << log_denom) - alpha_num),
half_((log_denom > 0) ? (Integer(1) << log_denom-1) : 0),
half_((log_denom > 0) ? Integer(Integer(1) << log_denom-1) : 0),
log_denom_(log_denom)
{
CGAL_precondition(log_denom_ >= 0);

View File

@ -206,7 +206,7 @@ polynomial_power_to_bernstein_approx(
std::vector<Integer> f(n+1);
polynomial_affine_transform_approx_log_denom(
first, beyond, f.begin(),
upper_num - lower_num, lower_num, log_denom,
Integer(upper_num - lower_num), lower_num, log_denom,
p+q,
approx, log, logl
);

View File

@ -27,31 +27,10 @@
#include <vector>
#if CGAL_USE_CORE
namespace CORE { class BigInt; }
#endif
namespace CGAL {
namespace internal {
#if CGAL_USE_CORE
// bugfix for CORE by Michael Kerber
// why is there a specialized function for CORE?
inline CORE::BigInt shift_integer_by(CORE::BigInt x, long shift){
if( shift > 0 ){
while(shift>63) {
x = (x >> 63);
shift-=63;
}
x = (x >> shift);
}else{
// add 0 bits
x = (x << -shift);
}
return x;
}
#endif
template <class Shiftable>
Shiftable shift_integer_by(Shiftable x, long shift){

View File

@ -327,7 +327,7 @@ public:
long operator()( CORE::BigFloat x ) const {
CGAL_precondition(!CGAL::zero_in(x));
x = CGAL::abs(x);
return CORE::floorLg(x.m()-x.err())+x.exp()*CORE::CHUNK_BIT;
return CORE::floorLg(CORE::BigInt(x.m()-x.err()))+x.exp()*CORE::CHUNK_BIT;
}
};
@ -337,7 +337,7 @@ public:
// (already commented out in EXACUS)...
// NiX_precond(!(NiX::in_zero(x) && NiX::singleton(x)));
x = CGAL::abs(x);
return CORE::ceilLg(x.m()+x.err())+x.exp()*CORE::CHUNK_BIT;
return CORE::ceilLg(CORE::BigInt(x.m()+x.err()))+x.exp()*CORE::CHUNK_BIT;
}
};

View File

@ -220,7 +220,7 @@ simple_bound_between(const Algebraic_real& a,
final_mantissa = final_mantissa << 1;
final_mantissa++;
y_log--;
x_m = x_m==0 ? 0 : x_m & ((Integer(1) << x_log) - 1); //x_m - CGAL::ipower(Integer(2),x_log);
x_m = x_m==0 ? 0 : Integer(x_m & ((Integer(1) << x_log) - 1)); //x_m - CGAL::ipower(Integer(2),x_log);
x_log = x_m==0 ? -1 : CGAL::internal::floor_log2_abs(x_m);
}
final_mantissa = final_mantissa << 1;

View File

@ -1,6 +1,7 @@
Algebraic_foundations
Algebraic_kernel_for_circles
Arithmetic_kernel
CGAL_Core
Filtered_kernel
Installation
Interval_support

View File

@ -1,6 +1,7 @@
Algebraic_foundations
Algebraic_kernel_for_spheres
Arithmetic_kernel
CGAL_Core
Filtered_kernel
Installation
Interval_support

View File

@ -1,6 +1,7 @@
Algebraic_foundations
Alpha_shapes_2
Arithmetic_kernel
CGAL_Core
Cartesian_kernel
Hash_map
Homogeneous_kernel

View File

@ -1,6 +1,7 @@
Algebraic_foundations
Alpha_shapes_3
Arithmetic_kernel
CGAL_Core
Cartesian_kernel
Circulator
Filtered_kernel

View File

@ -4,6 +4,7 @@ Alpha_wrap_3
Arithmetic_kernel
BGL
Box_intersection_d
CGAL_Core
Cartesian_kernel
Circulator
Distance_2

View File

@ -19,6 +19,10 @@
#ifdef CGAL_USE_BOOST_MP
#ifdef CGAL_USE_CORE
#include <CGAL/CORE_arithmetic_kernel.h>
#endif
//Currently already included in boost_mp.h
//#include <boost/multiprecision/cpp_int.hpp>
//#ifdef CGAL_USE_GMP
@ -26,20 +30,29 @@
//#endif
// FIXME: the could be several kernels based on Boost.Multiprecision.
namespace CGAL {
/** \ingroup CGAL_Arithmetic_kernel
* \brief The Boost.Multiprecision set of exact number types
*/
#if !defined(CGAL_USE_CORE) || defined(CGAL_CORE_USE_GMP_BACKEND)
struct BOOST_cpp_arithmetic_kernel : internal::Arithmetic_kernel_base {
typedef boost::multiprecision::cpp_int Integer;
typedef boost::multiprecision::cpp_rational Rational;
};
#else
typedef CORE_arithmetic_kernel BOOST_cpp_arithmetic_kernel;
#endif
#ifdef CGAL_USE_GMP
#if !defined(CGAL_USE_CORE) || !defined(CGAL_CORE_USE_GMP_BACKEND)
struct BOOST_gmp_arithmetic_kernel : internal::Arithmetic_kernel_base {
typedef boost::multiprecision::mpz_int Integer;
typedef boost::multiprecision::mpq_rational Rational;
};
#else
typedef CORE_arithmetic_kernel BOOST_gmp_arithmetic_kernel;
#endif
#endif
template <class T1, class T2, class T3, class T4, class T5>

View File

@ -55,14 +55,6 @@ public:
};
template <>
struct Get_arithmetic_kernel<CORE::BigInt>{
typedef CORE_arithmetic_kernel Arithmetic_kernel;
};
template <>
struct Get_arithmetic_kernel<CORE::BigRat>{
typedef CORE_arithmetic_kernel Arithmetic_kernel;
};
template <>
struct Get_arithmetic_kernel<CORE::Expr>{
typedef CORE_arithmetic_kernel Arithmetic_kernel;
@ -74,6 +66,8 @@ struct Get_arithmetic_kernel<CORE::BigFloat>{
} //namespace CGAL
#include <CGAL/BOOST_MP_arithmetic_kernel.h>
#endif // CGAL_USE_CORE
#endif // CGAL_CORE_ARITHMETIC_KERNEL_H

View File

@ -202,7 +202,7 @@ operator()(const Point_2& p, const X_monotone_curve_2& curve) const {
auto points = painterOstream.getPointsList(curve);
QPoint p_viewport =
view->mapFromScene(QPointF{p.x().doubleValue(), p.y().doubleValue()});
view->mapFromScene(QPointF{CGAL::to_double(p.x()), CGAL::to_double(p.y())});
double min_dist = (std::numeric_limits<double>::max)();
for (auto& vec : points) {

View File

@ -3316,9 +3316,9 @@ public:
// sqrt((r - s)^2 + t^2)
//
const int or_fact = (cv.orientation() == CLOCKWISE) ? -1 : 1;
const Algebraic r = m_nt_traits->convert(or_fact * cv.r());
const Algebraic s = m_nt_traits->convert(or_fact * cv.s());
const Algebraic t = m_nt_traits->convert(or_fact * cv.t());
const Algebraic r = m_nt_traits->convert(Integer(or_fact * cv.r()));
const Algebraic s = m_nt_traits->convert(Integer(or_fact * cv.s()));
const Algebraic t = m_nt_traits->convert(Integer(or_fact * cv.t()));
const Algebraic cos_2phi = (r - s) / m_nt_traits->sqrt((r-s)*(r-s) + t*t);
const Algebraic zero = 0;
const Algebraic one = 1;
@ -3363,8 +3363,8 @@ public:
// 4*r*s - t^2 4*r*s - t^2
//
// The denominator (4*r*s - t^2) must be negative for hyperbolas.
const Algebraic u = m_nt_traits->convert(or_fact * cv.u());
const Algebraic v = m_nt_traits->convert(or_fact * cv.v());
const Algebraic u = m_nt_traits->convert(Integer(or_fact * cv.u()));
const Algebraic v = m_nt_traits->convert(Integer(or_fact * cv.v()));
const Algebraic det = 4*r*s - t*t;
Algebraic x0, y0;
@ -3803,9 +3803,9 @@ public:
auto u = cv.u();
auto v = cv.v();
auto w = cv.w();
Algebraic* xs_end = m_nt_traits->solve_quadratic_equation(t*t - four*r*s,
two*t*v - four*s*u,
v*v - four*s*w,
Algebraic* xs_end = m_nt_traits->solve_quadratic_equation(Integer(t*t - four*r*s),
Integer(two*t*v - four*s*u),
Integer(v*v - four*s*w),
xs);
auto n_xs = static_cast<int>(xs_end - xs);
@ -3816,15 +3816,15 @@ public:
if (CGAL::sign(cv.t()) == ZERO) {
// The two vertical tangency points have the same y coordinate:
ys[0] = m_nt_traits->convert(-v) / m_nt_traits->convert(two*s);
ys[0] = m_nt_traits->convert(Integer(- v)) / m_nt_traits->convert(Integer(two * s));
n_ys = 1;
}
else {
ys_end = m_nt_traits->solve_quadratic_equation(four*r*s*s - s*t*t,
four*r*s*v - two*s*t*u,
r*v*v - t*u*v +
t*t*w,
ys_end = m_nt_traits->solve_quadratic_equation(Integer(four*r*s*s - s*t*t),
Integer(four*r*s*v - two*s*t*u),
Integer((r*v*v - t*u*v) + (t*t*w)),
ys);
n_ys = static_cast<int>(ys_end - ys);
}
@ -3837,7 +3837,7 @@ public:
}
else {
for (int j = 0; j < n_ys; ++j) {
if (CGAL::compare(m_nt_traits->convert(two*s) * ys[j],
if (CGAL::compare(m_nt_traits->convert(Integer(two*s)) * ys[j],
-(m_nt_traits->convert(t) * xs[i] +
m_nt_traits->convert(v))) == EQUAL)
{
@ -3904,10 +3904,11 @@ public:
auto u = cv.u();
auto v = cv.v();
auto w = cv.w();
Algebraic* ys_end = m_nt_traits->solve_quadratic_equation(t*t - four*r*s,
two*t*u - four*r*v,
u*u - four*r*w,
ys);
Algebraic* ys_end = m_nt_traits->template
solve_quadratic_equation<Integer>(t*t - four*r*s,
two*t*u - four*r*v,
u*u - four*r*w,
ys);
auto n = static_cast<int>(ys_end - ys);
// Compute the x coordinates and construct the horizontal tangency points.
@ -3915,7 +3916,7 @@ public:
// Having computed y, x is the single solution to the quadratic equation
// above, and since its discriminant is 0, x is simply given by:
Algebraic x = -(m_nt_traits->convert(t)*ys[i] + m_nt_traits->convert(u)) /
m_nt_traits->convert(two*r);
m_nt_traits->convert(Integer(two*r));
ps[i] = Point_2(x, ys[i]);
}

View File

@ -1430,8 +1430,8 @@ protected:
{
// Actually compare the slopes.
const bool swap_res = (sign_denom1 != sign_denom2);
const CoordNT A = (cv.y0() - y0())*p.x() + (y0()*cv.x0() - cv.y0()*x0());
const CoordNT B = (cv.x0() - x0())*p.y();
const CoordNT A = NT(cv.y0() - y0())*p.x() + (y0()*cv.x0() - cv.y0()*x0());
const CoordNT B = NT(cv.x0() - x0())*p.y();
slope_res = CGAL::compare (A, B);

View File

@ -1110,9 +1110,9 @@ protected:
//
Nt_traits nt_traits;
const int or_fact = (m_orient == CLOCKWISE) ? -1 : 1;
const Algebraic r = nt_traits.convert(or_fact * m_r);
const Algebraic s = nt_traits.convert(or_fact * m_s);
const Algebraic t = nt_traits.convert(or_fact * m_t);
const Algebraic r = nt_traits.convert(Integer(or_fact * m_r));
const Algebraic s = nt_traits.convert(Integer(or_fact * m_s));
const Algebraic t = nt_traits.convert(Integer(or_fact * m_t));
const Algebraic cos_2phi = (r - s) / nt_traits.sqrt((r-s)*(r-s) + t*t);
const Algebraic zero = 0;
const Algebraic one = 1;
@ -1158,8 +1158,8 @@ protected:
// 4*r*s - t^2 4*r*s - t^2
//
// The denominator (4*r*s - t^2) must be negative for hyperbolas.
const Algebraic u = nt_traits.convert(or_fact * m_u);
const Algebraic v = nt_traits.convert(or_fact * m_v);
const Algebraic u = nt_traits.convert(Integer(or_fact * m_u));
const Algebraic v = nt_traits.convert(Integer(or_fact * m_v));
const Algebraic det = 4*r*s - t*t;
Algebraic x0, y0;

View File

@ -64,8 +64,9 @@ int compute_resultant_roots(const Nt_traits& nt_traits,
}
// Act according to the degree of the first conic curve.
const typename Nt_traits::Integer two = 2;
typename Nt_traits::Integer c[5];
typedef typename Nt_traits::Integer Integer;
const Integer two = 2;
Integer c[5];
unsigned int degree = 4;
typename Nt_traits::Algebraic* xs_end;
@ -73,7 +74,7 @@ int compute_resultant_roots(const Nt_traits& nt_traits,
// The first curve has no quadratic coefficients, and represents a line.
if (CGAL::sign (v1) == ZERO) {
// The first line is u1*x + w1 = 0, therefore:
xs[0] = nt_traits.convert(-w1) / nt_traits.convert(u1);
xs[0] = nt_traits.convert(Integer(- w1)) / nt_traits.convert(u1);
return 1;
}
@ -87,7 +88,7 @@ int compute_resultant_roots(const Nt_traits& nt_traits,
// Return if the two lines are parallel
if (CGAL::sign (c[1]) == ZERO) return 0;
xs[0] = nt_traits.convert(-c[0]) / nt_traits.convert(c[1]);
xs[0] = nt_traits.convert(Integer(- c[0])) / nt_traits.convert(c[1]);
return 1;
}

View File

@ -225,10 +225,11 @@ public:
if (CGAL::compare(
CGAL::width(y_bfi),
CGAL::lower(CGAL::abs(y_bfi)) * eps)
== SMALLER)
== SMALLER){
return std::make_pair(
Bound(CGAL::lower(y_bfi)),
Bound(CGAL::upper(y_bfi)));
}
}
else precision*=2;
}
@ -287,10 +288,11 @@ private:
if (CGAL::zero_in(y_denom_bfi) == false)
{
BFI y_bfi(y_numer_bfi/y_denom_bfi);
if (CGAL::width(y_bfi) < eps )
if (CGAL::width(y_bfi) < eps ){
return std::make_pair(
Bound(CGAL::lower(y_bfi)),
Bound(CGAL::upper(y_bfi)));
}
}
else precision*=2;

View File

@ -106,7 +106,7 @@ public:
ix1 = scaled_x1.BigIntValue();
ix2 = scaled_x2.BigIntValue();
if (CORE::abs (ix2 - ix1) > one)
if (CGAL::abs (ix2 - ix1) > one)
break;
// Scale the values by a factor of 2.
@ -179,9 +179,9 @@ public:
temp_gcd = numer_gcd;
denom_lcm *= denom;
denom_lcm /= CORE::gcd (temp_lcm, denom);
denom_lcm /= CGAL::gcd (temp_lcm, denom);
numer_gcd = CORE::gcd (temp_gcd, numer);
numer_gcd = CGAL::gcd (temp_gcd, numer);
}
++q_iter;
@ -246,8 +246,8 @@ public:
if (sign_disc == ZERO)
{
// We have one real root with mutliplicity 2.
*oi = -Algebraic (b) / Algebraic (2*a);
// We have one real root with multiplicity 2.
*oi = -Algebraic (b) / Algebraic (NT(2*a));
++oi;
}
else if (sign_disc == POSITIVE)
@ -255,7 +255,7 @@ public:
// We have two distinct real roots. We return them in ascending order.
const Algebraic sqrt_disc = CGAL::sqrt (Algebraic (disc));
const Algebraic alg_b = b;
const Algebraic alg_2a = 2*a;
const Algebraic alg_2a = NT(2*a);
if (sign_a == POSITIVE)
{
@ -334,7 +334,7 @@ public:
temp_lcm = denom_lcm;
denom_lcm *= denom;
denom_lcm /= CORE::gcd (temp_lcm, denom);
denom_lcm /= CGAL::gcd (temp_lcm, denom);
}
index--;

View File

@ -865,7 +865,7 @@ void draw(const Arc_2& arc,
get_pixel_coords(l, y_clip, pix_beg);
get_pixel_coords(ptmp->left, it->second ? engine.y_max_r :
engine.y_min_r, pix_end);
if(CGAL_ABS(ptmp->left - l) <= engine.pixel_w_r*2) {
if(CGAL_ABS(Rational(ptmp->left - l)) <= engine.pixel_w_r*2) {
Coordinate_2 xy(Coordinate_1(pt), *support, arc.arcno());
Rational _;

View File

@ -695,7 +695,7 @@ bool get_range_QF_1(int var, const NT& l_, const NT& r_, const NT& key,
while(der_it != der_begin) {
--der_it;
e1 = xsum_abs * e1 + CGAL_ABS(x1 * z1);
e1 = xsum_abs * e1 + CGAL_ABS(NT(x1 * z1));
z1 = x0*z1 + x1*y1;
y1 = y1*x0 + x1*y0;
y0 = x0*y0 + extract(*cache_it)*(*der_it);
@ -726,7 +726,7 @@ bool get_range_QF_1(int var, const NT& l_, const NT& r_, const NT& key,
NT y0 = extract(*cache_it), y1(0), z1(0), e1(0);
while(cache_it != begin) {
--cache_it;
e1 = xsum_abs * e1 + CGAL_ABS(x1*z1);
e1 = xsum_abs * e1 + CGAL_ABS(NT(x1*z1));
z1 = x0*z1 + x1*y1;
y1 = y1*x0 + x1*y0;
y0 = x0*y0 + extract(*cache_it);

View File

@ -336,7 +336,7 @@ struct Curve_renderer_traits<CGAL::Interval_nt<true>, CORE::BigRat > :
//! Specialization for \c CORE::BigFloat
template <>
struct Curve_renderer_traits<CORE::BigFloat, class CORE::BigRat>
struct Curve_renderer_traits<CORE::BigFloat, CORE::BigRat>
: public Curve_renderer_traits_base<CORE::BigFloat, CORE::BigInt,
CORE::BigRat> {
@ -347,7 +347,7 @@ struct Curve_renderer_traits<CORE::BigFloat, class CORE::BigRat>
typedef Integer result_type;
Integer operator()(const Rational& x) const {
return x.BigIntValue();
return numerator(x)/denominator(x);
}
};
@ -400,7 +400,7 @@ struct Curve_renderer_traits<CORE::BigRat, CORE::BigRat> :
typedef Integer result_type;
Integer operator()(const Rational& x) const {
return x.BigIntValue();
return numerator(x)/denominator(x);
}
};
@ -409,9 +409,7 @@ struct Curve_renderer_traits<CORE::BigRat, CORE::BigRat> :
typedef std::size_t result_type;
inline result_type operator()(const Float& key) const {
const CORE::BigRatRep& rep = key.getRep();
std::size_t ret = reinterpret_cast<std::size_t>(&rep);
return ret;
return std::hash<Float>()(key);
}
};
};

View File

@ -877,7 +877,7 @@ endfunction()
#---------------------------------------------------------------------#
function(test_polycurve_conic_traits)
# echo polycurve test starting
if(CGAL_DISABLE_GMP)
if(NOT CGAL_Core_FOUND)
MESSAGE(STATUS "test_polycurve_conic_traits requires CORE and will not be executed")
return()
endif()
@ -948,7 +948,7 @@ endfunction()
# polycurve bezier traits
#---------------------------------------------------------------------#
function(test_polycurve_bezier_traits)
if(CGAL_DISABLE_GMP)
if(NOT CGAL_Core_FOUND)
MESSAGE(STATUS "test_polycurve_bezier_traits requires CORE and will not be executed")
return()
endif()
@ -1057,7 +1057,7 @@ endfunction()
# conic traits
#---------------------------------------------------------------------#
function(test_conic_traits)
if(CGAL_DISABLE_GMP)
if(NOT CGAL_Core_FOUND)
MESSAGE(STATUS "test_conic_traits requires CORE and will not be executed")
return()
endif()
@ -1188,7 +1188,7 @@ endfunction()
# bezier traits
#---------------------------------------------------------------------#
function(test_bezier_traits)
if(CGAL_DISABLE_GMP)
if(NOT CGAL_Core_FOUND)
MESSAGE(STATUS "test_bezier_traits requires CORE and will not be executed")
return()
endif()
@ -1235,7 +1235,7 @@ endfunction()
# rational arc traits
#---------------------------------------------------------------------#
function(test_rational_arc_traits)
if(CGAL_DISABLE_GMP)
if(NOT CGAL_Core_FOUND)
MESSAGE(STATUS "test_rational_arc_traits requires CORE and will not be executed")
return()
endif()
@ -1302,7 +1302,7 @@ endfunction()
#---------------------------------------------------------------------#
function(test_algebraic_traits_core)
#TODO: Adapt
if(CGAL_DISABLE_GMP)
if(NOT CGAL_Core_FOUND)
MESSAGE(STATUS "test_algebraic_traits_core requires CORE and will not be executed")
return()
endif()

View File

@ -7,18 +7,18 @@
# We need the bezier curve (not polycurve) to contruct a bezier point.
#
# Point ID: 0
r c 4 0 0 500 200 100 200 900 0 0.5
r c 4 0 0 500 200 100 200 900 0 1/2
# Point ID: 1
r c 4 900 0 1200 600 1500 400 900 600 0.3
r c 4 900 0 1200 600 1500 400 900 600 3/10
# Point id: 2
r c 4 0 0 100 200 500 200 900 0 0.0
r c 4 0 0 100 200 500 200 900 0 0
# Point id: 3
r c 4 900 0 1200 300 1500 400 2000 450 1.0
r c 4 900 0 1200 300 1500 400 2000 450 1
# Point id: 4
r c 4 2000 450 2100 300 2200 200 2300 450 0.0
r c 4 2000 450 2100 300 2200 200 2300 450 0
# Point id: 5
r c 4 2300 450 2500 500 2800 600 3000 450 1.0
r c 4 2300 450 2500 500 2800 600 3000 450 1
# Point id: 6
r c 4 0 0 100 200 500 200 900 0 0.0
r c 4 0 0 100 200 500 200 900 0 0
# Point id: 7
r c 4 2300 450 2500 500 2800 600 3000 450 1.0
r c 4 2300 450 2500 500 2800 600 3000 450 1

View File

@ -2,6 +2,7 @@ Algebraic_foundations
Arithmetic_kernel
BGL
Barycentric_coordinates_2
CGAL_Core
Cartesian_kernel
Circulator
Distance_2

View File

@ -2,6 +2,7 @@ Algebraic_foundations
Arithmetic_kernel
Arrangement_on_surface_2
Boolean_set_operations_2
CGAL_Core
Cartesian_kernel
Circular_kernel_2
Circulator

View File

@ -59,7 +59,7 @@ public:
/// constructor for <tt>const char* </tt>(default base = 10)
BigFloat(const char* s) : RCBigFloat(new BigFloatRep(s)) {}
/// constructor for <tt>std::string</tt>(default base = 10)
BigFloat(const std::string& s) : RCBigFloat(new BigFloatRep(s)) {}
BigFloat(const std::string& s) : RCBigFloat(new BigFloatRep(s.c_str())) {}
/// constructor for <tt>int</tt> and <tt>long</tt>
// This is a hack because in Sturm, we need to approximate any
@ -106,6 +106,9 @@ public:
explicit BigFloat(BigFloatRep* r, bool) : RCBigFloat(r) {
}
operator BigRat() const {
return this->BigRatValue();
}
//@}
@ -510,32 +513,6 @@ inline long minStar(long m, long n) {
}
/// \name Functions for Compatibility with BigInt (needed by Poly, Curves)
//@{
/// isDivisible(a,b) = "is a divisible by b"
/** Assuming that a and b are in coanonized forms.
Defined to be true if mantissa(b) | mantissa(a) &&
exp(b) = min*(exp(b), exp(a)).
* This concepts assume a and b are exact BigFloats.
*/
inline bool isDivisible(const BigFloat& a, const BigFloat& b) {
// assert: a and b are exact BigFloats.
if (sign(a.m()) == 0) return true;
if (sign(b.m()) == 0) return false;
unsigned long bin_a = getBinExpo(a.m());
unsigned long bin_b = getBinExpo(b.m());
BigInt m_a = a.m() >> bin_a;
BigInt m_b = b.m() >> bin_b;
long e_a = bin_a + BigFloatRep::bits(a.exp());
long e_b = bin_b + BigFloatRep::bits(b.exp());
long dx = minStar(e_a, e_b);
return isDivisible(m_a, m_b) && (dx == e_b);
}
inline bool isDivisible(double x, double y) {
//Are these exact?
return isDivisible(BigFloat(x), BigFloat(y));
}
/// div_exact(x,y) returns the BigFloat quotient of x divided by y
/** This is defined only if isDivisible(x,y).
@ -548,7 +525,6 @@ inline bool isDivisible(double x, double y) {
// normalizing it then we get zero.
inline BigFloat div_exact(const BigFloat& x, const BigFloat& y) {
BigInt z;
CGAL_assertion (isDivisible(x,y));
unsigned long bin_x = getBinExpo(x.m());
unsigned long bin_y = getBinExpo(y.m());
@ -615,15 +591,20 @@ inline BigFloat gcd(const BigFloat& a, const BigFloat& b) {
//}//
// constructor BigRat from BigFloat
inline BigRat::BigRat(const BigFloat& f) : RCBigRat(new BigRatRep()){
*this = f.BigRatValue();
inline double doubleValue(const BigFloat& bf)
{
return bf.doubleValue();
}
inline long longValue(const BigFloat& bf)
{
return bf.longValue();
}
} //namespace CORE
#ifdef CGAL_HEADER_ONLY
#include <CGAL/CORE/BigFloat_impl.h>
#include <CGAL/CORE/CoreIO_impl.h>
#endif // CGAL_HEADER_ONLY
#include <CGAL/enable_warnings.h>

View File

@ -317,7 +317,7 @@ inline void BigFloatRep::eliminateTrailingZeroes() {
// builtin functions
inline extLong BigFloatRep::lMSB() const {
if (!isZeroIn())
return extLong(floorLg(abs(m) - err)) + bits(exp);
return extLong(floorLg(BigInt(abs(m) - err))) + bits(exp);
else
return extLong(CORE_negInfty);
}
@ -327,7 +327,7 @@ inline extLong BigFloatRep::lMSB() const {
* Not well-defined if zero is in the interval.
*/
inline extLong BigFloatRep::uMSB() const {
return extLong(floorLg(abs(m) + err)) + bits(exp);
return extLong(floorLg(BigInt(abs(m) + err))) + bits(exp);
}
inline extLong BigFloatRep::MSB() const {

View File

@ -194,8 +194,7 @@ void BigFloatRep :: truncM(const BigFloatRep& B, const extLong& r, const extLong
err = 2;
exp = B.exp + t;
} else // t < chunkCeil(clLg(B.err))
core_error(std::string("BigFloat error: truncM called with stricter")
+ "precision than current error.", __FILE__, __LINE__, true);
CGAL_error_msg("BigFloat error: truncM called with stricter precision than current error.");
} else {// B.m == 0
long t = chunkFloor(- a.asLong()) - B.exp;
@ -204,8 +203,7 @@ void BigFloatRep :: truncM(const BigFloatRep& B, const extLong& r, const extLong
err = 1;
exp = B.exp + t;
} else // t < chunkCeil(clLg(B.err))
core_error(std::string("BigFloat error: truncM called with stricter")
+ "precision than current error.", __FILE__, __LINE__, true);
CGAL_error_msg("BigFloat error: truncM called with stricter precision than current error.");
}
}
@ -216,7 +214,7 @@ CGAL_INLINE_FUNCTION
void BigFloatRep::approx(const BigFloatRep& B,
const extLong& r, const extLong& a) {
if (B.err) {
if (1 + clLg(B.err) <= bitLength(B.m))
if (static_cast<std::size_t>(1 + clLg(B.err)) <= bitLength(B.m))
truncM(B, r + 1, a);
else // 1 + clLg(B.err) > lg(B.m)
truncM(B, CORE_posInfty, a);
@ -258,7 +256,7 @@ void BigFloatRep::div(const BigInt& N, const BigInt& D,
exp = 0;
}
} else // D == 0
core_error( "BigFloat error: zero divisor.", __FILE__, __LINE__, true);
CGAL_error_msg( "BigFloat error: zero divisor.");
// Call normalization globally -- IP 10/9/98
normal();
@ -455,6 +453,7 @@ void BigFloatRep::centerize(const BigFloatRep& a, const BigFloatRep& b) {
// Zilin & Vikram, 08/24/04
// err = 1 + longValue(chunkShift(r.m, r.exp - exp));
BigInt E = chunkShift(r.m, r.exp - exp);
E = abs(E);
bigNormal(E);
}
@ -538,8 +537,7 @@ void BigFloatRep :: div(const BigFloatRep& x, const BigFloatRep& y,
bigNormal(bigErr);
}
} else {// y.m <= y.err
core_error("BigFloat error: possible zero divisor.",
__FILE__, __LINE__, true);
CGAL_error_msg("BigFloat error: possible zero divisor.");
}
// Call normalization globally -- IP 10/9/98
@ -734,8 +732,7 @@ void BigFloatRep::sqrt(const BigFloatRep& x, const extLong& a, const BigFloat& A
} // end of case with error in mantissa
}//else
} else
core_error("BigFloat error: squareroot called with negative operand.",
__FILE__, __LINE__, true);
CGAL_error_msg("BigFloat error: squareroot called with negative operand.");
} //sqrt with initial approximation
// compareMExp(x)
@ -822,8 +819,7 @@ BigFloatRep::toDecimal(unsigned int width, bool Scientific) const {
if (err > 0 && err >= abs(m)) {
// if err is larger than mantissa, sign and significant values
// can not be determined.
core_error("BigFloat error: Error is too big!",
__FILE__, __LINE__, false);
CGAL_CORE_warning_msg(true, "BigFloat error: Error is too big!");
decOut.rep = "0.0e0"; // error is too big
decOut.isScientific = false;
decOut.noSignificant = 0;
@ -869,7 +865,7 @@ BigFloatRep::toDecimal(unsigned int width, bool Scientific) const {
M <<= e2; // M = x * 2^(e2)
}
std::string decRep = M.get_str();
std::string decRep = M.convert_to<std::string>();
// Determine the "significant part" of this string, i.e. the part which
// is guaranteed to be correct in the presence of error,
// except that the last digit which might be subject to +/- 1.
@ -1003,8 +999,7 @@ void BigFloatRep :: fromString(const char *str, extLong prec ) {
// NOTE: prec defaults to get_static_defBigFloatInputDigits() (see BigFloat.h)
// check that prec is not INFTY
if (prec.isInfty())
core_error("BigFloat error: infinite precision not allowed",
__FILE__, __LINE__, true);
CGAL_error_msg("BigFloat error: infinite precision not allowed");
const char *e = strchr(str, 'e');
int dot = 0;

View File

@ -24,448 +24,113 @@
#ifndef _CORE_BIGINT_H_
#define _CORE_BIGINT_H_
#include <CGAL/CORE/Gmp.h>
#include <CGAL/boost_mp_type.h>
#include <CGAL/CORE/RefCount.h>
#include <CGAL/CORE/MemoryPool.h>
#include <string>
#if !(defined(CGAL_CORE_USE_BOOST_BACKEND) && BOOST_VERSION > 107900 && defined(CGAL_USE_BOOST_MP)) && !defined(CGAL_DISABLE_GMP)
#define CGAL_CORE_USE_GMP_BACKEND 1
#endif
namespace CORE {
#ifdef CGAL_CORE_USE_GMP_BACKEND
typedef boost::multiprecision::mpz_int BigInt;
#else
typedef boost::multiprecision::cpp_int BigInt;
#endif
class BigIntRep : public RCRepImpl<BigIntRep> {
public:
BigIntRep() {
mpz_init(mp);
}
// Note : should the copy-ctor be allowed at all ? [Sylvain Pion]
BigIntRep(const BigIntRep& z) : RCRepImpl<BigIntRep>() {
mpz_init_set(mp, z.mp);
}
BigIntRep(signed char c) {
mpz_init_set_si(mp, c);
}
BigIntRep(unsigned char c) {
mpz_init_set_ui(mp, c);
}
BigIntRep(signed int i) {
mpz_init_set_si(mp, i);
}
BigIntRep(unsigned int i) {
mpz_init_set_ui(mp, i);
}
BigIntRep(signed short int s) {
mpz_init_set_si(mp, s);
}
BigIntRep(unsigned short int s) {
mpz_init_set_ui(mp, s);
}
BigIntRep(signed long int l) {
mpz_init_set_si(mp, l);
}
BigIntRep(unsigned long int l) {
mpz_init_set_ui(mp, l);
}
BigIntRep(float f) {
mpz_init_set_d(mp, f);
}
BigIntRep(double d) {
mpz_init_set_d(mp, d);
}
BigIntRep(const char* s, int base=0) {
mpz_init_set_str(mp, s, base);
}
BigIntRep(const std::string& s, int base=0) {
mpz_init_set_str(mp, s.c_str(), base);
}
explicit BigIntRep(mpz_srcptr z) {
mpz_init_set(mp, z);
}
~BigIntRep() {
mpz_clear(mp);
}
CGAL_CORE_EXPORT CORE_NEW(BigIntRep)
CGAL_CORE_EXPORT CORE_DELETE(BigIntRep)
mpz_srcptr get_mp() const {
return mp;
}
mpz_ptr get_mp() {
return mp;
}
private:
mpz_t mp;
};
typedef RCImpl<BigIntRep> RCBigInt;
class CGAL_CORE_EXPORT BigInt : public RCBigInt {
public:
/// \name Constructors
//@{
/// default constructor
BigInt() : RCBigInt(new BigIntRep()) {}
/// constructor for <tt>signed char</tt>
BigInt(signed char x) : RCBigInt(new BigIntRep(x)) {}
/// constructor for <tt>unsigned char</tt>
BigInt(unsigned char x) : RCBigInt(new BigIntRep(x)) {}
/// constructor for <tt>signed short int</tt>
BigInt(signed short int x) : RCBigInt(new BigIntRep(x)) {}
/// constructor for <tt>unsigned short int</tt>
BigInt(unsigned short int x) : RCBigInt(new BigIntRep(x)) {}
/// constructor for <tt>signed int</tt>
BigInt(signed int x) : RCBigInt(new BigIntRep(x)) {}
/// constructor for <tt>unsigned int</tt>
BigInt(unsigned int x) : RCBigInt(new BigIntRep(x)) {}
/// constructor for <tt>signed long int</tt>
BigInt(signed long int x) : RCBigInt(new BigIntRep(x)) {}
/// constructor for <tt>unsigned long int</tt>
BigInt(unsigned long int x) : RCBigInt(new BigIntRep(x)) {}
/// constructor for <tt>float</tt>
BigInt(float x) : RCBigInt(new BigIntRep(x)) {}
/// constructor for <tt>double</tt>
BigInt(double x) : RCBigInt(new BigIntRep(x)) {}
/// constructor for <tt>const char*</tt> with base
BigInt(const char* s, int base=0) : RCBigInt(new BigIntRep(s, base)) {}
/// constructor for <tt>std::string</tt> with base
BigInt(const std::string& s, int base=0) : RCBigInt(new BigIntRep(s, base)) {}
/// constructor for <tt>mpz_srcptr</tt>
explicit BigInt(mpz_srcptr z) : RCBigInt(new BigIntRep(z)) {}
//@}
/// \name Copy-Assignment-Destructor
//@{
/// copy constructor
BigInt(const BigInt& rhs) : RCBigInt(rhs) {
rep->incRef();
}
/// assignment operator
BigInt& operator=(const BigInt& rhs) {
if (this != &rhs) {
rep->decRef();
rep = rhs.rep;
rep->incRef();
}
return *this;
}
/// destructor
~BigInt() {
rep->decRef();
}
//@}
/// \name Overloaded operators
//@{
BigInt& operator +=(const BigInt& rhs) {
makeCopy();
mpz_add(get_mp(), get_mp(), rhs.get_mp());
return *this;
}
BigInt& operator -=(const BigInt& rhs) {
makeCopy();
mpz_sub(get_mp(), get_mp(), rhs.get_mp());
return *this;
}
BigInt& operator *=(const BigInt& rhs) {
makeCopy();
mpz_mul(get_mp(), get_mp(), rhs.get_mp());
return *this;
}
BigInt& operator /=(const BigInt& rhs) {
makeCopy();
mpz_tdiv_q(get_mp(), get_mp(), rhs.get_mp());
return *this;
}
BigInt& operator %=(const BigInt& rhs) {
makeCopy();
mpz_tdiv_r(get_mp(), get_mp(), rhs.get_mp());
return *this;
}
BigInt& operator &=(const BigInt& rhs) {
makeCopy();
mpz_and(get_mp(), get_mp(), rhs.get_mp());
return *this;
}
BigInt& operator |=(const BigInt& rhs) {
makeCopy();
mpz_ior(get_mp(), get_mp(), rhs.get_mp());
return *this;
}
BigInt& operator ^=(const BigInt& rhs) {
makeCopy();
mpz_xor(get_mp(), get_mp(), rhs.get_mp());
return *this;
}
BigInt& operator <<=(unsigned long ul) {
makeCopy();
mpz_mul_2exp(get_mp(), get_mp(), ul);
return *this;
}
BigInt& operator >>=(unsigned long ul) {
makeCopy();
mpz_tdiv_q_2exp(get_mp(), get_mp(), ul);
return *this;
}
//@}
/// \name unary, increment, decrement operators
//@{
BigInt operator+() const {
return BigInt(*this);
}
BigInt operator-() const {
BigInt r;
mpz_neg(r.get_mp(), get_mp());
return r;
}
BigInt& operator++() {
makeCopy();
mpz_add_ui(get_mp(), get_mp(), 1);
return *this;
}
BigInt& operator--() {
makeCopy();
mpz_sub_ui(get_mp(), get_mp(), 1);
return *this;
}
BigInt operator++(int) {
BigInt r(*this);
++(*this);
return r;
}
BigInt operator--(int) {
BigInt r(*this);
--(*this);
return r;
}
//@}
/// \name Helper Functions
//@{
/// Has Exact Division
static bool hasExactDivision() {
return false;
}
/// get mpz pointer (const)
mpz_srcptr get_mp() const {
return rep->get_mp();
}
/// get mpz pointer
mpz_ptr get_mp() {
return rep->get_mp();
}
//@}
/// \name String Conversion Functions
//@{
/// set value from <tt>const char*</tt>
int set_str(const char* s, int base = 0) {
makeCopy();
return mpz_set_str(get_mp(), s, base);
}
/// convert to <tt>std::string</tt>
std::string get_str(int base = 10) const {
int n = mpz_sizeinbase (get_mp(), base) + 2;
char *buffer = new char[n];
mpz_get_str(buffer, base, get_mp());
std::string result(buffer);
delete [] buffer;
return result;
}
//@}
/// \name Conversion Functions
//@{
/// intValue
int intValue() const {
return static_cast<int>(mpz_get_si(get_mp()));
}
/// longValue
long longValue() const {
return mpz_get_si(get_mp());
}
/// ulongValue
unsigned long ulongValue() const {
return mpz_get_ui(get_mp());
}
/// doubleValue
double doubleValue() const {
return mpz_get_d(get_mp());
}
//@}
};
inline BigInt operator+(const BigInt& a, const BigInt& b) {
BigInt r;
mpz_add(r.get_mp(), a.get_mp(), b.get_mp());
return r;
}
inline BigInt operator-(const BigInt& a, const BigInt& b) {
BigInt r;
mpz_sub(r.get_mp(), a.get_mp(), b.get_mp());
return r;
}
inline BigInt operator*(const BigInt& a, const BigInt& b) {
BigInt r;
mpz_mul(r.get_mp(), a.get_mp(), b.get_mp());
return r;
}
inline BigInt operator/(const BigInt& a, const BigInt& b) {
BigInt r;
mpz_tdiv_q(r.get_mp(), a.get_mp(), b.get_mp());
return r;
}
inline BigInt operator%(const BigInt& a, const BigInt& b) {
BigInt r;
mpz_tdiv_r(r.get_mp(), a.get_mp(), b.get_mp());
return r;
}
inline BigInt operator&(const BigInt& a, const BigInt& b) {
BigInt r;
mpz_and(r.get_mp(), a.get_mp(), b.get_mp());
return r;
}
inline BigInt operator|(const BigInt& a, const BigInt& b) {
BigInt r;
mpz_ior(r.get_mp(), a.get_mp(), b.get_mp());
return r;
}
inline BigInt operator^(const BigInt& a, const BigInt& b) {
BigInt r;
mpz_xor(r.get_mp(), a.get_mp(), b.get_mp());
return r;
}
inline BigInt operator<<(const BigInt& a, unsigned long ul) {
BigInt r;
mpz_mul_2exp(r.get_mp(), a.get_mp(), ul);
return r;
}
inline BigInt operator>>(const BigInt& a, unsigned long ul) {
BigInt r;
mpz_tdiv_q_2exp(r.get_mp(), a.get_mp(), ul);
return r;
}
inline int cmp(const BigInt& x, const BigInt& y) {
return mpz_cmp(x.get_mp(), y.get_mp());
}
inline bool operator==(const BigInt& a, const BigInt& b) {
return cmp(a, b) == 0;
}
inline bool operator!=(const BigInt& a, const BigInt& b) {
return cmp(a, b) != 0;
}
inline bool operator>=(const BigInt& a, const BigInt& b) {
return cmp(a, b) >= 0;
}
inline bool operator>(const BigInt& a, const BigInt& b) {
return cmp(a, b) > 0;
}
inline bool operator<=(const BigInt& a, const BigInt& b) {
return cmp(a, b) <= 0;
}
inline bool operator<(const BigInt& a, const BigInt& b) {
return cmp(a, b) < 0;
return x.compare(y);
}
inline std::ostream& operator<<(std::ostream& o, const BigInt& x) {
//return CORE::operator<<(o, x.get_mp());
return CORE::io_write(o, x.get_mp());
}
inline std::istream& operator>>(std::istream& i, BigInt& x) {
x.makeCopy();
//return CORE::operator>>(i, x.get_mp());
return CORE::io_read(i, x.get_mp());
}
/// sign
inline int sign(const BigInt& a) {
return mpz_sgn(a.get_mp());
}
/// abs
inline BigInt abs(const BigInt& a) {
BigInt r;
mpz_abs(r.get_mp(), a.get_mp());
return r;
}
/// neg
inline BigInt neg(const BigInt& a) {
BigInt r;
mpz_neg(r.get_mp(), a.get_mp());
return r;
}
/// negate
inline void negate(BigInt& a) {
a.makeCopy();
mpz_neg(a.get_mp(), a.get_mp());
}
/// cmpabs
inline int cmpabs(const BigInt& a, const BigInt& b) {
return mpz_cmpabs(a.get_mp(), b.get_mp());
}
inline int set_str(BigInt& a, const char* s) {
a = BigInt(s);
return 0; // should be -1 if not correct in the base (we ignore)
}
/// \name Conversion Functions
//@{
/// longValue
/// longValue
inline long longValue(const BigInt& a) {
return a.longValue();
return a.convert_to<long>();
}
/// ulongValue
inline unsigned long ulongValue(const BigInt& a) {
return a.ulongValue();
}
/// doubleValue
/// doubleValue
inline double doubleValue(const BigInt& a) {
return a.doubleValue();
return a.convert_to<double>();
}
//@}
/// \name File I/O Functions
//@{
/// read from file
void readFromFile(BigInt& z, std::istream& in, long maxLength = 0);
/// write to file
void writeToFile(const BigInt& z, std::ostream& in, int base=10, int charsPerLine=80);
//@}
/// \name Misc Functions
//@{
/// isEven
/// isEven
inline bool isEven(const BigInt& z) {
return mpz_even_p(z.get_mp());
return bit_test(z,0) == 0;
}
/// isOdd
inline bool isOdd(const BigInt& z) {
return mpz_odd_p(z.get_mp());
return bit_test(z,0) == 1;
}
/// get exponent of power 2
inline unsigned long getBinExpo(const BigInt& z) {
return mpz_scan1(z.get_mp(), 0);
}
/// get exponent of power k
inline void getKaryExpo(const BigInt& z, BigInt& m, int& e, unsigned long k) {
mpz_t f;
mpz_init_set_ui(f, k);
m.makeCopy();
e = mpz_remove(m.get_mp(), z.get_mp(), f);
mpz_clear(f);
}
/// divisible(x,y) = "x | y"
inline bool isDivisible(const BigInt& x, const BigInt& y) {
return mpz_divisible_p(x.get_mp(), y.get_mp()) != 0;
BigInt q, r;
divide_qr(x, y, q, r);
return r.is_zero();
}
inline bool isDivisible(int x, int y) {
return x % y == 0;
}
inline bool isDivisible(long x, long y) {
return x % y == 0;
}
/// exact div
/// get exponent of power 2
inline std::size_t getBinExpo(const BigInt& z) {
if (z.is_zero()) {
return (std::numeric_limits<std::size_t>::max)();
}
return lsb(abs(z));
}
// bit length
inline std::size_t bitLength(const BigInt& a){
if (a.is_zero()) {
return 0;
}
return msb(abs(a))+1;
}
/// floorLg -- floor of log_2(a)
/** Convention: a=0, floorLg(a) returns -1.
* This makes sense for integer a.
*/
inline long floorLg(const BigInt& a) {
assert(std::size_t((std::numeric_limits<long>::max)()) > bitLength(a));
return (sign(a) == 0) ? (-1) : static_cast<long>(bitLength(a)-1);
}
/// div_rem
inline void div_rem(BigInt& q, BigInt& r, const BigInt& a, const BigInt& b) {
divide_qr(a, b, q, r);
}
/// ulongValue
inline unsigned long ulongValue(const BigInt& a) {
assert(a >= BigInt(0));
return a.convert_to<unsigned long>();
}
/// exact div
inline void divexact(BigInt& z, const BigInt& x, const BigInt& y) {
z.makeCopy();
mpz_divexact(z.get_mp(), x.get_mp(), y.get_mp());
BigInt r;
divide_qr(x, y, z, r ); // was void mpz_divexact (mpz_t q, const mpz_t n, const mpz_t d) Is this faster?
assert(r.is_zero());
}
// Chee (1/12/2004) The definition of div_exact(x,y) next
// ensure that in Polynomials<NT> works with both NT=BigInt and NT=int:
inline BigInt div_exact(const BigInt& x, const BigInt& y) {
@ -473,50 +138,19 @@ inline BigInt div_exact(const BigInt& x, const BigInt& y) {
divexact(z, x, y); // z is set to x/y;
return z;
}
inline int div_exact(int x, int y) {
return x/y; // precondition: isDivisible(x,y)
}
inline long div_exact(long x, long y) {
return x/y; // precondition: isDivisible(x,y)
}
/// gcd
inline BigInt gcd(const BigInt& a, const BigInt& b) {
BigInt r;
mpz_gcd(r.get_mp(), a.get_mp(), b.get_mp());
return r;
}
/// div_rem
inline void div_rem(BigInt& q, BigInt& r, const BigInt& a, const BigInt& b) {
q.makeCopy();
r.makeCopy();
mpz_tdiv_qr(q.get_mp(), r.get_mp(), a.get_mp(), b.get_mp());
}
/// power
inline void power(BigInt& c, const BigInt& a, unsigned long ul) {
c.makeCopy();
mpz_pow_ui(c.get_mp(), a.get_mp(), ul);
inline BigInt gcd(const BigInt& a, const BigInt& b){
return boost::multiprecision::gcd(a,b);
}
// pow
inline BigInt pow(const BigInt& a, unsigned long ui) {
BigInt r;
power(r, a, ui);
return r;
}
// bit length
inline int bitLength(const BigInt& a) {
return mpz_sizeinbase(a.get_mp(), 2);
}
/// floorLg -- floor of log_2(a)
/** Convention: a=0, floorLg(a) returns -1.
* This makes sense for integer a.
*/
inline long floorLg(const BigInt& a) {
return (sign(a) == 0) ? (-1) : (bitLength(a)-1);
}
/// ceilLg -- ceiling of log_2(a) where a=BigInt, int or long
/** Convention: a=0, ceilLg(a) returns -1.
* This makes sense for integer a.
@ -524,20 +158,45 @@ inline long floorLg(const BigInt& a) {
inline long ceilLg(const BigInt& a) {
if (sign(a) == 0)
return -1;
unsigned long len = bitLength(a);
return (mpz_scan1(a.get_mp(), 0) == len-1) ? (len-1) : len;
assert(std::size_t((std::numeric_limits<long>::max)()) > bitLength(a));
std::size_t len = static_cast<long>(bitLength(a));
return (lsb(abs(a)) == len - 1) ? (static_cast<long>(len) - 1) : static_cast<long>(len);
}
inline long ceilLg(long a) { // need this for Polynomial<long>
return ceilLg(BigInt(a));
}
inline long ceilLg(int a) { // need this for Polynomial<int>
return ceilLg(BigInt(a));
}
//@}
/// negate
inline void negate(BigInt& a) {
a= - a;
}
/// get exponent of power k
inline void getKaryExpo(const BigInt& z, BigInt& m, int& e, unsigned long uk) {
BigInt k(uk), q, r;
e = 0;
m = z;
for(;;) {
divide_qr(m, k, q, r);
if (!r.is_zero()) break;
m = q;
++e;
}
}
inline void power(BigInt& c, const BigInt& a, unsigned long ul) {
c = pow(a, ul);
}
} // namespace CORE
} //namespace CORE
#endif // _CORE_BIGINT_H_

View File

@ -28,354 +28,35 @@
#include <CGAL/CORE/BigInt.h>
namespace CORE {
#ifdef CGAL_CORE_USE_GMP_BACKEND
typedef boost::multiprecision::mpq_rational BigRat;
#else
typedef boost::multiprecision::cpp_rational BigRat;
#endif
class BigRatRep : public RCRepImpl<BigRatRep> {
public:
BigRatRep() {
mpq_init(mp);
}
// Note : should the copy-ctor be allowed at all ? [Sylvain Pion]
BigRatRep(const BigRatRep& z) : RCRepImpl<BigRatRep>() {
mpq_init(mp);
mpq_set(mp, z.mp);
}
BigRatRep(signed char c) {
mpq_init(mp);
mpq_set_si(mp, c, 1);
}
BigRatRep(unsigned char c) {
mpq_init(mp);
mpq_set_ui(mp, c, 1);
}
BigRatRep(signed int i) {
mpq_init(mp);
mpq_set_si(mp, i, 1);
}
BigRatRep(unsigned int i) {
mpq_init(mp);
mpq_set_ui(mp, i, 1);
}
BigRatRep(signed short int s) {
mpq_init(mp);
mpq_set_si(mp, s, 1);
}
BigRatRep(unsigned short int s) {
mpq_init(mp);
mpq_set_ui(mp, s, 1);
}
BigRatRep(signed long int l) {
mpq_init(mp);
mpq_set_si(mp, l, 1);
}
BigRatRep(unsigned long int l) {
mpq_init(mp);
mpq_set_ui(mp, l, 1);
}
BigRatRep(float f) {
mpq_init(mp);
mpq_set_d(mp, f);
}
BigRatRep(double d) {
mpq_init(mp);
mpq_set_d(mp, d);
}
BigRatRep(const char* s) {
mpq_init(mp);
mpq_set_str(mp, s, 0);
}
BigRatRep(const std::string& s) {
mpq_init(mp);
mpq_set_str(mp, s.c_str(), 0);
}
explicit BigRatRep(mpq_srcptr q) {
mpq_init(mp);
mpq_set(mp, q);
}
BigRatRep(mpz_srcptr z) {
mpq_init(mp);
mpq_set_z(mp, z);
}
BigRatRep(mpz_srcptr n, mpz_srcptr d) {
mpq_init(mp);
mpz_set(mpq_numref(mp), n);
mpz_set(mpq_denref(mp), d);
mpq_canonicalize(mp);
}
~BigRatRep() {
mpq_clear(mp);
inline BigInt numerator(const BigRat& q)
{
return boost::multiprecision::numerator(q);
}
CGAL_CORE_EXPORT CORE_NEW(BigRatRep)
CGAL_CORE_EXPORT CORE_DELETE(BigRatRep)
mpq_srcptr get_mp() const {
return mp;
}
mpq_ptr get_mp() {
return mp;
}
private:
mpq_t mp;
}; //BigRatRep
class BigFloat;
typedef RCImpl<BigRatRep> RCBigRat;
class BigRat : public RCBigRat {
public:
/// \name Constructors
//@{
/// default constructor
BigRat() : RCBigRat(new BigRatRep()) {}
/// constructor for <tt>signed char</tt>
BigRat(signed char x) : RCBigRat(new BigRatRep(x)) {}
/// constructor for <tt>unsigned char</tt>
BigRat(unsigned char x) : RCBigRat(new BigRatRep(x)) {}
/// constructor for <tt>signed short int</tt>
BigRat(signed short int x) : RCBigRat(new BigRatRep(x)) {}
/// constructor for <tt>unsigned short int</tt>
BigRat(unsigned short int x) : RCBigRat(new BigRatRep(x)) {}
/// constructor for <tt>signed int</tt>
BigRat(signed int x) : RCBigRat(new BigRatRep(x)) {}
/// constructor for <tt>unsigned int</tt>
BigRat(unsigned int x) : RCBigRat(new BigRatRep(x)) {}
/// constructor for <tt>signed long int</tt>
BigRat(signed long int x) : RCBigRat(new BigRatRep(x)) {}
/// constructor for <tt>unsigned long int</tt>
BigRat(unsigned long int x) : RCBigRat(new BigRatRep(x)) {}
/// constructor for <tt>float</tt>
BigRat(float x) : RCBigRat(new BigRatRep(x)) {}
/// constructor for <tt>double</tt>
BigRat(double x) : RCBigRat(new BigRatRep(x)) {}
/// constructor for <tt>const char*</tt> with base
BigRat(const char* s) : RCBigRat(new BigRatRep(s)) {}
/// constructor for <tt>std::string</tt> with base
BigRat(const std::string& s) : RCBigRat(new BigRatRep(s)) {}
/// constructor for <tt>mpq_srcptr</tt>
explicit BigRat(mpq_srcptr z) : RCBigRat(new BigRatRep(z)) {}
/// constructor for <tt>BigInt</tt>
BigRat(const BigInt& z) : RCBigRat(new BigRatRep(z.get_mp())) {}
/// constructor for two <tt>BigInts</tt>
BigRat(const BigInt& n, const BigInt& d)
: RCBigRat(new BigRatRep(n.get_mp(), d.get_mp())) {}
/// constructor for <tt>BigFloat</tt>
BigRat(const BigFloat&);
//@}
/// \name Copy-Assignment-Destructor
//@{
/// copy constructor
BigRat(const BigRat& rhs) : RCBigRat(rhs) {
rep->incRef();
}
/// assignment operator
BigRat& operator=(const BigRat& rhs) {
if (this != &rhs) {
rep->decRef();
rep = rhs.rep;
rep->incRef();
}
return *this;
}
/// destructor
~BigRat() {
rep->decRef();
}
//@}
/// \name Overloaded operators
//@{
BigRat& operator +=(const BigRat& rhs) {
makeCopy();
mpq_add(get_mp(), get_mp(), rhs.get_mp());
return *this;
}
BigRat& operator -=(const BigRat& rhs) {
makeCopy();
mpq_sub(get_mp(), get_mp(), rhs.get_mp());
return *this;
}
BigRat& operator *=(const BigRat& rhs) {
makeCopy();
mpq_mul(get_mp(), get_mp(), rhs.get_mp());
return *this;
}
BigRat& operator /=(const BigRat& rhs) {
makeCopy();
mpq_div(get_mp(), get_mp(), rhs.get_mp());
return *this;
}
BigRat& operator <<=(unsigned long ul) {
makeCopy();
mpq_mul_2exp(get_mp(), get_mp(), ul);
return *this;
}
BigRat& operator >>=(unsigned long ul) {
makeCopy();
mpq_div_2exp(get_mp(), get_mp(), ul);
return *this;
}
//@}
/// \name div2, unary, increment, decrement operators
//@{
/// exact division by 2 (this method is provided for compatibility)
BigRat div2() const {
BigRat r; BigRat t(2); // probably not most efficient way
mpq_div(r.get_mp(), get_mp(), t.get_mp());
return r;
}
BigRat operator+() const {
return BigRat(*this);
}
BigRat operator-() const {
BigRat r;
mpq_neg(r.get_mp(), get_mp());
return r;
}
BigRat& operator++() {
makeCopy();
mpz_add(get_num_mp(),get_num_mp(),get_den_mp());
return *this;
}
BigRat& operator--() {
makeCopy();
mpz_sub(get_num_mp(),get_num_mp(),get_den_mp());
return *this;
}
BigRat operator++(int) {
BigRat r(*this);
++(*this);
return r;
}
BigRat operator--(int) {
BigRat r(*this);
--(*this);
return r;
}
//@}
/// \name Helper Functions
//@{
/// Canonicalize
void canonicalize() {
makeCopy();
mpq_canonicalize(get_mp());
}
/// Has Exact Division
static bool hasExactDivision() {
return true;
inline BigInt denominator(const BigRat& q)
{
return boost::multiprecision::denominator(q);
}
/// return mpz pointer of numerator (const)
mpz_srcptr get_num_mp() const {
return mpq_numref(get_mp());
}
/// return mpz pointer of numerator
mpz_ptr get_num_mp() {
return mpq_numref(get_mp());
}
/// return mpz pointer of denominator
mpz_srcptr get_den_mp() const {
return mpq_denref(get_mp());
}
/// return mpz pointer of denominator
mpz_ptr get_den_mp() {
return mpq_denref(get_mp());
}
/// get mpq pointer (const)
mpq_srcptr get_mp() const {
return rep->get_mp();
}
/// get mpq pointer
mpq_ptr get_mp() {
return rep->get_mp();
}
//@}
/// \name String Conversion Functions
//@{
/// set value from <tt>const char*</tt>
int set_str(const char* s, int base = 0) {
makeCopy();
return mpq_set_str(get_mp(), s, base);
}
/// convert to <tt>std::string</tt>
std::string get_str(int base = 10) const {
int n = mpz_sizeinbase(mpq_numref(get_mp()), base) + mpz_sizeinbase(mpq_denref(get_mp()), base)+ 3;
char *buffer = new char[n];
mpq_get_str(buffer, base, get_mp());
std::string result(buffer);
delete [] buffer;
return result;
}
//@}
/// \name Conversion Functions
//@{
/// intValue
int intValue() const {
return static_cast<int>(doubleValue());
}
/// longValue
long longValue() const {
return static_cast<long>(doubleValue());
}
/// doubleValue
double doubleValue() const {
return mpq_get_d(get_mp());
}
/// BigIntValue
BigInt BigIntValue() const {
BigInt r;
mpz_tdiv_q(r.get_mp(), get_num_mp(), get_den_mp());
return r;
}
//@}
}; //BigRat class
inline BigRat operator+(const BigRat& a, const BigRat& b) {
BigRat r;
mpq_add(r.get_mp(), a.get_mp(), b.get_mp());
return r;
}
inline BigRat operator-(const BigRat& a, const BigRat& b) {
BigRat r;
mpq_sub(r.get_mp(), a.get_mp(), b.get_mp());
return r;
}
inline BigRat operator*(const BigRat& a, const BigRat& b) {
BigRat r;
mpq_mul(r.get_mp(), a.get_mp(), b.get_mp());
return r;
}
inline BigRat operator/(const BigRat& a, const BigRat& b) {
BigRat r;
mpq_div(r.get_mp(), a.get_mp(), b.get_mp());
return r;
}
// Chee (3/19/2004):
// Chee (3/19/2004):
// The following definitions of div_exact(x,y) and gcd(x,y)
// ensures that in Polynomial<NT>
/// divisible(x,y) = "x | y"
inline BigRat div_exact(const BigRat& x, const BigRat& y) {
BigRat z;
mpq_div(z.get_mp(), x.get_mp(), y.get_mp());
return z;
}
/// numerator
inline BigInt numerator(const BigRat& a) {
return BigInt(a.get_num_mp());
}
/// denominator
inline BigInt denominator(const BigRat& a) {
return BigInt(a.get_den_mp());
}
inline BigRat div_exact(const BigRat& x, const BigRat& y) {
BigRat z = x / y;
return z;
}
inline BigRat gcd(const BigRat& x, const BigRat& y) {
// return BigRat(1); // Remark: we may want replace this by
inline BigRat gcd(const BigRat& x , const BigRat& y)
{
// return BigRat(1); // Remark: we may want replace this by
// the definition of gcd of a quotient field
// of a UFD [Yap's book, Chap.3]
//Here is one possible definition: gcd of x and y is just the
@ -384,98 +65,17 @@ inline BigRat gcd(const BigRat& x, const BigRat& y) {
BigInt n = gcd(numerator(x), numerator(y));
BigInt d = gcd(denominator(x), denominator(y));
return BigRat(n,d);
}
}
// Chee: 8/8/2004: need isDivisible to compile Polynomial<BigRat>
// A trivial implementation is to return true always. But this
// caused tPolyRat to fail.
// So we follow the definition of
// Expr::isDivisible(e1, e2) which checks if e1/e2 is an integer.
inline bool isInteger(const BigRat& x) {
return BigInt(x.get_den_mp()) == 1;
}
inline bool isDivisible(const BigRat& x, const BigRat& y) {
BigRat r;
mpq_div(r.get_mp(), x.get_mp(), y.get_mp());
return isInteger(r);
}
inline BigRat operator<<(const BigRat& a, unsigned long ul) {
BigRat r;
mpq_mul_2exp(r.get_mp(), a.get_mp(), ul);
return r;
}
inline BigRat operator>>(const BigRat& a, unsigned long ul) {
BigRat r;
mpq_div_2exp(r.get_mp(), a.get_mp(), ul);
/// BigIntValue
inline BigInt BigIntValue(const BigRat& br)
{
BigInt r, rem;
divide_qr(numerator(br), denominator(br), r, rem);
return r;
}
inline int cmp(const BigRat& x, const BigRat& y) {
return mpq_cmp(x.get_mp(), y.get_mp());
}
inline bool operator==(const BigRat& a, const BigRat& b) {
return cmp(a, b) == 0;
}
inline bool operator!=(const BigRat& a, const BigRat& b) {
return cmp(a, b) != 0;
}
inline bool operator>=(const BigRat& a, const BigRat& b) {
return cmp(a, b) >= 0;
}
inline bool operator>(const BigRat& a, const BigRat& b) {
return cmp(a, b) > 0;
}
inline bool operator<=(const BigRat& a, const BigRat& b) {
return cmp(a, b) <= 0;
}
inline bool operator<(const BigRat& a, const BigRat& b) {
return cmp(a, b) < 0;
}
inline std::ostream& operator<<(std::ostream& o, const BigRat& x) {
//return CORE::operator<<(o, x.get_mp());
return CORE::io_write(o, x.get_mp());
}
inline std::istream& operator>>(std::istream& i, BigRat& x) {
x.makeCopy();
//return CORE::operator>>(i, x.get_mp());
return CORE::io_read(i, x.get_mp());
}
/// sign
inline int sign(const BigRat& a) {
return mpq_sgn(a.get_mp());
}
/// abs
inline BigRat abs(const BigRat& a) {
BigRat r;
mpq_abs(r.get_mp(), a.get_mp());
return r;
}
/// neg
inline BigRat neg(const BigRat& a) {
BigRat r;
mpq_neg(r.get_mp(), a.get_mp());
return r;
}
/// div2
inline BigRat div2(const BigRat& a) {
BigRat r(a);
return r.div2();
}
/// longValue
inline long longValue(const BigRat& a) {
return a.longValue();
}
/// doubleValue
inline double doubleValue(const BigRat& a) {
return a.doubleValue();
}
/// return BigInt value
inline BigInt BigIntValue(const BigRat& a) {
return a.BigIntValue();
}
} // namespace CORE
} //namespace CORE
#endif // _CORE_BIGRAT_H_

View File

@ -29,4 +29,13 @@
#include <CGAL/export/CORE.h>
#ifdef CGAL_TEST_SUITE
// disabled for the testsuite to avoid `w`
#define CGAL_CORE_warning_msg(X ,Y)
// if (!(X)) CGAL_error_msg(Y)
#else
#define CGAL_CORE_warning_msg(X ,Y) CGAL_warning_msg(X ,Y)
#endif
#endif // _CORE_CONFIG_H_

View File

@ -156,12 +156,6 @@ CGAL_CORE_EXPORT double IntMantissa(double d);
// (See CORE_PATH/progs/ieee/frexp.cpp for details)
CGAL_CORE_EXPORT int IntExponent(double d);
/// Writes out an error or warning message in the local file CORE_DIAGFILE
/** If last argument (err) is TRUE, then this is considered an error
* (not just warning). In this case, the message is also printed in
* std::cerr, using std::perror().
* */
CGAL_CORE_EXPORT void core_error(std::string msg, std::string file, int lineno, bool err);
/// This is for debugging messages
inline void core_debug(std::string msg){

View File

@ -31,7 +31,6 @@
#include <CGAL/use.h>
#include <CGAL/CORE/CoreAux.h>
#include <CGAL/gmp.h>
namespace CORE {
@ -157,30 +156,5 @@ int IntExponent(double d) {
return e-53;
}
/// core_error is the method to write Core Library warning or error messages
/** Both warnings and errors are written to a file called CORE_DIAGFILE.
* But errors are also written on std::cerr (similar to std::perror()).
* */
// Usage: core_error(message, file_with_error, line_number, err_type)
// where err_type=0 means WARNING, error_type=0 means ERROR
CGAL_INLINE_FUNCTION
void core_error(std::string msg, std::string file, int lineno, bool err) {
std::ofstream outFile(CORE_DIAGFILE, std::ios::app); // open to append
if (!outFile) {
// perror("CORE ERROR: cannot open Core Diagnostics file");
std::cerr << "CORE ERROR: can't open Core Diagnostics file"<<std::endl;
std::exit(1); //Note: do not call abort()
}
outFile << "CORE " << (err? "ERROR" : "WARNING")
<< " (at " << file << ": " << lineno << "): "
<< msg << std::endl;
outFile.close();
if (err) {
std::cerr << (std::string("CORE ERROR") + " (file " + file + ", line "
+ std::to_string(lineno) +"):" + msg + "\n").c_str();
std::exit(1); //Note: do not call abort()
}
}
} //namespace CORE

View File

@ -1,479 +0,0 @@
/****************************************************************************
* Core Library Version 1.7, August 2004
* Copyright (c) 1995-2004 Exact Computation Project
* All rights reserved.
*
* This file is part of CGAL (www.cgal.org).
*
* File: CoreIO.cpp
*
* Written by
* Zilin Du <zilin@cs.nyu.edu>
* Chee Yap <yap@cs.nyu.edu>
*
* WWW URL: https://cs.nyu.edu/exact/
* Email: exact@cs.nyu.edu
*
* $URL$
* $Id$
* SPDX-License-Identifier: LGPL-3.0-or-later
***************************************************************************/
#ifndef _COREIO_IMPL_H_
#define _COREIO_IMPL_H_
#ifdef CGAL_HEADER_ONLY
#define CGAL_INLINE_FUNCTION inline
#else
#define CGAL_INLINE_FUNCTION
#endif
#include <CGAL/CORE/BigFloatRep.h>
#include <CGAL/CORE/BigFloat.h>
#include <CGAL/CORE/BigInt.h>
namespace CORE {
CGAL_INLINE_FUNCTION
void core_io_error_handler(const char *f, const char *m) {
std::cout << "\n error_handler";
std::cout << "::" << f << "::" << m << "\n";
std::cout.flush();
std::abort();
}
CGAL_INLINE_FUNCTION
void core_io_memory_handler(char *t, const char *f, const char *m) {
if (t == nullptr) {
std::cout << "\n memory_handler";
std::cout << "::" << f << "::" << m;
std::cout << "memory exhausted\n";
std::cout.flush();
std::abort();
}
}
// s has size old_size and will be resized to new_size.
CGAL_INLINE_FUNCTION
void allocate (char * &s, int old_size, int new_size) {
if (old_size > new_size)
old_size = new_size;
if (s == nullptr)
old_size = 0;
char *t = new char[new_size];
core_io_memory_handler(t, "CoreIO", "allocate::out of memory error");
int i;
for (i = 0; i < old_size; i++)
t[i] = s[i];
delete[] s;
s = t;
}
// appends c to s at position pos.
// sz is the size of s
CGAL_INLINE_FUNCTION
void append_char (char * &s, int & sz, int pos, char c) {
if (pos > sz)
core_io_error_handler("CoreIO", "append_char::invalid argument");
if (pos == sz) {
allocate(s, sz, 2*sz);
sz *= 2;
}
s[pos] = c;
}
// skip blanks, tabs, line breaks and comment lines
CGAL_INLINE_FUNCTION
int skip_comment_line (std::istream & in) {
char c;
do {
in.get(c);
while ( c == '#' ) {
do {
in.get(c);
} while ( c != '\n' );
in.get(c);
}
} while (c == ' ' || c == '\t' || c == '\n');
if (in.eof())
core_io_error_handler("CoreIO::read_from_file()","unexpected end of file.");
in.putback(c);
return c;
}
// skips '\\' followed by '\n'
CGAL_INLINE_FUNCTION
char skip_backslash_new_line (std::istream & in) {
char c;
in.get(c);
while (c == '\\') {
in.get(c);
if (c == '\n')
in.get(c);
else
core_io_error_handler("CoreIO::operator>>", "\\ must be immediately followed by new line.");
}
return c;
}
CGAL_INLINE_FUNCTION
void read_string(std::istream& in, char* &buffer, int sz) {
char c;
int pos=0;
skip_comment_line(in);
while ( in.get(c) ) {
if ( c == ' ' || c == '\t' || c == '\n' || c == '#')
break;
else
append_char(buffer, sz, pos++, c);
}
append_char(buffer, sz, pos, '\0');
}
CGAL_INLINE_FUNCTION
void read_base_number(std::istream& in, BigInt& m, long length, long maxBits) {
char *buffer;
int size, offset;
int base;
bool is_negate;
char c;
int pos = 0;
skip_comment_line(in);
// read sign
in.get(c);
if (c == '-') {
is_negate = true;
in.get(c);
} else
is_negate = false;
// read base and compute digits
if (c == '0') {
in.get(c);
if (c == 'b') {
base = 2;
size = (maxBits == 0 || maxBits > length) ? length : maxBits;
offset = length - size;
} else if (c == 'x') {
base = 16;
size = (maxBits == 0) ? length : (maxBits+3) >> 2;
size = (size > length) ? length : size;
offset = (length - size) << 2;
} else {
base = 8;
size = (maxBits == 0) ? length : (maxBits+2) / 3;
size = (size > length) ? length : size;
offset = (length - size) * 3;
in.putback(c);
}
} else {
base = 10;
size = (maxBits == 0) ? length : (int)std::ceil(maxBits*std::log(2.0)/std::log(10.0));
size = (size > length) ? length : size;
offset = length - size;
in.putback(c);
}
buffer = new char[size+2];
// read digits
for (int i=0; i<size; i++) {
c=skip_backslash_new_line(in);
if(in.eof()){
break;
}
if (c != ' ' && c != '\t' && c != '\n')
append_char(buffer, size, pos++, c);
}
if (base == 10) {
for(int j=0; j<offset; j++)
append_char(buffer, size, pos++, '0');
}
append_char(buffer, size, pos, '\0');
// convert string to bigint.
if (m.set_str(buffer, base) < 0)
core_io_error_handler("CoreIO::read_from_file()","bad big number format.");
delete[] buffer;
// shift left if necessary
if (offset > 0 && base != 10) {
m <<= offset;
}
if (is_negate)
negate(m);
}
CGAL_INLINE_FUNCTION
void write_base_number(std::ostream& out, char* buffer, std::size_t length, int base, int charsPerLine) {
// write big number in a format that gmp's mpz_set_str() can
// automatically recognize with argument base = 0.
if (base == 2)
out << "0b";
else if (base == 16)
out << "0x";
else if (base == 8)
out << '0';
// write big number in charsPerLine.
char* start, *end, c;
for (std::size_t i=0; i<length; i += charsPerLine) {
start = buffer + i;
if (i + charsPerLine >= length)
out << start;
else {
end = start + charsPerLine;
c = *end;
*end = '\0';
out << start << "\\\n";
*end = c;
}
}
}
CGAL_INLINE_FUNCTION
void readFromFile(BigInt& z, std::istream& in, long maxLength) {
char *buffer;
long length;
// check type name whether it is Integer or not.
buffer = new char[8];
read_string(in, buffer, sizeof(buffer));
if ( std::strcmp(buffer, "Integer") != 0)
core_io_error_handler("BigInt::read_from_file()","type name expected.");
delete[] buffer;
// read the bit length field.
buffer = new char[100];
read_string(in, buffer, sizeof(buffer));
length = std::atol(buffer);
delete[] buffer;
// read bigint
read_base_number(in, z, length, maxLength);
}
CGAL_INLINE_FUNCTION
void writeToFile(const BigInt& z, std::ostream& out, int base, int charsPerLine) {
BigInt c = abs(z);
// get the absolute value string
char* buffer = new char[mpz_sizeinbase(c.get_mp(), base) + 2];
mpz_get_str(buffer, base, c.get_mp());
std::size_t length = std::strlen(buffer);
// write type name of big number and length
//out << "# This is an experimental big number format.\n";
out << "Integer " << length << "\n";
// if bigint is negative, then write an sign '-'.
if ( sign(z) < 0 )
out << '-';
write_base_number(out, buffer, length, base, charsPerLine);
out << "\n";
delete[] buffer;
}
CGAL_INLINE_FUNCTION
void readFromFile(BigFloat& bf, std::istream& in, long maxLength) {
char *buffer;
long length;
long exponent;
BigInt mantissa;
// check type name whether it is Float
buffer = new char[6];
read_string(in, buffer, sizeof(buffer));
if (std::strcmp(buffer, "Float") != 0)
core_io_error_handler("BigFloat::read_from_file()", "type name expected");
delete[] buffer;
// read base (default is 16384)
buffer = new char[8];
read_string(in, buffer, sizeof(buffer));
if (std::strcmp(buffer, "(16384)") != 0)
core_io_error_handler("BigFloat::read_from_file()", "base expected");
delete[] buffer;
// read the bit length field.
buffer = new char[100];
read_string(in, buffer, sizeof(buffer));
length = std::atol(buffer);
delete[] buffer;
// read exponent
buffer = new char[100];
read_string(in, buffer, sizeof(buffer));
exponent = std::atol(buffer);
delete[] buffer;
// read mantissa
read_base_number(in, mantissa, length, maxLength);
// construct BigFloat
bf = BigFloat(mantissa, 0, exponent);
}
CGAL_INLINE_FUNCTION
void writeToFile(const BigFloat& bf, std::ostream& out, int base, int charsPerLine) {
BigInt c(CORE::abs(bf.m()));
// get the absolute value string
char* buffer = new char[mpz_sizeinbase(c.get_mp(), base) + 2];
mpz_get_str(buffer, base, c.get_mp());
std::size_t length = std::strlen(buffer);
// write type name, base, length
//out << "# This is an experimental Big Float format." << std::endl;
out << "Float (16384) " << length << std::endl;
// write exponent
out << bf.exp() << std::endl;
// write mantissa
if ( CORE::sign(bf.m()) < 0 )
out << '-';
write_base_number(out, buffer, length, base, charsPerLine);
out << '\n';
delete[] buffer;
}
/* Underconstruction ----
void BigFloat::read_from_file2(std::istream& in, long maxLength) {
long length = 1024;
char *buffer;
// check type name whether it is Float
buffer = new char[7];
BigInt::read_string(in, buffer, sizeof(buffer));
if (strcmp(buffer, "NFloat") != 0)
core_io_error_handler("BigFloat::read_from_file2()", "type name expected");
delete[] buffer;
// read base (default is 16)
buffer = new char[5];
BigInt::read_string(in, buffer, sizeof(buffer));
if (strcmp(buffer, "(16)") != 0)
core_io_error_handler("BigFloat::read_from_file2()", "base expected");
delete[] buffer;
// read length field
buffer = new char[100];
BigInt::read_string(in, buffer, sizeof(buffer));
// get the length field if it is not null.
if (buffer[0] != '\0') {
length = atol(buffer);
if (maxLength > 0 && length >= maxLength)
length = maxLength;
}
delete[] buffer;
// read exponent
buffer = new char[100];
BigInt::read_string(in, buffer, sizeof(buffer));
long exp16 = atol(buffer);
delete[] buffer;
// read mantissa
buffer = new char[length+2];
//BigInt::read_base_number(in, buffer, length);
BigInt m16(buffer);
delete[] buffer;
// convert to base CHUNK_BIT
exp16 = exp16 - length + 1;
if ( m16.is_negative() )
exp16 ++;
long tmp_exp = exp16 * 4;
long q = tmp_exp / CHUNK_BIT;
long r = tmp_exp % CHUNK_BIT;
if ( r < 0 ) {
r += CHUNK_BIT;
q --;
}
BigInt mantissa = m16 << r;
long exponent = q;
// construct BigFloat
if (--rep->refCount == 0)
delete rep;
rep = new BigFloatRep(mantissa, 0, exponent);
rep->refCount++;
}
// write normal float
// now it assumed to write in hex base, i.e. B=2^4=16
// (note: our default base B=2^(CHUNK_BIT)=2^14=16384
void BigFloat::write_to_file2(std::ostream& out, int base, int charsPerLine) {
// convert to base 16.
long new_base = 4; // 2^4 = 16
long tmp_exp = (rep->exp) * CHUNK_BIT;
long q = tmp_exp / new_base;
long r = tmp_exp % new_base;
std::cout << "CORE_DEBUG: q=" << q << ", r=" << r << std::endl;
if ( r < 0 ) {
r += new_base;
q--;
}
std::cout << "CORE_DEBUG: q=" << q << ", r=" << r << std::endl;
BigInt m16 = (rep->m) << r;
int size = mpz_sizeinbase(m16.I, base) + 2;
std::cout << "size=" << size << std::endl;
char* buffer = new char[size];
int length = bigint_to_string(m16, buffer, base);
std::cout << "length=" << length << std::endl;
long exp16 = q + length - 1;
if ( m16.is_negative() )
exp16 --;
// write type name, base, length
out << "# This is an experimental Big Float format." << std::endl;
out << "NFloat (16) " << length << std::endl;
// write exponent
out << exp16 << std::endl;
// write mantissa
if ( m16.is_negative() ) {
out << '-';
buffer ++;
}
BigInt::write_base_number(out, buffer, length, base, charsPerLine);
out << '\n';
delete[] buffer;
}
*/
} //namespace CORE
#endif // _COREIO_IMPL_H_

View File

@ -72,9 +72,7 @@ public:
Expr(float f) : RCExpr(nullptr) { // check for valid numbers
// (i.e., not infinite and not NaN)
if (! CGAL_CORE_finite(f)) {
core_error(" ERROR : constructed an invalid float! ", __FILE__, __LINE__, false);
if (get_static_AbortFlag())
abort();
CGAL_error_msg("ERROR : constructed an invalid float! ");
get_static_InvalidFlag() = -1;
}
rep = new ConstDoubleRep(f);
@ -83,9 +81,7 @@ public:
Expr(double d) : RCExpr(nullptr) { // check for valid numbers
// (i.e., not infinite and not NaN)
if (! CGAL_CORE_finite(d)) {
core_error(" ERROR : constructed an invalid double! ", __FILE__, __LINE__, false);
if (get_static_AbortFlag())
abort();
CGAL_error_msg("ERROR : constructed an invalid double! ");
get_static_InvalidFlag() = -2;
}
rep = new ConstDoubleRep(d);
@ -95,6 +91,14 @@ public:
Expr(const BigInt& I) : RCExpr(new ConstRealRep(Real(I))) {}
/// constructor for <tt>BigRat</tt>
Expr(const BigRat& R) : RCExpr(new ConstRealRep(Real(R))) {}
/// constructor from expression template
template <class TmplExpr,
class = std::enable_if_t<
boost::multiprecision::is_number_expression<TmplExpr>::value> >
Expr(const TmplExpr& R)
: RCExpr(new ConstRealRep(Real(
std::conditional_t<boost::multiprecision::number_category<TmplExpr>::value == boost::multiprecision::number_kind_integer,
BigInt, BigRat>(R)))) {}
/// constructor for <tt>BigFloat</tt>
Expr(const BigFloat& F) : RCExpr(new ConstRealRep(Real(F))) {}
@ -173,9 +177,7 @@ public:
/// /= operator
Expr& operator/=(const Expr& e) {
if ((e.rep)->getSign() == 0) {
core_error(" ERROR : division by zero ! ",__FILE__, __LINE__, false);
if (get_static_AbortFlag())
abort();
CGAL_error_msg("ERROR : division by zero ! ");
get_static_InvalidFlag() = -3;
}
*this = new DivRep(rep, e.rep);
@ -376,9 +378,7 @@ inline Expr operator*(const Expr& e1, const Expr& e2) {
/// division
inline Expr operator/(const Expr& e1, const Expr& e2) {
if (e2.sign() == 0) {
core_error(" ERROR : division by zero ! ", __FILE__, __LINE__, false);
if (get_static_AbortFlag())
abort();
CGAL_error_msg("ERROR : division by zero ! ");
get_static_InvalidFlag() = -4;
}
return Expr(new DivRep(e1.Rep(), e2.Rep()));
@ -479,9 +479,7 @@ inline bool isDivisible(const Expr& e1, const Expr& e2) {
/// square root
inline Expr sqrt(const Expr& e) {
if (e.sign() < 0) {
core_error(" ERROR : sqrt of negative value ! ", __FILE__, __LINE__, false);
if (get_static_AbortFlag())
abort();
CGAL_error_msg("ERROR : sqrt of negative value ! ");
get_static_InvalidFlag() = -5;
}
return Expr(new SqrtRep(e.Rep()));

View File

@ -564,9 +564,7 @@ public:
I = ss.isolateRoot(n);
// check whether n-th root exists
if (I.first == 1 && I.second == 0) {
core_error("CORE ERROR! root index out of bound",
__FILE__, __LINE__, true);
abort();
CGAL_error_msg("CORE ERROR! root index out of bound");
}
// test if the root isolated in I is 0:
if ((I.first == 0)&&(I.second == 0))
@ -583,9 +581,7 @@ public:
ss.isolateRoots(I.first, I.second, v);
I = v.front();
if (v.size() != 1) {
core_error("CORE ERROR! non-isolating interval",
__FILE__, __LINE__, true);
abort();
CGAL_error_msg("CORE ERROR! non-isolating interval");
}
ffVal = computeFilteredValue(); // Chee: this line seems unnecessary
}
@ -1092,8 +1088,7 @@ void AddSubRep<Operator>::computeExactFlags() {
uMSB() = newValue.uMSB(); // chen: to get tighers value.
sign() = newValue.sign();
} else if (lowBound.isInfty()) {//check if rootbound is too big
core_error("AddSubRep:root bound has exceeded the maximum size\n \
but we still cannot decide zero.\n", __FILE__, __LINE__, false);
CGAL_CORE_warning_msg(false, "AddSubRep:root bound has exceeded the maximum size but we still cannot decide zero.");
} else { // Op(first, second) == 0
lMSB() = CORE_negInfty;
sign() = 0;
@ -1186,8 +1181,7 @@ void AddSubRep<Operator>::computeExactFlags() {
//8/9/01, Chee: implement escape precision here:
if (i> get_static_EscapePrec()) {
get_static_EscapePrecFlag() = -i.asLong();//negative means EscapePrec is used
core_error("Escape precision triggered at",
__FILE__, __LINE__, false);
CGAL_CORE_warning_msg(false, "Escape precision triggered");
if (get_static_EscapePrecWarning())
std::cout<< "Escape Precision triggered at "
<< get_static_EscapePrec() << " bits" << std::endl;
@ -1204,8 +1198,7 @@ void AddSubRep<Operator>::computeExactFlags() {
#endif
if (sign() == 0 && ua .isInfty()) {
core_error("AddSubRep: root bound has exceeded the maximum size\n \
but we still cannot decide zero.\n", __FILE__, __LINE__, true);
CGAL_error_msg("AddSubRep: root bound has exceeded the maximum size but we still cannot decide zero.");
} // if (sign == 0 && ua .isInfty())
}// else do progressive
}
@ -1236,8 +1229,7 @@ void AddSubRep<Operator>::computeApproxValue(const extLong& relPrec,
{
std::ostringstream oss;
oss << "CORE WARNING: a huge lMSB in AddSubRep: " << lMSB();
core_error(oss.str(),
__FILE__, __LINE__, false);
CGAL_CORE_warning_msg(false, oss.str().c_str());
}
extLong rf = first->uMSB()-lMSB()+relPrec+EXTLONG_FOUR; // 2 better

View File

@ -702,7 +702,7 @@ void computeExactFlags_temp(ConstRep* t, const Real &value) {
} else {
t->uMSB() = value.uMSB();
t->lMSB() = value.lMSB();
core_error("Leaves in DAG is not exact!", __FILE__, __LINE__, true);
CGAL_error_msg("Leafs in DAG is not exact!");
}
t->sign() = value.sign();
@ -809,8 +809,7 @@ void SqrtRep::computeExactFlags() {
sign() = child->sign();
if (sign() < 0)
core_error("squareroot is called with negative operand.",
__FILE__, __LINE__, true);
CGAL_error_msg("square root is called with negative operand.");
uMSB() = child->uMSB() / EXTLONG_TWO;
lMSB() = child->lMSB() / EXTLONG_TWO;
@ -928,7 +927,7 @@ void DivRep::computeExactFlags() {
second->computeExactFlags();
if (!second->sign())
core_error("zero divisor.", __FILE__, __LINE__, true);
CGAL_error_msg("zero divisor.");
if (!first->sign()) {// value must be exactly zero.
reduceToZero();
@ -1025,8 +1024,7 @@ void MultRep::computeApproxValue(const extLong& relPrec,
{
std::ostringstream oss;
oss << "CORE WARNING: a huge lMSB in AddSubRep " << lMSB();
core_error(oss.str(),
__FILE__, __LINE__, false);
CGAL_CORE_warning_msg(false, oss.str().c_str());
}
extLong r = relPrec + EXTLONG_FOUR;
@ -1048,8 +1046,7 @@ void DivRep::computeApproxValue(const extLong& relPrec,
{
std::ostringstream oss;
oss << "CORE WARNING: a huge lMSB in AddSubRep " << lMSB();
core_error(oss.str(),
__FILE__, __LINE__, false);
CGAL_CORE_warning_msg(false, oss.str().c_str());
}
extLong rr = relPrec + EXTLONG_SEVEN; // These rules come from
@ -1082,7 +1079,9 @@ void Expr::debug(int mode, int level, int depthLimit) const {
else if (mode == Expr::TREE_MODE)
rep->debugTree(level, 0, depthLimit);
else
core_error("unknown debugging mode", __FILE__, __LINE__, false);
{
CGAL_CORE_warning_msg(false, "unknown debugging mode");
}
std::cout << "---- End Expr debug(): " << std::endl;
}
@ -1215,8 +1214,6 @@ void BinOpRep::debugTree(int level, int indent, int depthLimit) const {
second->debugTree(level, indent + 2, depthLimit - 1);
}
CORE_MEMORY_IMPL(BigIntRep)
CORE_MEMORY_IMPL(BigRatRep)
CORE_MEMORY_IMPL(ConstDoubleRep)
CORE_MEMORY_IMPL(ConstRealRep)

View File

@ -137,8 +137,8 @@ public:
}
/// division
filteredFp operator/ (const filteredFp& x) const {
if (x.fpVal == 0.0)
core_error("possible zero divisor!", __FILE__, __LINE__, false);
CGAL_CORE_warning_msg(x.fpVal != 0.0, "possible zero divisor!");
double xxx = core_abs(x.fpVal) / x.maxAbs - (x.ind+1)*CORE_EPS + DBL_MIN;
if (xxx > 0) {
double val = fpVal / x.fpVal;
@ -149,8 +149,8 @@ public:
}
/// square root
filteredFp sqrt () const {
if (fpVal < 0.0)
core_error("possible negative sqrt!", __FILE__, __LINE__, false);
CGAL_CORE_warning_msg( !(fpVal < 0.0), "possible negative sqrt!");
if (fpVal > 0.0) {
double val = std::sqrt(fpVal);
return filteredFp(val, ( maxAbs / fpVal ) * val, 1 + ind);

View File

@ -1,37 +0,0 @@
/****************************************************************************
* Core Library Version 1.7, August 2004
* Copyright (c) 1995-2004 Exact Computation Project
* All rights reserved.
*
* This file is part of CGAL (www.cgal.org).
*
* $URL$
* $Id$
* SPDX-License-Identifier: LGPL-3.0-or-later
***************************************************************************/
// CORE LIBRARY FILE
#ifndef _CORE_GMP_H_
#define _CORE_GMP_H_
#include <CGAL/CORE/Impl.h>
#include <gmp.h>
namespace CORE {
CGAL_CORE_EXPORT std::ostream& io_write (std::ostream &, mpz_srcptr);
CGAL_CORE_EXPORT std::ostream& io_write (std::ostream &, mpq_srcptr);
CGAL_CORE_EXPORT std::istream& io_read (std::istream &, mpz_ptr);
CGAL_CORE_EXPORT std::istream& io_read (std::istream &, mpq_ptr);
//std::ostream& operator<< (std::ostream &, mpz_srcptr);
//std::ostream& operator<< (std::ostream &, mpq_srcptr);
//std::istream& operator>> (std::istream &, mpz_ptr);
//std::istream& operator>> (std::istream &, mpq_ptr);
} //namespace CORE
#ifdef CGAL_HEADER_ONLY
#include <CGAL/CORE/Gmp_impl.h>
#endif // CGAL_HEADER_ONLY
#endif // _CORE_GMP_H_

View File

@ -1,265 +0,0 @@
/****************************************************************************
* Core Library Version 1.7, August 2004
* Copyright (c) 1995-2004 Exact Computation Project
* All rights reserved.
*
* file: GmpIO.cpp
* Adapted from multi-files under /cxx in GMP's source distribution
*
* Zilin Du, 2003
*
* $URL$
* $Id$
* SPDX-License-Identifier: LGPL-3.0-only
***************************************************************************/
/* Auxiliary functions for C++-style input of GMP types.
Copyright 2001 Free Software Foundation, Inc.
This file is part of the GNU MP Library.
*/
#ifdef CGAL_HEADER_ONLY
#define CGAL_INLINE_FUNCTION inline
#else
#define CGAL_INLINE_FUNCTION
#endif
#include <CGAL/CORE/Gmp.h>
#include <cctype>
#include <iostream>
#include <string>
#include <cstdio>
namespace CORE {
CGAL_INLINE_FUNCTION
int
__gmp_istream_set_base (std::istream &i, char &c, bool &zero, bool &showbase)
{
int base;
using std::ios;
zero = showbase = false;
switch (i.flags() & ios::basefield)
{
case ios::dec:
base = 10;
break;
case ios::hex:
base = 16;
break;
case ios::oct:
base = 8;
break;
default:
showbase = true; // look for initial "0" or "0x" or "0X"
if (c == '0')
{
if (! i.get(c))
c = 0; // reset or we might loop indefinitely
if (c == 'x' || c == 'X')
{
base = 16;
i.get(c);
}
else
{
base = 8;
zero = true; // if no other digit is read, the "0" counts
}
}
else
base = 10;
break;
}
return base;
}
CGAL_INLINE_FUNCTION
void
__gmp_istream_set_digits (std::string &s, std::istream &i, char &c, bool &ok, int base)
{
switch (base)
{
case 10:
while (isdigit(c))
{
ok = true; // at least a valid digit was read
s += c;
if (! i.get(c))
break;
}
break;
case 8:
while (isdigit(c) && c != '8' && c != '9')
{
ok = true; // at least a valid digit was read
s += c;
if (! i.get(c))
break;
}
break;
case 16:
while (isxdigit(c))
{
ok = true; // at least a valid digit was read
s += c;
if (! i.get(c))
break;
}
break;
}
}
CGAL_INLINE_FUNCTION
std::istream &
//operator>> (std::istream &i, mpz_ptr z)
io_read (std::istream &i, mpz_ptr z)
{
using namespace std;
int base;
char c = 0;
std::string s;
bool ok = false, zero, showbase;
i.get(c); // start reading
if (i.flags() & ios::skipws) // skip initial whitespace
while (isspace(c) && i.get(c))
;
if (c == '-' || c == '+') // sign
{
if (c == '-') // mpz_set_str doesn't accept '+'
s = "-";
i.get(c);
}
while (isspace(c) && i.get(c)) // skip whitespace
;
base = __gmp_istream_set_base(i, c, zero, showbase); // select the base
__gmp_istream_set_digits(s, i, c, ok, base); // read the number
if (i.good()) // last character read was non-numeric
i.putback(c);
else if (i.eof() && (ok || zero)) // stopped just before eof
i.clear();
if (ok)
mpz_set_str(z, s.c_str(), base); // extract the number
else if (zero)
mpz_set_ui(z, 0);
else
i.setstate(ios::failbit); // read failed
return i;
}
CGAL_INLINE_FUNCTION
std::istream &
//operator>> (std::istream &i, mpq_ptr q)
io_read (std::istream &i, mpq_ptr q)
{
using namespace std;
int base;
char c = 0;
std::string s;
bool ok = false, zero, showbase;
i.get(c); // start reading
if (i.flags() & ios::skipws) // skip initial whitespace
while (isspace(c) && i.get(c))
;
if (c == '-' || c == '+') // sign
{
if (c == '-')
s = "-";
i.get(c);
}
while (isspace(c) && i.get(c)) // skip whitespace
;
base = __gmp_istream_set_base(i, c, zero, showbase); // select the base
__gmp_istream_set_digits(s, i, c, ok, base); // read the numerator
if (! ok && zero) // the only digit read was "0"
{
base = 10;
s += '0';
ok = true;
}
if (c == '/') // there's a denominator
{
bool zero2 = false;
int base2 = base;
s += '/';
ok = false; // denominator is mandatory
i.get(c);
while (isspace(c) && i.get(c)) // skip whitespace
;
if (showbase) // check base of denominator
base2 = __gmp_istream_set_base(i, c, zero2, showbase);
if (base2 == base || base2 == 10) // read the denominator
__gmp_istream_set_digits(s, i, c, ok, base);
if (! ok && zero2) // the only digit read was "0"
{ // denominator is 0, but that's your business
s += '0';
ok = true;
}
}
if (i.good()) // last character read was non-numeric
i.putback(c);
else if (i.eof() && ok) // stopped just before eof
i.clear();
if (ok)
mpq_set_str(q, s.c_str(), base); // extract the number
else
i.setstate(ios::failbit); // read failed
return i;
}
CGAL_INLINE_FUNCTION
std::ostream&
//operator<< (std::ostream &o, mpz_srcptr z)
io_write (std::ostream &o, mpz_srcptr z)
{
char *str = new char [mpz_sizeinbase(z,10) + 2];
str = mpz_get_str(str, 10, z);
o << str ;
delete[] str;
return o;
}
CGAL_INLINE_FUNCTION
std::ostream&
//operator<< (std::ostream &o, mpq_srcptr q)
io_write (std::ostream &o, mpq_srcptr q)
{
// size according to GMP documentation
char *str = new char [mpz_sizeinbase(mpq_numref(q), 10) +
mpz_sizeinbase (mpq_denref(q), 10) + 3];
str = mpq_get_str(str, 10, q);
o << str ;
delete[] str;
return o;
}
} //namespace CORE

View File

@ -57,7 +57,7 @@ public:
t = t->next;
}
//);
//CGAL_warning_msg(count == nObjects * blocks.size(),
//CGAL_CORE_warning_msg(count == nObjects * blocks.size(),
// "Cannot delete memory as there are cyclic references");
if(count == nObjects * blocks.size()){

View File

@ -26,10 +26,12 @@
* SPDX-License-Identifier: LGPL-3.0-or-later
***************************************************************************/
#ifndef __PROMOTE_H__
#define __PROMOTE_H__
#ifndef _CORE_PROMOTE_H__
#define _CORE_PROMOTE_H__
#include <CGAL/CORE/Impl.h>
#include <CGAL/CORE/BigInt.h>
#include <CGAL/CORE/BigRat.h>
namespace CORE {
@ -67,10 +69,10 @@ class Promotion<T, T> {
typedef T ResultT;
};
#define MAX_TYPE(T1, T2) \
#define CORE_MAX_TYPE(T1, T2) \
typename Promotion<T1, T2>::ResultT
#define DEFINE_MAX_TYPE(T1, T2, Tr) \
#define CORE_DEFINE_MAX_TYPE(T1, T2, Tr) \
template<> class Promotion<T1, T2> { \
public: \
typedef Tr ResultT; \
@ -83,15 +85,15 @@ class Promotion<T, T> {
/*
* For example:
*
* DEFINE_MAX_TYPE(BigInt, BigRat, BigRat) // define the promotion
* CORE_DEFINE_MAX_TYPE(BigInt, BigRat, BigRat) // define the promotion
*
* template<typename T1, typename T2> // define function f with type templates
* MAX_TYPE(T1, T2) f(T1& , T2& );
* CORE_MAX_TYPE(T1, T2) f(T1& , T2& );
*
* or
*
* template<typename T1, typename T2> // define function f with type templates
* const MAX_TYPE(T1, T2)& f(T1& , T2& );
* const CORE_MAX_TYPE(T1, T2)& f(T1& , T2& );
*
* BigInt a = 1;
* BigRat b = "1/3";
@ -119,30 +121,30 @@ class Promotion<T, T> {
*
*/
class BigInt;
//class BigInt;
class BigFloat;
class BigRat;
//class BigRat;
class Expr;
DEFINE_MAX_TYPE(long, BigInt, BigInt)
DEFINE_MAX_TYPE(long, BigFloat, BigFloat)
DEFINE_MAX_TYPE(long, BigRat, BigRat)
DEFINE_MAX_TYPE(long, Expr, Expr)
CORE_DEFINE_MAX_TYPE(long, BigInt, BigInt)
CORE_DEFINE_MAX_TYPE(long, BigFloat, BigFloat)
CORE_DEFINE_MAX_TYPE(long, BigRat, BigRat)
CORE_DEFINE_MAX_TYPE(long, Expr, Expr)
DEFINE_MAX_TYPE(int, BigInt, BigInt)
DEFINE_MAX_TYPE(int, BigFloat, BigFloat)
DEFINE_MAX_TYPE(int, BigRat, BigRat)
DEFINE_MAX_TYPE(int, Expr, Expr)
CORE_DEFINE_MAX_TYPE(int, BigInt, BigInt)
CORE_DEFINE_MAX_TYPE(int, BigFloat, BigFloat)
CORE_DEFINE_MAX_TYPE(int, BigRat, BigRat)
CORE_DEFINE_MAX_TYPE(int, Expr, Expr)
DEFINE_MAX_TYPE(BigInt, BigFloat, BigFloat)
DEFINE_MAX_TYPE(BigInt, BigRat, BigRat)
DEFINE_MAX_TYPE(BigInt, Expr, Expr)
CORE_DEFINE_MAX_TYPE(BigInt, BigFloat, BigFloat)
CORE_DEFINE_MAX_TYPE(BigInt, BigRat, BigRat)
CORE_DEFINE_MAX_TYPE(BigInt, Expr, Expr)
DEFINE_MAX_TYPE(BigFloat, BigRat, BigRat)
DEFINE_MAX_TYPE(BigFloat, Expr, Expr)
CORE_DEFINE_MAX_TYPE(BigFloat, BigRat, BigRat)
CORE_DEFINE_MAX_TYPE(BigFloat, Expr, Expr)
DEFINE_MAX_TYPE(BigRat, Expr, Expr)
CORE_DEFINE_MAX_TYPE(BigRat, Expr, Expr)
} //namespace CORE
#endif //__PROMOTE_H__
#endif //_CORE_PROMOTE_H__

View File

@ -277,12 +277,12 @@ const long halfLongMin = LONG_MIN /2;
struct _real_add {
template <class T>
static Real eval(const T& a, const T& b) {
return a+b;
return T(a+b);
}
// specialized for two long values
static Real eval(long a, long b) {
if ((a > halfLongMax && b > halfLongMax) || (a < halfLongMin && b < halfLongMin))
return BigInt(a)+BigInt(b);
return BigInt(BigInt(a)+ BigInt(b));
else
return a+b;
}
@ -291,12 +291,12 @@ struct _real_add {
struct _real_sub {
template <class T>
static Real eval(const T& a, const T& b) {
return a-b;
return T(a-b);
}
// specialized for two long values
static Real eval(long a, long b) {
if ((a > halfLongMax && b < halfLongMin) || (a < halfLongMin && b > halfLongMax))
return BigInt(a)-BigInt(b);
return BigInt(BigInt(a)-BigInt(b));
else
return a-b;
}
@ -305,12 +305,12 @@ struct _real_sub {
struct _real_mul {
template <class T>
static Real eval(const T& a, const T& b) {
return a*b;
return T(a*b);
}
// specialized for two long values
static Real eval(long a, long b) {
if (flrLg(a) + flrLg(b) >= static_cast<int>(LONG_BIT-2))
return BigInt(a)*BigInt(b);
return BigInt(BigInt(a)*BigInt(b));
else
return a*b;
}
@ -357,7 +357,7 @@ struct real_div {
bf_a.approx(a.BigRatValue(), bf_b.MSB() - bf_b.flrLgErr() + 1, CORE_posInfty);
return bf_a.div(bf_b, r);
} else // both are BigRat
return a.BigRatValue()/b.BigRatValue();
return BigRat(a.BigRatValue() / b.BigRatValue());
} else if (a.ID() == REAL_BIGFLOAT || b.ID() == REAL_BIGFLOAT
|| a.ID() == REAL_DOUBLE || b.ID() == REAL_DOUBLE) {
return a.BigFloatValue().div(b.BigFloatValue(), r);
@ -478,11 +478,11 @@ inline Real sqrt(const Real& x) {
// unary minus operator
template <class T>
inline Real Realbase_for<T>::operator-() const {
return -ker;
return T(- T(ker));
}
template <>
inline Real RealLong::operator-() const {
return ker < -LONG_MAX ? -BigInt(ker) : -ker;
return ker < -LONG_MAX ? BigInt(- BigInt(ker)) : -ker;
}
inline void init_CORE() {

View File

@ -92,10 +92,10 @@ public:
int ID() const;
long longValue() const {
return ker.longValue();
return CORE::longValue(ker);
}
double doubleValue() const {
return ker.doubleValue();
return CORE::doubleValue(ker);
}
BigInt BigIntValue() const {
return BigInt(ker);
@ -231,7 +231,7 @@ inline BigInt RealBigInt::BigIntValue() const {
}
template<>
inline BigInt RealBigRat::BigIntValue() const {
return ker.BigIntValue();
return CORE::BigIntValue(ker);
}
template<>
inline BigInt RealBigFloat::BigIntValue() const {
@ -500,11 +500,11 @@ inline unsigned long RealBigRat::height() const {
// toString()
template<>
inline std::string RealBigInt::toString(long, bool) const {
return ker.get_str();
return ker.convert_to<std::string>();
}
template<>
inline std::string RealBigRat::toString(long, bool) const {
return ker.get_str();
return ker.convert_to<std::string>();
}
template<>
inline std::string RealBigFloat::toString(long prec, bool sci) const {

View File

@ -31,6 +31,9 @@
#include <CGAL/CORE/Impl.h>
#include <CGAL/CORE/CoreAux.h>
#include <limits>
#include <type_traits>
namespace CORE {
#ifndef LONG_MAX
@ -77,6 +80,9 @@ public:
extLong(long);
/// constructor for \c unsigned long
extLong(unsigned long);
/// constructor for \c std::size_t
template<typename T, typename = std::enable_if_t<std::is_same_v<T,std::size_t> && !std::is_same_v<unsigned long, std::size_t>>>
extLong(T s);
//@}
/// \name Arithmetic and assignment operators
@ -149,8 +155,7 @@ const extLong EXTLONG_EIGHT(8);
// private comparison function
inline int extLong::cmp(const extLong& x) const {
if (isNaN() || x.isNaN()) {
core_error("Two extLong NaN's cannot be compared!",
__FILE__, __LINE__, false);
CGAL_CORE_warning_msg(false, "Two extLong NaN's cannot be compared!");
}
return (val == x.val) ? 0 : ((val > x.val) ? 1 : -1);
}
@ -189,6 +194,17 @@ inline extLong::extLong(unsigned long u) {
}
}
template <typename T, typename>
inline extLong::extLong(T u) {
if (u >= (std::numeric_limits<std::size_t>::max)()) {
val = EXTLONG_MAX;
flag = 1;
} else {
val = static_cast<long>(u);
flag = 0;
}
}
// isNaN defaults to false
inline extLong::extLong(bool isNaN) : val(0), flag(0) {
if (isNaN) {

View File

@ -77,7 +77,7 @@ extLong& extLong::operator+= (const extLong& y) {
if (flag == 2 || y.flag == 2 || (flag * y.flag < 0)) {
#ifdef CORE_DEBUG
if (flag * y.flag < 0) //want a message at the first creation of NaN
core_error("extLong NaN Error in addition.", __FILE__, __LINE__, false);
CGAL_CORE_warning_msg(false, "extLong NaN Error in addition.");
#endif
*this = CORE_NaNLong;
@ -96,7 +96,7 @@ extLong& extLong::operator-= (const extLong& y) {
if (flag == 2 || y.flag == 2 || (flag * y.flag > 0)) {
#ifdef CORE_DEBUG
if (flag * y.flag > 0) //want a message at the first creation of NaN
core_error("extLong NaN Error in subtraction.", __FILE__, __LINE__, false);
CGAL_CORE_warning_msg(false, "extLong NaN Error in subtraction.");
#endif
*this = CORE_NaNLong;
@ -131,7 +131,7 @@ extLong& extLong::operator*= (const extLong& y) {
*this = CORE_negInfty;
} else {
#ifdef CORE_DEBUG
core_error("extLong NaN Error in multiplication.",__FILE__,__LINE__,false);
CGAL_CORE_warning_msg(false, "extLong NaN Error in multiplication.");
#endif
*this = CORE_NaNLong;
}
@ -144,9 +144,9 @@ extLong& extLong::operator/= (const extLong& y) {
if (flag==2 || y.flag==2 || ((flag != 0) && (y.flag != 0)) || (y.val == 0)) {
#ifdef CORE_DEBUG
if (y.val == 0)
core_error("extLong NaN Error, Divide by Zero.", __FILE__, __LINE__, false);
CGAL_CORE_warning_msg(false, "extLong NaN Error, Divide by Zero.");
else if ((flag !=0) && (y.flag !=0))
core_error("extLong NaN Error, +/-Inf/Inf.", __FILE__, __LINE__, false);
CGAL_CORE_warning_msg(false, "extLong NaN Error, +/-Inf/Inf.");
#endif
*this = CORE_NaNLong;
@ -180,8 +180,7 @@ extLong extLong::operator- () const {
// you cannot interpret the returned value!
CGAL_INLINE_FUNCTION
int extLong::sign() const {
if (flag == 2)
core_error("NaN Sign can not be determined!", __FILE__, __LINE__, false);
CGAL_CORE_warning_msg(flag != 2, "NaN Sign can not be determined!");
return ((val == 0) ? 0 : ((val > 0) ? 1 : -1));
}

View File

@ -1336,7 +1336,7 @@ cout <<"Number of roots at " << xCurr << " are " << numRoots<<endl;
if (!xCurr.isExact()){
std::ostringstream oss;
oss << "xCurr has error! xCurr=" << xCurr;
core_error(oss.str(), __FILE__, __LINE__, false);
CGAL_CORE_warning_msg(false, oss.str());
}
}//main while loop
@ -1426,4 +1426,3 @@ void showIntervals(char* s, BFVecInterval &vI) {
/*************************************************************************** */
// END
/*************************************************************************** */

View File

@ -48,6 +48,7 @@
#define CORE_POLY_H
#include <CGAL/CORE/BigFloat.h>
#include <CGAL/CORE/BigRat.h>
#include <CGAL/CORE/Promote.h>
#include <vector>
#include <CGAL/assertions.h>
@ -196,12 +197,10 @@ public:
/// In particular, if the value is 0, we return 0.
/// @param oldMSB is any estimate of the negative log of the evaluation
BigFloat evalExactSign(const BigFloat& val, const extLong& oldMSB=54) const;
/// Polynomial evaluation that return the same type as its argument
/// Caution: The type T must be greater or equal to the type NT
/// NOTE: Eventually, we will remove this restriction by
/// introduce MaxType(NT,T) for the return type.
template <class T>
MAX_TYPE(NT, T) eval(const T&) const;
CORE_MAX_TYPE(NT, T) eval(const T&) const;
// Bounds
BigFloat CauchyUpperBound() const; // Cauchy Root Upper Bound

View File

@ -673,7 +673,7 @@ Polynomial<NT> Polynomial<NT>::pseudoRemainder (
int bTrueDegree = tmpB.degree;
C = NT(1); // Initialized to C=1.
if (bTrueDegree == -1) {
core_error("ERROR in Polynomial<NT>::pseudoRemainder :\n -- divide by zero polynomial", __FILE__, __LINE__, false);
CGAL_CORE_warning_msg(false, "ERROR in Polynomial<NT>::pseudoRemainder :\n -- divide by zero polynomial");
return Polynomial(0); // Unit Polynomial (arbitrary!)
}
if (bTrueDegree > degree) {
@ -771,8 +771,8 @@ BigFloat Polynomial<NT>::eval(const BigFloat& f) const { // evaluation
template <class NT>
template <class T>
MAX_TYPE(NT, T) Polynomial<NT>::eval(const T& f) const { // evaluation
typedef MAX_TYPE(NT, T) ResultT;
CORE_MAX_TYPE(NT, T) Polynomial<NT>::eval(const T& f) const { // evaluation
typedef CORE_MAX_TYPE(NT, T) ResultT;
if (degree == -1)
return ResultT(0);
if (degree == 0)
@ -892,10 +892,10 @@ BigFloat Polynomial<NT>::CauchyUpperBound() const {
NT mx = 0;
int deg = getTrueDegree();
for (int i = 0; i < deg; ++i) {
mx = core_max(mx, abs(coeff[i]));
mx = core_max(mx, NT(abs(coeff[i])));
}
Expr e = mx;
e /= Expr(abs(coeff[deg]));
e /= Expr(NT(abs(coeff[deg])));
e.approx(CORE_INFTY, 2);
// get an absolute approximate value with error < 1/4
return (e.BigFloatValue().makeExact() + 2);
@ -922,7 +922,7 @@ BigInt Polynomial<NT>::CauchyBound() const {
/* compute B^{deg} */
if (rhs <= lhs) {
B <<= 1;
rhs *= (BigInt(1)<<deg);
rhs *= BigFloat(BigInt(BigInt(1)<<deg));
} else
break;
}
@ -959,7 +959,7 @@ BigInt Polynomial<NT>::UpperBound() const {
/* compute B^{deg} */
if (rhs <= (std::max)(lhsPos,lhsNeg)) {
B <<= 1;
rhs *= (BigInt(1)<<deg);
rhs *= BigFloat(BigInt(BigInt(1)<<deg));
} else
break;
}
@ -975,9 +975,9 @@ BigFloat Polynomial<NT>::CauchyLowerBound() const {
NT mx = 0;
int deg = getTrueDegree();
for (int i = 1; i <= deg; ++i) {
mx = core_max(mx, abs(coeff[i]));
mx = core_max(mx, NT(abs(coeff[i])));
}
Expr e = Expr(abs(coeff[0]))/ Expr(abs(coeff[0]) + mx);
Expr e = Expr(NT(abs(coeff[0])))/ Expr(NT(NT(abs(coeff[0])) + mx));
e.approx(2, CORE_INFTY);
// get an relative approximate value with error < 1/4
return (e.BigFloatValue().makeExact().div2());
@ -1018,8 +1018,8 @@ BigFloat Polynomial<NT>::height() const {
int deg = getTrueDegree();
NT ht = 0;
for (int i = 0; i< deg; i++)
if (ht < abs(coeff[i]))
ht = abs(coeff[i]);
if (ht < NT(abs(coeff[i])))
ht = NT(abs(coeff[i]));
return BigFloat(ht);
}

View File

@ -607,8 +607,7 @@ public:
if (ff == 0) {
NEWTON_DIV_BY_ZERO = true;
del = 0;
core_error("Zero divisor in Newton Iteration",
__FILE__, __LINE__, false);
CGAL_CORE_warning_msg(false, "Zero divisor in Newton Iteration");
return 0;
}
@ -680,8 +679,7 @@ public:
stepsize++; // heuristic
} while ((del != 0) && ((del.uMSB() >= -prec) && (count >0))) ;
if (count == 0) core_error("newtonIterE: reached count=0",
__FILE__, __LINE__, true);
CGAL_assertion_msg(count != 0, "newtonIterE: reached count=0");
del = BigFloat(core_abs(del.m()), err, del.exp() );
del.makeCeilExact();
return val;

View File

@ -1,2 +1 @@
LGPL (v3)
LGPL (v3 or later)

View File

@ -1,6 +1,7 @@
Algebraic_foundations
Algebraic_kernel_for_circles
Arithmetic_kernel
CGAL_Core
Cartesian_kernel
Circular_kernel_2
Distance_2

View File

@ -1,6 +1,7 @@
Algebraic_foundations
Algebraic_kernel_for_spheres
Arithmetic_kernel
CGAL_Core
Cartesian_kernel
Circular_kernel_3
Distance_2

View File

@ -1,6 +1,7 @@
Algebraic_foundations
Arithmetic_kernel
BGL
CGAL_Core
Cartesian_kernel
Circulator
Combinatorial_map

View File

@ -2,6 +2,7 @@ Algebraic_foundations
Arithmetic_kernel
BGL
Box_intersection_d
CGAL_Core
Cartesian_kernel
Circulator
Convex_decomposition_3

View File

@ -1,6 +1,7 @@
Algebraic_foundations
Arithmetic_kernel
BGL
CGAL_Core
Cartesian_kernel
Circulator
Convex_hull_2

View File

@ -56,7 +56,7 @@ or <A HREF="https://msdn.microsoft.com/en-us/library/1fe2x6kt(v=vs.140).aspx">`h
The \stl comes with the compiler, and as such no installation is required.
\subsection thirdpartyBoost Boost
<b>Version 1.66 or later</b>
<b>Version 1.72 or later</b>
The \boost libraries are a set of portable C++ source libraries.
Most of \boost libraries are header-only, but a few of them need to be compiled or
@ -72,7 +72,7 @@ from <A HREF="https://sourceforge.net/projects/boost/files/boost-binaries/">`htt
As there is no canonical directory for where to find \boost on Windows,
we recommend that you define the environment variable
`BOOST_ROOT` and set it to where you have installed \boost, e.g., `C:\boost\boost_1_69_0`.
`BOOST_ROOT` and set it to where you have installed \boost, e.g., `C:\boost\boost_1_70_0`.
\subsection thirdpartyMPFR GNU Multiple Precision Arithmetic (GMP) and GNU Multiple Precision Floating-Point Reliably (MPFR) Libraries
<b>GMP Version 4.2 or later, MPFR Version 2.2.1 or later</b>

View File

@ -103,8 +103,8 @@ other but never both.
\subsection installation_boost Boost Libraries
\subsubsection inst_boost_1_70_plus Version 1.70 and Later
Starting from \boost 1.70, the cmake config mode can be used for configuring the \boost version
\subsubsection inst_boost_1_72_plus Version 1.72 and Later
Starting from \boost 1.72, the cmake config mode can be used for configuring the \boost version
to use by setting the environment variable `Boost_DIR` to the path containing the file
`BoostConfig.cmake`. For example if you manually installed \boost 1.77 with `--prefix=<path>`,
then you should set `Boost_DIR=<path>/lib/cmake/Boost-1.77.0`.

View File

@ -265,7 +265,7 @@ public:
if (n_ys == 0) return o; // no intersection
// the x coordinate of the solution points
Algebraic xs = m / (2*a_diff);
Algebraic xs = m / (Rational(2)*a_diff);
if (n_ys == 1) {
// intersection is a point
@ -340,7 +340,7 @@ public:
}
if (n_xs == 1) {
// intersection is a point
Point_2 inter_point(xs[0], (-2*a_diff*xs[0] + m)/(2*b_diff) );
Point_2 inter_point(xs[0], (-Rational(2)*a_diff*xs[0] + m)/(Rational(2)*b_diff) );
*o++ = inter_point;
return o;
}
@ -350,8 +350,8 @@ public:
// so we construct a COLLINEAR conic (with equation as in (1))
// with 2 endpoints
Algebraic ys[2];
ys[0] = (-2*a_diff*xs[0] + m)/(2*b_diff);
ys[1] = (-2*a_diff*xs[1] + m)/(2*b_diff);
ys[0] = (-Rational(2)*a_diff*xs[0] + m)/(Rational(2)*b_diff);
ys[1] = (-Rational(2)*a_diff*xs[1] + m)/(Rational(2)*b_diff);
Alg_point_2 end1(xs[0], ys[0]);
Alg_point_2 end2(xs[1], ys[1]);
@ -457,7 +457,7 @@ public:
int envelope_coef = 1;
if (! m_traits.m_is_lower) envelope_coef = -1;
Sign sign_c_diff = CGAL_NTS sign(c_diff);
Rational sign_c_diff = Rational(sign(c_diff));
Rational la = envelope_coef*2*a_diff*sign_c_diff;
Rational lb = envelope_coef*2*b_diff*sign_c_diff;
Rational lc = envelope_coef*sign_c_diff*(2*c_diff*z_plane - m);
@ -977,10 +977,10 @@ public:
const Rational& u = cv.u();
const Rational& v = cv.v();
// const Rational& w = cv.w(); // unused
Algebraic m = -1 * (2*r*x0 + t*y0 + u);
Algebraic n = 2*s*y0 + t*x0 + v;
Algebraic m = -1 * (Rational(2)*r*x0 + t*y0 + u);
Algebraic n = Rational(2)*s*y0 + t*x0 + v;
// line coefficients: A3, B3, C3
Algebraic A3 = -1*m, B3 = n, C3 = m*x0 - n*y0;
Algebraic A3 = -m, B3 = n, C3 = m*x0 - n*y0;
// the tangences of the spheres (in point (x0,y0,z0)):
Algebraic z0 = compute_envelope_z_in_point(cv_point, s1);
@ -1077,8 +1077,8 @@ public:
Algebraic x_diff = x1 - a, y_diff = y1 - b;
// the coefficients are:
Algebraic A = 1;
Algebraic B = -2*c;
Algebraic C = x_diff*x_diff + y_diff*y_diff + c*c - sqr_r;
Algebraic B = -Rational(2)*c;
Algebraic C = x_diff*x_diff + y_diff*y_diff + Algebraic(c*c - sqr_r);
Algebraic zs[2];
Algebraic* zs_end;

View File

@ -2,6 +2,7 @@ Algebraic_foundations
Apollonius_graph_2
Arithmetic_kernel
Arrangement_on_surface_2
CGAL_Core
Cartesian_kernel
Circulator
Distance_2

View File

@ -1,5 +1,6 @@
Algebraic_foundations
Arithmetic_kernel
CGAL_Core
Cartesian_kernel
Distance_2
Distance_3

View File

@ -1,5 +1,6 @@
Algebraic_foundations
Arithmetic_kernel
CGAL_Core
Cartesian_kernel
Circulator
Combinatorial_map

View File

@ -15,6 +15,11 @@ Release date: October 2023
- **Breaking change**: The usage of `boost::optional` has been replaced by `std::optional`. Packages affected are 2D Straight Line Skeleton, 3D Fast Intersection and Distance Computation (AABB Tree), and the Kernel intersection.
- **Breaking change**: The usage of `boost::variant` has been replaced by `std::variant`. Packages affected are 2D Arrangements, and the Kernel intersection.
- **Breaking change**: The file CMake file `UseCGAL.cmake` has been removed from CGAL. Usages of the CMake variables `${CGAL_USE_FILE}` and `${CGAL_LIBRARIES}` must be replaced by a link to the imported target `CGAL::CGAL`, for example: `target_link_library(the_target PRIVATE CGAL::CGAL)`.
- The minimal supported version of Boost is now 1.72.0
### Installation
- The CGAL\_Core library is no longer based on GMP but boost multiprecision now, and can be used with either gmp backend or boost backend.
### [Polygon Repair](https://doc.cgal.org/6.0/Manual/packages.html#PkgPolygonRepair) (new package)

View File

@ -115,6 +115,9 @@ option(CGAL_ENABLE_TESTING "Build the testing tree." ${BUILD_TESTING})
endif()
endif(CGAL_BRANCH_BUILD)
#allow to force disabling boost multiprecision support
option(CGAL_DO_NOT_USE_BOOST_MP "Disable the support of boost multiprecision library" FALSE)
#message(STATUS "Packages found: ${CGAL_CONFIGURED_PACKAGES}")
list(SORT CGAL_CONFIGURED_PACKAGES_NAMES)

View File

@ -17,9 +17,9 @@ set ( CGAL_Boost_Setup TRUE )
include(${CMAKE_CURRENT_LIST_DIR}/CGAL_TweakFindBoost.cmake)
find_package( Boost 1.66 REQUIRED )
find_package( Boost 1.72 REQUIRED )
if(Boost_FOUND AND Boost_VERSION VERSION_LESS 1.70)
if(Boost_FOUND AND Boost_VERSION VERSION_LESS 1.72)
if(DEFINED Boost_DIR AND NOT Boost_DIR)
# Unset that cache variable that is set in the cache by FindBoost
# (while it was searching for boost-cmake).

View File

@ -131,12 +131,6 @@ function(CGAL_setup_CGAL_flags target)
$<$<COMPILE_LANGUAGE:CXX>:/fp:except->
$<$<COMPILE_LANGUAGE:CXX>:/bigobj> # Use /bigobj by default
)
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang")
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0.3)
message(STATUS "Apple Clang version ${CMAKE_CXX_COMPILER_VERSION} compiler detected")
message(STATUS "Boost MP is turned off for all Apple Clang versions below 11.0.3!")
target_compile_options(${target} INTERFACE "-DCGAL_DO_NOT_USE_BOOST_MP")
endif()
elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel")
message( STATUS "Using Intel Compiler. Adding -fp-model strict" )
if(WIN32)
@ -166,4 +160,9 @@ function(CGAL_setup_CGAL_flags target)
target_compile_options(${target} INTERFACE "-mieee" "-mfp-rounding-mode=d" )
endif()
endif()
if (CGAL_DO_NOT_USE_BOOST_MP)
target_compile_options(${target} INTERFACE "-DCGAL_DO_NOT_USE_BOOST_MP")
endif()
endfunction()

View File

@ -18,9 +18,6 @@ endif()
set(CGAL_SetupCGAL_CoreDependencies_included TRUE)
#.rst:
# Used Modules
# ^^^^^^^^^^^^
# - :module:`CGAL_SetupGMP`
#
# Result Variables
# ^^^^^^^^^^^^^^^^
@ -29,13 +26,10 @@ set(CGAL_SetupCGAL_CoreDependencies_included TRUE)
#
# Set to `TRUE` if the dependencies of `CGAL_Core` were found.
if(NOT CGAL_DISABLE_GMP)
include(${CMAKE_CURRENT_LIST_DIR}/CGAL_SetupGMP.cmake)
if(GMP_FOUND)
set(CGAL_Core_FOUND TRUE)
set_property(GLOBAL PROPERTY CGAL_Core_FOUND TRUE)
endif()
endif()
# always found as it requires the minimal version of boost required by CGAL
set(CGAL_Core_FOUND TRUE)
set_property(GLOBAL PROPERTY CGAL_Core_FOUND TRUE)
#.rst:
#
@ -54,8 +48,10 @@ endif()
#
function(CGAL_setup_CGAL_Core_dependencies target)
use_CGAL_GMP_support(CGAL_Core INTERFACE)
find_package( Boost 1.72 REQUIRED )
if (!CGAL_DISABLE_GMP AND GMP_FOUND)
use_CGAL_GMP_support(CGAL_Core INTERFACE)
endif()
target_compile_definitions(${target} INTERFACE CGAL_USE_CORE=1)
target_link_libraries( CGAL_Core INTERFACE CGAL::CGAL )
endfunction()

View File

@ -1,13 +0,0 @@
include(${CMAKE_CURRENT_LIST_DIR}/CGAL_Macros.cmake)
if( (GMP_FOUND AND NOT MPFR_FOUND) OR (NOT GMP_FOUND AND MPFR_FOUND) )
message( FATAL_ERROR "CGAL needs for its full functionality both GMP and MPFR.")
endif()
if( NOT GMP_FOUND )
set(CGAL_NO_CORE ON)
message( STATUS "CGAL_Core needs GMP, cannot be configured.")
endif( NOT GMP_FOUND )
# finally setup Boost
include(${CMAKE_CURRENT_LIST_DIR}/CGAL_SetupBoost.cmake)

View File

@ -35,8 +35,32 @@
# endif // CGAL_USE_MPFR and no <mpfr.h>
#endif // __has_include
#if CGAL_USE_GMP && CGAL_USE_MPFR && ! CGAL_NO_CORE
// It is easier to disable this number type completely for old versions.
// Before 1.63, I/O is broken. Again, disabling the whole file is just the
// easy solution.
// MSVC had trouble with versions <= 1.69:
// https://github.com/boostorg/multiprecision/issues/98
//
// Disable also on Windows 32 bits
// because CGAL/cpp_float.h assumes _BitScanForward64 is available
// See https://learn.microsoft.com/en-us/cpp/intrinsics/bitscanforward-bitscanforward64
//
// Disable also with PowerPC processors, with Boost<1.80 because of that bug:
// https://github.com/boostorg/multiprecision/pull/421
//
#if !defined CGAL_DO_NOT_USE_BOOST_MP && \
(!defined _MSC_VER || BOOST_VERSION >= 107000) && \
(!defined _WIN32 || defined _WIN64) && \
(BOOST_VERSION >= 108000 || (!defined _ARCH_PPC && !defined _ARCH_PPC64))
#define CGAL_USE_BOOST_MP 1
#endif
#if CGAL_USE_BOOST_MP
#if ! CGAL_NO_CORE
# define CGAL_USE_CORE 1
#endif
#endif
#endif // CGAL_INTERNAL_ENABLE_THIRD_PARTY_LIBRARIES_H

View File

@ -127,12 +127,18 @@ if( CGAL_DEV_MODE OR RUNNING_CGAL_AUTO_TEST OR CGAL_TEST_SUITE )
endif()
endif()
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0.3)
message(STATUS "Apple Clang version ${CMAKE_CXX_COMPILER_VERSION} compiler detected")
message(STATUS "Boost MP is turned off for all Apple Clang versions below 11.0.3!")
set(CGAL_DO_NOT_USE_BOOST_MP TRUE)
endif()
foreach(comp ${CGAL_FIND_COMPONENTS})
if(NOT comp MATCHES "Core|ImageIO|Qt6")
message(FATAL_ERROR "The requested CGAL component ${comp} does not exist!")
endif()
if(comp MATCHES "Core" AND CGAL_DISABLE_GMP)
message("CGAL_Core needs GMP and won't be used.")
if(comp MATCHES "Core" AND CGAL_DO_NOT_USE_BOOST_MP)
message(STATUS "CGAL_Core needs Boost multiprecision support and won't be used.")
else()
list(APPEND CGAL_LIBRARIES CGAL_${comp})
endif()

View File

@ -1,165 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.

View File

@ -1,6 +1,7 @@
Algebraic_foundations
Arithmetic_kernel
BGL
CGAL_Core
Cartesian_kernel
Circulator
Combinatorial_map

View File

@ -2,6 +2,7 @@ AABB_tree
Algebraic_foundations
Arithmetic_kernel
BGL
CGAL_Core
CGAL_ImageIO
Cartesian_kernel
Circulator

View File

@ -3,6 +3,7 @@ Algebraic_foundations
Arithmetic_kernel
Arrangement_on_surface_2
Boolean_set_operations_2
CGAL_Core
Cartesian_kernel
Circulator
Convex_hull_2

View File

@ -2,6 +2,7 @@ Algebraic_foundations
Arithmetic_kernel
BGL
Box_intersection_d
CGAL_Core
Cartesian_kernel
Circulator
Convex_decomposition_3

View File

@ -2,6 +2,7 @@ Algebraic_foundations
Arithmetic_kernel
BGL
Box_intersection_d
CGAL_Core
Cartesian_kernel
Circulator
Distance_2

View File

@ -1,5 +1,6 @@
Algebraic_foundations
Arithmetic_kernel
CGAL_Core
Filtered_kernel
Installation
Interval_support

View File

@ -178,13 +178,16 @@ public:
// shift such that err.m()+err.err() fits into long
int digits_long = std::numeric_limits<long>::digits;
if(::CORE::bitLength(err.m()+err.err()) >= digits_long){
long shift = ::CORE::bitLength(err.m()) - digits_long + 1 ;
if(::CORE::bitLength(err.m()+err.err()) >= static_cast<std::size_t>(digits_long)){
assert(std::size_t((std::numeric_limits<long>::max)()) > ::CORE::bitLength(err.m()));
long shift = static_cast<long>(::CORE::bitLength(err.m())) - digits_long + 1;
//std::cout << "shift " << shift<< std::endl;
long new_err = ((err.m()+err.err()) >> shift).longValue()+1;
CORE::BigInt bi = (err.m() + err.err());
bi = bi >> shift;
long new_err = CORE::longValue(bi)+1;
err = CORE::BigFloat(0,new_err,0) * CORE::BigFloat::exp2(err.exp()*CORE::CHUNK_BIT+shift);
}else{
err = CORE::BigFloat(0,err.m().longValue()+err.err(),err.exp());
err = CORE::BigFloat(0, CORE::longValue(err.m())+err.err(),err.exp());
}
//print_bf(err,"new_err");
@ -272,9 +275,10 @@ round(const CORE::BigFloat& x, long rel_prec = CORE::get_static_defRelPrec().toL
// long shift = ::CORE::bitLength(m) - rel_prec - 1;
long shift ;
if (err == 0)
shift = ::CORE::bitLength(m) - rel_prec - 3;
else
if (err == 0) {
assert(std::size_t((std::numeric_limits<long>::max)()) > ::CORE::bitLength(m));
shift = static_cast<long>(::CORE::bitLength(m)) - rel_prec - 3;
}else
shift = CGAL::relative_precision(x) - rel_prec -1;
if( shift > 0 ){
@ -324,7 +328,7 @@ public:
NT w = Width()(x);
w /= ::CORE::BigFloat(x.m()-x.err(),0,x.exp());
w = w.abs();
return -(CORE::ceilLg(w.m()+w.err())+w.exp()*CORE::CHUNK_BIT);
return -(CORE::ceilLg(CORE::BigInt(w.m()+w.err()))+w.exp()*CORE::CHUNK_BIT);
}
};

View File

@ -10,7 +10,6 @@
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
#ifndef CGAL_CORE_BIGINT_H
#define CGAL_CORE_BIGINT_H
@ -24,198 +23,6 @@
#include <CGAL/Residue.h>
#include <CGAL/Modular_traits.h>
namespace CGAL {
//
// Algebraic structure traits
//
template <> class Algebraic_structure_traits< CORE::BigInt >
: public Algebraic_structure_traits_base< CORE::BigInt,
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;
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:
//! computes the largest NT not larger than the square root of \a a.
Type operator()( const Type& x) const {
Type result;
mpz_sqrt(result.get_mp(), x.get_mp());
return result;
}
};
class Gcd
: public CGAL::cpp98::binary_function< Type, Type,
Type > {
public:
Type operator()( const Type& x,
const Type& y) const {
if ( x == Type(0) && y == Type(0) )
return Type(0);
Type result;
mpz_gcd(result.get_mp(), x.get_mp(), y.get_mp());
return result;
}
};
};
//
// Real embeddable traits
//
template <> class Real_embeddable_traits< CORE::BigInt >
: public INTERN_RET::Real_embeddable_traits_base< CORE::BigInt , CGAL::Tag_true > {
public:
class Abs
: public CGAL::cpp98::unary_function< Type, Type > {
public:
Type operator()( const Type& x ) const {
return CORE::abs( x );
}
};
class Sgn
: public CGAL::cpp98::unary_function< Type, ::CGAL::Sign > {
public:
::CGAL::Sign operator()( const Type& x ) const {
return (::CGAL::Sign) CORE::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 CGAL::sign(::CORE::cmp(x,y));
}
};
class To_double
: public CGAL::cpp98::unary_function< Type, double > {
public:
double operator()( const Type& x ) const {
// this call is required to get reasonable values for the double
// approximation
return x.doubleValue();
}
};
class To_interval
: public CGAL::cpp98::unary_function< Type, std::pair< double, double > > {
public:
std::pair<double, double> operator()( const Type& x_ ) const {
CORE::Expr x(x_);
std::pair<double,double> result;
x.doubleInterval(result.first, result.second);
CGAL_expensive_assertion(result.first <= x);
CGAL_expensive_assertion(result.second >= x);
return result;
}
};
};
/*! \ingroup NiX_Modular_traits_spec
* \brief a model of concept ModularTraits,
* specialization of NiX::Modular_traits.
*/
template<>
class Modular_traits< ::CORE::BigInt > {
typedef Residue RES;
public:
typedef ::CORE::BigInt NT;
typedef CGAL::Tag_true Is_modularizable;
typedef Residue Residue_type;
struct Modular_image{
Residue_type operator()(const NT& a){
NT tmp = a % NT(RES::get_current_prime());
// TODO: reactivate this assertion
// it fails with core_v1.6x_20040329
// NiX_assert(tmp.isInt());
int mi(tmp.longValue());
if (mi < 0) mi += RES::get_current_prime();
return Residue_type(mi);
}
};
struct Modular_image_representative{
NT operator()(const Residue_type& x){
return NT(x.get_value());
}
};
};
template<>
struct Needs_parens_as_product<CORE::BigInt>{
bool operator()(const CORE::BigInt& x){
return CGAL_NTS is_negative(x);
}
};
// Benchmark_rep specialization
template<>
class Benchmark_rep< CORE::BigInt > {
const CORE::BigInt& t;
public:
//! initialize with a const reference to \a t.
Benchmark_rep( const CORE::BigInt& tt) : t(tt) {}
//! perform the output, calls \c operator\<\< by default.
std::ostream& operator()( std::ostream& out) const {
out << t;
return out;
}
static std::string get_benchmark_name() {
return "Integer";
}
};
} //namespace CGAL
//since types are included by CORE_coercion_traits.h:
#include <CGAL/CORE_Expr.h>
#include <CGAL/CORE_BigRat.h>
#include <CGAL/CORE_BigFloat.h>
#include <CGAL/CORE_arithmetic_kernel.h>
namespace Eigen {
template<class> struct NumTraits;
template<> struct NumTraits<CORE::BigInt>
{
typedef CORE::BigInt Real;
typedef CORE::BigRat NonInteger;
typedef CORE::BigInt Nested;
typedef CORE::BigInt 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
};
};
}
#include <CGAL/enable_warnings.h>
#endif // CGAL_CORE_BIGINT_H

View File

@ -10,7 +10,6 @@
//
// Author(s) : Michael Hemmer <hemmer@mpi-inf.mpg.de>
#ifndef CGAL_CORE_BIGRAT_H
#define CGAL_CORE_BIGRAT_H
@ -21,237 +20,6 @@
#include <CGAL/CORE_coercion_traits.h>
#include <CGAL/CORE_Expr.h> // used for To_interval-functor
//#if defined(CGAL_CORE_BIGRAT_NUMER_DENOM_ARE_MEMBERS)
// #define CGAL_CORE_NUMERATOR(X) ((X).numerator())
// #define CGAL_CORE_DENOMINATOR(X) ((X).denominator())
//#elif defined(CGAL_CORE_BIGRAT_NUMER_DENOM_ARE_NONMEMBERS)
#define CGAL_CORE_NUMERATOR(X) (numerator((X)))
#define CGAL_CORE_DENOMINATOR(X) (denominator((X)))
//#else
namespace CGAL {
//
// Algebraic structure traits
//
template <> class Algebraic_structure_traits< CORE::BigRat >
: public Algebraic_structure_traits_base< CORE::BigRat,
Field_tag > {
public:
typedef Tag_true Is_exact;
typedef Tag_false Is_numerical_sensitive;
// BigRat are always normalized, so no special simplify-functor is needed
// Nothing new...
};
//
// Real embeddable traits
//
template <> class Real_embeddable_traits< CORE::BigRat >
: public INTERN_RET::Real_embeddable_traits_base< CORE::BigRat , CGAL::Tag_true > {
public:
class Abs
: public CGAL::cpp98::unary_function< Type, Type > {
public:
Type operator()( const Type& x ) const {
return CORE::abs( x );
}
};
class Sgn
: public CGAL::cpp98::unary_function< Type, ::CGAL::Sign > {
public:
::CGAL::Sign operator()( const Type& x ) const {
return (::CGAL::Sign) CORE::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 CGAL::sign( ::CORE::cmp(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 {
// this call is required to get reasonable values for the double
// approximation
return x.doubleValue();
}
};
class To_interval
: public CGAL::cpp98::unary_function< Type, std::pair< double, double > > {
public:
std::pair<double, double> operator()( const Type& x_ ) const {
CORE::Expr x(x_);
std::pair<double,double> result;
x.doubleInterval(result.first, result.second);
CGAL_expensive_assertion(result.first <= x);
CGAL_expensive_assertion(result.second >= x);
return result;
}
};
};
/*! \ingroup NiX_Fraction_traits_spec
* \brief Specialization of Fraction_traits for ::leda::rational
*/
template <>
class Fraction_traits< CORE::BigRat > {
public:
typedef CORE::BigRat Type;
typedef ::CGAL::Tag_true Is_fraction;
typedef CORE::BigInt 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 = CGAL_CORE_NUMERATOR(rat);
den = CGAL_CORE_DENOMINATOR(rat);
}
};
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 ) {
return Type(num, den);
}
};
};
template <class F>
class Output_rep< ::CORE::BigRat, F> : public IO_rep_is_specialized {
const ::CORE::BigRat& t;
public:
//! initialize with a const reference to \a t.
Output_rep( const ::CORE::BigRat& tt) : t(tt) {}
//! perform the output, calls \c operator\<\< by default.
std::ostream& operator()( std::ostream& out) const {
switch (IO::get_mode(out)) {
case IO::PRETTY:{
if(CGAL_CORE_DENOMINATOR(t) == ::CORE::BigRat(1))
return out <<CGAL_CORE_NUMERATOR(t);
else
return out << CGAL_CORE_NUMERATOR(t)
<< "/"
<< CGAL_CORE_DENOMINATOR(t);
//break; // unreachable
}
default:
return out << CGAL_CORE_NUMERATOR(t)
<< "/"
<< CGAL_CORE_DENOMINATOR(t);
}
}
};
template <>
struct Needs_parens_as_product< ::CORE::BigRat >{
bool operator()( ::CORE::BigRat t){
if (CGAL_CORE_DENOMINATOR(t) != 1 )
return true;
else
return needs_parens_as_product(CGAL_CORE_NUMERATOR(t)) ;
}
};
template <>
class Output_rep< ::CORE::BigRat, Parens_as_product_tag >
: public IO_rep_is_specialized
{
const ::CORE::BigRat& t;
public:
// Constructor
Output_rep( const ::CORE::BigRat& tt) : t(tt) {}
// operator
std::ostream& operator()( std::ostream& out) const {
Needs_parens_as_product< ::CORE::BigRat > needs_parens_as_product;
if (needs_parens_as_product(t))
return out <<"("<< IO::oformat(t) <<")";
else
return out << IO::oformat(t);
}
};
// Benchmark_rep specialization
template<>
class Benchmark_rep< CORE::BigRat > {
const CORE::BigRat& t;
public:
//! initialize with a const reference to \a t.
Benchmark_rep( const CORE::BigRat& tt) : t(tt) {}
//! perform the output, calls \c operator\<\< by default.
std::ostream& operator()( std::ostream& out) const {
out << "Rational(" << numerator(t) << "," << denominator(t) << ")";
return out;
}
static std::string get_benchmark_name() {
return "Rational";
}
};
} //namespace CGAL
//since types are included by CORE_coercion_traits.h:
#include <CGAL/CORE_Expr.h>
#include <CGAL/CORE_BigInt.h>
#include <CGAL/CORE_BigFloat.h>
#include <CGAL/CORE_arithmetic_kernel.h>
namespace Eigen {
template<class> struct NumTraits;
template<> struct NumTraits<CORE::BigRat>
{
typedef CORE::BigRat Real;
typedef CORE::BigRat NonInteger;
typedef CORE::BigRat Nested;
typedef CORE::BigRat Literal;
static inline Real epsilon() { return 0; }
static inline Real dummy_precision() { return 0; }
enum {
IsInteger = 0,
IsSigned = 1,
IsComplex = 0,
RequireInitialization = 1,
ReadCost = 6,
AddCost = 150,
MulCost = 100
};
};
}
#include <CGAL/enable_warnings.h>
#endif // CGAL_CORE_BIGRAT_H

View File

@ -24,29 +24,11 @@
#include <CGAL/CORE/CORE.h>
//#include <NiX/Coercion_traits.h>
namespace CGAL {
//CORE internal coercions:
// The following definitions reflect the interaction of the CORE number types
// with the built in types,
// CORE BigInt:
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(short ,::CORE::BigInt)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(int ,::CORE::BigInt)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(long ,::CORE::BigInt)
// CORE BigRat:
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(short ,::CORE::BigRat)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(int ,::CORE::BigRat)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(long ,::CORE::BigRat)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(float ,::CORE::BigRat)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(double ,::CORE::BigRat)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(::CORE::BigInt,::CORE::BigRat)
// CORE Expr:
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(short ,::CORE::Expr)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(int ,::CORE::Expr)
@ -75,12 +57,14 @@ struct Coercion_traits<CORE::BigFloat , ::CORE::BigInt>{
typedef Type result_type;
Type operator()(const CORE::BigFloat& x) const { return x;}
Type operator()(const ::CORE::BigInt x) const {
CORE::BigFloat result;
result.approx(x,CORE::get_static_defRelPrec().toLong(),LONG_MAX);
// Do not use MakeFloorExact as it changes the Bigfloat
CGAL_postcondition( ::CORE::BigRat(::CORE::BigFloat(result.m()-result.err(),0,result.exp())) <= x );
CGAL_postcondition( ::CORE::BigRat(::CORE::BigFloat(result.m()+result.err(),0,result.exp())) >= x );
return result;
CORE::BigFloat result;
result.approx(x,CORE::get_static_defRelPrec().toLong(),LONG_MAX);
// Do not use MakeFloorExact as it changes the Bigfloat
CGAL_postcondition_code(::CORE::BigRat r = ::CORE::BigFloat(result.m()-result.err(),0,result.exp()));
CGAL_postcondition( r <= x );
CGAL_postcondition_code(::CORE::BigRat r2 = ::CORE::BigFloat(result.m()+result.err(),0,result.exp()));
CGAL_postcondition( r2 >= x );
return result;
}
};
};
@ -95,12 +79,13 @@ struct Coercion_traits<CORE::BigFloat , ::CORE::BigRat>{
typedef Type result_type;
Type operator()(const CORE::BigFloat& x) const { return x;}
Type operator()(const ::CORE::BigRat x) const {
CORE::BigFloat result(x,CORE::get_static_defRelPrec().toLong(),LONG_MAX);
// Do not use MakeFloorExact as it changes the Bigfloat
CGAL_postcondition( ::CORE::BigRat(::CORE::BigFloat(result.m()-result.err(),0,result.exp())) <= x );
CGAL_postcondition( ::CORE::BigRat(::CORE::BigFloat(result.m()+result.err(),0,result.exp())) >= x );
return result;
// Do not use MakeFloorExact as it changes the Bigfloat
CGAL_postcondition_code(::CORE::BigRat r = ::CORE::BigFloat(result.m()-result.err(),0,result.exp()));
CGAL_postcondition( r <= x );
CGAL_postcondition_code(::CORE::BigRat r2 = ::CORE::BigFloat(result.m()+result.err(),0,result.exp()));
CGAL_postcondition( r2 >= x );
return result;
}
};
};
@ -115,11 +100,13 @@ struct Coercion_traits<CORE::BigFloat , ::CORE::Expr>{
typedef Type result_type;
Type operator()(const CORE::BigFloat& x) const { return x;}
Type operator()(const ::CORE::Expr x) const {
CORE::BigFloat result(x, CORE::get_static_defRelPrec().toLong(),LONG_MAX);
// Do not use MakeFloorExact as it changes the Bigfloat
CGAL_postcondition( ::CORE::BigRat(::CORE::BigFloat(result.m()-result.err(),0,result.exp())) <= x );
CGAL_postcondition( ::CORE::BigRat(::CORE::BigFloat(result.m()+result.err(),0,result.exp())) >= x );
return result;
CORE::BigFloat result(x, CORE::get_static_defRelPrec().toLong(),LONG_MAX);
// Do not use MakeFloorExact as it changes the Bigfloat
CGAL_postcondition_code(::CORE::BigRat r = ::CORE::BigFloat(result.m()-result.err(),0,result.exp()));
CGAL_postcondition( r <= x );
CGAL_postcondition_code(::CORE::BigRat r2 = ::CORE::BigFloat(result.m()+result.err(),0,result.exp()));
CGAL_postcondition( r2 >= x );
return result;
}
};
};
@ -150,6 +137,8 @@ template <> struct Coercion_traits< ::CORE::Expr, CORE::BigFloat >
} //namespace CGAL
#endif // CGAL_USE_CORE
#endif //CGAL_CORE_COERCION_TRAITS_H 1
//EOF

View File

@ -121,8 +121,12 @@ class Counted_number {
Counted_number() {}
//explicit Counted_number(int n) :m_rep(n){}
explicit Counted_number(NT n) :m_rep(n){}
Counted_number operator-() const
{inc_neg_count();return Counted_number(-m_rep);}
{
inc_neg_count(); NT neg = -m_rep; return Counted_number(neg);
}
Counted_number const & operator+=(Counted_number const &n)
{
inc_add_count();
@ -352,7 +356,7 @@ Counted_number<NT>
operator+(Counted_number<NT> const &n1, Counted_number<NT> const &n2)
{
Counted_number<NT>::inc_add_count();
return Counted_number<NT>(n1.rep() + n2.rep());
return Counted_number<NT>(NT(n1.rep() + n2.rep()));
}
template <class NT>
@ -360,7 +364,7 @@ Counted_number<NT>
operator-(Counted_number<NT> const &n1, Counted_number<NT> const &n2)
{
Counted_number<NT>::inc_sub_count();
return Counted_number<NT>(n1.rep() - n2.rep());
return Counted_number<NT>(NT(n1.rep() - n2.rep()));
}
template <class NT>
@ -368,7 +372,7 @@ Counted_number<NT>
operator*(Counted_number<NT> const &n1, Counted_number<NT> const &n2)
{
Counted_number<NT>::inc_mul_count();
return Counted_number<NT>(n1.rep() * n2.rep());
return Counted_number<NT>(NT(n1.rep() * n2.rep()));
}
template <class NT>
@ -376,7 +380,7 @@ Counted_number<NT>
operator/(Counted_number<NT> const &n1, Counted_number<NT> const &n2)
{
Counted_number<NT>::inc_div_count();
return Counted_number<NT>(n1.rep() / n2.rep());
return Counted_number<NT>(NT(n1.rep() / n2.rep()));
}
template< class NT >

View File

@ -23,7 +23,9 @@
#include <CGAL/MP_Float.h>
#include <CGAL/Quotient.h>
#include <CGAL/boost_mp.h>
#ifdef CGAL_USE_BOOST_MP
#include <CGAL/cpp_float.h>
#endif
#ifdef CGAL_USE_GMP
# include <CGAL/Gmpz.h>

View File

@ -76,7 +76,9 @@ compute_roots_of_2(const NT &a_, const NT &b_, const NT &c_, OutputIterator oit)
}
}
else {
*oit++ = -c/b; return oit;
Root_of_1 cb = -c / b;
*oit++ = Root_of_2(cb);
return oit;
}
}

View File

@ -12,902 +12,8 @@
#ifndef CGAL_BOOST_MP_H
#define CGAL_BOOST_MP_H
#include <CGAL/config.h>
#include <CGAL/number_utils.h>
// It is easier to disable this number type completely for old versions.
// Before 1.63, I/O is broken. Again, disabling the whole file is just the
// easy solution.
// MSVC had trouble with versions <= 1.69:
// https://github.com/boostorg/multiprecision/issues/98
//
// Disable also on Windows 32 bits
// because CGAL/cpp_float.h assumes _BitScanForward64 is available
// See https://learn.microsoft.com/en-us/cpp/intrinsics/bitscanforward-bitscanforward64
//
// Disable also with PowerPC processors, with Boost<1.80 because of that bug:
// https://github.com/boostorg/multiprecision/pull/421
//
#if !defined CGAL_DO_NOT_USE_BOOST_MP && \
(!defined _MSC_VER || BOOST_VERSION >= 107000) && \
(!defined _WIN32 || defined _WIN64) && \
(BOOST_VERSION >= 108000 || (!defined _ARCH_PPC && !defined _ARCH_PPC64))
#define CGAL_USE_BOOST_MP 1
#include <CGAL/Quotient.h>
#include <CGAL/functional.h> // *ary_function
#include <CGAL/number_type_basic.h>
#include <CGAL/Modular_traits.h>
// We can't just include all Boost.Multiprecision here...
#include <boost/multiprecision/number.hpp>
#include <boost/type_traits/common_type.hpp>
// ... but we kind of have to :-(
#include <boost/multiprecision/cpp_int.hpp>
#ifdef CGAL_USE_GMP
// Same dance as in CGAL/gmp.h
# include <CGAL/disable_warnings.h>
# if defined(BOOST_MSVC)
# pragma warning(push)
# pragma warning(disable: 4127 4244 4146 4267) // conversion with loss of data
// warning on - applied on unsigned number
# endif
# include <boost/multiprecision/gmp.hpp>
# if defined(BOOST_MSVC)
# pragma warning(pop)
# endif
# include <CGAL/enable_warnings.h>
#endif
#ifdef CGAL_USE_MPFR
# include <mpfr.h>
#endif
// TODO: work on the coercions (end of the file)
namespace CGAL {
// Algebraic_structure_traits
template <class T, class = boost::mpl::int_<boost::multiprecision::number_category<T>::value> >
struct AST_boost_mp;
template <class NT>
struct AST_boost_mp <NT, boost::mpl::int_<boost::multiprecision::number_kind_integer> >
: Algebraic_structure_traits_base< NT, Euclidean_ring_tag > {
typedef NT Type;
typedef Euclidean_ring_tag Algebraic_category;
typedef Boolean_tag<std::numeric_limits<Type>::is_exact> Is_exact;
typedef Tag_false Is_numerical_sensitive;
struct Is_zero: public CGAL::cpp98::unary_function<Type ,bool> {
bool operator()( const Type& x) const {
return x.is_zero();
}
};
struct Div:
public CGAL::cpp98::binary_function<Type ,Type, Type> {
template <typename T, typename U>
Type operator()(const T& x, const U& y) const {
return x / y;
}
};
struct Mod:
public CGAL::cpp98::binary_function<Type ,Type, Type> {
template <typename T, typename U>
Type operator()(const T& x, const U& y) const {
return x % y;
}
};
struct Gcd : public CGAL::cpp98::binary_function<Type, Type, Type> {
template <typename T, typename U>
Type operator()(const T& x, const U& y) const {
return boost::multiprecision::gcd(x, y);
}
};
struct Sqrt : public CGAL::cpp98::unary_function<Type, Type> {
template <typename T>
Type operator()(const T& x) const {
return boost::multiprecision::sqrt(x);
}
};
};
template <class NT>
struct AST_boost_mp <NT, boost::mpl::int_<boost::multiprecision::number_kind_rational> >
: public Algebraic_structure_traits_base< NT , Field_tag > {
public:
typedef NT Type;
typedef Field_tag Algebraic_category;
typedef Tag_true Is_exact;
typedef Tag_false Is_numerical_sensitive;
struct Is_zero: public CGAL::cpp98::unary_function<Type ,bool> {
bool operator()( const Type& x) const {
return x.is_zero();
}
};
struct Div:
public CGAL::cpp98::binary_function<Type ,Type, Type> {
template <typename T, typename U>
Type operator()(const T& x, const U& y) const {
return x / y;
}
};
};
template <class Backend, boost::multiprecision::expression_template_option Eto>
struct Algebraic_structure_traits<boost::multiprecision::number<Backend, Eto> >
: AST_boost_mp <boost::multiprecision::number<Backend, Eto> > {};
template <class T1,class T2,class T3,class T4,class T5>
struct Algebraic_structure_traits<boost::multiprecision::detail::expression<T1,T2,T3,T4,T5> >
: Algebraic_structure_traits<typename boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>::result_type > {};
// Real_embeddable_traits
namespace Boost_MP_internal {
// here we know that `intv` contains int64 numbers such that their msb is std::numeric_limits<double>::digits-1
// TODO: possibly return denormals sometimes...
inline
std::pair<double,double> shift_positive_interval( const std::pair<double,double>& intv, const int e ) {
CGAL_assertion(intv.first > 0.0);
CGAL_assertion(intv.second > 0.0);
#ifdef CGAL_LITTLE_ENDIAN
CGAL_assertion_code(
union {
struct { uint64_t man:52; uint64_t exp:11; uint64_t sig:1; } s;
double d;
} conv;
conv.d = intv.first;
)
#else
//WARNING: untested!
CGAL_assertion_code(
union {
struct { uint64_t sig:1; uint64_t exp:11; uint64_t man:52; } s;
double d;
} conv;
conv.d = intv.first;
)
#endif
// Check that the exponent of intv.inf is 52, which corresponds to a 53 bit integer
CGAL_assertion(conv.s.exp - ((1 << (11 - 1)) - 1) == std::numeric_limits<double>::digits - 1);
typedef std::numeric_limits<double> limits;
// warning: min_exponent and max_exponent are 1 more than what the name suggests
if (e < limits::min_exponent - limits::digits)
return {0, (limits::min)()};
if (e > limits::max_exponent - limits::digits)
return {(limits::max)(), limits::infinity()}; // intv is positive
const double scale = std::ldexp(1.0, e); // ldexp call is exact
return { scale * intv.first, scale * intv.second }; // cases that would require a rounding mode have been handled above
}
// This function checks if the computed interval is correct and if it is tight.
template<typename Type>
bool are_bounds_correct( const double l, const double u, const Type& x ) {
typedef std::numeric_limits<double> limits;
const double inf = std::numeric_limits<double>::infinity();
if ( u!=l && (l==-inf || u==inf
|| (u==0 && l >= -(limits::min)())
|| (l==0 && u <= (limits::min)())) )
{
return x > Type((limits::max)()) ||
x < Type(-(limits::max)()) ||
(x > Type(-(limits::min)()) && x < Type((limits::min)()));
}
if (!(u == l || u == std::nextafter(l, +inf))) return false;
//TODO: Type(nextafter(l,inf))>x && Type(nextafter(u,-inf))<x
const Type lb(l), ub(u);
const bool are_bounds_respected = (lb <= x && x <= ub);
return are_bounds_respected;
}
// This one returns zero length interval that is inf = sup.
inline
std::pair<double, double> get_0ulp_interval( const int shift, const uint64_t p ) {
const double pp_dbl = static_cast<double>(p);
const std::pair<double,double> intv(pp_dbl, pp_dbl);
return shift_positive_interval(intv, -shift);
}
// This one returns 1 unit length interval.
inline
std::pair<double, double> get_1ulp_interval( const int shift, const uint64_t p ) {
const double pp_dbl = static_cast<double>(p);
const double qq_dbl = pp_dbl+1;
const std::pair<double,double> intv(pp_dbl, qq_dbl);
return shift_positive_interval(intv, -shift);
}
template<typename ET>
std::pair<double, double> to_interval( ET x, int extra_shift = 0 );
// This is a version of to_interval that converts a rational type into a
// double tight interval.
template<typename Type, typename ET>
std::pair<double, double> to_interval( ET xnum, ET xden ) {
CGAL_assertion(!CGAL::is_zero(xden));
CGAL_assertion_code(const Type input(xnum, xden));
double l = 0.0, u = 0.0;
if (CGAL::is_zero(xnum)) { // return [0.0, 0.0]
CGAL_assertion(are_bounds_correct(l, u, input));
return std::make_pair(l, u);
}
CGAL_assertion(!CGAL::is_zero(xnum));
// Handle signs.
bool change_sign = false;
const bool is_num_pos = CGAL::is_positive(xnum);
const bool is_den_pos = CGAL::is_positive(xden);
if (!is_num_pos && !is_den_pos) {
xnum = -xnum;
xden = -xden;
} else if (!is_num_pos && is_den_pos) {
change_sign = true;
xnum = -xnum;
} else if (is_num_pos && !is_den_pos) {
change_sign = true;
xden = -xden;
}
CGAL_assertion(CGAL::is_positive(xnum) && CGAL::is_positive(xden));
const int64_t num_dbl_digits = std::numeric_limits<double>::digits - 1;
const int64_t msb_num = static_cast<int64_t>(boost::multiprecision::msb(xnum));
const int64_t msb_den = static_cast<int64_t>(boost::multiprecision::msb(xden));
#if 0 // Optimisation for the case of input that are double
// An alternative strategy would be to convert numerator and denominator to
// intervals, then divide. However, this would require setting the rounding
// mode (and dividing intervals is not completely free). An important
// special case is when the rational is exactly equal to a double
// (fit_in_double). Then the denominator is a power of 2, so we can skip
// the division and it becomes unnecessary to set the rounding mode, we
// just need to modify the exponent correction for the denominator.
if(msb_den == static_cast<int64_t>(lsb(xden))) {
std::tie(l,u)=to_interval(xnum, msb_den);
if (change_sign) {
CGAL_assertion(are_bounds_correct(-u, -l, input));
return {-u, -l};
}
CGAL_assertion(are_bounds_correct(l, u, input));
return {u, l};
}
#endif
const int64_t msb_diff = msb_num - msb_den;
// Shift so the division result has at least 53 (and at most 54) bits
int shift = static_cast<int>(num_dbl_digits - msb_diff + 1);
CGAL_assertion(shift == num_dbl_digits - msb_diff + 1);
if (shift > 0) {
xnum <<= +shift;
} else if (shift < 0) {
xden <<= -shift;
}
CGAL_assertion(num_dbl_digits + 1 ==
static_cast<int64_t>(boost::multiprecision::msb(xnum)) -
static_cast<int64_t>(boost::multiprecision::msb(xden)));
ET p, r;
boost::multiprecision::divide_qr(xnum, xden, p, r);
uint64_t uip = static_cast<uint64_t>(p);
const int64_t p_bits = static_cast<int64_t>(boost::multiprecision::msb(p));
bool exact = r.is_zero();
if (p_bits > num_dbl_digits) { // case 54 bits
exact &= ((uip & 1) == 0);
uip>>=1;
--shift;
}
std::tie(l, u) = exact ? get_0ulp_interval(shift, uip) : get_1ulp_interval(shift, uip);
if (change_sign) {
const double t = l;
l = -u;
u = -t;
}
CGAL_assertion(are_bounds_correct(l, u, input));
return std::make_pair(l, u);
}
// This is a version of to_interval that converts an integer type into a
// double tight interval.
template<typename ET>
std::pair<double, double> to_interval( ET x, int extra_shift) {
CGAL_assertion_code(const ET input = x);
double l = 0.0, u = 0.0;
if (CGAL::is_zero(x)) { // return [0.0, 0.0]
CGAL_assertion(are_bounds_correct(l, u, input));
return std::make_pair(l, u);
}
CGAL_assertion(!CGAL::is_zero(x));
bool change_sign = false;
const bool is_pos = CGAL::is_positive(x);
if (!is_pos) {
change_sign = true;
x = -x;
}
CGAL_assertion(CGAL::is_positive(x));
const int64_t n = static_cast<int64_t>(boost::multiprecision::msb(x)) + 1;
const int64_t num_dbl_digits = std::numeric_limits<double>::digits;
if (n > num_dbl_digits) {
const int64_t mindig = static_cast<int64_t>(boost::multiprecision::lsb(x));
int e = static_cast<int>(n - num_dbl_digits);
x >>= e;
if (n - mindig > num_dbl_digits)
std::tie(l, u) = get_1ulp_interval(-e+extra_shift, static_cast<uint64_t>(x));
else
std::tie(l, u) = get_0ulp_interval(-e+extra_shift, static_cast<uint64_t>(x));
} else {
l = u = extra_shift==0 ? static_cast<double>(static_cast<uint64_t>(x))
: std::ldexp(static_cast<double>(static_cast<uint64_t>(x)),-extra_shift);
}
if (change_sign) {
const double t = l;
l = -u;
u = -t;
}
CGAL_assertion(extra_shift != 0 || are_bounds_correct(l, u, input));
return std::make_pair(l, u);
}
} // Boost_MP_internal
template <class NT>
struct RET_boost_mp_base
: public INTERN_RET::Real_embeddable_traits_base< NT , CGAL::Tag_true > {
typedef NT Type;
struct Is_zero: public CGAL::cpp98::unary_function<Type ,bool> {
bool operator()( const Type& x) const {
return x.is_zero();
}
};
struct Is_positive: public CGAL::cpp98::unary_function<Type ,bool> {
bool operator()( const Type& x) const {
return x.sign() > 0;
}
};
struct Is_negative: public CGAL::cpp98::unary_function<Type ,bool> {
bool operator()( const Type& x) const {
return x.sign() < 0;
}
};
struct Abs : public CGAL::cpp98::unary_function<Type, Type> {
template <typename T>
Type operator()(const T& x) const {
return boost::multiprecision::abs(x);
}
};
struct Sgn : public CGAL::cpp98::unary_function<Type, ::CGAL::Sign> {
::CGAL::Sign operator()(Type const& x) const {
return CGAL::sign(x.sign());
}
};
struct Compare
: public CGAL::cpp98::binary_function<Type, Type, Comparison_result> {
Comparison_result operator()(const Type& x, const Type& y) const {
return CGAL::sign(x.compare(y));
}
};
struct To_double
: public CGAL::cpp98::unary_function<Type, double> {
double operator()(const Type& x) const {
return x.template convert_to<double>();
}
};
struct To_interval
: public CGAL::cpp98::unary_function< Type, std::pair< double, double > > {
std::pair<double, double>
operator()(const Type& x) const {
// See if https://github.com/boostorg/multiprecision/issues/108 suggests anything better
// assume the conversion is within 1 ulp
// adding IA::smallest() doesn't work because inf-e=inf, even rounded down.
// We must use to_nearest here.
double i;
const double inf = std::numeric_limits<double>::infinity();
{
Protect_FPU_rounding<true> P(CGAL_FE_TONEAREST);
i = static_cast<double>(x);
if (i == +inf) {
return std::make_pair((std::numeric_limits<double>::max)(), i);
} else if (i == -inf) {
return std::make_pair(i, std::numeric_limits<double>::lowest());
}
}
double s = i;
CGAL_assertion(CGAL::abs(i) != inf && CGAL::abs(s) != inf);
// Throws uncaught exception: Cannot convert a non-finite number to an integer.
// We can catch it earlier by using the CGAL_assertion() one line above.
const int cmp = x.compare(i);
if (cmp > 0) {
s = nextafter(s, +inf);
CGAL_assertion(x.compare(s) < 0);
}
else if (cmp < 0) {
i = nextafter(i, -inf);
CGAL_assertion(x.compare(i) > 0);
}
return std::pair<double, double>(i, s);
}
};
};
template <class T, class = boost::mpl::int_<boost::multiprecision::number_category<T>::value> >
struct RET_boost_mp;
template <class NT>
struct RET_boost_mp <NT, boost::mpl::int_<boost::multiprecision::number_kind_integer> >
: RET_boost_mp_base <NT> {
typedef NT Type;
struct To_interval
: public CGAL::cpp98::unary_function< Type, std::pair< double, double > > {
std::pair<double, double> operator()( const Type& x ) const {
return Boost_MP_internal::to_interval(x);
}
};
};
template <class NT>
struct RET_boost_mp <NT, boost::mpl::int_<boost::multiprecision::number_kind_rational> >
: RET_boost_mp_base <NT> {
typedef NT Type;
struct To_interval
: public CGAL::cpp98::unary_function< Type, std::pair< double, double > > {
std::pair<double, double> operator()( const Type& x ) const {
return Boost_MP_internal::to_interval<Type>(
boost::multiprecision::numerator(x), boost::multiprecision::denominator(x));
}
};
};
#ifdef CGAL_USE_MPFR
// Because of these full specializations, things get instantiated more eagerly. Make them artificially partial if necessary.
template <>
struct RET_boost_mp <boost::multiprecision::mpz_int>
: RET_boost_mp_base <boost::multiprecision::mpz_int> {
typedef boost::multiprecision::mpz_int Type;
struct To_interval
: public CGAL::cpp98::unary_function< Type, std::pair< double, double > > {
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.backend().data(), 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.backend().data(), GMP_RNDD);
double i = mpfr_get_d (y, GMP_RNDD); /* EXACT but can overflow */
mpfr_set_z (y, x.backend().data(), 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 <>
struct RET_boost_mp <boost::multiprecision::mpq_rational>
: RET_boost_mp_base <boost::multiprecision::mpq_rational> {
typedef boost::multiprecision::mpq_rational Type;
struct To_interval
: public CGAL::cpp98::unary_function< Type, std::pair< double, double > > {
std::pair<double, double>
operator()(const Type& x) const {
# if MPFR_VERSION_MAJOR >= 3
mpfr_exp_t emin = mpfr_get_emin();
mpfr_set_emin(-1073);
MPFR_DECL_INIT (y, 53); /* Assume IEEE-754 */
int r = mpfr_set_q (y, x.backend().data(), MPFR_RNDA);
r = mpfr_subnormalize (y, r, MPFR_RNDA); /* Round subnormals */
double i = mpfr_get_d (y, MPFR_RNDA); /* EXACT but can overflow */
mpfr_set_emin(emin); /* Restore old value, users may care */
// With mpfr_set_emax(1024) we could drop the is_finite test
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_q (y, x.backend().data(), GMP_RNDD);
double i = mpfr_get_d (y, GMP_RNDD); /* EXACT but can overflow */
mpfr_set_q (y, x.backend().data(), 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
}
};
};
#endif
template <class Backend, boost::multiprecision::expression_template_option Eto>
struct Real_embeddable_traits<boost::multiprecision::number<Backend, Eto> >
: RET_boost_mp <boost::multiprecision::number<Backend, Eto> > {};
template <class T1,class T2,class T3,class T4,class T5>
struct Real_embeddable_traits<boost::multiprecision::detail::expression<T1,T2,T3,T4,T5> >
: Real_embeddable_traits<typename boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>::result_type > {};
// Modular_traits
template <class T, class = boost::mpl::int_<boost::multiprecision::number_category<T>::value> >
struct MT_boost_mp {
typedef T NT;
typedef ::CGAL::Tag_false Is_modularizable;
typedef ::CGAL::Null_functor Residue_type;
typedef ::CGAL::Null_functor Modular_image;
typedef ::CGAL::Null_functor Modular_image_representative;
};
template <class T>
struct MT_boost_mp <T, boost::mpl::int_<boost::multiprecision::number_kind_integer> > {
typedef T NT;
typedef CGAL::Tag_true Is_modularizable;
typedef Residue Residue_type;
struct Modular_image{
Residue_type operator()(const NT& a){
NT tmp(CGAL::mod(a,NT(Residue::get_current_prime())));
return CGAL::Residue(tmp.template convert_to<int>());
}
};
struct Modular_image_representative{
NT operator()(const Residue_type& x){
return NT(x.get_value());
}
};
};
template <class Backend, boost::multiprecision::expression_template_option Eto>
struct Modular_traits<boost::multiprecision::number<Backend, Eto> >
: MT_boost_mp <boost::multiprecision::number<Backend, Eto> > {};
template <class T1,class T2,class T3,class T4,class T5>
struct Modular_traits<boost::multiprecision::detail::expression<T1,T2,T3,T4,T5> >
: Modular_traits<typename boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>::result_type > {};
// Split_double
template <class NT, class = boost::mpl::int_<boost::multiprecision::number_category<NT>::value> >
struct SD_boost_mp {
void operator()(double d, NT &num, NT &den) const
{
num = d;
den = 1;
}
};
template <class NT>
struct SD_boost_mp <NT, boost::mpl::int_<boost::multiprecision::number_kind_integer> >
{
void operator()(double d, NT &num, NT &den) const
{
std::pair<double, double> p = split_numerator_denominator(d);
num = NT(p.first);
den = NT(p.second);
}
};
template <class Backend, boost::multiprecision::expression_template_option Eto>
struct Split_double<boost::multiprecision::number<Backend, Eto> >
: SD_boost_mp <boost::multiprecision::number<Backend, Eto> > {};
template <class T1,class T2,class T3,class T4,class T5>
struct Split_double<boost::multiprecision::detail::expression<T1,T2,T3,T4,T5> >
: Split_double<typename boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>::result_type > {};
// Fraction_traits
template <class T, class = boost::mpl::int_<boost::multiprecision::number_category<T>::value> >
struct FT_boost_mp {
typedef T Type;
typedef Tag_false Is_fraction;
typedef Null_tag Numerator_type;
typedef Null_tag Denominator_type;
typedef Null_functor Common_factor;
typedef Null_functor Decompose;
typedef Null_functor Compose;
};
template <class NT>
struct FT_boost_mp <NT, boost::mpl::int_<boost::multiprecision::number_kind_rational> > {
typedef NT Type;
typedef ::CGAL::Tag_true Is_fraction;
typedef typename boost::multiprecision::component_type<NT>::type Numerator_type;
typedef Numerator_type Denominator_type;
typedef typename Algebraic_structure_traits< Numerator_type >::Gcd Common_factor;
class Decompose {
public:
typedef Type first_argument_type;
typedef Numerator_type& second_argument_type;
typedef Denominator_type& third_argument_type;
void operator () (
const Type& rat,
Numerator_type& num,
Denominator_type& den) {
num = numerator(rat);
den = denominator(rat);
}
};
class Compose {
public:
typedef Numerator_type first_argument_type;
typedef Denominator_type second_argument_type;
typedef Type result_type;
Type operator ()(
const Numerator_type& num ,
const Denominator_type& den ) {
return Type(num, den);
}
};
};
template <class Backend, boost::multiprecision::expression_template_option Eto>
struct Fraction_traits<boost::multiprecision::number<Backend, Eto> >
: FT_boost_mp <boost::multiprecision::number<Backend, Eto> > {};
template <class T1,class T2,class T3,class T4,class T5>
struct Fraction_traits<boost::multiprecision::detail::expression<T1,T2,T3,T4,T5> >
: Fraction_traits<typename boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>::result_type > {};
// Coercions
namespace internal { namespace boost_mp { BOOST_MPL_HAS_XXX_TRAIT_DEF(type) } }
template <class B1, boost::multiprecision::expression_template_option E1, class B2, boost::multiprecision::expression_template_option E2>
struct Coercion_traits<boost::multiprecision::number<B1, E1>, boost::multiprecision::number<B2, E2> >
{
typedef boost::common_type<boost::multiprecision::number<B1, E1>, boost::multiprecision::number<B2, E2> > CT;
typedef Boolean_tag<internal::boost_mp::has_type<CT>::value> Are_implicit_interoperable;
// FIXME: the implicit/explicit answers shouldn't be the same...
typedef Are_implicit_interoperable Are_explicit_interoperable;
// FIXME: won't compile when they are not interoperable.
typedef typename CT::type Type;
struct Cast{
typedef Type result_type;
template <class U>
Type operator()(const U& x) const {
return Type(x);
}
};
};
// Avoid ambiguity with the specialization for <A,A> ...
template <class B1, boost::multiprecision::expression_template_option E1>
struct Coercion_traits<boost::multiprecision::number<B1, E1>, boost::multiprecision::number<B1, E1> >
{
typedef boost::multiprecision::number<B1, E1> Type;
typedef Tag_true Are_implicit_interoperable;
typedef Tag_true Are_explicit_interoperable;
struct Cast{
typedef Type result_type;
template <class U>
Type operator()(const U& x) const {
return Type(x);
}
};
};
template <class T1, class T2, class T3, class T4, class T5, class U1, class U2, class U3, class U4, class U5>
struct Coercion_traits <
boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>,
boost::multiprecision::detail::expression<U1,U2,U3,U4,U5> >
: Coercion_traits <
typename boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>::result_type,
typename boost::multiprecision::detail::expression<U1,U2,U3,U4,U5>::result_type>
{ };
// Avoid ambiguity with the specialization for <A,A> ...
template <class T1, class T2, class T3, class T4, class T5>
struct Coercion_traits <
boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>,
boost::multiprecision::detail::expression<T1,T2,T3,T4,T5> >
: Coercion_traits <
typename boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>::result_type,
typename boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>::result_type>
{ };
template <class B, boost::multiprecision::expression_template_option E, class T1, class T2, class T3, class T4, class T5>
struct Coercion_traits<boost::multiprecision::number<B, E>, boost::multiprecision::detail::expression<T1,T2,T3,T4,T5> >
: Coercion_traits <
boost::multiprecision::number<B, E>,
typename boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>::result_type>
{ };
template <class B, boost::multiprecision::expression_template_option E, class T1, class T2, class T3, class T4, class T5>
struct Coercion_traits<boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>, boost::multiprecision::number<B, E> >
: Coercion_traits <
typename boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>::result_type,
boost::multiprecision::number<B, E> >
{ };
// TODO: fix existing coercions
// (double -> rational is implicit only for 1.56+, see ticket #10082)
// The real solution would be to avoid specializing Coercion_traits for all pairs of number types and let it auto-detect what works, so only broken types need an explicit specialization.
// Ignore types smaller than long
#define CGAL_COERCE_INT(int) \
template <class B1, boost::multiprecision::expression_template_option E1> \
struct Coercion_traits<boost::multiprecision::number<B1, E1>, int> { \
typedef boost::multiprecision::number<B1, E1> Type; \
typedef Tag_true Are_implicit_interoperable; \
typedef Tag_true Are_explicit_interoperable; \
struct Cast{ \
typedef Type result_type; \
template <class U> Type operator()(const U& x) const { return Type(x); } \
}; \
}; \
template <class B1, boost::multiprecision::expression_template_option E1> \
struct Coercion_traits<int, boost::multiprecision::number<B1, E1> > \
: Coercion_traits<boost::multiprecision::number<B1, E1>, int> {}; \
template <class T1, class T2, class T3, class T4, class T5> \
struct Coercion_traits<boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>, int> \
: Coercion_traits<typename boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>::result_type, int>{}; \
template <class T1, class T2, class T3, class T4, class T5> \
struct Coercion_traits<int, boost::multiprecision::detail::expression<T1,T2,T3,T4,T5> > \
: Coercion_traits<typename boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>::result_type, int>{}
CGAL_COERCE_INT(short);
CGAL_COERCE_INT(int);
CGAL_COERCE_INT(long);
#undef CGAL_COERCE_INT
// Ignore bounded-precision rationals
#define CGAL_COERCE_FLOAT(float) \
template <class B1, boost::multiprecision::expression_template_option E1> \
struct Coercion_traits<boost::multiprecision::number<B1, E1>, float> { \
typedef boost::multiprecision::number<B1, E1> Type; \
typedef Boolean_tag<boost::multiprecision::number_category<Type>::value != boost::multiprecision::number_kind_integer> Are_implicit_interoperable; \
typedef Are_implicit_interoperable Are_explicit_interoperable; \
struct Cast{ \
typedef Type result_type; \
template <class U> Type operator()(const U& x) const { return Type(x); } \
}; \
}; \
template <class B1, boost::multiprecision::expression_template_option E1> \
struct Coercion_traits<float, boost::multiprecision::number<B1, E1> > \
: Coercion_traits<boost::multiprecision::number<B1, E1>, float> {}; \
template <class T1, class T2, class T3, class T4, class T5> \
struct Coercion_traits<boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>, float> \
: Coercion_traits<typename boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>::result_type, float>{}; \
template <class T1, class T2, class T3, class T4, class T5> \
struct Coercion_traits<float, boost::multiprecision::detail::expression<T1,T2,T3,T4,T5> > \
: Coercion_traits<typename boost::multiprecision::detail::expression<T1,T2,T3,T4,T5>::result_type, float>{}
CGAL_COERCE_FLOAT(float);
CGAL_COERCE_FLOAT(double);
#undef CGAL_COERCE_FLOAT
// Because of https://github.com/boostorg/multiprecision/issues/29 , this is not perfect and fails to read some KDS files.
template <>
class Input_rep<boost::multiprecision::cpp_rational> : public IO_rep_is_specialized {
boost::multiprecision::cpp_rational& q;
public:
Input_rep(boost::multiprecision::cpp_rational& qq) : q(qq) {}
std::istream& operator()(std::istream& in) const {
internal::read_float_or_quotient<boost::multiprecision::cpp_int,boost::multiprecision::cpp_rational>(in, q);
return in;
}
};
#ifdef CGAL_USE_GMP
template <>
class Input_rep<boost::multiprecision::mpq_rational> : public IO_rep_is_specialized {
boost::multiprecision::mpq_rational& q;
public:
Input_rep(boost::multiprecision::mpq_rational& qq) : q(qq) {}
std::istream& operator()(std::istream& in) const {
internal::read_float_or_quotient<boost::multiprecision::mpz_int,boost::multiprecision::mpq_rational>(in, q);
return in;
}
};
#endif
// Copied from leda_rational.h
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, boost::multiprecision::cpp_rational& et)
{
internal::read_float_or_quotient<boost::multiprecision::cpp_int,boost::multiprecision::cpp_rational>(is, et);
}
#ifdef CGAL_USE_GMP
template <>
inline void read_float_or_quotient(std::istream & is, boost::multiprecision::mpq_rational& et)
{
internal::read_float_or_quotient<boost::multiprecision::mpz_int,boost::multiprecision::mpq_rational>(is, et);
}
#endif
} // namespace internal
#ifdef CGAL_USE_BOOST_MP
template< > class Real_embeddable_traits< Quotient<boost::multiprecision::cpp_int> >
: public INTERN_QUOTIENT::Real_embeddable_traits_quotient_base< Quotient<boost::multiprecision::cpp_int> > {
public:
typedef Quotient<boost::multiprecision::cpp_int> Type;
class To_interval
: public CGAL::cpp98::unary_function< Type, std::pair< double, double > > {
public:
std::pair<double, double> operator()( const Type& x ) const {
return Boost_MP_internal::to_interval<Type>(x.num, x.den);
}
};
};
#endif // CGAL_USE_BOOST_MP
} //namespace CGAL
#include <CGAL/boost_mp_type.h>
#include <CGAL/BOOST_MP_arithmetic_kernel.h>
#include <CGAL/cpp_float.h>
#endif // BOOST_VERSION
#endif
#endif // CGAL_BOOST_MP_H

File diff suppressed because it is too large Load Diff

View File

@ -13,10 +13,6 @@ include_directories(BEFORE include)
create_single_source_cgal_program("bench_interval.cpp")
create_single_source_cgal_program("cpp_float.cpp")
create_single_source_cgal_program("constant.cpp")
create_single_source_cgal_program("CORE_BigFloat.cpp")
create_single_source_cgal_program("CORE_BigInt.cpp")
create_single_source_cgal_program("CORE_BigRat.cpp")
create_single_source_cgal_program("CORE_Expr.cpp")
create_single_source_cgal_program("Counted_number.cpp")
create_single_source_cgal_program("double.cpp")
create_single_source_cgal_program("doubletst.cpp")
@ -66,14 +62,17 @@ create_single_source_cgal_program("utilities.cpp")
create_single_source_cgal_program("Exact_rational.cpp")
create_single_source_cgal_program("Mpzf_new.cpp")
find_package( GMP )
if( GMP_FOUND AND NOT CGAL_DISABLE_GMP )
if( CGAL_Core_FOUND )
create_single_source_cgal_program( "CORE_Expr_ticket_4296.cpp" )
create_single_source_cgal_program("CORE_BigFloat.cpp")
create_single_source_cgal_program("CORE_BigInt.cpp")
create_single_source_cgal_program("CORE_BigRat.cpp")
create_single_source_cgal_program("CORE_Expr.cpp")
find_package(MPFI QUIET)
if( MPFI_FOUND )
include( ${MPFI_USE_FILE} )
endif() #MPFI_FOUND
endif() #GMP_FOUND AND NOT CGAL_DISABLE_GMP
endif() #CGAL_Core_FOUND
if(NOT CGAL_DISABLE_GMP)
create_single_source_cgal_program( "Gmpfi.cpp" )

View File

@ -72,4 +72,3 @@ int main() { return 0; }
#endif // CGAL_USE_CORE
//EOF

View File

@ -19,24 +19,25 @@ void test_io(){
std::stringstream ss;
CGAL::IO::set_ascii_mode(ss);
ss << CGAL::IO::oformat(NT(1));
//std::cout << ss.str()<<std::endl;
assert( ss.str() == "1/1");
std::cout << ss.str()<<std::endl;
assert( ss.str() == "1");
}{
std::stringstream ss;
CGAL::IO::set_ascii_mode(ss);
ss << CGAL::IO::oformat(NT(0));
assert( ss.str() == "0/1");
assert( ss.str() == "0");
}{
std::stringstream ss;
CGAL::IO::set_ascii_mode(ss);
ss << CGAL::IO::oformat(NT(-1));
assert( ss.str() == "-1/1");
assert( ss.str() == "-1");
}
//MODE PRETTY
{
std::stringstream ss;
CGAL::IO::set_pretty_mode(ss);
ss << CGAL::IO::oformat(NT(2), CGAL::Parens_as_product_tag());
std::cout << "|" << ss.str() << "|" << std::endl;
assert( ss.str() == "2");
}{
std::stringstream ss;

View File

@ -7,7 +7,7 @@
#include <cstdlib>
#include <CGAL/CORE_Expr.h>
#include <CGAL/Gmpq.h>
#include <CGAL/CORE_BigRat.h>
#include <CGAL/Test/_test_algebraic_structure.h>
#include <CGAL/Test/_test_real_embeddable.h>
@ -119,7 +119,7 @@ void test_MSB_bug()
int main() {
precision_bug();
test_istream();
test_MSB_bug<CGAL::Gmpq>();
test_MSB_bug<CORE::BigRat>();
test_MSB_bug<CORE::Expr>();
typedef CORE::Expr NT;

View File

@ -106,7 +106,6 @@ int main()
// CORE
#ifdef CGAL_USE_CORE
static_assert(CGAL::Output_rep<CORE::BigRat>::is_specialized == true);
//bug in io for CORE.
test_it<CORE::BigInt>("CORE::BigInt");
test_it<CORE::BigRat>("CORE::BigRat");

View File

@ -24,6 +24,8 @@
#ifdef CGAL_EIGEN3_ENABLED
#include <Eigen/Dense>
// Just check that it all compiles.
template <class NT, int s>
void check_(){
@ -33,7 +35,7 @@ void check_(){
Eigen::Matrix<NT,s,1> v(3);
v << 1, 2, 3;
NT t=v.dot(v);
v+=d*m*(t*v);
v+=d*Eigen::Matrix<NT,s,1>(m*(t*v));
std::ptrdiff_t si=v.size();
CGAL_USE(si);
}

View File

@ -5,7 +5,10 @@
#include <CGAL/Lazy_exact_nt.h>
#include <CGAL/Interval_nt.h>
#include <CGAL/Sqrt_extension.h>
#ifdef CGAL_USE_BOOST_MP
#include <CGAL/boost_mp.h>
#endif
#ifdef CGAL_USE_GMP
#include <CGAL/Gmpz.h>

View File

@ -2,6 +2,7 @@ Algebraic_foundations
Arithmetic_kernel
BGL
Bounding_volumes
CGAL_Core
Cartesian_kernel
Circulator
Convex_hull_2

View File

@ -1,5 +1,6 @@
Algebraic_foundations
Arithmetic_kernel
CGAL_Core
Cartesian_kernel
Circulator
Convex_hull_2

View File

@ -1,6 +1,7 @@
Algebraic_foundations
Arithmetic_kernel
BGL
CGAL_Core
Cartesian_kernel
Circulator
Convex_hull_2

View File

@ -1,5 +1,6 @@
Algebraic_foundations
Arithmetic_kernel
CGAL_Core
Cartesian_kernel
Circulator
Distance_2

Some files were not shown because too many files have changed in this diff Show More