Added constructor Gmpq(Gmpfr) and eliminated constructor Gmpfr(Gmpq)

because it is not exact. Replaced all the operations between Gmpfr and Gmpq
that returned a Gmpfr by the same operations returning a Gmpq (these new
operations are exact). Changed coercion traits (I hope) accordingly.
This commit is contained in:
Luis Peñaranda 2010-02-19 11:52:49 +00:00
parent 2329e43f1a
commit abcfab4ee3
7 changed files with 150 additions and 104 deletions

View File

@ -19,7 +19,7 @@ can be set to any of the four rounding modes (initially, it is set
to nearest). To specify rounding modes for operations, the type
used is \ccc{std::float_round_style}.
This type is \ccc{ImplicitInteroperable} with \ccc{Gmpz}, \ccc{Gmpq},
This type is \ccc{ImplicitInteroperable} with \ccc{Gmpz}, %\ccc{Gmpq},
\verb-long-, \verb-unsigned long-, \verb-int-, \verb-double- and
\verb-long double-.
@ -71,8 +71,10 @@ This type is \ccc{ImplicitInteroperable} with \ccc{Gmpz}, \ccc{Gmpq},
\ccConstructor{Gmpfr(const Gmpz &z);}
{Creates a MPFR number, initialized with the value of \ccc{z}.}
\ccConstructor{Gmpfr(const Gmpq &q);}
{Creates a MPFR number, initialized with the value of \ccc{q}.}
%--------------------------------------------------
% \ccConstructor{Gmpfr(const Gmpq &q);}
% {Creates a MPFR number, initialized with the value of \ccc{q}.}
%--------------------------------------------------
\ccConstructor{Gmpfr(const Gmpzf &z);}
{Creates a MPFR number, initialized with the value of \ccc{z}.}
@ -197,7 +199,8 @@ as the maximum of the operands precision and the default precision.
The second operand of the former operations can be a \verb=Gmpfr=,
\verb=int=, \verb=long=, \verb=unsigned=, \verb=unsigned long=,
\verb=Gmpz= or \verb=Gmpq=. The precision of an operation between a
%\verb=Gmpz= or \verb=Gmpq=. The precision of an operation between a
or \verb=Gmpz=. The precision of an operation between a
\ccc{Gmpfr} and a number of another type is defined as the maximum between
the number's precision and the default precision.
@ -289,9 +292,11 @@ Other arithmetic functions provided by the class are:
is not necessarily the smallest possible value of \(m\) (that is,
it might be that \(2|m\)).}
\ccMethod{Gmpq to_fraction();}
{Returns a \ccc{Gmpq} with the same value of \ccVar. This
conversion is exact.}
%--------------------------------------------------
% \ccMethod{Gmpq to_fraction();}
% {Returns a \ccc{Gmpq} with the same value of \ccVar. This
% conversion is exact.}
%--------------------------------------------------
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@ -301,7 +306,7 @@ Other arithmetic functions provided by the class are:
Comparison operators \verb-==-, \verb-!=-, \verb->-, \verb-<-, \verb->=-
\ and \verb-<=- \ are also overloaded. A \ccc{Gmpfr} can be compared
with other \ccc{Gmpfr}, as well as with a \ccc{Gmpz}, \ccc{Gmpq},
with other \ccc{Gmpfr}, as well as with a \ccc{Gmpz}, %\ccc{Gmpq},
\verb=long=, \verb=unsigned long=, \verb=int=, \verb=double= \ or
\verb=long double=. It is worth noting that the numbers are never
converted nor rounded before comparison. In the case where one of the

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2009 Inria Lorraine (France). All rights reserved.
// Copyright (c) 2007-2010 Inria Lorraine (France). All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
@ -24,7 +24,6 @@
#include <boost/operators.hpp>
#include <CGAL/Handle_for.h>
#include <CGAL/GMP/Gmpz_type.h>
#include <CGAL/GMP/Gmpq_type.h>
#include <CGAL/GMP/Gmpzf_type.h>
#include <string>
#include <limits>
@ -62,10 +61,6 @@ bool operator<(const Gmpfr&,const Gmpz&);
bool operator>(const Gmpfr&,const Gmpz&);
bool operator==(const Gmpfr&,const Gmpz&);
bool operator<(const Gmpfr&,const Gmpq&);
bool operator>(const Gmpfr&,const Gmpq&);
bool operator==(const Gmpfr&,const Gmpq&);
struct Gmpfr_rep{
mpfr_t floating_point_number;
bool clear_on_destruction;
@ -96,9 +91,8 @@ class Gmpfr:
boost::ordered_euclidian_ring_operators2<Gmpfr,int,
boost::totally_ordered2<Gmpfr,double,
boost::totally_ordered2<Gmpfr,long double,
boost::ordered_euclidian_ring_operators2<Gmpfr,Gmpz,
boost::ordered_euclidian_ring_operators2<Gmpfr,Gmpq
> > > > > > > >
boost::ordered_euclidian_ring_operators2<Gmpfr,Gmpz
> > > > > > >
{
private:
@ -259,7 +253,6 @@ class Gmpfr:
_GMPFR_CONSTRUCTOR_FROM_TYPE(double,mpfr_set_d);
_GMPFR_CONSTRUCTOR_FROM_TYPE(long double,mpfr_set_ld);
_GMPFR_CONSTRUCTOR_FROM_OBJECT(Gmpz,mpz(),mpfr_set_z);
_GMPFR_CONSTRUCTOR_FROM_OBJECT(Gmpq,mpq(),mpfr_set_q);
#undef _GMPFR_CONSTRUCTOR_FROM_TYPE
#undef _GMPFR_CONSTRUCTOR_FROM_OBJECT
@ -353,7 +346,6 @@ class Gmpfr:
_GMPFR_DECLARE_OPERATORS(unsigned long)
_GMPFR_DECLARE_OPERATORS(int)
_GMPFR_DECLARE_OPERATORS(const Gmpz&)
_GMPFR_DECLARE_OPERATORS(const Gmpq&)
#undef _GMPFR_DECLARE_OPERATORS
@ -375,7 +367,6 @@ class Gmpfr:
_GMPFR_DECLARE_STATIC_FUNCTIONS(unsigned long)
_GMPFR_DECLARE_STATIC_FUNCTIONS(int)
_GMPFR_DECLARE_STATIC_FUNCTIONS(const Gmpz&)
_GMPFR_DECLARE_STATIC_FUNCTIONS(const Gmpq&)
#undef _GMPFR_DECLARE_STATIC_FUNCTION
#undef _GMPFR_DECLARE_STATIC_FUNCTIONS
@ -418,7 +409,6 @@ class Gmpfr:
to_double_exp(std::float_round_style=Gmpfr::get_default_rndmode())const;
std::pair<std::pair<double,double>,long> to_interval_exp()const;
std::pair<Gmpz,long> to_integer_exp()const;
Gmpq to_fraction()const;
};
@ -731,11 +721,6 @@ _GMPFR_OBJECT_BINARY_OPERATOR(operator-=,Gmpz,mpz(),mpfr_sub_z)
_GMPFR_OBJECT_BINARY_OPERATOR(operator*=,Gmpz,mpz(),mpfr_mul_z)
_GMPFR_OBJECT_BINARY_OPERATOR(operator/=,Gmpz,mpz(),mpfr_div_z)
_GMPFR_OBJECT_BINARY_OPERATOR(operator+=,Gmpq,mpq(),mpfr_add_q)
_GMPFR_OBJECT_BINARY_OPERATOR(operator-=,Gmpq,mpq(),mpfr_sub_q)
_GMPFR_OBJECT_BINARY_OPERATOR(operator*=,Gmpq,mpq(),mpfr_mul_q)
_GMPFR_OBJECT_BINARY_OPERATOR(operator/=,Gmpq,mpq(),mpfr_div_q)
#undef _GMPFR_OBJECT_BINARY_OPERATOR
#undef _GMPFR_GMPFR_BINARY_OPERATOR
#undef _GMPFR_TYPE_BINARY_OPERATOR
@ -896,29 +881,6 @@ std::pair<Gmpz,long> Gmpfr::to_integer_exp()const{
return std::make_pair(z,e);
}
inline
Gmpq Gmpfr::to_fraction()const{
std::pair<Gmpz,long> p=this->to_integer_exp();
Gmpq q(p.first);
CGAL_assertion(mpz_cmp(p.first.mpz(),mpq_numref(q.mpq()))==0);
CGAL_assertion(mpz_cmp_ui(mpq_denref(q.mpq()),(unsigned long)1)==0);
if(p.second<0){
mpz_mul_2exp(mpq_denref(q.mpq()),
mpq_denref(q.mpq()),
(unsigned long)(-p.second));
}else{
mpz_mul_2exp(mpq_numref(q.mpq()),
mpq_numref(q.mpq()),
(unsigned long)(p.second));
}
mpq_canonicalize(q.mpq());
CGAL_assertion_msg(mpz_sizeinbase(mpq_denref(q.mpq()),2)==
mpz_scan1(mpq_denref(q.mpq()),0)+1,
"denominator is not a power of 2");
CGAL_assertion_msg(mpfr_cmp_q(fr(),q.mpq())==0,"conversion error");
return q;
}
// input/output
@ -1154,21 +1116,6 @@ bool operator==(const Gmpfr &a,const Gmpz &b){
return !mpfr_cmp_z(a.fr(),b.mpz());
}
inline
bool operator<(const Gmpfr &a,const Gmpq &b){
return(mpfr_cmp_q(a.fr(),b.mpq())<0);
}
inline
bool operator>(const Gmpfr &a,const Gmpq &b){
return(mpfr_cmp_q(a.fr(),b.mpq())>0);
}
inline
bool operator==(const Gmpfr &a,const Gmpq &b){
return !mpfr_cmp_q(a.fr(),b.mpq());
}
inline
Gmpfr min BOOST_PREVENT_MACRO_SUBSTITUTION(const Gmpfr& x,const Gmpfr& y){
return (x<=y)?x:y;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2009 Inria Lorraine (France). All rights reserved.
// Copyright (c) 2007-2010 Inria Lorraine (France). All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
@ -105,11 +105,6 @@ _GMPFR_NONCOMMUTATIVE_OPERATION(sub,const Gmpz&,b.mpz(),mpfr_sub_z)
_GMPFR_NONCOMMUTATIVE_OPERATION(mul,const Gmpz&,b.mpz(),mpfr_mul_z)
_GMPFR_NONCOMMUTATIVE_OPERATION(div,const Gmpz&,b.mpz(),mpfr_div_z)
_GMPFR_NONCOMMUTATIVE_OPERATION(add,const Gmpq&,b.mpq(),mpfr_add_q)
_GMPFR_NONCOMMUTATIVE_OPERATION(sub,const Gmpq&,b.mpq(),mpfr_sub_q)
_GMPFR_NONCOMMUTATIVE_OPERATION(mul,const Gmpq&,b.mpq(),mpfr_mul_q)
_GMPFR_NONCOMMUTATIVE_OPERATION(div,const Gmpq&,b.mpq(),mpfr_div_q)
#undef _GMPFR_PREC
#undef _GMPFR_PREC_2
#undef _GMPFR_OPERATION_GMPFR

View File

@ -27,6 +27,7 @@
#include <CGAL/basic.h>
#include <CGAL/GMP/Gmpz_type.h>
#include <CGAL/GMP/Gmpfr_type.h>
#include <gmp.h>
#include <mpfr.h>
@ -37,9 +38,7 @@
#include <CGAL/Handle_for.h>
#include <CGAL/Profile_counter.h>
CGAL_BEGIN_NAMESPACE
// TODO : add mixed operators with Gmpz.
// Wrapper around mpq_t to get the destructor call mpq_clear.
// Contrary to mpz_t, there are no mpq_init_set_* functions,
@ -62,9 +61,10 @@ class Gmpq
: Handle_for<Gmpq_rep>,
boost::ordered_field_operators1< Gmpq
, boost::ordered_field_operators2< Gmpq, Gmpz
, boost::ordered_field_operators2< Gmpq, Gmpfr
, boost::ordered_field_operators2< Gmpq, int
, boost::ordered_field_operators2< Gmpq, long
> > > >
> > > > >
{
typedef Handle_for<Gmpq_rep> Base;
public:
@ -128,6 +128,28 @@ public:
mpq_set_d(mpq(), d);
}
Gmpq(Gmpfr f)
{
std::pair<Gmpz,long> intexp=f.to_integer_exp();
mpq_set_z(mpq(),intexp.first.mpz());
if(intexp.second>0){
mpz_mul_2exp(mpq_numref(mpq()),
mpq_denref(mpq()),
(unsigned long)intexp.second);
}else{
mpz_mul_2exp(mpq_denref(mpq()),
mpq_denref(mpq()),
(unsigned long)intexp.second);
}
// mpq_canonicalize is not needed, because:
// (i) to_integer_exp returns always an odd number
// (ii) the denominator is always a power of 2
CGAL_assertion_msg(mpz_tstbit(intexp.first.mpz(),0)==1,
"even numerator in conversion Gmpfr->Gmpq");
CGAL_assertion_msg(mpfr_cmp_q(f.fr(),mpq())==0,
"error in conversion Gmpfr->Gmpq");
}
Gmpq(const std::string& str, int base = 10)
{
mpq_set_str(mpq(), str.c_str(), base);
@ -180,30 +202,39 @@ public:
CGAL_HISTOGRAM_PROFILER("[Gmpq sizes in log2 scale]",
(unsigned) ( ::log(double(size())) / ::log(double(2)) ) );
}
// Interoperability with int
Gmpq& operator+=(int z){return (*this)+= Gmpq(z);}
Gmpq& operator-=(int z){return (*this)-= Gmpq(z);}
Gmpq& operator*=(int z){return (*this)*= Gmpq(z);}
Gmpq& operator/=(int z){return (*this)/= Gmpq(z);}
bool operator==(int z) const {return (*this)== Gmpq(z);}
bool operator< (int z) const {return (*this)< Gmpq(z);}
bool operator> (int z) const {return (*this)> Gmpq(z);}
bool operator==(int z) const {return mpq_cmp_si(mpq(),z,1)==0;}
bool operator< (int z) const {return mpq_cmp_si(mpq(),z,1)<0;}
bool operator> (int z) const {return mpq_cmp_si(mpq(),z,1)>0;}
// Interoperability with long
Gmpq& operator+=(long z){return (*this)+= Gmpq(z);}
Gmpq& operator-=(long z){return (*this)-= Gmpq(z);}
Gmpq& operator*=(long z){return (*this)*= Gmpq(z);}
Gmpq& operator/=(long z){return (*this)/= Gmpq(z);}
bool operator==(long z) const {return (*this)== Gmpq(z);}
bool operator< (long z) const {return (*this)< Gmpq(z);}
bool operator> (long z) const {return (*this)> Gmpq(z);}
bool operator==(long z) const {return mpq_cmp_si(mpq(),z,1)==0;}
bool operator< (long z) const {return mpq_cmp_si(mpq(),z,1)<0;}
bool operator> (long z) const {return mpq_cmp_si(mpq(),z,1)>0;}
// Interoperability with Gmpfr
Gmpq& operator+=(const Gmpfr &f){return (*this)+= Gmpq(f);}
Gmpq& operator-=(const Gmpfr &f){return (*this)-= Gmpq(f);}
Gmpq& operator*=(const Gmpfr &f){return (*this)*= Gmpq(f);}
Gmpq& operator/=(const Gmpfr &f){return (*this)/= Gmpq(f);}
bool operator==(const Gmpfr &f) const {return mpfr_cmp_q(f.fr(),mpq())==0;}
bool operator< (const Gmpfr &f) const {return mpfr_cmp_q(f.fr(),mpq())>0;}
bool operator> (const Gmpfr &f) const {return mpfr_cmp_q(f.fr(),mpq())<0;}
// Interoperability with Gmpz
Gmpq& operator+=(const Gmpz &z){return (*this)+= Gmpq(z);}
Gmpq& operator-=(const Gmpz &z){return (*this)-= Gmpq(z);}
Gmpq& operator*=(const Gmpz &z){return (*this)*= Gmpq(z);}
Gmpq& operator/=(const Gmpz &z){return (*this)/= Gmpq(z);}
Gmpq& operator+=(const Gmpz&);
Gmpq& operator-=(const Gmpz&);
Gmpq& operator*=(const Gmpz&);
Gmpq& operator/=(const Gmpz&);
bool operator==(const Gmpz &z) const {return (*this)== Gmpq(z);}
bool operator< (const Gmpz &z) const {return (*this)< Gmpq(z);}
bool operator> (const Gmpz &z) const {return (*this)> Gmpq(z);}
@ -267,12 +298,81 @@ Gmpq::operator/=(const Gmpq &z)
return *this;
}
inline
Gmpq& Gmpq::operator+=(const Gmpz &z){
if(unique()){
mpz_addmul(mpq_numref(mpq()),mpq_denref(mpq()),z.mpz());
mpq_canonicalize(mpq());
}else{
Gmpq result;
mpz_mul(mpq_numref(result.mpq()),
mpq_denref(mpq()),
z.mpz());
mpz_add(mpq_numref(result.mpq()),
mpq_numref(mpq()),
mpq_numref(result.mpq()));
mpz_set(mpq_denref(result.mpq()),mpq_denref(mpq()));
mpq_canonicalize(result.mpq());
swap(result);
}
return *this;
}
inline
Gmpq& Gmpq::operator-=(const Gmpz &z){
if(unique()){
mpz_submul(mpq_numref(mpq()),mpq_denref(mpq()),z.mpz());
mpq_canonicalize(mpq());
}else{
Gmpq result;
mpz_mul(mpq_numref(result.mpq()),
mpq_denref(mpq()),
z.mpz());
mpz_sub(mpq_numref(result.mpq()),
mpq_numref(mpq()),
mpq_numref(result.mpq()));
mpz_set(mpq_denref(result.mpq()),mpq_denref(mpq()));
mpq_canonicalize(result.mpq());
swap(result);
}
return *this;
}
inline
Gmpq& Gmpq::operator*=(const Gmpz &z){
if(unique()){
mpz_mul(mpq_numref(mpq()),mpq_numref(mpq()),z.mpz());
mpq_canonicalize(mpq());
}else{
Gmpq result;
mpz_mul(mpq_numref(result.mpq()),mpq_numref(mpq()),z.mpz());
mpz_set(mpq_denref(result.mpq()),mpq_denref(mpq()));
mpq_canonicalize(result.mpq());
swap(result);
}
return *this;
}
inline
Gmpq& Gmpq::operator/=(const Gmpz &z){
if(unique()){
mpz_mul(mpq_denref(mpq()),mpq_denref(mpq()),z.mpz());
mpq_canonicalize(mpq());
}else{
Gmpq result;
mpz_mul(mpq_denref(result.mpq()),mpq_denref(mpq()),z.mpz());
mpz_set(mpq_numref(result.mpq()),mpq_numref(mpq()));
mpq_canonicalize(result.mpq());
swap(result);
}
return *this;
}
inline
double
Gmpq::to_double() const
{ return mpq_get_d(mpq()); }
inline
Sign
Gmpq::sign() const
@ -426,14 +526,12 @@ operator>>(std::istream& is, Gmpq &z)
}
inline Gmpq min BOOST_PREVENT_MACRO_SUBSTITUTION(const Gmpq& x,const Gmpq& y){
return (x<=y)?x:y;
return (x<=y)?x:y;
}
inline Gmpq max BOOST_PREVENT_MACRO_SUBSTITUTION(const Gmpq& x,const Gmpq& y){
return (x>=y)?x:y;
return (x>=y)?x:y;
}
CGAL_END_NAMESPACE
#endif // CGAL_GMPQ_TYPE_H

View File

@ -29,6 +29,7 @@
#include <CGAL/number_type_basic.h>
#include <CGAL/GMP/Gmpz_type.h>
#include <CGAL/GMP/Gmpzf_type.h>
#include <CGAL/GMP/Gmpfr_type.h>
#include <CGAL/GMP/Gmpq_type.h>
#include <CGAL/Coercion_traits.h>
@ -43,6 +44,7 @@ CGAL_DEFINE_COERCION_TRAITS_FOR_SELF(Gmpq)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(Gmpz,Gmpzf)
//CGAL_DEFINE_COERCION_TRAITS_FROM_TO(Gmpzf,Gmpzq); // todo
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(Gmpz,Gmpq)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(Gmpfr,Gmpq)
// The following definitions reflect the interaction of the Gmp number types
// with the built in types,

View File

@ -1,25 +1,25 @@
// Copyright (c) 2007-2009 Inria Lorraine (France). All rights reserved.
//
// Copyright (c) 2007-2010 Inria Lorraine (France). All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with CGAL.
//
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
//
// $URL$
// $Id$
//
//
// Author: Luis Peñaranda <luis.penaranda@loria.fr>
#ifndef CGAL_MPFI_COERCION_TRAITS_H
#define CGAL_MPFI_COERCION_TRAITS_H
//#ifdef CGAL_USE_MPFI
#ifdef CGAL_USE_MPFI
#include <CGAL/number_type_basic.h>
#include <CGAL/GMP/Gmpfr_type.h>
@ -46,7 +46,7 @@ CGAL_DEFINE_COERCION_TRAITS_FROM_TO(Gmpfr ,Gmpfi)
}
//#endif // CGAL_USE_MPFI
#endif // CGAL_USE_MPFI
#endif // CGAL_MPFI_COERCION_TRAITS_H
// vim: tabstop=8: softtabstop=8: smarttab: shiftwidth=8: expandtab

View File

@ -1,19 +1,19 @@
// Copyright (c) 2007-2009 Inria Lorraine (France). All rights reserved.
//
// Copyright (c) 2007-2010 Inria Lorraine (France). All rights reserved.
//
// This file is part of CGAL (www.cgal.org); you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; version 2.1 of the License.
// See the file LICENSE.LGPL distributed with CGAL.
//
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
//
// $URL$
// $Id$
//
//
// Author: Luis Peñaranda <luis.penaranda@loria.fr>
#ifndef CGAL_MPFR_COERCION_TRAITS_H
@ -40,7 +40,6 @@ CGAL_DEFINE_COERCION_TRAITS_FROM_TO(long double ,Gmpfr)
// coercion with gmp types
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(Gmpz ,Gmpfr)
CGAL_DEFINE_COERCION_TRAITS_FROM_TO(Gmpq ,Gmpfr)
}