ASoftFloat.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. using System;
  2. namespace ChocolArm64.Instruction
  3. {
  4. static class ASoftFloat
  5. {
  6. static ASoftFloat()
  7. {
  8. InvSqrtEstimateTable = BuildInvSqrtEstimateTable();
  9. }
  10. private static readonly byte[] InvSqrtEstimateTable;
  11. private static byte[] BuildInvSqrtEstimateTable()
  12. {
  13. byte[] Table = new byte[512];
  14. for (ulong index = 128; index < 512; index++)
  15. {
  16. ulong a = index;
  17. if (a < 256)
  18. {
  19. a = (a << 1) + 1;
  20. }
  21. else
  22. {
  23. a = (a | 1) << 1;
  24. }
  25. ulong b = 256;
  26. while (a * (b + 1) * (b + 1) < (1ul << 28))
  27. {
  28. b++;
  29. }
  30. b = (b + 1) >> 1;
  31. Table[index] = (byte)(b & 0xFF);
  32. }
  33. return Table;
  34. }
  35. public static float InvSqrtEstimate(float x)
  36. {
  37. return (float)InvSqrtEstimate((double)x);
  38. }
  39. public static double InvSqrtEstimate(double x)
  40. {
  41. ulong x_bits = (ulong)BitConverter.DoubleToInt64Bits(x);
  42. ulong x_sign = x_bits & 0x8000000000000000;
  43. long x_exp = (long)((x_bits >> 52) & 0x7FF);
  44. ulong scaled = x_bits & ((1ul << 52) - 1);
  45. if (x_exp == 0x7FF && scaled != 0)
  46. {
  47. // NaN
  48. return BitConverter.Int64BitsToDouble((long)(x_bits | 0x0008000000000000));
  49. }
  50. if (x_exp == 0)
  51. {
  52. if (scaled == 0)
  53. {
  54. // Zero -> Infinity
  55. return BitConverter.Int64BitsToDouble((long)(x_sign | 0x7ff0000000000000));
  56. }
  57. // Denormal
  58. while ((scaled & (1 << 51)) == 0)
  59. {
  60. scaled <<= 1;
  61. x_exp--;
  62. }
  63. scaled <<= 1;
  64. }
  65. if (x_sign != 0)
  66. {
  67. // Negative -> NaN
  68. return BitConverter.Int64BitsToDouble((long)0x7ff8000000000000);
  69. }
  70. if (x_exp == 0x7ff && scaled == 0)
  71. {
  72. // Infinity -> Zero
  73. return BitConverter.Int64BitsToDouble((long)x_sign);
  74. }
  75. if (((ulong)x_exp & 1) == 1)
  76. {
  77. scaled >>= 45;
  78. scaled &= 0xFF;
  79. scaled |= 0x80;
  80. }
  81. else
  82. {
  83. scaled >>= 44;
  84. scaled &= 0xFF;
  85. scaled |= 0x100;
  86. }
  87. ulong result_exp = ((ulong)(3068 - x_exp) / 2) & 0x7FF;
  88. ulong estimate = (ulong)InvSqrtEstimateTable[scaled];
  89. ulong fraction = estimate << 44;
  90. ulong result = x_sign | (result_exp << 52) | fraction;
  91. return BitConverter.Int64BitsToDouble((long)result);
  92. }
  93. }
  94. }