/src/libreoffice/include/tools/bigint.hxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | #ifndef INCLUDED_TOOLS_BIGINT_HXX |
20 | | #define INCLUDED_TOOLS_BIGINT_HXX |
21 | | |
22 | | #include <tools/toolsdllapi.h> |
23 | | #include <tools/long.hxx> |
24 | | |
25 | | #include <cassert> |
26 | | #include <compare> |
27 | | #include <limits> |
28 | | #include <string_view> |
29 | | |
30 | 0 | #define MAX_DIGITS 4 |
31 | | |
32 | | class SAL_WARN_UNUSED TOOLS_DLLPUBLIC BigInt |
33 | | { |
34 | | private: |
35 | | // we only use one of these two fields at a time |
36 | | union { |
37 | | sal_Int32 nVal; |
38 | | sal_uInt32 nNum[MAX_DIGITS]; |
39 | | }; |
40 | | sal_uInt8 nLen; // current length, if 0, data is in nVal, otherwise data is in nNum |
41 | | bool bIsNeg; // Is Sign negative? |
42 | | |
43 | | TOOLS_DLLPRIVATE BigInt MakeBig() const; // Create a BigInt with minimal non-0 nLen |
44 | | TOOLS_DLLPRIVATE void Normalize(); // Use nVal if possible, otherwise use minimal nLen |
45 | | TOOLS_DLLPRIVATE bool ABS_IsLessBig(BigInt const& rVal) const; |
46 | | TOOLS_DLLPRIVATE void AddBig(BigInt& rB, BigInt& rRes); |
47 | | TOOLS_DLLPRIVATE void SubBig(BigInt& rB, BigInt& rRes); |
48 | | TOOLS_DLLPRIVATE void MultBig(BigInt const& rB, BigInt& rRes) const; |
49 | | TOOLS_DLLPRIVATE void DivModBig(BigInt const& rB, BigInt* pDiv, BigInt* pMod) const; |
50 | | |
51 | | public: |
52 | | BigInt() |
53 | 652k | : nVal(0) |
54 | 652k | , nLen(0) |
55 | 652k | , bIsNeg(false) |
56 | 652k | { |
57 | 652k | } |
58 | | |
59 | | BigInt(sal_Int32 nValue) |
60 | 113k | : nVal(nValue) |
61 | 113k | , nLen(0) |
62 | 113k | , bIsNeg(false) |
63 | 113k | { |
64 | 113k | } |
65 | | |
66 | | BigInt( double nVal ); |
67 | | BigInt( sal_uInt32 nVal ); |
68 | | BigInt( sal_Int64 nVal ); |
69 | | BigInt(const BigInt& rBigInt) = default; |
70 | | BigInt( std::u16string_view rString ); |
71 | | |
72 | | template <typename N> |
73 | | requires(std::is_integral_v<N> && std::is_signed_v<N> && sizeof(N) <= sizeof(sal_Int32)) |
74 | | BigInt(N val) |
75 | 0 | : BigInt(sal_Int32(val)) |
76 | 0 | { |
77 | 0 | } |
78 | | |
79 | | template <typename N> |
80 | | requires(std::is_integral_v<N> && std::is_unsigned_v<N> && sizeof(N) <= sizeof(sal_uInt32)) |
81 | | BigInt(N val) |
82 | | : BigInt(sal_uInt32(val)) |
83 | | { |
84 | | } |
85 | | |
86 | | template <typename N> |
87 | | requires(std::is_integral_v<N> && std::is_signed_v<N> && sizeof(N) == sizeof(sal_Int64)) |
88 | | BigInt(N val) |
89 | | : BigInt(sal_Int64(val)) |
90 | | { |
91 | | } |
92 | | |
93 | | operator sal_Int16() const; |
94 | | operator sal_uInt16() const; |
95 | | operator sal_Int32() const; |
96 | | operator sal_uInt32() const; |
97 | | operator double() const; |
98 | | operator sal_Int64() const; |
99 | | |
100 | 1.54M | bool IsNeg() const { return IsBig() ? bIsNeg : nVal < 0; } |
101 | 0 | bool IsZero() const { return !IsBig() && nVal == 0; } |
102 | 12.1M | bool IsBig() const { return nLen != 0; } |
103 | | |
104 | | BigInt Abs() const; |
105 | | |
106 | | BigInt& operator =( const BigInt& rVal ); |
107 | | BigInt& operator +=( const BigInt& rVal ); |
108 | | BigInt& operator -=( const BigInt& rVal ); |
109 | | BigInt& operator *=( const BigInt& rVal ); |
110 | | BigInt& operator /=( const BigInt& rVal ); |
111 | | BigInt& operator %=( const BigInt& rVal ); |
112 | | |
113 | | BigInt& operator =( sal_Int32 nValue ); |
114 | | |
115 | | void DivMod(BigInt const& rVal, BigInt* pDiv, BigInt* pMod) const; |
116 | | |
117 | | /* Scale and round value */ |
118 | | static tools::Long Scale(tools::Long nVal, tools::Long nMult, tools::Long nDiv); |
119 | | |
120 | | TOOLS_DLLPUBLIC friend bool operator==( const BigInt& rVal1, const BigInt& rVal2 ); |
121 | | TOOLS_DLLPUBLIC friend std::strong_ordering operator<=> ( const BigInt& rVal1, const BigInt& rVal2 ); |
122 | | }; |
123 | | |
124 | | inline BigInt::operator sal_Int16() const |
125 | 0 | { |
126 | 0 | if (!IsBig() && nVal >= SAL_MIN_INT16 && nVal <= SAL_MAX_INT16) |
127 | 0 | return static_cast<sal_Int16>(nVal); |
128 | 0 | assert(false && "out of range"); |
129 | 0 | return 0; |
130 | 0 | } Unexecuted instantiation: BigInt::operator short() const Unexecuted instantiation: BigInt::operator short() const |
131 | | |
132 | | inline BigInt::operator sal_uInt16() const |
133 | 0 | { |
134 | 0 | if (!IsBig() && nVal >= 0 && nVal <= SAL_MAX_UINT16) |
135 | 0 | return static_cast<sal_uInt16>(nVal); |
136 | 0 | assert(false && "out of range"); |
137 | 0 | return 0; |
138 | 0 | } |
139 | | |
140 | | inline BigInt::operator sal_Int32() const |
141 | 27.4k | { |
142 | 27.4k | if (!IsBig()) |
143 | 27.4k | return nVal; |
144 | 27.4k | assert(false && "out of range"); |
145 | 0 | return 0; |
146 | 27.4k | } |
147 | | |
148 | | inline BigInt::operator sal_uInt32() const |
149 | 0 | { |
150 | 0 | if (!IsBig() && nVal >= 0) |
151 | 0 | return static_cast<sal_uInt32>(nVal); |
152 | 0 | assert(false && "out of range"); |
153 | 0 | return 0; |
154 | 0 | } |
155 | | |
156 | | inline BigInt::operator sal_Int64() const |
157 | 1.57M | { |
158 | 1.57M | constexpr sal_uInt64 maxForPosInt64 = std::numeric_limits<sal_Int64>::max(); |
159 | 1.57M | constexpr sal_uInt64 maxForNegInt64 = std::numeric_limits<sal_Int64>::min(); |
160 | 1.57M | switch (nLen) |
161 | 1.57M | { |
162 | 1.55M | case 0: |
163 | 1.55M | return nVal; |
164 | 10.2k | case 1: |
165 | 10.2k | return bIsNeg ? -sal_Int64(nNum[0]) : nNum[0]; |
166 | 6.85k | case 2: |
167 | 6.85k | if (sal_uInt64 n = (sal_uInt64(nNum[1]) << 32) + nNum[0]; bIsNeg && n < maxForNegInt64) |
168 | 1.49k | return -sal_Int64(n); |
169 | 5.35k | else if ((bIsNeg && n == maxForNegInt64) || (!bIsNeg && n <= maxForPosInt64)) |
170 | 5.28k | return n; // maxForNegInt64 will convert correctly |
171 | 1.57M | } |
172 | 1.57M | assert(false && "out of range"); |
173 | 309 | return 0; |
174 | 1.57M | } |
175 | | |
176 | | inline BigInt& BigInt::operator =( sal_Int32 nValue ) |
177 | 1.49M | { |
178 | 1.49M | nLen = 0; |
179 | 1.49M | nVal = nValue; |
180 | | |
181 | 1.49M | return *this; |
182 | 1.49M | } |
183 | | |
184 | | inline BigInt BigInt::Abs() const |
185 | 0 | { |
186 | 0 | BigInt aRes(*this); |
187 | 0 | if (IsBig()) |
188 | 0 | aRes.bIsNeg = false; |
189 | 0 | else if ( nVal < 0 ) |
190 | 0 | { |
191 | 0 | if (nVal == std::numeric_limits<sal_Int32>::min()) |
192 | 0 | { |
193 | 0 | aRes.nNum[0] = -sal_Int64(std::numeric_limits<sal_Int32>::min()); |
194 | 0 | aRes.nLen = 1; |
195 | 0 | aRes.bIsNeg = false; |
196 | 0 | } |
197 | 0 | else |
198 | 0 | aRes.nVal = -nVal; |
199 | 0 | } |
200 | 0 | return aRes; |
201 | 0 | } |
202 | | |
203 | | inline BigInt operator+( const BigInt &rVal1, const BigInt &rVal2 ) |
204 | 0 | { |
205 | 0 | BigInt aRes( rVal1 ); |
206 | 0 | aRes += rVal2; |
207 | 0 | return aRes; |
208 | 0 | } |
209 | | |
210 | | inline BigInt operator-( const BigInt &rVal1, const BigInt &rVal2 ) |
211 | 0 | { |
212 | 0 | BigInt aRes( rVal1 ); |
213 | 0 | aRes -= rVal2; |
214 | 0 | return aRes; |
215 | 0 | } |
216 | | |
217 | | inline BigInt operator*( const BigInt &rVal1, const BigInt &rVal2 ) |
218 | 0 | { |
219 | 0 | BigInt aRes( rVal1 ); |
220 | 0 | aRes *= rVal2; |
221 | 0 | return aRes; |
222 | 0 | } |
223 | | |
224 | | inline BigInt operator/( const BigInt &rVal1, const BigInt &rVal2 ) |
225 | 0 | { |
226 | 0 | BigInt aRes( rVal1 ); |
227 | 0 | aRes /= rVal2; |
228 | 0 | return aRes; |
229 | 0 | } |
230 | | |
231 | | inline BigInt operator%( const BigInt &rVal1, const BigInt &rVal2 ) |
232 | 0 | { |
233 | 0 | BigInt aRes( rVal1 ); |
234 | 0 | aRes %= rVal2; |
235 | 0 | return aRes; |
236 | 0 | } |
237 | | |
238 | | #endif |
239 | | |
240 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |