#ifndef __FLOATBCD_AMV
#define __FLOATBCD_AMV
#include <string>
#include <iostream>
#include <cctype>
#include "uintBCD.h"
#include "exception.h"
#include "algorithm.h"
#include "REEvaluator.h"
#include "function.h"
#include "stringAMV.h"
#include "binaryTree.h"
#include "mathAMV.h"
#include "amvdefs.h"
namespace amv {
template <class type>
type rootGomezMorin(const type &N,const type &i, const unsigned int it=10)
{type x(1);
for(unsigned int j=0; j<it; ++j)
{
x=(type(2)*N+(i-type(2))*(x^i))/(N/x+(i-type(1))*(x^(i-type(1))));
}
return x;
}
template <class type>
type rootNewton(const type &N,const type &i, const unsigned int it=10)
{
type x(1);
for(unsigned int j=0; j<it; ++j)
{
x=(N+(i-type(1))*(x^i))/(i*(x^(i-type(1))));
}
return x;
}
class floatBCD {
public:
typedef unsigned int fmtflags;
static const fmtflags fix, sci;
private:
static fmtflags m_flags;
static REEvaluator REEfloatBCD;
uintBCD bcd; int posPoint; int exponent; int sign; void normalize();
void enforceExp(int nExp);
void doIntegerMantisa();
public:
static int precision;
static bool eval(const char *number);
floatBCD();
floatBCD(const string &s);
floatBCD(const char *number);
floatBCD(const floatBCD &nBCD);
floatBCD(int n, int exp=0);
floatBCD(bool b);
floatBCD &operator=(const floatBCD &op2);
floatBCD &operator+=(const floatBCD &op2);
floatBCD &operator-=(const floatBCD &op2);
floatBCD &operator*=(const floatBCD &op2);
floatBCD &operator/=(const floatBCD &op2);
floatBCD &operator^=(const floatBCD &op2);
floatBCD &operator%=(const floatBCD &op2);
floatBCD operator+(const floatBCD &op2) const;
floatBCD operator-(const floatBCD &op2) const;
floatBCD operator*(const floatBCD &op2) const;
floatBCD operator/(const floatBCD &op2) const;
floatBCD operator-() const;
floatBCD operator^(const floatBCD &op2) const;
floatBCD operator%(const floatBCD &op2) const;
floatBCD &operator++();
bool operator>(const floatBCD &op2) const;
bool operator<(const floatBCD &op2) const;
bool operator>=(const floatBCD &op2) const;
bool operator==(const floatBCD &op2) const;
void mul10();
void div10();
void invertSign();
int size() const;
bool isInteger() const;
bool isFraction() const;
bool isPositive() const;
bool isNegative() const;
bool isZero() const;
int getSign() const;
int getExponent() const;
floatBCD getIntegerPart() const;
fmtflags flags() const { return m_flags; }
fmtflags flags(fmtflags f) { fmtflags oldFlags=m_flags; m_flags=f; return oldFlags; }
friend floatBCD fact(const floatBCD &n);
friend floatBCD exp(const floatBCD &n);
friend floatBCD log(const floatBCD &n);
friend floatBCD ln(const floatBCD &n);
friend floatBCD sin(const floatBCD &n);
friend floatBCD sinh(const floatBCD &n);
friend floatBCD asin(const floatBCD &n);
friend floatBCD cos(const floatBCD &n);
friend floatBCD cosh(const floatBCD &n);
friend floatBCD acos(const floatBCD &n);
friend floatBCD tan(const floatBCD &n);
friend floatBCD tanh(const floatBCD &n);
friend floatBCD atan(const floatBCD &n);
friend floatBCD ctg(const floatBCD &n);
friend floatBCD actg(const floatBCD &n);
friend floatBCD sec(const floatBCD &n);
friend floatBCD asec(const floatBCD &n);
friend floatBCD csc(const floatBCD &n);
friend floatBCD acsc(const floatBCD &n);
friend floatBCD min1(const floatBCD &n1, const floatBCD &n2);
friend floatBCD max1(const floatBCD &n1, const floatBCD &n2);
friend floatBCD pow(const floatBCD &n, const floatBCD &nth);
friend floatBCD root(const floatBCD &nth, const floatBCD &n);
friend ostream &operator<<(ostream &os, const floatBCD nBCD);
friend istream &operator>>(istream &is, floatBCD &nBCD);
static binaryTree<function<floatBCD> > getFunctionsTree(const floatBCD &f)
{
binaryTree<function<floatBCD> > t;
t.insert(function<floatBCD>("fact",fact)),
t.insert(function<floatBCD>("exp",exp)),
t.insert(function<floatBCD>("log",log)),
t.insert(function<floatBCD>("ln",ln)),
t.insert(function<floatBCD>("sin",sin)),
t.insert(function<floatBCD>("sinh",sinh)),
t.insert(function<floatBCD>("asin",asin)),
t.insert(function<floatBCD>("cos",cos)),
t.insert(function<floatBCD>("cosh",cosh)),
t.insert(function<floatBCD>("acos",acos)),
t.insert(function<floatBCD>("tan",tan)),
t.insert(function<floatBCD>("tanh",tanh)),
t.insert(function<floatBCD>("atan",atan)),
t.insert(function<floatBCD>("ctg",ctg)),
t.insert(function<floatBCD>("actg",actg)),
t.insert(function<floatBCD>("sec",sec)),
t.insert(function<floatBCD>("asec",asec)),
t.insert(function<floatBCD>("csc",csc)),
t.insert(function<floatBCD>("acsc",acsc)),
t.insert(function<floatBCD>("min",min1,function<floatBCD>::BINARY)),
t.insert(function<floatBCD>("max",max1,function<floatBCD>::BINARY)),
t.insert(function<floatBCD>("pow",pow,function<floatBCD>::BINARY)),
t.insert(function<floatBCD>("root",root,function<floatBCD>::BINARY));
return t;
}
static floatBCD e; static floatBCD pi; static floatBCD fi;
};
const floatBCD::fmtflags floatBCD::fix=0x0001, floatBCD::sci=0x0002;
floatBCD::fmtflags floatBCD::m_flags(floatBCD::sci);
REEvaluator floatBCD::REEfloatBCD("\\-?<[0-9]+<(.<[0-9]+)?<(e<\\-?<[0-9]+)?");
int floatBCD::precision=4;
floatBCD floatBCD::e="2.78";
floatBCD floatBCD::pi="3.141592654";
floatBCD floatBCD::fi="1.71";
inline void floatBCD::normalize()
{
if(!sign)
return;
int zeros=0,i;
if(posPoint>0)
{
for(i=0; i<posPoint; ++i)
{
if(!bcd[i])
{
++zeros;
}
else
{
break;
}
}
if(zeros)
{
if(zeros==bcd.size())
{
bcd=uintBCD();
posPoint=0;
exponent=0;
sign=0;
return;
}
else
{
if(posPoint==bcd.size())
{
bcd.resizeI(bcd.size()-zeros,0);
posPoint=bcd.size();
}
else
{
bcd.resizeI(bcd.size()-zeros,0);
posPoint-=zeros;
}
}
}
}
if(posPoint<bcd.size())
{
zeros=0;
for(i=bcd.size()-1; i>=posPoint; --i)
{
if(!bcd[i])
{
++zeros;
}
else
{
break;
}
}
if(zeros)
{
if(zeros==bcd.size())
{
bcd=uintBCD();
posPoint=0;
exponent=0;
sign=0;
return;
}
else
{
bcd.resize(bcd.size()-zeros,0);
}
}
}
}
inline void floatBCD::enforceExp(int nExp)
{
if(exponent==nExp || (!sign))
return;
int dif=nExp-exponent;
exponent=nExp;
if(dif>0)
{
posPoint-=dif;
if(posPoint<0)
{
bcd.resizeI(bcd.size()+abs(posPoint),0);
posPoint=0;
}
}
else
{
posPoint+=abs(dif);
if(posPoint>bcd.size())
{
bcd.resize(posPoint,0);
}
}
this->normalize();
}
inline void floatBCD::doIntegerMantisa()
{
if(posPoint!=bcd.size())
{
exponent-=(bcd.size()-posPoint);
posPoint=bcd.size();
this->normalize();
}
}
inline bool floatBCD::eval(const char *number)
{
return (REEfloatBCD.eval(number));
}
inline floatBCD::floatBCD():
posPoint(0), exponent(0), sign(0)
{
}
inline floatBCD::floatBCD(const string &s)
{
string::const_iterator it(s.begin()), itPoint(find(s.begin(),s.end(),'.')), itExp(find(s.begin(),s.end(),'e'));
int length=s.size(), i, expDigits, exp=0, expSign;
char *pPos;
if(*it=='-')
{
sign=-1;
++it;
--length;
}
else
sign=1;
if(itExp!=s.end())
{
expDigits=s.end()-itExp;
length-=expDigits;
++itExp;
if(itExp!=s.end())
{
if(*itExp=='-')
{
++itExp;
expSign=-1;
}
while(itExp!=s.end())
{
exp=exp*10+AsciiBCD(*itExp);
++itExp;
}
if(exp>0 && expSign<0)
exp=-exp;
}
}
if(itPoint!=s.end())
{
posPoint=itPoint-it;
--length;
bcd.resize(length);
for(i=0; i<posPoint; ++i)
bcd[i]=AsciiBCD(*(it+i));
for(++i; i<=length; ++i)
bcd[i-1]=AsciiBCD(*(it+i));
}
else
{
posPoint=length;
bcd.resize(length);
for(i=0; i<length; ++i)
bcd[i]=AsciiBCD(*(it+i));
}
for(i=0; i<bcd.size() && bcd[i]==0; ++i)
;
if(i==bcd.size())
{
bcd=uintBCD();
posPoint=0;
exponent=0;
sign=0;
return;
}
else
{
exponent=exp;
this->normalize();
}
}
inline floatBCD::floatBCD(const char *number)
{
int length,i, exp=0;
const char *pPos;
if(*number=='-')
{
sign=-1;
++number;
}
else
sign=1;
length=strlen(number);
if(pPos=strstr(number,"."))
{
posPoint=pPos-number;
length-=1;
bcd.resize(length);
for(i=0; i<posPoint; ++i)
bcd[i]=AsciiBCD(number[i]);
for(++i; i<=length; ++i)
bcd[i-1]=AsciiBCD(number[i]);
}
else
{
posPoint=length;
bcd.resize(length);
for(i=0; i<length; ++i)
bcd[i]=AsciiBCD(number[i]);
}
for(i=0; i<bcd.size() && bcd[i]==0; ++i)
;
if(i==bcd.size())
{
bcd=uintBCD();
posPoint=0;
exponent=0;
sign=0;
return;
}
else
{
exponent=exp;
this->normalize();
}
}
inline floatBCD::floatBCD(const floatBCD &nBCD):
bcd(nBCD.bcd), posPoint(nBCD.posPoint),
exponent(nBCD.exponent), sign(nBCD.sign)
{
}
inline floatBCD::floatBCD(int n, int exp):
posPoint(0), exponent(exp), sign(0)
{
if(!n)
return;
if(n>0)
sign=1;
else
{
sign=-1;
n=abs(n);
}
int digits=0, temp(n);
while(temp)
{
++digits;
temp/=10;
}
bcd.resize(digits);
for(int i=digits-1, k=0; k<digits; ++k, --i)
{
bcd[i]=n%10;
n/=10;
}
posPoint=digits;
}
inline floatBCD::floatBCD(bool b)
{
if(b)
{
bcd.resize(1);
bcd[0]=1;
posPoint=1;
exponent=0;
sign=1;
}
else
{
posPoint=0;
exponent=0;
sign=0;
}
}
inline floatBCD &floatBCD::operator=(const floatBCD &op2)
{
bcd=op2.bcd;
posPoint=op2.posPoint;
exponent=op2.exponent;
sign=op2.sign;
return (*this);
}
inline floatBCD &floatBCD::operator+=(const floatBCD &op2)
{
if(!sign)
{
*this=op2;
return *this;
}
if(!op2.sign)
return *this;
floatBCD newOp2(op2);
newOp2.enforceExp(exponent);
int newLength,i,j,nI,nD, integersOp1, integersOp2, decimalsOp1, decimalsOp2;
integersOp1=posPoint;
integersOp2=newOp2.posPoint;
decimalsOp1=bcd.size()-posPoint;
decimalsOp2=newOp2.bcd.size()-newOp2.posPoint;
nI=(integersOp1>integersOp2)? (integersOp1+1): integersOp2+1;
nD=(decimalsOp1>decimalsOp2)? decimalsOp1: decimalsOp2;
newLength=nI+nD;
if(sign+newOp2.sign)
{
char carry=0, sum;
uintBCD temp2(newLength);
fill(temp2,0);
for(i=nI-1, j=integersOp1-1; j>=0; --i, --j)
temp2[i]=bcd[j];
for(i=nI, j=integersOp1; j<bcd.size(); ++i, ++j)
temp2[i]=bcd[j];
for(j=newOp2.bcd.size()-1; j>=integersOp2; --j)
{
sum=temp2[(nI-1)+(j-newOp2.posPoint+1)]+newOp2.bcd[j]+carry;
temp2[(nI-1)+(j-newOp2.posPoint)+1]=sum%10;
carry=sum/10;
}
for(i=nI-1; j>=0; --i,--j)
{
sum=temp2[i]+newOp2.bcd[j]+carry;
temp2[i]=sum%10;
carry=sum/10;
}
for(;i>=0; --i)
{
sum=temp2[i]+carry;
temp2[i]=sum%10;
carry=sum/10;
}
bcd=temp2;
posPoint=nI;
this->normalize();
return *this;
}
else
{
int newSign, lastSign=sign;
if(sign>0)
newOp2.invertSign();
else
invertSign();
if(*this==newOp2)
{
*this=floatBCD();
return *this;
}
char digit1, digit2, carry=0;
uintBCD temp2(newLength);
fill(temp2,0);
if(*this<newOp2)
{
if(lastSign>0)
newSign=-1;
else
newSign=1;
for(i=nI-1, j=integersOp2-1; j>=0; --i, --j)
temp2[i]=newOp2.bcd[j];
for(i=nI, j=integersOp2; j<newOp2.bcd.size(); ++i, ++j)
temp2[i]=newOp2.bcd[j];
for(j=bcd.size()-1; j>=integersOp1; --j)
{
digit1=temp2[(nI-1)+(j-posPoint+1)];
digit2=bcd[j];
digit1=digit1-carry;
if(digit1<digit2)
{
carry=1;
digit1+=10;
}
else
{
carry=0;
}
temp2[(nI-1)+(j-posPoint)+1]=digit1-digit2;
}
for(i=nI-1; j>=0; --i,--j)
{
digit1=temp2[i];
digit2=bcd[j];
digit1=digit1-carry;
if(digit1<digit2)
{
carry=1;
digit1+=10;
}
else
{
carry=0;
}
temp2[i]=digit1-digit2;
}
}
else
{
if(lastSign>0)
newSign=1;
else
newSign=-1;
for(i=nI-1, j=integersOp1-1; j>=0; --i, --j)
temp2[i]=bcd[j];
for(i=nI, j=integersOp1; j<bcd.size(); ++i, ++j)
temp2[i]=bcd[j];
for(j=newOp2.bcd.size()-1; j>=integersOp2; --j)
{
digit1=temp2[(nI-1)+(j-newOp2.posPoint+1)];
digit2=newOp2.bcd[j];
digit1=digit1-carry;
if(digit1<digit2)
{
carry=1;
digit1+=10;
}
else
{
carry=0;
}
temp2[(nI-1)+(j-newOp2.posPoint)+1]=digit1-digit2;
}
for(i=nI-1; j>=0; --i,--j)
{
digit1=temp2[i];
digit2=newOp2.bcd[j];
digit1=digit1-carry;
if(digit1<digit2)
{
carry=1;
digit1+=10;
}
else
{
carry=0;
}
temp2[i]=digit1-digit2;
}
}
for(;i>=0; --i)
{
digit1=temp2[i];
digit1=digit1-carry;
if(digit1<0)
{
carry=1;
digit1+=10;
}
else
{
carry=0;
}
temp2[i]=digit1;
}
bcd=temp2;
posPoint=nI;
sign=newSign;
normalize();
return *this;
}
}
inline floatBCD &floatBCD::operator-=(const floatBCD &op2)
{
*this+=(-op2);
return *this;
}
inline floatBCD &floatBCD::operator*=(const floatBCD &op2)
{
if(!sign)
return *this;
if(!op2.sign)
{
*this=floatBCD();
return *this;
}
int newLength,i,j,k,l,nD, decimalsOp1, decimalsOp2;
char product, digit1, digit2, newDigit, carry=0, carry2=0;
decimalsOp1=bcd.size()-posPoint;
decimalsOp2=op2.bcd.size()-op2.posPoint;
nD=decimalsOp1+decimalsOp2;
newLength=bcd.size()+op2.bcd.size();
uintBCD temp(newLength);
for(i=0; i<temp.size(); ++i)
temp[i]=0;
for(i=op2.bcd.size()-1, l=0; i>=0; --i, ++l)
{
carry=carry2=0;
k=temp.size()-1-l;
for(j=bcd.size()-1; j>=0; --j)
{
product=op2.bcd[i]*bcd[j]+carry;
newDigit=(product)%10;
carry=(product)/10;
digit2=temp[k]+newDigit+carry2;
carry2=digit2/10;
newDigit=digit2%10;
temp[k--]=newDigit;
}
for(; k>=0; --k)
{
digit1=temp[k]+carry+carry2;
carry2=0;
newDigit=digit1%10;
carry=digit1/10;
temp[k]=newDigit;
}
}
bcd=temp;
posPoint=newLength-nD;
exponent=exponent+op2.exponent;
if(sign+op2.sign)
sign=1;
else
sign=-1;
normalize();
return *this;
}
inline floatBCD &floatBCD::operator/=(const floatBCD &op2)
{
if(!(op2.sign))
throw division_by_zero();
if((!sign))
return *this;
if(*this==op2)
{
*this=floatBCD("1");
return *this;
}
if(op2==(floatBCD("1")))
return *this;
floatBCD temp(op2);
doIntegerMantisa();
temp.doIntegerMantisa();
int nExp=exponent-temp.exponent;
int newSign;
newSign=(sign+temp.sign)? 1: -1;
uintBCD temp2, quotient;
int nAggregates=0, newPosPoint;
newPosPoint=bcd.size();
if(bcd.size()<temp.bcd.size())
{
nAggregates=temp.bcd.size()-bcd.size();
bcd.resize(bcd.size()+nAggregates,0);
}
while(bcd<temp.bcd)
{
bcd.resize(bcd.size()+1,0);
++nAggregates;
}
uintBCD u1(bcd), u2(temp.bcd);
int i=0, lastPosition, pivot;
while(temp2<u2)
temp2=u1.snippet(0,temp2.size()+1);
quotient.resize(temp2.size()-1,0);
pivot=temp2.size()-1;
lastPosition=u1.size()+precision;
do
{
i=0;
while(temp2>=u2)
{
++i;
temp2=temp2-u2;
}
quotient.resize(quotient.size()+1);
quotient[quotient.size()-1]=i;
do
{
++pivot;
if(pivot<lastPosition)
{
temp2.resize(temp2.size()+1,0);
if(pivot<u1.size())
temp2[temp2.size()-1]=u1[pivot];
else
temp2[temp2.size()-1]=0;
if(temp2<u2)
{
quotient.resize(quotient.size()+1);
quotient[quotient.size()-1]=0;
}
else
break;
}
else
goto endDivision;
}while(true);
}while(true);
endDivision:
bcd=quotient;
posPoint=newPosPoint;
exponent=nExp;
sign=newSign;
normalize();
return *this;
}
inline floatBCD &floatBCD::operator^=(const floatBCD &op2)
{
if(!sign)
return *this;
if(op2.isZero())
{
*this=floatBCD(true);
return *this;
}
if(op2.isPositive())
{
if(op2.isInteger())
{
floatBCD temp(1);
for(floatBCD i; i<op2; ++i)
temp*=*this;
*this=temp;
}
else
{
floatBCD nth(10); floatBCD n(op2); floatBCD temp(*this);
n.doIntegerMantisa();
nth.exponent=abs(n.exponent);
nth.enforceExp(0);
n.exponent=0;
temp^=n;
temp=root(nth,temp);
*this=temp;
}
}
else
{
if(op2.isInteger())
{
floatBCD temp(1);
floatBCD inverse(op2);
inverse.invertSign();
for(floatBCD i; i<inverse; ++i)
temp*=*this;
temp=floatBCD(1)/temp;
*this=temp;
}
else
{
floatBCD nth(10); floatBCD n(op2); floatBCD temp(*this);
n.invertSign();
n.doIntegerMantisa();
nth.exponent=abs(n.exponent);
nth.enforceExp(0);
n.exponent=0;
temp^=n;
temp=root(nth,temp);
temp=floatBCD(1)/temp;
*this=temp;
}
}
return *this;
}
inline floatBCD &floatBCD::operator%=(const floatBCD &op2)
{
if(*this==op2)
{
*this=floatBCD(false);
return *this;
}
if(*this<op2)
return *this;
floatBCD divisor(*this/op2);
*this-=op2*divisor.getIntegerPart();
if(*this==op2)
*this=floatBCD(false);
return *this;
}
inline floatBCD floatBCD::operator+(const floatBCD &nBCD) const
{
if(!sign)
return nBCD;
if(!nBCD.sign)
return *this;
floatBCD temp(*this);
temp+=nBCD;
return temp;
}
inline floatBCD floatBCD::operator-(const floatBCD &op2) const
{
return (*this+(-op2));
}
inline floatBCD floatBCD::operator*(const floatBCD &op2) const
{
floatBCD temp(*this);
temp*=op2;
return temp;
}
inline floatBCD floatBCD::operator/(const floatBCD &op2) const
{
floatBCD temp(*this);
temp/=op2;
return temp;
}
inline floatBCD floatBCD::operator-() const
{
if(!sign)
return (*this);
floatBCD temp(*this);
temp.invertSign();
return temp;
}
inline floatBCD floatBCD::operator^(const floatBCD &op2) const
{
floatBCD temp(*this);
temp^=op2;
return temp;
}
inline floatBCD floatBCD::operator%(const floatBCD &op2) const
{
floatBCD temp(*this);
temp%=op2;
return temp;
}
inline floatBCD &floatBCD::operator++()
{
*this+=1;
return *this;
}
inline bool floatBCD::operator>(const floatBCD &op2) const
{
return !(*this<op2 || *this==op2);
}
inline bool floatBCD::operator<(const floatBCD &op2) const
{
int i;
if(!sign && !(op2.sign))
return false;
if(!sign && (op2.sign>0))
return true;
if(!sign && (op2.sign<0))
return false;
if((sign>0) && (op2.sign<=0))
return false;
if((sign<0) && (op2.sign>=0))
return true;
floatBCD temp(op2);
temp.enforceExp(exponent);
if(sign>0)
{
if(posPoint>temp.posPoint)
return false;
if(posPoint<temp.posPoint)
return true;
for(i=0; i<posPoint; ++i)
{
if(bcd[i]>temp.bcd[i])
return false;
else if(bcd[i]<temp.bcd[i])
return true;
}
int decimalsOp1=(bcd.size()-posPoint),
decimalsOp2=(temp.bcd.size()-temp.posPoint);
if(!(decimalsOp1+decimalsOp2))
return false;
int places=(decimalsOp1>decimalsOp2)? bcd.size(): temp.bcd.size();
char digit1, digit2;
for(; i<places; ++i)
{
digit1=(i>=bcd.size())? 0: bcd[i];
digit2=(i>=temp.bcd.size())? 0: temp.bcd[i];
if(digit1>digit2)
return false;
else if(digit1<digit2)
return true;
}
}
else
{
if(posPoint>temp.posPoint)
return true;
if(posPoint<temp.posPoint)
return false;
for(i=0; i<posPoint; ++i)
{
if(bcd[i]>temp.bcd[i])
return true;
else if(bcd[i]<temp.bcd[i])
return false;
}
int decimalsOp1=(bcd.size()-posPoint),
decimalsOp2=(temp.bcd.size()-temp.posPoint);
if(!(decimalsOp1+decimalsOp2))
return false;
int places=(decimalsOp1>decimalsOp2)? bcd.size(): temp.bcd.size();
char digit1, digit2;
for(; i<places; ++i)
{
digit1=(i>=bcd.size())? 0: bcd[i];
digit2=(i>=temp.bcd.size())? 0: temp.bcd[i];
if(digit1>digit2)
return true;
else if(digit1<digit2)
return false;
}
}
return false;
}
inline bool floatBCD::operator>=(const floatBCD &op2) const
{
return !(*this<op2);
}
inline bool floatBCD::operator==(const floatBCD &op2) const
{
if((!sign) && (!op2.sign))
return true;
if(!(sign+op2.sign))
return false;
floatBCD temp(op2);
temp.enforceExp(exponent);
if((posPoint==temp.posPoint) && (bcd.size()==temp.bcd.size()))
{
for(int i=0; i<bcd.size(); ++i)
{
if(bcd[i]!=temp.bcd[i])
return false;
}
return true;
}
else
return false;
}
inline void floatBCD::mul10()
{
++exponent;
}
inline void floatBCD::div10()
{
--exponent;
}
inline void floatBCD::invertSign()
{
if(!sign)
return;
if(sign>0)
sign=-1;
else
sign=1;
}
inline int floatBCD::size() const
{
return bcd.size();
}
inline bool floatBCD::isInteger() const
{
if(!sign)
return false;
if(posPoint+exponent>=bcd.size())
return true;
return false;
}
inline bool floatBCD::isFraction() const
{
if(!sign)
return false;
if(posPoint+exponent>=bcd.size())
return false;
return true;
}
inline bool floatBCD::isPositive() const
{
return (sign>0);
}
inline bool floatBCD::isNegative() const
{
return (sign<0);
}
inline bool floatBCD::isZero() const
{
return (sign==0);
}
inline int floatBCD::getSign() const
{
return sign;
}
inline int floatBCD::getExponent() const
{
return exponent;
}
inline floatBCD floatBCD::getIntegerPart() const
{
if(isFraction())
{
int realPosition=posPoint+exponent;
if(realPosition<=0)
return floatBCD();
else
{
floatBCD temp;
temp.bcd.resize(realPosition);
copy(bcd.begin(),bcd.begin()+realPosition,temp.bcd.begin());
temp.exponent=0;
temp.posPoint=realPosition;
temp.sign=sign;
return temp;
}
}
else
return *this;
}
ostream &operator<<(ostream &os, floatBCD nBCD)
{
if(!nBCD.sign)
return (os<<'0');
if(nBCD.sign<0)
os<<'-';
int i=0;
if(floatBCD::m_flags & floatBCD::sci)
{
if(!nBCD.posPoint)
os<<'0';
for(; i<nBCD.posPoint; ++i)
os<<BCDAscii(nBCD.bcd[i]);
if(i<nBCD.bcd.size())
{
os<<'.';
for(; i<nBCD.bcd.size(); ++i)
os<<BCDAscii(nBCD.bcd[i]);
}
if(nBCD.exponent)
os<<'e'<<nBCD.exponent;
return os;
}
nBCD.doIntegerMantisa();
if(!nBCD.exponent)
{
for(; i<nBCD.bcd.size(); ++i)
os<<BCDAscii(nBCD.bcd[i]);
}
else if(nBCD.exponent<0)
{
int dif=nBCD.bcd.size()+nBCD.exponent;
if(dif>0)
{
while(!nBCD.bcd[i] && i<dif)
++i;
if(i==dif)
os<<"0.";
else
{
for(; i<dif; ++i)
{
os<<BCDAscii(nBCD.bcd[i]);
}
os<<'.';
}
for(; i<nBCD.bcd.size(); ++i)
os<<BCDAscii(nBCD.bcd[i]);
}
else if(dif==0)
{
os<<"0.";
for(i=0; i<nBCD.bcd.size(); ++i)
os<<BCDAscii(nBCD.bcd[i]);
}
else
{
os<<"0.";
for(i=0; i>dif; --i)
os<<'0';
for(i=0; i<nBCD.bcd.size(); ++i)
os<<BCDAscii(nBCD.bcd[i]);
}
}
else
{
for(i=0; i<nBCD.bcd.size(); ++i)
os<<BCDAscii(nBCD.bcd[i]);
for(i=0; i<nBCD.exponent; ++i)
os<<'0';
}
return os;
}
istream &operator>>(istream &is, floatBCD &nBCD)
{
static REEvaluator REEnospace="#*";
string s;
REEnospace.skipNoSymbols(is);
if(floatBCD::REEfloatBCD.getLexema(is,s))
nBCD=floatBCD(s);
return is;
}
ostream &fixed(ostream &os)
{
floatBCD r;
r.flags(floatBCD::fix);
return os;
}
ostream &scientific(ostream &os)
{
floatBCD r;
r.flags(floatBCD::sci);
return os;
}
floatBCD reduce(const floatBCD &n)
{
if(abs(n)<"6.283185308")
return n;
else
{
floatBCD temp(abs(n));
while(temp>"6.283185308")
temp+=-(floatBCD("6.283185308"));
if(n.isNegative())
temp.invertSign();
return temp;
}
}
floatBCD fact(const floatBCD &n)
{
floatBCD temp(1), i(2);
for(; i<n || i==n; ++i)
temp*=i;
return temp;
}
floatBCD exp(const floatBCD &n)
{
floatBCD temp(1), i(2), limit(10);
temp+=n;
for(; i<limit; ++i)
{
temp+=(n^i)/fact(i);
}
return temp;
}
floatBCD log(const floatBCD &n)
{
floatBCD temp;
return temp;
}
floatBCD ln(const floatBCD &n)
{
floatBCD temp;
return temp;
}
floatBCD sin(const floatBCD &n)
{
floatBCD newAngle(reduce(n)), temp(newAngle), i(3), limit(10*2);
bool s=false;
for(; i<limit; i+=2)
{
if(s)
temp+=(newAngle^i)/fact(i);
else
temp+=-((newAngle^i)/fact(i));
s=!s;
}
return temp;
}
floatBCD sinh(const floatBCD &n)
{
floatBCD temp;
return temp;
}
floatBCD asin(const floatBCD &n)
{
floatBCD temp;
return temp;
}
floatBCD cos(const floatBCD &n)
{
floatBCD newAngle(reduce(n)), temp(1), i(2), limit(10*2);
bool s=false;
for(; i<limit; i+=2)
{
if(s)
temp+=(newAngle^i)/fact(i);
else
temp+=-((newAngle^i)/fact(i));
s=!s;
}
return temp;
}
floatBCD cosh(const floatBCD &n)
{
floatBCD temp;
return temp;
}
floatBCD acos(const floatBCD &n)
{
floatBCD temp;
return temp;
}
floatBCD tan(const floatBCD &n)
{
floatBCD temp(sin(n)/cos(n));
return temp;
}
floatBCD tanh(const floatBCD &n)
{
floatBCD temp(sin(n)/cos(n));
return temp;
}
floatBCD atan(const floatBCD &n)
{
floatBCD temp(sin(n)/cos(n));
return temp;
}
floatBCD ctg(const floatBCD &n)
{
floatBCD temp(cos(n)/sin(n));
return temp;
}
floatBCD actg(const floatBCD &n)
{
floatBCD temp(sin(n)/cos(n));
return temp;
}
floatBCD sec(const floatBCD &n)
{
floatBCD temp(floatBCD(1)/cos(n));
return temp;
}
floatBCD asec(const floatBCD &n)
{
floatBCD temp(sin(n)/cos(n));
return temp;
}
floatBCD csc(const floatBCD &n)
{
floatBCD temp(floatBCD(1)/sin(n));
return temp;
}
floatBCD acsc(const floatBCD &n)
{
floatBCD temp(sin(n)/cos(n));
return temp;
}
floatBCD min1(const floatBCD &n1, const floatBCD &n2)
{
return (n1<n2? n1: n2);
}
floatBCD max1(const floatBCD &n1, const floatBCD &n2)
{
return (n1<n2? n2: n1);
}
floatBCD pow(const floatBCD &n, const floatBCD &nth)
{
return (n^nth);
}
floatBCD root(const floatBCD &nth, const floatBCD &n)
{
return rootGomezMorin(n,nth);
}
}
#endif