Finish the rewrite.

This commit is contained in:
JoelKatz
2012-05-27 16:40:25 -07:00
parent d67f06d456
commit 64f903f21d
2 changed files with 103 additions and 44 deletions

View File

@@ -420,19 +420,37 @@ STAmount& STAmount::operator=(uint64 v)
}
STAmount& STAmount::operator+=(uint64 v)
{ // FIXME
if (mIsNative) mValue += v;
{
if (mIsNative)
{
if (mIsNegative)
*this += STAmount(v);
else mValue += v;
}
else *this += STAmount(mCurrency, v);
return *this;
}
STAmount& STAmount::operator-=(uint64 v)
{ // FIXME
{
if (mIsNative)
{
if (v > mValue)
throw std::runtime_error("amount underflow");
mValue -= v;
if (mIsNegative)
{
if (v >= mValue)
{
mIsNegative = false;
mValue = v - mValue;
}
else
mValue += v;
}
else if (v > mValue)
{
mIsNegative = true;
mValue = v - mValue;
}
else mValue -= v;
}
else *this -= STAmount(mCurrency, v);
return *this;
@@ -470,19 +488,28 @@ bool STAmount::operator>=(uint64 v) const
}
STAmount STAmount::operator+(uint64 v) const
{ // FIXME
{
if (!mIsNative)
throw std::runtime_error("operation not legal no non-native currency");
return STAmount(true, mValue + v);
if (mIsNegative)
{
if (v >= mValue)
return STAmount(false, v - mValue); // >=0 result
else return STAmount(true, mValue - v); // <0 result
}
return STAmount(false, mValue + v);
}
STAmount STAmount::operator-(uint64 v) const
{ // FIXME
{
if (!mIsNative)
throw std::runtime_error("operation not legal no non-native currency");
if (mValue < v)
throw std::runtime_error("native currency underflow");
return STAmount(true, mValue - v);
if (mIsNegative)
return STAmount(true, mValue + v);
else if (v > mValue) return STAmount(true, v - mValue);
return STAmount(false, mValue - v);
}
STAmount::operator double() const
@@ -493,53 +520,89 @@ STAmount::operator double() const
return static_cast<double>(mValue) * pow(10.0, mOffset);
}
STAmount operator+(STAmount v1, STAmount v2)
STAmount operator+(const STAmount& v1, const STAmount& v2)
{ // We can check for precision loss here (value%10)!=0
// FIXME
v1.throwComparable(v2);
if (v1.mIsNative)
return STAmount(v1.mValue + v2.mValue);
{
int64 iv1, iv2, s;
if (v1.mIsNegative) iv1 = -v1.mValue;
else iv1 = v1.mValue;
if (v2.mIsNegative) iv2 = -v2.mValue;
else iv2 = v2.mValue;
s = iv1 + iv2;
if (s >= 0) return STAmount(s, false);
else return STAmount(-s, true);
}
if (v1.isZero()) return v2;
if (v2.isZero()) return v1;
while (v1.mOffset < v2.mOffset)
int ov1 = v1.mOffset, ov2 = v2.mOffset;
int64 vv1 = v1.mValue, vv2 = v2.mValue;
if (v1.mIsNegative) vv1 = -vv1;
if (v2.mIsNegative) vv2 = -vv2;
while (ov1 < ov2)
{
v1.mValue /= 10;
++v1.mOffset;
vv1 /= 10;
++ov1;
}
while (v2.mOffset < v1.mOffset)
while (ov2 < ov1)
{
v2.mValue /= 10;
++v2.mOffset;
vv2 /= 10;
++ov2;
}
// this addition cannot overflow a uint64, it can overflow an STAmount and the constructor will throw
return STAmount(v1.name, v1.mCurrency, v1.mValue + v2.mValue, v1.mOffset);
// this addition cannot overflow an int64, it can overflow an STAmount and the constructor will throw
int64 fv = vv1 + vv2;
if (fv >= 0)
return STAmount(v1.name, v1.mCurrency, fv, ov1, false);
else
return STAmount(v1.name, v1.mCurrency, -fv, ov1, true);
}
STAmount operator-(STAmount v1, STAmount v2)
STAmount operator-(const STAmount& v1, const STAmount& v2)
{
// FIXME
v1.throwComparable(v2);
if (v2.mIsNative)
{
if (v2.mValue > v1.mValue)
throw std::runtime_error("amount underflow");
return STAmount(v1.mValue - v2.mValue);
int64 iv1, iv2, s;
if (v1.mIsNegative) iv1 = -v1.mValue;
else iv1 = v1.mValue;
if (v2.mIsNegative) iv2 = -v2.mValue;
else iv2 = v2.mValue;
s = iv1 - iv2;
if (s >= 0) return STAmount(s, false);
else return STAmount(-s, true);
}
if (v2.isZero()) return v1;
if (v1.isZero() || (v2.mOffset > v1.mOffset) )
throw std::runtime_error("value underflow");
while (v1.mOffset > v2.mOffset)
{
v2.mValue /= 10;
++v2.mOffset;
}
if (v1.mValue < v2.mValue)
throw std::runtime_error("value underflow");
int ov1 = v1.mOffset, ov2 = v2.mOffset;
int64 vv1 = v1.mValue, vv2 = v2.mValue;
if (v1.mIsNegative) vv1 = -vv1;
if (v2.mIsNegative) vv2 = -vv2;
return STAmount(v1.name, v1.mCurrency, v1.mValue - v2.mValue, v1.mOffset);
while (ov1 < ov2)
{
vv1 /= 10;
++ov1;
}
while (ov2 < ov1)
{
vv2 /= 10;
++ov2;
}
// this subtraction cannot overflow an int64, it can overflow an STAmount and the constructor will throw
int64 fv = vv1 - vv2;
if (fv >= 0)
return STAmount(v1.name, v1.mCurrency, fv, ov1, false);
else
return STAmount(v1.name, v1.mCurrency, -fv, ov1, true);
}
STAmount divide(const STAmount& num, const STAmount& den, const uint160& currencyOut)

View File

@@ -220,21 +220,17 @@ protected:
static const uint64 cNotNative = 0x8000000000000000ull;
static const uint64 cPosNative = 0x4000000000000000ull;
STAmount(bool, uint64 value) : mValue(value), mOffset(0), mIsNative(true), mIsNegative(false) { ; }
STAmount(bool isNeg, uint64 value) : mValue(value), mOffset(0), mIsNative(true), mIsNegative(isNeg) { ; }
STAmount(const char *name, uint64 value, bool isNegative)
: SerializedType(name), mValue(value), mOffset(0), mIsNative(true), mIsNegative(isNegative)
{ ; }
STAmount(const char *nm, const uint160& cur, uint64 v, int off, bool isNegative)
: SerializedType(nm), mCurrency(cur), mValue(v), mOffset(off), mIsNative(false), mIsNegative(isNegative)
{ ; }
uint64 toUInt64() const;
public:
STAmount(uint64 v = 0) : mValue(v), mOffset(0), mIsNative(true), mIsNegative(false)
{ ; }
STAmount(uint64 v = 0, bool isNeg = false) : mValue(v), mOffset(0), mIsNative(true), mIsNegative(isNeg)
{ if (v==0) mIsNegative = false; }
STAmount(const char* n, uint64 v = 0)
: SerializedType(n), mValue(v), mOffset(0), mIsNative(true), mIsNegative(false)
@@ -244,8 +240,8 @@ public:
: mCurrency(currency), mValue(v), mOffset(off), mIsNegative(false)
{ canonicalize(); }
STAmount(const char* n, const uint160& currency, uint64 v = 0, int off = 0) : SerializedType(n),
mCurrency(currency), mValue(v), mOffset(off), mIsNegative(false)
STAmount(const char* n, const uint160& currency, uint64 v = 0, int off = 0, bool isNeg = false) :
SerializedType(n), mCurrency(currency), mValue(v), mOffset(off), mIsNegative(isNeg)
{ canonicalize(); }
static std::auto_ptr<SerializedType> deserialize(SerializerIterator& sit, const char* name)
@@ -303,8 +299,8 @@ public:
operator double() const;
friend STAmount operator+(STAmount v1, STAmount v2);
friend STAmount operator-(STAmount v1, STAmount v2);
friend STAmount operator+(const STAmount& v1, const STAmount& v2);
friend STAmount operator-(const STAmount& v1, const STAmount& v2);
friend STAmount divide(const STAmount& v1, const STAmount& v2, const uint160& currencyOut);
friend STAmount multiply(const STAmount& v1, const STAmount& v2, const uint160& currencyOut);