mfbt/tests/TestFloatingPoint.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     4  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "mozilla/FloatingPoint.h"
     8 #include <math.h>
    10 using mozilla::ExponentComponent;
    11 using mozilla::FloatingPoint;
    12 using mozilla::FuzzyEqualsAdditive;
    13 using mozilla::FuzzyEqualsMultiplicative;
    14 using mozilla::IsFinite;
    15 using mozilla::IsInfinite;
    16 using mozilla::IsNaN;
    17 using mozilla::IsNegative;
    18 using mozilla::IsNegativeZero;
    19 using mozilla::NegativeInfinity;
    20 using mozilla::NumberEqualsInt32;
    21 using mozilla::NumberIsInt32;
    22 using mozilla::NumbersAreIdentical;
    23 using mozilla::PositiveInfinity;
    24 using mozilla::SpecificNaN;
    25 using mozilla::UnspecifiedNaN;
    27 template<typename T>
    28 static void
    29 ShouldBeIdentical(T d1, T d2)
    30 {
    31   MOZ_RELEASE_ASSERT(NumbersAreIdentical(d1, d2));
    32   MOZ_RELEASE_ASSERT(NumbersAreIdentical(d2, d1));
    33 }
    35 template<typename T>
    36 static void
    37 ShouldNotBeIdentical(T d1, T d2)
    38 {
    39   MOZ_RELEASE_ASSERT(!NumbersAreIdentical(d1, d2));
    40   MOZ_RELEASE_ASSERT(!NumbersAreIdentical(d2, d1));
    41 }
    43 static void
    44 TestDoublesAreIdentical()
    45 {
    46   ShouldBeIdentical(+0.0, +0.0);
    47   ShouldBeIdentical(-0.0, -0.0);
    48   ShouldNotBeIdentical(+0.0, -0.0);
    50   ShouldBeIdentical(1.0, 1.0);
    51   ShouldNotBeIdentical(-1.0, 1.0);
    52   ShouldBeIdentical(4294967295.0, 4294967295.0);
    53   ShouldNotBeIdentical(-4294967295.0, 4294967295.0);
    54   ShouldBeIdentical(4294967296.0, 4294967296.0);
    55   ShouldBeIdentical(4294967297.0, 4294967297.0);
    56   ShouldBeIdentical(1e300, 1e300);
    58   ShouldBeIdentical(PositiveInfinity<double>(), PositiveInfinity<double>());
    59   ShouldBeIdentical(NegativeInfinity<double>(), NegativeInfinity<double>());
    60   ShouldNotBeIdentical(PositiveInfinity<double>(), NegativeInfinity<double>());
    62   ShouldNotBeIdentical(-0.0, NegativeInfinity<double>());
    63   ShouldNotBeIdentical(+0.0, NegativeInfinity<double>());
    64   ShouldNotBeIdentical(1e300, NegativeInfinity<double>());
    65   ShouldNotBeIdentical(3.141592654, NegativeInfinity<double>());
    67   ShouldBeIdentical(UnspecifiedNaN<double>(), UnspecifiedNaN<double>());
    68   ShouldBeIdentical(-UnspecifiedNaN<double>(), UnspecifiedNaN<double>());
    69   ShouldBeIdentical(UnspecifiedNaN<double>(), -UnspecifiedNaN<double>());
    71   ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 42));
    72   ShouldBeIdentical(SpecificNaN<double>(1, 17), SpecificNaN<double>(1, 42));
    73   ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(1, 42));
    74   ShouldBeIdentical(SpecificNaN<double>(1, 17), SpecificNaN<double>(0, 42));
    76   const uint64_t Mask = 0xfffffffffffffULL;
    77   for (unsigned i = 0; i < 52; i++) {
    78     for (unsigned j = 0; j < 52; j++) {
    79       for (unsigned sign = 0; i < 2; i++) {
    80         ShouldBeIdentical(SpecificNaN<double>(0, 1ULL << i), SpecificNaN<double>(sign, 1ULL << j));
    81         ShouldBeIdentical(SpecificNaN<double>(1, 1ULL << i), SpecificNaN<double>(sign, 1ULL << j));
    83         ShouldBeIdentical(SpecificNaN<double>(0, Mask & ~(1ULL << i)),
    84                           SpecificNaN<double>(sign, Mask & ~(1ULL << j)));
    85         ShouldBeIdentical(SpecificNaN<double>(1, Mask & ~(1ULL << i)),
    86                           SpecificNaN<double>(sign, Mask & ~(1ULL << j)));
    87       }
    88     }
    89   }
    90   ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x8000000000000ULL));
    91   ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x4000000000000ULL));
    92   ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x2000000000000ULL));
    93   ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x1000000000000ULL));
    94   ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x0800000000000ULL));
    95   ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x0400000000000ULL));
    96   ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x0200000000000ULL));
    97   ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x0100000000000ULL));
    98   ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x0080000000000ULL));
    99   ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x0040000000000ULL));
   100   ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x0020000000000ULL));
   101   ShouldBeIdentical(SpecificNaN<double>(0, 17), SpecificNaN<double>(0, 0x0010000000000ULL));
   102   ShouldBeIdentical(SpecificNaN<double>(1, 17), SpecificNaN<double>(0, 0xff0ffffffffffULL));
   103   ShouldBeIdentical(SpecificNaN<double>(1, 17), SpecificNaN<double>(0, 0xfffffffffff0fULL));
   105   ShouldNotBeIdentical(UnspecifiedNaN<double>(), +0.0);
   106   ShouldNotBeIdentical(UnspecifiedNaN<double>(), -0.0);
   107   ShouldNotBeIdentical(UnspecifiedNaN<double>(), 1.0);
   108   ShouldNotBeIdentical(UnspecifiedNaN<double>(), -1.0);
   109   ShouldNotBeIdentical(UnspecifiedNaN<double>(), PositiveInfinity<double>());
   110   ShouldNotBeIdentical(UnspecifiedNaN<double>(), NegativeInfinity<double>());
   111 }
   113 static void
   114 TestFloatsAreIdentical()
   115 {
   116   ShouldBeIdentical(+0.0f, +0.0f);
   117   ShouldBeIdentical(-0.0f, -0.0f);
   118   ShouldNotBeIdentical(+0.0f, -0.0f);
   120   ShouldBeIdentical(1.0f, 1.0f);
   121   ShouldNotBeIdentical(-1.0f, 1.0f);
   122   ShouldBeIdentical(8388607.0f, 8388607.0f);
   123   ShouldNotBeIdentical(-8388607.0f, 8388607.0f);
   124   ShouldBeIdentical(8388608.0f, 8388608.0f);
   125   ShouldBeIdentical(8388609.0f, 8388609.0f);
   126   ShouldBeIdentical(1e36f, 1e36f);
   128   ShouldBeIdentical(PositiveInfinity<float>(), PositiveInfinity<float>());
   129   ShouldBeIdentical(NegativeInfinity<float>(), NegativeInfinity<float>());
   130   ShouldNotBeIdentical(PositiveInfinity<float>(), NegativeInfinity<float>());
   132   ShouldNotBeIdentical(-0.0f, NegativeInfinity<float>());
   133   ShouldNotBeIdentical(+0.0f, NegativeInfinity<float>());
   134   ShouldNotBeIdentical(1e36f, NegativeInfinity<float>());
   135   ShouldNotBeIdentical(3.141592654f, NegativeInfinity<float>());
   137   ShouldBeIdentical(UnspecifiedNaN<float>(), UnspecifiedNaN<float>());
   138   ShouldBeIdentical(-UnspecifiedNaN<float>(), UnspecifiedNaN<float>());
   139   ShouldBeIdentical(UnspecifiedNaN<float>(), -UnspecifiedNaN<float>());
   141   ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 42));
   142   ShouldBeIdentical(SpecificNaN<float>(1, 17), SpecificNaN<float>(1, 42));
   143   ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(1, 42));
   144   ShouldBeIdentical(SpecificNaN<float>(1, 17), SpecificNaN<float>(0, 42));
   146   const uint32_t Mask = 0x7fffffUL;
   147   for (unsigned i = 0; i < 23; i++) {
   148     for (unsigned j = 0; j < 23; j++) {
   149       for (unsigned sign = 0; i < 2; i++) {
   150         ShouldBeIdentical(SpecificNaN<float>(0, 1UL << i), SpecificNaN<float>(sign, 1UL << j));
   151         ShouldBeIdentical(SpecificNaN<float>(1, 1UL << i), SpecificNaN<float>(sign, 1UL << j));
   153         ShouldBeIdentical(SpecificNaN<float>(0, Mask & ~(1UL << i)),
   154                           SpecificNaN<float>(sign, Mask & ~(1UL << j)));
   155         ShouldBeIdentical(SpecificNaN<float>(1, Mask & ~(1UL << i)),
   156                           SpecificNaN<float>(sign, Mask & ~(1UL << j)));
   157       }
   158     }
   159   }
   160   ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x700000));
   161   ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x400000));
   162   ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x200000));
   163   ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x100000));
   164   ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x080000));
   165   ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x040000));
   166   ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x020000));
   167   ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x010000));
   168   ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x008000));
   169   ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x004000));
   170   ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x002000));
   171   ShouldBeIdentical(SpecificNaN<float>(0, 17), SpecificNaN<float>(0, 0x001000));
   172   ShouldBeIdentical(SpecificNaN<float>(1, 17), SpecificNaN<float>(0, 0x7f0fff));
   173   ShouldBeIdentical(SpecificNaN<float>(1, 17), SpecificNaN<float>(0, 0x7fff0f));
   175   ShouldNotBeIdentical(UnspecifiedNaN<float>(), +0.0f);
   176   ShouldNotBeIdentical(UnspecifiedNaN<float>(), -0.0f);
   177   ShouldNotBeIdentical(UnspecifiedNaN<float>(), 1.0f);
   178   ShouldNotBeIdentical(UnspecifiedNaN<float>(), -1.0f);
   179   ShouldNotBeIdentical(UnspecifiedNaN<float>(), PositiveInfinity<float>());
   180   ShouldNotBeIdentical(UnspecifiedNaN<float>(), NegativeInfinity<float>());
   181 }
   183 static void
   184 TestAreIdentical()
   185 {
   186   TestDoublesAreIdentical();
   187   TestFloatsAreIdentical();
   188 }
   190 static void
   191 TestDoubleExponentComponent()
   192 {
   193   MOZ_RELEASE_ASSERT(ExponentComponent(0.0) == -int_fast16_t(FloatingPoint<double>::ExponentBias));
   194   MOZ_RELEASE_ASSERT(ExponentComponent(-0.0) == -int_fast16_t(FloatingPoint<double>::ExponentBias));
   195   MOZ_RELEASE_ASSERT(ExponentComponent(0.125) == -3);
   196   MOZ_RELEASE_ASSERT(ExponentComponent(0.5) == -1);
   197   MOZ_RELEASE_ASSERT(ExponentComponent(1.0) == 0);
   198   MOZ_RELEASE_ASSERT(ExponentComponent(1.5) == 0);
   199   MOZ_RELEASE_ASSERT(ExponentComponent(2.0) == 1);
   200   MOZ_RELEASE_ASSERT(ExponentComponent(7.0) == 2);
   201   MOZ_RELEASE_ASSERT(ExponentComponent(PositiveInfinity<double>()) == FloatingPoint<double>::ExponentBias + 1);
   202   MOZ_RELEASE_ASSERT(ExponentComponent(NegativeInfinity<double>()) == FloatingPoint<double>::ExponentBias + 1);
   203   MOZ_RELEASE_ASSERT(ExponentComponent(UnspecifiedNaN<double>()) == FloatingPoint<double>::ExponentBias + 1);
   204 }
   206 static void
   207 TestFloatExponentComponent()
   208 {
   209   MOZ_RELEASE_ASSERT(ExponentComponent(0.0f) == -int_fast16_t(FloatingPoint<float>::ExponentBias));
   210   MOZ_RELEASE_ASSERT(ExponentComponent(-0.0f) == -int_fast16_t(FloatingPoint<float>::ExponentBias));
   211   MOZ_RELEASE_ASSERT(ExponentComponent(0.125f) == -3);
   212   MOZ_RELEASE_ASSERT(ExponentComponent(0.5f) == -1);
   213   MOZ_RELEASE_ASSERT(ExponentComponent(1.0f) == 0);
   214   MOZ_RELEASE_ASSERT(ExponentComponent(1.5f) == 0);
   215   MOZ_RELEASE_ASSERT(ExponentComponent(2.0f) == 1);
   216   MOZ_RELEASE_ASSERT(ExponentComponent(7.0f) == 2);
   217   MOZ_RELEASE_ASSERT(ExponentComponent(PositiveInfinity<float>()) == FloatingPoint<float>::ExponentBias + 1);
   218   MOZ_RELEASE_ASSERT(ExponentComponent(NegativeInfinity<float>()) == FloatingPoint<float>::ExponentBias + 1);
   219   MOZ_RELEASE_ASSERT(ExponentComponent(UnspecifiedNaN<float>()) == FloatingPoint<float>::ExponentBias + 1);
   220 }
   222 static void
   223 TestExponentComponent()
   224 {
   225   TestDoubleExponentComponent();
   226   TestFloatExponentComponent();
   227 }
   229 static void
   230 TestDoublesPredicates()
   231 {
   232   MOZ_RELEASE_ASSERT(IsNaN(UnspecifiedNaN<double>()));
   233   MOZ_RELEASE_ASSERT(IsNaN(SpecificNaN<double>(1, 17)));;
   234   MOZ_RELEASE_ASSERT(IsNaN(SpecificNaN<double>(0, 0xfffffffffff0fULL)));
   235   MOZ_RELEASE_ASSERT(!IsNaN(0.0));
   236   MOZ_RELEASE_ASSERT(!IsNaN(-0.0));
   237   MOZ_RELEASE_ASSERT(!IsNaN(1.0));
   238   MOZ_RELEASE_ASSERT(!IsNaN(PositiveInfinity<double>()));
   239   MOZ_RELEASE_ASSERT(!IsNaN(NegativeInfinity<double>()));
   241   MOZ_RELEASE_ASSERT(IsInfinite(PositiveInfinity<double>()));
   242   MOZ_RELEASE_ASSERT(IsInfinite(NegativeInfinity<double>()));
   243   MOZ_RELEASE_ASSERT(!IsInfinite(UnspecifiedNaN<double>()));
   244   MOZ_RELEASE_ASSERT(!IsInfinite(0.0));
   245   MOZ_RELEASE_ASSERT(!IsInfinite(-0.0));
   246   MOZ_RELEASE_ASSERT(!IsInfinite(1.0));
   248   MOZ_RELEASE_ASSERT(!IsFinite(PositiveInfinity<double>()));
   249   MOZ_RELEASE_ASSERT(!IsFinite(NegativeInfinity<double>()));
   250   MOZ_RELEASE_ASSERT(!IsFinite(UnspecifiedNaN<double>()));
   251   MOZ_RELEASE_ASSERT(IsFinite(0.0));
   252   MOZ_RELEASE_ASSERT(IsFinite(-0.0));
   253   MOZ_RELEASE_ASSERT(IsFinite(1.0));
   255   MOZ_RELEASE_ASSERT(!IsNegative(PositiveInfinity<double>()));
   256   MOZ_RELEASE_ASSERT(IsNegative(NegativeInfinity<double>()));
   257   MOZ_RELEASE_ASSERT(IsNegative(-0.0));
   258   MOZ_RELEASE_ASSERT(!IsNegative(0.0));
   259   MOZ_RELEASE_ASSERT(IsNegative(-1.0));
   260   MOZ_RELEASE_ASSERT(!IsNegative(1.0));
   262   MOZ_RELEASE_ASSERT(!IsNegativeZero(PositiveInfinity<double>()));
   263   MOZ_RELEASE_ASSERT(!IsNegativeZero(NegativeInfinity<double>()));
   264   MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN<double>(1, 17)));;
   265   MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN<double>(1, 0xfffffffffff0fULL)));
   266   MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN<double>(0, 17)));;
   267   MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN<double>(0, 0xfffffffffff0fULL)));
   268   MOZ_RELEASE_ASSERT(!IsNegativeZero(UnspecifiedNaN<double>()));
   269   MOZ_RELEASE_ASSERT(IsNegativeZero(-0.0));
   270   MOZ_RELEASE_ASSERT(!IsNegativeZero(0.0));
   271   MOZ_RELEASE_ASSERT(!IsNegativeZero(-1.0));
   272   MOZ_RELEASE_ASSERT(!IsNegativeZero(1.0));
   274   int32_t i;
   275   MOZ_RELEASE_ASSERT(NumberIsInt32(0.0, &i)); MOZ_RELEASE_ASSERT(i == 0);
   276   MOZ_RELEASE_ASSERT(!NumberIsInt32(-0.0, &i));
   277   MOZ_RELEASE_ASSERT(NumberEqualsInt32(0.0, &i)); MOZ_RELEASE_ASSERT(i == 0);
   278   MOZ_RELEASE_ASSERT(NumberEqualsInt32(-0.0, &i)); MOZ_RELEASE_ASSERT(i == 0);
   279   MOZ_RELEASE_ASSERT(NumberIsInt32(double(INT32_MIN), &i)); MOZ_RELEASE_ASSERT(i == INT32_MIN);
   280   MOZ_RELEASE_ASSERT(NumberIsInt32(double(INT32_MAX), &i)); MOZ_RELEASE_ASSERT(i == INT32_MAX);
   281   MOZ_RELEASE_ASSERT(NumberEqualsInt32(double(INT32_MIN), &i)); MOZ_RELEASE_ASSERT(i == INT32_MIN);
   282   MOZ_RELEASE_ASSERT(NumberEqualsInt32(double(INT32_MAX), &i)); MOZ_RELEASE_ASSERT(i == INT32_MAX);
   283   MOZ_RELEASE_ASSERT(!NumberIsInt32(0.5, &i));
   284   MOZ_RELEASE_ASSERT(!NumberIsInt32(double(INT32_MAX) + 0.1, &i));
   285   MOZ_RELEASE_ASSERT(!NumberIsInt32(double(INT32_MIN) - 0.1, &i));
   286   MOZ_RELEASE_ASSERT(!NumberIsInt32(NegativeInfinity<double>(), &i));
   287   MOZ_RELEASE_ASSERT(!NumberIsInt32(PositiveInfinity<double>(), &i));
   288   MOZ_RELEASE_ASSERT(!NumberIsInt32(UnspecifiedNaN<double>(), &i));
   289   MOZ_RELEASE_ASSERT(!NumberEqualsInt32(0.5, &i));
   290   MOZ_RELEASE_ASSERT(!NumberEqualsInt32(double(INT32_MAX) + 0.1, &i));
   291   MOZ_RELEASE_ASSERT(!NumberEqualsInt32(double(INT32_MIN) - 0.1, &i));
   292   MOZ_RELEASE_ASSERT(!NumberEqualsInt32(NegativeInfinity<double>(), &i));
   293   MOZ_RELEASE_ASSERT(!NumberEqualsInt32(PositiveInfinity<double>(), &i));
   294   MOZ_RELEASE_ASSERT(!NumberEqualsInt32(UnspecifiedNaN<double>(), &i));
   295 }
   297 static void
   298 TestFloatsPredicates()
   299 {
   300   MOZ_RELEASE_ASSERT(IsNaN(UnspecifiedNaN<float>()));
   301   MOZ_RELEASE_ASSERT(IsNaN(SpecificNaN<float>(1, 17)));;
   302   MOZ_RELEASE_ASSERT(IsNaN(SpecificNaN<float>(0, 0x7fff0fUL)));
   303   MOZ_RELEASE_ASSERT(!IsNaN(0.0f));
   304   MOZ_RELEASE_ASSERT(!IsNaN(-0.0f));
   305   MOZ_RELEASE_ASSERT(!IsNaN(1.0f));
   306   MOZ_RELEASE_ASSERT(!IsNaN(PositiveInfinity<float>()));
   307   MOZ_RELEASE_ASSERT(!IsNaN(NegativeInfinity<float>()));
   309   MOZ_RELEASE_ASSERT(IsInfinite(PositiveInfinity<float>()));
   310   MOZ_RELEASE_ASSERT(IsInfinite(NegativeInfinity<float>()));
   311   MOZ_RELEASE_ASSERT(!IsInfinite(UnspecifiedNaN<float>()));
   312   MOZ_RELEASE_ASSERT(!IsInfinite(0.0f));
   313   MOZ_RELEASE_ASSERT(!IsInfinite(-0.0f));
   314   MOZ_RELEASE_ASSERT(!IsInfinite(1.0f));
   316   MOZ_RELEASE_ASSERT(!IsFinite(PositiveInfinity<float>()));
   317   MOZ_RELEASE_ASSERT(!IsFinite(NegativeInfinity<float>()));
   318   MOZ_RELEASE_ASSERT(!IsFinite(UnspecifiedNaN<float>()));
   319   MOZ_RELEASE_ASSERT(IsFinite(0.0f));
   320   MOZ_RELEASE_ASSERT(IsFinite(-0.0f));
   321   MOZ_RELEASE_ASSERT(IsFinite(1.0f));
   323   MOZ_RELEASE_ASSERT(!IsNegative(PositiveInfinity<float>()));
   324   MOZ_RELEASE_ASSERT(IsNegative(NegativeInfinity<float>()));
   325   MOZ_RELEASE_ASSERT(IsNegative(-0.0f));
   326   MOZ_RELEASE_ASSERT(!IsNegative(0.0f));
   327   MOZ_RELEASE_ASSERT(IsNegative(-1.0f));
   328   MOZ_RELEASE_ASSERT(!IsNegative(1.0f));
   330   MOZ_RELEASE_ASSERT(!IsNegativeZero(PositiveInfinity<float>()));
   331   MOZ_RELEASE_ASSERT(!IsNegativeZero(NegativeInfinity<float>()));
   332   MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN<float>(1, 17)));;
   333   MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN<float>(1, 0x7fff0fUL)));
   334   MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN<float>(0, 17)));;
   335   MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN<float>(0, 0x7fff0fUL)));
   336   MOZ_RELEASE_ASSERT(!IsNegativeZero(UnspecifiedNaN<float>()));
   337   MOZ_RELEASE_ASSERT(IsNegativeZero(-0.0f));
   338   MOZ_RELEASE_ASSERT(!IsNegativeZero(0.0f));
   339   MOZ_RELEASE_ASSERT(!IsNegativeZero(-1.0f));
   340   MOZ_RELEASE_ASSERT(!IsNegativeZero(1.0f));
   342   int32_t i;
   343   const int32_t BIG = 2097151;
   344   MOZ_RELEASE_ASSERT(NumberIsInt32(0.0f, &i)); MOZ_RELEASE_ASSERT(i == 0);
   345   MOZ_RELEASE_ASSERT(!NumberIsInt32(-0.0f, &i));
   346   MOZ_RELEASE_ASSERT(NumberEqualsInt32(0.0f, &i)); MOZ_RELEASE_ASSERT(i == 0);
   347   MOZ_RELEASE_ASSERT(NumberEqualsInt32(-0.0f, &i)); MOZ_RELEASE_ASSERT(i == 0);
   348   MOZ_RELEASE_ASSERT(NumberIsInt32(float(INT32_MIN), &i)); MOZ_RELEASE_ASSERT(i == INT32_MIN);
   349   MOZ_RELEASE_ASSERT(NumberIsInt32(float(BIG), &i)); MOZ_RELEASE_ASSERT(i == BIG);
   350   MOZ_RELEASE_ASSERT(NumberEqualsInt32(float(INT32_MIN), &i)); MOZ_RELEASE_ASSERT(i == INT32_MIN);
   351   MOZ_RELEASE_ASSERT(NumberEqualsInt32(float(BIG), &i)); MOZ_RELEASE_ASSERT(i == BIG);
   352   MOZ_RELEASE_ASSERT(!NumberIsInt32(0.5f, &i));
   353   MOZ_RELEASE_ASSERT(!NumberIsInt32(float(BIG) + 0.1f, &i));
   354   MOZ_RELEASE_ASSERT(!NumberIsInt32(NegativeInfinity<float>(), &i));
   355   MOZ_RELEASE_ASSERT(!NumberIsInt32(PositiveInfinity<float>(), &i));
   356   MOZ_RELEASE_ASSERT(!NumberIsInt32(UnspecifiedNaN<float>(), &i));
   357   MOZ_RELEASE_ASSERT(!NumberEqualsInt32(0.5f, &i));
   358   MOZ_RELEASE_ASSERT(!NumberEqualsInt32(float(BIG) + 0.1f, &i));
   359   MOZ_RELEASE_ASSERT(!NumberEqualsInt32(NegativeInfinity<float>(), &i));
   360   MOZ_RELEASE_ASSERT(!NumberEqualsInt32(PositiveInfinity<float>(), &i));
   361   MOZ_RELEASE_ASSERT(!NumberEqualsInt32(UnspecifiedNaN<float>(), &i));
   362 }
   364 static void
   365 TestPredicates()
   366 {
   367   TestFloatsPredicates();
   368   TestDoublesPredicates();
   369 }
   371 static void
   372 TestFloatsAreApproximatelyEqual()
   373 {
   374   float epsilon = mozilla::detail::FuzzyEqualsEpsilon<float>::value();
   375   float lessThanEpsilon = epsilon / 2.0f;
   376   float moreThanEpsilon = epsilon * 2.0f;
   378   // Additive tests using the default epsilon
   379   // ... around 1.0
   380   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0f, 1.0f + lessThanEpsilon));
   381   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0f, 1.0f - lessThanEpsilon));
   382   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0f, 1.0f + epsilon));
   383   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0f, 1.0f - epsilon));
   384   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0f, 1.0f + moreThanEpsilon));
   385   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0f, 1.0f - moreThanEpsilon));
   386   // ... around 1.0e2 (this is near the upper bound of the range where
   387   // adding moreThanEpsilon will still be representable and return false)
   388   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e2f, 1.0e2f + lessThanEpsilon));
   389   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e2f, 1.0e2f + epsilon));
   390   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e2f, 1.0e2f + moreThanEpsilon));
   391   // ... around 1.0e-10
   392   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-10f, 1.0e-10f + lessThanEpsilon));
   393   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-10f, 1.0e-10f + epsilon));
   394   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-10f, 1.0e-10f + moreThanEpsilon));
   395   // ... straddling 0
   396   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-6f, -1.0e-6f));
   397   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-5f, -1.0e-5f));
   398   // Using a small epsilon
   399   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-5f, 1.0e-5f + 1.0e-10f, 1.0e-9f));
   400   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-5f, 1.0e-5f + 1.0e-10f, 1.0e-11f));
   401   // Using a big epsilon
   402   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e20f, 1.0e20f + 1.0e15f, 1.0e16f));
   403   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e20f, 1.0e20f + 1.0e15f, 1.0e14f));
   405   // Multiplicative tests using the default epsilon
   406   // ... around 1.0
   407   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0f, 1.0f + lessThanEpsilon));
   408   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0f, 1.0f - lessThanEpsilon));
   409   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0f, 1.0f + epsilon));
   410   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0f, 1.0f - epsilon));
   411   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0f, 1.0f + moreThanEpsilon));
   412   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0f, 1.0f - moreThanEpsilon));
   413   // ... around 1.0e10
   414   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e10f, 1.0e10f + (lessThanEpsilon * 1.0e10f)));
   415   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e10f, 1.0e10f + (moreThanEpsilon * 1.0e10f)));
   416   // ... around 1.0e-10
   417   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-10f, 1.0e-10f + (lessThanEpsilon * 1.0e-10f)));
   418   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-10f, 1.0e-10f + (moreThanEpsilon * 1.0e-10f)));
   419   // ... straddling 0
   420   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-6f, -1.0e-6f));
   421   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-6f, -1.0e-6f, 1.0e2f));
   422   // Using a small epsilon
   423   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-5f, 1.0e-5f + 1.0e-10f, 1.0e-4f));
   424   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-5f, 1.0e-5f + 1.0e-10f, 1.0e-5f));
   425   // Using a big epsilon
   426   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0f, 2.0f, 1.0f));
   427   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0f, 2.0f, 0.1f));
   429   // "real world case"
   430   float oneThird = 10.0f / 3.0f;
   431   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(10.0f, 3.0f * oneThird));
   432   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(10.0f, 3.0f * oneThird));
   433   // NaN check
   434   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(SpecificNaN<float>(1, 1), SpecificNaN<float>(1, 1)));
   435   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(SpecificNaN<float>(1, 2), SpecificNaN<float>(0, 8)));
   436   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(SpecificNaN<float>(1, 1), SpecificNaN<float>(1, 1)));
   437   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(SpecificNaN<float>(1, 2), SpecificNaN<float>(0, 200)));
   438 }
   440 static void
   441 TestDoublesAreApproximatelyEqual()
   442 {
   443   double epsilon = mozilla::detail::FuzzyEqualsEpsilon<double>::value();
   444   double lessThanEpsilon = epsilon / 2.0;
   445   double moreThanEpsilon = epsilon * 2.0;
   447   // Additive tests using the default epsilon
   448   // ... around 1.0
   449   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0, 1.0 + lessThanEpsilon));
   450   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0, 1.0 - lessThanEpsilon));
   451   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0, 1.0 + epsilon));
   452   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0, 1.0 - epsilon));
   453   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0, 1.0 + moreThanEpsilon));
   454   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0, 1.0 - moreThanEpsilon));
   455   // ... around 1.0e4 (this is near the upper bound of the range where
   456   // adding moreThanEpsilon will still be representable and return false)
   457   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e4, 1.0e4 + lessThanEpsilon));
   458   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e4, 1.0e4 + epsilon));
   459   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e4, 1.0e4 + moreThanEpsilon));
   460   // ... around 1.0e-25
   461   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-25, 1.0e-25 + lessThanEpsilon));
   462   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-25, 1.0e-25 + epsilon));
   463   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-25, 1.0e-25 + moreThanEpsilon));
   464   // ... straddling 0
   465   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-13, -1.0e-13));
   466   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-12, -1.0e-12));
   467   // Using a small epsilon
   468   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-29));
   469   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-31));
   470   // Using a big epsilon
   471   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e40, 1.0e40 + 1.0e25, 1.0e26));
   472   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e40, 1.0e40 + 1.0e25, 1.0e24));
   474   // Multiplicative tests using the default epsilon
   475   // ... around 1.0
   476   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0, 1.0 + lessThanEpsilon));
   477   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0, 1.0 - lessThanEpsilon));
   478   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0, 1.0 + epsilon));
   479   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0, 1.0 - epsilon));
   480   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0, 1.0 + moreThanEpsilon));
   481   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0, 1.0 - moreThanEpsilon));
   482   // ... around 1.0e30
   483   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e30, 1.0e30 + (lessThanEpsilon * 1.0e30)));
   484   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e30, 1.0e30 + (moreThanEpsilon * 1.0e30)));
   485   // ... around 1.0e-30
   486   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-30, 1.0e-30 + (lessThanEpsilon * 1.0e-30)));
   487   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-30, 1.0e-30 + (moreThanEpsilon * 1.0e-30)));
   488   // ... straddling 0
   489   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-6, -1.0e-6));
   490   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-6, -1.0e-6, 1.0e2));
   491   // Using a small epsilon
   492   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-15));
   493   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-16));
   494   // Using a big epsilon
   495   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e40, 2.0e40, 1.0));
   496   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e40, 2.0e40, 0.1));
   498   // "real world case"
   499   double oneThird = 10.0 / 3.0;
   500   MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(10.0, 3.0 * oneThird));
   501   MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(10.0, 3.0 * oneThird));
   502   // NaN check
   503   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(SpecificNaN<double>(1, 1), SpecificNaN<double>(1, 1)));
   504   MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(SpecificNaN<double>(1, 2), SpecificNaN<double>(0, 8)));
   505   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(SpecificNaN<double>(1, 1), SpecificNaN<double>(1, 1)));
   506   MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(SpecificNaN<double>(1, 2), SpecificNaN<double>(0, 200)));
   507 }
   509 static void
   510 TestAreApproximatelyEqual()
   511 {
   512   TestFloatsAreApproximatelyEqual();
   513   TestDoublesAreApproximatelyEqual();
   514 }
   516 int
   517 main()
   518 {
   519   TestAreIdentical();
   520   TestExponentComponent();
   521   TestPredicates();
   522   TestAreApproximatelyEqual();
   523 }

mercurial