builtin_math.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. package otto
  2. import (
  3. "math"
  4. "math/rand"
  5. )
  6. // Math
  7. func builtinMath_abs(call FunctionCall) Value {
  8. number := call.Argument(0).float64()
  9. return toValue_float64(math.Abs(number))
  10. }
  11. func builtinMath_acos(call FunctionCall) Value {
  12. number := call.Argument(0).float64()
  13. return toValue_float64(math.Acos(number))
  14. }
  15. func builtinMath_asin(call FunctionCall) Value {
  16. number := call.Argument(0).float64()
  17. return toValue_float64(math.Asin(number))
  18. }
  19. func builtinMath_atan(call FunctionCall) Value {
  20. number := call.Argument(0).float64()
  21. return toValue_float64(math.Atan(number))
  22. }
  23. func builtinMath_atan2(call FunctionCall) Value {
  24. y := call.Argument(0).float64()
  25. if math.IsNaN(y) {
  26. return NaNValue()
  27. }
  28. x := call.Argument(1).float64()
  29. if math.IsNaN(x) {
  30. return NaNValue()
  31. }
  32. return toValue_float64(math.Atan2(y, x))
  33. }
  34. func builtinMath_cos(call FunctionCall) Value {
  35. number := call.Argument(0).float64()
  36. return toValue_float64(math.Cos(number))
  37. }
  38. func builtinMath_ceil(call FunctionCall) Value {
  39. number := call.Argument(0).float64()
  40. return toValue_float64(math.Ceil(number))
  41. }
  42. func builtinMath_exp(call FunctionCall) Value {
  43. number := call.Argument(0).float64()
  44. return toValue_float64(math.Exp(number))
  45. }
  46. func builtinMath_floor(call FunctionCall) Value {
  47. number := call.Argument(0).float64()
  48. return toValue_float64(math.Floor(number))
  49. }
  50. func builtinMath_log(call FunctionCall) Value {
  51. number := call.Argument(0).float64()
  52. return toValue_float64(math.Log(number))
  53. }
  54. func builtinMath_max(call FunctionCall) Value {
  55. switch len(call.ArgumentList) {
  56. case 0:
  57. return negativeInfinityValue()
  58. case 1:
  59. return toValue_float64(call.ArgumentList[0].float64())
  60. }
  61. result := call.ArgumentList[0].float64()
  62. if math.IsNaN(result) {
  63. return NaNValue()
  64. }
  65. for _, value := range call.ArgumentList[1:] {
  66. value := value.float64()
  67. if math.IsNaN(value) {
  68. return NaNValue()
  69. }
  70. result = math.Max(result, value)
  71. }
  72. return toValue_float64(result)
  73. }
  74. func builtinMath_min(call FunctionCall) Value {
  75. switch len(call.ArgumentList) {
  76. case 0:
  77. return positiveInfinityValue()
  78. case 1:
  79. return toValue_float64(call.ArgumentList[0].float64())
  80. }
  81. result := call.ArgumentList[0].float64()
  82. if math.IsNaN(result) {
  83. return NaNValue()
  84. }
  85. for _, value := range call.ArgumentList[1:] {
  86. value := value.float64()
  87. if math.IsNaN(value) {
  88. return NaNValue()
  89. }
  90. result = math.Min(result, value)
  91. }
  92. return toValue_float64(result)
  93. }
  94. func builtinMath_pow(call FunctionCall) Value {
  95. // TODO Make sure this works according to the specification (15.8.2.13)
  96. x := call.Argument(0).float64()
  97. y := call.Argument(1).float64()
  98. if math.Abs(x) == 1 && math.IsInf(y, 0) {
  99. return NaNValue()
  100. }
  101. return toValue_float64(math.Pow(x, y))
  102. }
  103. func builtinMath_random(call FunctionCall) Value {
  104. var v float64
  105. if call.runtime.random != nil {
  106. v = call.runtime.random()
  107. } else {
  108. v = rand.Float64()
  109. }
  110. return toValue_float64(v)
  111. }
  112. func builtinMath_round(call FunctionCall) Value {
  113. number := call.Argument(0).float64()
  114. value := math.Floor(number + 0.5)
  115. if value == 0 {
  116. value = math.Copysign(0, number)
  117. }
  118. return toValue_float64(value)
  119. }
  120. func builtinMath_sin(call FunctionCall) Value {
  121. number := call.Argument(0).float64()
  122. return toValue_float64(math.Sin(number))
  123. }
  124. func builtinMath_sqrt(call FunctionCall) Value {
  125. number := call.Argument(0).float64()
  126. return toValue_float64(math.Sqrt(number))
  127. }
  128. func builtinMath_tan(call FunctionCall) Value {
  129. number := call.Argument(0).float64()
  130. return toValue_float64(math.Tan(number))
  131. }