LCOV - code coverage report
Current view: top level - mfbt - FloatingPoint.h (source / functions) Hit Total Coverage
Test: output.info Lines: 51 57 89.5 %
Date: 2017-07-14 16:53:18 Functions: 20 33 60.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /* Various predicates and operations on IEEE-754 floating point types. */
       8             : 
       9             : #ifndef mozilla_FloatingPoint_h
      10             : #define mozilla_FloatingPoint_h
      11             : 
      12             : #include "mozilla/Assertions.h"
      13             : #include "mozilla/Attributes.h"
      14             : #include "mozilla/Casting.h"
      15             : #include "mozilla/MathAlgorithms.h"
      16             : #include "mozilla/Types.h"
      17             : 
      18             : #include <stdint.h>
      19             : 
      20             : namespace mozilla {
      21             : 
      22             : /*
      23             :  * It's reasonable to ask why we have this header at all.  Don't isnan,
      24             :  * copysign, the built-in comparison operators, and the like solve these
      25             :  * problems?  Unfortunately, they don't.  We've found that various compilers
      26             :  * (MSVC, MSVC when compiling with PGO, and GCC on OS X, at least) miscompile
      27             :  * the standard methods in various situations, so we can't use them.  Some of
      28             :  * these compilers even have problems compiling seemingly reasonable bitwise
      29             :  * algorithms!  But with some care we've found algorithms that seem to not
      30             :  * trigger those compiler bugs.
      31             :  *
      32             :  * For the aforementioned reasons, be very wary of making changes to any of
      33             :  * these algorithms.  If you must make changes, keep a careful eye out for
      34             :  * compiler bustage, particularly PGO-specific bustage.
      35             :  */
      36             : 
      37             : struct FloatTypeTraits
      38             : {
      39             :   typedef uint32_t Bits;
      40             : 
      41             :   static const unsigned kExponentBias = 127;
      42             :   static const unsigned kExponentShift = 23;
      43             : 
      44             :   static const Bits kSignBit         = 0x80000000UL;
      45             :   static const Bits kExponentBits    = 0x7F800000UL;
      46             :   static const Bits kSignificandBits = 0x007FFFFFUL;
      47             : };
      48             : 
      49             : struct DoubleTypeTraits
      50             : {
      51             :   typedef uint64_t Bits;
      52             : 
      53             :   static const unsigned kExponentBias = 1023;
      54             :   static const unsigned kExponentShift = 52;
      55             : 
      56             :   static const Bits kSignBit         = 0x8000000000000000ULL;
      57             :   static const Bits kExponentBits    = 0x7ff0000000000000ULL;
      58             :   static const Bits kSignificandBits = 0x000fffffffffffffULL;
      59             : };
      60             : 
      61             : template<typename T> struct SelectTrait;
      62             : template<> struct SelectTrait<float> : public FloatTypeTraits {};
      63             : template<> struct SelectTrait<double> : public DoubleTypeTraits {};
      64             : 
      65             : /*
      66             :  *  This struct contains details regarding the encoding of floating-point
      67             :  *  numbers that can be useful for direct bit manipulation. As of now, the
      68             :  *  template parameter has to be float or double.
      69             :  *
      70             :  *  The nested typedef |Bits| is the unsigned integral type with the same size
      71             :  *  as T: uint32_t for float and uint64_t for double (static assertions
      72             :  *  double-check these assumptions).
      73             :  *
      74             :  *  kExponentBias is the offset that is subtracted from the exponent when
      75             :  *  computing the value, i.e. one plus the opposite of the mininum possible
      76             :  *  exponent.
      77             :  *  kExponentShift is the shift that one needs to apply to retrieve the
      78             :  *  exponent component of the value.
      79             :  *
      80             :  *  kSignBit contains a bits mask. Bit-and-ing with this mask will result in
      81             :  *  obtaining the sign bit.
      82             :  *  kExponentBits contains the mask needed for obtaining the exponent bits and
      83             :  *  kSignificandBits contains the mask needed for obtaining the significand
      84             :  *  bits.
      85             :  *
      86             :  *  Full details of how floating point number formats are encoded are beyond
      87             :  *  the scope of this comment. For more information, see
      88             :  *  http://en.wikipedia.org/wiki/IEEE_floating_point
      89             :  *  http://en.wikipedia.org/wiki/Floating_point#IEEE_754:_floating_point_in_modern_computers
      90             :  */
      91             : template<typename T>
      92             : struct FloatingPoint : public SelectTrait<T>
      93             : {
      94             :   typedef SelectTrait<T> Base;
      95             :   typedef typename Base::Bits Bits;
      96             : 
      97             :   static_assert((Base::kSignBit & Base::kExponentBits) == 0,
      98             :                 "sign bit shouldn't overlap exponent bits");
      99             :   static_assert((Base::kSignBit & Base::kSignificandBits) == 0,
     100             :                 "sign bit shouldn't overlap significand bits");
     101             :   static_assert((Base::kExponentBits & Base::kSignificandBits) == 0,
     102             :                 "exponent bits shouldn't overlap significand bits");
     103             : 
     104             :   static_assert((Base::kSignBit | Base::kExponentBits | Base::kSignificandBits) ==
     105             :                 ~Bits(0),
     106             :                 "all bits accounted for");
     107             : 
     108             :   /*
     109             :    * These implementations assume float/double are 32/64-bit single/double
     110             :    * format number types compatible with the IEEE-754 standard.  C++ don't
     111             :    * require this to be the case.  But we required this in implementations of
     112             :    * these algorithms that preceded this header, so we shouldn't break anything
     113             :    * if we keep doing so.
     114             :    */
     115             :   static_assert(sizeof(T) == sizeof(Bits), "Bits must be same size as T");
     116             : };
     117             : 
     118             : /** Determines whether a float/double is NaN. */
     119             : template<typename T>
     120             : static MOZ_ALWAYS_INLINE bool
     121       52819 : IsNaN(T aValue)
     122             : {
     123             :   /*
     124             :    * A float/double is NaN if all exponent bits are 1 and the significand
     125             :    * contains at least one non-zero bit.
     126             :    */
     127             :   typedef FloatingPoint<T> Traits;
     128             :   typedef typename Traits::Bits Bits;
     129       53064 :   return (BitwiseCast<Bits>(aValue) & Traits::kExponentBits) == Traits::kExponentBits &&
     130       53064 :          (BitwiseCast<Bits>(aValue) & Traits::kSignificandBits) != 0;
     131             : }
     132             : 
     133             : /** Determines whether a float/double is +Infinity or -Infinity. */
     134             : template<typename T>
     135             : static MOZ_ALWAYS_INLINE bool
     136         839 : IsInfinite(T aValue)
     137             : {
     138             :   /* Infinities have all exponent bits set to 1 and an all-0 significand. */
     139             :   typedef FloatingPoint<T> Traits;
     140             :   typedef typename Traits::Bits Bits;
     141         839 :   Bits bits = BitwiseCast<Bits>(aValue);
     142         839 :   return (bits & ~Traits::kSignBit) == Traits::kExponentBits;
     143             : }
     144             : 
     145             : /** Determines whether a float/double is not NaN or infinite. */
     146             : template<typename T>
     147             : static MOZ_ALWAYS_INLINE bool
     148        5907 : IsFinite(T aValue)
     149             : {
     150             :   /*
     151             :    * NaN and Infinities are the only non-finite floats/doubles, and both have
     152             :    * all exponent bits set to 1.
     153             :    */
     154             :   typedef FloatingPoint<T> Traits;
     155             :   typedef typename Traits::Bits Bits;
     156        5907 :   Bits bits = BitwiseCast<Bits>(aValue);
     157        5907 :   return (bits & Traits::kExponentBits) != Traits::kExponentBits;
     158             : }
     159             : 
     160             : /**
     161             :  * Determines whether a float/double is negative or -0.  It is an error
     162             :  * to call this method on a float/double which is NaN.
     163             :  */
     164             : template<typename T>
     165             : static MOZ_ALWAYS_INLINE bool
     166         611 : IsNegative(T aValue)
     167             : {
     168         611 :   MOZ_ASSERT(!IsNaN(aValue), "NaN does not have a sign");
     169             : 
     170             :   /* The sign bit is set if the double is negative. */
     171             :   typedef FloatingPoint<T> Traits;
     172             :   typedef typename Traits::Bits Bits;
     173         611 :   Bits bits = BitwiseCast<Bits>(aValue);
     174         611 :   return (bits & Traits::kSignBit) != 0;
     175             : }
     176             : 
     177             : /** Determines whether a float/double represents -0. */
     178             : template<typename T>
     179             : static MOZ_ALWAYS_INLINE bool
     180       30486 : IsNegativeZero(T aValue)
     181             : {
     182             :   /* Only the sign bit is set if the value is -0. */
     183             :   typedef FloatingPoint<T> Traits;
     184             :   typedef typename Traits::Bits Bits;
     185       30486 :   Bits bits = BitwiseCast<Bits>(aValue);
     186       30486 :   return bits == Traits::kSignBit;
     187             : }
     188             : 
     189             : /** Determines wether a float/double represents +0. */
     190             : template<typename T>
     191             : static MOZ_ALWAYS_INLINE bool
     192           0 : IsPositiveZero(T aValue)
     193             : {
     194             :   /* All bits are zero if the value is +0. */
     195             :   typedef FloatingPoint<T> Traits;
     196             :   typedef typename Traits::Bits Bits;
     197           0 :   Bits bits = BitwiseCast<Bits>(aValue);
     198           0 :   return bits == 0;
     199             : }
     200             : 
     201             : /**
     202             :  * Returns 0 if a float/double is NaN or infinite;
     203             :  * otherwise, the float/double is returned.
     204             :  */
     205             : template<typename T>
     206             : static MOZ_ALWAYS_INLINE T
     207           0 : ToZeroIfNonfinite(T aValue)
     208             : {
     209           0 :   return IsFinite(aValue) ? aValue : 0;
     210             : }
     211             : 
     212             : /**
     213             :  * Returns the exponent portion of the float/double.
     214             :  *
     215             :  * Zero is not special-cased, so ExponentComponent(0.0) is
     216             :  * -int_fast16_t(Traits::kExponentBias).
     217             :  */
     218             : template<typename T>
     219             : static MOZ_ALWAYS_INLINE int_fast16_t
     220         400 : ExponentComponent(T aValue)
     221             : {
     222             :   /*
     223             :    * The exponent component of a float/double is an unsigned number, biased
     224             :    * from its actual value.  Subtract the bias to retrieve the actual exponent.
     225             :    */
     226             :   typedef FloatingPoint<T> Traits;
     227             :   typedef typename Traits::Bits Bits;
     228         400 :   Bits bits = BitwiseCast<Bits>(aValue);
     229         400 :   return int_fast16_t((bits & Traits::kExponentBits) >> Traits::kExponentShift) -
     230         400 :          int_fast16_t(Traits::kExponentBias);
     231             : }
     232             : 
     233             : /** Returns +Infinity. */
     234             : template<typename T>
     235             : static MOZ_ALWAYS_INLINE T
     236        7222 : PositiveInfinity()
     237             : {
     238             :   /*
     239             :    * Positive infinity has all exponent bits set, sign bit set to 0, and no
     240             :    * significand.
     241             :    */
     242             :   typedef FloatingPoint<T> Traits;
     243        7222 :   return BitwiseCast<T>(Traits::kExponentBits);
     244             : }
     245             : 
     246             : /** Returns -Infinity. */
     247             : template<typename T>
     248             : static MOZ_ALWAYS_INLINE T
     249        7214 : NegativeInfinity()
     250             : {
     251             :   /*
     252             :    * Negative infinity has all exponent bits set, sign bit set to 1, and no
     253             :    * significand.
     254             :    */
     255             :   typedef FloatingPoint<T> Traits;
     256        7214 :   return BitwiseCast<T>(Traits::kSignBit | Traits::kExponentBits);
     257             : }
     258             : 
     259             : /**
     260             :  * Computes the bit pattern for a NaN with the specified sign bit and
     261             :  * significand bits.
     262             :  */
     263             : template<typename T,
     264             :          int SignBit,
     265             :          typename FloatingPoint<T>::Bits Significand>
     266             : struct SpecificNaNBits
     267             : {
     268             :   using Traits = FloatingPoint<T>;
     269             : 
     270             :   static_assert(SignBit == 0 || SignBit == 1, "bad sign bit");
     271             :   static_assert((Significand & ~Traits::kSignificandBits) == 0,
     272             :                 "significand must only have significand bits set");
     273             :   static_assert(Significand & Traits::kSignificandBits,
     274             :                 "significand must be nonzero");
     275             : 
     276             :   static constexpr typename Traits::Bits value =
     277             :     (SignBit * Traits::kSignBit) | Traits::kExponentBits | Significand;
     278             : };
     279             : 
     280             : /**
     281             :  * Constructs a NaN value with the specified sign bit and significand bits.
     282             :  *
     283             :  * There is also a variant that returns the value directly.  In most cases, the
     284             :  * two variants should be identical.  However, in the specific case of x86
     285             :  * chips, the behavior differs: returning floating-point values directly is done
     286             :  * through the x87 stack, and x87 loads and stores turn signaling NaNs into
     287             :  * quiet NaNs... silently.  Returning floating-point values via outparam,
     288             :  * however, is done entirely within the SSE registers when SSE2 floating-point
     289             :  * is enabled in the compiler, which has semantics-preserving behavior you would
     290             :  * expect.
     291             :  *
     292             :  * If preserving the distinction between signaling NaNs and quiet NaNs is
     293             :  * important to you, you should use the outparam version.  In all other cases,
     294             :  * you should use the direct return version.
     295             :  */
     296             : template<typename T>
     297             : static MOZ_ALWAYS_INLINE void
     298         232 : SpecificNaN(int signbit, typename FloatingPoint<T>::Bits significand, T* result)
     299             : {
     300             :   typedef FloatingPoint<T> Traits;
     301         232 :   MOZ_ASSERT(signbit == 0 || signbit == 1);
     302         232 :   MOZ_ASSERT((significand & ~Traits::kSignificandBits) == 0);
     303         232 :   MOZ_ASSERT(significand & Traits::kSignificandBits);
     304             : 
     305         232 :   BitwiseCast<T>((signbit ? Traits::kSignBit : 0) |
     306             :                   Traits::kExponentBits |
     307             :                   significand,
     308             :                   result);
     309         232 :   MOZ_ASSERT(IsNaN(*result));
     310         232 : }
     311             : 
     312             : template<typename T>
     313             : static MOZ_ALWAYS_INLINE T
     314         232 : SpecificNaN(int signbit, typename FloatingPoint<T>::Bits significand)
     315             : {
     316             :   T t;
     317         232 :   SpecificNaN(signbit, significand, &t);
     318         232 :   return t;
     319             : }
     320             : 
     321             : /** Computes the smallest non-zero positive float/double value. */
     322             : template<typename T>
     323             : static MOZ_ALWAYS_INLINE T
     324           3 : MinNumberValue()
     325             : {
     326             :   typedef FloatingPoint<T> Traits;
     327             :   typedef typename Traits::Bits Bits;
     328           3 :   return BitwiseCast<T>(Bits(1));
     329             : }
     330             : 
     331             : /**
     332             :  * If aValue is equal to some int32_t value, set *aInt32 to that value and
     333             :  * return true; otherwise return false.
     334             :  *
     335             :  * Note that negative zero is "equal" to zero here. To test whether a value can
     336             :  * be losslessly converted to int32_t and back, use NumberIsInt32 instead.
     337             :  */
     338             : template<typename T>
     339             : static MOZ_ALWAYS_INLINE bool
     340       30406 : NumberEqualsInt32(T aValue, int32_t* aInt32)
     341             : {
     342             :   /*
     343             :    * XXX Casting a floating-point value that doesn't truncate to int32_t, to
     344             :    *     int32_t, induces undefined behavior.  We should definitely fix this
     345             :    *     (bug 744965), but as apparently it "works" in practice, it's not a
     346             :    *     pressing concern now.
     347             :    */
     348       30406 :   return aValue == (*aInt32 = int32_t(aValue));
     349             : }
     350             : 
     351             : /**
     352             :  * If d can be converted to int32_t and back to an identical double value,
     353             :  * set *aInt32 to that value and return true; otherwise return false.
     354             :  *
     355             :  * The difference between this and NumberEqualsInt32 is that this method returns
     356             :  * false for negative zero.
     357             :  */
     358             : template<typename T>
     359             : static MOZ_ALWAYS_INLINE bool
     360       30405 : NumberIsInt32(T aValue, int32_t* aInt32)
     361             : {
     362       30405 :   return !IsNegativeZero(aValue) && NumberEqualsInt32(aValue, aInt32);
     363             : }
     364             : 
     365             : /**
     366             :  * Computes a NaN value.  Do not use this method if you depend upon a particular
     367             :  * NaN value being returned.
     368             :  */
     369             : template<typename T>
     370             : static MOZ_ALWAYS_INLINE T
     371          19 : UnspecifiedNaN()
     372             : {
     373             :   /*
     374             :    * If we can use any quiet NaN, we might as well use the all-ones NaN,
     375             :    * since it's cheap to materialize on common platforms (such as x64, where
     376             :    * this value can be represented in a 32-bit signed immediate field, allowing
     377             :    * it to be stored to memory in a single instruction).
     378             :    */
     379             :   typedef FloatingPoint<T> Traits;
     380          19 :   return SpecificNaN<T>(1, Traits::kSignificandBits);
     381             : }
     382             : 
     383             : /**
     384             :  * Compare two doubles for equality, *without* equating -0 to +0, and equating
     385             :  * any NaN value to any other NaN value.  (The normal equality operators equate
     386             :  * -0 with +0, and they equate NaN to no other value.)
     387             :  */
     388             : template<typename T>
     389             : static inline bool
     390          28 : NumbersAreIdentical(T aValue1, T aValue2)
     391             : {
     392             :   typedef FloatingPoint<T> Traits;
     393             :   typedef typename Traits::Bits Bits;
     394          28 :   if (IsNaN(aValue1)) {
     395           0 :     return IsNaN(aValue2);
     396             :   }
     397          28 :   return BitwiseCast<Bits>(aValue1) == BitwiseCast<Bits>(aValue2);
     398             : }
     399             : 
     400             : namespace detail {
     401             : 
     402             : template<typename T>
     403             : struct FuzzyEqualsEpsilon;
     404             : 
     405             : template<>
     406             : struct FuzzyEqualsEpsilon<float>
     407             : {
     408             :   // A number near 1e-5 that is exactly representable in a float.
     409         166 :   static float value() { return 1.0f / (1 << 17); }
     410             : };
     411             : 
     412             : template<>
     413             : struct FuzzyEqualsEpsilon<double>
     414             : {
     415             :   // A number near 1e-12 that is exactly representable in a double.
     416             :   static double value() { return 1.0 / (1LL << 40); }
     417             : };
     418             : 
     419             : } // namespace detail
     420             : 
     421             : /**
     422             :  * Compare two floating point values for equality, modulo rounding error. That
     423             :  * is, the two values are considered equal if they are both not NaN and if they
     424             :  * are less than or equal to aEpsilon apart. The default value of aEpsilon is
     425             :  * near 1e-5.
     426             :  *
     427             :  * For most scenarios you will want to use FuzzyEqualsMultiplicative instead,
     428             :  * as it is more reasonable over the entire range of floating point numbers.
     429             :  * This additive version should only be used if you know the range of the
     430             :  * numbers you are dealing with is bounded and stays around the same order of
     431             :  * magnitude.
     432             :  */
     433             : template<typename T>
     434             : static MOZ_ALWAYS_INLINE bool
     435          34 : FuzzyEqualsAdditive(T aValue1, T aValue2,
     436             :                     T aEpsilon = detail::FuzzyEqualsEpsilon<T>::value())
     437             : {
     438             :   static_assert(IsFloatingPoint<T>::value, "floating point type required");
     439          34 :   return Abs(aValue1 - aValue2) <= aEpsilon;
     440             : }
     441             : 
     442             : /**
     443             :  * Compare two floating point values for equality, allowing for rounding error
     444             :  * relative to the magnitude of the values. That is, the two values are
     445             :  * considered equal if they are both not NaN and they are less than or equal to
     446             :  * some aEpsilon apart, where the aEpsilon is scaled by the smaller of the two
     447             :  * argument values.
     448             :  *
     449             :  * In most cases you will want to use this rather than FuzzyEqualsAdditive, as
     450             :  * this function effectively masks out differences in the bottom few bits of
     451             :  * the floating point numbers being compared, regardless of what order of
     452             :  * magnitude those numbers are at.
     453             :  */
     454             : template<typename T>
     455             : static MOZ_ALWAYS_INLINE bool
     456         136 : FuzzyEqualsMultiplicative(T aValue1, T aValue2,
     457             :                           T aEpsilon = detail::FuzzyEqualsEpsilon<T>::value())
     458             : {
     459             :   static_assert(IsFloatingPoint<T>::value, "floating point type required");
     460             :   // can't use std::min because of bug 965340
     461         136 :   T smaller = Abs(aValue1) < Abs(aValue2) ? Abs(aValue1) : Abs(aValue2);
     462         136 :   return Abs(aValue1 - aValue2) <= aEpsilon * smaller;
     463             : }
     464             : 
     465             : /**
     466             :  * Returns true if the given value can be losslessly represented as an IEEE-754
     467             :  * single format number, false otherwise.  All NaN values are considered
     468             :  * representable (notwithstanding that the exact bit pattern of a double format
     469             :  * NaN value can't be exactly represented in single format).
     470             :  *
     471             :  * This function isn't inlined to avoid buggy optimizations by MSVC.
     472             :  */
     473             : MOZ_MUST_USE
     474             : extern MFBT_API bool
     475             : IsFloat32Representable(double aFloat32);
     476             : 
     477             : } /* namespace mozilla */
     478             : 
     479             : #endif /* mozilla_FloatingPoint_h */

Generated by: LCOV version 1.13