blob: 4b906830606f83f1a2379d95c38e05a1778c973b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2016 CEA LIST.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Created on: 10 mai 2016
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and Implementation
******************************************************************************/
#ifndef FML_NUMERIC_GMP_RATIONALIMPL_H_
#define FML_NUMERIC_GMP_RATIONALIMPL_H_
#include <gmpxx.h>
#include <fml/numeric/Number.h>
#include <fml/numeric/Integer.h>
#include <cmath>
namespace sep
{
class Rational :
public Number,
public GenericNumberClass< mpq_class , Rational >
{
AVM_DECLARE_CLONABLE_CLASS( Rational )
/**
* TYPEDEF
*/
public:
typedef mpq_class RawValueType;
private:
typedef GenericNumberClass< RawValueType , Rational > ThisNumberClass;
public:
/**
* CONSTRUCTOR
* Default
*/
// RawValueType
Rational(const RawValueType & aValue)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( aValue )
{
simplif();
}
// mpq_t
Rational(const mpq_t & aValue)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType(aValue) )
{
simplif();
}
// Integer / Integer
Rational(const Integer & aNumerator, const Integer & aDenominator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType(
aNumerator.getValue(), aDenominator.getValue()) )
{
simplif();
}
// Integer::RawValueType / Integer::RawValueType
// i.e mpz_class / mpz_class
Rational(const Integer::RawValueType & aNumerator,
const Integer::RawValueType & aDenominator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType(aNumerator, aDenominator) )
{
simplif();
}
// mpz_t / mpz_t
Rational(const mpz_t & aNumerator, const mpz_t & aDenominator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType(
Integer::RawValueType(aNumerator),
Integer::RawValueType(aDenominator)) )
{
simplif();
}
// avm_integer_t / avm_integer_t i.e. avm_int64_t / avm_int64_t
Rational(avm_integer_t aNumerator, avm_integer_t aDenominator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType(
Integer( aNumerator ).getValue(),
Integer( aDenominator ).getValue() ) )
{
simplif();
}
// avm_integer_t / avm_uinteger_t i.e. avm_int64_t / avm_uint64_t
Rational(avm_integer_t aNumerator, avm_uinteger_t aDenominator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType(
Integer( aNumerator ).getValue(),
Integer( aDenominator ).getValue() ) )
{
simplif();
}
// avm_uinteger_t / avm_integer_t i.e. avm_uint64_t / avm_int64_t
Rational(avm_uinteger_t aNumerator, avm_integer_t aDenominator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType(
Integer( aNumerator ).getValue(),
Integer( aDenominator ).getValue() ) )
{
simplif();
}
// avm_uinteger_t / avm_uinteger_t i.e. avm_uint64_t / avm_uint64_t
Rational(avm_uinteger_t aNumerator, avm_uinteger_t aDenominator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType(
Integer( aNumerator ).getValue(),
Integer( aDenominator ).getValue() ) )
{
//!! NOTHING
}
// std::string / avm_integer_t i.e. std::string / avm_int64_t
Rational(const std::string & aNumerator, avm_integer_t aDenominator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType(
Integer( aNumerator ).getValue(),
Integer( aDenominator ).getValue() ) )
{
simplif();
}
// avm_integer_t / std::string i.e. avm_int64_t / std::string
Rational(avm_integer_t aNumerator, const std::string & aDenominator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType(
Integer( aNumerator ).getValue(),
Integer( aDenominator ).getValue() ) )
{
simplif();
}
// std::string / std::string
Rational(const std::string & aNumerator, const std::string & aDenominator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType(
Integer::RawValueType(aNumerator),
Integer::RawValueType(aDenominator) ) )
{
simplif();
}
// Integer
Rational(const Integer & aNumerator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType( aNumerator.getValue() ) )
{
simplif();
}
// Integer::RawValueType i.e. mpz_class
Rational(const Integer::RawValueType & aNumerator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType(aNumerator) )
{
simplif();
}
// mpz_t
Rational(const mpz_t & aNumerator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType( Integer::RawValueType(aNumerator) ) )
{
simplif();
}
// avm_integer_t i.e. avm_int64_t
Rational(avm_integer_t aNumerator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType( Integer( aNumerator ).getValue() ) )
{
simplif();
}
// avm_uinteger_t i.e. avm_uint64_t
Rational(avm_uinteger_t aNumerator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType( Integer( aNumerator ).getValue() ) )
{
simplif();
}
#ifdef _AVM_NEED_INT64_T_OVERLOADS_
// long
Rational(long aNumerator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType( Integer::RawValueType(aNumerator) ) )
{
simplif();
}
// unsigned long
Rational(unsigned long aNumerator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType( Integer::RawValueType(aNumerator) ) )
{
simplif();
}
#endif /* _AVM_NEED_INT64_T_OVERLOADS_ */
// int32_t
Rational(int aNumerator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType( Integer::RawValueType(aNumerator) ) )
{
simplif();
}
// uint32_t
Rational(unsigned int aNumerator)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType( Integer::RawValueType(aNumerator) ) )
{
simplif();
}
// std::string
Rational(const std::string & aRational)
: Number( CLASS_KIND_T( Rational ) ),
ThisNumberClass( RawValueType( ) )
{
fromString(ThisNumberClass::mValue, aRational);
simplif();
}
/**
* CONSTRUCTOR
* Copy
*/
Rational(const Rational & aRational)
: Number( aRational ),
ThisNumberClass( aRational )
{
simplif();
}
inline static void fromString(RawValueType & rop, const std::string & aValue)
{
std::string::size_type pos = aValue.find('/');
if( pos != std::string::npos)
{
rop = RawValueType( aValue );
}
else if( (pos = aValue.find('.')) != std::string::npos )
{
Integer aNumer( std::string(aValue).erase(pos, 1) );
Integer aDenom = Integer::pow(10, aValue.size() - (pos + 1));
rop = RawValueType( aNumer.getValue(), aDenom.getValue() );
}
else
{
rop = RawValueType( aValue );
}
}
/**
* DESTRUCTOR
*/
virtual ~Rational()
{
//!! NOTHING
}
/**
* GETTER - SETTER
* ThisNumberClass::mValue
*/
bool simplif()
{
ThisNumberClass::mValue.canonicalize();
return( true );
}
/**
* GETTER - SETTER
* ThisNumberClass::mValue
*/
inline Integer getNumerator() const
{
return( Integer( ThisNumberClass::mValue.get_num() ) );
}
inline Integer getDenominator() const
{
return( Integer( ThisNumberClass::mValue.get_den() ) );
}
inline const Integer::RawValueType & rawNumerator() const
{
return( ThisNumberClass::mValue.get_num() );
}
inline const Integer::RawValueType & rawDenominator() const
{
return( ThisNumberClass::mValue.get_den() );
}
inline void setValue(avm_integer_t aNumerator, avm_integer_t aDenominator)
{
ThisNumberClass::mValue = RawValueType(
Integer( aNumerator ).getValue(),
Integer( aDenominator ).getValue() );
}
inline void setValue(avm_integer_t aValue)
{
ThisNumberClass::mValue = RawValueType( Integer( aValue ).getValue() );
}
/**
* BASICS TESTS
*/
virtual inline int sign() const
{
return( mpq_sgn(ThisNumberClass::mValue.get_mpq_t()) );
}
virtual inline bool isZero() const
{
return( sign() == 0 );
}
virtual inline bool isOne() const
{
return( mpq_cmp_si(
ThisNumberClass::mValue.get_mpq_t(), 1, 1) == 0 );
}
virtual inline bool isNegativeOne() const
{
return( mpq_cmp_si(
ThisNumberClass::mValue.get_mpq_t(), -1, 1) == 0 );
}
/**
* CONVERSION
*/
#define MPQ_IS_INTEGER( MPQ_NUM, MPQ_DEN, INF, SUP) \
(mpz_cmp_si(MPQ_DEN.get_mpz_t(), 1 ) == 0) && \
(mpz_cmp_si(MPQ_NUM.get_mpz_t(), INF) >= 0) && \
(mpz_cmp_ui(MPQ_NUM.get_mpz_t(), SUP) <= 0)
#define MPQ_IS_POSITIVE_INTEGER(MPQ_NUM, MPQ_DEN, SUP) \
(sign() >= 0) && \
(mpz_cmp_si(MPQ_DEN.get_mpz_t(), 1 ) == 0) && \
(mpz_cmp_ui(MPQ_NUM.get_mpz_t(), MPQ_NUM.get_ui()) == 0) && \
(mpz_cmp_ui(MPQ_NUM.get_mpz_t(), SUP) <= 0)
inline virtual bool isInt32() const
{
return( MPQ_IS_INTEGER(rawNumerator(), rawDenominator(),
AVM_NUMERIC_MIN_INT32, AVM_NUMERIC_MAX_INT32) );
}
inline virtual avm_int32_t toInt32() const
{
return( static_cast< avm_int32_t >( rawNumerator().get_si() ) );
}
inline virtual bool isInt64() const
{
return( MPQ_IS_INTEGER(rawNumerator(), rawDenominator(),
AVM_NUMERIC_MIN_INT64, AVM_NUMERIC_MAX_INT64) );
}
inline virtual avm_int64_t toInt64() const
{
return( static_cast< avm_int64_t >( rawNumerator().get_si() ) );
}
inline virtual bool isInteger() const
{
return( MPQ_IS_INTEGER(rawNumerator(), rawDenominator(),
AVM_NUMERIC_MIN_INTEGER, AVM_NUMERIC_MAX_INTEGER) );
}
inline virtual avm_integer_t toInteger() const
{
return( rawNumerator().get_si() );
}
inline virtual bool isPosInteger() const
{
return( MPQ_IS_POSITIVE_INTEGER(rawNumerator(),
rawDenominator(), AVM_NUMERIC_MAX_UINTEGER) );
}
inline virtual bool isUInteger() const
{
return( MPQ_IS_POSITIVE_INTEGER(rawNumerator(),
rawDenominator(), AVM_NUMERIC_MAX_UINTEGER) );
}
inline virtual avm_uinteger_t toUInteger() const
{
return( static_cast< avm_uinteger_t >( rawNumerator().get_ui() ) );
}
inline virtual bool isRational() const
{
return( true );
}
virtual avm_integer_t toDenominator() const
{
return( rawDenominator().get_si() );
}
virtual avm_integer_t toNumerator() const
{
return( rawNumerator().get_si() );
}
inline virtual bool isFloat() const
{
return( true );
}
inline virtual avm_float_t toFloat() const
{
return( static_cast< avm_float_t >( ThisNumberClass::mValue.get_d() ) );
}
inline virtual bool isReal() const
{
return( true );
}
inline virtual avm_real_t toReal() const
{
return( static_cast< avm_real_t >( ThisNumberClass::mValue.get_d() ) );
}
/**
* math function
*/
inline void set_pow(avm_uinteger_t anExponent)
{
// RawValueType mpResult;
//
// mpq_pow_ui( mpResult.get_mpq_t(),
// ThisNumberClass::mValue.get_mpq_t(), anExponent );
//
// ThisNumberClass::mValue = mpResult;
mpz_pow_ui( mpq_numref(ThisNumberClass::mValue.get_mpq_t()),
mpq_numref(ThisNumberClass::mValue.get_mpq_t()), anExponent );
mpz_pow_ui( mpq_denref(ThisNumberClass::mValue.get_mpq_t()),
mpq_denref(ThisNumberClass::mValue.get_mpq_t()), anExponent );
}
/**
* Serialization
*/
inline void toStream(OutStream & os) const
{
os << TAB << rawNumerator();
if( rawDenominator() != 1 )
{
os << "/" << rawDenominator();
}
AVM_DEBUG_REF_COUNTER(os);
os << EOL_FLUSH;
}
virtual std::string str() const
{
if( rawDenominator() != 1 )
{
return( OSS() << rawNumerator() << '/' << rawDenominator() );
}
else
{
return( OSS() << rawNumerator() );
}
}
inline virtual std::string strNum(
avm_uint8_t precision = AVM_MUMERIC_PRECISION) const
{
if( rawDenominator() != 1 )
{
return( OSS() << rawNumerator() << '/' << rawDenominator() );
}
else
{
return( OSS() << rawNumerator() );
}
}
inline virtual std::string strNumerator(
avm_uint8_t precision = AVM_MUMERIC_PRECISION) const
{
return( OSS() << rawNumerator() );
}
inline virtual std::string strDenominator(
avm_uint8_t precision = AVM_MUMERIC_PRECISION) const
{
return( OSS() << rawDenominator() );
}
};
} /* namespace sep */
#endif /* FML_NUMERIC_GMP_RATIONALIMPL_H_ */