michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "mozilla/FloatingPoint.h" michael@0: michael@0: #include michael@0: michael@0: using mozilla::ExponentComponent; michael@0: using mozilla::FloatingPoint; michael@0: using mozilla::FuzzyEqualsAdditive; michael@0: using mozilla::FuzzyEqualsMultiplicative; michael@0: using mozilla::IsFinite; michael@0: using mozilla::IsInfinite; michael@0: using mozilla::IsNaN; michael@0: using mozilla::IsNegative; michael@0: using mozilla::IsNegativeZero; michael@0: using mozilla::NegativeInfinity; michael@0: using mozilla::NumberEqualsInt32; michael@0: using mozilla::NumberIsInt32; michael@0: using mozilla::NumbersAreIdentical; michael@0: using mozilla::PositiveInfinity; michael@0: using mozilla::SpecificNaN; michael@0: using mozilla::UnspecifiedNaN; michael@0: michael@0: template michael@0: static void michael@0: ShouldBeIdentical(T d1, T d2) michael@0: { michael@0: MOZ_RELEASE_ASSERT(NumbersAreIdentical(d1, d2)); michael@0: MOZ_RELEASE_ASSERT(NumbersAreIdentical(d2, d1)); michael@0: } michael@0: michael@0: template michael@0: static void michael@0: ShouldNotBeIdentical(T d1, T d2) michael@0: { michael@0: MOZ_RELEASE_ASSERT(!NumbersAreIdentical(d1, d2)); michael@0: MOZ_RELEASE_ASSERT(!NumbersAreIdentical(d2, d1)); michael@0: } michael@0: michael@0: static void michael@0: TestDoublesAreIdentical() michael@0: { michael@0: ShouldBeIdentical(+0.0, +0.0); michael@0: ShouldBeIdentical(-0.0, -0.0); michael@0: ShouldNotBeIdentical(+0.0, -0.0); michael@0: michael@0: ShouldBeIdentical(1.0, 1.0); michael@0: ShouldNotBeIdentical(-1.0, 1.0); michael@0: ShouldBeIdentical(4294967295.0, 4294967295.0); michael@0: ShouldNotBeIdentical(-4294967295.0, 4294967295.0); michael@0: ShouldBeIdentical(4294967296.0, 4294967296.0); michael@0: ShouldBeIdentical(4294967297.0, 4294967297.0); michael@0: ShouldBeIdentical(1e300, 1e300); michael@0: michael@0: ShouldBeIdentical(PositiveInfinity(), PositiveInfinity()); michael@0: ShouldBeIdentical(NegativeInfinity(), NegativeInfinity()); michael@0: ShouldNotBeIdentical(PositiveInfinity(), NegativeInfinity()); michael@0: michael@0: ShouldNotBeIdentical(-0.0, NegativeInfinity()); michael@0: ShouldNotBeIdentical(+0.0, NegativeInfinity()); michael@0: ShouldNotBeIdentical(1e300, NegativeInfinity()); michael@0: ShouldNotBeIdentical(3.141592654, NegativeInfinity()); michael@0: michael@0: ShouldBeIdentical(UnspecifiedNaN(), UnspecifiedNaN()); michael@0: ShouldBeIdentical(-UnspecifiedNaN(), UnspecifiedNaN()); michael@0: ShouldBeIdentical(UnspecifiedNaN(), -UnspecifiedNaN()); michael@0: michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 42)); michael@0: ShouldBeIdentical(SpecificNaN(1, 17), SpecificNaN(1, 42)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(1, 42)); michael@0: ShouldBeIdentical(SpecificNaN(1, 17), SpecificNaN(0, 42)); michael@0: michael@0: const uint64_t Mask = 0xfffffffffffffULL; michael@0: for (unsigned i = 0; i < 52; i++) { michael@0: for (unsigned j = 0; j < 52; j++) { michael@0: for (unsigned sign = 0; i < 2; i++) { michael@0: ShouldBeIdentical(SpecificNaN(0, 1ULL << i), SpecificNaN(sign, 1ULL << j)); michael@0: ShouldBeIdentical(SpecificNaN(1, 1ULL << i), SpecificNaN(sign, 1ULL << j)); michael@0: michael@0: ShouldBeIdentical(SpecificNaN(0, Mask & ~(1ULL << i)), michael@0: SpecificNaN(sign, Mask & ~(1ULL << j))); michael@0: ShouldBeIdentical(SpecificNaN(1, Mask & ~(1ULL << i)), michael@0: SpecificNaN(sign, Mask & ~(1ULL << j))); michael@0: } michael@0: } michael@0: } michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x8000000000000ULL)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x4000000000000ULL)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x2000000000000ULL)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x1000000000000ULL)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x0800000000000ULL)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x0400000000000ULL)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x0200000000000ULL)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x0100000000000ULL)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x0080000000000ULL)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x0040000000000ULL)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x0020000000000ULL)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x0010000000000ULL)); michael@0: ShouldBeIdentical(SpecificNaN(1, 17), SpecificNaN(0, 0xff0ffffffffffULL)); michael@0: ShouldBeIdentical(SpecificNaN(1, 17), SpecificNaN(0, 0xfffffffffff0fULL)); michael@0: michael@0: ShouldNotBeIdentical(UnspecifiedNaN(), +0.0); michael@0: ShouldNotBeIdentical(UnspecifiedNaN(), -0.0); michael@0: ShouldNotBeIdentical(UnspecifiedNaN(), 1.0); michael@0: ShouldNotBeIdentical(UnspecifiedNaN(), -1.0); michael@0: ShouldNotBeIdentical(UnspecifiedNaN(), PositiveInfinity()); michael@0: ShouldNotBeIdentical(UnspecifiedNaN(), NegativeInfinity()); michael@0: } michael@0: michael@0: static void michael@0: TestFloatsAreIdentical() michael@0: { michael@0: ShouldBeIdentical(+0.0f, +0.0f); michael@0: ShouldBeIdentical(-0.0f, -0.0f); michael@0: ShouldNotBeIdentical(+0.0f, -0.0f); michael@0: michael@0: ShouldBeIdentical(1.0f, 1.0f); michael@0: ShouldNotBeIdentical(-1.0f, 1.0f); michael@0: ShouldBeIdentical(8388607.0f, 8388607.0f); michael@0: ShouldNotBeIdentical(-8388607.0f, 8388607.0f); michael@0: ShouldBeIdentical(8388608.0f, 8388608.0f); michael@0: ShouldBeIdentical(8388609.0f, 8388609.0f); michael@0: ShouldBeIdentical(1e36f, 1e36f); michael@0: michael@0: ShouldBeIdentical(PositiveInfinity(), PositiveInfinity()); michael@0: ShouldBeIdentical(NegativeInfinity(), NegativeInfinity()); michael@0: ShouldNotBeIdentical(PositiveInfinity(), NegativeInfinity()); michael@0: michael@0: ShouldNotBeIdentical(-0.0f, NegativeInfinity()); michael@0: ShouldNotBeIdentical(+0.0f, NegativeInfinity()); michael@0: ShouldNotBeIdentical(1e36f, NegativeInfinity()); michael@0: ShouldNotBeIdentical(3.141592654f, NegativeInfinity()); michael@0: michael@0: ShouldBeIdentical(UnspecifiedNaN(), UnspecifiedNaN()); michael@0: ShouldBeIdentical(-UnspecifiedNaN(), UnspecifiedNaN()); michael@0: ShouldBeIdentical(UnspecifiedNaN(), -UnspecifiedNaN()); michael@0: michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 42)); michael@0: ShouldBeIdentical(SpecificNaN(1, 17), SpecificNaN(1, 42)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(1, 42)); michael@0: ShouldBeIdentical(SpecificNaN(1, 17), SpecificNaN(0, 42)); michael@0: michael@0: const uint32_t Mask = 0x7fffffUL; michael@0: for (unsigned i = 0; i < 23; i++) { michael@0: for (unsigned j = 0; j < 23; j++) { michael@0: for (unsigned sign = 0; i < 2; i++) { michael@0: ShouldBeIdentical(SpecificNaN(0, 1UL << i), SpecificNaN(sign, 1UL << j)); michael@0: ShouldBeIdentical(SpecificNaN(1, 1UL << i), SpecificNaN(sign, 1UL << j)); michael@0: michael@0: ShouldBeIdentical(SpecificNaN(0, Mask & ~(1UL << i)), michael@0: SpecificNaN(sign, Mask & ~(1UL << j))); michael@0: ShouldBeIdentical(SpecificNaN(1, Mask & ~(1UL << i)), michael@0: SpecificNaN(sign, Mask & ~(1UL << j))); michael@0: } michael@0: } michael@0: } michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x700000)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x400000)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x200000)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x100000)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x080000)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x040000)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x020000)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x010000)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x008000)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x004000)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x002000)); michael@0: ShouldBeIdentical(SpecificNaN(0, 17), SpecificNaN(0, 0x001000)); michael@0: ShouldBeIdentical(SpecificNaN(1, 17), SpecificNaN(0, 0x7f0fff)); michael@0: ShouldBeIdentical(SpecificNaN(1, 17), SpecificNaN(0, 0x7fff0f)); michael@0: michael@0: ShouldNotBeIdentical(UnspecifiedNaN(), +0.0f); michael@0: ShouldNotBeIdentical(UnspecifiedNaN(), -0.0f); michael@0: ShouldNotBeIdentical(UnspecifiedNaN(), 1.0f); michael@0: ShouldNotBeIdentical(UnspecifiedNaN(), -1.0f); michael@0: ShouldNotBeIdentical(UnspecifiedNaN(), PositiveInfinity()); michael@0: ShouldNotBeIdentical(UnspecifiedNaN(), NegativeInfinity()); michael@0: } michael@0: michael@0: static void michael@0: TestAreIdentical() michael@0: { michael@0: TestDoublesAreIdentical(); michael@0: TestFloatsAreIdentical(); michael@0: } michael@0: michael@0: static void michael@0: TestDoubleExponentComponent() michael@0: { michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(0.0) == -int_fast16_t(FloatingPoint::ExponentBias)); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(-0.0) == -int_fast16_t(FloatingPoint::ExponentBias)); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(0.125) == -3); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(0.5) == -1); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(1.0) == 0); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(1.5) == 0); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(2.0) == 1); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(7.0) == 2); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(PositiveInfinity()) == FloatingPoint::ExponentBias + 1); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(NegativeInfinity()) == FloatingPoint::ExponentBias + 1); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(UnspecifiedNaN()) == FloatingPoint::ExponentBias + 1); michael@0: } michael@0: michael@0: static void michael@0: TestFloatExponentComponent() michael@0: { michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(0.0f) == -int_fast16_t(FloatingPoint::ExponentBias)); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(-0.0f) == -int_fast16_t(FloatingPoint::ExponentBias)); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(0.125f) == -3); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(0.5f) == -1); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(1.0f) == 0); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(1.5f) == 0); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(2.0f) == 1); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(7.0f) == 2); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(PositiveInfinity()) == FloatingPoint::ExponentBias + 1); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(NegativeInfinity()) == FloatingPoint::ExponentBias + 1); michael@0: MOZ_RELEASE_ASSERT(ExponentComponent(UnspecifiedNaN()) == FloatingPoint::ExponentBias + 1); michael@0: } michael@0: michael@0: static void michael@0: TestExponentComponent() michael@0: { michael@0: TestDoubleExponentComponent(); michael@0: TestFloatExponentComponent(); michael@0: } michael@0: michael@0: static void michael@0: TestDoublesPredicates() michael@0: { michael@0: MOZ_RELEASE_ASSERT(IsNaN(UnspecifiedNaN())); michael@0: MOZ_RELEASE_ASSERT(IsNaN(SpecificNaN(1, 17)));; michael@0: MOZ_RELEASE_ASSERT(IsNaN(SpecificNaN(0, 0xfffffffffff0fULL))); michael@0: MOZ_RELEASE_ASSERT(!IsNaN(0.0)); michael@0: MOZ_RELEASE_ASSERT(!IsNaN(-0.0)); michael@0: MOZ_RELEASE_ASSERT(!IsNaN(1.0)); michael@0: MOZ_RELEASE_ASSERT(!IsNaN(PositiveInfinity())); michael@0: MOZ_RELEASE_ASSERT(!IsNaN(NegativeInfinity())); michael@0: michael@0: MOZ_RELEASE_ASSERT(IsInfinite(PositiveInfinity())); michael@0: MOZ_RELEASE_ASSERT(IsInfinite(NegativeInfinity())); michael@0: MOZ_RELEASE_ASSERT(!IsInfinite(UnspecifiedNaN())); michael@0: MOZ_RELEASE_ASSERT(!IsInfinite(0.0)); michael@0: MOZ_RELEASE_ASSERT(!IsInfinite(-0.0)); michael@0: MOZ_RELEASE_ASSERT(!IsInfinite(1.0)); michael@0: michael@0: MOZ_RELEASE_ASSERT(!IsFinite(PositiveInfinity())); michael@0: MOZ_RELEASE_ASSERT(!IsFinite(NegativeInfinity())); michael@0: MOZ_RELEASE_ASSERT(!IsFinite(UnspecifiedNaN())); michael@0: MOZ_RELEASE_ASSERT(IsFinite(0.0)); michael@0: MOZ_RELEASE_ASSERT(IsFinite(-0.0)); michael@0: MOZ_RELEASE_ASSERT(IsFinite(1.0)); michael@0: michael@0: MOZ_RELEASE_ASSERT(!IsNegative(PositiveInfinity())); michael@0: MOZ_RELEASE_ASSERT(IsNegative(NegativeInfinity())); michael@0: MOZ_RELEASE_ASSERT(IsNegative(-0.0)); michael@0: MOZ_RELEASE_ASSERT(!IsNegative(0.0)); michael@0: MOZ_RELEASE_ASSERT(IsNegative(-1.0)); michael@0: MOZ_RELEASE_ASSERT(!IsNegative(1.0)); michael@0: michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(PositiveInfinity())); michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(NegativeInfinity())); michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN(1, 17)));; michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN(1, 0xfffffffffff0fULL))); michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN(0, 17)));; michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN(0, 0xfffffffffff0fULL))); michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(UnspecifiedNaN())); michael@0: MOZ_RELEASE_ASSERT(IsNegativeZero(-0.0)); michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(0.0)); michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(-1.0)); michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(1.0)); michael@0: michael@0: int32_t i; michael@0: MOZ_RELEASE_ASSERT(NumberIsInt32(0.0, &i)); MOZ_RELEASE_ASSERT(i == 0); michael@0: MOZ_RELEASE_ASSERT(!NumberIsInt32(-0.0, &i)); michael@0: MOZ_RELEASE_ASSERT(NumberEqualsInt32(0.0, &i)); MOZ_RELEASE_ASSERT(i == 0); michael@0: MOZ_RELEASE_ASSERT(NumberEqualsInt32(-0.0, &i)); MOZ_RELEASE_ASSERT(i == 0); michael@0: MOZ_RELEASE_ASSERT(NumberIsInt32(double(INT32_MIN), &i)); MOZ_RELEASE_ASSERT(i == INT32_MIN); michael@0: MOZ_RELEASE_ASSERT(NumberIsInt32(double(INT32_MAX), &i)); MOZ_RELEASE_ASSERT(i == INT32_MAX); michael@0: MOZ_RELEASE_ASSERT(NumberEqualsInt32(double(INT32_MIN), &i)); MOZ_RELEASE_ASSERT(i == INT32_MIN); michael@0: MOZ_RELEASE_ASSERT(NumberEqualsInt32(double(INT32_MAX), &i)); MOZ_RELEASE_ASSERT(i == INT32_MAX); michael@0: MOZ_RELEASE_ASSERT(!NumberIsInt32(0.5, &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberIsInt32(double(INT32_MAX) + 0.1, &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberIsInt32(double(INT32_MIN) - 0.1, &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberIsInt32(NegativeInfinity(), &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberIsInt32(PositiveInfinity(), &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberIsInt32(UnspecifiedNaN(), &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberEqualsInt32(0.5, &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberEqualsInt32(double(INT32_MAX) + 0.1, &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberEqualsInt32(double(INT32_MIN) - 0.1, &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberEqualsInt32(NegativeInfinity(), &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberEqualsInt32(PositiveInfinity(), &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberEqualsInt32(UnspecifiedNaN(), &i)); michael@0: } michael@0: michael@0: static void michael@0: TestFloatsPredicates() michael@0: { michael@0: MOZ_RELEASE_ASSERT(IsNaN(UnspecifiedNaN())); michael@0: MOZ_RELEASE_ASSERT(IsNaN(SpecificNaN(1, 17)));; michael@0: MOZ_RELEASE_ASSERT(IsNaN(SpecificNaN(0, 0x7fff0fUL))); michael@0: MOZ_RELEASE_ASSERT(!IsNaN(0.0f)); michael@0: MOZ_RELEASE_ASSERT(!IsNaN(-0.0f)); michael@0: MOZ_RELEASE_ASSERT(!IsNaN(1.0f)); michael@0: MOZ_RELEASE_ASSERT(!IsNaN(PositiveInfinity())); michael@0: MOZ_RELEASE_ASSERT(!IsNaN(NegativeInfinity())); michael@0: michael@0: MOZ_RELEASE_ASSERT(IsInfinite(PositiveInfinity())); michael@0: MOZ_RELEASE_ASSERT(IsInfinite(NegativeInfinity())); michael@0: MOZ_RELEASE_ASSERT(!IsInfinite(UnspecifiedNaN())); michael@0: MOZ_RELEASE_ASSERT(!IsInfinite(0.0f)); michael@0: MOZ_RELEASE_ASSERT(!IsInfinite(-0.0f)); michael@0: MOZ_RELEASE_ASSERT(!IsInfinite(1.0f)); michael@0: michael@0: MOZ_RELEASE_ASSERT(!IsFinite(PositiveInfinity())); michael@0: MOZ_RELEASE_ASSERT(!IsFinite(NegativeInfinity())); michael@0: MOZ_RELEASE_ASSERT(!IsFinite(UnspecifiedNaN())); michael@0: MOZ_RELEASE_ASSERT(IsFinite(0.0f)); michael@0: MOZ_RELEASE_ASSERT(IsFinite(-0.0f)); michael@0: MOZ_RELEASE_ASSERT(IsFinite(1.0f)); michael@0: michael@0: MOZ_RELEASE_ASSERT(!IsNegative(PositiveInfinity())); michael@0: MOZ_RELEASE_ASSERT(IsNegative(NegativeInfinity())); michael@0: MOZ_RELEASE_ASSERT(IsNegative(-0.0f)); michael@0: MOZ_RELEASE_ASSERT(!IsNegative(0.0f)); michael@0: MOZ_RELEASE_ASSERT(IsNegative(-1.0f)); michael@0: MOZ_RELEASE_ASSERT(!IsNegative(1.0f)); michael@0: michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(PositiveInfinity())); michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(NegativeInfinity())); michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN(1, 17)));; michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN(1, 0x7fff0fUL))); michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN(0, 17)));; michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(SpecificNaN(0, 0x7fff0fUL))); michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(UnspecifiedNaN())); michael@0: MOZ_RELEASE_ASSERT(IsNegativeZero(-0.0f)); michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(0.0f)); michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(-1.0f)); michael@0: MOZ_RELEASE_ASSERT(!IsNegativeZero(1.0f)); michael@0: michael@0: int32_t i; michael@0: const int32_t BIG = 2097151; michael@0: MOZ_RELEASE_ASSERT(NumberIsInt32(0.0f, &i)); MOZ_RELEASE_ASSERT(i == 0); michael@0: MOZ_RELEASE_ASSERT(!NumberIsInt32(-0.0f, &i)); michael@0: MOZ_RELEASE_ASSERT(NumberEqualsInt32(0.0f, &i)); MOZ_RELEASE_ASSERT(i == 0); michael@0: MOZ_RELEASE_ASSERT(NumberEqualsInt32(-0.0f, &i)); MOZ_RELEASE_ASSERT(i == 0); michael@0: MOZ_RELEASE_ASSERT(NumberIsInt32(float(INT32_MIN), &i)); MOZ_RELEASE_ASSERT(i == INT32_MIN); michael@0: MOZ_RELEASE_ASSERT(NumberIsInt32(float(BIG), &i)); MOZ_RELEASE_ASSERT(i == BIG); michael@0: MOZ_RELEASE_ASSERT(NumberEqualsInt32(float(INT32_MIN), &i)); MOZ_RELEASE_ASSERT(i == INT32_MIN); michael@0: MOZ_RELEASE_ASSERT(NumberEqualsInt32(float(BIG), &i)); MOZ_RELEASE_ASSERT(i == BIG); michael@0: MOZ_RELEASE_ASSERT(!NumberIsInt32(0.5f, &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberIsInt32(float(BIG) + 0.1f, &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberIsInt32(NegativeInfinity(), &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberIsInt32(PositiveInfinity(), &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberIsInt32(UnspecifiedNaN(), &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberEqualsInt32(0.5f, &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberEqualsInt32(float(BIG) + 0.1f, &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberEqualsInt32(NegativeInfinity(), &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberEqualsInt32(PositiveInfinity(), &i)); michael@0: MOZ_RELEASE_ASSERT(!NumberEqualsInt32(UnspecifiedNaN(), &i)); michael@0: } michael@0: michael@0: static void michael@0: TestPredicates() michael@0: { michael@0: TestFloatsPredicates(); michael@0: TestDoublesPredicates(); michael@0: } michael@0: michael@0: static void michael@0: TestFloatsAreApproximatelyEqual() michael@0: { michael@0: float epsilon = mozilla::detail::FuzzyEqualsEpsilon::value(); michael@0: float lessThanEpsilon = epsilon / 2.0f; michael@0: float moreThanEpsilon = epsilon * 2.0f; michael@0: michael@0: // Additive tests using the default epsilon michael@0: // ... around 1.0 michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0f, 1.0f + lessThanEpsilon)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0f, 1.0f - lessThanEpsilon)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0f, 1.0f + epsilon)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0f, 1.0f - epsilon)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0f, 1.0f + moreThanEpsilon)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0f, 1.0f - moreThanEpsilon)); michael@0: // ... around 1.0e2 (this is near the upper bound of the range where michael@0: // adding moreThanEpsilon will still be representable and return false) michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e2f, 1.0e2f + lessThanEpsilon)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e2f, 1.0e2f + epsilon)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e2f, 1.0e2f + moreThanEpsilon)); michael@0: // ... around 1.0e-10 michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-10f, 1.0e-10f + lessThanEpsilon)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-10f, 1.0e-10f + epsilon)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-10f, 1.0e-10f + moreThanEpsilon)); michael@0: // ... straddling 0 michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-6f, -1.0e-6f)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-5f, -1.0e-5f)); michael@0: // Using a small epsilon michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-5f, 1.0e-5f + 1.0e-10f, 1.0e-9f)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-5f, 1.0e-5f + 1.0e-10f, 1.0e-11f)); michael@0: // Using a big epsilon michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e20f, 1.0e20f + 1.0e15f, 1.0e16f)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e20f, 1.0e20f + 1.0e15f, 1.0e14f)); michael@0: michael@0: // Multiplicative tests using the default epsilon michael@0: // ... around 1.0 michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0f, 1.0f + lessThanEpsilon)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0f, 1.0f - lessThanEpsilon)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0f, 1.0f + epsilon)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0f, 1.0f - epsilon)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0f, 1.0f + moreThanEpsilon)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0f, 1.0f - moreThanEpsilon)); michael@0: // ... around 1.0e10 michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e10f, 1.0e10f + (lessThanEpsilon * 1.0e10f))); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e10f, 1.0e10f + (moreThanEpsilon * 1.0e10f))); michael@0: // ... around 1.0e-10 michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-10f, 1.0e-10f + (lessThanEpsilon * 1.0e-10f))); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-10f, 1.0e-10f + (moreThanEpsilon * 1.0e-10f))); michael@0: // ... straddling 0 michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-6f, -1.0e-6f)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-6f, -1.0e-6f, 1.0e2f)); michael@0: // Using a small epsilon michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-5f, 1.0e-5f + 1.0e-10f, 1.0e-4f)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-5f, 1.0e-5f + 1.0e-10f, 1.0e-5f)); michael@0: // Using a big epsilon michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0f, 2.0f, 1.0f)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0f, 2.0f, 0.1f)); michael@0: michael@0: // "real world case" michael@0: float oneThird = 10.0f / 3.0f; michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(10.0f, 3.0f * oneThird)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(10.0f, 3.0f * oneThird)); michael@0: // NaN check michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(SpecificNaN(1, 1), SpecificNaN(1, 1))); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(SpecificNaN(1, 2), SpecificNaN(0, 8))); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(SpecificNaN(1, 1), SpecificNaN(1, 1))); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(SpecificNaN(1, 2), SpecificNaN(0, 200))); michael@0: } michael@0: michael@0: static void michael@0: TestDoublesAreApproximatelyEqual() michael@0: { michael@0: double epsilon = mozilla::detail::FuzzyEqualsEpsilon::value(); michael@0: double lessThanEpsilon = epsilon / 2.0; michael@0: double moreThanEpsilon = epsilon * 2.0; michael@0: michael@0: // Additive tests using the default epsilon michael@0: // ... around 1.0 michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0, 1.0 + lessThanEpsilon)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0, 1.0 - lessThanEpsilon)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0, 1.0 + epsilon)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0, 1.0 - epsilon)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0, 1.0 + moreThanEpsilon)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0, 1.0 - moreThanEpsilon)); michael@0: // ... around 1.0e4 (this is near the upper bound of the range where michael@0: // adding moreThanEpsilon will still be representable and return false) michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e4, 1.0e4 + lessThanEpsilon)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e4, 1.0e4 + epsilon)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e4, 1.0e4 + moreThanEpsilon)); michael@0: // ... around 1.0e-25 michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-25, 1.0e-25 + lessThanEpsilon)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-25, 1.0e-25 + epsilon)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-25, 1.0e-25 + moreThanEpsilon)); michael@0: // ... straddling 0 michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-13, -1.0e-13)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-12, -1.0e-12)); michael@0: // Using a small epsilon michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-29)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-31)); michael@0: // Using a big epsilon michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(1.0e40, 1.0e40 + 1.0e25, 1.0e26)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(1.0e40, 1.0e40 + 1.0e25, 1.0e24)); michael@0: michael@0: // Multiplicative tests using the default epsilon michael@0: // ... around 1.0 michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0, 1.0 + lessThanEpsilon)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0, 1.0 - lessThanEpsilon)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0, 1.0 + epsilon)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0, 1.0 - epsilon)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0, 1.0 + moreThanEpsilon)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0, 1.0 - moreThanEpsilon)); michael@0: // ... around 1.0e30 michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e30, 1.0e30 + (lessThanEpsilon * 1.0e30))); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e30, 1.0e30 + (moreThanEpsilon * 1.0e30))); michael@0: // ... around 1.0e-30 michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-30, 1.0e-30 + (lessThanEpsilon * 1.0e-30))); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-30, 1.0e-30 + (moreThanEpsilon * 1.0e-30))); michael@0: // ... straddling 0 michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-6, -1.0e-6)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-6, -1.0e-6, 1.0e2)); michael@0: // Using a small epsilon michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-15)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e-15, 1.0e-15 + 1.0e-30, 1.0e-16)); michael@0: // Using a big epsilon michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(1.0e40, 2.0e40, 1.0)); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(1.0e40, 2.0e40, 0.1)); michael@0: michael@0: // "real world case" michael@0: double oneThird = 10.0 / 3.0; michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsAdditive(10.0, 3.0 * oneThird)); michael@0: MOZ_RELEASE_ASSERT(FuzzyEqualsMultiplicative(10.0, 3.0 * oneThird)); michael@0: // NaN check michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(SpecificNaN(1, 1), SpecificNaN(1, 1))); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsAdditive(SpecificNaN(1, 2), SpecificNaN(0, 8))); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(SpecificNaN(1, 1), SpecificNaN(1, 1))); michael@0: MOZ_RELEASE_ASSERT(!FuzzyEqualsMultiplicative(SpecificNaN(1, 2), SpecificNaN(0, 200))); michael@0: } michael@0: michael@0: static void michael@0: TestAreApproximatelyEqual() michael@0: { michael@0: TestFloatsAreApproximatelyEqual(); michael@0: TestDoublesAreApproximatelyEqual(); michael@0: } michael@0: michael@0: int michael@0: main() michael@0: { michael@0: TestAreIdentical(); michael@0: TestExponentComponent(); michael@0: TestPredicates(); michael@0: TestAreApproximatelyEqual(); michael@0: }