summaryrefslogtreecommitdiff
path: root/include/tools
diff options
context:
space:
mode:
Diffstat (limited to 'include/tools')
-rw-r--r--include/tools/bigint.hxx127
1 files changed, 51 insertions, 76 deletions
diff --git a/include/tools/bigint.hxx b/include/tools/bigint.hxx
index f8f57fc45de7..a880f81c748b 100644
--- a/include/tools/bigint.hxx
+++ b/include/tools/bigint.hxx
@@ -23,9 +23,11 @@
#include <tools/long.hxx>
#include <cassert>
+#include <compare>
+#include <limits>
#include <string_view>
-#define MAX_DIGITS 8
+#define MAX_DIGITS 4
class SAL_WARN_UNUSED TOOLS_DLLPUBLIC BigInt
{
@@ -33,21 +35,20 @@ private:
// we only use one of these two fields at a time
union {
sal_Int32 nVal;
- sal_uInt16 nNum[MAX_DIGITS];
+ sal_uInt32 nNum[MAX_DIGITS];
};
- sal_uInt8 nLen : 5; // current length, if 0, data is in nVal, otherwise data is in nNum
- bool bIsNeg : 1; // Is Sign negative?
+ sal_uInt8 nLen; // current length, if 0, data is in nVal, otherwise data is in nNum
+ bool bIsNeg; // Is Sign negative?
- TOOLS_DLLPRIVATE void MakeBigInt(BigInt const &);
+ TOOLS_DLLPRIVATE BigInt MakeBig() const;
TOOLS_DLLPRIVATE void Normalize();
- TOOLS_DLLPRIVATE void Mult(BigInt const &, sal_uInt16);
- TOOLS_DLLPRIVATE void Div(sal_uInt16, sal_uInt16 &);
- TOOLS_DLLPRIVATE bool IsLess(BigInt const &) const;
+ TOOLS_DLLPRIVATE static BigInt Mult(BigInt const &, sal_uInt32);
+ TOOLS_DLLPRIVATE void Div(sal_uInt32, sal_uInt32 &);
+ 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 DivLong(BigInt const &, BigInt &) const;
- TOOLS_DLLPRIVATE void ModLong(BigInt const &, BigInt &) const;
+ TOOLS_DLLPRIVATE void DivLong(BigInt const &, BigInt &, BigInt * = nullptr) const;
TOOLS_DLLPRIVATE bool ABS_IsLess(BigInt const &) const;
public:
@@ -65,32 +66,42 @@ public:
{
}
-#if SAL_TYPES_SIZEOFLONG == 4
- BigInt(int nValue)
- : nVal(nValue)
- , nLen(0)
- , bIsNeg(false)
- {
- }
-#endif
-
BigInt( double nVal );
BigInt( sal_uInt32 nVal );
BigInt( sal_Int64 nVal );
BigInt( const BigInt& rBigInt );
BigInt( std::u16string_view rString );
+ template <typename N>
+ requires(std::is_integral_v<N> && std::is_signed_v<N> && sizeof(N) <= sizeof(sal_Int32))
+ BigInt(N val)
+ : BigInt(sal_Int32(val))
+ {
+ }
+
+ template <typename N>
+ requires(std::is_integral_v<N> && std::is_unsigned_v<N> && sizeof(N) <= sizeof(sal_uInt32))
+ BigInt(N val)
+ : BigInt(sal_uInt32(val))
+ {
+ }
+
+ template <typename N>
+ requires(std::is_integral_v<N> && std::is_signed_v<N> && sizeof(N) == sizeof(sal_Int64))
+ BigInt(N val)
+ : BigInt(sal_Int64(val))
+ {
+ }
+
operator sal_Int16() const;
operator sal_uInt16() const;
operator sal_Int32() const;
operator sal_uInt32() const;
operator double() const;
-#if SAL_TYPES_SIZEOFPOINTER == 8
- operator tools::Long() const;
-#endif
+ operator sal_Int64() const;
- bool IsNeg() const;
- bool IsZero() const;
+ bool IsNeg() const { return !IsLong() ? bIsNeg : nVal < 0; }
+ bool IsZero() const { return IsLong() && nVal == 0; }
bool IsLong() const { return nLen == 0; }
void Abs();
@@ -107,20 +118,8 @@ public:
/* Scale and round value */
static tools::Long Scale(tools::Long nVal, tools::Long nMult, tools::Long nDiv);
- friend inline BigInt operator +( const BigInt& rVal1, const BigInt& rVal2 );
- friend inline BigInt operator -( const BigInt& rVal1, const BigInt& rVal2 );
- friend inline BigInt operator *( const BigInt& rVal1, const BigInt& rVal2 );
- friend inline BigInt operator /( const BigInt& rVal1, const BigInt& rVal2 );
- friend inline BigInt operator %( const BigInt& rVal1, const BigInt& rVal2 );
-
TOOLS_DLLPUBLIC friend bool operator==( const BigInt& rVal1, const BigInt& rVal2 );
- friend inline bool operator!=( const BigInt& rVal1, const BigInt& rVal2 );
- TOOLS_DLLPUBLIC friend bool operator< ( const BigInt& rVal1, const BigInt& rVal2 );
- friend inline bool operator> ( const BigInt& rVal1, const BigInt& rVal2 );
- friend inline bool operator<=( const BigInt& rVal1, const BigInt& rVal2 );
- friend inline bool operator>=( const BigInt& rVal1, const BigInt& rVal2 );
-
- friend class Fraction;
+ TOOLS_DLLPUBLIC friend std::strong_ordering operator<=> ( const BigInt& rVal1, const BigInt& rVal2 );
};
inline BigInt::operator sal_Int16() const
@@ -155,16 +154,25 @@ inline BigInt::operator sal_uInt32() const
return 0;
}
-#if SAL_TYPES_SIZEOFPOINTER == 8
-inline BigInt::operator tools::Long() const
+inline BigInt::operator sal_Int64() const
{
- // Clamp to int32 since long is int32 on Windows.
- if (nLen == 0)
- return nVal;
+ constexpr sal_uInt64 maxForPosInt64 = std::numeric_limits<sal_Int64>::max();
+ constexpr sal_uInt64 maxForNegInt64 = std::numeric_limits<sal_Int64>::min();
+ switch (nLen)
+ {
+ case 0:
+ return nVal;
+ case 1:
+ return bIsNeg ? -sal_Int64(nNum[0]) : nNum[0];
+ case 2:
+ if (sal_uInt64 n = (sal_uInt64(nNum[1]) << 32) + nNum[0]; bIsNeg && n <= maxForNegInt64)
+ return -sal_Int64(n); // maxForNegInt64 will convert correctly
+ else if (!bIsNeg && n <= maxForPosInt64)
+ return n;
+ }
assert(false && "out of range");
return 0;
}
-#endif
inline BigInt& BigInt::operator =( sal_Int32 nValue )
{
@@ -174,22 +182,6 @@ inline BigInt& BigInt::operator =( sal_Int32 nValue )
return *this;
}
-inline bool BigInt::IsNeg() const
-{
- if ( nLen == 0 )
- return (nVal < 0);
- else
- return bIsNeg;
-}
-
-inline bool BigInt::IsZero() const
-{
- if ( nLen != 0 )
- return false;
- else
- return (nVal == 0);
-}
-
inline void BigInt::Abs()
{
if ( nLen != 0 )
@@ -233,23 +225,6 @@ inline BigInt operator%( const BigInt &rVal1, const BigInt &rVal2 )
return aErg;
}
-inline bool operator!=( const BigInt& rVal1, const BigInt& rVal2 )
-{
- return !(rVal1 == rVal2);
-}
-
-inline bool operator>(const BigInt& rVal1, const BigInt& rVal2) { return rVal2 < rVal1; }
-
-inline bool operator<=( const BigInt& rVal1, const BigInt& rVal2 )
-{
- return !( rVal1 > rVal2);
-}
-
-inline bool operator>=( const BigInt& rVal1, const BigInt& rVal2 )
-{
- return !(rVal1 < rVal2);
-}
-
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */