Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/tools/source/generic/bigint.cxx
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
20
#include <sal/config.h>
21
22
#include <osl/diagnose.h>
23
#include <tools/bigint.hxx>
24
25
#include <algorithm>
26
#include <cmath>
27
#include <cstring>
28
#include <limits>
29
#include <span>
30
31
/**
32
 * The range in which we can perform add/sub without fear of overflow
33
 */
34
const sal_Int32 MY_MAXLONG  = 0x3fffffff;
35
const sal_Int32 MY_MINLONG  = -MY_MAXLONG;
36
37
/*
38
 * The algorithms for Addition, Subtraction, Multiplication and Division
39
 * of large numbers originate from SEMINUMERICAL ALGORITHMS by
40
 * DONALD E. KNUTH in the series The Art of Computer Programming:
41
 * chapter 4.3.1. The Classical Algorithms.
42
 */
43
44
BigInt BigInt::MakeBig() const
45
42.7k
{
46
42.7k
    if (IsBig())
47
36.8k
    {
48
36.8k
        BigInt ret(*this);
49
36.8k
        while ( ret.nLen > 1 && ret.nNum[ret.nLen-1] == 0 )
50
0
            ret.nLen--;
51
36.8k
        return ret;
52
36.8k
    }
53
54
5.90k
    BigInt ret;
55
5.90k
    if (nVal < 0)
56
3.51k
    {
57
3.51k
        ret.bIsNeg = true;
58
3.51k
        ret.nNum[0] = -static_cast<sal_Int64>(nVal);
59
3.51k
    }
60
2.38k
    else
61
2.38k
    {
62
2.38k
        ret.bIsNeg = false;
63
2.38k
        ret.nNum[0] = nVal;
64
2.38k
    }
65
5.90k
    ret.nLen = 1;
66
5.90k
    return ret;
67
42.7k
}
68
69
void BigInt::Normalize()
70
21.7k
{
71
21.7k
    if (IsBig())
72
21.7k
    {
73
30.0k
        while ( nLen > 1 && nNum[nLen-1] == 0 )
74
8.31k
            nLen--;
75
76
21.7k
        if (nLen < 2)
77
6.54k
        {
78
6.54k
            static constexpr sal_uInt32 maxForPosInt32 = std::numeric_limits<sal_Int32>::max();
79
6.54k
            static constexpr sal_uInt32 maxForNegInt32 = -sal_Int64(std::numeric_limits<sal_Int32>::min());
80
6.54k
            sal_uInt32 nNum0 = nNum[0];
81
6.54k
            if (bIsNeg && nNum0 <= maxForNegInt32)
82
680
            {
83
680
                nVal = -sal_Int64(nNum0);
84
680
                nLen = 0;
85
680
            }
86
5.86k
            else if (!bIsNeg && nNum0 <= maxForPosInt32)
87
1.38k
            {
88
1.38k
                nVal = nNum0;
89
1.38k
                nLen = 0;
90
1.38k
            }
91
6.54k
        }
92
21.7k
    }
93
21.7k
}
94
95
// Normalization in DivLong requires that dividend is multiplied by a number, and the resulting
96
// value has 1 more 32-bit "digits". 'ret' provides enough room for that. Use of std::span gives
97
// run-time index checking in debug builds.
98
static std::span<sal_uInt32> Mult(std::span<const sal_uInt32> aNum, sal_uInt32 nMul, std::span<sal_uInt32> retBuf)
99
13.6k
{
100
13.6k
    assert(retBuf.size() >= aNum.size());
101
13.6k
    sal_uInt64 nK = 0;
102
38.7k
    for (size_t i = 0; i < aNum.size(); i++)
103
25.0k
    {
104
25.0k
        sal_uInt64 nTmp = static_cast<sal_uInt64>(aNum[i]) * nMul + nK;
105
25.0k
        nK = nTmp >> 32;
106
25.0k
        retBuf[i] = static_cast<sal_uInt32>(nTmp);
107
25.0k
    }
108
109
13.6k
    if ( nK )
110
4.52k
    {
111
4.52k
        assert(retBuf.size() > aNum.size());
112
4.52k
        retBuf[aNum.size()] = nK;
113
4.52k
        return retBuf.subspan(0, aNum.size() + 1);
114
4.52k
    }
115
116
9.16k
    return retBuf.subspan(0, aNum.size());
117
13.6k
}
118
119
static size_t DivInPlace(std::span<sal_uInt32> aNum, sal_uInt32 nDiv, sal_uInt32& rRem)
120
310
{
121
310
    assert(aNum.size() > 0);
122
310
    sal_uInt64 nK = 0;
123
930
    for (int i = aNum.size() - 1; i >= 0; i--)
124
620
    {
125
620
        sal_uInt64 nTmp = aNum[i] + (nK << 32);
126
620
        aNum[i] = nTmp / nDiv;
127
620
        nK            = nTmp % nDiv;
128
620
    }
129
310
    rRem = nK;
130
131
310
    if (aNum[aNum.size() - 1] == 0)
132
6
        return aNum.size() - 1;
133
134
304
    return aNum.size();
135
310
}
136
137
bool BigInt::ABS_IsLessBig(const BigInt& rVal) const
138
6.84k
{
139
6.84k
    assert(IsBig() && rVal.IsBig());
140
6.84k
    if ( rVal.nLen < nLen)
141
2.31k
        return false;
142
4.52k
    if ( rVal.nLen > nLen )
143
0
        return true;
144
145
4.52k
    int i = nLen - 1;
146
4.52k
    while (i > 0 && nNum[i] == rVal.nNum[i])
147
0
        --i;
148
4.52k
    return nNum[i] < rVal.nNum[i];
149
4.52k
}
150
151
void BigInt::AddBig(BigInt& rB, BigInt& rRes)
152
7.15k
{
153
7.15k
    assert(IsBig() && rB.IsBig());
154
7.15k
    if ( bIsNeg == rB.bIsNeg )
155
7.15k
    {
156
7.15k
        int  i;
157
7.15k
        char len;
158
159
        // if length of the two values differ, fill remaining positions
160
        // of the smaller value with zeros.
161
7.15k
        if (nLen >= rB.nLen)
162
7.15k
        {
163
7.15k
            len = nLen;
164
14.3k
            for (i = rB.nLen; i < len; i++)
165
7.15k
                rB.nNum[i] = 0;
166
7.15k
        }
167
0
        else
168
0
        {
169
0
            len = rB.nLen;
170
0
            for (i = nLen; i < len; i++)
171
0
                nNum[i] = 0;
172
0
        }
173
174
        // Add numerals, starting from the back
175
7.15k
        sal_Int64 k = 0;
176
21.4k
        for (i = 0; i < len; i++) {
177
14.3k
            sal_Int64 nZ = static_cast<sal_Int64>(nNum[i]) + static_cast<sal_Int64>(rB.nNum[i]) + k;
178
14.3k
            if (nZ > sal_Int64(std::numeric_limits<sal_uInt32>::max()))
179
3.61k
                k = 1;
180
10.6k
            else
181
10.6k
                k = 0;
182
14.3k
            rRes.nNum[i] = static_cast<sal_uInt32>(nZ);
183
14.3k
        }
184
        // If an overflow occurred, add to solution
185
7.15k
        if (k)
186
0
        {
187
0
            assert(i < MAX_DIGITS);
188
0
            rRes.nNum[i] = 1;
189
0
            len++;
190
0
        }
191
        // Set length and sign
192
7.15k
        rRes.nLen = len;
193
7.15k
        rRes.bIsNeg = bIsNeg;
194
7.15k
    }
195
    // If one of the values is negative, perform subtraction instead
196
0
    else
197
0
    {
198
0
        bIsNeg = !bIsNeg;
199
0
        rB.SubBig(*this, rRes);
200
0
        bIsNeg = !bIsNeg;
201
0
    }
202
7.15k
}
203
204
void BigInt::SubBig(BigInt& rB, BigInt& rRes)
205
3.27k
{
206
3.27k
    assert(IsBig() && rB.IsBig());
207
3.27k
    if ( bIsNeg == rB.bIsNeg )
208
0
    {
209
0
        char len;
210
211
        // if length of the two values differ, fill remaining positions
212
        // of the smaller value with zeros.
213
0
        if (nLen >= rB.nLen)
214
0
        {
215
0
            len = nLen;
216
0
            for (int i = rB.nLen; i < len; i++)
217
0
                rB.nNum[i] = 0;
218
0
        }
219
0
        else
220
0
        {
221
0
            len = rB.nLen;
222
0
            for (int i = nLen; i < len; i++)
223
0
                nNum[i] = 0;
224
0
        }
225
226
0
        const bool bThisIsLess = ABS_IsLessBig(rB);
227
0
        BigInt& rGreater = bThisIsLess ? rB : *this;
228
0
        BigInt& rSmaller = bThisIsLess ? *this : rB;
229
230
0
        sal_Int64 k = 0;
231
0
        for (int i = 0; i < len; i++)
232
0
        {
233
0
            sal_Int64 nZ = static_cast<sal_Int64>(rGreater.nNum[i]) - static_cast<sal_Int64>(rSmaller.nNum[i]) + k;
234
0
            if (nZ < 0)
235
0
                k = -1;
236
0
            else
237
0
                k = 0;
238
0
            rRes.nNum[i] = static_cast<sal_uInt32>(nZ);
239
0
        }
240
241
        // if a < b, revert sign
242
0
        rRes.bIsNeg = bThisIsLess ? !bIsNeg : bIsNeg;
243
0
        rRes.nLen   = len;
244
0
    }
245
    // If one of the values is negative, perform addition instead
246
3.27k
    else
247
3.27k
    {
248
3.27k
        bIsNeg = !bIsNeg;
249
3.27k
        AddBig(rB, rRes);
250
3.27k
        bIsNeg = !bIsNeg;
251
3.27k
        rRes.bIsNeg = bIsNeg;
252
3.27k
    }
253
3.27k
}
254
255
void BigInt::MultBig(const BigInt& rB, BigInt& rRes) const
256
7.39k
{
257
7.39k
    assert(IsBig() && rB.IsBig());
258
259
7.39k
    rRes.bIsNeg = bIsNeg != rB.bIsNeg;
260
7.39k
    rRes.nLen = nLen + rB.nLen;
261
7.39k
    assert(rRes.nLen <= MAX_DIGITS);
262
263
28.4k
    for (int i = 0; i < rRes.nLen; i++)
264
21.0k
        rRes.nNum[i] = 0;
265
266
14.7k
    for (int j = 0; j < rB.nLen; j++)
267
7.39k
    {
268
7.39k
        sal_uInt64 k = 0;
269
7.39k
        int i;
270
21.0k
        for (i = 0; i < nLen; i++)
271
13.6k
        {
272
13.6k
            sal_uInt64 nZ = static_cast<sal_uInt64>(nNum[i]) * static_cast<sal_uInt64>(rB.nNum[j]) +
273
13.6k
                 static_cast<sal_uInt64>(rRes.nNum[i + j]) + k;
274
13.6k
            rRes.nNum[i + j] = static_cast<sal_uInt32>(nZ);
275
13.6k
            k = nZ >> 32;
276
13.6k
        }
277
7.39k
        rRes.nNum[i + j] = k;
278
7.39k
    }
279
7.39k
}
280
281
void BigInt::DivModBig(const BigInt& rB, BigInt* pDiv, BigInt* pMod) const
282
6.84k
{
283
6.84k
    assert(IsBig() && rB.IsBig());
284
6.84k
    assert(nLen >= rB.nLen);
285
286
6.84k
    assert(rB.nNum[rB.nLen - 1] != 0);
287
6.84k
    sal_uInt32 nMult = static_cast<sal_uInt32>(0x100000000 / (static_cast<sal_Int64>(rB.nNum[rB.nLen - 1]) + 1));
288
289
6.84k
    sal_uInt32 numBuf[MAX_DIGITS + 1]; // normalized dividend
290
6.84k
    auto num = Mult({ nNum, nLen }, nMult, numBuf);
291
6.84k
    if (num.size() == nLen)
292
2.31k
    {
293
2.31k
        num = std::span(numBuf, nLen + 1);
294
2.31k
        num[nLen] = 0;
295
2.31k
    }
296
297
6.84k
    sal_uInt32 denBuf[MAX_DIGITS + 1]; // normalized divisor
298
6.84k
    const auto den = Mult({ rB.nNum, rB.nLen }, nMult, denBuf);
299
6.84k
    assert(den.size() == rB.nLen);
300
6.84k
    const sal_uInt64 nDenMostSig = den[rB.nLen - 1];
301
6.84k
    assert(nDenMostSig >= 0x100000000 / 2);
302
6.84k
    const sal_uInt64 nDen2ndSig = rB.nLen > 1 ? den[rB.nLen - 2] : 0;
303
304
6.84k
    BigInt aTmp;
305
6.84k
    BigInt& rRes = pDiv ? *pDiv : aTmp;
306
307
16.0k
    for (size_t j = num.size() - 1; j >= den.size(); j--)
308
9.16k
    { // guess divisor
309
9.16k
        assert(num[j] < nDenMostSig || (num[j] == nDenMostSig && num[j - 1] == 0));
310
9.16k
        sal_uInt64 nTmp = ( static_cast<sal_uInt64>(num[j]) << 32 ) + num[j - 1];
311
9.16k
        sal_uInt32 nQ;
312
9.16k
        if (num[j] == nDenMostSig)
313
0
            nQ = 0xFFFFFFFF;
314
9.16k
        else
315
9.16k
            nQ = static_cast<sal_uInt32>(nTmp / nDenMostSig);
316
317
9.16k
        if (nDen2ndSig && (nDen2ndSig * nQ) > ((nTmp - nDenMostSig * nQ) << 32) + num[j - 2])
318
1.68k
            nQ--;
319
        // Start division
320
9.16k
        sal_uInt32 nK = 0;
321
9.16k
        size_t i;
322
22.8k
        for (i = 0; i < den.size(); i++)
323
13.6k
        {
324
13.6k
            nTmp = static_cast<sal_uInt64>(num[j - den.size() + i])
325
13.6k
                   - (static_cast<sal_uInt64>(den[i]) * nQ)
326
13.6k
                   - nK;
327
13.6k
            num[j - den.size() + i] = static_cast<sal_uInt32>(nTmp);
328
13.6k
            nK = static_cast<sal_uInt32>(nTmp >> 32);
329
13.6k
            if ( nK )
330
10.2k
                nK = static_cast<sal_uInt32>(0x100000000 - nK);
331
13.6k
        }
332
9.16k
        sal_uInt32& rNum(num[j - den.size() + i]);
333
9.16k
        rNum -= nK;
334
9.16k
        if (num[j - den.size() + i] == 0)
335
9.16k
            rRes.nNum[j - den.size()] = nQ;
336
0
        else
337
0
        {
338
0
            rRes.nNum[j - den.size()] = nQ - 1;
339
0
            nK = 0;
340
0
            for (i = 0; i < den.size(); i++)
341
0
            {
342
0
                nTmp = num[j - den.size() + i] + den[i] + nK;
343
0
                num[j - den.size() + i] = static_cast<sal_uInt32>(nTmp & 0xFFFFFFFF);
344
0
                if (nTmp > std::numeric_limits<sal_uInt32>::max())
345
0
                    nK = 1;
346
0
                else
347
0
                    nK = 0;
348
0
            }
349
0
        }
350
9.16k
    }
351
352
6.84k
    if (pMod)
353
0
    {
354
0
        pMod->nLen = DivInPlace(num, nMult, nMult);
355
0
        assert(pMod->nLen <= MAX_DIGITS);
356
0
        pMod->bIsNeg = bIsNeg;
357
0
        std::copy_n(num.begin(), pMod->nLen, pMod->nNum);
358
0
        pMod->Normalize();
359
0
    }
360
6.84k
    if (pDiv) // rRes references pDiv
361
6.84k
    {
362
6.84k
        pDiv->bIsNeg = bIsNeg != rB.bIsNeg;
363
6.84k
        pDiv->nLen = nLen - rB.nLen + 1;
364
6.84k
        pDiv->Normalize();
365
6.84k
    }
366
6.84k
}
367
368
BigInt::BigInt( std::u16string_view rString )
369
0
    : nLen(0)
370
0
{
371
0
    bIsNeg = false;
372
0
    nVal   = 0;
373
374
0
    bool bNeg = false;
375
0
    auto p = rString.begin();
376
0
    auto pEnd = rString.end();
377
0
    if (p == pEnd)
378
0
        return;
379
0
    if ( *p == '-' )
380
0
    {
381
0
        bNeg = true;
382
0
        p++;
383
0
    }
384
0
    if (p == pEnd)
385
0
        return;
386
0
    while( p != pEnd && *p >= '0' && *p <= '9' )
387
0
    {
388
0
        *this *= 10;
389
0
        *this += *p - '0';
390
0
        p++;
391
0
    }
392
0
    if (IsBig())
393
0
        bIsNeg = bNeg;
394
0
    else if( bNeg )
395
0
        nVal = -nVal;
396
0
}
397
398
BigInt::BigInt( double nValue )
399
0
    : nVal(0)
400
0
{
401
0
    if ( nValue < 0 )
402
0
    {
403
0
        nValue *= -1;
404
0
        bIsNeg  = true;
405
0
    }
406
0
    else
407
0
    {
408
0
        bIsNeg  = false;
409
0
    }
410
411
0
    if ( nValue < 1 )
412
0
    {
413
0
        nVal   = 0;
414
0
        nLen   = 0;
415
0
    }
416
0
    else
417
0
    {
418
0
        int i=0;
419
420
0
        while ( ( nValue > 0x100000000 ) && ( i < MAX_DIGITS ) )
421
0
        {
422
0
            nNum[i] = static_cast<sal_uInt32>(fmod( nValue, 0x100000000 ));
423
0
            nValue -= nNum[i];
424
0
            nValue /= 0x100000000;
425
0
            i++;
426
0
        }
427
0
        if ( i < MAX_DIGITS )
428
0
            nNum[i++] = static_cast<sal_uInt32>(nValue);
429
430
0
        nLen = i;
431
432
0
        if ( i < 2 )
433
0
            Normalize();
434
0
    }
435
0
}
436
437
BigInt::BigInt( sal_uInt32 nValue )
438
0
    : nVal(0)
439
0
    , bIsNeg(false)
440
0
{
441
0
    if ( nValue & 0x80000000U )
442
0
    {
443
0
        nNum[0] = nValue;
444
0
        nLen = 1;
445
0
    }
446
0
    else
447
0
    {
448
0
        nVal   = nValue;
449
0
        nLen   = 0;
450
0
    }
451
0
}
452
453
BigInt::BigInt( sal_Int64 nValue )
454
1.34M
    : nVal(0)
455
1.34M
{
456
1.34M
    bIsNeg = nValue < 0;
457
1.34M
    nLen = 0;
458
459
1.34M
    if ((nValue >= SAL_MIN_INT32) && (nValue <= SAL_MAX_INT32))
460
1.32M
    {
461
1.32M
        nVal = static_cast<sal_Int32>(nValue);
462
1.32M
    }
463
22.8k
    else
464
22.8k
    {
465
22.8k
        for (sal_uInt64 n = static_cast<sal_uInt64>(
466
22.8k
                 (bIsNeg && nValue != std::numeric_limits<sal_Int64>::min()) ? -nValue : nValue);
467
56.5k
             n != 0; n >>= 32)
468
33.7k
            nNum[nLen++] = static_cast<sal_uInt32>(n);
469
22.8k
    }
470
1.34M
}
471
472
BigInt::operator double() const
473
0
{
474
0
    if (!IsBig())
475
0
        return static_cast<double>(nVal);
476
0
    else
477
0
    {
478
0
        int     i = nLen-1;
479
0
        double  nRet = static_cast<double>(nNum[i]);
480
481
0
        while ( i )
482
0
        {
483
0
            nRet *= 0x100000000;
484
0
            i--;
485
0
            nRet += static_cast<double>(nNum[i]);
486
0
        }
487
488
0
        if ( bIsNeg )
489
0
            nRet *= -1;
490
491
0
        return nRet;
492
0
    }
493
0
}
494
495
BigInt& BigInt::operator=( const BigInt& rBigInt )
496
310
{
497
310
    if (this == &rBigInt)
498
310
        return *this;
499
500
0
    if (rBigInt.IsBig())
501
0
        memcpy( static_cast<void*>(this), static_cast<const void*>(&rBigInt), sizeof( BigInt ) );
502
0
    else
503
0
    {
504
0
        nLen = 0;
505
0
        nVal = rBigInt.nVal;
506
0
    }
507
0
    return *this;
508
310
}
509
510
BigInt& BigInt::operator+=( const BigInt& rVal )
511
333k
{
512
333k
    if (!IsBig() && !rVal.IsBig())
513
329k
    {
514
329k
        if( nVal <= MY_MAXLONG && rVal.nVal <= MY_MAXLONG
515
329k
            && nVal >= MY_MINLONG && rVal.nVal >= MY_MINLONG )
516
329k
        { // No overflows may occur here
517
329k
            nVal += rVal.nVal;
518
329k
            return *this;
519
329k
        }
520
521
0
        if( (nVal < 0) != (rVal.nVal < 0) )
522
0
        { // No overflows may occur here
523
0
            nVal += rVal.nVal;
524
0
            return *this;
525
0
        }
526
0
    }
527
528
3.88k
    BigInt aTmp2 = rVal.MakeBig();
529
3.88k
    MakeBig().AddBig(aTmp2, *this);
530
3.88k
    Normalize();
531
3.88k
    return *this;
532
333k
}
533
534
BigInt& BigInt::operator-=( const BigInt& rVal )
535
3.27k
{
536
3.27k
    if (!IsBig() && !rVal.IsBig())
537
0
    {
538
0
        if ( nVal <= MY_MAXLONG && rVal.nVal <= MY_MAXLONG &&
539
0
             nVal >= MY_MINLONG && rVal.nVal >= MY_MINLONG )
540
0
        { // No overflows may occur here
541
0
            nVal -= rVal.nVal;
542
0
            return *this;
543
0
        }
544
545
0
        if ( (nVal < 0) == (rVal.nVal < 0) )
546
0
        { // No overflows may occur here
547
0
            nVal -= rVal.nVal;
548
0
            return *this;
549
0
        }
550
0
    }
551
552
3.27k
    BigInt aTmp2 = rVal.MakeBig();
553
3.27k
    MakeBig().SubBig(aTmp2, *this);
554
3.27k
    Normalize();
555
3.27k
    return *this;
556
3.27k
}
557
558
BigInt& BigInt::operator*=( const BigInt& rVal )
559
336k
{
560
336k
    static const sal_Int32 MY_MAXSHORT = 0x00007fff;
561
336k
    static const sal_Int32 MY_MINSHORT = -MY_MAXSHORT;
562
563
336k
    if (!IsBig() && !rVal.IsBig()
564
329k
         && nVal <= MY_MAXSHORT && rVal.nVal <= MY_MAXSHORT
565
328k
         && nVal >= MY_MINSHORT && rVal.nVal >= MY_MINSHORT )
566
         // TODO: not optimal !!! W.P.
567
328k
    { // No overflows may occur here
568
328k
        nVal *= rVal.nVal;
569
328k
    }
570
7.39k
    else
571
7.39k
    {
572
7.39k
        rVal.MakeBig().MultBig(MakeBig(), *this);
573
7.39k
        Normalize();
574
7.39k
    }
575
336k
    return *this;
576
336k
}
577
578
void BigInt::DivMod(const BigInt& rVal, BigInt* pDiv, BigInt* pMod) const
579
336k
{
580
336k
    assert(pDiv || pMod); // Avoid useless calls
581
336k
    if (!rVal.IsBig())
582
329k
    {
583
329k
        if ( rVal.nVal == 0 )
584
0
        {
585
0
            OSL_FAIL( "BigInt::operator/ --> divide by zero" );
586
0
            return;
587
0
        }
588
589
329k
        if (rVal.nVal == 1)
590
0
        {
591
0
            if (pDiv)
592
0
            {
593
0
                *pDiv = *this;
594
0
                pDiv->Normalize();
595
0
            }
596
0
            if (pMod)
597
0
                *pMod = 0;
598
0
            return;
599
0
        }
600
601
329k
        if (!IsBig())
602
329k
        {
603
            // No overflows may occur here
604
329k
            const sal_Int32 nDiv = nVal / rVal.nVal; // Compilers usually optimize adjacent
605
329k
            const sal_Int32 nMod = nVal % rVal.nVal; // / and % into a single instruction
606
329k
            if (pDiv)
607
329k
                *pDiv = nDiv;
608
329k
            if (pMod)
609
0
                *pMod = nMod;
610
329k
            return;
611
329k
        }
612
613
310
        if ( rVal.nVal == -1 )
614
0
        {
615
0
            if (pDiv)
616
0
            {
617
0
                *pDiv = *this;
618
0
                pDiv->bIsNeg = !bIsNeg;
619
0
                pDiv->Normalize();
620
0
            }
621
0
            if (pMod)
622
0
                *pMod = 0;
623
0
            return;
624
0
        }
625
626
        // Divide BigInt with an sal_uInt32
627
310
        sal_uInt32 nTmp;
628
310
        bool bNegate;
629
310
        if ( rVal.nVal < 0 )
630
228
        {
631
228
            nTmp = static_cast<sal_uInt32>(-rVal.nVal);
632
228
            bNegate = true;
633
228
        }
634
82
        else
635
82
        {
636
82
            nTmp = static_cast<sal_uInt32>(rVal.nVal);
637
82
            bNegate = false;
638
82
        }
639
640
310
        BigInt aTmp;
641
310
        BigInt& rDiv = pDiv ? *pDiv : aTmp;
642
310
        rDiv = *this;
643
310
        rDiv.nLen = DivInPlace({ rDiv.nNum, rDiv.nLen }, nTmp, nTmp);
644
310
        if (pDiv)
645
310
        {
646
310
            if (bNegate)
647
228
                pDiv->bIsNeg = !pDiv->bIsNeg;
648
310
            pDiv->Normalize();
649
310
        }
650
310
        if (pMod)
651
0
        {
652
0
            *pMod = BigInt(nTmp);
653
0
        }
654
310
        return;
655
310
    }
656
657
6.84k
    BigInt tmpA = MakeBig(), tmpB = rVal.MakeBig();
658
6.84k
    if (tmpA.ABS_IsLessBig(tmpB))
659
0
    {
660
        // First store *this to *pMod, then nullify *pDiv, to handle 'pDiv == this' case
661
0
        if (pMod)
662
0
        {
663
0
            *pMod = *this;
664
0
            pMod->Normalize();
665
0
        }
666
0
        if (pDiv)
667
0
            *pDiv = 0;
668
0
        return;
669
0
    }
670
671
    // Divide BigInt with BigInt
672
6.84k
    tmpA.DivModBig(tmpB, pDiv, pMod);
673
6.84k
}
674
675
BigInt& BigInt::operator/=( const BigInt& rVal )
676
336k
{
677
336k
    DivMod(rVal, this, nullptr);
678
336k
    return *this;
679
336k
}
680
681
BigInt& BigInt::operator%=( const BigInt& rVal )
682
0
{
683
0
    DivMod(rVal, nullptr, this);
684
0
    return *this;
685
0
}
686
687
bool operator==( const BigInt& rVal1, const BigInt& rVal2 )
688
0
{
689
0
    if (!rVal1.IsBig() && !rVal2.IsBig())
690
0
        return rVal1.nVal == rVal2.nVal;
691
692
0
    BigInt nA = rVal1.MakeBig(), nB = rVal2.MakeBig();
693
0
    return nA.bIsNeg == nB.bIsNeg && nA.nLen == nB.nLen
694
0
           && std::equal(nA.nNum, nA.nNum + nA.nLen, nB.nNum);
695
0
}
696
697
std::strong_ordering operator<=>(const BigInt& rVal1, const BigInt& rVal2)
698
0
{
699
0
    if (!rVal1.IsBig() && !rVal2.IsBig())
700
0
        return rVal1.nVal <=> rVal2.nVal;
701
702
0
    BigInt nA = rVal1.MakeBig(), nB = rVal2.MakeBig();
703
0
    if (nA.bIsNeg != nB.bIsNeg)
704
0
        return nB.bIsNeg ? std::strong_ordering::less : std::strong_ordering::greater;
705
0
    if (nA.nLen < nB.nLen)
706
0
        return nB.bIsNeg ? std::strong_ordering::greater : std::strong_ordering::less;
707
0
    if (nA.nLen > nB.nLen)
708
0
        return nB.bIsNeg ? std::strong_ordering::less : std::strong_ordering::greater;
709
0
    int i = nA.nLen - 1;
710
0
    while (i > 0 && nA.nNum[i] == nB.nNum[i])
711
0
        --i;
712
0
    return nB.bIsNeg ? (nB.nNum[i] <=> nA.nNum[i]) : (nA.nNum[i] <=> nB.nNum[i]);
713
0
}
714
715
tools::Long BigInt::Scale( tools::Long nVal, tools::Long nMul, tools::Long nDiv )
716
329k
{
717
329k
    BigInt aVal( nVal );
718
719
329k
    aVal *= nMul;
720
721
329k
    if ( aVal.IsNeg() != ( nDiv < 0 ) )
722
0
        aVal -= nDiv / 2; // for correct rounding
723
329k
    else
724
329k
        aVal += nDiv / 2; // for correct rounding
725
726
329k
    aVal /= nDiv;
727
728
329k
    return tools::Long( aVal );
729
329k
}
730
731
tools::Long BigInt::Scale( tools::Long nVal, double fScale )
732
125k
{
733
125k
    return std::llround(nVal * fScale);
734
125k
}
735
736
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */