tor-browser

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

TestFloatingPoint.cpp (28438B)


      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 file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/Assertions.h"
      8 #include "mozilla/FloatingPoint.h"
      9 
     10 #include <math.h>
     11 
     12 using mozilla::ExponentComponent;
     13 using mozilla::FloatingPoint;
     14 using mozilla::FuzzyEqualsAdditive;
     15 using mozilla::FuzzyEqualsMultiplicative;
     16 using mozilla::IsFloat32Representable;
     17 using mozilla::IsNegative;
     18 using mozilla::IsNegativeZero;
     19 using mozilla::IsPositiveZero;
     20 using mozilla::NegativeInfinity;
     21 using mozilla::NumberEqualsInt32;
     22 using mozilla::NumberEqualsInt64;
     23 using mozilla::NumberIsInt32;
     24 using mozilla::NumberIsInt64;
     25 using mozilla::NumbersAreIdentical;
     26 using mozilla::PositiveInfinity;
     27 using mozilla::SpecificNaN;
     28 using mozilla::UnspecifiedNaN;
     29 using std::exp2;
     30 using std::exp2f;
     31 
     32 #define A(a) MOZ_RELEASE_ASSERT(a)
     33 
     34 template <typename T>
     35 static void ShouldBeIdentical(T aD1, T aD2) {
     36  A(NumbersAreIdentical(aD1, aD2));
     37  A(NumbersAreIdentical(aD2, aD1));
     38 }
     39 
     40 template <typename T>
     41 static void ShouldNotBeIdentical(T aD1, T aD2) {
     42  A(!NumbersAreIdentical(aD1, aD2));
     43  A(!NumbersAreIdentical(aD2, aD1));
     44 }
     45 
     46 static void TestDoublesAreIdentical() {
     47  ShouldBeIdentical(+0.0, +0.0);
     48  ShouldBeIdentical(-0.0, -0.0);
     49  ShouldNotBeIdentical(+0.0, -0.0);
     50 
     51  ShouldBeIdentical(1.0, 1.0);
     52  ShouldNotBeIdentical(-1.0, 1.0);
     53  ShouldBeIdentical(4294967295.0, 4294967295.0);
     54  ShouldNotBeIdentical(-4294967295.0, 4294967295.0);
     55  ShouldBeIdentical(4294967296.0, 4294967296.0);
     56  ShouldBeIdentical(4294967297.0, 4294967297.0);
     57  ShouldBeIdentical(1e300, 1e300);
     58 
     59  ShouldBeIdentical(PositiveInfinity<double>(), PositiveInfinity<double>());
     60  ShouldBeIdentical(NegativeInfinity<double>(), NegativeInfinity<double>());
     61  ShouldNotBeIdentical(PositiveInfinity<double>(), NegativeInfinity<double>());
     62 
     63  ShouldNotBeIdentical(-0.0, NegativeInfinity<double>());
     64  ShouldNotBeIdentical(+0.0, NegativeInfinity<double>());
     65  ShouldNotBeIdentical(1e300, NegativeInfinity<double>());
     66  ShouldNotBeIdentical(3.141592654, NegativeInfinity<double>());
     67 
     68  ShouldBeIdentical(UnspecifiedNaN<double>(), UnspecifiedNaN<double>());
     69  ShouldBeIdentical(-UnspecifiedNaN<double>(), UnspecifiedNaN<double>());
     70  ShouldBeIdentical(UnspecifiedNaN<double>(), -UnspecifiedNaN<double>());
     71 
     72  ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 42));
     73  ShouldBeIdentical(SpecificNaN<double>(1, 17), SpecificNaN<double>(1, 42));
     74  ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(1, 42));
     75  ShouldBeIdentical(SpecificNaN<double>(1, 17), SpecificNaN<double>(0, 42));
     76 
     77  const uint64_t Mask = 0xfffffffffffffULL;
     78  for (unsigned i = 0; i < 52; i++) {
     79    for (unsigned j = 0; j < 52; j++) {
     80      for (unsigned sign = 0; i < 2; i++) {
     81        ShouldBeIdentical(SpecificNaN<double>(0, 1ULL << i),
     82                          SpecificNaN<double>(sign, 1ULL << j));
     83        ShouldBeIdentical(SpecificNaN<double>(1, 1ULL << i),
     84                          SpecificNaN<double>(sign, 1ULL << j));
     85 
     86        ShouldBeIdentical(SpecificNaN<double>(0, Mask & ~(1ULL << i)),
     87                          SpecificNaN<double>(sign, Mask & ~(1ULL << j)));
     88        ShouldBeIdentical(SpecificNaN<double>(1, Mask & ~(1ULL << i)),
     89                          SpecificNaN<double>(sign, Mask & ~(1ULL << j)));
     90      }
     91    }
     92  }
     93  ShouldBeIdentical(SpecificNaN<double>(0, 17),
     94                    SpecificNaN<double>(0, 0x8000000000000ULL));
     95  ShouldBeIdentical(SpecificNaN<double>(0, 17),
     96                    SpecificNaN<double>(0, 0x4000000000000ULL));
     97  ShouldBeIdentical(SpecificNaN<double>(0, 17),
     98                    SpecificNaN<double>(0, 0x2000000000000ULL));
     99  ShouldBeIdentical(SpecificNaN<double>(0, 17),
    100                    SpecificNaN<double>(0, 0x1000000000000ULL));
    101  ShouldBeIdentical(SpecificNaN<double>(0, 17),
    102                    SpecificNaN<double>(0, 0x0800000000000ULL));
    103  ShouldBeIdentical(SpecificNaN<double>(0, 17),
    104                    SpecificNaN<double>(0, 0x0400000000000ULL));
    105  ShouldBeIdentical(SpecificNaN<double>(0, 17),
    106                    SpecificNaN<double>(0, 0x0200000000000ULL));
    107  ShouldBeIdentical(SpecificNaN<double>(0, 17),
    108                    SpecificNaN<double>(0, 0x0100000000000ULL));
    109  ShouldBeIdentical(SpecificNaN<double>(0, 17),
    110                    SpecificNaN<double>(0, 0x0080000000000ULL));
    111  ShouldBeIdentical(SpecificNaN<double>(0, 17),
    112                    SpecificNaN<double>(0, 0x0040000000000ULL));
    113  ShouldBeIdentical(SpecificNaN<double>(0, 17),
    114                    SpecificNaN<double>(0, 0x0020000000000ULL));
    115  ShouldBeIdentical(SpecificNaN<double>(0, 17),
    116                    SpecificNaN<double>(0, 0x0010000000000ULL));
    117  ShouldBeIdentical(SpecificNaN<double>(1, 17),
    118                    SpecificNaN<double>(0, 0xff0ffffffffffULL));
    119  ShouldBeIdentical(SpecificNaN<double>(1, 17),
    120                    SpecificNaN<double>(0, 0xfffffffffff0fULL));
    121 
    122  ShouldNotBeIdentical(UnspecifiedNaN<double>(), +0.0);
    123  ShouldNotBeIdentical(UnspecifiedNaN<double>(), -0.0);
    124  ShouldNotBeIdentical(UnspecifiedNaN<double>(), 1.0);
    125  ShouldNotBeIdentical(UnspecifiedNaN<double>(), -1.0);
    126  ShouldNotBeIdentical(UnspecifiedNaN<double>(), PositiveInfinity<double>());
    127  ShouldNotBeIdentical(UnspecifiedNaN<double>(), NegativeInfinity<double>());
    128 }
    129 
    130 static void TestFloatsAreIdentical() {
    131  ShouldBeIdentical(+0.0f, +0.0f);
    132  ShouldBeIdentical(-0.0f, -0.0f);
    133  ShouldNotBeIdentical(+0.0f, -0.0f);
    134 
    135  ShouldBeIdentical(1.0f, 1.0f);
    136  ShouldNotBeIdentical(-1.0f, 1.0f);
    137  ShouldBeIdentical(8388607.0f, 8388607.0f);
    138  ShouldNotBeIdentical(-8388607.0f, 8388607.0f);
    139  ShouldBeIdentical(8388608.0f, 8388608.0f);
    140  ShouldBeIdentical(8388609.0f, 8388609.0f);
    141  ShouldBeIdentical(1e36f, 1e36f);
    142 
    143  ShouldBeIdentical(PositiveInfinity<float>(), PositiveInfinity<float>());
    144  ShouldBeIdentical(NegativeInfinity<float>(), NegativeInfinity<float>());
    145  ShouldNotBeIdentical(PositiveInfinity<float>(), NegativeInfinity<float>());
    146 
    147  ShouldNotBeIdentical(-0.0f, NegativeInfinity<float>());
    148  ShouldNotBeIdentical(+0.0f, NegativeInfinity<float>());
    149  ShouldNotBeIdentical(1e36f, NegativeInfinity<float>());
    150  ShouldNotBeIdentical(3.141592654f, NegativeInfinity<float>());
    151 
    152  ShouldBeIdentical(UnspecifiedNaN<float>(), UnspecifiedNaN<float>());
    153  ShouldBeIdentical(-UnspecifiedNaN<float>(), UnspecifiedNaN<float>());
    154  ShouldBeIdentical(UnspecifiedNaN<float>(), -UnspecifiedNaN<float>());
    155 
    156  ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 42));
    157  ShouldBeIdentical(SpecificNaN<float>(1, 17), SpecificNaN<float>(1, 42));
    158  ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(1, 42));
    159  ShouldBeIdentical(SpecificNaN<float>(1, 17), SpecificNaN<float>(0, 42));
    160 
    161  const uint32_t Mask = 0x7fffffUL;
    162  for (unsigned i = 0; i < 23; i++) {
    163    for (unsigned j = 0; j < 23; j++) {
    164      for (unsigned sign = 0; i < 2; i++) {
    165        ShouldBeIdentical(SpecificNaN<float>(0, 1UL << i),
    166                          SpecificNaN<float>(sign, 1UL << j));
    167        ShouldBeIdentical(SpecificNaN<float>(1, 1UL << i),
    168                          SpecificNaN<float>(sign, 1UL << j));
    169 
    170        ShouldBeIdentical(SpecificNaN<float>(0, Mask & ~(1UL << i)),
    171                          SpecificNaN<float>(sign, Mask & ~(1UL << j)));
    172        ShouldBeIdentical(SpecificNaN<float>(1, Mask & ~(1UL << i)),
    173                          SpecificNaN<float>(sign, Mask & ~(1UL << j)));
    174      }
    175    }
    176  }
    177  ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x700000));
    178  ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x400000));
    179  ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x200000));
    180  ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x100000));
    181  ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x080000));
    182  ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x040000));
    183  ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x020000));
    184  ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x010000));
    185  ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x008000));
    186  ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x004000));
    187  ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x002000));
    188  ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x001000));
    189  ShouldBeIdentical(SpecificNaN<float>(1, 17), SpecificNaN<float>(0, 0x7f0fff));
    190  ShouldBeIdentical(SpecificNaN<float>(1, 17), SpecificNaN<float>(0, 0x7fff0f));
    191 
    192  ShouldNotBeIdentical(UnspecifiedNaN<float>(), +0.0f);
    193  ShouldNotBeIdentical(UnspecifiedNaN<float>(), -0.0f);
    194  ShouldNotBeIdentical(UnspecifiedNaN<float>(), 1.0f);
    195  ShouldNotBeIdentical(UnspecifiedNaN<float>(), -1.0f);
    196  ShouldNotBeIdentical(UnspecifiedNaN<float>(), PositiveInfinity<float>());
    197  ShouldNotBeIdentical(UnspecifiedNaN<float>(), NegativeInfinity<float>());
    198 }
    199 
    200 static void TestAreIdentical() {
    201  TestDoublesAreIdentical();
    202  TestFloatsAreIdentical();
    203 }
    204 
    205 static void TestDoubleExponentComponent() {
    206  A(ExponentComponent(0.0) ==
    207    -int_fast16_t(FloatingPoint<double>::kExponentBias));
    208  A(ExponentComponent(-0.0) ==
    209    -int_fast16_t(FloatingPoint<double>::kExponentBias));
    210  A(ExponentComponent(0.125) == -3);
    211  A(ExponentComponent(0.5) == -1);
    212  A(ExponentComponent(1.0) == 0);
    213  A(ExponentComponent(1.5) == 0);
    214  A(ExponentComponent(2.0) == 1);
    215  A(ExponentComponent(7.0) == 2);
    216  A(ExponentComponent(PositiveInfinity<double>()) ==
    217    FloatingPoint<double>::kExponentBias + 1);
    218  A(ExponentComponent(NegativeInfinity<double>()) ==
    219    FloatingPoint<double>::kExponentBias + 1);
    220  A(ExponentComponent(UnspecifiedNaN<double>()) ==
    221    FloatingPoint<double>::kExponentBias + 1);
    222 }
    223 
    224 static void TestFloatExponentComponent() {
    225  A(ExponentComponent(0.0f) ==
    226    -int_fast16_t(FloatingPoint<float>::kExponentBias));
    227  A(ExponentComponent(-0.0f) ==
    228    -int_fast16_t(FloatingPoint<float>::kExponentBias));
    229  A(ExponentComponent(0.125f) == -3);
    230  A(ExponentComponent(0.5f) == -1);
    231  A(ExponentComponent(1.0f) == 0);
    232  A(ExponentComponent(1.5f) == 0);
    233  A(ExponentComponent(2.0f) == 1);
    234  A(ExponentComponent(7.0f) == 2);
    235  A(ExponentComponent(PositiveInfinity<float>()) ==
    236    FloatingPoint<float>::kExponentBias + 1);
    237  A(ExponentComponent(NegativeInfinity<float>()) ==
    238    FloatingPoint<float>::kExponentBias + 1);
    239  A(ExponentComponent(UnspecifiedNaN<float>()) ==
    240    FloatingPoint<float>::kExponentBias + 1);
    241 }
    242 
    243 static void TestExponentComponent() {
    244  TestDoubleExponentComponent();
    245  TestFloatExponentComponent();
    246 }
    247 
    248 // Used to test Number{Is,Equals}{Int32,Int64} for -0.0, the only case where
    249 // NumberEquals* and NumberIs* aren't equivalent.
    250 template <typename T>
    251 static void TestEqualsIsForNegativeZero() {
    252  T negZero = T(-0.0);
    253 
    254  int32_t i32;
    255  A(!NumberIsInt32(negZero, &i32));
    256  A(NumberEqualsInt32(negZero, &i32));
    257  A(i32 == 0);
    258 
    259  int64_t i64;
    260  A(!NumberIsInt64(negZero, &i64));
    261  A(NumberEqualsInt64(negZero, &i64));
    262  A(i64 == 0);
    263 }
    264 
    265 // Used to test Number{Is,Equals}{Int32,Int64} for int32 values.
    266 template <typename T>
    267 static void TestEqualsIsForInt32(T aVal) {
    268  int32_t i32;
    269  A(NumberIsInt32(aVal, &i32));
    270  MOZ_RELEASE_ASSERT(i32 == aVal);
    271  A(NumberEqualsInt32(aVal, &i32));
    272  MOZ_RELEASE_ASSERT(i32 == aVal);
    273 
    274  int64_t i64;
    275  A(NumberIsInt64(aVal, &i64));
    276  MOZ_RELEASE_ASSERT(i64 == aVal);
    277  A(NumberEqualsInt64(aVal, &i64));
    278  MOZ_RELEASE_ASSERT(i64 == aVal);
    279 };
    280 
    281 // Used to test Number{Is,Equals}{Int32,Int64} for values that fit in int64 but
    282 // not int32.
    283 template <typename T>
    284 static void TestEqualsIsForInt64(T aVal) {
    285  int32_t i32;
    286  A(!NumberIsInt32(aVal, &i32));
    287  A(!NumberEqualsInt32(aVal, &i32));
    288 
    289  int64_t i64;
    290  A(NumberIsInt64(aVal, &i64));
    291  MOZ_RELEASE_ASSERT(i64 == aVal);
    292  A(NumberEqualsInt64(aVal, &i64));
    293  MOZ_RELEASE_ASSERT(i64 == aVal);
    294 };
    295 
    296 // Used to test Number{Is,Equals}{Int32,Int64} for values that aren't equal to
    297 // any int32 or int64.
    298 template <typename T>
    299 static void TestEqualsIsForNonInteger(T aVal) {
    300  int32_t i32;
    301  A(!NumberIsInt32(aVal, &i32));
    302  A(!NumberEqualsInt32(aVal, &i32));
    303 
    304  int64_t i64;
    305  A(!NumberIsInt64(aVal, &i64));
    306  A(!NumberEqualsInt64(aVal, &i64));
    307 };
    308 
    309 static void TestDoublesPredicates() {
    310  A(std::isnan(UnspecifiedNaN<double>()));
    311  A(std::isnan(SpecificNaN<double>(1, 17)));
    312  ;
    313  A(std::isnan(SpecificNaN<double>(0, 0xfffffffffff0fULL)));
    314  A(!std::isnan(PositiveInfinity<double>()));
    315  A(!std::isnan(NegativeInfinity<double>()));
    316 
    317  A(std::isinf(PositiveInfinity<double>()));
    318  A(std::isinf(NegativeInfinity<double>()));
    319  A(!std::isinf(UnspecifiedNaN<double>()));
    320 
    321  A(!std::isfinite(PositiveInfinity<double>()));
    322  A(!std::isfinite(NegativeInfinity<double>()));
    323  A(!std::isfinite(UnspecifiedNaN<double>()));
    324 
    325  A(!IsNegative(PositiveInfinity<double>()));
    326  A(IsNegative(NegativeInfinity<double>()));
    327  A(IsNegative(-0.0));
    328  A(!IsNegative(0.0));
    329  A(IsNegative(-1.0));
    330  A(!IsNegative(1.0));
    331 
    332  A(!IsNegativeZero(PositiveInfinity<double>()));
    333  A(!IsNegativeZero(NegativeInfinity<double>()));
    334  A(!IsNegativeZero(SpecificNaN<double>(1, 17)));
    335  ;
    336  A(!IsNegativeZero(SpecificNaN<double>(1, 0xfffffffffff0fULL)));
    337  A(!IsNegativeZero(SpecificNaN<double>(0, 17)));
    338  ;
    339  A(!IsNegativeZero(SpecificNaN<double>(0, 0xfffffffffff0fULL)));
    340  A(!IsNegativeZero(UnspecifiedNaN<double>()));
    341  A(IsNegativeZero(-0.0));
    342  A(!IsNegativeZero(0.0));
    343  A(!IsNegativeZero(-1.0));
    344  A(!IsNegativeZero(1.0));
    345 
    346  // Edge case: negative zero.
    347  TestEqualsIsForNegativeZero<double>();
    348 
    349  // Int32 values.
    350  auto testInt32 = TestEqualsIsForInt32<double>;
    351  testInt32(0.0);
    352  testInt32(1.0);
    353  testInt32(INT32_MIN);
    354  testInt32(INT32_MAX);
    355 
    356  // Int64 values that don't fit in int32.
    357  auto testInt64 = TestEqualsIsForInt64<double>;
    358  testInt64(2147483648);
    359  testInt64(2147483649);
    360  testInt64(-2147483649);
    361  testInt64(INT64_MIN);
    362  // Note: INT64_MAX can't be represented exactly as double. Use a large double
    363  // very close to it.
    364  testInt64(9223372036854772000.0);
    365 
    366  constexpr double MinSafeInteger = -9007199254740991.0;
    367  constexpr double MaxSafeInteger = 9007199254740991.0;
    368  testInt64(MinSafeInteger);
    369  testInt64(MaxSafeInteger);
    370 
    371  // Doubles that aren't equal to any int32 or int64.
    372  auto testNonInteger = TestEqualsIsForNonInteger<double>;
    373  testNonInteger(NegativeInfinity<double>());
    374  testNonInteger(PositiveInfinity<double>());
    375  testNonInteger(UnspecifiedNaN<double>());
    376  testNonInteger(-double(1ULL << 52) + 0.5);
    377  testNonInteger(double(1ULL << 52) - 0.5);
    378  testNonInteger(double(INT32_MAX) + 0.1);
    379  testNonInteger(double(INT32_MIN) - 0.1);
    380  testNonInteger(0.5);
    381  testNonInteger(-0.0001);
    382  testNonInteger(-9223372036854778000.0);
    383  testNonInteger(9223372036854776000.0);
    384 
    385  // Sanity-check that the IEEE-754 double-precision-derived literals used in
    386  // testing here work as we intend them to.
    387  A(exp2(-1075.0) == 0.0);
    388  A(exp2(-1074.0) != 0.0);
    389  testNonInteger(exp2(-1074.0));
    390  testNonInteger(2 * exp2(-1074.0));
    391 
    392  A(1.0 - exp2(-54.0) == 1.0);
    393  A(1.0 - exp2(-53.0) != 1.0);
    394  testNonInteger(1.0 - exp2(-53.0));
    395  testNonInteger(1.0 - exp2(-52.0));
    396 
    397  A(1.0 + exp2(-53.0) == 1.0f);
    398  A(1.0 + exp2(-52.0) != 1.0f);
    399  testNonInteger(1.0 + exp2(-52.0));
    400 }
    401 
    402 static void TestFloatsPredicates() {
    403  A(std::isnan(UnspecifiedNaN<float>()));
    404  A(std::isnan(SpecificNaN<float>(1, 17)));
    405  ;
    406  A(std::isnan(SpecificNaN<float>(0, 0x7fff0fUL)));
    407  A(!std::isnan(PositiveInfinity<float>()));
    408  A(!std::isnan(NegativeInfinity<float>()));
    409 
    410  A(std::isinf(PositiveInfinity<float>()));
    411  A(std::isinf(NegativeInfinity<float>()));
    412  A(!std::isinf(UnspecifiedNaN<float>()));
    413 
    414  A(!std::isfinite(PositiveInfinity<float>()));
    415  A(!std::isfinite(NegativeInfinity<float>()));
    416  A(!std::isfinite(UnspecifiedNaN<float>()));
    417 
    418  A(!IsNegative(PositiveInfinity<float>()));
    419  A(IsNegative(NegativeInfinity<float>()));
    420  A(IsNegative(-0.0f));
    421  A(!IsNegative(0.0f));
    422  A(IsNegative(-1.0f));
    423  A(!IsNegative(1.0f));
    424 
    425  A(!IsNegativeZero(PositiveInfinity<float>()));
    426  A(!IsNegativeZero(NegativeInfinity<float>()));
    427  A(!IsNegativeZero(SpecificNaN<float>(1, 17)));
    428  ;
    429  A(!IsNegativeZero(SpecificNaN<float>(1, 0x7fff0fUL)));
    430  A(!IsNegativeZero(SpecificNaN<float>(0, 17)));
    431  ;
    432  A(!IsNegativeZero(SpecificNaN<float>(0, 0x7fff0fUL)));
    433  A(!IsNegativeZero(UnspecifiedNaN<float>()));
    434  A(IsNegativeZero(-0.0f));
    435  A(!IsNegativeZero(0.0f));
    436  A(!IsNegativeZero(-1.0f));
    437  A(!IsNegativeZero(1.0f));
    438 
    439  A(!IsPositiveZero(PositiveInfinity<float>()));
    440  A(!IsPositiveZero(NegativeInfinity<float>()));
    441  A(!IsPositiveZero(SpecificNaN<float>(1, 17)));
    442  ;
    443  A(!IsPositiveZero(SpecificNaN<float>(1, 0x7fff0fUL)));
    444  A(!IsPositiveZero(SpecificNaN<float>(0, 17)));
    445  ;
    446  A(!IsPositiveZero(SpecificNaN<float>(0, 0x7fff0fUL)));
    447  A(!IsPositiveZero(UnspecifiedNaN<float>()));
    448  A(IsPositiveZero(0.0f));
    449  A(!IsPositiveZero(-0.0f));
    450  A(!IsPositiveZero(-1.0f));
    451  A(!IsPositiveZero(1.0f));
    452 
    453  // Edge case: negative zero.
    454  TestEqualsIsForNegativeZero<float>();
    455 
    456  // Int32 values.
    457  auto testInt32 = TestEqualsIsForInt32<float>;
    458  testInt32(0.0f);
    459  testInt32(1.0f);
    460  testInt32(INT32_MIN);
    461  testInt32(float(2147483648 - 128));  // max int32_t fitting in float
    462  const int32_t BIG = 2097151;
    463  testInt32(BIG);
    464 
    465  // Int64 values that don't fit in int32.
    466  auto testInt64 = TestEqualsIsForInt64<float>;
    467  testInt64(INT64_MIN);
    468  testInt64(9007199254740992.0f);
    469  testInt64(-float(2147483648) - 256);
    470  testInt64(float(2147483648));
    471  testInt64(float(2147483648) + 256);
    472 
    473  // Floats that aren't equal to any int32 or int64.
    474  auto testNonInteger = TestEqualsIsForNonInteger<float>;
    475  testNonInteger(NegativeInfinity<float>());
    476  testNonInteger(PositiveInfinity<float>());
    477  testNonInteger(UnspecifiedNaN<float>());
    478  testNonInteger(0.5f);
    479  testNonInteger(1.5f);
    480  testNonInteger(-0.0001f);
    481  testNonInteger(-19223373116872850000.0f);
    482  testNonInteger(19223373116872850000.0f);
    483  testNonInteger(float(BIG) + 0.1f);
    484 
    485  A(powf(2.0f, -150.0f) == 0.0f);
    486  A(powf(2.0f, -149.0f) != 0.0f);
    487  testNonInteger(powf(2.0f, -149.0f));
    488  testNonInteger(2 * powf(2.0f, -149.0f));
    489 
    490  A(1.0f - powf(2.0f, -25.0f) == 1.0f);
    491  A(1.0f - powf(2.0f, -24.0f) != 1.0f);
    492  testNonInteger(1.0f - powf(2.0f, -24.0f));
    493  testNonInteger(1.0f - powf(2.0f, -23.0f));
    494 
    495  A(1.0f + powf(2.0f, -24.0f) == 1.0f);
    496  A(1.0f + powf(2.0f, -23.0f) != 1.0f);
    497  testNonInteger(1.0f + powf(2.0f, -23.0f));
    498 }
    499 
    500 static void TestPredicates() {
    501  TestFloatsPredicates();
    502  TestDoublesPredicates();
    503 }
    504 
    505 static void TestFloatsAreApproximatelyEqual() {
    506  float epsilon = mozilla::detail::FuzzyEqualsEpsilon<float>::value();
    507  float lessThanEpsilon = epsilon / 2.0f;
    508  float moreThanEpsilon = epsilon * 2.0f;
    509 
    510  // Additive tests using the default epsilon
    511  // ... around 1.0
    512  A(FuzzyEqualsAdditive(1.0f, 1.0f + lessThanEpsilon));
    513  A(FuzzyEqualsAdditive(1.0f, 1.0f - lessThanEpsilon));
    514  A(FuzzyEqualsAdditive(1.0f, 1.0f + epsilon));
    515  A(FuzzyEqualsAdditive(1.0f, 1.0f - epsilon));
    516  A(!FuzzyEqualsAdditive(1.0f, 1.0f + moreThanEpsilon));
    517  A(!FuzzyEqualsAdditive(1.0f, 1.0f - moreThanEpsilon));
    518  // ... around 1.0e2 (this is near the upper bound of the range where
    519  // adding moreThanEpsilon will still be representable and return false)
    520  A(FuzzyEqualsAdditive(1.0e2f, 1.0e2f + lessThanEpsilon));
    521  A(FuzzyEqualsAdditive(1.0e2f, 1.0e2f + epsilon));
    522  A(!FuzzyEqualsAdditive(1.0e2f, 1.0e2f + moreThanEpsilon));
    523  // ... around 1.0e-10
    524  A(FuzzyEqualsAdditive(1.0e-10f, 1.0e-10f + lessThanEpsilon));
    525  A(FuzzyEqualsAdditive(1.0e-10f, 1.0e-10f + epsilon));
    526  A(!FuzzyEqualsAdditive(1.0e-10f, 1.0e-10f + moreThanEpsilon));
    527  // ... straddling 0
    528  A(FuzzyEqualsAdditive(1.0e-6f, -1.0e-6f));
    529  A(!FuzzyEqualsAdditive(1.0e-5f, -1.0e-5f));
    530  // Using a small epsilon
    531  A(FuzzyEqualsAdditive(1.0e-5f, 1.0e-5f + 1.0e-10f, 1.0e-9f));
    532  A(!FuzzyEqualsAdditive(1.0e-5f, 1.0e-5f + 1.0e-10f, 1.0e-11f));
    533  // Using a big epsilon
    534  A(FuzzyEqualsAdditive(1.0e20f, 1.0e20f + 1.0e15f, 1.0e16f));
    535  A(!FuzzyEqualsAdditive(1.0e20f, 1.0e20f + 1.0e15f, 1.0e14f));
    536 
    537  // Multiplicative tests using the default epsilon
    538  // ... around 1.0
    539  A(FuzzyEqualsMultiplicative(1.0f, 1.0f + lessThanEpsilon));
    540  A(FuzzyEqualsMultiplicative(1.0f, 1.0f - lessThanEpsilon));
    541  A(FuzzyEqualsMultiplicative(1.0f, 1.0f + epsilon));
    542  A(!FuzzyEqualsMultiplicative(1.0f, 1.0f - epsilon));
    543  A(!FuzzyEqualsMultiplicative(1.0f, 1.0f + moreThanEpsilon));
    544  A(!FuzzyEqualsMultiplicative(1.0f, 1.0f - moreThanEpsilon));
    545  // ... around 1.0e10
    546  A(FuzzyEqualsMultiplicative(1.0e10f, 1.0e10f + (lessThanEpsilon * 1.0e10f)));
    547  A(!FuzzyEqualsMultiplicative(1.0e10f, 1.0e10f + (moreThanEpsilon * 1.0e10f)));
    548  // ... around 1.0e-10
    549  A(FuzzyEqualsMultiplicative(1.0e-10f,
    550                              1.0e-10f + (lessThanEpsilon * 1.0e-10f)));
    551  A(!FuzzyEqualsMultiplicative(1.0e-10f,
    552                               1.0e-10f + (moreThanEpsilon * 1.0e-10f)));
    553  // ... straddling 0
    554  A(!FuzzyEqualsMultiplicative(1.0e-6f, -1.0e-6f));
    555  A(FuzzyEqualsMultiplicative(1.0e-6f, -1.0e-6f, 1.0e2f));
    556  // Using a small epsilon
    557  A(FuzzyEqualsMultiplicative(1.0e-5f, 1.0e-5f + 1.0e-10f, 1.0e-4f));
    558  A(!FuzzyEqualsMultiplicative(1.0e-5f, 1.0e-5f + 1.0e-10f, 1.0e-5f));
    559  // Using a big epsilon
    560  A(FuzzyEqualsMultiplicative(1.0f, 2.0f, 1.0f));
    561  A(!FuzzyEqualsMultiplicative(1.0f, 2.0f, 0.1f));
    562 
    563  // "real world case"
    564  float oneThird = 10.0f / 3.0f;
    565  A(FuzzyEqualsAdditive(10.0f, 3.0f * oneThird));
    566  A(FuzzyEqualsMultiplicative(10.0f, 3.0f * oneThird));
    567  // NaN check
    568  A(!FuzzyEqualsAdditive(SpecificNaN<float>(1, 1), SpecificNaN<float>(1, 1)));
    569  A(!FuzzyEqualsAdditive(SpecificNaN<float>(1, 2), SpecificNaN<float>(0, 8)));
    570  A(!FuzzyEqualsMultiplicative(SpecificNaN<float>(1, 1),
    571                               SpecificNaN<float>(1, 1)));
    572  A(!FuzzyEqualsMultiplicative(SpecificNaN<float>(1, 2),
    573                               SpecificNaN<float>(0, 200)));
    574 }
    575 
    576 static void TestDoublesAreApproximatelyEqual() {
    577  double epsilon = mozilla::detail::FuzzyEqualsEpsilon<double>::value();
    578  double lessThanEpsilon = epsilon / 2.0;
    579  double moreThanEpsilon = epsilon * 2.0;
    580 
    581  // Additive tests using the default epsilon
    582  // ... around 1.0
    583  A(FuzzyEqualsAdditive(1.0, 1.0 + lessThanEpsilon));
    584  A(FuzzyEqualsAdditive(1.0, 1.0 - lessThanEpsilon));
    585  A(FuzzyEqualsAdditive(1.0, 1.0 + epsilon));
    586  A(FuzzyEqualsAdditive(1.0, 1.0 - epsilon));
    587  A(!FuzzyEqualsAdditive(1.0, 1.0 + moreThanEpsilon));
    588  A(!FuzzyEqualsAdditive(1.0, 1.0 - moreThanEpsilon));
    589  // ... around 1.0e4 (this is near the upper bound of the range where
    590  // adding moreThanEpsilon will still be representable and return false)
    591  A(FuzzyEqualsAdditive(1.0e4, 1.0e4 + lessThanEpsilon));
    592  A(FuzzyEqualsAdditive(1.0e4, 1.0e4 + epsilon));
    593  A(!FuzzyEqualsAdditive(1.0e4, 1.0e4 + moreThanEpsilon));
    594  // ... around 1.0e-25
    595  A(FuzzyEqualsAdditive(1.0e-25, 1.0e-25 + lessThanEpsilon));
    596  A(FuzzyEqualsAdditive(1.0e-25, 1.0e-25 + epsilon));
    597  A(!FuzzyEqualsAdditive(1.0e-25, 1.0e-25 + moreThanEpsilon));
    598  // ... straddling 0
    599  A(FuzzyEqualsAdditive(1.0e-13, -1.0e-13));
    600  A(!FuzzyEqualsAdditive(1.0e-12, -1.0e-12));
    601  // Using a small epsilon
    602  A(FuzzyEqualsAdditive(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-29));
    603  A(!FuzzyEqualsAdditive(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-31));
    604  // Using a big epsilon
    605  A(FuzzyEqualsAdditive(1.0e40, 1.0e40 + 1.0e25, 1.0e26));
    606  A(!FuzzyEqualsAdditive(1.0e40, 1.0e40 + 1.0e25, 1.0e24));
    607 
    608  // Multiplicative tests using the default epsilon
    609  // ... around 1.0
    610  A(FuzzyEqualsMultiplicative(1.0, 1.0 + lessThanEpsilon));
    611  A(FuzzyEqualsMultiplicative(1.0, 1.0 - lessThanEpsilon));
    612  A(FuzzyEqualsMultiplicative(1.0, 1.0 + epsilon));
    613  A(!FuzzyEqualsMultiplicative(1.0, 1.0 - epsilon));
    614  A(!FuzzyEqualsMultiplicative(1.0, 1.0 + moreThanEpsilon));
    615  A(!FuzzyEqualsMultiplicative(1.0, 1.0 - moreThanEpsilon));
    616  // ... around 1.0e30
    617  A(FuzzyEqualsMultiplicative(1.0e30, 1.0e30 + (lessThanEpsilon * 1.0e30)));
    618  A(!FuzzyEqualsMultiplicative(1.0e30, 1.0e30 + (moreThanEpsilon * 1.0e30)));
    619  // ... around 1.0e-30
    620  A(FuzzyEqualsMultiplicative(1.0e-30, 1.0e-30 + (lessThanEpsilon * 1.0e-30)));
    621  A(!FuzzyEqualsMultiplicative(1.0e-30, 1.0e-30 + (moreThanEpsilon * 1.0e-30)));
    622  // ... straddling 0
    623  A(!FuzzyEqualsMultiplicative(1.0e-6, -1.0e-6));
    624  A(FuzzyEqualsMultiplicative(1.0e-6, -1.0e-6, 1.0e2));
    625  // Using a small epsilon
    626  A(FuzzyEqualsMultiplicative(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-15));
    627  A(!FuzzyEqualsMultiplicative(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-16));
    628  // Using a big epsilon
    629  A(FuzzyEqualsMultiplicative(1.0e40, 2.0e40, 1.0));
    630  A(!FuzzyEqualsMultiplicative(1.0e40, 2.0e40, 0.1));
    631 
    632  // "real world case"
    633  double oneThird = 10.0 / 3.0;
    634  A(FuzzyEqualsAdditive(10.0, 3.0 * oneThird));
    635  A(FuzzyEqualsMultiplicative(10.0, 3.0 * oneThird));
    636  // NaN check
    637  A(!FuzzyEqualsAdditive(SpecificNaN<double>(1, 1), SpecificNaN<double>(1, 1)));
    638  A(!FuzzyEqualsAdditive(SpecificNaN<double>(1, 2), SpecificNaN<double>(0, 8)));
    639  A(!FuzzyEqualsMultiplicative(SpecificNaN<double>(1, 1),
    640                               SpecificNaN<double>(1, 1)));
    641  A(!FuzzyEqualsMultiplicative(SpecificNaN<double>(1, 2),
    642                               SpecificNaN<double>(0, 200)));
    643 }
    644 
    645 static void TestAreApproximatelyEqual() {
    646  TestFloatsAreApproximatelyEqual();
    647  TestDoublesAreApproximatelyEqual();
    648 }
    649 
    650 static void TestIsFloat32Representable() {
    651  // Zeroes are representable.
    652  A(IsFloat32Representable(+0.0));
    653  A(IsFloat32Representable(-0.0));
    654 
    655  // NaN and infinities are representable.
    656  A(IsFloat32Representable(UnspecifiedNaN<double>()));
    657  A(IsFloat32Representable(SpecificNaN<double>(0, 1)));
    658  A(IsFloat32Representable(SpecificNaN<double>(0, 71389)));
    659  A(IsFloat32Representable(SpecificNaN<double>(0, (uint64_t(1) << 52) - 2)));
    660  A(IsFloat32Representable(SpecificNaN<double>(1, 1)));
    661  A(IsFloat32Representable(SpecificNaN<double>(1, 71389)));
    662  A(IsFloat32Representable(SpecificNaN<double>(1, (uint64_t(1) << 52) - 2)));
    663  A(IsFloat32Representable(PositiveInfinity<double>()));
    664  A(IsFloat32Representable(NegativeInfinity<double>()));
    665 
    666  // Sanity-check that the IEEE-754 double-precision-derived literals used in
    667  // testing here work as we intend them to.
    668  A(exp2(-1075.0) == 0.0);
    669  A(exp2(-1074.0) != 0.0);
    670 
    671  for (double littleExp = -1074.0; littleExp < -149.0; littleExp++) {
    672    // Powers of two representable as doubles but not as floats aren't
    673    // representable.
    674    A(!IsFloat32Representable(exp2(littleExp)));
    675  }
    676 
    677  // Sanity-check that the IEEE-754 single-precision-derived literals used in
    678  // testing here work as we intend them to.
    679  A(exp2f(-150.0f) == 0.0);
    680  A(exp2f(-149.0f) != 0.0);
    681 
    682  // Exact powers of two within the available range are representable.
    683  for (double exponent = -149.0; exponent < 128.0; exponent++) {
    684    A(IsFloat32Representable(exp2(exponent)));
    685  }
    686 
    687  // Powers of two above the available range aren't representable.
    688  for (double bigExp = 128.0; bigExp < 1024.0; bigExp++) {
    689    A(!IsFloat32Representable(exp2(bigExp)));
    690  }
    691 
    692  // Various denormal (i.e. super-small) doubles with MSB and LSB as far apart
    693  // as possible are representable (but taken one bit further apart are not
    694  // representable).
    695  //
    696  // Note that the final iteration tests non-denormal with exponent field
    697  // containing (biased) 1, as |oneTooSmall| and |widestPossible| happen still
    698  // to be correct for that exponent due to the extra bit of precision in the
    699  // implicit-one bit.
    700  double oneTooSmall = exp2(-150.0);
    701  for (double denormExp = -149.0;
    702       denormExp < 1 - double(FloatingPoint<double>::kExponentBias) + 1;
    703       denormExp++) {
    704    double baseDenorm = exp2(denormExp);
    705    double tooWide = baseDenorm + oneTooSmall;
    706    A(!IsFloat32Representable(tooWide));
    707 
    708    double widestPossible = baseDenorm;
    709    if (oneTooSmall * 2.0 != baseDenorm) {
    710      widestPossible += oneTooSmall * 2.0;
    711    }
    712 
    713    A(IsFloat32Representable(widestPossible));
    714  }
    715 
    716  // Finally, check certain interesting/special values for basic sanity.
    717  A(!IsFloat32Representable(2147483647.0));
    718  A(!IsFloat32Representable(-2147483647.0));
    719 }
    720 
    721 #undef A
    722 
    723 int main() {
    724  TestAreIdentical();
    725  TestExponentComponent();
    726  TestPredicates();
    727  TestAreApproximatelyEqual();
    728  TestIsFloat32Representable();
    729  return 0;
    730 }