ipow.go 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package goja
  2. // inspired by https://gist.github.com/orlp/3551590
  3. var overflows = [64]int64{
  4. 9223372036854775807, 9223372036854775807, 3037000499, 2097151,
  5. 55108, 6208, 1448, 511,
  6. 234, 127, 78, 52,
  7. 38, 28, 22, 18,
  8. 15, 13, 11, 9,
  9. 8, 7, 7, 6,
  10. 6, 5, 5, 5,
  11. 4, 4, 4, 4,
  12. 3, 3, 3, 3,
  13. 3, 3, 3, 3,
  14. 2, 2, 2, 2,
  15. 2, 2, 2, 2,
  16. 2, 2, 2, 2,
  17. 2, 2, 2, 2,
  18. 2, 2, 2, 2,
  19. 2, 2, 2, 2,
  20. }
  21. var highestBitSet = [63]byte{
  22. 0, 1, 2, 2, 3, 3, 3, 3,
  23. 4, 4, 4, 4, 4, 4, 4, 4,
  24. 5, 5, 5, 5, 5, 5, 5, 5,
  25. 5, 5, 5, 5, 5, 5, 5, 5,
  26. 6, 6, 6, 6, 6, 6, 6, 6,
  27. 6, 6, 6, 6, 6, 6, 6, 6,
  28. 6, 6, 6, 6, 6, 6, 6, 6,
  29. 6, 6, 6, 6, 6, 6, 6,
  30. }
  31. func ipow(base, exp int64) (result int64) {
  32. if exp >= 63 {
  33. if base == 1 {
  34. return 1
  35. }
  36. if base == -1 {
  37. return 1 - 2*(exp&1)
  38. }
  39. return 0
  40. }
  41. if base > overflows[exp] || -base > overflows[exp] {
  42. return 0
  43. }
  44. result = 1
  45. switch highestBitSet[byte(exp)] {
  46. case 6:
  47. if exp&1 != 0 {
  48. result *= base
  49. }
  50. exp >>= 1
  51. base *= base
  52. fallthrough
  53. case 5:
  54. if exp&1 != 0 {
  55. result *= base
  56. }
  57. exp >>= 1
  58. base *= base
  59. fallthrough
  60. case 4:
  61. if exp&1 != 0 {
  62. result *= base
  63. }
  64. exp >>= 1
  65. base *= base
  66. fallthrough
  67. case 3:
  68. if exp&1 != 0 {
  69. result *= base
  70. }
  71. exp >>= 1
  72. base *= base
  73. fallthrough
  74. case 2:
  75. if exp&1 != 0 {
  76. result *= base
  77. }
  78. exp >>= 1
  79. base *= base
  80. fallthrough
  81. case 1:
  82. if exp&1 != 0 {
  83. result *= base
  84. }
  85. fallthrough
  86. default:
  87. return result
  88. }
  89. }