DoubleHelper.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // Copyright 2010 the V8 project authors. All rights reserved.
  2. // Redistribution and use in source and binary forms, with or without
  3. // modification, are permitted provided that the following conditions are
  4. // met:
  5. //
  6. // * Redistributions of source code must retain the above copyright
  7. // notice, this list of conditions and the following disclaimer.
  8. // * Redistributions in binary form must reproduce the above
  9. // copyright notice, this list of conditions and the following
  10. // disclaimer in the documentation and/or other materials provided
  11. // with the distribution.
  12. // * Neither the name of Google Inc. nor the names of its
  13. // contributors may be used to endorse or promote products derived
  14. // from this software without specific prior written permission.
  15. //
  16. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  17. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  18. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  19. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  20. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  21. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  22. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  26. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27. // Ported to Java from Mozilla's version of V8-dtoa by Hannes Wallnoefer.
  28. // The original revision was 67d1049b0bf9 from the mozilla-central tree.
  29. using System.Diagnostics;
  30. namespace Jint.Native.Number.Dtoa
  31. {
  32. // Helper functions for doubles.
  33. public class DoubleHelper
  34. {
  35. private const long KExponentMask = 0x7FF0000000000000L;
  36. private const long KSignificandMask = 0x000FFFFFFFFFFFFFL;
  37. private const long KHiddenBit = 0x0010000000000000L;
  38. private static DiyFp AsDiyFp(long d64)
  39. {
  40. Debug.Assert(!IsSpecial(d64));
  41. return new DiyFp(Significand(d64), Exponent(d64));
  42. }
  43. // this->Significand() must not be 0.
  44. internal static DiyFp AsNormalizedDiyFp(long d64)
  45. {
  46. long f = Significand(d64);
  47. int e = Exponent(d64);
  48. Debug.Assert(f != 0);
  49. // The current double could be a denormal.
  50. while ((f & KHiddenBit) == 0)
  51. {
  52. f <<= 1;
  53. e--;
  54. }
  55. // Do the final shifts in one go. Don't forget the hidden bit (the '-1').
  56. f <<= DiyFp.KSignificandSize - KSignificandSize - 1;
  57. e -= DiyFp.KSignificandSize - KSignificandSize - 1;
  58. return new DiyFp(f, e);
  59. }
  60. private static int Exponent(long d64)
  61. {
  62. if (IsDenormal(d64)) return KDenormalExponent;
  63. int biasedE = (int) ((d64 & KExponentMask).UnsignedShift(KSignificandSize) & 0xffffffffL);
  64. return biasedE - KExponentBias;
  65. }
  66. private static long Significand(long d64)
  67. {
  68. long significand = d64 & KSignificandMask;
  69. if (!IsDenormal(d64))
  70. {
  71. return significand + KHiddenBit;
  72. }
  73. else
  74. {
  75. return significand;
  76. }
  77. }
  78. // Returns true if the double is a denormal.
  79. private static bool IsDenormal(long d64)
  80. {
  81. return (d64 & KExponentMask) == 0L;
  82. }
  83. // We consider denormals not to be special.
  84. // Hence only Infinity and NaN are special.
  85. private static bool IsSpecial(long d64)
  86. {
  87. return (d64 & KExponentMask) == KExponentMask;
  88. }
  89. // Returns the two boundaries of first argument.
  90. // The bigger boundary (m_plus) is normalized. The lower boundary has the same
  91. // exponent as m_plus.
  92. internal static void NormalizedBoundaries(long d64, DiyFp mMinus, DiyFp mPlus)
  93. {
  94. DiyFp v = AsDiyFp(d64);
  95. bool significandIsZero = (v.F == KHiddenBit);
  96. mPlus.F = (v.F << 1) + 1;
  97. mPlus.E = v.E - 1;
  98. mPlus.Normalize();
  99. if (significandIsZero && v.E != KDenormalExponent)
  100. {
  101. // The boundary is closer. Think of v = 1000e10 and v- = 9999e9.
  102. // Then the boundary (== (v - v-)/2) is not just at a distance of 1e9 but
  103. // at a distance of 1e8.
  104. // The only exception is for the smallest normal: the largest denormal is
  105. // at the same distance as its successor.
  106. // Note: denormals have the same exponent as the smallest normals.
  107. mMinus.F = (v.F << 2) - 1;
  108. mMinus.E = v.E - 2;
  109. }
  110. else
  111. {
  112. mMinus.F = (v.F << 1) - 1;
  113. mMinus.E = v.E - 1;
  114. }
  115. mMinus.F = mMinus.F << (mMinus.E - mPlus.E);
  116. mMinus.E = mPlus.E;
  117. }
  118. private const int KSignificandSize = 52; // Excludes the hidden bit.
  119. private const int KExponentBias = 0x3FF + KSignificandSize;
  120. private const int KDenormalExponent = -KExponentBias + 1;
  121. }
  122. }