include/tools/bigint.hxx | 76 ++++++------ tools/qa/cppunit/test_bigint.cxx | 12 - tools/source/generic/bigint.cxx | 237 ++++++++++++++++++++------------------- vcl/source/control/longcurr.cxx | 13 -- 4 files changed, 172 insertions(+), 166 deletions(-)
New commits: commit 36df3f9ad2f71c122af3cf9fbc58c661f416658e Author: Mike Kaganski <[email protected]> AuthorDate: Wed Dec 20 12:17:31 2023 +0300 Commit: Mike Kaganski <[email protected]> CommitDate: Wed Dec 20 20:30:01 2023 +0100 Make BigInt::DivMod public, to allow optimized division Change-Id: I4f79c30b9ab997d01e59a0dec76986e74abfc11f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161053 Tested-by: Jenkins Reviewed-by: Mike Kaganski <[email protected]> diff --git a/include/tools/bigint.hxx b/include/tools/bigint.hxx index 1b089e173ef0..644bb4c3e29d 100644 --- a/include/tools/bigint.hxx +++ b/include/tools/bigint.hxx @@ -46,8 +46,7 @@ private: TOOLS_DLLPRIVATE void AddBig(BigInt& rB, BigInt& rRes); TOOLS_DLLPRIVATE void SubBig(BigInt& rB, BigInt& rRes); TOOLS_DLLPRIVATE void MultBig(BigInt const& rB, BigInt& rRes) const; - TOOLS_DLLPRIVATE void DivModBig(BigInt const& rB, BigInt& rRes, bool bMod) const; - TOOLS_DLLPRIVATE void DivMod(BigInt const& rVal, bool bMod); + TOOLS_DLLPRIVATE void DivModBig(BigInt const& rB, BigInt* pDiv, BigInt* pMod) const; public: BigInt() @@ -113,6 +112,8 @@ public: BigInt& operator =( sal_Int32 nValue ); + void DivMod(BigInt const& rVal, BigInt* pDiv, BigInt* pMod) const; + /* Scale and round value */ static tools::Long Scale(tools::Long nVal, tools::Long nMult, tools::Long nDiv); diff --git a/tools/source/generic/bigint.cxx b/tools/source/generic/bigint.cxx index 3f4a82ffe33e..240494dfc15d 100644 --- a/tools/source/generic/bigint.cxx +++ b/tools/source/generic/bigint.cxx @@ -276,7 +276,7 @@ void BigInt::MultBig(const BigInt& rB, BigInt& rRes) const } } -void BigInt::DivModBig(const BigInt& rB, BigInt& rRes, bool bMod) const +void BigInt::DivModBig(const BigInt& rB, BigInt* pDiv, BigInt* pMod) const { assert(IsBig() && rB.IsBig()); assert(nLen >= rB.nLen); @@ -299,6 +299,9 @@ void BigInt::DivModBig(const BigInt& rB, BigInt& rRes, bool bMod) const assert(nDenMostSig >= 0x100000000 / 2); const sal_uInt64 nDen2ndSig = rB.nLen > 1 ? den[rB.nLen - 2] : 0; + BigInt aTmp; + BigInt& rRes = pDiv ? *pDiv : aTmp; + for (size_t j = num.size() - 1; j >= den.size(); j--) { // guess divisor assert(num[j] < nDenMostSig || (num[j] == nDenMostSig && num[j - 1] == 0)); @@ -344,17 +347,19 @@ void BigInt::DivModBig(const BigInt& rB, BigInt& rRes, bool bMod) const } } - if (bMod) + if (pMod) { - rRes.nLen = DivInPlace(num, nMult, nMult); - assert(rRes.nLen <= MAX_DIGITS); - rRes.bIsNeg = bIsNeg; - std::copy_n(num.begin(), rRes.nLen, rRes.nNum); + pMod->nLen = DivInPlace(num, nMult, nMult); + assert(pMod->nLen <= MAX_DIGITS); + pMod->bIsNeg = bIsNeg; + std::copy_n(num.begin(), pMod->nLen, pMod->nNum); + pMod->Normalize(); } - else + if (pDiv) // rRes references pDiv { - rRes.bIsNeg = bIsNeg != rB.bIsNeg; - rRes.nLen = nLen - rB.nLen + 1; + pDiv->bIsNeg = bIsNeg != rB.bIsNeg; + pDiv->nLen = nLen - rB.nLen + 1; + pDiv->Normalize(); } } @@ -566,8 +571,9 @@ BigInt& BigInt::operator*=( const BigInt& rVal ) return *this; } -void BigInt::DivMod(const BigInt& rVal, bool bMod) +void BigInt::DivMod(const BigInt& rVal, BigInt* pDiv, BigInt* pMod) const { + assert(pDiv || pMod); // Avoid useless calls if (!rVal.IsBig()) { if ( rVal.nVal == 0 ) @@ -578,66 +584,99 @@ void BigInt::DivMod(const BigInt& rVal, bool bMod) if (rVal.nVal == 1) { - if (bMod) - *this = 0; + if (pDiv) + { + *pDiv = *this; + pDiv->Normalize(); + } + if (pMod) + *pMod = 0; return; } if (!IsBig()) { // No overflows may occur here - nVal = bMod ? nVal % rVal.nVal : nVal / rVal.nVal; + const sal_Int32 nDiv = nVal / rVal.nVal; // Compilers usually optimize adjacent + const sal_Int32 nMod = nVal % rVal.nVal; // / and % into a single instruction + if (pDiv) + *pDiv = nDiv; + if (pMod) + *pMod = nMod; return; } if ( rVal.nVal == -1 ) { - if (bMod) - *this = 0; - else - bIsNeg = !bIsNeg; + if (pDiv) + { + *pDiv = *this; + pDiv->bIsNeg = !bIsNeg; + pDiv->Normalize(); + } + if (pMod) + *pMod = 0; return; } // Divide BigInt with an sal_uInt32 sal_uInt32 nTmp; + bool bNegate; if ( rVal.nVal < 0 ) { nTmp = static_cast<sal_uInt32>(-rVal.nVal); - bIsNeg = !bIsNeg; + bNegate = true; } else + { nTmp = static_cast<sal_uInt32>(rVal.nVal); + bNegate = false; + } - nLen = DivInPlace({ nNum, nLen }, nTmp, nTmp); - if (bMod) - *this = BigInt(nTmp); + BigInt aTmp; + BigInt& rDiv = pDiv ? *pDiv : aTmp; + rDiv = *this; + rDiv.nLen = DivInPlace({ rDiv.nNum, rDiv.nLen }, nTmp, nTmp); + if (pDiv) + { + if (bNegate) + pDiv->bIsNeg = !pDiv->bIsNeg; + pDiv->Normalize(); + } + if (pMod) + { + *pMod = BigInt(nTmp); + } return; } BigInt tmpA = MakeBig(), tmpB = rVal.MakeBig(); if (tmpA.ABS_IsLessBig(tmpB)) { - if (!bMod) - *this = 0; + // First store *this to *pMod, then nullify *pDiv, to handle 'pDiv == this' case + if (pMod) + { + *pMod = *this; + pMod->Normalize(); + } + if (pDiv) + *pDiv = 0; return; } // Divide BigInt with BigInt - tmpA.DivModBig(tmpB, *this, bMod); + tmpA.DivModBig(tmpB, pDiv, pMod); } BigInt& BigInt::operator/=( const BigInt& rVal ) { - DivMod(rVal, false); - Normalize(); + DivMod(rVal, this, nullptr); return *this; } BigInt& BigInt::operator%=( const BigInt& rVal ) { - DivMod(rVal, true); - Normalize(); + DivMod(rVal, nullptr, this); return *this; } diff --git a/vcl/source/control/longcurr.cxx b/vcl/source/control/longcurr.cxx index ee9451d79655..587c99cf1724 100644 --- a/vcl/source/control/longcurr.cxx +++ b/vcl/source/control/longcurr.cxx @@ -56,10 +56,9 @@ OUString ImplGetCurr( const LocaleDataWrapper& rLocaleDataWrapper, const BigInt return rLocaleDataWrapper.getCurr( static_cast<tools::Long>(rNumber), nDigits, rCurrSymbol, bShowThousandSep ); BigInt aTmp( ImplPower10( nDigits ) ); - BigInt aInteger(rNumber.Abs()); - BigInt aFraction(aInteger); - aInteger /= aTmp; - aFraction %= aTmp; + BigInt aInteger; + BigInt aFraction; + rNumber.Abs().DivMod(aTmp, &aInteger, &aFraction); if ( !aInteger.IsZero() ) { aFraction += aTmp; @@ -71,9 +70,7 @@ OUString ImplGetCurr( const LocaleDataWrapper& rLocaleDataWrapper, const BigInt OUStringBuffer aTemplate(rLocaleDataWrapper.getCurr( static_cast<tools::Long>(aFraction), nDigits, rCurrSymbol, bShowThousandSep )); while( !aInteger.IsZero() ) { - aFraction = aInteger; - aFraction %= aTmp; - aInteger /= aTmp; + aInteger.DivMod(aTmp, &aInteger, &aFraction); if( !aInteger.IsZero() ) aFraction += aTmp; commit c684aa9cf33fdbae5bf5f05d2c391f27a140b56d Author: Mike Kaganski <[email protected]> AuthorDate: Wed Dec 20 11:02:08 2023 +0300 Commit: Mike Kaganski <[email protected]> CommitDate: Wed Dec 20 20:29:51 2023 +0100 Simplify and rename for clarity Change-Id: Ic97a2b313c6f7d9da540a8867f01362c2fe7b0d0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/161052 Tested-by: Jenkins Reviewed-by: Mike Kaganski <[email protected]> diff --git a/include/tools/bigint.hxx b/include/tools/bigint.hxx index 1a5a2284324a..1b089e173ef0 100644 --- a/include/tools/bigint.hxx +++ b/include/tools/bigint.hxx @@ -40,15 +40,14 @@ private: sal_uInt8 nLen; // current length, if 0, data is in nVal, otherwise data is in nNum bool bIsNeg; // Is Sign negative? - TOOLS_DLLPRIVATE BigInt MakeBig() const; - TOOLS_DLLPRIVATE void Normalize(); - TOOLS_DLLPRIVATE bool ABS_IsLessLong(BigInt const &) const; - TOOLS_DLLPRIVATE void AddLong(BigInt &, BigInt &); - TOOLS_DLLPRIVATE void SubLong(BigInt &, BigInt &); - TOOLS_DLLPRIVATE void MultLong(BigInt const &, BigInt &) const; - TOOLS_DLLPRIVATE void DivModLong(BigInt const &, BigInt &, bool) const; - TOOLS_DLLPRIVATE void DivMod(BigInt const &, bool); - TOOLS_DLLPRIVATE bool ABS_IsLess(BigInt const &) const; + TOOLS_DLLPRIVATE BigInt MakeBig() const; // Create a BigInt with minimal non-0 nLen + TOOLS_DLLPRIVATE void Normalize(); // Use nVal if possible, otherwise use minimal nLen + TOOLS_DLLPRIVATE bool ABS_IsLessBig(BigInt const& rVal) const; + TOOLS_DLLPRIVATE void AddBig(BigInt& rB, BigInt& rRes); + TOOLS_DLLPRIVATE void SubBig(BigInt& rB, BigInt& rRes); + TOOLS_DLLPRIVATE void MultBig(BigInt const& rB, BigInt& rRes) const; + TOOLS_DLLPRIVATE void DivModBig(BigInt const& rB, BigInt& rRes, bool bMod) const; + TOOLS_DLLPRIVATE void DivMod(BigInt const& rVal, bool bMod); public: BigInt() @@ -68,7 +67,7 @@ public: BigInt( double nVal ); BigInt( sal_uInt32 nVal ); BigInt( sal_Int64 nVal ); - BigInt( const BigInt& rBigInt ); + BigInt(const BigInt& rBigInt) = default; BigInt( std::u16string_view rString ); template <typename N> @@ -99,11 +98,11 @@ public: operator double() const; operator sal_Int64() const; - bool IsNeg() const { return !IsLong() ? bIsNeg : nVal < 0; } - bool IsZero() const { return IsLong() && nVal == 0; } - bool IsLong() const { return nLen == 0; } + bool IsNeg() const { return IsBig() ? bIsNeg : nVal < 0; } + bool IsZero() const { return !IsBig() && nVal == 0; } + bool IsBig() const { return nLen != 0; } - void Abs(); + BigInt Abs() const; BigInt& operator =( const BigInt& rVal ); BigInt& operator +=( const BigInt& rVal ); @@ -123,7 +122,7 @@ public: inline BigInt::operator sal_Int16() const { - if ( nLen == 0 && nVal >= SAL_MIN_INT16 && nVal <= SAL_MAX_INT16 ) + if (!IsBig() && nVal >= SAL_MIN_INT16 && nVal <= SAL_MAX_INT16) return static_cast<sal_Int16>(nVal); assert(false && "out of range"); return 0; @@ -131,7 +130,7 @@ inline BigInt::operator sal_Int16() const inline BigInt::operator sal_uInt16() const { - if ( nLen == 0 && nVal >= 0 && nVal <= SAL_MAX_UINT16 ) + if (!IsBig() && nVal >= 0 && nVal <= SAL_MAX_UINT16) return static_cast<sal_uInt16>(nVal); assert(false && "out of range"); return 0; @@ -139,7 +138,7 @@ inline BigInt::operator sal_uInt16() const inline BigInt::operator sal_Int32() const { - if (nLen == 0) + if (!IsBig()) return nVal; assert(false && "out of range"); return 0; @@ -147,7 +146,7 @@ inline BigInt::operator sal_Int32() const inline BigInt::operator sal_uInt32() const { - if ( nLen == 0 && nVal >= 0 ) + if (!IsBig() && nVal >= 0) return static_cast<sal_uInt32>(nVal); assert(false && "out of range"); return 0; @@ -181,47 +180,49 @@ inline BigInt& BigInt::operator =( sal_Int32 nValue ) return *this; } -inline void BigInt::Abs() +inline BigInt BigInt::Abs() const { - if ( nLen != 0 ) - bIsNeg = false; + BigInt aRes(*this); + if (IsBig()) + aRes.bIsNeg = false; else if ( nVal < 0 ) - nVal = -nVal; + aRes.nVal = -nVal; + return aRes; } inline BigInt operator+( const BigInt &rVal1, const BigInt &rVal2 ) { - BigInt aErg( rVal1 ); - aErg += rVal2; - return aErg; + BigInt aRes( rVal1 ); + aRes += rVal2; + return aRes; } inline BigInt operator-( const BigInt &rVal1, const BigInt &rVal2 ) { - BigInt aErg( rVal1 ); - aErg -= rVal2; - return aErg; + BigInt aRes( rVal1 ); + aRes -= rVal2; + return aRes; } inline BigInt operator*( const BigInt &rVal1, const BigInt &rVal2 ) { - BigInt aErg( rVal1 ); - aErg *= rVal2; - return aErg; + BigInt aRes( rVal1 ); + aRes *= rVal2; + return aRes; } inline BigInt operator/( const BigInt &rVal1, const BigInt &rVal2 ) { - BigInt aErg( rVal1 ); - aErg /= rVal2; - return aErg; + BigInt aRes( rVal1 ); + aRes /= rVal2; + return aRes; } inline BigInt operator%( const BigInt &rVal1, const BigInt &rVal2 ) { - BigInt aErg( rVal1 ); - aErg %= rVal2; - return aErg; + BigInt aRes( rVal1 ); + aRes %= rVal2; + return aRes; } #endif diff --git a/tools/qa/cppunit/test_bigint.cxx b/tools/qa/cppunit/test_bigint.cxx index 9a958836bb5e..065a2719b9b3 100644 --- a/tools/qa/cppunit/test_bigint.cxx +++ b/tools/qa/cppunit/test_bigint.cxx @@ -45,7 +45,7 @@ void BigIntTest::testConstructionFromLongLong() BigInt bi(static_cast<sal_Int64>(42)); CPPUNIT_ASSERT(!bi.IsZero()); CPPUNIT_ASSERT(!bi.IsNeg()); - CPPUNIT_ASSERT(bi.IsLong()); + CPPUNIT_ASSERT(!bi.IsBig()); CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(42), static_cast<sal_Int32>(bi)); } @@ -54,7 +54,7 @@ void BigIntTest::testConstructionFromLongLong() BigInt bi(static_cast<sal_Int64>(-42)); CPPUNIT_ASSERT(!bi.IsZero()); CPPUNIT_ASSERT(bi.IsNeg()); - CPPUNIT_ASSERT(bi.IsLong()); + CPPUNIT_ASSERT(!bi.IsBig()); CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(-42), static_cast<sal_Int32>(bi)); } @@ -63,7 +63,7 @@ void BigIntTest::testConstructionFromLongLong() BigInt bi(static_cast<sal_Int64>(std::numeric_limits<sal_Int32>::max())); CPPUNIT_ASSERT(!bi.IsZero()); CPPUNIT_ASSERT(!bi.IsNeg()); - CPPUNIT_ASSERT(bi.IsLong()); + CPPUNIT_ASSERT(!bi.IsBig()); CPPUNIT_ASSERT_EQUAL(std::numeric_limits<sal_Int32>::max(), static_cast<sal_Int32>(bi)); } @@ -72,7 +72,7 @@ void BigIntTest::testConstructionFromLongLong() BigInt bi(static_cast<sal_Int64>(std::numeric_limits<sal_Int32>::min())); CPPUNIT_ASSERT(!bi.IsZero()); CPPUNIT_ASSERT(bi.IsNeg()); - CPPUNIT_ASSERT(bi.IsLong()); + CPPUNIT_ASSERT(!bi.IsBig()); CPPUNIT_ASSERT_EQUAL(std::numeric_limits<sal_Int32>::min(), static_cast<sal_Int32>(bi)); } @@ -81,7 +81,7 @@ void BigIntTest::testConstructionFromLongLong() BigInt bi(static_cast<sal_Int64>(std::numeric_limits<sal_Int32>::max()) + 1); CPPUNIT_ASSERT(!bi.IsZero()); CPPUNIT_ASSERT(!bi.IsNeg()); - CPPUNIT_ASSERT(!bi.IsLong()); + CPPUNIT_ASSERT(bi.IsBig()); } // negative number not fitting to sal_Int32 @@ -89,7 +89,7 @@ void BigIntTest::testConstructionFromLongLong() BigInt bi(static_cast<sal_Int64>(std::numeric_limits<sal_Int32>::min()) - 1); CPPUNIT_ASSERT(!bi.IsZero()); CPPUNIT_ASSERT(bi.IsNeg()); - CPPUNIT_ASSERT(!bi.IsLong()); + CPPUNIT_ASSERT(bi.IsBig()); } } diff --git a/tools/source/generic/bigint.cxx b/tools/source/generic/bigint.cxx index 8d8afd0c3f64..3f4a82ffe33e 100644 --- a/tools/source/generic/bigint.cxx +++ b/tools/source/generic/bigint.cxx @@ -42,7 +42,7 @@ const sal_Int32 MY_MINLONG = -MY_MAXLONG; BigInt BigInt::MakeBig() const { - if (!IsLong()) + if (IsBig()) { BigInt ret(*this); while ( ret.nLen > 1 && ret.nNum[ret.nLen-1] == 0 ) @@ -67,8 +67,7 @@ BigInt BigInt::MakeBig() const void BigInt::Normalize() { - // nLen == 0 means that the active union member is nVal, otherwise nNum - if ( nLen != 0 ) + if (IsBig()) { while ( nLen > 1 && nNum[nLen-1] == 0 ) nLen--; @@ -96,7 +95,6 @@ void BigInt::Normalize() // run-time index checking in debug builds. static std::span<sal_uInt32> Mult(std::span<const sal_uInt32> aNum, sal_uInt32 nMul, std::span<sal_uInt32> retBuf) { - assert(aNum.size() <= MAX_DIGITS); assert(retBuf.size() >= aNum.size()); sal_uInt64 nK = 0; for (size_t i = 0; i < aNum.size(); i++) @@ -134,24 +132,23 @@ static size_t DivInPlace(std::span<sal_uInt32> aNum, sal_uInt32 nDiv, sal_uInt32 return aNum.size(); } -bool BigInt::ABS_IsLessLong(const BigInt& rVal) const +bool BigInt::ABS_IsLessBig(const BigInt& rVal) const { - assert(!IsLong() && !rVal.IsLong()); + assert(IsBig() && rVal.IsBig()); if ( rVal.nLen < nLen) return false; if ( rVal.nLen > nLen ) return true; - int i; - for ( i = nLen - 1; i > 0 && nNum[i] == rVal.nNum[i]; i-- ) - { - } + int i = nLen - 1; + while (i > 0 && nNum[i] == rVal.nNum[i]) + --i; return nNum[i] < rVal.nNum[i]; } -void BigInt::AddLong( BigInt& rB, BigInt& rErg ) +void BigInt::AddBig(BigInt& rB, BigInt& rRes) { - assert(!IsLong() && !rB.IsLong()); + assert(IsBig() && rB.IsBig()); if ( bIsNeg == rB.bIsNeg ) { int i; @@ -180,34 +177,33 @@ void BigInt::AddLong( BigInt& rB, BigInt& rErg ) k = 1; else k = 0; - rErg.nNum[i] = static_cast<sal_uInt32>(nZ); + rRes.nNum[i] = static_cast<sal_uInt32>(nZ); } // If an overflow occurred, add to solution if (k) { assert(i < MAX_DIGITS); - rErg.nNum[i] = 1; + rRes.nNum[i] = 1; len++; } // Set length and sign - rErg.nLen = len; - rErg.bIsNeg = bIsNeg; + rRes.nLen = len; + rRes.bIsNeg = bIsNeg; } // If one of the values is negative, perform subtraction instead else { bIsNeg = !bIsNeg; - rB.SubLong(*this, rErg); + rB.SubBig(*this, rRes); bIsNeg = !bIsNeg; } } -void BigInt::SubLong( BigInt& rB, BigInt& rErg ) +void BigInt::SubBig(BigInt& rB, BigInt& rRes) { - assert(!IsLong() && !rB.IsLong()); + assert(IsBig() && rB.IsBig()); if ( bIsNeg == rB.bIsNeg ) { - int i; char len; // if length of the two values differ, fill remaining positions @@ -215,74 +211,74 @@ void BigInt::SubLong( BigInt& rB, BigInt& rErg ) if (nLen >= rB.nLen) { len = nLen; - for (i = rB.nLen; i < len; i++) + for (int i = rB.nLen; i < len; i++) rB.nNum[i] = 0; } else { len = rB.nLen; - for (i = nLen; i < len; i++) + for (int i = nLen; i < len; i++) nNum[i] = 0; } - const bool bThisIsLess = ABS_IsLessLong(rB); + const bool bThisIsLess = ABS_IsLessBig(rB); BigInt& rGreater = bThisIsLess ? rB : *this; BigInt& rSmaller = bThisIsLess ? *this : rB; sal_Int64 k = 0; - for (i = 0; i < len; i++) + for (int i = 0; i < len; i++) { sal_Int64 nZ = static_cast<sal_Int64>(rGreater.nNum[i]) - static_cast<sal_Int64>(rSmaller.nNum[i]) + k; if (nZ < 0) k = -1; else k = 0; - rErg.nNum[i] = static_cast<sal_uInt32>(nZ); + rRes.nNum[i] = static_cast<sal_uInt32>(nZ); } // if a < b, revert sign - rErg.bIsNeg = bThisIsLess ? !bIsNeg : bIsNeg; - rErg.nLen = len; + rRes.bIsNeg = bThisIsLess ? !bIsNeg : bIsNeg; + rRes.nLen = len; } // If one of the values is negative, perform addition instead else { bIsNeg = !bIsNeg; - AddLong(rB, rErg); + AddBig(rB, rRes); bIsNeg = !bIsNeg; - rErg.bIsNeg = bIsNeg; + rRes.bIsNeg = bIsNeg; } } -void BigInt::MultLong( const BigInt& rB, BigInt& rErg ) const +void BigInt::MultBig(const BigInt& rB, BigInt& rRes) const { - assert(!IsLong() && !rB.IsLong()); + assert(IsBig() && rB.IsBig()); - rErg.bIsNeg = bIsNeg != rB.bIsNeg; - rErg.nLen = nLen + rB.nLen; - assert(rErg.nLen <= MAX_DIGITS); + rRes.bIsNeg = bIsNeg != rB.bIsNeg; + rRes.nLen = nLen + rB.nLen; + assert(rRes.nLen <= MAX_DIGITS); - int i; - for (i = 0; i < rErg.nLen; i++) - rErg.nNum[i] = 0; + for (int i = 0; i < rRes.nLen; i++) + rRes.nNum[i] = 0; for (int j = 0; j < rB.nLen; j++) { sal_uInt64 k = 0; + int i; for (i = 0; i < nLen; i++) { sal_uInt64 nZ = static_cast<sal_uInt64>(nNum[i]) * static_cast<sal_uInt64>(rB.nNum[j]) + - static_cast<sal_uInt64>(rErg.nNum[i + j]) + k; - rErg.nNum[i + j] = static_cast<sal_uInt32>(nZ); + static_cast<sal_uInt64>(rRes.nNum[i + j]) + k; + rRes.nNum[i + j] = static_cast<sal_uInt32>(nZ); k = nZ >> 32; } - rErg.nNum[i + j] = k; + rRes.nNum[i + j] = k; } } -void BigInt::DivModLong(const BigInt& rB, BigInt& rErg, bool bMod) const +void BigInt::DivModBig(const BigInt& rB, BigInt& rRes, bool bMod) const { - assert(!IsLong() && !rB.IsLong()); + assert(IsBig() && rB.IsBig()); assert(nLen >= rB.nLen); assert(rB.nNum[rB.nLen - 1] != 0); @@ -331,10 +327,10 @@ void BigInt::DivModLong(const BigInt& rB, BigInt& rErg, bool bMod) const sal_uInt32& rNum(num[j - den.size() + i]); rNum -= nK; if (num[j - den.size() + i] == 0) - rErg.nNum[j - den.size()] = nQ; + rRes.nNum[j - den.size()] = nQ; else { - rErg.nNum[j - den.size()] = nQ - 1; + rRes.nNum[j - den.size()] = nQ - 1; nK = 0; for (i = 0; i < den.size(); i++) { @@ -350,39 +346,18 @@ void BigInt::DivModLong(const BigInt& rB, BigInt& rErg, bool bMod) const if (bMod) { - rErg.nLen = DivInPlace(num, nMult, nMult); - assert(rErg.nLen <= MAX_DIGITS); - rErg.bIsNeg = bIsNeg; - std::copy_n(num.begin(), rErg.nLen, rErg.nNum); + rRes.nLen = DivInPlace(num, nMult, nMult); + assert(rRes.nLen <= MAX_DIGITS); + rRes.bIsNeg = bIsNeg; + std::copy_n(num.begin(), rRes.nLen, rRes.nNum); } else { - rErg.bIsNeg = bIsNeg != rB.bIsNeg; - rErg.nLen = nLen - rB.nLen + 1; + rRes.bIsNeg = bIsNeg != rB.bIsNeg; + rRes.nLen = nLen - rB.nLen + 1; } } -bool BigInt::ABS_IsLess( const BigInt& rB ) const -{ - if (nLen != 0 || rB.nLen != 0) - return MakeBig().ABS_IsLessLong(rB.MakeBig()); - - if ( nVal < 0 ) - return nVal > (rB.nVal < 0 ? rB.nVal : -rB.nVal); - else - return nVal < (rB.nVal < 0 ? -rB.nVal : rB.nVal); -} - -BigInt::BigInt( const BigInt& rBigInt ) - : nLen(0) - , bIsNeg(false) -{ - if ( rBigInt.nLen != 0 ) - memcpy( static_cast<void*>(this), static_cast<const void*>(&rBigInt), sizeof( BigInt ) ); - else - nVal = rBigInt.nVal; -} - BigInt::BigInt( std::u16string_view rString ) : nLen(0) { @@ -407,7 +382,7 @@ BigInt::BigInt( std::u16string_view rString ) *this += *p - '0'; p++; } - if ( nLen != 0 ) + if (IsBig()) bIsNeg = bNeg; else if( bNeg ) nVal = -nVal; @@ -447,7 +422,7 @@ BigInt::BigInt( double nValue ) nLen = i; - if ( i < 3 ) + if ( i < 2 ) Normalize(); } } @@ -480,19 +455,14 @@ BigInt::BigInt( sal_Int64 nValue ) } else { - sal_uInt64 nUValue = static_cast<sal_uInt64>(bIsNeg ? -nValue : nValue); - for (int i = 0; (i != sizeof(sal_uInt64) / 4) && (nUValue != 0); ++i) - { - nNum[i] = static_cast<sal_uInt32>(nUValue); - nUValue = nUValue >> 32; - ++nLen; - } + for (sal_uInt64 n = static_cast<sal_uInt64>(bIsNeg ? -nValue : nValue); n != 0; n >>= 32) + nNum[nLen++] = static_cast<sal_uInt32>(n); } } BigInt::operator double() const { - if (IsLong()) + if (!IsBig()) return static_cast<double>(nVal); else { @@ -518,7 +488,7 @@ BigInt& BigInt::operator=( const BigInt& rBigInt ) if (this == &rBigInt) return *this; - if ( rBigInt.nLen != 0 ) + if (rBigInt.IsBig()) memcpy( static_cast<void*>(this), static_cast<const void*>(&rBigInt), sizeof( BigInt ) ); else { @@ -530,7 +500,7 @@ BigInt& BigInt::operator=( const BigInt& rBigInt ) BigInt& BigInt::operator+=( const BigInt& rVal ) { - if ( nLen == 0 && rVal.nLen == 0 ) + if (!IsBig() && !rVal.IsBig()) { if( nVal <= MY_MAXLONG && rVal.nVal <= MY_MAXLONG && nVal >= MY_MINLONG && rVal.nVal >= MY_MINLONG ) @@ -547,14 +517,14 @@ BigInt& BigInt::operator+=( const BigInt& rVal ) } BigInt aTmp2 = rVal.MakeBig(); - MakeBig().AddLong(aTmp2, *this); + MakeBig().AddBig(aTmp2, *this); Normalize(); return *this; } BigInt& BigInt::operator-=( const BigInt& rVal ) { - if ( nLen == 0 && rVal.nLen == 0 ) + if (!IsBig() && !rVal.IsBig()) { if ( nVal <= MY_MAXLONG && rVal.nVal <= MY_MAXLONG && nVal >= MY_MINLONG && rVal.nVal >= MY_MINLONG ) @@ -571,7 +541,7 @@ BigInt& BigInt::operator-=( const BigInt& rVal ) } BigInt aTmp2 = rVal.MakeBig(); - MakeBig().SubLong(aTmp2, *this); + MakeBig().SubBig(aTmp2, *this); Normalize(); return *this; } @@ -581,7 +551,7 @@ BigInt& BigInt::operator*=( const BigInt& rVal ) static const sal_Int32 MY_MAXSHORT = 0x00007fff; static const sal_Int32 MY_MINSHORT = -MY_MAXSHORT; - if ( nLen == 0 && rVal.nLen == 0 + if (!IsBig() && !rVal.IsBig() && nVal <= MY_MAXSHORT && rVal.nVal <= MY_MAXSHORT && nVal >= MY_MINSHORT && rVal.nVal >= MY_MINSHORT ) // TODO: not optimal !!! W.P. @@ -590,7 +560,7 @@ BigInt& BigInt::operator*=( const BigInt& rVal ) } else { - rVal.MakeBig().MultLong(MakeBig(), *this); + rVal.MakeBig().MultBig(MakeBig(), *this); Normalize(); } return *this; @@ -598,7 +568,7 @@ BigInt& BigInt::operator*=( const BigInt& rVal ) void BigInt::DivMod(const BigInt& rVal, bool bMod) { - if ( rVal.nLen == 0 ) + if (!rVal.IsBig()) { if ( rVal.nVal == 0 ) { @@ -613,7 +583,7 @@ void BigInt::DivMod(const BigInt& rVal, bool bMod) return; } - if ( nLen == 0 ) + if (!IsBig()) { // No overflows may occur here nVal = bMod ? nVal % rVal.nVal : nVal / rVal.nVal; @@ -646,7 +616,7 @@ void BigInt::DivMod(const BigInt& rVal, bool bMod) } BigInt tmpA = MakeBig(), tmpB = rVal.MakeBig(); - if (tmpA.ABS_IsLessLong(tmpB)) + if (tmpA.ABS_IsLessBig(tmpB)) { if (!bMod) *this = 0; @@ -654,7 +624,7 @@ void BigInt::DivMod(const BigInt& rVal, bool bMod) } // Divide BigInt with BigInt - tmpA.DivModLong(tmpB, *this, bMod); + tmpA.DivModBig(tmpB, *this, bMod); } BigInt& BigInt::operator/=( const BigInt& rVal ) @@ -673,7 +643,7 @@ BigInt& BigInt::operator%=( const BigInt& rVal ) bool operator==( const BigInt& rVal1, const BigInt& rVal2 ) { - if (rVal1.IsLong() && rVal2.IsLong()) + if (!rVal1.IsBig() && !rVal2.IsBig()) return rVal1.nVal == rVal2.nVal; BigInt nA = rVal1.MakeBig(), nB = rVal2.MakeBig(); @@ -683,7 +653,7 @@ bool operator==( const BigInt& rVal1, const BigInt& rVal2 ) std::strong_ordering operator<=>(const BigInt& rVal1, const BigInt& rVal2) { - if (rVal1.IsLong() && rVal2.IsLong()) + if (!rVal1.IsBig() && !rVal2.IsBig()) return rVal1.nVal <=> rVal2.nVal; BigInt nA = rVal1.MakeBig(), nB = rVal2.MakeBig(); diff --git a/vcl/source/control/longcurr.cxx b/vcl/source/control/longcurr.cxx index 1d942d1e5608..ee9451d79655 100644 --- a/vcl/source/control/longcurr.cxx +++ b/vcl/source/control/longcurr.cxx @@ -56,11 +56,9 @@ OUString ImplGetCurr( const LocaleDataWrapper& rLocaleDataWrapper, const BigInt return rLocaleDataWrapper.getCurr( static_cast<tools::Long>(rNumber), nDigits, rCurrSymbol, bShowThousandSep ); BigInt aTmp( ImplPower10( nDigits ) ); - BigInt aInteger( rNumber ); - aInteger.Abs(); + BigInt aInteger(rNumber.Abs()); + BigInt aFraction(aInteger); aInteger /= aTmp; - BigInt aFraction( rNumber ); - aFraction.Abs(); aFraction %= aTmp; if ( !aInteger.IsZero() ) {
