Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/mfbt/decimal/Decimal.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (C) 2012 Google Inc. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions are
6
 * met:
7
 *
8
 *     * Redistributions of source code must retain the above copyright
9
 * notice, this list of conditions and the following disclaimer.
10
 *     * Redistributions in binary form must reproduce the above
11
 * copyright notice, this list of conditions and the following disclaimer
12
 * in the documentation and/or other materials provided with the
13
 * distribution.
14
 *     * Neither the name of Google Inc. nor the names of its
15
 * contributors may be used to endorse or promote products derived from
16
 * this software without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
 */
30
31
#include "Decimal.h"
32
#include "moz-decimal-utils.h"
33
34
using namespace moz_decimal_utils;
35
36
#include <algorithm>
37
#include <float.h>
38
39
namespace blink {
40
41
namespace DecimalPrivate {
42
43
static int const ExponentMax = 1023;
44
static int const ExponentMin = -1023;
45
static int const Precision = 18;
46
47
static const uint64_t MaxCoefficient = UINT64_C(0xDE0B6B3A763FFFF); // 999999999999999999 == 18 9's
48
49
// This class handles Decimal special values.
50
class SpecialValueHandler {
51
    STACK_ALLOCATED();
52
    WTF_MAKE_NONCOPYABLE(SpecialValueHandler);
53
public:
54
    enum HandleResult {
55
        BothFinite,
56
        BothInfinity,
57
        EitherNaN,
58
        LHSIsInfinity,
59
        RHSIsInfinity,
60
    };
61
62
    SpecialValueHandler(const Decimal& lhs, const Decimal& rhs);
63
    HandleResult handle();
64
    Decimal value() const;
65
66
private:
67
    enum Result {
68
        ResultIsLHS,
69
        ResultIsRHS,
70
        ResultIsUnknown,
71
    };
72
73
    const Decimal& m_lhs;
74
    const Decimal& m_rhs;
75
    Result m_result;
76
};
77
78
SpecialValueHandler::SpecialValueHandler(const Decimal& lhs, const Decimal& rhs)
79
    : m_lhs(lhs), m_rhs(rhs), m_result(ResultIsUnknown)
80
0
{
81
0
}
82
83
SpecialValueHandler::HandleResult SpecialValueHandler::handle()
84
0
{
85
0
    if (m_lhs.isFinite() && m_rhs.isFinite())
86
0
        return BothFinite;
87
0
88
0
    const Decimal::EncodedData::FormatClass lhsClass = m_lhs.value().formatClass();
89
0
    const Decimal::EncodedData::FormatClass rhsClass = m_rhs.value().formatClass();
90
0
    if (lhsClass == Decimal::EncodedData::ClassNaN) {
91
0
        m_result = ResultIsLHS;
92
0
        return EitherNaN;
93
0
    }
94
0
95
0
    if (rhsClass == Decimal::EncodedData::ClassNaN) {
96
0
        m_result = ResultIsRHS;
97
0
        return EitherNaN;
98
0
    }
99
0
100
0
    if (lhsClass == Decimal::EncodedData::ClassInfinity)
101
0
        return rhsClass == Decimal::EncodedData::ClassInfinity ? BothInfinity : LHSIsInfinity;
102
0
103
0
    if (rhsClass == Decimal::EncodedData::ClassInfinity)
104
0
        return RHSIsInfinity;
105
0
106
0
    ASSERT_NOT_REACHED();
107
0
    return BothFinite;
108
0
}
109
110
Decimal SpecialValueHandler::value() const
111
0
{
112
0
    switch (m_result) {
113
0
    case ResultIsLHS:
114
0
        return m_lhs;
115
0
    case ResultIsRHS:
116
0
        return m_rhs;
117
0
    case ResultIsUnknown:
118
0
    default:
119
0
        ASSERT_NOT_REACHED();
120
0
        return m_lhs;
121
0
    }
122
0
}
123
124
// This class is used for 128 bit unsigned integer arithmetic.
125
class UInt128 {
126
public:
127
    UInt128(uint64_t low, uint64_t high)
128
        : m_high(high), m_low(low)
129
0
    {
130
0
    }
131
132
    UInt128& operator/=(uint32_t);
133
134
0
    uint64_t high() const { return m_high; }
135
0
    uint64_t low() const { return m_low; }
136
137
0
    static UInt128 multiply(uint64_t u, uint64_t v) { return UInt128(u * v, multiplyHigh(u, v)); }
138
139
private:
140
0
    static uint32_t highUInt32(uint64_t x) { return static_cast<uint32_t>(x >> 32); }
141
0
    static uint32_t lowUInt32(uint64_t x) { return static_cast<uint32_t>(x & ((static_cast<uint64_t>(1) << 32) - 1)); }
142
0
    static uint64_t makeUInt64(uint32_t low, uint32_t high) { return low | (static_cast<uint64_t>(high) << 32); }
143
144
    static uint64_t multiplyHigh(uint64_t, uint64_t);
145
146
    uint64_t m_high;
147
    uint64_t m_low;
148
};
149
150
UInt128& UInt128::operator/=(const uint32_t divisor)
151
0
{
152
0
    ASSERT(divisor);
153
0
154
0
    if (!m_high) {
155
0
        m_low /= divisor;
156
0
        return *this;
157
0
    }
158
0
159
0
    uint32_t dividend[4];
160
0
    dividend[0] = lowUInt32(m_low);
161
0
    dividend[1] = highUInt32(m_low);
162
0
    dividend[2] = lowUInt32(m_high);
163
0
    dividend[3] = highUInt32(m_high);
164
0
165
0
    uint32_t quotient[4];
166
0
    uint32_t remainder = 0;
167
0
    for (int i = 3; i >= 0; --i) {
168
0
        const uint64_t work = makeUInt64(dividend[i], remainder);
169
0
        remainder = static_cast<uint32_t>(work % divisor);
170
0
        quotient[i] = static_cast<uint32_t>(work / divisor);
171
0
    }
172
0
    m_low = makeUInt64(quotient[0], quotient[1]);
173
0
    m_high = makeUInt64(quotient[2], quotient[3]);
174
0
    return *this;
175
0
}
176
177
// Returns high 64bit of 128bit product.
178
uint64_t UInt128::multiplyHigh(uint64_t u, uint64_t v)
179
0
{
180
0
    const uint64_t uLow = lowUInt32(u);
181
0
    const uint64_t uHigh = highUInt32(u);
182
0
    const uint64_t vLow = lowUInt32(v);
183
0
    const uint64_t vHigh = highUInt32(v);
184
0
    const uint64_t partialProduct = uHigh * vLow + highUInt32(uLow * vLow);
185
0
    return uHigh * vHigh + highUInt32(partialProduct) + highUInt32(uLow * vHigh + lowUInt32(partialProduct));
186
0
}
187
188
static int countDigits(uint64_t x)
189
0
{
190
0
    int numberOfDigits = 0;
191
0
    for (uint64_t powerOfTen = 1; x >= powerOfTen; powerOfTen *= 10) {
192
0
        ++numberOfDigits;
193
0
        if (powerOfTen >= std::numeric_limits<uint64_t>::max() / 10)
194
0
            break;
195
0
    }
196
0
    return numberOfDigits;
197
0
}
198
199
static uint64_t scaleDown(uint64_t x, int n)
200
0
{
201
0
    ASSERT(n >= 0);
202
0
    while (n > 0 && x) {
203
0
        x /= 10;
204
0
        --n;
205
0
    }
206
0
    return x;
207
0
}
208
209
static uint64_t scaleUp(uint64_t x, int n)
210
0
{
211
0
    ASSERT(n >= 0);
212
0
    ASSERT(n <= Precision);
213
0
214
0
    uint64_t y = 1;
215
0
    uint64_t z = 10;
216
0
    for (;;) {
217
0
        if (n & 1)
218
0
            y = y * z;
219
0
220
0
        n >>= 1;
221
0
        if (!n)
222
0
            return x * y;
223
0
224
0
        z = z * z;
225
0
    }
226
0
}
227
228
} // namespace DecimalPrivate
229
230
using namespace DecimalPrivate;
231
232
Decimal::EncodedData::EncodedData(Sign sign, FormatClass formatClass)
233
    : m_coefficient(0)
234
    , m_exponent(0)
235
    , m_formatClass(formatClass)
236
    , m_sign(sign)
237
0
{
238
0
}
239
240
Decimal::EncodedData::EncodedData(Sign sign, int exponent, uint64_t coefficient)
241
    : m_formatClass(coefficient ? ClassNormal : ClassZero)
242
    , m_sign(sign)
243
33
{
244
33
    if (exponent >= ExponentMin && exponent <= ExponentMax) {
245
33
        while (coefficient > MaxCoefficient) {
246
0
            coefficient /= 10;
247
0
            ++exponent;
248
0
        }
249
33
    }
250
33
251
33
    if (exponent > ExponentMax) {
252
0
        m_coefficient = 0;
253
0
        m_exponent = 0;
254
0
        m_formatClass = ClassInfinity;
255
0
        return;
256
0
    }
257
33
258
33
    if (exponent < ExponentMin) {
259
0
        m_coefficient = 0;
260
0
        m_exponent = 0;
261
0
        m_formatClass = ClassZero;
262
0
        return;
263
0
    }
264
33
265
33
    m_coefficient = coefficient;
266
33
    m_exponent = static_cast<int16_t>(exponent);
267
33
}
268
269
bool Decimal::EncodedData::operator==(const EncodedData& another) const
270
0
{
271
0
    return m_sign == another.m_sign
272
0
        && m_formatClass == another.m_formatClass
273
0
        && m_exponent == another.m_exponent
274
0
        && m_coefficient == another.m_coefficient;
275
0
}
276
277
Decimal::Decimal(int32_t i32)
278
    : m_data(i32 < 0 ? Negative : Positive, 0, i32 < 0 ? static_cast<uint64_t>(-static_cast<int64_t>(i32)) : static_cast<uint64_t>(i32))
279
33
{
280
33
}
281
282
Decimal::Decimal(Sign sign, int exponent, uint64_t coefficient)
283
    : m_data(sign, coefficient ? exponent : 0, coefficient)
284
0
{
285
0
}
286
287
Decimal::Decimal(const EncodedData& data)
288
    : m_data(data)
289
0
{
290
0
}
291
292
Decimal::Decimal(const Decimal& other)
293
    : m_data(other.m_data)
294
0
{
295
0
}
296
297
Decimal& Decimal::operator=(const Decimal& other)
298
0
{
299
0
    m_data = other.m_data;
300
0
    return *this;
301
0
}
302
303
Decimal& Decimal::operator+=(const Decimal& other)
304
0
{
305
0
    m_data = (*this + other).m_data;
306
0
    return *this;
307
0
}
308
309
Decimal& Decimal::operator-=(const Decimal& other)
310
0
{
311
0
    m_data = (*this - other).m_data;
312
0
    return *this;
313
0
}
314
315
Decimal& Decimal::operator*=(const Decimal& other)
316
0
{
317
0
    m_data = (*this * other).m_data;
318
0
    return *this;
319
0
}
320
321
Decimal& Decimal::operator/=(const Decimal& other)
322
0
{
323
0
    m_data = (*this / other).m_data;
324
0
    return *this;
325
0
}
326
327
Decimal Decimal::operator-() const
328
0
{
329
0
    if (isNaN())
330
0
        return *this;
331
0
332
0
    Decimal result(*this);
333
0
    result.m_data.setSign(invertSign(m_data.sign()));
334
0
    return result;
335
0
}
336
337
Decimal Decimal::operator+(const Decimal& rhs) const
338
0
{
339
0
    const Decimal& lhs = *this;
340
0
    const Sign lhsSign = lhs.sign();
341
0
    const Sign rhsSign = rhs.sign();
342
0
343
0
    SpecialValueHandler handler(lhs, rhs);
344
0
    switch (handler.handle()) {
345
0
    case SpecialValueHandler::BothFinite:
346
0
        break;
347
0
348
0
    case SpecialValueHandler::BothInfinity:
349
0
        return lhsSign == rhsSign ? lhs : nan();
350
0
351
0
    case SpecialValueHandler::EitherNaN:
352
0
        return handler.value();
353
0
354
0
    case SpecialValueHandler::LHSIsInfinity:
355
0
        return lhs;
356
0
357
0
    case SpecialValueHandler::RHSIsInfinity:
358
0
        return rhs;
359
0
    }
360
0
361
0
    const AlignedOperands alignedOperands = alignOperands(lhs, rhs);
362
0
363
0
    const uint64_t result = lhsSign == rhsSign
364
0
        ? alignedOperands.lhsCoefficient + alignedOperands.rhsCoefficient
365
0
        : alignedOperands.lhsCoefficient - alignedOperands.rhsCoefficient;
366
0
367
0
    if (lhsSign == Negative && rhsSign == Positive && !result)
368
0
        return Decimal(Positive, alignedOperands.exponent, 0);
369
0
370
0
    return static_cast<int64_t>(result) >= 0
371
0
        ? Decimal(lhsSign, alignedOperands.exponent, result)
372
0
        : Decimal(invertSign(lhsSign), alignedOperands.exponent, -static_cast<int64_t>(result));
373
0
}
374
375
Decimal Decimal::operator-(const Decimal& rhs) const
376
0
{
377
0
    const Decimal& lhs = *this;
378
0
    const Sign lhsSign = lhs.sign();
379
0
    const Sign rhsSign = rhs.sign();
380
0
381
0
    SpecialValueHandler handler(lhs, rhs);
382
0
    switch (handler.handle()) {
383
0
    case SpecialValueHandler::BothFinite:
384
0
        break;
385
0
386
0
    case SpecialValueHandler::BothInfinity:
387
0
        return lhsSign == rhsSign ? nan() : lhs;
388
0
389
0
    case SpecialValueHandler::EitherNaN:
390
0
        return handler.value();
391
0
392
0
    case SpecialValueHandler::LHSIsInfinity:
393
0
        return lhs;
394
0
395
0
    case SpecialValueHandler::RHSIsInfinity:
396
0
        return infinity(invertSign(rhsSign));
397
0
    }
398
0
399
0
    const AlignedOperands alignedOperands = alignOperands(lhs, rhs);
400
0
401
0
    const uint64_t result = lhsSign == rhsSign
402
0
        ? alignedOperands.lhsCoefficient - alignedOperands.rhsCoefficient
403
0
        : alignedOperands.lhsCoefficient + alignedOperands.rhsCoefficient;
404
0
405
0
    if (lhsSign == Negative && rhsSign == Negative && !result)
406
0
        return Decimal(Positive, alignedOperands.exponent, 0);
407
0
408
0
    return static_cast<int64_t>(result) >= 0
409
0
        ? Decimal(lhsSign, alignedOperands.exponent, result)
410
0
        : Decimal(invertSign(lhsSign), alignedOperands.exponent, -static_cast<int64_t>(result));
411
0
}
412
413
Decimal Decimal::operator*(const Decimal& rhs) const
414
0
{
415
0
    const Decimal& lhs = *this;
416
0
    const Sign lhsSign = lhs.sign();
417
0
    const Sign rhsSign = rhs.sign();
418
0
    const Sign resultSign = lhsSign == rhsSign ? Positive : Negative;
419
0
420
0
    SpecialValueHandler handler(lhs, rhs);
421
0
    switch (handler.handle()) {
422
0
    case SpecialValueHandler::BothFinite: {
423
0
        const uint64_t lhsCoefficient = lhs.m_data.coefficient();
424
0
        const uint64_t rhsCoefficient = rhs.m_data.coefficient();
425
0
        int resultExponent = lhs.exponent() + rhs.exponent();
426
0
        UInt128 work(UInt128::multiply(lhsCoefficient, rhsCoefficient));
427
0
        while (work.high()) {
428
0
            work /= 10;
429
0
            ++resultExponent;
430
0
        }
431
0
        return Decimal(resultSign, resultExponent, work.low());
432
0
    }
433
0
434
0
    case SpecialValueHandler::BothInfinity:
435
0
        return infinity(resultSign);
436
0
437
0
    case SpecialValueHandler::EitherNaN:
438
0
        return handler.value();
439
0
440
0
    case SpecialValueHandler::LHSIsInfinity:
441
0
        return rhs.isZero() ? nan() : infinity(resultSign);
442
0
443
0
    case SpecialValueHandler::RHSIsInfinity:
444
0
        return lhs.isZero() ? nan() : infinity(resultSign);
445
0
    }
446
0
447
0
    ASSERT_NOT_REACHED();
448
0
    return nan();
449
0
}
450
451
Decimal Decimal::operator/(const Decimal& rhs) const
452
0
{
453
0
    const Decimal& lhs = *this;
454
0
    const Sign lhsSign = lhs.sign();
455
0
    const Sign rhsSign = rhs.sign();
456
0
    const Sign resultSign = lhsSign == rhsSign ? Positive : Negative;
457
0
458
0
    SpecialValueHandler handler(lhs, rhs);
459
0
    switch (handler.handle()) {
460
0
    case SpecialValueHandler::BothFinite:
461
0
        break;
462
0
463
0
    case SpecialValueHandler::BothInfinity:
464
0
        return nan();
465
0
466
0
    case SpecialValueHandler::EitherNaN:
467
0
        return handler.value();
468
0
469
0
    case SpecialValueHandler::LHSIsInfinity:
470
0
        return infinity(resultSign);
471
0
472
0
    case SpecialValueHandler::RHSIsInfinity:
473
0
        return zero(resultSign);
474
0
    }
475
0
476
0
    ASSERT(lhs.isFinite());
477
0
    ASSERT(rhs.isFinite());
478
0
479
0
    if (rhs.isZero())
480
0
        return lhs.isZero() ? nan() : infinity(resultSign);
481
0
482
0
    int resultExponent = lhs.exponent() - rhs.exponent();
483
0
484
0
    if (lhs.isZero())
485
0
        return Decimal(resultSign, resultExponent, 0);
486
0
487
0
    uint64_t remainder = lhs.m_data.coefficient();
488
0
    const uint64_t divisor = rhs.m_data.coefficient();
489
0
    uint64_t result = 0;
490
0
    for (;;) {
491
0
        while (remainder < divisor && result < MaxCoefficient / 10) {
492
0
            remainder *= 10;
493
0
            result *= 10;
494
0
            --resultExponent;
495
0
        }
496
0
        if (remainder < divisor)
497
0
            break;
498
0
        uint64_t quotient = remainder / divisor;
499
0
        if (result > MaxCoefficient - quotient)
500
0
            break;
501
0
        result += quotient;
502
0
        remainder %= divisor;
503
0
        if (!remainder)
504
0
            break;
505
0
    }
506
0
507
0
    if (remainder > divisor / 2)
508
0
        ++result;
509
0
510
0
    return Decimal(resultSign, resultExponent, result);
511
0
}
512
513
bool Decimal::operator==(const Decimal& rhs) const
514
0
{
515
0
    if (isNaN() || rhs.isNaN())
516
0
        return false;
517
0
    return m_data == rhs.m_data || compareTo(rhs).isZero();
518
0
}
519
520
bool Decimal::operator!=(const Decimal& rhs) const
521
0
{
522
0
    if (isNaN() || rhs.isNaN())
523
0
        return true;
524
0
    if (m_data == rhs.m_data)
525
0
        return false;
526
0
    const Decimal result = compareTo(rhs);
527
0
    if (result.isNaN())
528
0
        return false;
529
0
    return !result.isZero();
530
0
}
531
532
bool Decimal::operator<(const Decimal& rhs) const
533
0
{
534
0
    const Decimal result = compareTo(rhs);
535
0
    if (result.isNaN())
536
0
        return false;
537
0
    return !result.isZero() && result.isNegative();
538
0
}
539
540
bool Decimal::operator<=(const Decimal& rhs) const
541
0
{
542
0
    if (isNaN() || rhs.isNaN())
543
0
        return false;
544
0
    if (m_data == rhs.m_data)
545
0
        return true;
546
0
    const Decimal result = compareTo(rhs);
547
0
    if (result.isNaN())
548
0
        return false;
549
0
    return result.isZero() || result.isNegative();
550
0
}
551
552
bool Decimal::operator>(const Decimal& rhs) const
553
0
{
554
0
    const Decimal result = compareTo(rhs);
555
0
    if (result.isNaN())
556
0
        return false;
557
0
    return !result.isZero() && result.isPositive();
558
0
}
559
560
bool Decimal::operator>=(const Decimal& rhs) const
561
0
{
562
0
    if (isNaN() || rhs.isNaN())
563
0
        return false;
564
0
    if (m_data == rhs.m_data)
565
0
        return true;
566
0
    const Decimal result = compareTo(rhs);
567
0
    if (result.isNaN())
568
0
        return false;
569
0
    return result.isZero() || !result.isNegative();
570
0
}
571
572
Decimal Decimal::abs() const
573
0
{
574
0
    Decimal result(*this);
575
0
    result.m_data.setSign(Positive);
576
0
    return result;
577
0
}
578
579
Decimal::AlignedOperands Decimal::alignOperands(const Decimal& lhs, const Decimal& rhs)
580
0
{
581
0
    ASSERT(lhs.isFinite());
582
0
    ASSERT(rhs.isFinite());
583
0
584
0
    const int lhsExponent = lhs.exponent();
585
0
    const int rhsExponent = rhs.exponent();
586
0
    int exponent = std::min(lhsExponent, rhsExponent);
587
0
    uint64_t lhsCoefficient = lhs.m_data.coefficient();
588
0
    uint64_t rhsCoefficient = rhs.m_data.coefficient();
589
0
590
0
    if (lhsExponent > rhsExponent) {
591
0
        const int numberOfLHSDigits = countDigits(lhsCoefficient);
592
0
        if (numberOfLHSDigits) {
593
0
            const int lhsShiftAmount = lhsExponent - rhsExponent;
594
0
            const int overflow = numberOfLHSDigits + lhsShiftAmount - Precision;
595
0
            if (overflow <= 0) {
596
0
                lhsCoefficient = scaleUp(lhsCoefficient, lhsShiftAmount);
597
0
            } else {
598
0
                lhsCoefficient = scaleUp(lhsCoefficient, lhsShiftAmount - overflow);
599
0
                rhsCoefficient = scaleDown(rhsCoefficient, overflow);
600
0
                exponent += overflow;
601
0
            }
602
0
        }
603
0
604
0
    } else if (lhsExponent < rhsExponent) {
605
0
        const int numberOfRHSDigits = countDigits(rhsCoefficient);
606
0
        if (numberOfRHSDigits) {
607
0
            const int rhsShiftAmount = rhsExponent - lhsExponent;
608
0
            const int overflow = numberOfRHSDigits + rhsShiftAmount - Precision;
609
0
            if (overflow <= 0) {
610
0
                rhsCoefficient = scaleUp(rhsCoefficient, rhsShiftAmount);
611
0
            } else {
612
0
                rhsCoefficient = scaleUp(rhsCoefficient, rhsShiftAmount - overflow);
613
0
                lhsCoefficient = scaleDown(lhsCoefficient, overflow);
614
0
                exponent += overflow;
615
0
            }
616
0
        }
617
0
    }
618
0
619
0
    AlignedOperands alignedOperands;
620
0
    alignedOperands.exponent = exponent;
621
0
    alignedOperands.lhsCoefficient = lhsCoefficient;
622
0
    alignedOperands.rhsCoefficient = rhsCoefficient;
623
0
    return alignedOperands;
624
0
}
625
626
static bool isMultiplePowersOfTen(uint64_t coefficient, int n)
627
0
{
628
0
    return !coefficient || !(coefficient % scaleUp(1, n));
629
0
}
630
631
// Round toward positive infinity.
632
Decimal Decimal::ceil() const
633
0
{
634
0
    if (isSpecial())
635
0
        return *this;
636
0
637
0
    if (exponent() >= 0)
638
0
        return *this;
639
0
640
0
    uint64_t result = m_data.coefficient();
641
0
    const int numberOfDigits = countDigits(result);
642
0
    const int numberOfDropDigits = -exponent();
643
0
    if (numberOfDigits <= numberOfDropDigits)
644
0
        return isPositive() ? Decimal(1) : zero(Positive);
645
0
646
0
    result = scaleDown(result, numberOfDropDigits);
647
0
    if (isPositive() && !isMultiplePowersOfTen(m_data.coefficient(), numberOfDropDigits))
648
0
        ++result;
649
0
    return Decimal(sign(), 0, result);
650
0
}
651
652
Decimal Decimal::compareTo(const Decimal& rhs) const
653
0
{
654
0
    const Decimal result(*this - rhs);
655
0
    switch (result.m_data.formatClass()) {
656
0
    case EncodedData::ClassInfinity:
657
0
        return result.isNegative() ? Decimal(-1) : Decimal(1);
658
0
659
0
    case EncodedData::ClassNaN:
660
0
    case EncodedData::ClassNormal:
661
0
        return result;
662
0
663
0
    case EncodedData::ClassZero:
664
0
        return zero(Positive);
665
0
666
0
    default:
667
0
        ASSERT_NOT_REACHED();
668
0
        return nan();
669
0
    }
670
0
}
671
672
// Round toward negative infinity.
673
Decimal Decimal::floor() const
674
0
{
675
0
    if (isSpecial())
676
0
        return *this;
677
0
678
0
    if (exponent() >= 0)
679
0
        return *this;
680
0
681
0
    uint64_t result = m_data.coefficient();
682
0
    const int numberOfDigits = countDigits(result);
683
0
    const int numberOfDropDigits = -exponent();
684
0
    if (numberOfDigits < numberOfDropDigits)
685
0
        return isPositive() ? zero(Positive) : Decimal(-1);
686
0
687
0
    result = scaleDown(result, numberOfDropDigits);
688
0
    if (isNegative() && !isMultiplePowersOfTen(m_data.coefficient(), numberOfDropDigits))
689
0
        ++result;
690
0
    return Decimal(sign(), 0, result);
691
0
}
692
693
Decimal Decimal::fromDouble(double doubleValue)
694
0
{
695
0
    if (std::isfinite(doubleValue))
696
0
        return fromString(mozToString(doubleValue));
697
0
698
0
    if (std::isinf(doubleValue))
699
0
        return infinity(doubleValue < 0 ? Negative : Positive);
700
0
701
0
    return nan();
702
0
}
703
704
Decimal Decimal::fromString(const String& str)
705
0
{
706
0
    int exponent = 0;
707
0
    Sign exponentSign = Positive;
708
0
    int numberOfDigits = 0;
709
0
    int numberOfDigitsAfterDot = 0;
710
0
    int numberOfExtraDigits = 0;
711
0
    Sign sign = Positive;
712
0
713
0
    enum {
714
0
        StateDigit,
715
0
        StateDot,
716
0
        StateDotDigit,
717
0
        StateE,
718
0
        StateEDigit,
719
0
        StateESign,
720
0
        StateSign,
721
0
        StateStart,
722
0
        StateZero,
723
0
    } state = StateStart;
724
0
725
0
#define HandleCharAndBreak(expected, nextState) \
726
0
    if (ch == expected) { \
727
0
        state = nextState; \
728
0
        break; \
729
0
    }
730
0
731
0
#define HandleTwoCharsAndBreak(expected1, expected2, nextState) \
732
0
    if (ch == expected1 || ch == expected2) { \
733
0
        state = nextState; \
734
0
        break; \
735
0
    }
736
0
737
0
    uint64_t accumulator = 0;
738
0
    for (unsigned index = 0; index < str.length(); ++index) {
739
0
        const int ch = str[index];
740
0
        switch (state) {
741
0
        case StateDigit:
742
0
            if (ch >= '0' && ch <= '9') {
743
0
                if (numberOfDigits < Precision) {
744
0
                    ++numberOfDigits;
745
0
                    accumulator *= 10;
746
0
                    accumulator += ch - '0';
747
0
                } else {
748
0
                    ++numberOfExtraDigits;
749
0
                }
750
0
                break;
751
0
            }
752
0
753
0
            HandleCharAndBreak('.', StateDot);
754
0
            HandleTwoCharsAndBreak('E', 'e', StateE);
755
0
            return nan();
756
0
757
0
        case StateDot:
758
0
        case StateDotDigit:
759
0
            if (ch >= '0' && ch <= '9') {
760
0
                if (numberOfDigits < Precision) {
761
0
                    ++numberOfDigits;
762
0
                    ++numberOfDigitsAfterDot;
763
0
                    accumulator *= 10;
764
0
                    accumulator += ch - '0';
765
0
                }
766
0
                state = StateDotDigit;
767
0
                break;
768
0
            }
769
0
770
0
            HandleTwoCharsAndBreak('E', 'e', StateE);
771
0
            return nan();
772
0
773
0
        case StateE:
774
0
            if (ch == '+') {
775
0
                exponentSign = Positive;
776
0
                state = StateESign;
777
0
                break;
778
0
            }
779
0
780
0
            if (ch == '-') {
781
0
                exponentSign = Negative;
782
0
                state = StateESign;
783
0
                break;
784
0
            }
785
0
786
0
            if (ch >= '0' && ch <= '9') {
787
0
                exponent = ch - '0';
788
0
                state = StateEDigit;
789
0
                break;
790
0
            }
791
0
792
0
            return nan();
793
0
794
0
        case StateEDigit:
795
0
            if (ch >= '0' && ch <= '9') {
796
0
                exponent *= 10;
797
0
                exponent += ch - '0';
798
0
                if (exponent > ExponentMax + Precision) {
799
0
                    if (accumulator)
800
0
                        return exponentSign == Negative ? zero(Positive) : infinity(sign);
801
0
                    return zero(sign);
802
0
                }
803
0
                state = StateEDigit;
804
0
                break;
805
0
            }
806
0
807
0
            return nan();
808
0
809
0
        case StateESign:
810
0
            if (ch >= '0' && ch <= '9') {
811
0
                exponent = ch - '0';
812
0
                state = StateEDigit;
813
0
                break;
814
0
            }
815
0
816
0
            return nan();
817
0
818
0
        case StateSign:
819
0
            if (ch >= '1' && ch <= '9') {
820
0
                accumulator = ch - '0';
821
0
                numberOfDigits = 1;
822
0
                state = StateDigit;
823
0
                break;
824
0
            }
825
0
826
0
            HandleCharAndBreak('0', StateZero);
827
0
            return nan();
828
0
829
0
        case StateStart:
830
0
            if (ch >= '1' && ch <= '9') {
831
0
                accumulator = ch - '0';
832
0
                numberOfDigits = 1;
833
0
                state = StateDigit;
834
0
                break;
835
0
            }
836
0
837
0
            if (ch == '-') {
838
0
                sign = Negative;
839
0
                state = StateSign;
840
0
                break;
841
0
            }
842
0
843
0
            if (ch == '+') {
844
0
                sign = Positive;
845
0
                state = StateSign;
846
0
                break;
847
0
            }
848
0
849
0
            HandleCharAndBreak('0', StateZero);
850
0
            HandleCharAndBreak('.', StateDot);
851
0
            return nan();
852
0
853
0
        case StateZero:
854
0
            if (ch == '0')
855
0
                break;
856
0
857
0
            if (ch >= '1' && ch <= '9') {
858
0
                accumulator = ch - '0';
859
0
                numberOfDigits = 1;
860
0
                state = StateDigit;
861
0
                break;
862
0
            }
863
0
864
0
            HandleCharAndBreak('.', StateDot);
865
0
            HandleTwoCharsAndBreak('E', 'e', StateE);
866
0
            return nan();
867
0
868
0
        default:
869
0
            ASSERT_NOT_REACHED();
870
0
            return nan();
871
0
        }
872
0
    }
873
0
874
0
    if (state == StateZero)
875
0
        return zero(sign);
876
0
877
0
    if (state == StateDigit || state == StateEDigit || state == StateDotDigit) {
878
0
        int resultExponent = exponent * (exponentSign == Negative ? -1 : 1) - numberOfDigitsAfterDot + numberOfExtraDigits;
879
0
        if (resultExponent < ExponentMin)
880
0
            return zero(Positive);
881
0
882
0
        const int overflow = resultExponent - ExponentMax + 1;
883
0
        if (overflow > 0) {
884
0
            if (overflow + numberOfDigits - numberOfDigitsAfterDot > Precision)
885
0
                return infinity(sign);
886
0
            accumulator = scaleUp(accumulator, overflow);
887
0
            resultExponent -= overflow;
888
0
        }
889
0
890
0
        return Decimal(sign, resultExponent, accumulator);
891
0
    }
892
0
893
0
    return nan();
894
0
}
895
896
Decimal Decimal::infinity(const Sign sign)
897
0
{
898
0
    return Decimal(EncodedData(sign, EncodedData::ClassInfinity));
899
0
}
900
901
Decimal Decimal::nan()
902
0
{
903
0
    return Decimal(EncodedData(Positive, EncodedData::ClassNaN));
904
0
}
905
906
Decimal Decimal::remainder(const Decimal& rhs) const
907
0
{
908
0
    const Decimal quotient = *this / rhs;
909
0
    return quotient.isSpecial() ? quotient : *this - (quotient.isNegative() ? quotient.ceil() : quotient.floor()) * rhs;
910
0
}
911
912
Decimal Decimal::round() const
913
0
{
914
0
    if (isSpecial())
915
0
        return *this;
916
0
917
0
    if (exponent() >= 0)
918
0
        return *this;
919
0
920
0
    uint64_t result = m_data.coefficient();
921
0
    const int numberOfDigits = countDigits(result);
922
0
    const int numberOfDropDigits = -exponent();
923
0
    if (numberOfDigits < numberOfDropDigits)
924
0
        return zero(Positive);
925
0
926
0
    result = scaleDown(result, numberOfDropDigits - 1);
927
0
    if (result % 10 >= 5)
928
0
        result += 10;
929
0
    result /= 10;
930
0
    return Decimal(sign(), 0, result);
931
0
}
932
933
double Decimal::toDouble() const
934
0
{
935
0
    if (isFinite()) {
936
0
        bool valid;
937
0
        const double doubleValue = mozToDouble(toString(), &valid);
938
0
        return valid ? doubleValue : std::numeric_limits<double>::quiet_NaN();
939
0
    }
940
0
941
0
    if (isInfinity())
942
0
        return isNegative() ? -std::numeric_limits<double>::infinity() : std::numeric_limits<double>::infinity();
943
0
944
0
    return std::numeric_limits<double>::quiet_NaN();
945
0
}
946
947
String Decimal::toString() const
948
0
{
949
0
    switch (m_data.formatClass()) {
950
0
    case EncodedData::ClassInfinity:
951
0
        return sign() ? "-Infinity" : "Infinity";
952
0
953
0
    case EncodedData::ClassNaN:
954
0
        return "NaN";
955
0
956
0
    case EncodedData::ClassNormal:
957
0
    case EncodedData::ClassZero:
958
0
        break;
959
0
960
0
    default:
961
0
        ASSERT_NOT_REACHED();
962
0
        return "";
963
0
    }
964
0
965
0
    StringBuilder builder;
966
0
    if (sign())
967
0
        builder.append('-');
968
0
969
0
    int originalExponent = exponent();
970
0
    uint64_t coefficient = m_data.coefficient();
971
0
972
0
    if (originalExponent < 0) {
973
0
        const int maxDigits = DBL_DIG;
974
0
        uint64_t lastDigit = 0;
975
0
        while (countDigits(coefficient) > maxDigits) {
976
0
            lastDigit = coefficient % 10;
977
0
            coefficient /= 10;
978
0
            ++originalExponent;
979
0
        }
980
0
981
0
        if (lastDigit >= 5)
982
0
            ++coefficient;
983
0
984
0
        while (originalExponent < 0 && coefficient && !(coefficient % 10)) {
985
0
            coefficient /= 10;
986
0
            ++originalExponent;
987
0
        }
988
0
    }
989
0
990
0
    const String digits = mozToString(coefficient);
991
0
    int coefficientLength = static_cast<int>(digits.length());
992
0
    const int adjustedExponent = originalExponent + coefficientLength - 1;
993
0
    if (originalExponent <= 0 && adjustedExponent >= -6) {
994
0
        if (!originalExponent) {
995
0
            builder.append(digits);
996
0
            return builder.toString();
997
0
        }
998
0
999
0
        if (adjustedExponent >= 0) {
1000
0
            for (int i = 0; i < coefficientLength; ++i) {
1001
0
                builder.append(digits[i]);
1002
0
                if (i == adjustedExponent)
1003
0
                    builder.append('.');
1004
0
            }
1005
0
            return builder.toString();
1006
0
        }
1007
0
1008
0
        builder.appendLiteral("0.");
1009
0
        for (int i = adjustedExponent + 1; i < 0; ++i)
1010
0
            builder.append('0');
1011
0
1012
0
        builder.append(digits);
1013
0
1014
0
    } else {
1015
0
        builder.append(digits[0]);
1016
0
        while (coefficientLength >= 2 && digits[coefficientLength - 1] == '0')
1017
0
            --coefficientLength;
1018
0
        if (coefficientLength >= 2) {
1019
0
            builder.append('.');
1020
0
            for (int i = 1; i < coefficientLength; ++i)
1021
0
                builder.append(digits[i]);
1022
0
        }
1023
0
1024
0
        if (adjustedExponent) {
1025
0
            builder.append(adjustedExponent < 0 ? "e" : "e+");
1026
0
            builder.appendNumber(adjustedExponent);
1027
0
        }
1028
0
    }
1029
0
    return builder.toString();
1030
0
}
1031
1032
bool Decimal::toString(char* strBuf, size_t bufLength) const
1033
0
{
1034
0
  ASSERT(bufLength > 0);
1035
0
  String str = toString();
1036
0
  size_t length = str.copy(strBuf, bufLength);
1037
0
  if (length < bufLength) {
1038
0
    strBuf[length] = '\0';
1039
0
    return true;
1040
0
  }
1041
0
  strBuf[bufLength - 1] = '\0';
1042
0
  return false;
1043
0
}
1044
1045
Decimal Decimal::zero(Sign sign)
1046
0
{
1047
0
    return Decimal(EncodedData(sign, EncodedData::ClassZero));
1048
0
}
1049
1050
} // namespace blink