mfbt/tests/TestFloatingPoint.cpp

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

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

mercurial