decimal.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. // Copyright (C) MongoDB, Inc. 2017-present.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License"); you may
  4. // not use this file except in compliance with the License. You may obtain
  5. // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
  6. //
  7. // Based on gopkg.in/mgo.v2/bson by Gustavo Niemeyer
  8. // See THIRD-PARTY-NOTICES for original license terms.
  9. package primitive
  10. import (
  11. "encoding/json"
  12. "errors"
  13. "fmt"
  14. "math/big"
  15. "regexp"
  16. "strconv"
  17. "strings"
  18. )
  19. // These constants are the maximum and minimum values for the exponent field in a decimal128 value.
  20. const (
  21. MaxDecimal128Exp = 6111
  22. MinDecimal128Exp = -6176
  23. )
  24. // These errors are returned when an invalid value is parsed as a big.Int.
  25. var (
  26. ErrParseNaN = errors.New("cannot parse NaN as a *big.Int")
  27. ErrParseInf = errors.New("cannot parse Infinity as a *big.Int")
  28. ErrParseNegInf = errors.New("cannot parse -Infinity as a *big.Int")
  29. )
  30. // Decimal128 holds decimal128 BSON values.
  31. type Decimal128 struct {
  32. h, l uint64
  33. }
  34. // NewDecimal128 creates a Decimal128 using the provide high and low uint64s.
  35. func NewDecimal128(h, l uint64) Decimal128 {
  36. return Decimal128{h: h, l: l}
  37. }
  38. // GetBytes returns the underlying bytes of the BSON decimal value as two uint64 values. The first
  39. // contains the most first 8 bytes of the value and the second contains the latter.
  40. func (d Decimal128) GetBytes() (uint64, uint64) {
  41. return d.h, d.l
  42. }
  43. // String returns a string representation of the decimal value.
  44. func (d Decimal128) String() string {
  45. var posSign int // positive sign
  46. var exp int // exponent
  47. var high, low uint64 // significand high/low
  48. if d.h>>63&1 == 0 {
  49. posSign = 1
  50. }
  51. switch d.h >> 58 & (1<<5 - 1) {
  52. case 0x1F:
  53. return "NaN"
  54. case 0x1E:
  55. return "-Infinity"[posSign:]
  56. }
  57. low = d.l
  58. if d.h>>61&3 == 3 {
  59. // Bits: 1*sign 2*ignored 14*exponent 111*significand.
  60. // Implicit 0b100 prefix in significand.
  61. exp = int(d.h >> 47 & (1<<14 - 1))
  62. //high = 4<<47 | d.h&(1<<47-1)
  63. // Spec says all of these values are out of range.
  64. high, low = 0, 0
  65. } else {
  66. // Bits: 1*sign 14*exponent 113*significand
  67. exp = int(d.h >> 49 & (1<<14 - 1))
  68. high = d.h & (1<<49 - 1)
  69. }
  70. exp += MinDecimal128Exp
  71. // Would be handled by the logic below, but that's trivial and common.
  72. if high == 0 && low == 0 && exp == 0 {
  73. return "-0"[posSign:]
  74. }
  75. var repr [48]byte // Loop 5 times over 9 digits plus dot, negative sign, and leading zero.
  76. var last = len(repr)
  77. var i = len(repr)
  78. var dot = len(repr) + exp
  79. var rem uint32
  80. Loop:
  81. for d9 := 0; d9 < 5; d9++ {
  82. high, low, rem = divmod(high, low, 1e9)
  83. for d1 := 0; d1 < 9; d1++ {
  84. // Handle "-0.0", "0.00123400", "-1.00E-6", "1.050E+3", etc.
  85. if i < len(repr) && (dot == i || low == 0 && high == 0 && rem > 0 && rem < 10 && (dot < i-6 || exp > 0)) {
  86. exp += len(repr) - i
  87. i--
  88. repr[i] = '.'
  89. last = i - 1
  90. dot = len(repr) // Unmark.
  91. }
  92. c := '0' + byte(rem%10)
  93. rem /= 10
  94. i--
  95. repr[i] = c
  96. // Handle "0E+3", "1E+3", etc.
  97. if low == 0 && high == 0 && rem == 0 && i == len(repr)-1 && (dot < i-5 || exp > 0) {
  98. last = i
  99. break Loop
  100. }
  101. if c != '0' {
  102. last = i
  103. }
  104. // Break early. Works without it, but why.
  105. if dot > i && low == 0 && high == 0 && rem == 0 {
  106. break Loop
  107. }
  108. }
  109. }
  110. repr[last-1] = '-'
  111. last--
  112. if exp > 0 {
  113. return string(repr[last+posSign:]) + "E+" + strconv.Itoa(exp)
  114. }
  115. if exp < 0 {
  116. return string(repr[last+posSign:]) + "E" + strconv.Itoa(exp)
  117. }
  118. return string(repr[last+posSign:])
  119. }
  120. // BigInt returns significand as big.Int and exponent, bi * 10 ^ exp.
  121. func (d Decimal128) BigInt() (*big.Int, int, error) {
  122. high, low := d.GetBytes()
  123. posSign := high>>63&1 == 0 // positive sign
  124. switch high >> 58 & (1<<5 - 1) {
  125. case 0x1F:
  126. return nil, 0, ErrParseNaN
  127. case 0x1E:
  128. if posSign {
  129. return nil, 0, ErrParseInf
  130. }
  131. return nil, 0, ErrParseNegInf
  132. }
  133. var exp int
  134. if high>>61&3 == 3 {
  135. // Bits: 1*sign 2*ignored 14*exponent 111*significand.
  136. // Implicit 0b100 prefix in significand.
  137. exp = int(high >> 47 & (1<<14 - 1))
  138. //high = 4<<47 | d.h&(1<<47-1)
  139. // Spec says all of these values are out of range.
  140. high, low = 0, 0
  141. } else {
  142. // Bits: 1*sign 14*exponent 113*significand
  143. exp = int(high >> 49 & (1<<14 - 1))
  144. high = high & (1<<49 - 1)
  145. }
  146. exp += MinDecimal128Exp
  147. // Would be handled by the logic below, but that's trivial and common.
  148. if high == 0 && low == 0 && exp == 0 {
  149. if posSign {
  150. return new(big.Int), 0, nil
  151. }
  152. return new(big.Int), 0, nil
  153. }
  154. bi := big.NewInt(0)
  155. const host32bit = ^uint(0)>>32 == 0
  156. if host32bit {
  157. bi.SetBits([]big.Word{big.Word(low), big.Word(low >> 32), big.Word(high), big.Word(high >> 32)})
  158. } else {
  159. bi.SetBits([]big.Word{big.Word(low), big.Word(high)})
  160. }
  161. if !posSign {
  162. return bi.Neg(bi), exp, nil
  163. }
  164. return bi, exp, nil
  165. }
  166. // IsNaN returns whether d is NaN.
  167. func (d Decimal128) IsNaN() bool {
  168. return d.h>>58&(1<<5-1) == 0x1F
  169. }
  170. // IsInf returns:
  171. //
  172. // +1 d == Infinity
  173. // 0 other case
  174. // -1 d == -Infinity
  175. func (d Decimal128) IsInf() int {
  176. if d.h>>58&(1<<5-1) != 0x1E {
  177. return 0
  178. }
  179. if d.h>>63&1 == 0 {
  180. return 1
  181. }
  182. return -1
  183. }
  184. // IsZero returns true if d is the empty Decimal128.
  185. func (d Decimal128) IsZero() bool {
  186. return d.h == 0 && d.l == 0
  187. }
  188. // MarshalJSON returns Decimal128 as a string.
  189. func (d Decimal128) MarshalJSON() ([]byte, error) {
  190. return json.Marshal(d.String())
  191. }
  192. // UnmarshalJSON creates a primitive.Decimal128 from a JSON string, an extended JSON $numberDecimal value, or the string
  193. // "null". If b is a JSON string or extended JSON value, d will have the value of that string, and if b is "null", d will
  194. // be unchanged.
  195. func (d *Decimal128) UnmarshalJSON(b []byte) error {
  196. // Ignore "null" to keep parity with the standard library. Decoding a JSON null into a non-pointer Decimal128 field
  197. // will leave the field unchanged. For pointer values, encoding/json will set the pointer to nil and will not
  198. // enter the UnmarshalJSON hook.
  199. if string(b) == "null" {
  200. return nil
  201. }
  202. var res interface{}
  203. err := json.Unmarshal(b, &res)
  204. if err != nil {
  205. return err
  206. }
  207. str, ok := res.(string)
  208. // Extended JSON
  209. if !ok {
  210. m, ok := res.(map[string]interface{})
  211. if !ok {
  212. return errors.New("not an extended JSON Decimal128: expected document")
  213. }
  214. d128, ok := m["$numberDecimal"]
  215. if !ok {
  216. return errors.New("not an extended JSON Decimal128: expected key $numberDecimal")
  217. }
  218. str, ok = d128.(string)
  219. if !ok {
  220. return errors.New("not an extended JSON Decimal128: expected decimal to be string")
  221. }
  222. }
  223. *d, err = ParseDecimal128(str)
  224. return err
  225. }
  226. func divmod(h, l uint64, div uint32) (qh, ql uint64, rem uint32) {
  227. div64 := uint64(div)
  228. a := h >> 32
  229. aq := a / div64
  230. ar := a % div64
  231. b := ar<<32 + h&(1<<32-1)
  232. bq := b / div64
  233. br := b % div64
  234. c := br<<32 + l>>32
  235. cq := c / div64
  236. cr := c % div64
  237. d := cr<<32 + l&(1<<32-1)
  238. dq := d / div64
  239. dr := d % div64
  240. return (aq<<32 | bq), (cq<<32 | dq), uint32(dr)
  241. }
  242. var dNaN = Decimal128{0x1F << 58, 0}
  243. var dPosInf = Decimal128{0x1E << 58, 0}
  244. var dNegInf = Decimal128{0x3E << 58, 0}
  245. func dErr(s string) (Decimal128, error) {
  246. return dNaN, fmt.Errorf("cannot parse %q as a decimal128", s)
  247. }
  248. // match scientific notation number, example -10.15e-18
  249. var normalNumber = regexp.MustCompile(`^(?P<int>[-+]?\d*)?(?:\.(?P<dec>\d*))?(?:[Ee](?P<exp>[-+]?\d+))?$`)
  250. // ParseDecimal128 takes the given string and attempts to parse it into a valid
  251. // Decimal128 value.
  252. func ParseDecimal128(s string) (Decimal128, error) {
  253. if s == "" {
  254. return dErr(s)
  255. }
  256. matches := normalNumber.FindStringSubmatch(s)
  257. if len(matches) == 0 {
  258. orig := s
  259. neg := s[0] == '-'
  260. if neg || s[0] == '+' {
  261. s = s[1:]
  262. }
  263. if s == "NaN" || s == "nan" || strings.EqualFold(s, "nan") {
  264. return dNaN, nil
  265. }
  266. if s == "Inf" || s == "inf" || strings.EqualFold(s, "inf") || strings.EqualFold(s, "infinity") {
  267. if neg {
  268. return dNegInf, nil
  269. }
  270. return dPosInf, nil
  271. }
  272. return dErr(orig)
  273. }
  274. intPart := matches[1]
  275. decPart := matches[2]
  276. expPart := matches[3]
  277. var err error
  278. exp := 0
  279. if expPart != "" {
  280. exp, err = strconv.Atoi(expPart)
  281. if err != nil {
  282. return dErr(s)
  283. }
  284. }
  285. if decPart != "" {
  286. exp -= len(decPart)
  287. }
  288. if len(strings.Trim(intPart+decPart, "-0")) > 35 {
  289. return dErr(s)
  290. }
  291. // Parse the significand (i.e. the non-exponent part) as a big.Int.
  292. bi, ok := new(big.Int).SetString(intPart+decPart, 10)
  293. if !ok {
  294. return dErr(s)
  295. }
  296. d, ok := ParseDecimal128FromBigInt(bi, exp)
  297. if !ok {
  298. return dErr(s)
  299. }
  300. if bi.Sign() == 0 && s[0] == '-' {
  301. d.h |= 1 << 63
  302. }
  303. return d, nil
  304. }
  305. var (
  306. ten = big.NewInt(10)
  307. zero = new(big.Int)
  308. maxS, _ = new(big.Int).SetString("9999999999999999999999999999999999", 10)
  309. )
  310. // ParseDecimal128FromBigInt attempts to parse the given significand and exponent into a valid Decimal128 value.
  311. func ParseDecimal128FromBigInt(bi *big.Int, exp int) (Decimal128, bool) {
  312. //copy
  313. bi = new(big.Int).Set(bi)
  314. q := new(big.Int)
  315. r := new(big.Int)
  316. // If the significand is zero, the logical value will always be zero, independent of the
  317. // exponent. However, the loops for handling out-of-range exponent values below may be extremely
  318. // slow for zero values because the significand never changes. Limit the exponent value to the
  319. // supported range here to prevent entering the loops below.
  320. if bi.Cmp(zero) == 0 {
  321. if exp > MaxDecimal128Exp {
  322. exp = MaxDecimal128Exp
  323. }
  324. if exp < MinDecimal128Exp {
  325. exp = MinDecimal128Exp
  326. }
  327. }
  328. for bigIntCmpAbs(bi, maxS) == 1 {
  329. bi, _ = q.QuoRem(bi, ten, r)
  330. if r.Cmp(zero) != 0 {
  331. return Decimal128{}, false
  332. }
  333. exp++
  334. if exp > MaxDecimal128Exp {
  335. return Decimal128{}, false
  336. }
  337. }
  338. for exp < MinDecimal128Exp {
  339. // Subnormal.
  340. bi, _ = q.QuoRem(bi, ten, r)
  341. if r.Cmp(zero) != 0 {
  342. return Decimal128{}, false
  343. }
  344. exp++
  345. }
  346. for exp > MaxDecimal128Exp {
  347. // Clamped.
  348. bi.Mul(bi, ten)
  349. if bigIntCmpAbs(bi, maxS) == 1 {
  350. return Decimal128{}, false
  351. }
  352. exp--
  353. }
  354. b := bi.Bytes()
  355. var h, l uint64
  356. for i := 0; i < len(b); i++ {
  357. if i < len(b)-8 {
  358. h = h<<8 | uint64(b[i])
  359. continue
  360. }
  361. l = l<<8 | uint64(b[i])
  362. }
  363. h |= uint64(exp-MinDecimal128Exp) & uint64(1<<14-1) << 49
  364. if bi.Sign() == -1 {
  365. h |= 1 << 63
  366. }
  367. return Decimal128{h: h, l: l}, true
  368. }
  369. // bigIntCmpAbs computes big.Int.Cmp(absoluteValue(x), absoluteValue(y)).
  370. func bigIntCmpAbs(x, y *big.Int) int {
  371. xAbs := bigIntAbsValue(x)
  372. yAbs := bigIntAbsValue(y)
  373. return xAbs.Cmp(yAbs)
  374. }
  375. // bigIntAbsValue returns a big.Int containing the absolute value of b.
  376. // If b is already a non-negative number, it is returned without any changes or copies.
  377. func bigIntAbsValue(b *big.Int) *big.Int {
  378. if b.Sign() >= 0 {
  379. return b // already positive
  380. }
  381. return new(big.Int).Abs(b)
  382. }