numeric.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. package util
  2. import (
  3. "math"
  4. "math/big"
  5. "math/cmplx"
  6. "strconv"
  7. "unicode"
  8. "unicode/utf8"
  9. )
  10. const MaxSafeIntegerToDouble = 9007199254740991
  11. const MinSafeIntegerToDouble = -9007199254740991
  12. func GetNumberUint(small uint) *big.Int {
  13. var n big.Int
  14. n.SetUint64(uint64(small))
  15. return &n
  16. }
  17. func GetNumberUint64(small uint64) *big.Int {
  18. var n big.Int
  19. n.SetUint64(small)
  20. return &n
  21. }
  22. func GetUintNumber(n *big.Int) uint {
  23. if n.Cmp(big.NewInt(0)) < 0 { panic("something went wrong") }
  24. var limit big.Int
  25. limit.SetUint64(uint64(^uint(0)))
  26. if n.Cmp(&limit) <= 0 {
  27. return uint(n.Uint64())
  28. } else {
  29. panic("given number too big")
  30. }
  31. }
  32. func GetInt64Integer(n *big.Int) int64 {
  33. if n.IsInt64() {
  34. return n.Int64()
  35. } else {
  36. panic("given number too big")
  37. }
  38. }
  39. func IsNonNegative(n *big.Int) bool {
  40. return (n.Cmp(big.NewInt(0)) >= 0)
  41. }
  42. func IsNormalFloat(x float64) bool {
  43. return !(math.IsNaN(x) || math.IsInf(x, 0))
  44. }
  45. func IsNormalComplex(z complex128) bool {
  46. return !(cmplx.IsNaN(z) || cmplx.IsInf(z))
  47. }
  48. func WellBehavedParseInteger(chars ([] rune)) (*big.Int, bool) {
  49. var abs_chars ([] rune)
  50. if chars[0] == '-' {
  51. abs_chars = chars[1:]
  52. } else {
  53. abs_chars = chars
  54. }
  55. var has_base_prefix = false
  56. if len(abs_chars) >= 2 {
  57. var c1 = abs_chars[0]
  58. var c2 = abs_chars[1]
  59. if c1 == '0' &&
  60. (c2 == 'x' || c2 == 'o' || c2 == 'b' ||
  61. c2 == 'X' || c2 == 'O' || c2 == 'B') {
  62. has_base_prefix = true
  63. }
  64. }
  65. var str = string(chars)
  66. // note: forbid "0" as octal prefix
  67. if has_base_prefix {
  68. return big.NewInt(0).SetString(str, 0)
  69. } else {
  70. if len(str) >= 2 && str[0] == '0' {
  71. return nil, false
  72. }
  73. return big.NewInt(0).SetString(str, 10)
  74. }
  75. }
  76. func IntegerToDouble(value *big.Int) (float64, bool) {
  77. if value.IsInt64() {
  78. var i64 = value.Int64()
  79. var ok = MinSafeIntegerToDouble <= i64 && i64 <= MaxSafeIntegerToDouble
  80. if ok {
  81. return float64(i64), true
  82. } else {
  83. return math.NaN(), false
  84. }
  85. } else {
  86. return math.NaN(), false
  87. }
  88. }
  89. func ParseDouble(chars ([] rune)) (float64, bool) {
  90. var value, err = strconv.ParseFloat(string(chars), 64)
  91. if err != nil { return math.NaN(), false }
  92. return value, true
  93. }
  94. func ParseRune(chars ([] rune)) (rune, bool) {
  95. const E = utf8.RuneError
  96. var invalid = func() (rune, bool) {
  97. return E, false
  98. }
  99. var got = func(r rune) (rune, bool) {
  100. return r, true
  101. }
  102. if len(chars) == 0 {
  103. return invalid()
  104. } else if len(chars) == 1 {
  105. return got(chars[0])
  106. } else {
  107. var c0 = chars[0]
  108. if c0 == '`' {
  109. return got(chars[1])
  110. } else if c0 == '\\' {
  111. var c1 = chars[1]
  112. switch c1 {
  113. case 'n':
  114. return got('\n')
  115. case 'r':
  116. return got('\r')
  117. case 't':
  118. return got('\t')
  119. case 'e':
  120. return got('\033')
  121. case 'b':
  122. return got('\b')
  123. case 'a':
  124. return got('\a')
  125. case 'f':
  126. return got('\f')
  127. case 'u':
  128. var code_point_raw = string(chars[2:])
  129. var n, ok1 = big.NewInt(0).SetString(code_point_raw, 16)
  130. if !ok1 { return invalid() }
  131. var min = big.NewInt(0)
  132. var max = big.NewInt(unicode.MaxRune)
  133. var ok2 = ((min.Cmp(n) <= 0) && (n.Cmp(max) <= 0))
  134. if !ok2 { return invalid() }
  135. return got(rune(n.Int64()))
  136. default:
  137. return invalid()
  138. }
  139. } else {
  140. return invalid()
  141. }
  142. }
  143. }