#ifndef __UINTBCD_AMV
#define __UINTBCD_AMV
#include "vectorx.h"
#include "REEvaluator.h"
#include "algorithm.h"
#include "stringAMV.h"
#include "amvdefs.h"
namespace amv {
inline char AsciiBCD(const char ch)
{
return (ch&0x0F);
}
inline char BCDAscii(const char ch)
{
return (ch|0x30);
}
class uintBCD: public vectorx<char> {
static REEvaluator REEuintBCD;
public:
static bool eval(const char *number);
uintBCD();
explicit uintBCD(size_type Size);
uintBCD(const char *number);
uintBCD(const string &s);
void reduce();
uintBCD &operator+=(const uintBCD &op2);
uintBCD operator+(const uintBCD &op2) const;
uintBCD &operator-=(const uintBCD &op2);
uintBCD operator-(const uintBCD &op2) const;
bool operator<(const uintBCD &op2) const;
bool operator>=(const uintBCD &op2) const;
uintBCD snippet(size_type subscript, size_type n) const;
friend ostream &operator<<(ostream &os, const uintBCD &n);
friend istream &operator>>(istream &is, uintBCD &n);
};
REEvaluator uintBCD::REEuintBCD("[0-9]+");
inline bool uintBCD::eval(const char *number)
{
return (REEuintBCD.eval(number));
}
inline uintBCD::uintBCD(): vectorx<char>()
{
}
inline uintBCD::uintBCD(size_type Size): vectorx<char>(Size)
{
fill(*this,0);
}
inline uintBCD::uintBCD(const char *number)
{
size_type Size=strlen(number);
resize(Size);
for(size_type i=0; i<Size; ++i)
{
ptr[i]=AsciiBCD(*number);
++number;
}
reduce();
}
inline uintBCD::uintBCD(const string &s)
{
resize(s.size());
string::const_iterator itSource(s.begin());
uintBCD::iterator itTarget(begin());
while(itSource!=s.end())
{
*itTarget=AsciiBCD(*itSource);
++itTarget;
++itSource;
}
reduce();
}
inline void uintBCD::reduce()
{
if(!m_size)
return;
size_type zeros=0;
char *pBegin=ptr, *pEnd=ptr+m_size;
while(pBegin!=pEnd)
{
if(*pBegin)
break;
else
++zeros;
++pBegin;
}
if(zeros)
resizeI(m_size-zeros,0);
}
inline uintBCD &uintBCD::operator+=(const uintBCD &op2)
{
if(!op2.m_size)
return *this;
if(!m_size)
{
*this=op2;
return *this;
}
uintBCD result(m_size>op2.m_size? m_size+1: op2.m_size+1);
size_type i,j,k;
char carry=0;
if(m_size>op2.m_size)
{
for(i=result.m_size-1, j=m_size-1, k=op2.m_size-1; k>=0; --i, --j, --k)
{
result[i]=carry+ptr[j]+op2.ptr[k];
if(result[i]>9)
{
result[i]%=10;
carry=1;
}
else
carry=0;
}
for(; j>=0; --i, --j)
{
result[i]=carry+ptr[j];
if(result[i]>9)
{
result[i]%=10;
carry=1;
}
else
carry=0;
}
result[i]=carry;
}
else
{
for(i=result.m_size-1, j=m_size-1, k=op2.m_size-1; j>=0; --i, --j, --k)
{
result[i]=carry+ptr[j]+op2.ptr[k];
if(result[i]>9)
{
result[i]%=10;
carry=1;
}
else
carry=0;
}
for(; k>=0; --i, --k)
{
result[i]=carry+op2.ptr[k];
if(result[i]>9)
{
result[i]%=10;
carry=1;
}
else
carry=0;
}
if(!i)
result[i]=carry;
}
result.reduce();
*this=result;
return *this;
}
inline uintBCD uintBCD::operator+(const uintBCD &op2) const
{
uintBCD temp(*this);
temp+=op2;
return temp;
}
inline uintBCD &uintBCD::operator-=(const uintBCD &op2)
{
if(!op2.m_size)
return *this;
uintBCD result(m_size);
size_type i,j,k,limit;
char digit1,digit2,carry=0;
for(i=m_size-1, j=op2.m_size-1, k=0; k<op2.m_size; --i, --j, ++k)
{
digit1=ptr[i];
digit2=carry+op2.ptr[j];
if(digit1<digit2)
{
result[i]=digit1+10-digit2;
carry=1;
}
else
{
result[i]=digit1-digit2;
carry=0;
}
}
limit=i+1;
for(k=0; k<limit; --i, ++k)
{
digit1=ptr[i];
digit2=carry;
if(digit1<digit2)
{
result[i]=digit1+10-digit2;
carry=1;
}
else
{
result[i]=digit1-digit2;
carry=0;
}
}
result.reduce();
*this=result;
return *this;
}
inline uintBCD uintBCD::operator-(const uintBCD &op2) const
{
uintBCD temp(*this);
temp-=op2;
return temp;
}
inline bool uintBCD::operator<(const uintBCD &op2) const
{
if(!m_size && !op2.m_size)
return false;
if(!m_size)
{
if(op2.m_size==count(op2,0))
return false;
else
return true;
}
else if(!op2.m_size)
return false;
else
{
bool op1Zero, op2Zero;
op1Zero=m_size==count(*this,0);
op2Zero=op2.m_size==count(op2,0);
if(op1Zero && !op2Zero)
return true;
if(op2Zero)
return false;
size_type i,j;
for(i=0; i<m_size; ++i)
{
if(ptr[i]!=0)
break;
}
for(j=0; j<op2.m_size; ++j)
{
if(op2.ptr[j]!=0)
break;
}
size_type digits1=m_size-i, digits2=op2.m_size-j;
if(digits1<digits2)
return true;
else if(digits1>digits2)
return false;
for(;i<m_size; ++i,++j)
{
if(ptr[i]<op2.ptr[j])
return true;
else if(ptr[i]>op2.ptr[j])
return false;
}
return false;
}
}
inline bool uintBCD::operator>=(const uintBCD &op2) const
{
return !(*this<op2);
}
inline uintBCD uintBCD::snippet(size_type subscript, size_type n) const
{
uintBCD temp(n);
copy(ptr+subscript,ptr+subscript+n,temp.ptr);
return temp;
}
ostream &operator<<(ostream &os, const uintBCD &n)
{
if(n.size())
{
for(uintBCD::size_type i=0; i<n.m_size; ++i)
os<<int(n.ptr[i]);
}
else
os<<'0';
return os;
}
istream &operator>>(istream &is, uintBCD &n)
{
string s;
if(uintBCD::REEuintBCD.getLexema(is,s))
n=uintBCD(s);
return is;
}
}
#endif