blob: 4018e0162248e545620375449e13c99995b214f9 [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: 1 mars 2012
*
* Contributors:
* Arnault Lapitre (CEA LIST) arnault.lapitre@cea.fr
* - Initial API and implementation
******************************************************************************/
#ifndef FML_EXPRESSION_NUMERIC_H_
#define FML_EXPRESSION_NUMERIC_H_
#include <base/ClassKindInfo.h>
#include <base/SmartPointer.h>
#include <fml/numeric/Number.h>
#include <util/avm_assert.h>
#include <common/BF.h>
#if defined( _AVM_BUILTIN_NUMERIC_GMP_ )
#include <fml/numeric/gmp/NumericImpl.h>
#elif defined( _AVM_BUILTIN_NUMERIC_BOOST_ )
#include <fml/numeric/boost/NumericImpl.h>
#else
#include <fml/numeric/basic/NumericImpl.h>
#endif /* _AVM_BUILTIN_NUMERIC_GMP_ */
#include <fml/numeric/Integer.h>
#include <fml/numeric/Rational.h>
#include <fml/numeric/Float.h>
namespace sep
{
class Operator;
class Numeric :
public SmartPointer< Number , DestroyElementPolicy >,
AVM_INJECT_INSTANCE_COUNTER_CLASS( Numeric )
{
private:
/**
* TYPEDEF
*/
typedef SmartPointer< Number , DestroyElementPolicy > base_this_type;
public:
/**
* CONSTRUCTOR
* Default
*/
Numeric()
: base_this_type( )
{
//!! NOTHING
}
Numeric(Number * aNumber)
: base_this_type( aNumber )
{
//!! NOTHING
}
Numeric(const Integer & aNumber)
: base_this_type( new Integer(aNumber) )
{
//!! NOTHING
}
Numeric(Integer * aNumber)
: base_this_type( aNumber )
{
//!! NOTHING
}
Numeric(const Rational & aNumber)
: base_this_type( new Rational(aNumber) )
{
//!! NOTHING
}
Numeric(Rational * aNumber)
: base_this_type( aNumber )
{
//!! NOTHING
}
Numeric(const Float & aNumber)
: base_this_type( new Float(aNumber) )
{
//!! NOTHING
}
Numeric(Float * aNumber)
: base_this_type( aNumber )
{
//!! NOTHING
}
/**
* CONSTRUCTOR
* Builtin
*/
// // avm_int8_t
// Numeric(avm_int8_t aNumber)
// : base_this_type( new Integer( aNumber ) )
// {
// //!! NOTHING
// }
//
// // avm_uint8_t
// Numeric(avm_uint8_t aNumber)
// : base_this_type( new Integer( aNumber ) )
// {
// //!! NOTHING
// }
//
// // avm_int16_t
// Numeric(avm_int16_t aNumber)
// : base_this_type( new Integer( aNumber ) )
// {
// //!! NOTHING
// }
//
// // avm_uint16_t
// Numeric(avm_uint16_t aNumber)
// : base_this_type( new Integer( aNumber ) )
// {
// //!! NOTHING
// }
//
// // avm_int32_t
// Numeric(avm_int32_t aNumber)
// : base_this_type( new Integer( aNumber ) )
// {
// //!! NOTHING
// }
//
// // avm_uint32_t
// Numeric(avm_uint32_t aNumber)
// : base_this_type( new Integer( aNumber ) )
// {
// //!! NOTHING
// }
// int
Numeric(int aNumber)
: base_this_type( new Integer( aNumber ) )
{
//!! NOTHING
}
// uint32_t
Numeric(unsigned int aNumber)
: base_this_type( new Integer( aNumber ) )
{
//!! NOTHING
}
#ifdef _AVM_NEED_INT64_T_OVERLOADS_
// long
Numeric(long aNumber)
: base_this_type( new Integer( aNumber ) )
{
//!! NOTHING
}
// unsigned long
Numeric(unsigned long aNumber)
: base_this_type( new Integer( aNumber ) )
{
//!! NOTHING
}
#endif /* _AVM_NEED_INT64_T_OVERLOADS_ */
// avm_integer_t i.e. avm_int64_t
Numeric(avm_integer_t aNumber)
: base_this_type( new Integer( aNumber ) )
{
//!! NOTHING
}
Numeric(avm_uinteger_t aNumber)
: base_this_type( new Integer( aNumber ) )
{
//!! NOTHING
}
// Integer / Integer
Numeric(const Integer & aNumerator, const Integer & aDenominator)
: base_this_type( new Rational(aNumerator, aDenominator) )
{
//!! NOTHING
}
// avm_integer_t / avm_integer_t i.e. avm_int64_t / avm_int64_t
Numeric(avm_integer_t aNumerator, avm_integer_t aDenominator)
: base_this_type( new Rational(aNumerator, aDenominator) )
{
//!! NOTHING
}
// avm_uinteger_t / avm_integer_t i.e. avm_uint64_t / avm_int64_t
Numeric(avm_uinteger_t aNumerator, avm_integer_t aDenominator)
: base_this_type( new Rational(aNumerator, aDenominator) )
{
//!! NOTHING
}
// avm_integer_t / avm_uinteger_t i.e. avm_int64_t / avm_uint64_t
Numeric(avm_integer_t aNumerator, avm_uinteger_t aDenominator)
: base_this_type( new Rational(aNumerator, aDenominator) )
{
//!! NOTHING
}
// std::string / avm_integer_t i.e. std::string / avm_int64_t
Numeric(const std::string & aNumerator, avm_integer_t aDenominator)
: base_this_type( new Rational(aNumerator, aDenominator) )
{
//!! NOTHING
}
// avm_integer_t / std::string i.e. avm_integer_t / std::string
Numeric(avm_integer_t aNumerator, const std::string & aDenominator)
: base_this_type( new Rational(aNumerator, aDenominator) )
{
//!! NOTHING
}
// std::string / std::string
Numeric(const std::string & aNumerator, const std::string & aDenominator)
: base_this_type( new Rational(aNumerator, aDenominator) )
{
//!! NOTHING
}
// float
Numeric(float aNumber)
: base_this_type( new Float( aNumber ) )
{
//!! NOTHING
}
// avm_float_t i.e. double
Numeric(avm_float_t aNumber)
: base_this_type( new Float( aNumber ) )
{
//!! NOTHING
}
// const std::string &
Numeric(const std::string & aNumber)
: base_this_type( )
{
setStringNumber( aNumber );
}
inline void setStringNumber(const std::string & aNumber)
{
std::string::size_type pos = aNumber.find('/');
if( pos != std::string::npos)
{
release( new Rational(
aNumber.substr(0, pos), aNumber.substr(pos+1) ) );
}
else if( (pos = aNumber.find('.')) != std::string::npos )
{
release( new Float( aNumber ) );
// replacePointer( new Rational(
// std::string(aNumber).erase(pos, 1),
// Integer::pow(10, aNumber.size() - (pos + 1)) ) );
}
else
{
release( new Integer( aNumber ) );
}
}
/**
* CONSTRUCTOR
* Copy
*/
Numeric(const Numeric & aNumeric)
: base_this_type( aNumeric )
{
//!! NOTHING
}
/**
* DESTRUCTOR
*/
virtual ~Numeric()
{
//!! NOTHING
}
/**
* ACQUIRE POINTER
*/
static Numeric acquire(Number * aNumber)
{
AVM_OS_ASSERT_FATAL_NULL_POINTER_EXIT( aNumber )
<< "Number in Numeric::acquire() !!!"
<< SEND_EXIT;
aNumber->incrRefCount();
return( Numeric( aNumber ) );
}
/**
* GETTER
* ClassKindInfo
*/
inline class_kind_t classKind() const
{
AVM_OS_ASSERT_FATAL_NULL_POINTER_EXIT( mPTR )
<< "raw_pointer in Numeric::classKind() !!!"
<< SEND_EXIT;
return( mPTR->classKind() );
}
inline const std::string & classKindName() const
{
AVM_OS_ASSERT_FATAL_NULL_POINTER_EXIT( mPTR )
<< "raw_pointer in Numeric::classKindName() !!!"
<< SEND_EXIT;
return( mPTR->classKindName() );
}
inline std::string classKindInfo() const
{
AVM_OS_ASSERT_FATAL_NULL_POINTER_EXIT( mPTR )
<< "raw_pointer in Numeric::classKindInfo() !!!"
<< SEND_EXIT;
return( mPTR->classKindInfo() );
}
// Check if Numeric is a handle to a T, including base classes.
template<class T >
inline bool is() const
{
return( (mPTR != NULL) && mPTR->is< T >() );
}
template< class T >
inline const T & to_ref() const
{
return( mPTR->to_ref< T >() );
}
/**
* operator= <expression>
*/
inline Numeric & operator=(const BF & anExpression)
{
if( mPTR != anExpression.raw_pointer() )
{
AVM_OS_ASSERT_FATAL_ERROR_EXIT( anExpression.is< Number >() )
<< "Invalid Assignment Cast of a <BF> to a <Numeric> !!!"
<< SEND_EXIT;
release_acquire( anExpression.to_ptr< Number >() );
}
return( *this );
}
/**
* operator=
*/
// Integer
inline Numeric & operator=(const Integer & aNumber)
{
return( this->operator=( Numeric( aNumber ) ) );
}
// Rational
inline Numeric & operator=(const Rational & aNumber)
{
return( this->operator=( Numeric( aNumber ) ) );
}
// Float
inline Numeric & operator=(const Float & aNumber)
{
return( this->operator=( Numeric( aNumber ) ) );
}
// // avm_int8_t
// inline Numeric & operator=(avm_int8_t aNumber)
// {
// return( this->operator=( Numeric( aNumber ) ) );
// }
//
// // avm_uint8_t
// inline Numeric & operator=(avm_uint8_t aNumber)
// {
// return( this->operator=( Numeric( aNumber ) ) );
// }
//
// // avm_int16_t
// inline Numeric & operator=(avm_int16_t aNumber)
// {
// return( this->operator=( Numeric( aNumber ) ) );
// }
//
// // avm_uint16_t
// inline Numeric & operator=(avm_uint16_t aNumber)
// {
// return( this->operator=( Numeric( aNumber ) ) );
// }
//
// // avm_int32_t
// inline Numeric & operator=(avm_int32_t aNumber)
// {
// return( this->operator=( Numeric( aNumber ) ) );
// }
//
// // avm_uint32_t
// inline Numeric & operator=(avm_uint32_t aNumber)
// {
// return( this->operator=( Numeric( aNumber ) ) );
// }
// int
inline Numeric & operator=(int aNumber)
{
return( this->operator=( Numeric( aNumber ) ) );
}
// unsigned int
inline Numeric & operator=(unsigned int aNumber)
{
return( this->operator=( Numeric( aNumber ) ) );
}
#ifdef _AVM_NEED_INT64_T_OVERLOADS_
// long
inline Numeric & operator=(long aNumber)
{
return( this->operator=( Numeric( aNumber ) ) );
}
// unsigned long
inline Numeric & operator=(unsigned long aNumber)
{
return( this->operator=( Numeric( aNumber ) ) );
}
#endif /* _AVM_NEED_INT64_T_OVERLOADS_ */
// avm_integer_t
inline Numeric & operator=(avm_integer_t aNumber)
{
return( this->operator=( Numeric( aNumber ) ) );
}
// avm_uinteger_t
inline Numeric & operator=(avm_uinteger_t aNumber)
{
return( this->operator=( Numeric( aNumber ) ) );
}
// float
inline Numeric & operator=(float aNumber)
{
return( this->operator=( Numeric( aNumber ) ) );
}
// avm_float_t i.e. double
inline Numeric & operator=(avm_float_t aNumber)
{
return( this->operator=( Numeric( aNumber ) ) );
}
// const std::string &
inline Numeric & operator=(const std::string & aNumber)
{
return( this->operator=( Numeric( aNumber ) ) );
}
/**
* SIGN TESTS
*/
inline int sign() const
{
return( mPTR->sign() );
}
inline bool isPositive() const
{
return( mPTR->isPositive() );
}
inline bool strictlyPositive() const
{
return( mPTR->strictlyPositive() );
}
inline bool isNegative() const
{
return( mPTR->isNegative() );
}
inline bool strictlyNegative() const
{
return( mPTR->strictlyNegative() );
}
/**
* BASICS TESTS
*/
inline bool isZero() const
{
return( mPTR->isZero() );
}
inline bool isOne() const
{
return( mPTR->isOne() );
}
inline bool isNegativeOne() const
{
return( mPTR->isNegativeOne() );
}
/**
* CONVERSION
*/
// Int32
inline bool isInt32() const
{
return( mPTR->isInt32() );
}
inline avm_int32_t toInt32() const
{
return( mPTR->toInt32() );
}
// Int64
inline bool isInt64() const
{
return( mPTR->isInt64() );
}
inline avm_int64_t toInt64() const
{
return( mPTR->toInt64() );
}
// Integer
inline bool isInteger() const
{
return( mPTR->isInteger() );
}
inline avm_integer_t toInteger() const
{
return( mPTR->toInteger() );
}
// Rational
inline bool isRational() const
{
return( mPTR->sign() );
}
inline avm_integer_t toDenominator() const
{
return( mPTR->sign() );
}
inline avm_integer_t toNumerator() const
{
return( mPTR->sign() );
}
// Float
inline bool isFloat() const
{
return( mPTR->sign() );
}
inline avm_float_t toFloat() const
{
return( mPTR->sign() );
}
// Real
inline bool isReal() const
{
return( mPTR->sign() );
}
inline avm_real_t toReal() const
{
return( mPTR->sign() );
}
/**
* POINTER TRIVIALLY EQUAL COMPARISON
*/
inline bool isTEQ(const Numeric & aNumeric) const
{
return( mPTR == aNumeric.mPTR );
}
inline bool isTEQ(const Number & aNumber) const
{
return( mPTR == &aNumber );
}
inline bool isTEQ(const Number * aNumber) const
{
return( mPTR == aNumber );
}
inline bool isTEQ(const BF & anExpression) const
{
return( mPTR == anExpression.raw_pointer() );
}
inline bool isNTEQ(const Numeric & aNumeric) const
{
return( mPTR != aNumeric.mPTR );
}
inline bool isNTEQ(const Number & aNumber) const
{
return( mPTR != (& aNumber) );
}
inline bool isNTEQ(const Number * aNumber) const
{
return( mPTR != aNumber );
}
inline bool isNTEQ(const BF & anExpression) const
{
return( mPTR != anExpression.raw_pointer() );
}
/**
* COMPARISON
*/
inline bool isEQ(const Numeric & aNumeric) const
{
return( this->operator==( aNumeric ) );
}
inline bool isEQ(const Number & aNumber) const
{
return( this->operator==( aNumber ) );
}
inline bool isEQ(const BF & anExpression) const
{
return( this->operator==( anExpression.as_ref< Number >() ) );
}
inline bool isNEQ(const Numeric & aNumeric) const
{
return( this->operator!=( aNumeric ) );
}
inline bool isNEQ(const Number & aNumber) const
{
return( this->operator!=( aNumber ) );
}
inline bool isNEQ(const BF & anExpression) const
{
return( this->operator!=( anExpression.as_ref< Number >() ) );
}
inline bool strEQ(const Numeric & aNumeric) const
{
return( this->operator==( aNumeric ) );
}
inline bool strEQ(const Number & aNumber) const
{
return( this->operator==( aNumber ) );
}
inline bool strEQ(const BF & anExpression) const
{
return( this->operator==( anExpression.as_ref< Number >() ) );
}
inline bool strNEQ(const Numeric & aNumeric) const
{
return( this->operator!=( aNumeric ) );
}
inline bool strNEQ(const Number & aNumber) const
{
return( this->operator!=( aNumber ) );
}
inline bool strNEQ(const BF & anExpression) const
{
return( this->operator!=( anExpression.as_ref< Number >() ) );
}
////////////////////////////////////////////////////////////////////////////////
// bool operator...
////////////////////////////////////////////////////////////////////////////////
#define BOOL_OPERATION_AUX(op, number, numeric) \
switch( numeric.classKind() ) \
{ \
case FORM_BUILTIN_INTEGER_KIND: \
return( op(number, numeric.to_ref< Integer >()) ); \
case FORM_BUILTIN_RATIONAL_KIND: \
return( op(number, numeric.to_ref< Rational >()) ); \
case FORM_BUILTIN_FLOAT_KIND: \
return( op(number, numeric.to_ref< Float >()) ); \
default: \
{ \
AVM_OS_FATAL_ERROR_EXIT << "Unexpected a <Numeric> type info << " \
<< numeric.classKindInfo() << " >> !!!" << SEND_EXIT; \
return( false ); \
} \
}
#define BOOL_OPERATION(op, N1, N2) \
switch( N1.classKind() ) \
{ \
case FORM_BUILTIN_INTEGER_KIND: \
BOOL_OPERATION_AUX(op, N1.to_ref< Integer >(), N2) \
case FORM_BUILTIN_RATIONAL_KIND: \
BOOL_OPERATION_AUX(op, N1.to_ref< Rational >(), N2) \
case FORM_BUILTIN_FLOAT_KIND: \
BOOL_OPERATION_AUX(op, N1.to_ref< Float >(), N2) \
default: \
{ \
AVM_OS_FATAL_ERROR_EXIT << "Unexpected a <Numeric> type info << " \
<< N1.classKindInfo() << " >> !!!" << SEND_EXIT; \
return( false ); \
} \
}
/**
* compare
*/
int compare(const Numeric & aNumeric) const
{
if( mPTR == aNumeric.mPTR )
{
return( 0 );
}
BOOL_OPERATION( sep::numeric::compare , (*this) , aNumeric )
}
int compare(const Number & aNumber) const
{
if( mPTR == (& aNumber) )
{
return( 0 );
}
BOOL_OPERATION( sep::numeric::compare , (*this) , aNumber )
}
int compare(const BF & anExpression) const
{
if( mPTR == anExpression.raw_pointer() )
{
return( 0 );
}
BOOL_OPERATION( sep::numeric::compare ,
(*this) , anExpression.as_ref< Number >() )
}
/**
* operator==
*/
inline bool operator==(const Numeric & aNumeric) const
{
if( mPTR == aNumeric.mPTR )
{
return( true );
}
BOOL_OPERATION( sep::numeric::operator== , (*this) , aNumeric )
}
inline bool operator==(const Number & aNumber) const
{
if( mPTR == (& aNumber) )
{
return( true );
}
BOOL_OPERATION( sep::numeric::operator== , (*this) , aNumber )
}
inline bool operator==(const BF & anExpression) const
{
if( mPTR == anExpression.raw_pointer() )
{
return( true );
}
BOOL_OPERATION( sep::numeric::operator== ,
(*this) , anExpression.as_ref< Number >() )
}
/**
* operator!=
*/
inline bool operator!=(const Numeric & aNumeric) const
{
if( mPTR == aNumeric.mPTR )
{
return( false );
}
BOOL_OPERATION( sep::numeric::operator!= , (*this) , aNumeric )
}
inline bool operator!=(const Number & aNumber) const
{
if( mPTR == (& aNumber) )
{
return( false );
}
BOOL_OPERATION( sep::numeric::operator!= , (*this) , aNumber )
}
inline bool operator!=(const BF & anExpression) const
{
if( mPTR == anExpression.raw_pointer() )
{
return( false );
}
BOOL_OPERATION( sep::numeric::operator!= ,
(*this) , anExpression.as_ref< Number >() )
}
/**
* operator<
*/
inline bool operator<(const Numeric & aNumeric) const
{
if( mPTR == aNumeric.mPTR )
{
return( false );
}
BOOL_OPERATION( sep::numeric::operator< , (*this) , aNumeric )
}
inline bool operator<(const Number & aNumber) const
{
if( mPTR == (& aNumber) )
{
return( false );
}
BOOL_OPERATION( sep::numeric::operator< , (*this) , aNumber )
}
inline bool operator<(const BF & anExpression) const
{
if( mPTR == anExpression.raw_pointer() )
{
return( false );
}
BOOL_OPERATION( sep::numeric::operator< ,
(*this) , anExpression.as_ref< Number >() )
}
/**
* operator<=
*/
inline bool operator<=(const Numeric & aNumeric) const
{
if( mPTR == aNumeric.mPTR )
{
return( true );
}
BOOL_OPERATION( sep::numeric::operator<= , (*this) , aNumeric )
}
inline bool operator<=(const Number & aNumber) const
{
if( mPTR == (& aNumber) )
{
return( true );
}
BOOL_OPERATION( sep::numeric::operator<= , (*this) , aNumber )
}
inline bool operator<=(const BF & anExpression) const
{
if( mPTR == anExpression.raw_pointer() )
{
return( true );
}
BOOL_OPERATION( sep::numeric::operator<= ,
(*this) , anExpression.as_ref< Number >() )
}
/**
* operator>
*/
inline bool operator>(const Numeric & aNumeric) const
{
if( mPTR == aNumeric.mPTR )
{
return( false );
}
BOOL_OPERATION( sep::numeric::operator> , (*this) , aNumeric )
}
inline bool operator>(const Number & aNumber) const
{
if( mPTR == (& aNumber) )
{
return( false );
}
BOOL_OPERATION( sep::numeric::operator> , (*this) , aNumber )
}
inline bool operator>(const BF & anExpression) const
{
if( mPTR == anExpression.raw_pointer() )
{
return( false );
}
BOOL_OPERATION( sep::numeric::operator> ,
(*this) , anExpression.as_ref< Number >() )
}
/**
* operator>=
*/
inline bool operator>=(const Numeric & aNumeric) const
{
if( mPTR == aNumeric.mPTR )
{
return( true );
}
BOOL_OPERATION( sep::numeric::operator>= , (*this) , aNumeric )
}
inline bool operator>=(const Number & aNumber) const
{
if( mPTR == (& aNumber) )
{
return( true );
}
BOOL_OPERATION( sep::numeric::operator>= , (*this) , aNumber )
}
inline bool operator>=(const BF & anExpression) const
{
if( mPTR == anExpression.raw_pointer() )
{
return( true );
}
BOOL_OPERATION( sep::numeric::operator>= ,
(*this) , anExpression.as_ref< Number >() )
}
////////////////////////////////////////////////////////////////////////////////
// Numeric operator...
////////////////////////////////////////////////////////////////////////////////
#define ARITHMETIC_OPERATION_AUX(op, number, numeric) \
switch( numeric.classKind() ) \
{ \
case FORM_BUILTIN_INTEGER_KIND: \
return( Numeric( op(number, numeric.to_ref< Integer >()) ) ); \
case FORM_BUILTIN_RATIONAL_KIND: \
return( Numeric( op(number, numeric.to_ref< Rational >()) ) ); \
case FORM_BUILTIN_FLOAT_KIND: \
return( Numeric( op(number, numeric.to_ref< Float >()) ) ); \
default: \
{ \
AVM_OS_FATAL_ERROR_EXIT << "Unexpected a <Numeric> type info << " \
<< numeric.classKindInfo() << " >> !!!" << SEND_EXIT; \
return( Numeric(0) ); \
} \
}
#define ARITHMETIC_OPERATION(op, N1, N2) \
switch( N1.classKind() ) \
{ \
case FORM_BUILTIN_INTEGER_KIND: \
ARITHMETIC_OPERATION_AUX(op, N1.to_ref< Integer >(), N2) \
case FORM_BUILTIN_RATIONAL_KIND: \
ARITHMETIC_OPERATION_AUX(op, N1.to_ref< Rational >(), N2) \
case FORM_BUILTIN_FLOAT_KIND: \
ARITHMETIC_OPERATION_AUX(op, N1.to_ref< Float >(), N2) \
default: \
{ \
AVM_OS_FATAL_ERROR_EXIT << "Unexpected a <Numeric> type info << " \
<< N1.classKindInfo() << " >> !!!" << SEND_EXIT; \
return( Numeric(0) ); \
} \
}
#define ARITHMETIC_UNARY_OPERATION(op, N) \
switch( N.classKind() ) \
{ \
case FORM_BUILTIN_INTEGER_KIND: \
return( Numeric( op(N.to_ref< Integer >()) ) ); \
case FORM_BUILTIN_RATIONAL_KIND: \
return( Numeric( op(N.to_ref< Rational >()) ) ); \
case FORM_BUILTIN_FLOAT_KIND: \
return( Numeric( op(N.to_ref< Float >()) ) ); \
default: \
{ \
AVM_OS_FATAL_ERROR_EXIT << "Unexpected a <Numeric> type info << " \
<< N.classKindInfo() << " >> !!!" << SEND_EXIT; \
return( Numeric(0) ); \
} \
}
#define ARITHMETIC_OPERATION_NUM(op, numeric, number) \
switch( numeric.classKind() ) \
{ \
case FORM_BUILTIN_INTEGER_KIND: \
return( Numeric( op(numeric.to_ref< Integer >(), number) ) ); \
case FORM_BUILTIN_RATIONAL_KIND: \
return( Numeric( op(numeric.to_ref< Rational >(), number) ) ); \
case FORM_BUILTIN_FLOAT_KIND: \
return( Numeric( op(numeric.to_ref< Float >(), number) ) ); \
default: \
{ \
AVM_OS_FATAL_ERROR_EXIT << "Unexpected a <Numeric> type info << " \
<< numeric.classKindInfo() << " >> !!!" << SEND_EXIT; \
return( Numeric(0) ); \
} \
}
/**
* operator+
*/
inline Numeric operator+(const Numeric & aNumeric) const
{
if( aNumeric.isZero() )
{
return( *this );
}
ARITHMETIC_OPERATION( sep::numeric::operator+ , (*this) , aNumeric )
}
inline Numeric operator+(const Number & aNumber) const
{
if( aNumber.isZero() )
{
return( *this );
}
ARITHMETIC_OPERATION( sep::numeric::operator+ , (*this) , aNumber )
}
inline Numeric operator+(const BF & anExpression) const
{
return( this->operator+( anExpression.as_ref< Number >() ) );
}
// operator+=
inline Numeric & operator+=(const Numeric & aNumeric)
{
this->operator=( this->operator+( aNumeric ) );
return( *this );
}
inline Numeric & operator+=(const BF & anExpression)
{
this->operator=( this->operator+( anExpression ) );
return( *this );
}
/**
* operator++
*/
inline Numeric operator++()
{
this->operator=( this->operator+( Integer(1) ) );
return( *this );
}
inline Numeric operator++(int)
{
Numeric tmp( *this );
this->operator=( this->operator+( Integer(1) ) );
return( tmp );
}
/**
* operator-
*/
inline Numeric operator-() const
{
ARITHMETIC_UNARY_OPERATION( sep::numeric::operator- , (*this) )
}
/**
* operator--
*/
inline Numeric operator--()
{
this->operator=( this->operator-( Integer(1) ) );
return( *this );
}
inline Numeric operator--(int)
{
Numeric tmp( *this );
this->operator=( this->operator-( Integer(1) ) );
return( tmp );
}
/**
* operator-
*/
inline Numeric operator-(const Numeric & aNumeric) const
{
if( aNumeric.isZero() )
{
return( *this );
}
ARITHMETIC_OPERATION( sep::numeric::operator- , (*this) , aNumeric )
}
inline Numeric operator-(const Number & aNumber) const
{
if( aNumber.isZero() )
{
return( *this );
}
ARITHMETIC_OPERATION( sep::numeric::operator- , (*this) , aNumber )
}
inline Numeric operator-(const BF & anExpression) const
{
return( this->operator-( anExpression.as_ref< Number >() ) );
}
// operator-=
inline Numeric & operator-=(const Numeric & aNumeric)
{
this->operator=( this->operator-( aNumeric ) );
return( *this );
}
inline Numeric & operator-=(const BF & anExpression)
{
this->operator=( this->operator-( anExpression ) );
return( *this );
}
/**
* operator*
*/
inline Numeric operator*(const Numeric & aNumeric) const
{
if( aNumeric.isOne() )
{
return( *this );
}
ARITHMETIC_OPERATION( sep::numeric::operator* , (*this) , aNumeric )
}
inline Numeric operator*(const Number & aNumber) const
{
if( aNumber.isOne() )
{
return( *this );
}
ARITHMETIC_OPERATION( sep::numeric::operator* , (*this) , aNumber )
}
inline Numeric operator*(const BF & anExpression) const
{
return( this->operator*( anExpression.as_ref< Number >() ) );
}
// operator*=
inline Numeric & operator*=(const Numeric & aNumeric)
{
this->operator=( this->operator*( aNumeric ) );
return( *this );
}
inline Numeric & operator*=(const BF & anExpression)
{
this->operator=( this->operator*( anExpression ) );
return( *this );
}
/**
* operator/
*/
inline Numeric operator/(const Numeric & aNumeric) const
{
if( aNumeric.isOne() )
{
return( *this );
}
ARITHMETIC_OPERATION( sep::numeric::operator/ , (*this) , aNumeric )
}
inline Numeric operator/(const Number & aNumber) const
{
if( aNumber.isOne() )
{
return( *this );
}
ARITHMETIC_OPERATION( sep::numeric::operator/ , (*this) , aNumber )
}
inline Numeric operator/(const BF & anExpression) const
{
return( this->operator/( anExpression.as_ref< Number >() ) );
}
// operator/=
inline Numeric & operator/=(const Numeric & aNumeric)
{
this->operator=( this->operator/( aNumeric ) );
return( *this );
}
inline Numeric & operator/=(const BF & anExpression)
{
this->operator=( this->operator/( anExpression ) );
return( *this );
}
/**
* COMPARISON OPERATION
*/
inline bool eq(const Numeric & arg)
{
return( this->operator==( arg ) );
}
inline bool neq(const Numeric & arg)
{
return( this->operator!=( arg ) );
}
inline bool lt(const Numeric & arg)
{
return( this->operator<( arg ) );
}
inline bool lte(const Numeric & arg)
{
return( this->operator<=( arg ) );
}
inline bool gt(const Numeric & arg)
{
return( this->operator>( arg ) );
}
inline bool gte(const Numeric & arg)
{
return( this->operator>=( arg ) );
}
/**
* ARITHMETIC OPERATION
*/
inline Numeric add(const Numeric & arg)
{
return( this->operator+( arg ) );
}
inline Numeric incr(avm_uinteger_t val = 1)
{
return( this->operator+( Integer(val) ) );
}
inline Numeric minus(const Numeric & arg)
{
return( this->operator-( arg ) );
}
inline Numeric uminus()
{
return( this->operator-() );
}
inline Numeric decr(avm_uinteger_t val = 1)
{
return( this->operator-( Integer(val) ) );
}
inline Numeric mult(const Numeric & arg)
{
return( this->operator*( arg ) );
}
inline Numeric pow(avm_uinteger_t anExponent)
{
ARITHMETIC_OPERATION_NUM( sep::numeric::pow , (*this) , anExponent )
}
inline Numeric div(const Numeric & arg)
{
return( this->operator/( arg ) );
}
inline Numeric inv()
{
ARITHMETIC_UNARY_OPERATION( sep::numeric::inverse , (*this) )
}
/**
* Serialization
*/
inline void toStream(OutStream & os) const
{
AVM_OS_ASSERT_FATAL_NULL_POINTER_EXIT( mPTR )
<< "raw_pointer in Numeric::toStream(OutStream &) !!!"
<< SEND_EXIT;
mPTR->toStream( os );
}
inline void toStream(PairOutStream & os) const
{
AVM_OS_ASSERT_FATAL_NULL_POINTER_EXIT( mPTR )
<< "raw_pointer in Numeric::toStream(PairOutStream &) !!!"
<< SEND_EXIT;
mPTR->toStream( os.OS1 );
mPTR->toStream( os.OS2 );
}
inline void toStream(TripleOutStream & os) const
{
AVM_OS_ASSERT_FATAL_NULL_POINTER_EXIT( mPTR )
<< "raw_pointer in Numeric::toStream(TripleOutStream &) !!!"
<< SEND_EXIT;
mPTR->toStream( os.OS1 );
mPTR->toStream( os.OS2 );
mPTR->toStream( os.OS3 );
}
inline std::string toString(
const AvmIndent & indent = AVM_TAB_INDENT) const
{
StringOutStream oss(indent);
toStream( oss );
return( oss.str() );
}
inline std::string str() const
{
AVM_OS_ASSERT_FATAL_NULL_POINTER_EXIT( mPTR )
<< "raw_pointer in Numeric::str() !!!"
<< SEND_EXIT;
return( mPTR->str() );
}
};
/**
* operator<<
*/
AVM_OS_STREAM( Numeric )
inline OutStream & operator<<(OutStream & os, const Integer & aNumber)
{
aNumber.toStream( os );
return( os );
}
/**
* Serialization
*/
inline OutStream & operator<<(OutStream & os, const Rational & aNumber)
{
aNumber.toStream( os );
return( os );
}
/**
* Serialization
*/
inline OutStream & operator<<(OutStream & os, const Float & aNumber)
{
aNumber.toStream( os );
return( os );
}
} /* namespace sep */
#endif /* FML_EXPRESSION_NUMERIC_H_ */