You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
434 lines
13 KiB
C++
434 lines
13 KiB
C++
9 years ago
|
#ifndef QDECNUMBER_HH
|
||
|
#define QDECNUMBER_HH
|
||
|
|
||
|
/** \file QDecNumber.hh
|
||
|
* Declarations for the class QDecNumber.
|
||
|
*
|
||
|
* (C) Copyright by Semih Cemiloglu
|
||
|
* All rights reserved, see COPYRIGHT file for details.
|
||
|
*
|
||
|
* $Id$
|
||
|
*
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
#include <QByteArray>
|
||
|
#include <QMetaType>
|
||
|
|
||
|
#include "QDecFwd.hh"
|
||
|
#include "QDecContext.hh"
|
||
|
|
||
|
// FORWARDS
|
||
|
QT_BEGIN_NAMESPACE
|
||
|
class QTextStream;
|
||
|
QT_END_NAMESPACE
|
||
|
|
||
|
|
||
|
/*!
|
||
|
\class QDecNumber
|
||
|
QDecNumber encapsulates decNumber and reimplements global functions
|
||
|
that operates upon decNumber as member functions with the same name.
|
||
|
decNumber module uses an arbitrary-precision decimal number representation
|
||
|
designed for efficient computation in software and implements the
|
||
|
arithmetic and logical operations, together with a number of conversions
|
||
|
and utilities. Once a number is held as a decNumber, no further conversions
|
||
|
are necessary to carry out arithmetic.
|
||
|
The decNumber representation is variable-length and machine-dependent
|
||
|
(for example, it contains integers which may be big-endian or little-endian).
|
||
|
*/
|
||
|
class QDECIMAL_EXPORT QDecNumber
|
||
|
{
|
||
|
// MEMBERS
|
||
|
//! Embedded decNumber structure
|
||
|
decNumber m_data;
|
||
|
|
||
|
public:
|
||
|
// TYPES
|
||
|
typedef decNumber* decNumberPtr_t;
|
||
|
enum {
|
||
|
MaxStrSize = QDECMAXSTRSIZE
|
||
|
};
|
||
|
|
||
|
// CREATORS
|
||
|
//! Default constructor
|
||
|
QDecNumber() { decNumberZero(&m_data); }
|
||
|
|
||
|
// Constructors using decNumber structure
|
||
|
QDecNumber(const decNumber& d) : m_data(d) {}
|
||
|
QDecNumber(const decNumber* p) : m_data(*p) {}
|
||
|
|
||
|
// Conversion constructors using simple types
|
||
|
QDecNumber(const char* str) { fromString(str); }
|
||
|
// m_data must have space for the digits needed to represent
|
||
|
// the value of val, which may need up to ten digits.
|
||
|
QDecNumber(uint32_t val) { fromUInt32(val); }
|
||
|
QDecNumber(int32_t val) { fromInt32(val); }
|
||
|
QDecNumber(double d) { fromDouble(d); }
|
||
|
|
||
|
// Conversion constructors using composite types
|
||
|
QDecNumber(const QDecSingle& s);
|
||
|
QDecNumber(const QDecDouble& d);
|
||
|
QDecNumber(const QDecQuad& q);
|
||
|
QDecNumber(const QDecPacked& p);
|
||
|
|
||
|
//! Copy constructor
|
||
|
QDecNumber(const QDecNumber& o)
|
||
|
{ decNumberCopy(&m_data, &o.m_data); }
|
||
|
|
||
|
//! Copy assignment
|
||
|
QDecNumber& operator=(const QDecNumber& o)
|
||
|
{ if(this != &o) decNumberCopy(&m_data, &o.m_data); return *this; }
|
||
|
|
||
|
//! Type conversion operator to decNumber*
|
||
|
operator decNumberPtr_t() { return &m_data; }
|
||
|
|
||
|
|
||
|
// ACCESSORS
|
||
|
const decNumber* data() const
|
||
|
{ return &m_data; }
|
||
|
|
||
|
// MODIFIERS
|
||
|
decNumber* data()
|
||
|
{ return &m_data; }
|
||
|
|
||
|
|
||
|
// CONVERSIONS
|
||
|
QDecNumber& fromBCD(QByteArray& bcd) {
|
||
|
decNumberSetBCD(&m_data, (const uint8_t*)bcd.data(), bcd.size());
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
QDecNumber& fromDouble(double d);
|
||
|
|
||
|
QDecNumber& fromInt32(int32_t val)
|
||
|
{ decNumberFromInt32(&m_data, val); return *this; }
|
||
|
|
||
|
QDecNumber& fromUInt32(uint32_t val)
|
||
|
{ decNumberFromUInt32(&m_data, val); return *this; }
|
||
|
|
||
|
QDecNumber& fromString(const char* str, QDecContext* c = 0)
|
||
|
{ decNumberFromString(&m_data, str, CXT(c)); return *this; }
|
||
|
|
||
|
QByteArray toBCD() const {
|
||
|
QByteArray bcd(m_data.digits+1, '\0');
|
||
|
decNumberGetBCD(&m_data, (uint8_t*)bcd.data());
|
||
|
return bcd;
|
||
|
}
|
||
|
|
||
|
double toDouble() const;
|
||
|
|
||
|
QByteArray toEngString() const {
|
||
|
char str[MaxStrSize] = { 0 };
|
||
|
return decNumberToEngString(&m_data, str);
|
||
|
}
|
||
|
|
||
|
QByteArray toString() const {
|
||
|
char str[MaxStrSize] = { 0 };
|
||
|
return decNumberToString(&m_data, str);
|
||
|
}
|
||
|
|
||
|
int32_t toInt32(QDecContext* c = 0) const
|
||
|
{ return decNumberToInt32(&m_data, CXT(c)); }
|
||
|
|
||
|
uint32_t toUInt32(QDecContext* c = 0) const
|
||
|
{ return decNumberToUInt32(&m_data, CXT(c)); }
|
||
|
|
||
|
|
||
|
// COMPUTATIONAL FUNCTIONS
|
||
|
QDecNumber abs(QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberAbs(&n, &m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber add(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberAdd(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber digitAnd(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberAnd(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber compare(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberCompare(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber compareSignal(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberCompareSignal(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber compareTotal(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberCompareTotal(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber compareTotalMag(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberCompareTotalMag(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber divide(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberDivide(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber divideInteger(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberDivideInteger(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber exp(QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberExp(&n, &m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber fma(const QDecNumber& mo, const QDecNumber& ao,
|
||
|
QDecContext* c = 0) const {
|
||
|
decNumber n;
|
||
|
return decNumberFMA(&n, &m_data, &mo.m_data, &ao.m_data, CXT(c));
|
||
|
}
|
||
|
|
||
|
QDecNumber invert(QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberInvert(&n, &m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber ln(QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberLn(&n, &m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber logB(QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberLogB(&n, &m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber log10(QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberLog10(&n, &m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber max(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberMax(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber maxMag(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberMaxMag(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber min(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberMin(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber minMag(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberMinMag(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber minus(QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberMinus(&n, &m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber multiply(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberMultiply(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber nextMinus(QDecContext* c = 0)
|
||
|
{ decNumber n; return decNumberNextMinus(&n, &m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber nextPlus(QDecContext* c = 0)
|
||
|
{ decNumber n; return decNumberNextPlus(&n, &m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber nextToward(const QDecNumber& o, QDecContext* c = 0)
|
||
|
{ decNumber n; return decNumberNextToward(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber normalize(QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberNormalize(&n, &m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber digitOr(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberOr(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber plus(QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberPlus(&n, &m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber power(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberPower(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber quantize(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberQuantize(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber reduce(QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberReduce(&n, &m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber remainder(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberRemainder(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber remainderNear(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberRemainderNear(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber rescale(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberRescale(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber rotate(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberRotate(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
bool sameQuantum(const QDecNumber& o) const {
|
||
|
decNumber n;
|
||
|
QDecNumber r = decNumberSameQuantum(&n, data(), o.data());
|
||
|
return !r.isZero();
|
||
|
}
|
||
|
|
||
|
QDecNumber scaleB(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberScaleB(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber shift(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberShift(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber squareRoot(QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberSquareRoot(&n, &m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber subtract(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberSubtract(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber toIntegralExact(QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberToIntegralExact(&n, &m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber toIntegralValue(QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberToIntegralValue(&n, &m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber digitXor(const QDecNumber& o, QDecContext* c = 0) const
|
||
|
{ decNumber n; return decNumberXor(&n, &m_data, &o.m_data, CXT(c)); }
|
||
|
|
||
|
|
||
|
// TESTING FUNCTIONS
|
||
|
bool isCanonical() const
|
||
|
{ return decNumberIsCanonical(&m_data); }
|
||
|
|
||
|
bool isFinite() const
|
||
|
{ return decNumberIsFinite(&m_data); }
|
||
|
|
||
|
bool isInfinite() const
|
||
|
{ return decNumberIsInfinite(&m_data); }
|
||
|
|
||
|
bool isNaN() const
|
||
|
{ return decNumberIsNaN(&m_data); }
|
||
|
|
||
|
bool isNegative() const
|
||
|
{ return decNumberIsNegative(&m_data); }
|
||
|
|
||
|
bool isQNaN() const
|
||
|
{ return decNumberIsQNaN(&m_data); }
|
||
|
|
||
|
bool isSNaN() const
|
||
|
{ return decNumberIsSNaN(&m_data); }
|
||
|
|
||
|
bool isSpecial() const
|
||
|
{ return decNumberIsSpecial(&m_data); }
|
||
|
|
||
|
bool isZero() const
|
||
|
{ return decNumberIsZero(&m_data); }
|
||
|
|
||
|
|
||
|
// TEST FUNCTIONS (CONTEXT DEPENDENT)
|
||
|
bool isNormal(QDecContext* c = 0) const
|
||
|
{ return decNumberIsNormal(&m_data, CXT(c)); }
|
||
|
|
||
|
bool isSubnormal(QDecContext* c = 0) const
|
||
|
{ return decNumberIsSubnormal(&m_data, CXT(c)); }
|
||
|
|
||
|
|
||
|
|
||
|
// UTILITIES
|
||
|
enum decClass toClass(QDecContext* c = 0) const
|
||
|
{ return decNumberClass(&m_data, CXT(c)); }
|
||
|
|
||
|
QDecNumber& copy(const QDecNumber& o)
|
||
|
{ decNumberCopy(&m_data, &o.m_data); return *this; }
|
||
|
|
||
|
QDecNumber& copyAbs(const QDecNumber& o)
|
||
|
{ decNumberCopyAbs(&m_data, &o.m_data); return *this; }
|
||
|
|
||
|
QDecNumber& copyNegate(const QDecNumber& o)
|
||
|
{ decNumberCopyNegate(&m_data, &o.m_data); return *this; }
|
||
|
|
||
|
QDecNumber& copySign(const QDecNumber& o, const QDecNumber& so)
|
||
|
{ decNumberCopySign(&m_data, &o.m_data, &so.m_data); return *this; }
|
||
|
|
||
|
uint32_t radix() const
|
||
|
{ return decNumberRadix(&m_data); }
|
||
|
|
||
|
QDecNumber& trim()
|
||
|
{ decNumberTrim(&m_data); return *this; }
|
||
|
|
||
|
const char* version() const
|
||
|
{ return decNumberVersion(); }
|
||
|
|
||
|
QDecNumber& zero()
|
||
|
{ decNumberZero(&m_data); return *this; }
|
||
|
|
||
|
|
||
|
// STATIC FUNCTIONS (UTILITIES)
|
||
|
static const char* ClassToString(enum decClass dc)
|
||
|
{ return decNumberClassToString(dc); }
|
||
|
|
||
|
static const char* Version()
|
||
|
{ return decNumberVersion(); }
|
||
|
|
||
|
|
||
|
// RELATIONAL AND LOGICAL OPERATORS
|
||
|
bool operator==(const QDecNumber& o) const
|
||
|
{ return compare(o).isZero(); }
|
||
|
|
||
|
bool operator!=(const QDecNumber& o) const
|
||
|
{ return !(this->operator==(o)); }
|
||
|
|
||
|
bool operator<(const QDecNumber& o) const
|
||
|
{ return compare(o).isNegative(); }
|
||
|
|
||
|
bool operator<=(const QDecNumber& o) const
|
||
|
{
|
||
|
const QDecNumber& r = compare(o);
|
||
|
return r.isNegative() || r.isZero();
|
||
|
}
|
||
|
|
||
|
bool operator>(const QDecNumber& o) const
|
||
|
{ return !(this->operator<=(o)); }
|
||
|
|
||
|
bool operator>=(const QDecNumber& o) const
|
||
|
{
|
||
|
const QDecNumber& r = compare(o);
|
||
|
return !r.isNegative() || r.isZero();
|
||
|
}
|
||
|
|
||
|
// BITWISE OPERATORS
|
||
|
QDecNumber operator&(const QDecNumber& o) const
|
||
|
{ return digitAnd(o); }
|
||
|
|
||
|
QDecNumber operator|(const QDecNumber& o) const
|
||
|
{ return digitOr(o); }
|
||
|
|
||
|
QDecNumber operator^(const QDecNumber& o) const
|
||
|
{ return digitXor(o); }
|
||
|
|
||
|
|
||
|
// ARITHMETIC OPERATORS
|
||
|
QDecNumber operator+(const QDecNumber& o) const
|
||
|
{ return add(o); }
|
||
|
|
||
|
QDecNumber operator-(const QDecNumber& o) const
|
||
|
{ return subtract(o); }
|
||
|
|
||
|
QDecNumber operator*(const QDecNumber& o) const
|
||
|
{ return multiply(o); }
|
||
|
|
||
|
QDecNumber operator/(const QDecNumber& o) const
|
||
|
{ return divide(o); }
|
||
|
|
||
|
QDecNumber operator%(const QDecNumber& o) const
|
||
|
{ return remainder(o); }
|
||
|
|
||
|
|
||
|
// COMPOUND ASSIGNMENT OPERATORS
|
||
|
QDecNumber& operator+=(const QDecNumber& o)
|
||
|
{ return copy(add(o)); }
|
||
|
|
||
|
QDecNumber& operator-=(const QDecNumber& o)
|
||
|
{ return copy(subtract(o)); }
|
||
|
|
||
|
QDecNumber& operator*=(const QDecNumber& o)
|
||
|
{ return copy(multiply(o)); }
|
||
|
|
||
|
QDecNumber& operator/=(const QDecNumber& o)
|
||
|
{ return copy(divide(o)); }
|
||
|
|
||
|
QDecNumber& operator%=(const QDecNumber& o)
|
||
|
{ return copy(remainder(o)); }
|
||
|
|
||
|
QDecNumber& operator&=(const QDecNumber& o)
|
||
|
{ return copy(digitAnd(o)); }
|
||
|
|
||
|
QDecNumber& operator|=(const QDecNumber& o)
|
||
|
{ return copy(digitOr(o)); }
|
||
|
|
||
|
QDecNumber& operator^=(const QDecNumber& o)
|
||
|
{ return copy(digitXor(o)); }
|
||
|
|
||
|
|
||
|
}; // end class
|
||
|
|
||
|
|
||
|
Q_DECLARE_METATYPE(QDecNumber);
|
||
|
|
||
|
QDECIMAL_EXPORT
|
||
|
QTextStream& operator<<(QTextStream& ts, const QDecNumber& n);
|
||
|
|
||
|
#endif /* Include guard */
|