| Differences between
and this patch
- a/Source/WebCore/ChangeLog +85 lines
Lines 1-3 a/Source/WebCore/ChangeLog_sec1
1
2012-05-24  Yoshifumi Inoue  <yosin@chromium.org>
2
3
        [Platform] Introduce Decimal class for Number/Range input type.
4
        https://bugs.webkit.org/show_bug.cgi?id=87360
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        This patch added new class Decimal for decimal arithmatic in two
9
        files: platform/Decimal.cpp and Decimal.h with unit test.
10
11
        Test: WebKit/chromium/tests/DecimalTest.cpp
12
13
        * CMakeLists.txt:
14
        * GNUmakefile.list.am:
15
        * Target.pri:
16
        * WebCore.gypi:
17
        * WebCore.vcproj/WebCore.vcproj:
18
        * WebCore.xcodeproj/project.pbxproj:
19
        * platform/Decimal.cpp: Added.
20
        (WebCore):
21
        (DecimalPrivate):
22
        (SpecialValueHandler):
23
        (UInt128):
24
        (WebCore::DecimalPrivate::UInt128::high):
25
        (WebCore::DecimalPrivate::UInt128::low):
26
        (WebCore::DecimalPrivate::UInt128::isZero):
27
        (WebCore::DecimalPrivate::countDigits):
28
        (WebCore::DecimalPrivate::multiplyHigh):
29
        (WebCore::DecimalPrivate::power):
30
        (WebCore::DecimalPrivate::scaleDown):
31
        (WebCore::DecimalPrivate::scaleUp):
32
        (WebCore::DecimalPrivate::SpecialValueHandler::SpecialValueHandler):
33
        (WebCore::DecimalPrivate::SpecialValueHandler::handle):
34
        (WebCore::DecimalPrivate::SpecialValueHandler::value):
35
        (WebCore::DecimalPrivate::UInt128::UInt128):
36
        (WebCore::DecimalPrivate::UInt128::operator /=):
37
        (WebCore::DecimalPrivate::UInt128::multiply):
38
        (WebCore::Decimal::EncodedData::EncodedData):
39
        (WebCore::Decimal::EncodedData::coefficient):
40
        (WebCore::Decimal::EncodedData::formatClass)
41
        (WebCore::Decimal::EncodedData::exponent):
42
        (WebCore::Decimal::EncodedData::isFinite):
43
        (WebCore::Decimal::EncodedData::isSpecial):
44
        (WebCore::Decimal::EncodedData::isZero):
45
        (WebCore::Decimal::EncodedData::sign):
46
        (WebCore::Decimal::EncodedData::setSign):
47
        (WebCore::Decimal::Decimal):
48
        (WebCore::Decimal::operator =):
49
        (WebCore::Decimal::operator +=):
50
        (WebCore::Decimal::operator -=):
51
        (WebCore::Decimal::operator *=):
52
        (WebCore::Decimal::operator /=):
53
        (WebCore::Decimal::operator -):
54
        (WebCore::Decimal::operator +):
55
        (WebCore::Decimal::operator *):
56
        (WebCore::Decimal::operator /):
57
        (WebCore::Decimal::operator==):
58
        (WebCore::Decimal::operator!=):
59
        (WebCore::Decimal::operator <):
60
        (WebCore::Decimal::operator <=):
61
        (WebCore::Decimal::operator >):
62
        (WebCore::Decimal::operator >=):
63
        (WebCore::Decimal::exponent):
64
        (WebCore::Decimal::sign):
65
        (WebCore::Decimal::abs):
66
        (WebCore::Decimal::ceiling):
67
        (WebCore::Decimal::compareTo):
68
        (WebCore::Decimal::fastEquals):
69
        (WebCore::Decimal::floor):
70
        (WebCore::Decimal::fromString):
71
        (WebCore::Decimal::infinity):
72
        (WebCore::Decimal::nan):
73
        (WebCore::Decimal::remainder):
74
        (WebCore::Decimal::round):
75
        (WebCore::Decimal::toString):
76
        (WebCore::Decimal::zero):
77
        * platform/Decimal.h: Added.
78
        (WebCore::Decimal::isFinite):
79
        (WebCore::Decimal::isNegative):
80
        (WebCore::Decimal::isPositive):
81
        (WebCore::Decimal::isSpecial):
82
        (WebCore::Decimal::isZero):
83
        (WebCore::Decimal::value):
84
        (WebCore::Decimal::invertSign):
85
1
2012-05-27  Yoshifumi Inoue  <yosin@chromium.org>
86
2012-05-27  Yoshifumi Inoue  <yosin@chromium.org>
2
87
3
        [WTF] Introduce UINT64_C to MathExtras.h
88
        [WTF] Introduce UINT64_C to MathExtras.h
- a/Source/WebKit/chromium/ChangeLog +22 lines
Lines 1-3 a/Source/WebKit/chromium/ChangeLog_sec1
1
2012-05-24  Yoshifumi Inoue  <yosin@chromium.org>
2
3
        [Platform] Introduce Decimal class for Number/Range input type.
4
        https://bugs.webkit.org/show_bug.cgi?id=87360
5
6
        Reviewed by NOBODY (OOPS!).
7
8
        This patch added unit test for Decimal class.
9
10
        * WebKit.gypi:
11
        * tests/DecimalTest.cpp: Added.
12
        (WebCore::operator<<): Output Decimal for unit test debugging
13
        (DecimalTest):
14
        (DecimalStepRange):
15
        (DecimalTest::DecimalStepRange::DecimalStepRange):
16
        (DecimalTest::DecimalStepRange::clampValue):
17
        (DecimalTest::DecimalTest::encode):
18
        (DecimalTest::DecimalTest::fromString):
19
        (DecimalTest::DecimalTest::stepDown):
20
        (DecimalTest::DecimalTest::stepUp):
21
        (DecimalTest::TEST_F):
22
1
2012-05-25  Ryosuke Niwa  <rniwa@webkit.org>
23
2012-05-25  Ryosuke Niwa  <rniwa@webkit.org>
2
24
3
        Roll chromium DEPS from r139156 to r139184.
25
        Roll chromium DEPS from r139156 to r139184.
- a/Source/WebCore/CMakeLists.txt +1 lines
Lines 1107-1112 SET(WebCore_SOURCES a/Source/WebCore/CMakeLists.txt_sec1
1107
    platform/ContentType.cpp
1107
    platform/ContentType.cpp
1108
    platform/CrossThreadCopier.cpp
1108
    platform/CrossThreadCopier.cpp
1109
    platform/DateComponents.cpp
1109
    platform/DateComponents.cpp
1110
    platform/Decimal.cpp
1110
    platform/DragData.cpp
1111
    platform/DragData.cpp
1111
    platform/DragImage.cpp
1112
    platform/DragImage.cpp
1112
    platform/EventTracer.cpp
1113
    platform/EventTracer.cpp
- a/Source/WebCore/GNUmakefile.list.am +2 lines
Lines 3115-3120 webcore_sources += \ a/Source/WebCore/GNUmakefile.list.am_sec1
3115
	Source/WebCore/platform/Cursor.h \
3115
	Source/WebCore/platform/Cursor.h \
3116
	Source/WebCore/platform/DateComponents.cpp \
3116
	Source/WebCore/platform/DateComponents.cpp \
3117
	Source/WebCore/platform/DateComponents.h \
3117
	Source/WebCore/platform/DateComponents.h \
3118
	Source/WebCore/platform/Decimal.cpp \
3119
	Source/WebCore/platform/Decimal.h \
3118
	Source/WebCore/platform/DragData.cpp \
3120
	Source/WebCore/platform/DragData.cpp \
3119
	Source/WebCore/platform/DragData.h \
3121
	Source/WebCore/platform/DragData.h \
3120
	Source/WebCore/platform/DragImage.cpp \
3122
	Source/WebCore/platform/DragImage.cpp \
- a/Source/WebCore/Target.pri +2 lines
Lines 1083-1088 SOURCES += \ a/Source/WebCore/Target.pri_sec1
1083
    platform/ContentType.cpp \
1083
    platform/ContentType.cpp \
1084
    platform/CrossThreadCopier.cpp \
1084
    platform/CrossThreadCopier.cpp \
1085
    platform/DateComponents.cpp \
1085
    platform/DateComponents.cpp \
1086
    platform/Decimal.cpp \
1086
    platform/DragData.cpp \
1087
    platform/DragData.cpp \
1087
    platform/DragImage.cpp \
1088
    platform/DragImage.cpp \
1088
    platform/EventTracer.cpp \
1089
    platform/EventTracer.cpp \
Lines 2200-2205 HEADERS += \ a/Source/WebCore/Target.pri_sec2
2200
    platform/ContextMenu.h \
2201
    platform/ContextMenu.h \
2201
    platform/CrossThreadCopier.h \
2202
    platform/CrossThreadCopier.h \
2202
    platform/DateComponents.h \
2203
    platform/DateComponents.h \
2204
    platform/Decimal.h \
2203
    platform/DragData.h \
2205
    platform/DragData.h \
2204
    platform/DragImage.h \
2206
    platform/DragImage.h \
2205
    platform/EventTracer.h \
2207
    platform/EventTracer.h \
- a/Source/WebCore/WebCore.gypi +2 lines
Lines 271-276 a/Source/WebCore/WebCore.gypi_sec1
271
            'platform/CookiesStrategy.h',
271
            'platform/CookiesStrategy.h',
272
            'platform/Cursor.h',
272
            'platform/Cursor.h',
273
            'platform/DateComponents.h',
273
            'platform/DateComponents.h',
274
            'platform/Decimal.h'
274
            'platform/DragData.h',
275
            'platform/DragData.h',
275
            'platform/DragImage.h',
276
            'platform/DragImage.h',
276
            'platform/EventTracer.h',
277
            'platform/EventTracer.h',
Lines 3149-3154 a/Source/WebCore/WebCore.gypi_sec2
3149
            'platform/CrossThreadCopier.h',
3150
            'platform/CrossThreadCopier.h',
3150
            'platform/Cursor.cpp',
3151
            'platform/Cursor.cpp',
3151
            'platform/DateComponents.cpp',
3152
            'platform/DateComponents.cpp',
3153
            'platform/Decimal.cpp',
3152
            'platform/DragData.cpp',
3154
            'platform/DragData.cpp',
3153
            'platform/DragImage.cpp',
3155
            'platform/DragImage.cpp',
3154
            'platform/EventLoop.h',
3156
            'platform/EventLoop.h',
- a/Source/WebCore/WebCore.vcproj/WebCore.vcproj +8 lines
Lines 27835-27840 a/Source/WebCore/WebCore.vcproj/WebCore.vcproj_sec1
27835
				>
27835
				>
27836
			</File>
27836
			</File>
27837
			<File
27837
			<File
27838
				RelativePath="..\platform\Decimal.cpp"
27839
				>
27840
			</File>
27841
			<File
27842
				RelativePath="..\platform\Decimal.h"
27843
				>
27844
			</File>
27845
			<File
27838
				RelativePath="..\platform\DragData.cpp"
27846
				RelativePath="..\platform\DragData.cpp"
27839
				>
27847
				>
27840
			</File>
27848
			</File>
- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj +8 lines
Lines 1194-1199 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec1
1194
		450CEBF015073BBE002BB149 /* LabelableElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 450CEBEE15073BBE002BB149 /* LabelableElement.cpp */; };
1194
		450CEBF015073BBE002BB149 /* LabelableElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 450CEBEE15073BBE002BB149 /* LabelableElement.cpp */; };
1195
		450CEBF115073BBE002BB149 /* LabelableElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 450CEBEF15073BBE002BB149 /* LabelableElement.h */; settings = {ATTRIBUTES = (Private, ); }; };
1195
		450CEBF115073BBE002BB149 /* LabelableElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 450CEBEF15073BBE002BB149 /* LabelableElement.h */; settings = {ATTRIBUTES = (Private, ); }; };
1196
		45BAC2B01360BBAB005DA258 /* IconURL.h in Headers */ = {isa = PBXBuildFile; fileRef = 45BAC2AF1360BBAB005DA258 /* IconURL.h */; settings = {ATTRIBUTES = (Private, ); }; };
1196
		45BAC2B01360BBAB005DA258 /* IconURL.h in Headers */ = {isa = PBXBuildFile; fileRef = 45BAC2AF1360BBAB005DA258 /* IconURL.h */; settings = {ATTRIBUTES = (Private, ); }; };
1197
		45FEA5CF156DDE8C00654101 /* Decimal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45FEA5CD156DDE8C00654101 /* Decimal.cpp */; };
1198
		45FEA5D0156DDE8C00654101 /* Decimal.h in Headers */ = {isa = PBXBuildFile; fileRef = 45FEA5CE156DDE8C00654101 /* Decimal.h */; settings = {ATTRIBUTES = (Private, ); }; };
1197
		4614A1FE0B23A8D600446E1C /* copyCursor.png in Resources */ = {isa = PBXBuildFile; fileRef = 4614A1FD0B23A8D600446E1C /* copyCursor.png */; };
1199
		4614A1FE0B23A8D600446E1C /* copyCursor.png in Resources */ = {isa = PBXBuildFile; fileRef = 4614A1FD0B23A8D600446E1C /* copyCursor.png */; };
1198
		46700ED0127B96CB00F5D5D6 /* FileWriterSync.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46700ECE127B96CB00F5D5D6 /* FileWriterSync.cpp */; };
1200
		46700ED0127B96CB00F5D5D6 /* FileWriterSync.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 46700ECE127B96CB00F5D5D6 /* FileWriterSync.cpp */; };
1199
		46700ED1127B96CB00F5D5D6 /* FileWriterSync.h in Headers */ = {isa = PBXBuildFile; fileRef = 46700ECF127B96CB00F5D5D6 /* FileWriterSync.h */; };
1201
		46700ED1127B96CB00F5D5D6 /* FileWriterSync.h in Headers */ = {isa = PBXBuildFile; fileRef = 46700ECF127B96CB00F5D5D6 /* FileWriterSync.h */; };
Lines 8195-8200 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec2
8195
		450CEBEE15073BBE002BB149 /* LabelableElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LabelableElement.cpp; sourceTree = "<group>"; };
8197
		450CEBEE15073BBE002BB149 /* LabelableElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LabelableElement.cpp; sourceTree = "<group>"; };
8196
		450CEBEF15073BBE002BB149 /* LabelableElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelableElement.h; sourceTree = "<group>"; };
8198
		450CEBEF15073BBE002BB149 /* LabelableElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LabelableElement.h; sourceTree = "<group>"; };
8197
		45BAC2AF1360BBAB005DA258 /* IconURL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IconURL.h; sourceTree = "<group>"; };
8199
		45BAC2AF1360BBAB005DA258 /* IconURL.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IconURL.h; sourceTree = "<group>"; };
8200
		45FEA5CD156DDE8C00654101 /* Decimal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Decimal.cpp; sourceTree = "<group>"; };
8201
		45FEA5CE156DDE8C00654101 /* Decimal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Decimal.h; sourceTree = "<group>"; };
8198
		4614A1FD0B23A8D600446E1C /* copyCursor.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = copyCursor.png; sourceTree = "<group>"; };
8202
		4614A1FD0B23A8D600446E1C /* copyCursor.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = copyCursor.png; sourceTree = "<group>"; };
8199
		46700ECE127B96CB00F5D5D6 /* FileWriterSync.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FileWriterSync.cpp; path = Modules/filesystem/FileWriterSync.cpp; sourceTree = "<group>"; };
8203
		46700ECE127B96CB00F5D5D6 /* FileWriterSync.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FileWriterSync.cpp; path = Modules/filesystem/FileWriterSync.cpp; sourceTree = "<group>"; };
8200
		46700ECF127B96CB00F5D5D6 /* FileWriterSync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileWriterSync.h; path = Modules/filesystem/FileWriterSync.h; sourceTree = "<group>"; };
8204
		46700ECF127B96CB00F5D5D6 /* FileWriterSync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileWriterSync.h; path = Modules/filesystem/FileWriterSync.h; sourceTree = "<group>"; };
Lines 20324-20329 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec3
20324
				F587868402DE3B8601EA4122 /* Cursor.h */,
20328
				F587868402DE3B8601EA4122 /* Cursor.h */,
20325
				A5732B08136A161D005C8D7C /* DateComponents.cpp */,
20329
				A5732B08136A161D005C8D7C /* DateComponents.cpp */,
20326
				A5732B09136A161D005C8D7C /* DateComponents.h */,
20330
				A5732B09136A161D005C8D7C /* DateComponents.h */,
20331
				45FEA5CD156DDE8C00654101 /* Decimal.cpp */,
20332
				45FEA5CE156DDE8C00654101 /* Decimal.h */,
20327
				A79546420B5C4CB4007B438F /* DragData.cpp */,
20333
				A79546420B5C4CB4007B438F /* DragData.cpp */,
20328
				A7B6E69D0B291A9600D0529F /* DragData.h */,
20334
				A7B6E69D0B291A9600D0529F /* DragData.h */,
20329
				A7CFB3CF0B7ED10A0070C32D /* DragImage.cpp */,
20335
				A7CFB3CF0B7ED10A0070C32D /* DragImage.cpp */,
Lines 22083-22088 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec4
22083
				F55B3DB61251F12D003EF269 /* DateInputType.h in Headers */,
22089
				F55B3DB61251F12D003EF269 /* DateInputType.h in Headers */,
22084
				F55B3DB81251F12D003EF269 /* DateTimeInputType.h in Headers */,
22090
				F55B3DB81251F12D003EF269 /* DateTimeInputType.h in Headers */,
22085
				F55B3DBA1251F12D003EF269 /* DateTimeLocalInputType.h in Headers */,
22091
				F55B3DBA1251F12D003EF269 /* DateTimeLocalInputType.h in Headers */,
22092
				45FEA5D0156DDE8C00654101 /* Decimal.h in Headers */,
22086
				A8C228A111D5722E00D5A7D3 /* DecodedDataDocumentParser.h in Headers */,
22093
				A8C228A111D5722E00D5A7D3 /* DecodedDataDocumentParser.h in Headers */,
22087
				CECCFC3B141973D5002A0AC1 /* DecodeEscapeSequences.h in Headers */,
22094
				CECCFC3B141973D5002A0AC1 /* DecodeEscapeSequences.h in Headers */,
22088
				4162A451101145AE00DFF3ED /* DedicatedWorkerContext.h in Headers */,
22095
				4162A451101145AE00DFF3ED /* DedicatedWorkerContext.h in Headers */,
Lines 25577-25582 a/Source/WebCore/WebCore.xcodeproj/project.pbxproj_sec5
25577
				F55B3DB51251F12D003EF269 /* DateInputType.cpp in Sources */,
25584
				F55B3DB51251F12D003EF269 /* DateInputType.cpp in Sources */,
25578
				F55B3DB71251F12D003EF269 /* DateTimeInputType.cpp in Sources */,
25585
				F55B3DB71251F12D003EF269 /* DateTimeInputType.cpp in Sources */,
25579
				F55B3DB91251F12D003EF269 /* DateTimeLocalInputType.cpp in Sources */,
25586
				F55B3DB91251F12D003EF269 /* DateTimeLocalInputType.cpp in Sources */,
25587
				45FEA5CF156DDE8C00654101 /* Decimal.cpp in Sources */,
25580
				A8C228A211D5722E00D5A7D3 /* DecodedDataDocumentParser.cpp in Sources */,
25588
				A8C228A211D5722E00D5A7D3 /* DecodedDataDocumentParser.cpp in Sources */,
25581
				4162A450101145AE00DFF3ED /* DedicatedWorkerContext.cpp in Sources */,
25589
				4162A450101145AE00DFF3ED /* DedicatedWorkerContext.cpp in Sources */,
25582
				41A3D58E101C152D00316D07 /* DedicatedWorkerThread.cpp in Sources */,
25590
				41A3D58E101C152D00316D07 /* DedicatedWorkerThread.cpp in Sources */,
- a/Source/WebCore/platform/Decimal.cpp +1038 lines
Line 0 a/Source/WebCore/platform/Decimal.cpp_sec1
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 "config.h"
32
#include "Decimal.h"
33
34
#include <algorithm>
35
#include <float.h>
36
37
#include <wtf/Assertions.h>
38
#include <wtf/MathExtras.h>
39
#include <wtf/Noncopyable.h>
40
#include <wtf/text/StringBuilder.h>
41
42
namespace WebCore {
43
44
namespace DecimalPrivate {
45
46
static int const ExponentMax = 1023;
47
static int const ExponentMin = -1023;
48
static int const Precision = 18;
49
50
static const uint64_t MaxCoefficient = UINT64_C(0x16345785D89FFFF); // 999999999999999999 == 18 9's
51
52
// This class handles Decimal special values.
53
class SpecialValueHandler {
54
    WTF_MAKE_NONCOPYABLE(SpecialValueHandler);
55
public:
56
    enum HandleResult {
57
        BothFinite,
58
        Bothinfinity,
59
        EitherNaN,
60
        LHSIsinfinity,
61
        RHSIsinfinity,
62
    };
63
64
    SpecialValueHandler(const Decimal& lhs, const Decimal& rhs);
65
    HandleResult handle();
66
    Decimal value() const;
67
68
private:
69
    enum Result {
70
        ResultIsLHS,
71
        ResultIsRHS,
72
        ResultIsUnknown,
73
    };
74
75
    const Decimal& m_lhs;
76
    const Decimal& m_rhs;
77
    Result m_result;
78
};
79
80
// This class is used for 128 bit unsigned integer arithmetic.
81
class UInt128 {
82
public:
83
    UInt128(uint64_t low, uint64_t high);
84
85
    UInt128& operator/=(uint32_t);
86
87
    uint64_t high() const { return m_high; }
88
    uint64_t low() const { return m_low; }
89
90
    static UInt128 multiply(uint64_t low, uint64_t high);
91
92
private:
93
    bool isZero() const { return !m_low && !m_high; }
94
95
    uint64_t m_high;
96
    uint64_t m_low;
97
};
98
99
static int countDigits(uint64_t x)
100
{
101
    int numberOfDigits = 0;
102
    uint64_t powerOf10 = 1;
103
    while (x >= powerOf10) {
104
        ++numberOfDigits;
105
        if (powerOf10 >= uint64_t(-1) / 10)
106
            break;
107
        powerOf10 *= 10;
108
    }
109
    return numberOfDigits;
110
}
111
112
static uint64_t multiplyHigh(uint64_t u, uint64_t v)
113
{
114
    const int n = 64;
115
    const int n2 = n / 2;
116
    const uint64_t mask = (uint64_t(1) << n2) - 1;
117
    uint64_t u0 = u & mask;
118
    uint64_t u1 = u >> n2;
119
    uint64_t v0 = v & mask;
120
    uint64_t v1 = v >> n2;
121
    uint64_t w0 = u0 * v0;
122
    uint64_t tt = u1 * v0 + (w0 >> n2);
123
    uint64_t w1 = tt & mask;
124
    uint64_t w2 = tt >> n2;
125
    w1 = u0 * v1 + w1;
126
    return u1 * v1 + w2 + (w1 >> n2);
127
}
128
129
template<typename T>
130
static T power(T const x, unsigned n)
131
{
132
    T y = 1;
133
    T z = x;
134
    for (;;) {
135
        if (n & 1)
136
            y = y * z;
137
138
        n >>= 1;
139
        if (!n)
140
            return y;
141
142
        z = z * z;
143
    }
144
}
145
146
static uint64_t scaleDown(uint64_t x, int n)
147
{
148
    ASSERT(n >= 0);
149
    while (n > 0 && x) {
150
        x /= 10;
151
        --n;
152
    }
153
    return x;
154
}
155
156
static uint64_t scaleUp(uint64_t x, int n)
157
{
158
    ASSERT(n >= 0);
159
    ASSERT(n < Precision);
160
    uint64_t result = x * power(uint64_t(10), n);
161
    ASSERT(result >= x);
162
    return result;
163
}
164
165
SpecialValueHandler::SpecialValueHandler(const Decimal& lhs, const Decimal& rhs)
166
    : m_lhs(lhs), m_rhs(rhs), m_result(ResultIsUnknown)
167
{
168
}
169
170
SpecialValueHandler::HandleResult SpecialValueHandler::handle()
171
{
172
    if (m_lhs.isFinite() && m_rhs.isFinite())
173
        return BothFinite;
174
175
    const Decimal::FormatClass lhsClass = m_lhs.value().formatClass();
176
    const Decimal::FormatClass rhsClass = m_rhs.value().formatClass();
177
    if (lhsClass == Decimal::ClassNaN) {
178
        m_result = ResultIsLHS;
179
        return EitherNaN;
180
     }
181
182
    if (rhsClass == Decimal::ClassNaN) {
183
        m_result = ResultIsRHS;
184
        return EitherNaN;
185
     }
186
187
    if (lhsClass == Decimal::ClassInfinity)
188
        return rhsClass == Decimal::ClassInfinity ? Bothinfinity : LHSIsinfinity;
189
190
    if (rhsClass == Decimal::ClassInfinity)
191
        return RHSIsinfinity;
192
193
    ASSERT_NOT_REACHED();
194
    return BothFinite;
195
}
196
197
Decimal SpecialValueHandler::value() const
198
{
199
    switch (m_result) {
200
    case ResultIsLHS:
201
        return m_lhs;
202
    case ResultIsRHS:
203
        return m_rhs;
204
    case ResultIsUnknown:
205
    default:
206
        ASSERT_NOT_REACHED();
207
        return m_lhs;
208
    }
209
}
210
211
UInt128::UInt128(uint64_t low, uint64_t high)
212
    : m_high(high), m_low(low)
213
{
214
}
215
216
UInt128& UInt128::operator/=(const uint32_t divisor)
217
{
218
    if (!m_high) {
219
        m_low /= divisor;
220
        return *this;
221
    }
222
223
    uint32_t dividend[4];
224
    dividend[0] = uint32_t(m_low & uint32_t(-1));
225
    dividend[1] = uint32_t(m_low >> 32);
226
    dividend[2] = uint32_t(m_high & uint32_t(-1));
227
    dividend[3] = uint32_t(m_high >> 32);
228
229
    uint32_t quotient[4];
230
    uint32_t remainder = 0;
231
    for (int i = 3; i >= 0; --i) {
232
        const uint64_t work = (uint64_t(remainder) << 32) | dividend[i];
233
        remainder = uint32_t(work % divisor);
234
        quotient[i] = uint32_t(work / divisor);
235
    }
236
    m_low = quotient[0] | (uint64_t(quotient[1]) << 32);
237
    m_high = quotient[2] | (uint64_t(quotient[3]) << 32);
238
    return *this;
239
}
240
241
UInt128 UInt128::multiply(uint64_t u, uint64_t v)
242
{
243
    return UInt128(u * v, multiplyHigh(u, v));
244
}
245
246
} // namespace DecimalPrivate
247
248
using namespace DecimalPrivate;
249
250
Decimal::EncodedData::EncodedData(Sign sign, FormatClass formatClass)
251
    : m_coefficient(0)
252
    , m_exponent(0)
253
    , m_formatClass(formatClass)
254
    , m_sign(sign)
255
{
256
}
257
258
Decimal::EncodedData::EncodedData(Sign sign, int exponent, uint64_t coefficient)
259
    : m_formatClass(coefficient ? ClassNormal : ClassZero)
260
    , m_sign(sign)
261
{
262
    if (exponent >= ExponentMin && exponent <= ExponentMax) {
263
        while (coefficient >= MaxCoefficient) {
264
            coefficient /= 10;
265
            ++exponent;
266
        }
267
    }
268
269
    if (exponent > ExponentMax) {
270
        m_coefficient = 0;
271
        m_exponent = 0;
272
        m_formatClass = ClassInfinity;
273
        return;
274
    }
275
276
    if (exponent < ExponentMin) {
277
        m_coefficient = 0;
278
        m_exponent = 0;
279
        m_formatClass = ClassZero;
280
        return;
281
    }
282
283
    m_coefficient = coefficient;
284
    m_exponent = int16_t(exponent);
285
}
286
287
bool Decimal::EncodedData::operator==(const EncodedData& another) const
288
{
289
    return m_sign == another.m_sign
290
        && m_formatClass == another.m_formatClass
291
        && m_exponent == another.m_exponent
292
        && m_coefficient == another.m_coefficient;
293
}
294
295
Decimal::Decimal(int32_t i32)
296
    : m_data(i32 < 0 ? Negative : Positive, 0, i32 < 0 ? uint32_t(-i32) : i32)
297
{
298
}
299
300
Decimal::Decimal(Sign sign, int exponent, uint64_t coefficient)
301
    : m_data(sign, exponent, coefficient)
302
{
303
}
304
305
Decimal::Decimal(const EncodedData& data)
306
    : m_data(data)
307
{
308
}
309
310
Decimal::Decimal(const Decimal& other)
311
    : m_data(other.m_data)
312
{
313
}
314
315
Decimal& Decimal::operator=(const Decimal& other)
316
{
317
    m_data = other.m_data;
318
    return *this;
319
}
320
321
Decimal& Decimal::operator+=(const Decimal& other)
322
{
323
    m_data = (*this + other).m_data;
324
    return *this;
325
}
326
327
Decimal& Decimal::operator-=(const Decimal& other)
328
{
329
    m_data = (*this - other).m_data;
330
    return *this;
331
}
332
333
Decimal& Decimal::operator*=(const Decimal& other)
334
{
335
    m_data = (*this * other).m_data;
336
    return *this;
337
}
338
339
Decimal& Decimal::operator/=(const Decimal& other)
340
{
341
    m_data = (*this / other).m_data;
342
    return *this;
343
}
344
345
Decimal Decimal::operator-() const
346
{
347
    Decimal result(*this);
348
    result.m_data.setSign(invertSign(m_data.sign()));
349
    return result;
350
}
351
352
Decimal Decimal::operator+(const Decimal& rhs) const
353
{
354
    const Decimal& lhs = *this;
355
    const Sign lhsSign = lhs.sign();
356
    const Sign rhsSign = rhs.sign();
357
358
    SpecialValueHandler handler(lhs, rhs);
359
    switch (handler.handle()) {
360
    case SpecialValueHandler::BothFinite:
361
        break;
362
363
    case SpecialValueHandler::Bothinfinity:
364
        return lhsSign == rhsSign ? lhs : nan();
365
366
    case SpecialValueHandler::EitherNaN:
367
        return handler.value();
368
369
    case SpecialValueHandler::LHSIsinfinity:
370
        return lhs;
371
372
    case SpecialValueHandler::RHSIsinfinity:
373
        return rhs;
374
    }
375
376
    ASSERT(lhs.isFinite());
377
    ASSERT(rhs.isFinite());
378
379
    const int lhsExponent = lhs.exponent();
380
    const int rhsExponent = rhs.exponent();
381
    int resultExponent = std::min(lhsExponent, rhsExponent);
382
    uint64_t lhsCoefficient = lhs.m_data.coefficient();
383
    uint64_t rhsCoefficient = rhs.m_data.coefficient();
384
385
    // Make coefficient aligned.
386
    if (lhsExponent > rhsExponent) {
387
        const int numberOfLHSDigits = countDigits(lhsCoefficient);
388
        if (numberOfLHSDigits) {
389
            const int lhsShiftAmount = lhsExponent - rhsExponent;
390
            const int overflow = numberOfLHSDigits + lhsShiftAmount - Precision;
391
            if (overflow <= 0)
392
                lhsCoefficient = scaleUp(lhsCoefficient, lhsShiftAmount);
393
            else {
394
                lhsCoefficient = scaleUp(lhsCoefficient, lhsShiftAmount - overflow);
395
                rhsCoefficient = scaleDown(rhsCoefficient, overflow);
396
                resultExponent += overflow;
397
            }
398
        }
399
400
    } if (lhsExponent < rhsExponent) {
401
        const int numberOfRHSDigits = countDigits(rhsCoefficient);
402
        if (numberOfRHSDigits) {
403
            const int rhsShiftAmount = rhsExponent - lhsExponent;
404
            const int overflow = numberOfRHSDigits + rhsShiftAmount - Precision;
405
            if (overflow <= 0)
406
                rhsCoefficient = scaleUp(rhsCoefficient, rhsShiftAmount);
407
            else {
408
                rhsCoefficient = scaleUp(rhsCoefficient, rhsShiftAmount - overflow);
409
                lhsCoefficient = scaleDown(lhsCoefficient, overflow);
410
                resultExponent += overflow;
411
            }
412
        }
413
    }
414
415
    uint64_t const result = lhsSign == rhsSign ? lhsCoefficient + rhsCoefficient : lhsCoefficient - rhsCoefficient;
416
    return lhsSign == Negative && rhsSign == Positive && !result
417
            ? Decimal(Positive, resultExponent, 0)
418
            : int64_t(result) >= 0
419
                ? Decimal(lhsSign, resultExponent, result)
420
                : Decimal(invertSign(lhsSign), resultExponent, -int64_t(result));
421
}
422
423
Decimal Decimal::operator-(const Decimal& rhs) const
424
{
425
    const Decimal& lhs = *this;
426
    const Sign lhsSign = lhs.sign();
427
    const Sign rhsSign = rhs.sign();
428
429
    SpecialValueHandler handler(lhs, rhs);
430
    switch (handler.handle()) {
431
    case SpecialValueHandler::BothFinite:
432
        break;
433
434
    case SpecialValueHandler::Bothinfinity:
435
        return lhsSign == rhsSign ? nan() : lhs;
436
437
    case SpecialValueHandler::EitherNaN:
438
        return handler.value();
439
440
    case SpecialValueHandler::LHSIsinfinity:
441
        return lhs;
442
443
    case SpecialValueHandler::RHSIsinfinity:
444
        return infinity(invertSign(rhsSign));
445
    }
446
447
    ASSERT(lhs.isFinite());
448
    ASSERT(rhs.isFinite());
449
450
    uint64_t lhsCoefficient = lhs.m_data.coefficient();
451
    uint64_t rhsCoefficient = rhs.m_data.coefficient();
452
453
    const int lhsExponent = lhs.exponent();
454
    const int rhsExponent = rhs.exponent();
455
    int resultExponent = std::min(lhsExponent, rhsExponent);
456
457
    // Make coefficient aligned.
458
    if (lhsExponent > rhsExponent) {
459
        const int numberOfLHSDigits = countDigits(lhsCoefficient);
460
        if (numberOfLHSDigits) {
461
            const int lhsShiftAmount = lhsExponent - rhsExponent;
462
            const int overflow = numberOfLHSDigits + lhsShiftAmount - Precision;
463
            if (overflow <= 0)
464
                lhsCoefficient = scaleUp(lhsCoefficient, lhsShiftAmount);
465
            else {
466
                lhsCoefficient = scaleUp(lhsCoefficient, lhsShiftAmount - overflow);
467
                rhsCoefficient = scaleDown(rhsCoefficient, overflow);
468
                resultExponent += overflow;
469
            }
470
        }
471
472
    } if (lhsExponent < rhsExponent) {
473
        const int numberOfRHSDigits = countDigits(rhsCoefficient);
474
        if (numberOfRHSDigits) {
475
            const int rhsShiftAmount = rhsExponent - lhsExponent;
476
            const int overflow = numberOfRHSDigits + rhsShiftAmount - Precision;
477
            if (overflow <= 0)
478
                rhsCoefficient = scaleUp(rhsCoefficient, rhsShiftAmount);
479
            else {
480
                rhsCoefficient = scaleUp(rhsCoefficient, rhsShiftAmount - overflow);
481
                lhsCoefficient = scaleDown(lhsCoefficient, overflow);
482
                resultExponent += overflow;
483
            }
484
        }
485
    }
486
487
    uint64_t result = lhsSign == rhsSign ? lhsCoefficient - rhsCoefficient : lhsCoefficient + rhsCoefficient;
488
    return lhsSign == Negative && rhsSign == Negative && !result
489
            ? Decimal(Positive, resultExponent, 0)
490
            : int64_t(result) >= 0
491
                ? Decimal(lhsSign, resultExponent, result)
492
                : Decimal(invertSign(lhsSign), resultExponent, -int64_t(result));
493
}
494
495
Decimal Decimal::operator*(const Decimal& rhs) const
496
{
497
    const Decimal& lhs = *this;
498
    const Sign lhsSign = lhs.sign();
499
    const Sign rhsSign = rhs.sign();
500
    Sign resultSign = lhsSign == rhsSign ? Positive : Negative;
501
502
    SpecialValueHandler handler(lhs, rhs);
503
    switch (handler.handle()) {
504
    case SpecialValueHandler::BothFinite: {
505
        const uint64_t lhsCoefficient = lhs.m_data.coefficient();
506
        const uint64_t rhsCoefficient = rhs.m_data.coefficient();
507
        int resultExponent = lhs.exponent() + rhs.exponent();
508
        UInt128 work(UInt128::multiply(lhsCoefficient, rhsCoefficient));
509
        while (work.high()) {
510
          work /= 10;
511
          ++resultExponent;
512
        }
513
        return Decimal(resultSign, resultExponent, work.low());
514
    }
515
516
    case SpecialValueHandler::Bothinfinity:
517
        return infinity(resultSign);
518
519
    case SpecialValueHandler::EitherNaN:
520
        return handler.value();
521
522
    case SpecialValueHandler::LHSIsinfinity:
523
        return rhs.isZero() ? nan() : infinity(resultSign);
524
525
    case SpecialValueHandler::RHSIsinfinity:
526
        return lhs.isZero() ? nan() : infinity(resultSign);
527
    }
528
529
    ASSERT_NOT_REACHED();
530
    return nan();
531
}
532
533
Decimal Decimal::operator/(const Decimal& rhs) const
534
{
535
    const Decimal& lhs = *this;
536
    const Sign lhsSign = lhs.sign();
537
    const Sign rhsSign = rhs.sign();
538
    Sign resultSign = lhsSign == rhsSign ? Positive : Negative;
539
540
    SpecialValueHandler handler(lhs, rhs);
541
    switch (handler.handle()) {
542
    case SpecialValueHandler::BothFinite:
543
        break;
544
545
    case SpecialValueHandler::Bothinfinity:
546
        return nan();
547
548
    case SpecialValueHandler::EitherNaN:
549
        return handler.value();
550
551
    case SpecialValueHandler::LHSIsinfinity:
552
        return infinity(resultSign);
553
554
    case SpecialValueHandler::RHSIsinfinity:
555
        return zero(resultSign);
556
    }
557
558
    ASSERT(lhs.isFinite());
559
    ASSERT(rhs.isFinite());
560
561
    if (rhs.isZero())
562
        return lhs.isZero() ? nan() : infinity(resultSign);
563
564
    int resultExponent = lhs.exponent() - rhs.exponent();
565
566
    if (lhs.isZero()) {
567
        // 0/non-zero => 0
568
        return Decimal(resultSign, resultExponent, 0);
569
    }
570
571
    uint64_t remainder = lhs.m_data.coefficient();
572
    const uint64_t divisor = rhs.m_data.coefficient();
573
    uint64_t result = 0;
574
    while (result < MaxCoefficient / 100) {
575
        while (remainder < divisor) {
576
            remainder *= 10;
577
            result *= 10;
578
            --resultExponent;
579
        }
580
        result += remainder / divisor;
581
        remainder %= divisor;
582
        if (!remainder)
583
            break;
584
    }
585
586
    if (remainder > divisor / 2)
587
        ++result;
588
589
    return Decimal(resultSign, resultExponent, result);
590
}
591
592
bool Decimal::operator==(const Decimal& rhs) const
593
{
594
    return m_data == rhs.m_data || compareTo(rhs).isZero();
595
}
596
597
bool Decimal::operator!=(const Decimal& rhs) const
598
{
599
    return !operator==(rhs);
600
}
601
602
bool Decimal::operator<(const Decimal& rhs) const
603
{
604
    return !operator>=(rhs);
605
}
606
607
bool Decimal::operator<=(const Decimal& rhs) const
608
{
609
    if (m_data == rhs.m_data)
610
        return true;
611
    const Decimal result = compareTo(rhs);
612
    return result.isZero() || result.isNegative();
613
}
614
615
bool Decimal::operator>(const Decimal& rhs) const
616
{
617
    return !operator<=(rhs);
618
}
619
620
bool Decimal::operator>=(const Decimal& rhs) const
621
{
622
    if (m_data == rhs.m_data)
623
        return true;
624
    const Decimal result = compareTo(rhs);
625
    return result.isZero() || !result.isNegative();
626
}
627
628
int Decimal::exponent() const
629
{
630
    return isFinite() ? m_data.exponent() : 0;
631
}
632
633
Decimal::Sign Decimal::sign() const
634
{
635
    return m_data.sign();
636
}
637
638
Decimal Decimal::abs() const
639
{
640
    Decimal result(*this);
641
    result.m_data.setSign(Positive);
642
    return result;
643
}
644
645
// Round toward positive infinity.
646
// Note: Mac ports defines ceil(x) as wtf_ceil(x), so we can't use name "ceil" here.
647
Decimal Decimal::ceiling() const
648
{
649
    if (isSpecial())
650
        return *this;
651
652
    if (exponent() >= 0)
653
        return *this;
654
655
    uint64_t result = m_data.coefficient();
656
    const int numberOfDigits = countDigits(result);
657
    const int numberOfDropDigits = -exponent();
658
    if (numberOfDigits < numberOfDropDigits)
659
        return zero(Positive);
660
661
    result = scaleDown(result, numberOfDropDigits - 1);
662
    if (sign() == Positive && result % 10 > 0)
663
        result += 10;
664
    result /= 10;
665
    return Decimal(sign(), 0, result);
666
}
667
668
Decimal Decimal::compareTo(const Decimal& rhs) const
669
{
670
    const Decimal result(*this - rhs);
671
    return result.isZero()
672
            ? zero(Positive)
673
            : result.isFinite()
674
                    ? result
675
                    : result.isNegative() ? Decimal(-1) : Decimal(1);
676
}
677
678
// Round toward negative infinity.
679
Decimal Decimal::floor() const
680
{
681
    if (isSpecial())
682
        return *this;
683
684
    if (exponent() >= 0)
685
        return *this;
686
687
    uint64_t result = m_data.coefficient();
688
    const int numberOfDigits = countDigits(result);
689
    const int numberOfDropDigits = -exponent();
690
    if (numberOfDigits < numberOfDropDigits)
691
        return zero(Positive);
692
693
    result = scaleDown(result, numberOfDropDigits - 1);
694
    if (isNegative() && result % 10 > 0)
695
        result += 10;
696
    result /= 10;
697
    return Decimal(sign(), 0, result);
698
}
699
700
Decimal Decimal::fromString(const String& str)
701
{
702
    int exponent = 0;
703
    Sign exponentSign = Positive;
704
    int numberOfDigits = 0;
705
    int numberOfDigitsAfterDot = 0;
706
    int numberOfExtraDigits = 0;
707
    Sign sign = Positive;
708
709
    enum {
710
        StateDigit,
711
        StateDot,
712
        StateDotDigit,
713
        StateE,
714
        StateEDigit,
715
        StateESign,
716
        StateSign,
717
        StateStart,
718
        StateZero,
719
    } state = StateStart;
720
721
    #define HandleCharAndBreak(ch1, next, ...) \
722
        if (ch == ch1 || ch == ch1 - 'A' + 'a') { \
723
            __VA_ARGS__; \
724
            state = next; \
725
            break; \
726
        }
727
728
    uint64_t accumulator = 0;
729
    for (unsigned index = 0; index < str.length(); ++index) {
730
        const int ch = str[index];
731
        switch (state) {
732
        case StateDigit:
733
            if (ch >= '0' && ch <= '9') {
734
                if (numberOfDigits < Precision) {
735
                    ++numberOfDigits;
736
                    accumulator *= 10;
737
                    accumulator += ch - '0';
738
                } else
739
                    ++numberOfExtraDigits;
740
                break;
741
            }
742
743
            if (ch == '.') {
744
                state = StateDot;
745
                break;
746
            }
747
748
            HandleCharAndBreak('E', StateE);
749
            return nan();
750
751
        case StateDot:
752
            if (ch >= '0' && ch <= '9') {
753
                if (numberOfDigits < Precision) {
754
                    ++numberOfDigits;
755
                    ++numberOfDigitsAfterDot;
756
                    accumulator *= 10;
757
                    accumulator += ch - '0';
758
                }
759
                state = StateDotDigit;
760
                break;
761
            }
762
763
        case StateDotDigit:
764
            if (ch >= '0' && ch <= '9') {
765
                if (numberOfDigits < Precision) {
766
                    ++numberOfDigits;
767
                    ++numberOfDigitsAfterDot;
768
                    accumulator *= 10;
769
                    accumulator += ch - '0';
770
                }
771
                break;
772
            }
773
774
            HandleCharAndBreak('E', StateE);
775
            return nan();
776
777
        case StateE:
778
            if (ch == '+') {
779
                exponentSign = Positive;
780
                state = StateESign;
781
                break;
782
            }
783
784
            if (ch == '-') {
785
                exponentSign = Negative;
786
                state = StateESign;
787
                break;
788
            }
789
790
            if (ch >= '0' && ch <= '9') {
791
                exponent = ch - '0';
792
                state = StateEDigit;
793
                break;
794
            }
795
796
            return nan();
797
798
        case StateEDigit:
799
            if (ch >= '0' && ch <= '9') {
800
                exponent *= 10;
801
                exponent += ch - '0';
802
                if (exponent > ExponentMax + Precision)
803
                    return exponentSign == Negative ? zero(Positive) : infinity(sign);
804
                state = StateEDigit;
805
                break;
806
            }
807
808
            return nan();
809
810
        case StateESign:
811
            if (ch >= '0' && ch <= '9') {
812
                exponent = ch - '0';
813
                state = StateEDigit;
814
                break;
815
            }
816
817
            return nan();
818
819
        case StateSign:
820
            if (ch == '0') {
821
                state = StateZero;
822
                break;
823
            }
824
825
            if (ch >= '1' && ch <= '9') {
826
                accumulator = ch - '0';
827
                numberOfDigits = 1;
828
                state = StateDigit;
829
                break;
830
            }
831
832
            return nan();
833
834
        case StateStart:
835
            if (ch == '0') {
836
                state = StateZero;
837
                break;
838
            }
839
840
            if (ch >= '1' && ch <= '9') {
841
                accumulator = ch - '0';
842
                numberOfDigits = 1;
843
                state = StateDigit;
844
                break;
845
            }
846
847
            if (ch == '-') {
848
                sign = Negative;
849
                state = StateSign;
850
                break;
851
            }
852
853
            if (ch == '+') {
854
                sign = Positive;
855
                state = StateSign;
856
                break;
857
            }
858
859
            if (ch == '.') {
860
                state = StateDot;
861
                break;
862
            }
863
864
            return nan();
865
866
        case StateZero:
867
            if (ch == '0')
868
                break;
869
870
            if (ch >= '1' && ch <= '9') {
871
                accumulator = ch - '0';
872
                numberOfDigits = 1;
873
                state = StateDigit;
874
                break;
875
            }
876
877
            if (ch == '.') {
878
                state = StateDot;
879
                break;
880
            }
881
882
            HandleCharAndBreak('E', StateE);
883
            return nan();
884
885
        default:
886
            ASSERT_NOT_REACHED();
887
            return nan();
888
        }
889
    }
890
891
    if (state == StateZero)
892
        return zero(sign);
893
894
    if (state == StateDigit || state == StateEDigit || state == StateDotDigit) {
895
        int resultExponent = exponent * (exponentSign == Negative ? -1 : 1) - numberOfDigitsAfterDot + numberOfExtraDigits;
896
        if (resultExponent < ExponentMin)
897
            return zero(Positive);
898
899
        const int overflow = resultExponent - ExponentMax + 1;
900
        if (overflow > 0) {
901
            if (overflow + numberOfDigits - numberOfDigitsAfterDot > Precision)
902
                return infinity(sign);
903
            accumulator = scaleUp(accumulator, overflow);
904
            resultExponent -= overflow;
905
        }
906
907
        return Decimal(sign, resultExponent, accumulator);
908
    }
909
910
    return nan();
911
}
912
913
Decimal Decimal::infinity(const Sign sign)
914
{
915
    return Decimal(EncodedData(sign, ClassInfinity));
916
}
917
918
Decimal Decimal::nan()
919
{
920
    return Decimal(EncodedData(Positive, ClassNaN));
921
}
922
923
Decimal Decimal::remainder(const Decimal& rhs) const
924
{
925
    const Decimal quotient = (*this / rhs).round();
926
    return quotient.isSpecial() ? quotient : *this - quotient * rhs;
927
}
928
929
Decimal Decimal::round() const
930
{
931
    if (isSpecial())
932
        return *this;
933
934
    if (exponent() >= 0)
935
        return *this;
936
937
    uint64_t result = m_data.coefficient();
938
    const int numberOfDigits = countDigits(result);
939
    const int numberOfDropDigits = -exponent();
940
    if (numberOfDigits < numberOfDropDigits)
941
        return zero(Positive);
942
943
    result = scaleDown(result, numberOfDropDigits - 1);
944
    if (result % 10 >= 5)
945
        result += 10;
946
    result /= 10;
947
    return Decimal(sign(), 0, result);
948
}
949
950
String Decimal::toString() const
951
{
952
    switch (m_data.formatClass()) {
953
    case ClassInfinity:
954
        return sign() ? "-Infinity" : "Infinity";
955
956
    case ClassNaN:
957
        return sign() ? "-NaN" : "NaN";
958
959
    case ClassNormal:
960
    case ClassZero:
961
        break;
962
963
    default:
964
        ASSERT_NOT_REACHED();
965
        return "";
966
    }
967
968
    StringBuilder builder;
969
    if (sign())
970
        builder.append('-');
971
972
    int originalExponent = exponent();
973
974
    const int maxDigits = DBL_DIG;
975
    uint64_t coefficient = m_data.coefficient();
976
    int lastDigit = 0;
977
    while (countDigits(coefficient) > maxDigits) {
978
        lastDigit = coefficient % 10;
979
        coefficient /= 10;
980
        ++originalExponent;
981
    }
982
983
    if (lastDigit >= 5)
984
        ++coefficient;
985
986
    while (originalExponent < 0 && coefficient && !(coefficient % 10)) {
987
        coefficient /= 10;
988
        ++originalExponent;
989
    }
990
991
    const String digits = String::number(coefficient);
992
    int coefficientLength = int(digits.length());
993
    const int adjustedExponent = originalExponent + coefficientLength - 1;
994
    if (originalExponent <= 0 && adjustedExponent >= -6) {
995
        if (!originalExponent) {
996
            builder.append(digits);
997
            return builder.toString();
998
        }
999
1000
        if (adjustedExponent >= 0) {
1001
            for (int i = 0; i < coefficientLength; ++i) {
1002
                builder.append(digits[i]);
1003
                if (i == adjustedExponent)
1004
                    builder.append('.');
1005
            }
1006
            return builder.toString();
1007
        }
1008
1009
        builder.append("0.");
1010
        for (int i = adjustedExponent + 1; i < 0; ++i)
1011
            builder.append('0');
1012
1013
        builder.append(digits);
1014
1015
    } else {
1016
        builder.append(digits[0]);
1017
        while (coefficientLength >= 2 && digits[coefficientLength - 1] == '0')
1018
            --coefficientLength;
1019
        if (coefficientLength >= 2) {
1020
            builder.append('.');
1021
            for (int i = 1; i < coefficientLength; ++i)
1022
                builder.append(digits[i]);
1023
        }
1024
1025
        if (adjustedExponent) {
1026
            builder.append(adjustedExponent < 0 ? "e" : "e+");
1027
            builder.append(String::number(adjustedExponent));
1028
        }
1029
    }
1030
    return builder.toString();
1031
}
1032
1033
Decimal Decimal::zero(Sign sign)
1034
{
1035
    return Decimal(EncodedData(sign, ClassZero));
1036
}
1037
1038
} // namespace WebCore
- a/Source/WebCore/platform/Decimal.h +147 lines
Line 0 a/Source/WebCore/platform/Decimal.h_sec1
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
#ifndef Decimal_h
31
#define Decimal_h
32
33
#include <stdint.h>
34
#include <wtf/text/WTFString.h>
35
36
namespace WebCore {
37
38
// This class represents decimal base floating point number.
39
//
40
// FIXME: Once all C++ compiler support decimal type, we should replace this
41
// class to compiler supported one. See below URI for current status of decimal
42
// type for C++: // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1977.html
43
class Decimal {
44
public:
45
    enum Sign {
46
        Positive,
47
        Negative,
48
    };
49
50
    // You should not use FormatClass. This is for implementation.
51
    enum FormatClass {
52
        ClassInfinity,
53
        ClassNormal,
54
        ClassNaN,
55
        ClassZero,
56
    };
57
58
    // You should not use EncodedData other than unit testing.
59
    class EncodedData {
60
    public:
61
        EncodedData(Sign, FormatClass);
62
        EncodedData(Sign, int exponent, uint64_t coefficient);
63
64
        bool operator==(const EncodedData&) const;
65
        bool operator!=(const EncodedData& another) const { return !operator==(another); }
66
67
        uint64_t coefficient() const { return m_coefficient; }
68
        int countDigits() const;
69
        int exponent() const { return m_exponent; }
70
        FormatClass formatClass() const { return m_formatClass; }
71
        bool isFinite() const { return !isSpecial(); }
72
        bool isSpecial() const { return m_formatClass == ClassInfinity || m_formatClass == ClassNaN; }
73
        bool isZero() const { return m_formatClass == ClassZero; }
74
        Sign sign() const { return m_sign; }
75
        void setSign(Sign sign) { m_sign = sign; }
76
77
    private:
78
        uint64_t m_coefficient;
79
        int16_t m_exponent;
80
        FormatClass m_formatClass;
81
        Sign m_sign;
82
    };
83
84
    Decimal(int32_t = 0);
85
    Decimal(Sign, int exponent, uint64_t coefficient);
86
    Decimal(const Decimal&);
87
88
    Decimal& operator=(const Decimal&);
89
    Decimal& operator+=(const Decimal&);
90
    Decimal& operator-=(const Decimal&);
91
    Decimal& operator*=(const Decimal&);
92
    Decimal& operator/=(const Decimal&);
93
94
    Decimal operator-() const;
95
96
    bool operator==(const Decimal&) const;
97
    bool operator!=(const Decimal&) const;
98
    bool operator<(const Decimal&) const;
99
    bool operator<=(const Decimal&) const;
100
    bool operator>(const Decimal&) const;
101
    bool operator>=(const Decimal&) const;
102
103
    Decimal operator+(const Decimal&) const;
104
    Decimal operator-(const Decimal&) const;
105
    Decimal operator*(const Decimal&) const;
106
    Decimal operator/(const Decimal&) const;
107
108
    int exponent() const;
109
    bool isFinite() const { return m_data.isFinite(); }
110
    bool isNegative() const { return sign() == Negative; }
111
    bool isPositive() const { return sign() == Positive; }
112
    bool isSpecial() const { return m_data.isSpecial(); }
113
    bool isZero() const { return m_data.isZero(); }
114
115
    Decimal abs() const;
116
    Decimal ceiling() const;
117
    Decimal floor() const;
118
    Decimal remainder(const Decimal&) const;
119
    Decimal round() const;
120
    String toString() const;
121
122
    static Decimal fromString(const String&);
123
    static Decimal infinity(Sign);
124
    static Decimal nan();
125
    static Decimal zero(Sign);
126
127
    // You should not use below methods. We expose them for unit testing.
128
    explicit Decimal(const EncodedData&);
129
    const EncodedData& value() const { return m_data; }
130
131
private:
132
    Decimal(double);
133
    Decimal compareTo(const Decimal&) const;
134
135
    static inline Sign invertSign(Sign sign)
136
    {
137
        return sign == Negative ? Positive : Negative;
138
    }
139
140
    Sign sign() const;
141
142
    EncodedData m_data;
143
};
144
145
} // namespace WebCore
146
147
#endif // Decimal_h
- a/Source/WebKit/chromium/WebKit.gypi +1 lines
Lines 95-100 a/Source/WebKit/chromium/WebKit.gypi_sec1
95
            'tests/ClipboardChromiumTest.cpp',
95
            'tests/ClipboardChromiumTest.cpp',
96
            'tests/CompositorFakeGraphicsContext3D.h',
96
            'tests/CompositorFakeGraphicsContext3D.h',
97
            'tests/CompositorFakeWebGraphicsContext3D.h',
97
            'tests/CompositorFakeWebGraphicsContext3D.h',
98
            'tests/DecimalTest.cpp',
98
            'tests/DragImageTest.cpp',
99
            'tests/DragImageTest.cpp',
99
            'tests/DrawingBufferChromiumTest.cpp',
100
            'tests/DrawingBufferChromiumTest.cpp',
100
            'tests/EventListenerTest.cpp',
101
            'tests/EventListenerTest.cpp',
- a/Source/WebKit/chromium/tests/DecimalTest.cpp +615 lines
Line 0 a/Source/WebKit/chromium/tests/DecimalTest.cpp_sec1
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 "config.h"
32
#include "Decimal.h"
33
34
#include <gtest/gtest.h>
35
#include <wtf/MathExtras.h>
36
#include <wtf/text/CString.h>
37
38
namespace WebCore {
39
40
std::ostream& operator<<(std::ostream& os, const Decimal& decimal)
41
{
42
    Decimal::EncodedData data = decimal.value();
43
    return os 
44
        << "encode(" << String::number(data.coefficient()).ascii().data()
45
        << ", " << String::number(data.exponent()).ascii().data()
46
        << ", " << (data.sign() == Decimal::Negative ? "Negative" : "Positive")
47
        << ")=" << decimal.toString().ascii().data();
48
}
49
50
} // namespace WebCore
51
52
using namespace WebCore;
53
54
// Simulate WebCore/html/StepRange
55
class DecimalStepRange {
56
public:
57
    Decimal maximum;
58
    Decimal minimum;
59
    Decimal step;
60
61
    DecimalStepRange(const Decimal& minimum, const Decimal& maximum, const Decimal& step)
62
        : maximum(maximum)
63
        , minimum(minimum)
64
        , step(step)
65
    {
66
    }
67
68
    Decimal clampValue(Decimal value) const
69
    {
70
        const Decimal result = minimum + ((value - minimum) / step).round() * step;
71
        ASSERT(result.isFinite());
72
        return result > maximum ? result - step : result;
73
    }
74
};
75
76
class DecimalTest : public ::testing::Test {
77
protected:
78
    typedef Decimal::Sign Sign;
79
    protected: static const Sign Positive = Decimal::Positive;
80
    protected: static const Sign Negative = Decimal::Negative;
81
82
    Decimal encode(uint64_t coefficient, int exponent, Sign sign)
83
    {
84
        return Decimal(sign, exponent, coefficient);
85
    }
86
87
    protected: Decimal fromString(const String& string)
88
    {
89
        return Decimal::fromString(string);
90
    }
91
92
    protected: String stepDown(const String& minimum, const String& maximum, const String& step, const String& valueString, int numberOfStepTimes)
93
    {
94
        DecimalStepRange stepRange(fromString(minimum), fromString(maximum), fromString(step));
95
        Decimal value = fromString(valueString);
96
        for (int i = 0; i < numberOfStepTimes; ++i) {
97
          value -= stepRange.step;
98
          value = stepRange.clampValue(value);
99
        }
100
        return value.toString();
101
    }
102
103
    protected: String stepUp(const String& minimum, const String& maximum, const String& step, const String& valueString, int numberOfStepTimes)
104
    {
105
        DecimalStepRange stepRange(fromString(minimum), fromString(maximum), fromString(step));
106
        Decimal value = fromString(valueString);
107
        for (int i = 0; i < numberOfStepTimes; ++i) {
108
          value += stepRange.step;
109
          value = stepRange.clampValue(value);
110
        }
111
        return value.toString();
112
    }
113
};
114
115
TEST_F(DecimalTest, Abs)
116
{
117
    EXPECT_EQ(encode(0, 0, Positive), encode(0, 0, Positive).abs());
118
    EXPECT_EQ(encode(0, 0, Positive), encode(0, 0, Negative).abs());
119
120
    EXPECT_EQ(encode(0, 10, Positive), encode(0, 10, Positive).abs());
121
    EXPECT_EQ(encode(0, 10, Positive), encode(0, 10, Negative).abs());
122
123
    EXPECT_EQ(encode(0, -10, Positive), encode(0, -10, Positive).abs());
124
    EXPECT_EQ(encode(0, -10, Positive), encode(0, -10, Negative).abs());
125
126
    EXPECT_EQ(encode(1, 0, Positive), encode(1, 0, Positive).abs());
127
    EXPECT_EQ(encode(1, 0, Positive), encode(1, 0, Negative).abs());
128
129
    EXPECT_EQ(encode(1, 10, Positive), encode(1, 10, Positive).abs());
130
    EXPECT_EQ(encode(1, 10, Positive), encode(1, 10, Negative).abs());
131
132
    EXPECT_EQ(encode(1, -10, Positive), encode(1, -10, Positive).abs());
133
    EXPECT_EQ(encode(1, -10, Positive), encode(1, -10, Negative).abs());
134
}
135
136
TEST_F(DecimalTest, Ceiling)
137
{
138
    EXPECT_EQ(Decimal(1), Decimal(1).ceiling());
139
    EXPECT_EQ(Decimal(2), encode(11, -1, Positive).ceiling());
140
    EXPECT_EQ(Decimal(2), encode(13, -1, Positive).ceiling());
141
    EXPECT_EQ(Decimal(2), encode(15, -1, Positive).ceiling());
142
    EXPECT_EQ(Decimal(2), encode(19, -1, Positive).ceiling());
143
144
    EXPECT_EQ(Decimal(-1), Decimal(-1).ceiling());
145
    EXPECT_EQ(Decimal(-1), encode(11, -1, Negative).ceiling());
146
    EXPECT_EQ(Decimal(-1), encode(13, -1, Negative).ceiling());
147
    EXPECT_EQ(Decimal(-1), encode(15, -1, Negative).ceiling());
148
    EXPECT_EQ(Decimal(-1), encode(19, -1, Negative).ceiling());
149
}
150
151
TEST_F(DecimalTest, EncodedData)
152
{
153
    EXPECT_EQ(encode(0, 0, Positive), encode(0, 0, Positive));
154
    EXPECT_EQ(encode(0, 0, Negative), encode(0, 0, Negative));
155
    EXPECT_EQ(Decimal(1), Decimal(1));
156
    EXPECT_EQ(encode(1, 0, Negative), encode(1, 0, Negative));
157
    EXPECT_EQ(Decimal::infinity(Positive), encode(1, 2000, Positive));
158
    EXPECT_EQ(Decimal::zero(Positive), encode(1, -2000, Positive));
159
}
160
161
TEST_F(DecimalTest, Floor)
162
{
163
    EXPECT_EQ(Decimal(1), Decimal(1).floor());
164
    EXPECT_EQ(Decimal(1), encode(11, -1, Positive).floor());
165
    EXPECT_EQ(Decimal(1), encode(13, -1, Positive).floor());
166
    EXPECT_EQ(Decimal(1), encode(15, -1, Positive).floor());
167
    EXPECT_EQ(Decimal(1), encode(19, -1, Positive).floor());
168
169
    EXPECT_EQ(Decimal(-1), Decimal(-1).floor());
170
    EXPECT_EQ(Decimal(-2), encode(11, -1, Negative).floor());
171
    EXPECT_EQ(Decimal(-2), encode(13, -1, Negative).floor());
172
    EXPECT_EQ(Decimal(-2), encode(15, -1, Negative).floor());
173
    EXPECT_EQ(Decimal(-2), encode(19, -1, Negative).floor());
174
}
175
176
TEST_F(DecimalTest, FromInt32)
177
{
178
    EXPECT_EQ(encode(0, 0, Positive), Decimal(0));
179
    EXPECT_EQ(Decimal(1), Decimal(1));
180
    EXPECT_EQ(encode(1, 0, Negative), Decimal(-1));
181
    EXPECT_EQ(encode(100, 0, Positive), Decimal(100));
182
    EXPECT_EQ(encode(100, 0, Negative), Decimal(-100));
183
    EXPECT_EQ(encode(0x7FFFFFFF, 0, Positive), Decimal(INT_MAX));
184
    EXPECT_EQ(encode(0x80000000u, 0, Negative), Decimal(INT_MIN));
185
}
186
187
TEST_F(DecimalTest, FromString)
188
{
189
    EXPECT_EQ(encode(0, 0, Positive), fromString("0"));
190
    EXPECT_EQ(encode(0, 0, Negative), fromString("-0"));
191
    EXPECT_EQ(Decimal(1), fromString("1"));
192
    EXPECT_EQ(encode(1, 0, Negative), fromString("-1"));
193
    EXPECT_EQ(Decimal(1), fromString("01"));
194
    EXPECT_EQ(encode(3, 0, Positive), fromString("+3"));
195
    EXPECT_EQ(encode(0, 3, Positive), fromString("0E3"));
196
    EXPECT_EQ(encode(5, -1, Positive), fromString(".5"));
197
    EXPECT_EQ(encode(100, 0, Positive), fromString("100"));
198
    EXPECT_EQ(encode(100, 0, Negative), fromString("-100"));
199
    EXPECT_EQ(encode(123, -2, Positive), fromString("1.23"));
200
    EXPECT_EQ(encode(123, -2, Negative), fromString("-1.23"));
201
    EXPECT_EQ(encode(123, 8, Positive), fromString("1.23E10"));
202
    EXPECT_EQ(encode(123, 8, Negative), fromString("-1.23E10"));
203
    EXPECT_EQ(encode(123, 8, Positive), fromString("1.23E+10"));
204
    EXPECT_EQ(encode(123, 8, Negative), fromString("-1.23E+10"));
205
    EXPECT_EQ(encode(123, -12, Positive), fromString("1.23E-10"));
206
    EXPECT_EQ(encode(123, -12, Negative), fromString("-1.23E-10"));
207
    EXPECT_EQ(encode(5, -7, Positive), fromString("0.0000005"));
208
    EXPECT_EQ(encode(123, -3, Positive), fromString("0.123"));
209
    EXPECT_EQ(encode(0, -2, Positive), fromString("00.00"));
210
    EXPECT_EQ(encode(1, 2, Positive), fromString("1E2"));
211
    EXPECT_EQ(Decimal::infinity(Positive), fromString("1E20000"));
212
    EXPECT_EQ(Decimal::zero(Positive), fromString("1E-20000"));
213
    EXPECT_EQ(encode(1000, 1023, Positive), fromString("1E1026"));
214
    EXPECT_EQ(Decimal::zero(Positive), fromString("1E-1026"));
215
    EXPECT_EQ(Decimal::infinity(Positive), fromString("1234567890E1036"));
216
217
    // 2^1024
218
    const uint64_t leadingDigitsOf2PowerOf1024 = UINT64_C(17976931348623159);
219
    EXPECT_EQ(encode(leadingDigitsOf2PowerOf1024, 292, Positive), fromString("179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216"));
220
}
221
222
// These strings are look like proper number, but we don't accept them.
223
TEST_F(DecimalTest, FromStringLikeNumber)
224
{
225
    EXPECT_EQ(Decimal::nan(), fromString(" 123 "));
226
    EXPECT_EQ(Decimal::nan(), fromString("1,234"));
227
    EXPECT_EQ(Decimal::nan(), fromString("INF"));
228
}
229
230
TEST_F(DecimalTest, fromStringTruncated)
231
{
232
    EXPECT_EQ(Decimal::nan(), fromString("x"));
233
    EXPECT_EQ(Decimal::nan(), fromString("0."));
234
    EXPECT_EQ(Decimal::nan(), fromString("1x"));
235
236
    EXPECT_EQ(Decimal::nan(), fromString("1Ex"));
237
    EXPECT_EQ(Decimal::nan(), fromString("1E2x"));
238
    EXPECT_EQ(Decimal::nan(), fromString("1E+x"));
239
}
240
241
TEST_F(DecimalTest, Predicates)
242
{
243
    EXPECT_TRUE(Decimal::zero(Positive).isFinite());
244
    EXPECT_TRUE(Decimal::zero(Positive).isPositive());
245
    EXPECT_FALSE(Decimal::zero(Positive).isNegative());
246
    EXPECT_FALSE(Decimal::zero(Positive).isSpecial());
247
    EXPECT_TRUE(Decimal::zero(Positive).isZero());
248
249
    EXPECT_TRUE(Decimal::zero(Negative).isFinite());
250
    EXPECT_FALSE(Decimal::zero(Negative).isPositive());
251
    EXPECT_TRUE(Decimal::zero(Negative).isNegative());
252
    EXPECT_FALSE(Decimal::zero(Negative).isSpecial());
253
    EXPECT_TRUE(Decimal::zero(Negative).isZero());
254
255
    EXPECT_TRUE(Decimal(123).isFinite());
256
    EXPECT_TRUE(Decimal(123).isPositive());
257
    EXPECT_FALSE(Decimal(123).isNegative());
258
    EXPECT_FALSE(Decimal(123).isSpecial());
259
    EXPECT_FALSE(Decimal(123).isZero());
260
261
    EXPECT_TRUE(Decimal(-123).isFinite());
262
    EXPECT_FALSE(Decimal(-123).isPositive());
263
    EXPECT_TRUE(Decimal(-123).isNegative());
264
    EXPECT_FALSE(Decimal(-123).isSpecial());
265
    EXPECT_FALSE(Decimal(-123).isZero());
266
}
267
268
TEST_F(DecimalTest, PredicatesSpecialValues)
269
{
270
    EXPECT_FALSE(Decimal::infinity(Positive).isFinite());
271
    EXPECT_TRUE(Decimal::infinity(Positive).isPositive());
272
    EXPECT_FALSE(Decimal::infinity(Positive).isNegative());
273
    EXPECT_TRUE(Decimal::infinity(Positive).isSpecial());
274
    EXPECT_FALSE(Decimal::infinity(Positive).isZero());
275
276
    EXPECT_FALSE(Decimal::infinity(Negative).isFinite());
277
    EXPECT_FALSE(Decimal::infinity(Negative).isPositive());
278
    EXPECT_TRUE(Decimal::infinity(Negative).isNegative());
279
    EXPECT_TRUE(Decimal::infinity(Negative).isSpecial());
280
    EXPECT_FALSE(Decimal::infinity(Negative).isZero());
281
282
    EXPECT_FALSE(Decimal::nan().isFinite());
283
    EXPECT_TRUE(Decimal::nan().isSpecial());
284
    EXPECT_FALSE(Decimal::nan().isZero());
285
}
286
287
TEST_F(DecimalTest, OpAdd)
288
{
289
    EXPECT_EQ(encode(0, 0, Positive), Decimal(0) + Decimal(0));
290
    EXPECT_EQ(Decimal(1), Decimal(2) + Decimal(-1));
291
    EXPECT_EQ(Decimal(1), Decimal(-1) + Decimal(2));
292
    EXPECT_EQ(encode(100, 0, Positive), Decimal(99) + Decimal(1));
293
    EXPECT_EQ(encode(100, 0, Negative), Decimal(-50) + Decimal(-50));
294
    EXPECT_EQ(encode(1000000000000000, 35, Positive), encode(1, 50, Positive) + Decimal(1));
295
    EXPECT_EQ(encode(1000000000000000, 35, Positive), Decimal(1) + encode(1, 50, Positive));
296
    EXPECT_EQ(encode(10000000001, 0, Positive), encode(1, 10, Positive) + Decimal(1));
297
    EXPECT_EQ(encode(10000000001, 0, Positive), Decimal(1) + encode(1, 10, Positive));
298
    EXPECT_EQ(encode(1, 0, Positive), encode(1, -1022, Positive) + encode(1, 0, Positive));
299
    EXPECT_EQ(encode(2, -1022, Positive), encode(1, -1022, Positive) + encode(1, -1022, Positive));
300
}
301
302
TEST_F(DecimalTest, OpAddBigE)
303
{
304
    EXPECT_EQ(encode(1, 1022, Positive), encode(1, 1022, Positive) + encode(1, 0, Positive));
305
    EXPECT_EQ(encode(2, 1022, Positive), encode(1, 1022, Positive) + encode(1, 1022, Positive));
306
    EXPECT_EQ(Decimal::infinity(Positive), encode(uint64_t(-1), 1022, Positive) + encode(1, 0, Positive));
307
}
308
309
TEST_F(DecimalTest, OpAddSmallE)
310
{
311
    EXPECT_EQ(encode(1, 0, Positive), encode(1, -1022, Positive) + encode(1, 0, Positive));
312
    EXPECT_EQ(encode(2, -1022, Positive), encode(1, -1022, Positive) + encode(1, -1022, Positive));
313
}
314
315
TEST_F(DecimalTest, OpAddSpecialValues)
316
{
317
    const Decimal Infinity(Decimal::infinity(Positive));
318
    const Decimal MinusInfinity(Decimal::infinity(Negative));
319
    const Decimal NaN(Decimal::nan());
320
    const Decimal Ten(10);
321
322
    EXPECT_EQ(Infinity, Infinity + Infinity);
323
    EXPECT_EQ(NaN, Infinity + MinusInfinity);
324
    EXPECT_EQ(NaN, MinusInfinity + Infinity);
325
    EXPECT_EQ(MinusInfinity, MinusInfinity + MinusInfinity);
326
327
    EXPECT_EQ(Infinity, Infinity + Ten);
328
    EXPECT_EQ(Infinity, Ten + Infinity);
329
    EXPECT_EQ(MinusInfinity, MinusInfinity + Ten);
330
    EXPECT_EQ(MinusInfinity, Ten + MinusInfinity);
331
332
    EXPECT_EQ(NaN, NaN + NaN);
333
    EXPECT_EQ(NaN, NaN + Ten);
334
    EXPECT_EQ(NaN, Ten + NaN);
335
}
336
337
TEST_F(DecimalTest, OpCompare)
338
{
339
    EXPECT_TRUE(Decimal(0) == Decimal(0));
340
    EXPECT_TRUE(Decimal(0) != Decimal(1));
341
    EXPECT_TRUE(Decimal(0) < Decimal(1));
342
    EXPECT_TRUE(Decimal(0) <= Decimal(0));
343
    EXPECT_TRUE(Decimal(0) > Decimal(-1));
344
    EXPECT_TRUE(Decimal(0) >= Decimal(0));
345
346
    EXPECT_FALSE(Decimal(1) == Decimal(2));
347
    EXPECT_FALSE(Decimal(1) != Decimal(1));
348
    EXPECT_FALSE(Decimal(1) < Decimal(0));
349
    EXPECT_FALSE(Decimal(1) <= Decimal(0));
350
    EXPECT_FALSE(Decimal(1) > Decimal(2));
351
    EXPECT_FALSE(Decimal(1) >= Decimal(2));
352
}
353
354
TEST_F(DecimalTest, OpCompareSpecialValues)
355
{
356
    EXPECT_TRUE(Decimal(1) < Decimal::infinity(Positive));
357
    EXPECT_TRUE(Decimal(1) > Decimal::infinity(Negative));
358
}
359
360
TEST_F(DecimalTest, OpDiv)
361
{
362
    EXPECT_EQ(encode(0, 0, Positive), Decimal(0) / Decimal(1));
363
    EXPECT_EQ(encode(2, 0, Negative), Decimal(2) / Decimal(-1));
364
    EXPECT_EQ(encode(5, -1, Negative), Decimal(-1) / Decimal(2));
365
    EXPECT_EQ(encode(99, 0, Positive), Decimal(99) / Decimal(1));
366
    EXPECT_EQ(Decimal(1), Decimal(-50) / Decimal(-50));
367
    EXPECT_EQ(encode(3333333333333333, -16, Positive), Decimal(1) / Decimal(3));
368
    EXPECT_EQ(encode(12345678901234, -1, Positive), encode(12345678901234, 0, Positive) / Decimal(10));
369
}
370
371
TEST_F(DecimalTest, OpDivBigE)
372
{
373
    EXPECT_EQ(encode(1, 1022, Positive), encode(1, 1022, Positive) / encode(1, 0, Positive));
374
    EXPECT_EQ(encode(1, 0, Positive), encode(1, 1022, Positive) / encode(1, 1022, Positive));
375
}
376
377
TEST_F(DecimalTest, OpDivSmallE)
378
{
379
    EXPECT_EQ(encode(1, -1022, Positive), encode(1, -1022, Positive) / encode(1, 0, Positive));
380
    EXPECT_EQ(encode(1, 0, Positive), encode(1, -1022, Positive) / encode(1, -1022, Positive));
381
}
382
383
TEST_F(DecimalTest, OpDivSpecialValues)
384
{
385
    const Decimal Infinity(Decimal::infinity(Positive));
386
    const Decimal MinusInfinity(Decimal::infinity(Negative));
387
    const Decimal NaN(Decimal::nan());
388
    const Decimal Zero(Decimal::zero(Positive));
389
    const Decimal MinusZero(Decimal::zero(Negative));
390
    const Decimal Ten(10);
391
    const Decimal MinusTen(-10);
392
393
    EXPECT_EQ(NaN, Zero / Zero);
394
    EXPECT_EQ(NaN, Zero / MinusZero);
395
    EXPECT_EQ(NaN, MinusZero / Zero);
396
    EXPECT_EQ(NaN, MinusZero / MinusZero);
397
398
    EXPECT_EQ(Infinity, Ten / Zero);
399
    EXPECT_EQ(MinusInfinity, Ten / MinusZero);
400
    EXPECT_EQ(MinusInfinity, MinusTen / Zero);
401
    EXPECT_EQ(Infinity, MinusTen / MinusZero);
402
403
    EXPECT_EQ(Infinity, Infinity / Zero);
404
    EXPECT_EQ(MinusInfinity, Infinity / MinusZero);
405
    EXPECT_EQ(MinusInfinity, MinusInfinity / Zero);
406
    EXPECT_EQ(Infinity, MinusInfinity / MinusZero);
407
408
    EXPECT_EQ(NaN, Infinity / Infinity);
409
    EXPECT_EQ(NaN, Infinity / MinusInfinity);
410
    EXPECT_EQ(NaN, MinusInfinity / Infinity);
411
    EXPECT_EQ(NaN, MinusInfinity / MinusInfinity);
412
413
    EXPECT_EQ(Zero, Ten / Infinity);
414
    EXPECT_EQ(MinusZero, Ten / MinusInfinity);
415
    EXPECT_EQ(MinusZero, MinusTen / Infinity);
416
    EXPECT_EQ(Zero, MinusTen / MinusInfinity);
417
418
    EXPECT_EQ(NaN, NaN / NaN);
419
    EXPECT_EQ(NaN, NaN / Ten);
420
    EXPECT_EQ(NaN, Ten / NaN);
421
}
422
423
TEST_F(DecimalTest, OpMul)
424
{
425
    EXPECT_EQ(encode(0, 0, Positive), Decimal(0) * Decimal(0));
426
    EXPECT_EQ(encode(2, 0, Negative), Decimal(2) * Decimal(-1));
427
    EXPECT_EQ(encode(2, 0, Negative), Decimal(-1) * Decimal(2));
428
    EXPECT_EQ(encode(99, 0, Positive), Decimal(99) * Decimal(1));
429
    EXPECT_EQ(encode(2500, 0, Positive), Decimal(-50) * Decimal(-50));
430
}
431
432
TEST_F(DecimalTest, OpMulBigE)
433
{
434
    EXPECT_EQ(encode(1, 1022, Positive), encode(1, 1022, Positive) * encode(1, 0, Positive));
435
    EXPECT_EQ(Decimal::infinity(Positive), encode(1, 1022, Positive) * encode(1, 1022, Positive));
436
}
437
438
TEST_F(DecimalTest, OpMulSmallE)
439
{
440
    EXPECT_EQ(encode(1, -1022, Positive), encode(1, -1022, Positive) * encode(1, 0, Positive));
441
    EXPECT_EQ(encode(0, 0, Positive), encode(1, -1022, Positive) * encode(1, -1022, Positive));
442
}
443
444
TEST_F(DecimalTest, OpMulSpecialValues)
445
{
446
    const Decimal Infinity(Decimal::infinity(Positive));
447
    const Decimal MinusInfinity(Decimal::infinity(Negative));
448
    const Decimal NaN(Decimal::nan());
449
    const Decimal Ten(10);
450
    const Decimal MinusTen(-10);
451
    const Decimal Zero(Decimal::zero(Positive));
452
    const Decimal MinusZero(Decimal::zero(Negative));
453
454
    EXPECT_EQ(Infinity, Infinity * Infinity);
455
    EXPECT_EQ(MinusInfinity, Infinity * MinusInfinity);
456
    EXPECT_EQ(MinusInfinity, MinusInfinity * Infinity);
457
    EXPECT_EQ(Infinity, MinusInfinity * MinusInfinity);
458
459
    EXPECT_EQ(NaN, Infinity * Zero);
460
    EXPECT_EQ(NaN, Zero * MinusInfinity);
461
    EXPECT_EQ(NaN, MinusInfinity * Zero);
462
    EXPECT_EQ(NaN, MinusInfinity * Zero);
463
464
    EXPECT_EQ(NaN, Infinity * MinusZero);
465
    EXPECT_EQ(NaN, MinusZero * MinusInfinity);
466
    EXPECT_EQ(NaN, MinusInfinity * MinusZero);
467
    EXPECT_EQ(NaN, MinusInfinity * MinusZero);
468
469
    EXPECT_EQ(Infinity, Infinity * Ten);
470
    EXPECT_EQ(Infinity, Ten * Infinity);
471
    EXPECT_EQ(MinusInfinity, MinusInfinity * Ten);
472
    EXPECT_EQ(MinusInfinity, Ten * MinusInfinity);
473
474
    EXPECT_EQ(MinusInfinity, Infinity * MinusTen);
475
    EXPECT_EQ(MinusInfinity, MinusTen * Infinity);
476
    EXPECT_EQ(Infinity, MinusInfinity * MinusTen);
477
    EXPECT_EQ(Infinity, MinusTen * MinusInfinity);
478
479
    EXPECT_EQ(NaN, NaN * NaN);
480
    EXPECT_EQ(NaN, NaN * Ten);
481
    EXPECT_EQ(NaN, Ten * NaN);
482
}
483
484
TEST_F(DecimalTest, OpSub)
485
{
486
    EXPECT_EQ(encode(0, 0, Positive), Decimal(0) - Decimal(0));
487
    EXPECT_EQ(encode(3, 0, Positive), Decimal(2) - Decimal(-1));
488
    EXPECT_EQ(encode(3, 0, Negative), Decimal(-1) - Decimal(2));
489
    EXPECT_EQ(encode(98, 0, Positive), Decimal(99) - Decimal(1));
490
    EXPECT_EQ(encode(0, 0, Positive), Decimal(-50) - Decimal(-50));
491
    EXPECT_EQ(encode(1000000000000000, 35, Positive), encode(1, 50, Positive) - Decimal(1));
492
    EXPECT_EQ(encode(1000000000000000, 35, Negative), Decimal(1) - encode(1, 50, Positive));
493
}
494
495
TEST_F(DecimalTest, OpSubBigE)
496
{
497
    EXPECT_EQ(encode(1, 1022, Positive), encode(1, 1022, Positive) - encode(1, 0, Positive));
498
    EXPECT_EQ(encode(0, 0, Positive), encode(1, 1022, Positive) - encode(1, 1022, Positive));
499
}
500
501
TEST_F(DecimalTest, OpSubSmallE)
502
{
503
    EXPECT_EQ(encode(UINT64_C(10000000000000000), -16, Negative), encode(1, -1022, Positive) - encode(1, 0, Positive));
504
    EXPECT_EQ(encode(0, 0, Positive), encode(1, -1022, Positive) - encode(1, -1022, Positive));
505
}
506
507
TEST_F(DecimalTest, OpSubSpecialValues)
508
{
509
    const Decimal Infinity(Decimal::infinity(Positive));
510
    const Decimal MinusInfinity(Decimal::infinity(Negative));
511
    const Decimal NaN(Decimal::nan());
512
    const Decimal Ten(10);
513
514
    EXPECT_EQ(NaN, Infinity - Infinity);
515
    EXPECT_EQ(Infinity, Infinity - MinusInfinity);
516
    EXPECT_EQ(MinusInfinity, MinusInfinity - Infinity);
517
    EXPECT_EQ(NaN, MinusInfinity - MinusInfinity);
518
519
    EXPECT_EQ(Infinity, Infinity - Ten);
520
    EXPECT_EQ(MinusInfinity, Ten - Infinity);
521
    EXPECT_EQ(MinusInfinity, MinusInfinity - Ten);
522
    EXPECT_EQ(Infinity, Ten - MinusInfinity);
523
524
    EXPECT_EQ(NaN, NaN - NaN);
525
    EXPECT_EQ(NaN, NaN - Ten);
526
    EXPECT_EQ(NaN, Ten - NaN);
527
}
528
529
TEST_F(DecimalTest, Properties)
530
{
531
    EXPECT_TRUE(Decimal(0).isFinite());
532
    EXPECT_FALSE(Decimal(0).isSpecial());
533
}
534
535
TEST_F(DecimalTest, PropertiesSpecial)
536
{
537
    EXPECT_TRUE(Decimal::infinity(Positive).isSpecial());
538
    EXPECT_FALSE(Decimal::infinity(Positive).isFinite());
539
540
    EXPECT_TRUE(Decimal::infinity(Negative).isSpecial());
541
    EXPECT_FALSE(Decimal::infinity(Negative).isFinite());
542
543
    EXPECT_TRUE(Decimal::nan().isSpecial());
544
    EXPECT_FALSE(Decimal::nan().isFinite());
545
}
546
547
// LayoutTests/fast/forms/number/number-stepup-stepdown-from-renderer
548
TEST_F(DecimalTest, RealWorldExampleNumberStepUpStepDownFromRenderer)
549
{
550
    EXPECT_EQ(String("10"), stepDown("0", "100", "10", "19", 1));
551
    EXPECT_EQ(String("90"), stepUp("0", "99", "10", "89", 1));
552
    EXPECT_EQ(String("1"), stepUp("0", "1", "0.33333333333333333", "0", 3)); // step=1/3
553
    EXPECT_EQ(String("0.01"), stepUp("0", "0.01", "0.0033333333333333333", "0", 3)); // step=1/300
554
    EXPECT_EQ(String("1"), stepUp("0", "1", "0.003921568627450980", "0", 255)); // step=1/255
555
    EXPECT_EQ(String("1"), stepUp("0", "1", "0.1", "0", 10));
556
}
557
558
TEST_F(DecimalTest, RealWorldExampleNumberStepUpStepDownFromRendererRounding)
559
{
560
    EXPECT_EQ(String("5.015"), stepUp("0", "100", "0.005", "5.005", 2));
561
    EXPECT_EQ(String("5.06"), stepUp("0", "100", "0.005", "5.005", 11));
562
    EXPECT_EQ(String("5.065"), stepUp("0", "100", "0.005", "5.005", 12));
563
564
    EXPECT_EQ(String("5.015"), stepUp("4", "9", "0.005", "5.005", 2));
565
    EXPECT_EQ(String("5.06"), stepUp("4", "9", "0.005", "5.005", 11));
566
    EXPECT_EQ(String("5.065"), stepUp("4", "9", "0.005", "5.005", 12));
567
}
568
569
TEST_F(DecimalTest, RealWorldExampleRangeStepUpStepDown)
570
{
571
    EXPECT_EQ(String("1e+38"), stepUp("0", "1E38", "1", "1E38", 9));
572
    EXPECT_EQ(String("1e+38"), stepDown("0", "1E38", "1", "1E38", 9));
573
}
574
575
TEST_F(DecimalTest, Remainder)
576
{
577
    EXPECT_EQ(encode(9, -1, Negative), encode(21, -1, Positive).remainder(3));
578
    EXPECT_EQ(Decimal(1), Decimal(10).remainder(3));
579
    EXPECT_EQ(encode(1, 0, Negative), Decimal(-10).remainder(3));
580
    EXPECT_EQ(encode(2, -1, Positive), encode(102, -1, Positive).remainder(1));
581
    EXPECT_EQ(encode(1, -1, Positive), Decimal(10).remainder(encode(3, -1, Positive)));
582
    EXPECT_EQ(encode(3, -1, Negative), encode(36, -1, Positive).remainder(encode(13, -1, Positive)));
583
}
584
585
TEST_F(DecimalTest, RemainderSpecialValues)
586
{
587
    EXPECT_EQ(Decimal::infinity(Positive), Decimal::infinity(Positive).remainder(1));
588
    EXPECT_EQ(Decimal::nan(), Decimal::nan().remainder(1));
589
}
590
591
TEST_F(DecimalTest, Round)
592
{
593
    EXPECT_EQ(Decimal(1), (Decimal(9) / Decimal(10)).round());
594
    EXPECT_EQ(Decimal(25), (Decimal(5) / fromString("0.200")).round());
595
    EXPECT_EQ(Decimal(3), (Decimal(5) / Decimal(2)).round());
596
    EXPECT_EQ(Decimal(1), (Decimal(2) / Decimal(3)).round());
597
    EXPECT_EQ(Decimal(3), (Decimal(10) / Decimal(3)).round());
598
    EXPECT_EQ(Decimal(3), (Decimal(1) / fromString("0.3")).round());
599
    EXPECT_EQ(Decimal(10), (Decimal(1) / fromString("0.1")).round());
600
    EXPECT_EQ(Decimal(5), (Decimal(1) / fromString("0.2")).round());
601
    EXPECT_EQ(Decimal(10), (fromString("10.2") / 1).round());
602
}
603
604
TEST_F(DecimalTest, RoundSepcialValues)
605
{
606
    EXPECT_EQ(Decimal::infinity(Positive), Decimal::infinity(Positive).round());
607
    EXPECT_EQ(Decimal::nan(), Decimal::nan().round());
608
}
609
610
TEST_F(DecimalTest, ToStringSpecial)
611
{
612
    EXPECT_EQ(String("Infinity"), Decimal::infinity(Positive).toString());
613
    EXPECT_EQ(String("-Infinity"), Decimal::infinity(Negative).toString());
614
    EXPECT_EQ(String("NaN"), Decimal::nan().toString());
615
}

Return to Bug 87360