Coverage Report

Created: 2025-12-08 09:28

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
988k
{
46
988k
    if (IsBig())
47
111k
    {
48
111k
        BigInt ret(*this);
49
111k
        while ( ret.nLen > 1 && ret.nNum[ret.nLen-1] == 0 )
50
0
            ret.nLen--;
51
111k
        return ret;
52
111k
    }
53
54
876k
    BigInt ret;
55
876k
    if (nVal < 0)
56
40.3k
    {
57
40.3k
        ret.bIsNeg = true;
58
40.3k
        ret.nNum[0] = -static_cast<sal_Int64>(nVal);
59
40.3k
    }
60
836k
    else
61
836k
    {
62
836k
        ret.bIsNeg = false;
63
836k
        ret.nNum[0] = nVal;
64
836k
    }
65
876k
    ret.nLen = 1;
66
876k
    return ret;
67
988k
}
68
69
void BigInt::Normalize()
70
612k
{
71
612k
    if (IsBig())
72
532k
    {
73
931k
        while ( nLen > 1 && nNum[nLen-1] == 0 )
74
398k
            nLen--;
75
76
532k
        if (nLen < 2)
77
426k
        {
78
426k
            static constexpr sal_uInt32 maxForPosInt32 = std::numeric_limits<sal_Int32>::max();
79
426k
            static constexpr sal_uInt32 maxForNegInt32 = -sal_Int64(std::numeric_limits<sal_Int32>::min());
80
426k
            sal_uInt32 nNum0 = nNum[0];
81
426k
            if (bIsNeg && nNum0 <= maxForNegInt32)
82
33.8k
            {
83
33.8k
                nVal = -sal_Int64(nNum0);
84
33.8k
                nLen = 0;
85
33.8k
            }
86
392k
            else if (!bIsNeg && nNum0 <= maxForPosInt32)
87
378k
            {
88
378k
                nVal = nNum0;
89
378k
                nLen = 0;
90
378k
            }
91
426k
        }
92
532k
    }
93
612k
}
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
24.1k
{
100
24.1k
    assert(retBuf.size() >= aNum.size());
101
24.1k
    sal_uInt64 nK = 0;
102
68.5k
    for (size_t i = 0; i < aNum.size(); i++)
103
44.3k
    {
104
44.3k
        sal_uInt64 nTmp = static_cast<sal_uInt64>(aNum[i]) * nMul + nK;
105
44.3k
        nK = nTmp >> 32;
106
44.3k
        retBuf[i] = static_cast<sal_uInt32>(nTmp);
107
44.3k
    }
108
109
24.1k
    if ( nK )
110
5.89k
    {
111
5.89k
        assert(retBuf.size() > aNum.size());
112
5.89k
        retBuf[aNum.size()] = nK;
113
5.89k
        return retBuf.subspan(0, aNum.size() + 1);
114
5.89k
    }
115
116
18.2k
    return retBuf.subspan(0, aNum.size());
117
24.1k
}
118
119
static size_t DivInPlace(std::span<sal_uInt32> aNum, sal_uInt32 nDiv, sal_uInt32& rRem)
120
37.0k
{
121
37.0k
    assert(aNum.size() > 0);
122
37.0k
    sal_uInt64 nK = 0;
123
112k
    for (int i = aNum.size() - 1; i >= 0; i--)
124
75.8k
    {
125
75.8k
        sal_uInt64 nTmp = aNum[i] + (nK << 32);
126
75.8k
        aNum[i] = nTmp / nDiv;
127
75.8k
        nK            = nTmp % nDiv;
128
75.8k
    }
129
37.0k
    rRem = nK;
130
131
37.0k
    if (aNum[aNum.size() - 1] == 0)
132
32.4k
        return aNum.size() - 1;
133
134
4.65k
    return aNum.size();
135
37.0k
}
136
137
bool BigInt::ABS_IsLessBig(const BigInt& rVal) const
138
13.3k
{
139
13.3k
    assert(IsBig() && rVal.IsBig());
140
13.3k
    if ( rVal.nLen < nLen)
141
7.65k
        return false;
142
5.68k
    if ( rVal.nLen > nLen )
143
212
        return true;
144
145
5.47k
    int i = nLen - 1;
146
5.47k
    while (i > 0 && nNum[i] == rVal.nNum[i])
147
0
        --i;
148
5.47k
    return nNum[i] < rVal.nNum[i];
149
5.68k
}
150
151
void BigInt::AddBig(BigInt& rB, BigInt& rRes)
152
51.6k
{
153
51.6k
    assert(IsBig() && rB.IsBig());
154
51.6k
    if ( bIsNeg == rB.bIsNeg )
155
51.4k
    {
156
51.4k
        int  i;
157
51.4k
        char len;
158
159
        // if length of the two values differ, fill remaining positions
160
        // of the smaller value with zeros.
161
51.4k
        if (nLen >= rB.nLen)
162
51.4k
        {
163
51.4k
            len = nLen;
164
99.8k
            for (i = rB.nLen; i < len; i++)
165
48.4k
                rB.nNum[i] = 0;
166
51.4k
        }
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
51.4k
        sal_Int64 k = 0;
176
154k
        for (i = 0; i < len; i++) {
177
102k
            sal_Int64 nZ = static_cast<sal_Int64>(nNum[i]) + static_cast<sal_Int64>(rB.nNum[i]) + k;
178
102k
            if (nZ > sal_Int64(std::numeric_limits<sal_uInt32>::max()))
179
8.75k
                k = 1;
180
94.0k
            else
181
94.0k
                k = 0;
182
102k
            rRes.nNum[i] = static_cast<sal_uInt32>(nZ);
183
102k
        }
184
        // If an overflow occurred, add to solution
185
51.4k
        if (k)
186
42
        {
187
42
            assert(i < MAX_DIGITS);
188
42
            rRes.nNum[i] = 1;
189
42
            len++;
190
42
        }
191
        // Set length and sign
192
51.4k
        rRes.nLen = len;
193
51.4k
        rRes.bIsNeg = bIsNeg;
194
51.4k
    }
195
    // If one of the values is negative, perform subtraction instead
196
212
    else
197
212
    {
198
212
        bIsNeg = !bIsNeg;
199
212
        rB.SubBig(*this, rRes);
200
212
        bIsNeg = !bIsNeg;
201
212
    }
202
51.6k
}
203
204
void BigInt::SubBig(BigInt& rB, BigInt& rRes)
205
11.8k
{
206
11.8k
    assert(IsBig() && rB.IsBig());
207
11.8k
    if ( bIsNeg == rB.bIsNeg )
208
1.26k
    {
209
1.26k
        char len;
210
211
        // if length of the two values differ, fill remaining positions
212
        // of the smaller value with zeros.
213
1.26k
        if (nLen >= rB.nLen)
214
1.04k
        {
215
1.04k
            len = nLen;
216
2.35k
            for (int i = rB.nLen; i < len; i++)
217
1.30k
                rB.nNum[i] = 0;
218
1.04k
        }
219
212
        else
220
212
        {
221
212
            len = rB.nLen;
222
469
            for (int i = nLen; i < len; i++)
223
257
                nNum[i] = 0;
224
212
        }
225
226
1.26k
        const bool bThisIsLess = ABS_IsLessBig(rB);
227
1.26k
        BigInt& rGreater = bThisIsLess ? rB : *this;
228
1.26k
        BigInt& rSmaller = bThisIsLess ? *this : rB;
229
230
1.26k
        sal_Int64 k = 0;
231
4.08k
        for (int i = 0; i < len; i++)
232
2.82k
        {
233
2.82k
            sal_Int64 nZ = static_cast<sal_Int64>(rGreater.nNum[i]) - static_cast<sal_Int64>(rSmaller.nNum[i]) + k;
234
2.82k
            if (nZ < 0)
235
105
                k = -1;
236
2.71k
            else
237
2.71k
                k = 0;
238
2.82k
            rRes.nNum[i] = static_cast<sal_uInt32>(nZ);
239
2.82k
        }
240
241
        // if a < b, revert sign
242
1.26k
        rRes.bIsNeg = bThisIsLess ? !bIsNeg : bIsNeg;
243
1.26k
        rRes.nLen   = len;
244
1.26k
    }
245
    // If one of the values is negative, perform addition instead
246
10.5k
    else
247
10.5k
    {
248
10.5k
        bIsNeg = !bIsNeg;
249
10.5k
        AddBig(rB, rRes);
250
10.5k
        bIsNeg = !bIsNeg;
251
10.5k
        rRes.bIsNeg = bIsNeg;
252
10.5k
    }
253
11.8k
}
254
255
void BigInt::MultBig(const BigInt& rB, BigInt& rRes) const
256
429k
{
257
429k
    assert(IsBig() && rB.IsBig());
258
259
429k
    rRes.bIsNeg = bIsNeg != rB.bIsNeg;
260
429k
    rRes.nLen = nLen + rB.nLen;
261
429k
    assert(rRes.nLen <= MAX_DIGITS);
262
263
1.30M
    for (int i = 0; i < rRes.nLen; i++)
264
875k
        rRes.nNum[i] = 0;
265
266
868k
    for (int j = 0; j < rB.nLen; j++)
267
438k
    {
268
438k
        sal_uInt64 k = 0;
269
438k
        int i;
270
885k
        for (i = 0; i < nLen; i++)
271
446k
        {
272
446k
            sal_uInt64 nZ = static_cast<sal_uInt64>(nNum[i]) * static_cast<sal_uInt64>(rB.nNum[j]) +
273
446k
                 static_cast<sal_uInt64>(rRes.nNum[i + j]) + k;
274
446k
            rRes.nNum[i + j] = static_cast<sal_uInt32>(nZ);
275
446k
            k = nZ >> 32;
276
446k
        }
277
438k
        rRes.nNum[i + j] = k;
278
438k
    }
279
429k
}
280
281
void BigInt::DivModBig(const BigInt& rB, BigInt* pDiv, BigInt* pMod) const
282
12.0k
{
283
12.0k
    assert(IsBig() && rB.IsBig());
284
12.0k
    assert(nLen >= rB.nLen);
285
286
12.0k
    assert(rB.nNum[rB.nLen - 1] != 0);
287
12.0k
    sal_uInt32 nMult = static_cast<sal_uInt32>(0x100000000 / (static_cast<sal_Int64>(rB.nNum[rB.nLen - 1]) + 1));
288
289
12.0k
    sal_uInt32 numBuf[MAX_DIGITS + 1]; // normalized dividend
290
12.0k
    auto num = Mult({ nNum, nLen }, nMult, numBuf);
291
12.0k
    if (num.size() == nLen)
292
6.18k
    {
293
6.18k
        num = std::span(numBuf, nLen + 1);
294
6.18k
        num[nLen] = 0;
295
6.18k
    }
296
297
12.0k
    sal_uInt32 denBuf[MAX_DIGITS + 1]; // normalized divisor
298
12.0k
    const auto den = Mult({ rB.nNum, rB.nLen }, nMult, denBuf);
299
12.0k
    assert(den.size() == rB.nLen);
300
12.0k
    const sal_uInt64 nDenMostSig = den[rB.nLen - 1];
301
12.0k
    assert(nDenMostSig >= 0x100000000 / 2);
302
12.0k
    const sal_uInt64 nDen2ndSig = rB.nLen > 1 ? den[rB.nLen - 2] : 0;
303
304
12.0k
    BigInt aTmp;
305
12.0k
    BigInt& rRes = pDiv ? *pDiv : aTmp;
306
307
30.7k
    for (size_t j = num.size() - 1; j >= den.size(); j--)
308
18.7k
    { // guess divisor
309
18.7k
        assert(num[j] < nDenMostSig || (num[j] == nDenMostSig && num[j - 1] == 0));
310
18.7k
        sal_uInt64 nTmp = ( static_cast<sal_uInt64>(num[j]) << 32 ) + num[j - 1];
311
18.7k
        sal_uInt32 nQ;
312
18.7k
        if (num[j] == nDenMostSig)
313
0
            nQ = 0xFFFFFFFF;
314
18.7k
        else
315
18.7k
            nQ = static_cast<sal_uInt32>(nTmp / nDenMostSig);
316
317
18.7k
        if (nDen2ndSig && (nDen2ndSig * nQ) > ((nTmp - nDenMostSig * nQ) << 32) + num[j - 2])
318
2.74k
            nQ--;
319
        // Start division
320
18.7k
        sal_uInt32 nK = 0;
321
18.7k
        size_t i;
322
45.5k
        for (i = 0; i < den.size(); i++)
323
26.7k
        {
324
26.7k
            nTmp = static_cast<sal_uInt64>(num[j - den.size() + i])
325
26.7k
                   - (static_cast<sal_uInt64>(den[i]) * nQ)
326
26.7k
                   - nK;
327
26.7k
            num[j - den.size() + i] = static_cast<sal_uInt32>(nTmp);
328
26.7k
            nK = static_cast<sal_uInt32>(nTmp >> 32);
329
26.7k
            if ( nK )
330
18.6k
                nK = static_cast<sal_uInt32>(0x100000000 - nK);
331
26.7k
        }
332
18.7k
        sal_uInt32& rNum(num[j - den.size() + i]);
333
18.7k
        rNum -= nK;
334
18.7k
        if (num[j - den.size() + i] == 0)
335
18.7k
            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
18.7k
    }
351
352
12.0k
    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
12.0k
    if (pDiv) // rRes references pDiv
361
12.0k
    {
362
12.0k
        pDiv->bIsNeg = bIsNeg != rB.bIsNeg;
363
12.0k
        pDiv->nLen = nLen - rB.nLen + 1;
364
12.0k
        pDiv->Normalize();
365
12.0k
    }
366
12.0k
}
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
8.71M
    : nVal(0)
455
8.71M
{
456
8.71M
    bIsNeg = nValue < 0;
457
8.71M
    nLen = 0;
458
459
8.71M
    if ((nValue >= SAL_MIN_INT32) && (nValue <= SAL_MAX_INT32))
460
8.66M
    {
461
8.66M
        nVal = static_cast<sal_Int32>(nValue);
462
8.66M
    }
463
49.5k
    else
464
49.5k
    {
465
49.5k
        for (sal_uInt64 n = static_cast<sal_uInt64>(
466
49.5k
                 (bIsNeg && nValue != std::numeric_limits<sal_Int64>::min()) ? -nValue : nValue);
467
125k
             n != 0; n >>= 32)
468
75.7k
            nNum[nLen++] = static_cast<sal_uInt32>(n);
469
49.5k
    }
470
8.71M
}
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
118k
{
497
118k
    if (this == &rBigInt)
498
118k
        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
118k
}
509
510
BigInt& BigInt::operator+=( const BigInt& rVal )
511
2.16M
{
512
2.16M
    if (!IsBig() && !rVal.IsBig())
513
2.12M
    {
514
2.12M
        if( nVal <= MY_MAXLONG && rVal.nVal <= MY_MAXLONG
515
2.12M
            && nVal >= MY_MINLONG && rVal.nVal >= MY_MINLONG )
516
2.12M
        { // No overflows may occur here
517
2.12M
            nVal += rVal.nVal;
518
2.12M
            return *this;
519
2.12M
        }
520
521
1.33k
        if( (nVal < 0) != (rVal.nVal < 0) )
522
2
        { // No overflows may occur here
523
2
            nVal += rVal.nVal;
524
2
            return *this;
525
2
        }
526
1.33k
    }
527
528
41.0k
    BigInt aTmp2 = rVal.MakeBig();
529
41.0k
    MakeBig().AddBig(aTmp2, *this);
530
41.0k
    Normalize();
531
41.0k
    return *this;
532
2.16M
}
533
534
BigInt& BigInt::operator-=( const BigInt& rVal )
535
27.9k
{
536
27.9k
    if (!IsBig() && !rVal.IsBig())
537
17.3k
    {
538
17.3k
        if ( nVal <= MY_MAXLONG && rVal.nVal <= MY_MAXLONG &&
539
17.3k
             nVal >= MY_MINLONG && rVal.nVal >= MY_MINLONG )
540
16.3k
        { // No overflows may occur here
541
16.3k
            nVal -= rVal.nVal;
542
16.3k
            return *this;
543
16.3k
        }
544
545
991
        if ( (nVal < 0) == (rVal.nVal < 0) )
546
1
        { // No overflows may occur here
547
1
            nVal -= rVal.nVal;
548
1
            return *this;
549
1
        }
550
991
    }
551
552
11.6k
    BigInt aTmp2 = rVal.MakeBig();
553
11.6k
    MakeBig().SubBig(aTmp2, *this);
554
11.6k
    Normalize();
555
11.6k
    return *this;
556
27.9k
}
557
558
BigInt& BigInt::operator*=( const BigInt& rVal )
559
2.22M
{
560
2.22M
    static const sal_Int32 MY_MAXSHORT = 0x00007fff;
561
2.22M
    static const sal_Int32 MY_MINSHORT = -MY_MAXSHORT;
562
563
2.22M
    if (!IsBig() && !rVal.IsBig()
564
2.20M
         && nVal <= MY_MAXSHORT && rVal.nVal <= MY_MAXSHORT
565
1.82M
         && nVal >= MY_MINSHORT && rVal.nVal >= MY_MINSHORT )
566
         // TODO: not optimal !!! W.P.
567
1.79M
    { // No overflows may occur here
568
1.79M
        nVal *= rVal.nVal;
569
1.79M
    }
570
429k
    else
571
429k
    {
572
429k
        rVal.MakeBig().MultBig(MakeBig(), *this);
573
429k
        Normalize();
574
429k
    }
575
2.22M
    return *this;
576
2.22M
}
577
578
void BigInt::DivMod(const BigInt& rVal, BigInt* pDiv, BigInt* pMod) const
579
2.22M
{
580
2.22M
    assert(pDiv || pMod); // Avoid useless calls
581
2.22M
    if (!rVal.IsBig())
582
2.21M
    {
583
2.21M
        if ( rVal.nVal == 0 )
584
10
        {
585
10
            OSL_FAIL( "BigInt::operator/ --> divide by zero" );
586
10
            return;
587
10
        }
588
589
2.21M
        if (rVal.nVal == 1)
590
80.9k
        {
591
80.9k
            if (pDiv)
592
80.9k
            {
593
80.9k
                *pDiv = *this;
594
80.9k
                pDiv->Normalize();
595
80.9k
            }
596
80.9k
            if (pMod)
597
0
                *pMod = 0;
598
80.9k
            return;
599
80.9k
        }
600
601
2.13M
        if (!IsBig())
602
2.09M
        {
603
            // No overflows may occur here
604
2.09M
            const sal_Int32 nDiv = nVal / rVal.nVal; // Compilers usually optimize adjacent
605
2.09M
            const sal_Int32 nMod = nVal % rVal.nVal; // / and % into a single instruction
606
2.09M
            if (pDiv)
607
2.09M
                *pDiv = nDiv;
608
2.09M
            if (pMod)
609
0
                *pMod = nMod;
610
2.09M
            return;
611
2.09M
        }
612
613
37.0k
        if ( rVal.nVal == -1 )
614
4
        {
615
4
            if (pDiv)
616
4
            {
617
4
                *pDiv = *this;
618
4
                pDiv->bIsNeg = !bIsNeg;
619
4
                pDiv->Normalize();
620
4
            }
621
4
            if (pMod)
622
0
                *pMod = 0;
623
4
            return;
624
4
        }
625
626
        // Divide BigInt with an sal_uInt32
627
37.0k
        sal_uInt32 nTmp;
628
37.0k
        bool bNegate;
629
37.0k
        if ( rVal.nVal < 0 )
630
1.59k
        {
631
1.59k
            nTmp = static_cast<sal_uInt32>(-rVal.nVal);
632
1.59k
            bNegate = true;
633
1.59k
        }
634
35.4k
        else
635
35.4k
        {
636
35.4k
            nTmp = static_cast<sal_uInt32>(rVal.nVal);
637
35.4k
            bNegate = false;
638
35.4k
        }
639
640
37.0k
        BigInt aTmp;
641
37.0k
        BigInt& rDiv = pDiv ? *pDiv : aTmp;
642
37.0k
        rDiv = *this;
643
37.0k
        rDiv.nLen = DivInPlace({ rDiv.nNum, rDiv.nLen }, nTmp, nTmp);
644
37.0k
        if (pDiv)
645
37.0k
        {
646
37.0k
            if (bNegate)
647
1.59k
                pDiv->bIsNeg = !pDiv->bIsNeg;
648
37.0k
            pDiv->Normalize();
649
37.0k
        }
650
37.0k
        if (pMod)
651
0
        {
652
0
            *pMod = BigInt(nTmp);
653
0
        }
654
37.0k
        return;
655
37.0k
    }
656
657
12.0k
    BigInt tmpA = MakeBig(), tmpB = rVal.MakeBig();
658
12.0k
    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
12.0k
    tmpA.DivModBig(tmpB, pDiv, pMod);
673
12.0k
}
674
675
BigInt& BigInt::operator/=( const BigInt& rVal )
676
2.22M
{
677
2.22M
    DivMod(rVal, this, nullptr);
678
2.22M
    return *this;
679
2.22M
}
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
2.13M
{
717
2.13M
    BigInt aVal( nVal );
718
719
2.13M
    aVal *= nMul;
720
721
2.13M
    if ( aVal.IsNeg() != ( nDiv < 0 ) )
722
17.5k
        aVal -= nDiv / 2; // for correct rounding
723
2.12M
    else
724
2.12M
        aVal += nDiv / 2; // for correct rounding
725
726
2.13M
    aVal /= nDiv;
727
728
2.13M
    return tools::Long( aVal );
729
2.13M
}
730
731
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */