Ensure that the sign is correctly preserved and transferred.

This commit is contained in:
John Ralls 2014-11-29 13:22:00 -08:00
parent 9e37ad27b3
commit f4c69dbc48

View File

@ -170,7 +170,7 @@ QofInt128
QofInt128::lcm(const QofInt128& b) const noexcept QofInt128::lcm(const QofInt128& b) const noexcept
{ {
auto common = gcd(b); auto common = gcd(b);
return *this / common * b; return *this / common * b.abs(); //Preserve our sign, discard the other's.
} }
/* Knuth section 4.6.3 */ /* Knuth section 4.6.3 */
@ -351,7 +351,7 @@ QofInt128::operator-= (const QofInt128& b) noexcept
if ((!isNeg() && b.isNeg()) || (isNeg() && !b.isNeg())) if ((!isNeg() && b.isNeg()) || (isNeg() && !b.isNeg()))
return this->operator+= (-b); return this->operator+= (-b);
bool operand_bigger {cmp (b) < 0}; bool operand_bigger {abs().cmp (b.abs()) < 0};
if (operand_bigger) if (operand_bigger)
{ {
m_flags ^= neg; // ^= flips the bit m_flags ^= neg; // ^= flips the bit
@ -494,6 +494,7 @@ div_multi_leg (uint64_t* u, size_t m, uint64_t* v, size_t n, QofInt128& q, QofIn
uint64_t qv[sublegs] {}; uint64_t qv[sublegs] {};
uint64_t d {(UINT64_C(1) << sublegbits)/(v[n - 1] + UINT64_C(1))}; uint64_t d {(UINT64_C(1) << sublegbits)/(v[n - 1] + UINT64_C(1))};
uint64_t carry {UINT64_C(0)}; uint64_t carry {UINT64_C(0)};
bool negative {q.isNeg()};
for (auto i = 0; i < m; ++i) for (auto i = 0; i < m; ++i)
{ {
u[i] = u[i] * d + carry; u[i] = u[i] * d + carry;
@ -580,6 +581,7 @@ div_multi_leg (uint64_t* u, size_t m, uint64_t* v, size_t n, QofInt128& q, QofIn
q = QofInt128 ((qv[3] << sublegbits) + qv[2], (qv[1] << sublegbits) + qv[0]); q = QofInt128 ((qv[3] << sublegbits) + qv[2], (qv[1] << sublegbits) + qv[0]);
r = QofInt128 ((u[3] << sublegbits) + u[2], (u[1] << sublegbits) + u[0]); r = QofInt128 ((u[3] << sublegbits) + u[2], (u[1] << sublegbits) + u[0]);
r /= d; r /= d;
if (negative) q = -q;
} }
void void
@ -587,6 +589,7 @@ div_single_leg (uint64_t* u, size_t m, uint64_t v, QofInt128& q, QofInt128& r) n
{ {
uint64_t qv[sublegs] {}; uint64_t qv[sublegs] {};
uint64_t carry {}; uint64_t carry {};
bool negative {q.isNeg()};
for (int i = m - 1; i >= 0; --i) for (int i = m - 1; i >= 0; --i)
{ {
qv[i] = u[i] / v; qv[i] = u[i] / v;
@ -601,6 +604,7 @@ div_single_leg (uint64_t* u, size_t m, uint64_t v, QofInt128& q, QofInt128& r) n
q = QofInt128 ((qv[3] << sublegbits) + qv[2], (qv[1] << sublegbits) + qv[0]); q = QofInt128 ((qv[3] << sublegbits) + qv[2], (qv[1] << sublegbits) + qv[0]);
r = QofInt128 ((u[3] << sublegbits) + u[2], (u[1] << sublegbits) + u[0]); r = QofInt128 ((u[3] << sublegbits) + u[2], (u[1] << sublegbits) + u[0]);
if (negative) q = -q;
} }
}// namespace }// namespace
@ -629,6 +633,10 @@ QofInt128::div (const QofInt128& b, QofInt128& q, QofInt128& r) noexcept
r.m_flags |= NaN; r.m_flags |= NaN;
return; return;
} }
if (isNeg())
q.m_flags |= neg;
if (b.isNeg()) if (b.isNeg())
q.m_flags ^= neg; q.m_flags ^= neg;