tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Decimal.h (9680B)


      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 /**
     32 * Imported from:
     33 * https://chromium.googlesource.com/chromium/src.git/+/master/third_party/WebKit/Source/platform/Decimal.h
     34 * Check UPSTREAM-GIT-SHA for the commit ID of the last update from Blink core.
     35 */
     36 
     37 #ifndef Decimal_h
     38 #define Decimal_h
     39 
     40 #include "mozilla/Assertions.h"
     41 #include <stdint.h>
     42 #include "mozilla/Types.h"
     43 
     44 #include <string>
     45 
     46 #ifndef ASSERT
     47 #define DEFINED_ASSERT_FOR_DECIMAL_H 1
     48 #define ASSERT MOZ_ASSERT
     49 #endif
     50 
     51 #define PLATFORM_EXPORT
     52 
     53 // To use USING_FAST_MALLOC we'd need:
     54 // https://chromium.googlesource.com/chromium/src.git/+/master/third_party/WebKit/Source/wtf/Allocator.h
     55 // Since we don't allocate Decimal objects, no need.
     56 #define USING_FAST_MALLOC(type) \
     57  void ignore_this_dummy_method() = delete
     58 
     59 #define DISALLOW_NEW()                                          \
     60    private:                                                    \
     61        void* operator new(size_t) = delete;                    \
     62        void* operator new(size_t, void*) = delete;             \
     63    public:
     64 
     65 namespace blink {
     66 
     67 namespace DecimalPrivate {
     68 constexpr int ExponentMax = 1023;
     69 constexpr int ExponentMin = -1023;
     70 constexpr int Precision = 18;
     71 
     72 static const uint64_t MaxCoefficient = UINT64_C(0xDE0B6B3A763FFFF);  // 999999999999999999 == 18 9's
     73 class SpecialValueHandler;
     74 }
     75 
     76 struct DecimalLiteral {
     77  int32_t value;
     78  friend constexpr DecimalLiteral operator*(int32_t lhs, DecimalLiteral rhs) {
     79    return {lhs * rhs.value};
     80  }
     81  constexpr DecimalLiteral operator-() {
     82    return {-value};
     83  }
     84 };
     85 
     86 constexpr DecimalLiteral operator""_d(unsigned long long value) {
     87  return {static_cast<int32_t>(value)};
     88 }
     89 
     90 // This class represents decimal base floating point number.
     91 //
     92 // FIXME: Once all C++ compiler support decimal type, we should replace this
     93 // class to compiler supported one. See below URI for current status of decimal
     94 // type for C++: // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1977.html
     95 class PLATFORM_EXPORT Decimal {
     96    USING_FAST_MALLOC(Decimal);
     97 public:
     98    enum Sign {
     99        Positive,
    100        Negative,
    101    };
    102 
    103    // You should not use EncodedData other than unit testing.
    104    class EncodedData {
    105        DISALLOW_NEW();
    106        // For accessing FormatClass.
    107        friend class Decimal;
    108        friend class DecimalPrivate::SpecialValueHandler;
    109    public:
    110     constexpr EncodedData(Sign sign, int exponent, uint64_t coefficient)
    111         : m_coefficient(0),
    112           m_exponent(0),
    113           m_formatClass(coefficient ? ClassNormal : ClassZero),
    114           m_sign(sign) {
    115       if (exponent >= DecimalPrivate::ExponentMin &&
    116           exponent <= DecimalPrivate::ExponentMax) {
    117         while (coefficient > DecimalPrivate::MaxCoefficient) {
    118           coefficient /= 10;
    119           ++exponent;
    120         }
    121       }
    122 
    123       if (exponent > DecimalPrivate::ExponentMax) {
    124         m_formatClass = ClassInfinity;
    125         return;
    126       }
    127 
    128       if (exponent < DecimalPrivate::ExponentMin) {
    129         m_formatClass = ClassZero;
    130         return;
    131       }
    132 
    133       m_coefficient = coefficient;
    134       m_exponent = static_cast<int16_t>(exponent);
    135     }
    136 
    137        bool operator==(const EncodedData&) const;
    138        bool operator!=(const EncodedData& another) const { return !operator==(another); }
    139 
    140        uint64_t coefficient() const { return m_coefficient; }
    141        int countDigits() const;
    142        int exponent() const { return m_exponent; }
    143        bool isFinite() const { return !isSpecial(); }
    144        bool isInfinity() const { return m_formatClass == ClassInfinity; }
    145        bool isNaN() const { return m_formatClass == ClassNaN; }
    146        bool isSpecial() const { return m_formatClass == ClassInfinity || m_formatClass == ClassNaN; }
    147        bool isZero() const { return m_formatClass == ClassZero; }
    148        Sign sign() const { return m_sign; }
    149        void setSign(Sign sign) { m_sign = sign; }
    150 
    151    private:
    152        enum FormatClass {
    153            ClassInfinity,
    154            ClassNormal,
    155            ClassNaN,
    156            ClassZero,
    157        };
    158 
    159        constexpr EncodedData(Sign sign, FormatClass formatClass)
    160            : m_coefficient(0),
    161              m_exponent(0),
    162              m_formatClass(formatClass),
    163              m_sign(sign) {}
    164 
    165        FormatClass formatClass() const { return m_formatClass; }
    166 
    167        uint64_t m_coefficient;
    168        int16_t m_exponent;
    169        FormatClass m_formatClass;
    170        Sign m_sign;
    171    };
    172 
    173    constexpr explicit Decimal(DecimalLiteral i32)
    174    : m_data(i32.value < 0 ? Negative : Positive, 0,
    175             i32.value < 0 ? static_cast<uint64_t>(-static_cast<int64_t>(i32.value))
    176                     : static_cast<uint64_t>(i32.value)) {}
    177 
    178    MFBT_API explicit Decimal(int32_t i32 = 0);
    179    MFBT_API Decimal(Sign sign, int exponent, uint64_t coefficient);
    180    MFBT_API Decimal(const Decimal&);
    181 
    182    MFBT_API Decimal& operator=(const Decimal&);
    183    MFBT_API Decimal& operator+=(const Decimal&);
    184    MFBT_API Decimal& operator-=(const Decimal&);
    185    MFBT_API Decimal& operator*=(const Decimal&);
    186    MFBT_API Decimal& operator/=(const Decimal&);
    187 
    188    MFBT_API Decimal operator-() const;
    189 
    190    MFBT_API bool operator==(const Decimal&) const;
    191    MFBT_API bool operator!=(const Decimal&) const;
    192    MFBT_API bool operator<(const Decimal&) const;
    193    MFBT_API bool operator<=(const Decimal&) const;
    194    MFBT_API bool operator>(const Decimal&) const;
    195    MFBT_API bool operator>=(const Decimal&) const;
    196 
    197    MFBT_API Decimal operator+(const Decimal&) const;
    198    MFBT_API Decimal operator-(const Decimal&) const;
    199    MFBT_API Decimal operator*(const Decimal&) const;
    200    MFBT_API Decimal operator/(const Decimal&) const;
    201 
    202    int exponent() const
    203    {
    204        ASSERT(isFinite());
    205        return m_data.exponent();
    206    }
    207 
    208    bool isFinite() const { return m_data.isFinite(); }
    209    bool isInfinity() const { return m_data.isInfinity(); }
    210    bool isNaN() const { return m_data.isNaN(); }
    211    bool isNegative() const { return sign() == Negative; }
    212    bool isPositive() const { return sign() == Positive; }
    213    bool isSpecial() const { return m_data.isSpecial(); }
    214    bool isZero() const { return m_data.isZero(); }
    215 
    216    MFBT_API Decimal abs() const;
    217    MFBT_API Decimal ceil() const;
    218    MFBT_API Decimal floor() const;
    219    MFBT_API Decimal remainder(const Decimal&) const;
    220    MFBT_API Decimal round() const;
    221 
    222    MFBT_API double toDouble() const;
    223    // Note: toString method supports infinity and nan but fromString not.
    224    MFBT_API std::string toString() const;
    225 
    226    static MFBT_API Decimal fromDouble(double);
    227    // fromString supports following syntax EBNF:
    228    //  number ::= sign? digit+ ('.' digit*) (exponent-marker sign? digit+)?
    229    //          | sign? '.' digit+ (exponent-marker sign? digit+)?
    230    //  sign ::= '+' | '-'
    231    //  exponent-marker ::= 'e' | 'E'
    232    //  digit ::= '0' | '1' | ... | '9'
    233    // Note: fromString doesn't support "infinity" and "nan".
    234    static MFBT_API Decimal fromString(const std::string& aValue);
    235    static MFBT_API Decimal infinity(Sign);
    236    static constexpr Decimal nan() {
    237        return Decimal(EncodedData(Positive, EncodedData::ClassNaN));
    238    }
    239    static MFBT_API Decimal zero(Sign);
    240 
    241    // You should not use below methods. We expose them for unit testing.
    242    constexpr explicit Decimal(const EncodedData& data) : m_data(data) {}
    243    const EncodedData& value() const { return m_data; }
    244 
    245 private:
    246    struct AlignedOperands {
    247        uint64_t lhsCoefficient;
    248        uint64_t rhsCoefficient;
    249        int exponent;
    250    };
    251 
    252    MFBT_API explicit Decimal(double);
    253    MFBT_API Decimal compareTo(const Decimal&) const;
    254 
    255    static MFBT_API AlignedOperands alignOperands(const Decimal& lhs, const Decimal& rhs);
    256    static inline Sign invertSign(Sign sign) { return sign == Negative ? Positive : Negative; }
    257 
    258    Sign sign() const { return m_data.sign(); }
    259 
    260    EncodedData m_data;
    261 };
    262 
    263 } // namespace blink
    264 
    265 namespace mozilla {
    266 typedef blink::Decimal Decimal;
    267 using blink::operator""_d;
    268 } // namespace mozilla
    269 
    270 #undef USING_FAST_MALLOC
    271 
    272 #ifdef DEFINED_ASSERT_FOR_DECIMAL_H
    273 #undef DEFINED_ASSERT_FOR_DECIMAL_H
    274 #undef ASSERT
    275 #endif
    276 
    277 #endif // Decimal_h