int.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. // Copyright (c) 2018 The mathutil Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package mathutil // import "modernc.org/mathutil"
  5. import (
  6. "fmt"
  7. "math"
  8. "math/big"
  9. )
  10. var (
  11. // MaxInt128 represents the maximun Int128 value as big.Int
  12. MaxInt128 *big.Int
  13. // MinInt128 represents the minimun Int128 value as big.Int
  14. MinInt128 *big.Int
  15. // MaxUint128 represents the maximun Uint128 value as big.Int
  16. MaxUint128 *big.Int
  17. )
  18. func init() {
  19. var ok bool
  20. MaxInt128, ok = big.NewInt(0).SetString("0x7fffffff_ffffffff_ffffffff_ffffffff", 0)
  21. if !ok {
  22. panic("internal error")
  23. }
  24. MinInt128 = big.NewInt(0).Set(MaxInt128)
  25. MinInt128.Add(MinInt128, _1)
  26. MinInt128.Neg(MinInt128)
  27. MaxUint128, ok = big.NewInt(0).SetString("0xffffffff_ffffffff_ffffffff_ffffffff", 0)
  28. if !ok {
  29. panic("internal error")
  30. }
  31. }
  32. const (
  33. maxInt128 = 1<<127 - 1
  34. maxUint128 = 1<<128 - 1
  35. minInt128 = -maxInt128 - 1
  36. )
  37. // Int128 is an 128 bit signed integer.
  38. type Int128 struct {
  39. Lo int64 // Bits 63..0.
  40. Hi int64 // Bits 127..64.
  41. }
  42. // Add returns the sum of x and y and a carry indication.
  43. func (x Int128) Add(y Int128) (r Int128, cy bool) {
  44. r.Lo = x.Lo + y.Lo
  45. r.Hi = x.Hi + y.Hi
  46. if uint64(r.Lo) < uint64(x.Lo) {
  47. r.Hi++
  48. }
  49. return r, (r.Cmp(x) < 0) == (y.Sign() >= 0)
  50. }
  51. // BigInt returns x in the form of a big.Int.
  52. func (x Int128) BigInt() *big.Int {
  53. r := big.NewInt(x.Hi)
  54. r.Lsh(r, 64)
  55. lo := big.NewInt(0)
  56. lo.SetUint64(uint64(x.Lo))
  57. return r.Add(r, lo)
  58. }
  59. // Cmp compares x and y and returns:
  60. //
  61. // -1 if x < y
  62. // 0 if x == y
  63. // +1 if x > y
  64. func (x Int128) Cmp(y Int128) int {
  65. if x.Hi > y.Hi {
  66. return 1
  67. }
  68. if x.Hi < y.Hi {
  69. return -1
  70. }
  71. if uint64(x.Lo) > uint64(y.Lo) {
  72. return 1
  73. }
  74. if uint64(x.Lo) < uint64(y.Lo) {
  75. return -1
  76. }
  77. return 0
  78. }
  79. // Neg returns -x and an indication that x was not equal to MinInt128.
  80. func (x Int128) Neg() (r Int128, ok bool) {
  81. if x == (Int128{Hi: math.MinInt64}) {
  82. return x, false
  83. }
  84. x.Lo = ^x.Lo
  85. x.Hi = ^x.Hi
  86. r, _ = x.Add(Int128{Lo: 1})
  87. return r, true
  88. }
  89. // SetBigInt sets x to y, returns x and an error, if any.
  90. func (x *Int128) SetBigInt(y *big.Int) (r Int128, err error) {
  91. if y.Cmp(MaxInt128) > 0 {
  92. return *x, fmt.Errorf("%T.SetInt: overflow", x)
  93. }
  94. if y.Cmp(MinInt128) < 0 {
  95. return *x, fmt.Errorf("%T.SetInt: underflow", x)
  96. }
  97. neg := y.Sign() < 0
  98. var z big.Int
  99. z.Set(y)
  100. if neg {
  101. z.Neg(&z)
  102. }
  103. r.Lo = z.Int64()
  104. z.Rsh(&z, 64)
  105. r.Hi = z.Int64()
  106. if neg {
  107. r, _ = r.Neg()
  108. }
  109. *x = r
  110. return r, nil
  111. }
  112. // SetInt64 sets x to y and returns x.
  113. func (x *Int128) SetInt64(y int64) (r Int128) {
  114. r.Lo = y
  115. if y >= 0 {
  116. r.Hi = 0
  117. *x = r
  118. return r
  119. }
  120. r.Hi = -1
  121. *x = r
  122. return r
  123. }
  124. // SetUint64 sets x to y and returns x.
  125. func (x *Int128) SetUint64(y uint64) (r Int128) {
  126. r = Int128{Lo: int64(y)}
  127. *x = r
  128. return r
  129. }
  130. // Sign returns:
  131. //
  132. // -1 if x < 0
  133. // 0 if x == 0
  134. // +1 if x > 0
  135. func (x Int128) Sign() int {
  136. if x.Hi < 0 {
  137. return -1
  138. }
  139. if x.Hi != 0 || x.Lo != 0 {
  140. return 1
  141. }
  142. return 0
  143. }
  144. // String implements fmt.Stringer()
  145. func (x Int128) String() string { return x.BigInt().String() }
  146. // NewInt128FromInt64 return a new Int128 value initialized to n.
  147. func NewInt128FromInt64(n int64) (r Int128) {
  148. r.Lo = n
  149. if n < 0 {
  150. r.Hi = -1
  151. }
  152. return r
  153. }
  154. // NewInt128FromUint64 return a new Int128 value initialized to n.
  155. func NewInt128FromUint64(n uint64) (r Int128) { return Int128{Lo: int64(n)} }
  156. // NewInt128FromFloat32 returns a new Int128 value initialized to n. Result is
  157. // not specified in n does not represent a number within the range of Int128
  158. // values.
  159. func NewInt128FromFloat32(n float32) (r Int128) {
  160. if n >= minInt128 && n <= maxInt128 {
  161. if n >= math.MinInt64 && n <= math.MaxInt64 {
  162. return NewInt128FromInt64(int64(n))
  163. }
  164. f := big.NewFloat(float64(n))
  165. bi, _ := f.Int(nil)
  166. r.SetBigInt(bi)
  167. }
  168. return r
  169. }
  170. // NewInt128FromFloat64 returns a new Int128 value initialized to n. Result is
  171. // not specified in n does not represent a number within the range of Int128
  172. // values.
  173. func NewInt128FromFloat64(n float64) (r Int128) {
  174. if n >= minInt128 && n <= maxInt128 {
  175. if n >= math.MinInt64 && n <= math.MaxInt64 {
  176. return NewInt128FromInt64(int64(n))
  177. }
  178. f := big.NewFloat(n)
  179. bi, _ := f.Int(nil)
  180. r.SetBigInt(bi)
  181. }
  182. return r
  183. }
  184. // Uint128 is an 128 bit unsigned integer.
  185. type Uint128 struct {
  186. Lo uint64 // Bits 63..0.
  187. Hi uint64 // Bits 127..64.
  188. }
  189. // NewUint128FromInt64 return a new Uint128 value initialized to n.
  190. func NewUint128FromInt64(n int64) (r Uint128) {
  191. r.Lo = uint64(n)
  192. if n < 0 {
  193. r.Hi = ^uint64(0)
  194. }
  195. return r
  196. }
  197. // NewUint128FromUint64 return a new Uint128 value initialized to n.
  198. func NewUint128FromUint64(n uint64) (r Uint128) { return Uint128{Lo: n} }
  199. // NewUint128FromFloat32 returns a new Uint128 value initialized to n. Result is
  200. // not specified in n does not represent a number within the range of Uint128
  201. // values.
  202. func NewUint128FromFloat32(n float32) (r Uint128) {
  203. if n >= 0 {
  204. if n <= math.MaxUint64 {
  205. return NewUint128FromUint64(uint64(n))
  206. }
  207. f := big.NewFloat(float64(n))
  208. bi, _ := f.Int(nil)
  209. r.SetBigInt(bi)
  210. }
  211. return r
  212. }
  213. // NewUint128FromFloat64 returns a new Uint128 value initialized to n. Result is
  214. // not specified in n does not represent a number within the range of Uint128
  215. // values.
  216. func NewUint128FromFloat64(n float64) (r Uint128) {
  217. if n >= 0 && n <= maxUint128 {
  218. if n <= math.MaxUint64 {
  219. return NewUint128FromUint64(uint64(n))
  220. }
  221. f := big.NewFloat(n)
  222. bi, _ := f.Int(nil)
  223. r.SetBigInt(bi)
  224. }
  225. return r
  226. }
  227. // SetBigInt sets x to y, returns x and an error, if any.
  228. func (x *Uint128) SetBigInt(y *big.Int) (r Uint128, err error) {
  229. if y.Sign() < 0 || y.Cmp(MaxUint128) > 0 {
  230. return *x, fmt.Errorf("%T.SetInt: overflow", x)
  231. }
  232. var z big.Int
  233. z.Set(y)
  234. r.Lo = z.Uint64()
  235. z.Rsh(&z, 64)
  236. r.Hi = z.Uint64()
  237. *x = r
  238. return r, nil
  239. }