numeric.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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. if math.IsNaN(x) || math.IsInf(x, 0) {
  44. return false
  45. }
  46. return true
  47. }
  48. func IsNormalComplex(z complex128) bool {
  49. if cmplx.IsNaN(z) || cmplx.IsInf(z) {
  50. return false
  51. }
  52. return true
  53. }
  54. func WellBehavedParseInteger(chars ([] rune)) (*big.Int, bool) {
  55. var abs_chars ([] rune)
  56. if chars[0] == '-' {
  57. abs_chars = chars[1:]
  58. } else {
  59. abs_chars = chars
  60. }
  61. var has_base_prefix = false
  62. if len(abs_chars) >= 2 {
  63. var c1 = abs_chars[0]
  64. var c2 = abs_chars[1]
  65. if c1 == '0' &&
  66. (c2 == 'x' || c2 == 'o' || c2 == 'b' ||
  67. c2 == 'X' || c2 == 'O' || c2 == 'B') {
  68. has_base_prefix = true
  69. }
  70. }
  71. var str = string(chars)
  72. // note: forbid "0" as octal prefix
  73. if has_base_prefix {
  74. return big.NewInt(0).SetString(str, 0)
  75. } else {
  76. if len(str) >= 2 && str[0] == '0' {
  77. return nil, false
  78. }
  79. return big.NewInt(0).SetString(str, 10)
  80. }
  81. }
  82. func IntegerToDouble(value *big.Int) (float64, bool) {
  83. if value.IsInt64() {
  84. var i64 = value.Int64()
  85. var ok = MinSafeIntegerToDouble <= i64 && i64 <= MaxSafeIntegerToDouble
  86. if ok {
  87. return float64(i64), true
  88. } else {
  89. return math.NaN(), false
  90. }
  91. } else {
  92. return math.NaN(), false
  93. }
  94. }
  95. func ParseDouble(chars ([] rune)) (float64, bool) {
  96. var value, err = strconv.ParseFloat(string(chars), 64)
  97. if err != nil { return math.NaN(), false }
  98. return value, true
  99. }
  100. func ParseRune(chars ([] rune)) (rune, bool) {
  101. const E = utf8.RuneError
  102. var invalid = func() (rune, bool) {
  103. return E, false
  104. }
  105. var got = func(r rune) (rune, bool) {
  106. return r, true
  107. }
  108. if len(chars) == 0 {
  109. return invalid()
  110. } else if len(chars) == 1 {
  111. return got(chars[0])
  112. } else {
  113. var c0 = chars[0]
  114. if c0 == '`' {
  115. return got(chars[1])
  116. } else if c0 == '\\' {
  117. var c1 = chars[1]
  118. switch c1 {
  119. case 'n':
  120. return got('\n')
  121. case 'r':
  122. return got('\r')
  123. case 't':
  124. return got('\t')
  125. case 'e':
  126. return got('\033')
  127. case 'b':
  128. return got('\b')
  129. case 'a':
  130. return got('\a')
  131. case 'f':
  132. return got('\f')
  133. case 'u':
  134. var code_point_raw = string(chars[2:])
  135. var n, ok1 = big.NewInt(0).SetString(code_point_raw, 16)
  136. if !ok1 { return invalid() }
  137. var min = big.NewInt(0)
  138. var max = big.NewInt(unicode.MaxRune)
  139. var ok2 = ((min.Cmp(n) <= 0) && (n.Cmp(max) <= 0))
  140. if !ok2 { return invalid() }
  141. return got(rune(n.Int64()))
  142. default:
  143. return invalid()
  144. }
  145. } else {
  146. return invalid()
  147. }
  148. }
  149. }