builtin_math.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. package otto
  2. import (
  3. "math"
  4. "math/rand"
  5. )
  6. // Math
  7. func builtinMathAbs(call FunctionCall) Value {
  8. number := call.Argument(0).float64()
  9. return float64Value(math.Abs(number))
  10. }
  11. func builtinMathAcos(call FunctionCall) Value {
  12. number := call.Argument(0).float64()
  13. return float64Value(math.Acos(number))
  14. }
  15. func builtinMathAcosh(call FunctionCall) Value {
  16. number := call.Argument(0).float64()
  17. return float64Value(math.Acosh(number))
  18. }
  19. func builtinMathAsin(call FunctionCall) Value {
  20. number := call.Argument(0).float64()
  21. return float64Value(math.Asin(number))
  22. }
  23. func builtinMathAsinh(call FunctionCall) Value {
  24. number := call.Argument(0).float64()
  25. return float64Value(math.Asinh(number))
  26. }
  27. func builtinMathAtan(call FunctionCall) Value {
  28. number := call.Argument(0).float64()
  29. return float64Value(math.Atan(number))
  30. }
  31. func builtinMathAtan2(call FunctionCall) Value {
  32. y := call.Argument(0).float64()
  33. if math.IsNaN(y) {
  34. return NaNValue()
  35. }
  36. x := call.Argument(1).float64()
  37. if math.IsNaN(x) {
  38. return NaNValue()
  39. }
  40. return float64Value(math.Atan2(y, x))
  41. }
  42. func builtinMathAtanh(call FunctionCall) Value {
  43. number := call.Argument(0).float64()
  44. return float64Value(math.Atanh(number))
  45. }
  46. func builtinMathCbrt(call FunctionCall) Value {
  47. number := call.Argument(0).float64()
  48. return float64Value(math.Cbrt(number))
  49. }
  50. func builtinMathCos(call FunctionCall) Value {
  51. number := call.Argument(0).float64()
  52. return float64Value(math.Cos(number))
  53. }
  54. func builtinMathCeil(call FunctionCall) Value {
  55. number := call.Argument(0).float64()
  56. return float64Value(math.Ceil(number))
  57. }
  58. func builtinMathCosh(call FunctionCall) Value {
  59. number := call.Argument(0).float64()
  60. return float64Value(math.Cosh(number))
  61. }
  62. func builtinMathExp(call FunctionCall) Value {
  63. number := call.Argument(0).float64()
  64. return float64Value(math.Exp(number))
  65. }
  66. func builtinMathExpm1(call FunctionCall) Value {
  67. number := call.Argument(0).float64()
  68. return float64Value(math.Expm1(number))
  69. }
  70. func builtinMathFloor(call FunctionCall) Value {
  71. number := call.Argument(0).float64()
  72. return float64Value(math.Floor(number))
  73. }
  74. func builtinMathLog(call FunctionCall) Value {
  75. number := call.Argument(0).float64()
  76. return float64Value(math.Log(number))
  77. }
  78. func builtinMathLog10(call FunctionCall) Value {
  79. number := call.Argument(0).float64()
  80. return float64Value(math.Log10(number))
  81. }
  82. func builtinMathLog1p(call FunctionCall) Value {
  83. number := call.Argument(0).float64()
  84. return float64Value(math.Log1p(number))
  85. }
  86. func builtinMathLog2(call FunctionCall) Value {
  87. number := call.Argument(0).float64()
  88. return float64Value(math.Log2(number))
  89. }
  90. func builtinMathMax(call FunctionCall) Value {
  91. switch len(call.ArgumentList) {
  92. case 0:
  93. return negativeInfinityValue()
  94. case 1:
  95. return float64Value(call.ArgumentList[0].float64())
  96. }
  97. result := call.ArgumentList[0].float64()
  98. if math.IsNaN(result) {
  99. return NaNValue()
  100. }
  101. for _, value := range call.ArgumentList[1:] {
  102. value := value.float64()
  103. if math.IsNaN(value) {
  104. return NaNValue()
  105. }
  106. result = math.Max(result, value)
  107. }
  108. return float64Value(result)
  109. }
  110. func builtinMathMin(call FunctionCall) Value {
  111. switch len(call.ArgumentList) {
  112. case 0:
  113. return positiveInfinityValue()
  114. case 1:
  115. return float64Value(call.ArgumentList[0].float64())
  116. }
  117. result := call.ArgumentList[0].float64()
  118. if math.IsNaN(result) {
  119. return NaNValue()
  120. }
  121. for _, value := range call.ArgumentList[1:] {
  122. value := value.float64()
  123. if math.IsNaN(value) {
  124. return NaNValue()
  125. }
  126. result = math.Min(result, value)
  127. }
  128. return float64Value(result)
  129. }
  130. func builtinMathPow(call FunctionCall) Value {
  131. // TODO Make sure this works according to the specification (15.8.2.13)
  132. x := call.Argument(0).float64()
  133. y := call.Argument(1).float64()
  134. if math.Abs(x) == 1 && math.IsInf(y, 0) {
  135. return NaNValue()
  136. }
  137. return float64Value(math.Pow(x, y))
  138. }
  139. func builtinMathRandom(call FunctionCall) Value {
  140. var v float64
  141. if call.runtime.random != nil {
  142. v = call.runtime.random()
  143. } else {
  144. v = rand.Float64() //nolint:gosec
  145. }
  146. return float64Value(v)
  147. }
  148. func builtinMathRound(call FunctionCall) Value {
  149. number := call.Argument(0).float64()
  150. value := math.Floor(number + 0.5)
  151. if value == 0 {
  152. value = math.Copysign(0, number)
  153. }
  154. return float64Value(value)
  155. }
  156. func builtinMathSin(call FunctionCall) Value {
  157. number := call.Argument(0).float64()
  158. return float64Value(math.Sin(number))
  159. }
  160. func builtinMathSinh(call FunctionCall) Value {
  161. number := call.Argument(0).float64()
  162. return float64Value(math.Sinh(number))
  163. }
  164. func builtinMathSqrt(call FunctionCall) Value {
  165. number := call.Argument(0).float64()
  166. return float64Value(math.Sqrt(number))
  167. }
  168. func builtinMathTan(call FunctionCall) Value {
  169. number := call.Argument(0).float64()
  170. return float64Value(math.Tan(number))
  171. }
  172. func builtinMathTanh(call FunctionCall) Value {
  173. number := call.Argument(0).float64()
  174. return float64Value(math.Tanh(number))
  175. }
  176. func builtinMathTrunc(call FunctionCall) Value {
  177. number := call.Argument(0).float64()
  178. return float64Value(math.Trunc(number))
  179. }