Coverage Report

Created: 2026-02-14 09:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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: */