math.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. package main
  2. import (
  3. "fmt"
  4. "math"
  5. "math/rand"
  6. "strconv"
  7. )
  8. func opAdd(val1, val2 value) value {
  9. num1, num2 := toNumber(val1.val), toNumber(val2.val)
  10. return value{val: strconv.FormatFloat(num1+num2, 'g', -1, 64)}
  11. }
  12. func opSub(val1, val2 value) value {
  13. num1, num2 := toNumber(val1.val), toNumber(val2.val)
  14. return value{val: strconv.FormatFloat(num1-num2, 'g', -1, 64)}
  15. }
  16. func opMul(val1, val2 value) value {
  17. num1, num2 := toNumber(val1.val), toNumber(val2.val)
  18. return value{val: strconv.FormatFloat(num1*num2, 'g', -1, 64)}
  19. }
  20. func opDiv(val1, val2 value) value {
  21. num1, num2 := toNumber(val1.val), toNumber(val2.val)
  22. if num2 == 0 {
  23. panic(fmt.Errorf("div: %s (%s / %s)", errDivisionByZero, val1.val, val2.val))
  24. }
  25. return value{val: strconv.FormatFloat(num1/num2, 'g', -1, 64)}
  26. }
  27. func opMod(val1, val2 value) value {
  28. num1, num2 := toNumber(val1.val), toNumber(val2.val)
  29. if num2 == 0 {
  30. panic(fmt.Errorf("mod: %s (%s %% %s)", errDivisionByZero, val1.val, val2.val))
  31. }
  32. return value{val: strconv.FormatFloat(math.Mod(num1, num2), 'g', -1, 64)}
  33. }
  34. func opEq(val1, val2 value) value {
  35. if isNumber(val1.val) && isNumber(val2.val) {
  36. num1, num2 := toNumber(val1.val), toNumber(val2.val)
  37. return value{val: strconv.FormatBool(num1 == num2)}
  38. }
  39. if isBool(val1.val) && isBool(val2.val) {
  40. b1, b2 := toBool(val1.val), toBool(val2.val)
  41. return value{val: strconv.FormatBool(b1 == b2)}
  42. }
  43. if isWord(val1.val) && isWord(val2.val) {
  44. return value{val: strconv.FormatBool(val1.val == val2.val)}
  45. }
  46. panic(fmt.Errorf("eq: %s (%s, %s)", errIllegalOperandType, val1.val, val2.val))
  47. }
  48. func opGt(val1, val2 value) value {
  49. if isNumber(val1.val) && isNumber(val2.val) {
  50. num1, num2 := toNumber(val1.val), toNumber(val2.val)
  51. return value{val: strconv.FormatBool(num1 > num2)}
  52. }
  53. if isBool(val1.val) && isBool(val2.val) {
  54. b1, b2 := toBool(val1.val), toBool(val2.val)
  55. return value{val: strconv.FormatBool(b1 || !b2)}
  56. }
  57. if isWord(val1.val) && isWord(val2.val) {
  58. return value{val: strconv.FormatBool(val1.val > val2.val)}
  59. }
  60. panic(fmt.Errorf("gt: %s (%s, %s)", errIllegalOperandType, val1.val, val2.val))
  61. }
  62. func opLt(val1, val2 value) value {
  63. if isNumber(val1.val) && isNumber(val2.val) {
  64. num1, num2 := toNumber(val1.val), toNumber(val2.val)
  65. return value{val: strconv.FormatBool(num1 < num2)}
  66. }
  67. if isBool(val1.val) && isBool(val2.val) {
  68. b1, b2 := toBool(val1.val), toBool(val2.val)
  69. return value{val: strconv.FormatBool(!b1 || b2)}
  70. }
  71. if isWord(val1.val) && isWord(val2.val) {
  72. return value{val: strconv.FormatBool(val1.val < val2.val)}
  73. }
  74. panic(fmt.Errorf("lt: %s (%s, %s)", errIllegalOperandType, val1.val, val2.val))
  75. }
  76. func opAnd(val1, val2 value) value {
  77. b1, b2 := toBool(val1.val), toBool(val2.val)
  78. return value{val: strconv.FormatBool(b1 && b2)}
  79. }
  80. func opOr(val1, val2 value) value {
  81. b1, b2 := toBool(val1.val), toBool(val2.val)
  82. return value{val: strconv.FormatBool(b1 || b2)}
  83. }
  84. func opNot(val1 value) value {
  85. b1 := toBool(val1.val)
  86. return value{val: strconv.FormatBool(!b1)}
  87. }
  88. func opRandom(val1 value) value {
  89. return value{val: strconv.FormatFloat(toNumber(val1.val)*rand.Float64(), 'g', -1, 64)}
  90. }
  91. func opInt(val1 value) value {
  92. return value{val: strconv.FormatFloat(math.Floor(toNumber(val1.val)), 'g', -1, 64)}
  93. }
  94. func opSqrt(val1 value) value {
  95. num1 := toNumber(val1.val)
  96. if num1 < 0 {
  97. panic(fmt.Errorf("sqrt: %s (%s)", errNegativeSquareRoot, val1.val))
  98. }
  99. return value{val: strconv.FormatFloat(math.Sqrt(num1), 'g', -1, 64)}
  100. }