FSTComparisonTests.m 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. * Copyright 2017 Google
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #import "Firestore/Source/Util/FSTComparison.h"
  17. #import <XCTest/XCTest.h>
  18. union DoubleBits {
  19. double d;
  20. uint64_t bits;
  21. };
  22. #define ASSERT_BIT_EQUALS(expected, actual) \
  23. do { \
  24. union DoubleBits expectedBits = {.d = expected}; \
  25. union DoubleBits actualBits = {.d = expected}; \
  26. if (expectedBits.bits != actualBits.bits) { \
  27. XCTFail(@"Expected <%f> to compare equal to <%f> with bits <%llX> equal to <%llX>", actual, \
  28. expected, actualBits.bits, expectedBits.bits); \
  29. } \
  30. } while (0);
  31. #define ASSERT_ORDERED_SAME(doubleValue, longValue) \
  32. do { \
  33. NSComparisonResult result = FSTCompareMixed(doubleValue, longValue); \
  34. if (result != NSOrderedSame) { \
  35. XCTFail(@"Expected <%f> to compare equal to <%lld>", doubleValue, longValue); \
  36. } \
  37. } while (0);
  38. #define ASSERT_ORDERED_DESCENDING(doubleValue, longValue) \
  39. do { \
  40. NSComparisonResult result = FSTCompareMixed(doubleValue, longValue); \
  41. if (result != NSOrderedDescending) { \
  42. XCTFail(@"Expected <%f> to compare equal to <%lld>", doubleValue, longValue); \
  43. } \
  44. } while (0);
  45. #define ASSERT_ORDERED_ASCENDING(doubleValue, longValue) \
  46. do { \
  47. NSComparisonResult result = FSTCompareMixed(doubleValue, longValue); \
  48. if (result != NSOrderedAscending) { \
  49. XCTFail(@"Expected <%f> to compare equal to <%lld>", doubleValue, longValue); \
  50. } \
  51. } while (0);
  52. @interface FSTComparisonTests : XCTestCase
  53. @end
  54. @implementation FSTComparisonTests
  55. - (void)testMixedComparison {
  56. // Infinities
  57. ASSERT_ORDERED_ASCENDING(-INFINITY, LLONG_MIN);
  58. ASSERT_ORDERED_ASCENDING(-INFINITY, LLONG_MAX);
  59. ASSERT_ORDERED_ASCENDING(-INFINITY, 0LL);
  60. ASSERT_ORDERED_DESCENDING(INFINITY, LLONG_MIN);
  61. ASSERT_ORDERED_DESCENDING(INFINITY, LLONG_MAX);
  62. ASSERT_ORDERED_DESCENDING(INFINITY, 0LL);
  63. // NaN
  64. ASSERT_ORDERED_ASCENDING(NAN, LLONG_MIN);
  65. ASSERT_ORDERED_ASCENDING(NAN, LLONG_MAX);
  66. ASSERT_ORDERED_ASCENDING(NAN, 0LL);
  67. // Large values (note DBL_MIN is positive and near zero).
  68. ASSERT_ORDERED_ASCENDING(-DBL_MAX, LLONG_MIN);
  69. // Tests around LLONG_MIN
  70. ASSERT_BIT_EQUALS((double)LLONG_MIN, -0x1.0p63);
  71. ASSERT_ORDERED_SAME(-0x1.0p63, LLONG_MIN);
  72. ASSERT_ORDERED_ASCENDING(-0x1.0p63, LLONG_MIN + 1);
  73. XCTAssertLessThan(-0x1.0000000000001p63, -0x1.0p63);
  74. ASSERT_ORDERED_ASCENDING(-0x1.0000000000001p63, LLONG_MIN);
  75. ASSERT_ORDERED_DESCENDING(-0x1.FFFFFFFFFFFFFp62, LLONG_MIN);
  76. // Tests around LLONG_MAX
  77. // Note LLONG_MAX cannot be exactly represented by a double, so the system rounds it to the
  78. // nearest double, which is 2^63. This number, in turn is larger than the maximum representable
  79. // as a long.
  80. ASSERT_BIT_EQUALS(0x1.0p63, (double)LLONG_MAX);
  81. ASSERT_ORDERED_DESCENDING(0x1.0p63, LLONG_MAX);
  82. // The largest value with an exactly long representation
  83. XCTAssertEqual((long)0x1.FFFFFFFFFFFFFp62, 0x7FFFFFFFFFFFFC00LL);
  84. ASSERT_ORDERED_SAME(0x1.FFFFFFFFFFFFFp62, 0x7FFFFFFFFFFFFC00LL);
  85. ASSERT_ORDERED_DESCENDING(0x1.FFFFFFFFFFFFFp62, 0x7FFFFFFFFFFFFB00LL);
  86. ASSERT_ORDERED_DESCENDING(0x1.FFFFFFFFFFFFFp62, 0x7FFFFFFFFFFFFBFFLL);
  87. ASSERT_ORDERED_ASCENDING(0x1.FFFFFFFFFFFFFp62, 0x7FFFFFFFFFFFFC01LL);
  88. ASSERT_ORDERED_ASCENDING(0x1.FFFFFFFFFFFFFp62, 0x7FFFFFFFFFFFFD00LL);
  89. ASSERT_ORDERED_ASCENDING(0x1.FFFFFFFFFFFFEp62, 0x7FFFFFFFFFFFFC00LL);
  90. // Tests around MAX_SAFE_INTEGER
  91. ASSERT_ORDERED_SAME(0x1.FFFFFFFFFFFFFp52, 0x1FFFFFFFFFFFFFLL);
  92. ASSERT_ORDERED_DESCENDING(0x1.FFFFFFFFFFFFFp52, 0x1FFFFFFFFFFFFELL);
  93. ASSERT_ORDERED_ASCENDING(0x1.FFFFFFFFFFFFEp52, 0x1FFFFFFFFFFFFFLL);
  94. ASSERT_ORDERED_ASCENDING(0x1.FFFFFFFFFFFFFp52, 0x20000000000000LL);
  95. // Tests around MIN_SAFE_INTEGER
  96. ASSERT_ORDERED_SAME(-0x1.FFFFFFFFFFFFFp52, -0x1FFFFFFFFFFFFFLL);
  97. ASSERT_ORDERED_ASCENDING(-0x1.FFFFFFFFFFFFFp52, -0x1FFFFFFFFFFFFELL);
  98. ASSERT_ORDERED_DESCENDING(-0x1.FFFFFFFFFFFFEp52, -0x1FFFFFFFFFFFFFLL);
  99. ASSERT_ORDERED_DESCENDING(-0x1.FFFFFFFFFFFFFp52, -0x20000000000000LL);
  100. // Tests around zero.
  101. ASSERT_ORDERED_SAME(-0.0, 0LL);
  102. ASSERT_ORDERED_SAME(0.0, 0LL);
  103. // The smallest representable positive value should be greater than zero
  104. ASSERT_ORDERED_DESCENDING(DBL_MIN, 0LL);
  105. ASSERT_ORDERED_ASCENDING(-DBL_MIN, 0LL);
  106. // Note that 0x1.0p-1074 is a hex floating point literal representing the minimum subnormal
  107. // number: <https://en.wikipedia.org/wiki/Denormal_number>.
  108. double minSubNormal = 0x1.0p-1074;
  109. ASSERT_ORDERED_DESCENDING(minSubNormal, 0LL);
  110. ASSERT_ORDERED_ASCENDING(-minSubNormal, 0LL);
  111. // Other sanity checks
  112. ASSERT_ORDERED_ASCENDING(0.5, 1LL);
  113. ASSERT_ORDERED_DESCENDING(0.5, 0LL);
  114. ASSERT_ORDERED_ASCENDING(1.5, 2LL);
  115. ASSERT_ORDERED_DESCENDING(1.5, 1LL);
  116. }
  117. @end