15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2012 Google Inc. All rights reserved.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met:
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions of source code must retain the above copyright
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Redistributions in binary form must reproduce the above
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution.
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *     * Neither the name of Google Inc. nor the names of its
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission.
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef Decimal_h
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#define Decimal_h
335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
341e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/PlatformExport.h"
357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/Assertions.h"
367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "wtf/text/WTFString.h"
371e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include <stdint.h>
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
39c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace DecimalPrivate {
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)class SpecialValueHandler;
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// This class represents decimal base floating point number.
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)//
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// FIXME: Once all C++ compiler support decimal type, we should replace this
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// class to compiler supported one. See below URI for current status of decimal
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)// type for C++: // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1977.html
501e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)class PLATFORM_EXPORT Decimal {
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    WTF_MAKE_FAST_ALLOCATED;
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)public:
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    enum Sign {
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Positive,
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Negative,
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // You should not use EncodedData other than unit testing.
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    class EncodedData {
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // For accessing FormatClass.
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        friend class Decimal;
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        friend class DecimalPrivate::SpecialValueHandler;
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    public:
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EncodedData(Sign, int exponent, uint64_t coefficient);
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool operator==(const EncodedData&) const;
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool operator!=(const EncodedData& another) const { return !operator==(another); }
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint64_t coefficient() const { return m_coefficient; }
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int countDigits() const;
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int exponent() const { return m_exponent; }
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool isFinite() const { return !isSpecial(); }
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool isInfinity() const { return m_formatClass == ClassInfinity; }
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool isNaN() const { return m_formatClass == ClassNaN; }
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool isSpecial() const { return m_formatClass == ClassInfinity || m_formatClass == ClassNaN; }
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        bool isZero() const { return m_formatClass == ClassZero; }
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Sign sign() const { return m_sign; }
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        void setSign(Sign sign) { m_sign = sign; }
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    private:
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        enum FormatClass {
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ClassInfinity,
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ClassNormal,
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ClassNaN,
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ClassZero,
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        };
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        EncodedData(Sign, FormatClass);
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FormatClass formatClass() const { return m_formatClass; }
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint64_t m_coefficient;
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int16_t m_exponent;
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FormatClass m_formatClass;
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Sign m_sign;
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal(int32_t = 0);
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal(Sign, int exponent, uint64_t coefficient);
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal(const Decimal&);
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal& operator=(const Decimal&);
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal& operator+=(const Decimal&);
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal& operator-=(const Decimal&);
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal& operator*=(const Decimal&);
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal& operator/=(const Decimal&);
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal operator-() const;
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool operator==(const Decimal&) const;
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool operator!=(const Decimal&) const;
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool operator<(const Decimal&) const;
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool operator<=(const Decimal&) const;
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool operator>(const Decimal&) const;
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool operator>=(const Decimal&) const;
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal operator+(const Decimal&) const;
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal operator-(const Decimal&) const;
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal operator*(const Decimal&) const;
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal operator/(const Decimal&) const;
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int exponent() const
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    {
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(isFinite());
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return m_data.exponent();
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isFinite() const { return m_data.isFinite(); }
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isInfinity() const { return m_data.isInfinity(); }
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isNaN() const { return m_data.isNaN(); }
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isNegative() const { return sign() == Negative; }
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isPositive() const { return sign() == Positive; }
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isSpecial() const { return m_data.isSpecial(); }
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool isZero() const { return m_data.isZero(); }
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal abs() const;
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal ceiling() const;
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal floor() const;
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal remainder(const Decimal&) const;
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal round() const;
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    double toDouble() const;
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Note: toString method supports infinity and nan but fromString not.
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    String toString() const;
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static Decimal fromDouble(double);
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // fromString supports following syntax EBNF:
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //  number ::= sign? digit+ ('.' digit*) (exponent-marker sign? digit+)?
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //          | sign? '.' digit+ (exponent-marker sign? digit+)?
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //  sign ::= '+' | '-'
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //  exponent-marker ::= 'e' | 'E'
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    //  digit ::= '0' | '1' | ... | '9'
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Note: fromString doesn't support "infinity" and "nan".
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static Decimal fromString(const String&);
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static Decimal infinity(Sign);
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static Decimal nan();
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static Decimal zero(Sign);
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // You should not use below methods. We expose them for unit testing.
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    explicit Decimal(const EncodedData&);
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const EncodedData& value() const { return m_data; }
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)private:
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    struct AlignedOperands {
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint64_t lhsCoefficient;
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        uint64_t rhsCoefficient;
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        int exponent;
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    };
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal(double);
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Decimal compareTo(const Decimal&) const;
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static AlignedOperands alignOperands(const Decimal& lhs, const Decimal& rhs);
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    static inline Sign invertSign(Sign sign) { return sign == Negative ? Positive : Negative; }
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Sign sign() const { return m_data.sign(); }
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    EncodedData m_data;
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
180c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif // Decimal_h
183