int128.nim 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  1. ## This module is for compiler internal use only. For reliable error
  2. ## messages and range checks, the compiler needs a data type that can
  3. ## hold all from ``low(BiggestInt)`` to ``high(BiggestUInt)``, This
  4. ## type is for that purpose.
  5. from math import trunc
  6. type
  7. Int128* = object
  8. udata: array[4,uint32]
  9. template sdata(arg: Int128, idx: int): int32 =
  10. # udata and sdata was supposed to be in a union, but unions are
  11. # handled incorrectly in the VM.
  12. cast[ptr int32](arg.udata[idx].unsafeAddr)[]
  13. # encoding least significant int first (like LittleEndian)
  14. const
  15. Zero* = Int128(udata: [0'u32,0,0,0])
  16. One* = Int128(udata: [1'u32,0,0,0])
  17. Ten* = Int128(udata: [10'u32,0,0,0])
  18. Min = Int128(udata: [0'u32,0,0,0x80000000'u32])
  19. Max = Int128(udata: [high(uint32),high(uint32),high(uint32),uint32(high(int32))])
  20. NegOne* = Int128(udata: [0xffffffff'u32,0xffffffff'u32,0xffffffff'u32,0xffffffff'u32])
  21. template low*(t: typedesc[Int128]): Int128 = Min
  22. template high*(t: typedesc[Int128]): Int128 = Max
  23. proc `$`*(a: Int128): string
  24. proc toInt128*[T: SomeInteger | bool](arg: T): Int128 =
  25. when T is bool: result.sdata(0) = int32(arg)
  26. elif T is SomeUnsignedInt:
  27. when sizeof(arg) <= 4:
  28. result.udata[0] = uint32(arg)
  29. else:
  30. result.udata[0] = uint32(arg and T(0xffffffff))
  31. result.udata[1] = uint32(arg shr 32)
  32. elif sizeof(arg) <= 4:
  33. result.sdata(0) = int32(arg)
  34. if arg < 0: # sign extend
  35. result.sdata(1) = -1
  36. result.sdata(2) = -1
  37. result.sdata(3) = -1
  38. else:
  39. let tmp = int64(arg)
  40. result.udata[0] = uint32(tmp and 0xffffffff)
  41. result.sdata(1) = int32(tmp shr 32)
  42. if arg < 0: # sign extend
  43. result.sdata(2) = -1
  44. result.sdata(3) = -1
  45. template isNegative(arg: Int128): bool =
  46. arg.sdata(3) < 0
  47. template isNegative(arg: int32): bool =
  48. arg < 0
  49. proc bitconcat(a,b: uint32): uint64 =
  50. (uint64(a) shl 32) or uint64(b)
  51. proc bitsplit(a: uint64): (uint32,uint32) =
  52. (cast[uint32](a shr 32), cast[uint32](a))
  53. proc toInt64*(arg: Int128): int64 =
  54. if isNegative(arg):
  55. assert(arg.sdata(3) == -1, "out of range")
  56. assert(arg.sdata(2) == -1, "out of range")
  57. else:
  58. assert(arg.sdata(3) == 0, "out of range")
  59. assert(arg.sdata(2) == 0, "out of range")
  60. cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
  61. proc toInt64Checked*(arg: Int128; onError: int64): int64 =
  62. if isNegative(arg):
  63. if arg.sdata(3) != -1 or arg.sdata(2) != -1:
  64. return onError
  65. else:
  66. if arg.sdata(3) != 0 or arg.sdata(2) != 0:
  67. return onError
  68. return cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
  69. proc toInt32*(arg: Int128): int32 =
  70. if isNegative(arg):
  71. assert(arg.sdata(3) == -1, "out of range")
  72. assert(arg.sdata(2) == -1, "out of range")
  73. assert(arg.sdata(1) == -1, "out of range")
  74. else:
  75. assert(arg.sdata(3) == 0, "out of range")
  76. assert(arg.sdata(2) == 0, "out of range")
  77. assert(arg.sdata(1) == 0, "out of range")
  78. arg.sdata(0)
  79. proc toInt16*(arg: Int128): int16 =
  80. if isNegative(arg):
  81. assert(arg.sdata(3) == -1, "out of range")
  82. assert(arg.sdata(2) == -1, "out of range")
  83. assert(arg.sdata(1) == -1, "out of range")
  84. else:
  85. assert(arg.sdata(3) == 0, "out of range")
  86. assert(arg.sdata(2) == 0, "out of range")
  87. assert(arg.sdata(1) == 0, "out of range")
  88. int16(arg.sdata(0))
  89. proc toInt8*(arg: Int128): int8 =
  90. if isNegative(arg):
  91. assert(arg.sdata(3) == -1, "out of range")
  92. assert(arg.sdata(2) == -1, "out of range")
  93. assert(arg.sdata(1) == -1, "out of range")
  94. else:
  95. assert(arg.sdata(3) == 0, "out of range")
  96. assert(arg.sdata(2) == 0, "out of range")
  97. assert(arg.sdata(1) == 0, "out of range")
  98. int8(arg.sdata(0))
  99. proc toInt*(arg: Int128): int =
  100. when sizeof(int) == 4:
  101. cast[int](toInt32(arg))
  102. else:
  103. cast[int](toInt64(arg))
  104. proc toUInt64*(arg: Int128): uint64 =
  105. assert(arg.udata[3] == 0)
  106. assert(arg.udata[2] == 0)
  107. bitconcat(arg.udata[1], arg.udata[0])
  108. proc toUInt32*(arg: Int128): uint32 =
  109. assert(arg.udata[3] == 0)
  110. assert(arg.udata[2] == 0)
  111. assert(arg.udata[1] == 0)
  112. arg.udata[0]
  113. proc toUInt16*(arg: Int128): uint16 =
  114. assert(arg.udata[3] == 0)
  115. assert(arg.udata[2] == 0)
  116. assert(arg.udata[1] == 0)
  117. uint16(arg.udata[0])
  118. proc toUInt8*(arg: Int128): uint8 =
  119. assert(arg.udata[3] == 0)
  120. assert(arg.udata[2] == 0)
  121. assert(arg.udata[1] == 0)
  122. uint8(arg.udata[0])
  123. proc toUInt*(arg: Int128): uint =
  124. when sizeof(int) == 4:
  125. cast[uint](toInt32(arg))
  126. else:
  127. cast[uint](toInt64(arg))
  128. proc castToInt64*(arg: Int128): int64 =
  129. ## Conversion to int64 without range check.
  130. cast[int64](bitconcat(arg.udata[1], arg.udata[0]))
  131. proc castToUInt64*(arg: Int128): uint64 =
  132. ## Conversion to uint64 without range check.
  133. cast[uint64](bitconcat(arg.udata[1], arg.udata[0]))
  134. proc addToHex(result: var string; arg: uint32) =
  135. for i in 0..<8:
  136. let idx = (arg shr ((7-i) * 4)) and 0xf
  137. result.add "0123456789abcdef"[idx]
  138. proc addToHex*(result: var string; arg: Int128) =
  139. var i = 3
  140. while i >= 0:
  141. result.addToHex(arg.udata[i])
  142. i -= 1
  143. proc toHex*(arg: Int128): string =
  144. result.addToHex(arg)
  145. proc inc*(a: var Int128, y: uint32 = 1) =
  146. let input = a
  147. a.udata[0] += y
  148. if unlikely(a.udata[0] < y):
  149. a.udata[1].inc
  150. if unlikely(a.udata[1] == 0):
  151. a.udata[2].inc
  152. if unlikely(a.udata[2] == 0):
  153. a.udata[3].inc
  154. doAssert(a.sdata(3) != low(int32), "overflow")
  155. proc cmp*(a,b: Int128): int =
  156. let tmp1 = cmp(a.sdata(3), b.sdata(3))
  157. if tmp1 != 0: return tmp1
  158. let tmp2 = cmp(a.udata[2], b.udata[2])
  159. if tmp2 != 0: return tmp2
  160. let tmp3 = cmp(a.udata[1], b.udata[1])
  161. if tmp3 != 0: return tmp3
  162. let tmp4 = cmp(a.udata[0], b.udata[0])
  163. return tmp4
  164. proc `<`*(a,b: Int128): bool =
  165. cmp(a,b) < 0
  166. proc `<=`*(a,b: Int128): bool =
  167. cmp(a,b) <= 0
  168. proc `==`*(a,b: Int128): bool =
  169. if a.udata[0] != b.udata[0]: return false
  170. if a.udata[1] != b.udata[1]: return false
  171. if a.udata[2] != b.udata[2]: return false
  172. if a.udata[3] != b.udata[3]: return false
  173. return true
  174. proc inplaceBitnot(a: var Int128) =
  175. a.udata[0] = not a.udata[0]
  176. a.udata[1] = not a.udata[1]
  177. a.udata[2] = not a.udata[2]
  178. a.udata[3] = not a.udata[3]
  179. proc bitnot*(a: Int128): Int128 =
  180. result.udata[0] = not a.udata[0]
  181. result.udata[1] = not a.udata[1]
  182. result.udata[2] = not a.udata[2]
  183. result.udata[3] = not a.udata[3]
  184. proc bitand*(a,b: Int128): Int128 =
  185. result.udata[0] = a.udata[0] and b.udata[0]
  186. result.udata[1] = a.udata[1] and b.udata[1]
  187. result.udata[2] = a.udata[2] and b.udata[2]
  188. result.udata[3] = a.udata[3] and b.udata[3]
  189. proc bitor*(a,b: Int128): Int128 =
  190. result.udata[0] = a.udata[0] or b.udata[0]
  191. result.udata[1] = a.udata[1] or b.udata[1]
  192. result.udata[2] = a.udata[2] or b.udata[2]
  193. result.udata[3] = a.udata[3] or b.udata[3]
  194. proc bitxor*(a,b: Int128): Int128 =
  195. result.udata[0] = a.udata[0] xor b.udata[0]
  196. result.udata[1] = a.udata[1] xor b.udata[1]
  197. result.udata[2] = a.udata[2] xor b.udata[2]
  198. result.udata[3] = a.udata[3] xor b.udata[3]
  199. proc `shr`*(a: Int128, b: int): Int128 =
  200. let b = b and 127
  201. if b < 32:
  202. result.sdata(3) = a.sdata(3) shr b
  203. result.udata[2] = cast[uint32](bitconcat(a.udata[3], a.udata[2]) shr b)
  204. result.udata[1] = cast[uint32](bitconcat(a.udata[2], a.udata[1]) shr b)
  205. result.udata[0] = cast[uint32](bitconcat(a.udata[1], a.udata[0]) shr b)
  206. elif b < 64:
  207. if isNegative(a):
  208. result.sdata(3) = -1
  209. result.sdata(2) = a.sdata(3) shr (b and 31)
  210. result.udata[1] = cast[uint32](bitconcat(a.udata[3], a.udata[2]) shr (b and 31))
  211. result.udata[0] = cast[uint32](bitconcat(a.udata[2], a.udata[1]) shr (b and 31))
  212. elif b < 96:
  213. if isNegative(a):
  214. result.sdata(3) = -1
  215. result.sdata(2) = -1
  216. result.sdata(1) = a.sdata(3) shr (b and 31)
  217. result.udata[0] = cast[uint32](bitconcat(a.udata[3], a.udata[2]) shr (b and 31))
  218. else: # b < 128
  219. if isNegative(a):
  220. result.sdata(3) = -1
  221. result.sdata(2) = -1
  222. result.sdata(1) = -1
  223. result.sdata(0) = a.sdata(3) shr (b and 31)
  224. proc `shl`*(a: Int128, b: int): Int128 =
  225. let b = b and 127
  226. if b < 32:
  227. result.udata[0] = a.udata[0] shl b
  228. result.udata[1] = cast[uint32]((bitconcat(a.udata[1], a.udata[0]) shl b) shr 32)
  229. result.udata[2] = cast[uint32]((bitconcat(a.udata[2], a.udata[1]) shl b) shr 32)
  230. result.udata[3] = cast[uint32]((bitconcat(a.udata[3], a.udata[2]) shl b) shr 32)
  231. elif b < 64:
  232. result.udata[0] = 0
  233. result.udata[1] = a.udata[0] shl (b and 31)
  234. result.udata[2] = cast[uint32]((bitconcat(a.udata[1], a.udata[0]) shl (b and 31)) shr 32)
  235. result.udata[3] = cast[uint32]((bitconcat(a.udata[2], a.udata[1]) shl (b and 31)) shr 32)
  236. elif b < 96:
  237. result.udata[0] = 0
  238. result.udata[1] = 0
  239. result.udata[2] = a.udata[0] shl (b and 31)
  240. result.udata[3] = cast[uint32]((bitconcat(a.udata[1], a.udata[0]) shl (b and 31)) shr 32)
  241. else:
  242. result.udata[0] = 0
  243. result.udata[1] = 0
  244. result.udata[2] = 0
  245. result.udata[3] = a.udata[0] shl (b and 31)
  246. proc `+`*(a,b: Int128): Int128 =
  247. let tmp0 = uint64(a.udata[0]) + uint64(b.udata[0])
  248. result.udata[0] = cast[uint32](tmp0)
  249. let tmp1 = uint64(a.udata[1]) + uint64(b.udata[1]) + (tmp0 shr 32)
  250. result.udata[1] = cast[uint32](tmp1)
  251. let tmp2 = uint64(a.udata[2]) + uint64(b.udata[2]) + (tmp1 shr 32)
  252. result.udata[2] = cast[uint32](tmp2)
  253. let tmp3 = uint64(a.udata[3]) + uint64(b.udata[3]) + (tmp2 shr 32)
  254. result.udata[3] = cast[uint32](tmp3)
  255. proc `+=`*(a: var Int128, b: Int128) =
  256. a = a + b
  257. proc `-`*(a: Int128): Int128 =
  258. result = bitnot(a)
  259. result.inc
  260. proc `-`*(a,b: Int128): Int128 =
  261. a + (-b)
  262. proc `-=`*(a: var Int128, b: Int128) =
  263. a = a - b
  264. proc abs*(a: Int128): Int128 =
  265. if isNegative(a):
  266. -a
  267. else:
  268. a
  269. proc abs(a: int32): int =
  270. if a < 0: -a else: a
  271. proc `*`(a: Int128, b: uint32): Int128 =
  272. let tmp0 = uint64(a.udata[0]) * uint64(b)
  273. let tmp1 = uint64(a.udata[1]) * uint64(b)
  274. let tmp2 = uint64(a.udata[2]) * uint64(b)
  275. let tmp3 = uint64(a.udata[3]) * uint64(b)
  276. if unlikely(tmp3 > uint64(high(int32))):
  277. assert(false, "overflow")
  278. result.udata[0] = cast[uint32](tmp0)
  279. result.udata[1] = cast[uint32](tmp1) + cast[uint32](tmp0 shr 32)
  280. result.udata[2] = cast[uint32](tmp2) + cast[uint32](tmp1 shr 32)
  281. result.udata[3] = cast[uint32](tmp3) + cast[uint32](tmp2 shr 32)
  282. proc `*`*(a: Int128, b: int32): Int128 =
  283. result = a * cast[uint32](abs(b))
  284. if b < 0:
  285. result = -result
  286. proc `*=`*(a: var Int128, b: int32): Int128 =
  287. result = result * b
  288. proc makeInt128(high,low: uint64): Int128 =
  289. result.udata[0] = cast[uint32](low)
  290. result.udata[1] = cast[uint32](low shr 32)
  291. result.udata[2] = cast[uint32](high)
  292. result.udata[3] = cast[uint32](high shr 32)
  293. proc high64(a: Int128): uint64 =
  294. bitconcat(a.udata[3], a.udata[2])
  295. proc low64(a: Int128): uint64 =
  296. bitconcat(a.udata[1], a.udata[0])
  297. proc `*`*(lhs,rhs: Int128): Int128 =
  298. let
  299. a = cast[uint64](lhs.udata[0])
  300. b = cast[uint64](lhs.udata[1])
  301. c = cast[uint64](lhs.udata[2])
  302. d = cast[uint64](lhs.udata[3])
  303. e = cast[uint64](rhs.udata[0])
  304. f = cast[uint64](rhs.udata[1])
  305. g = cast[uint64](rhs.udata[2])
  306. h = cast[uint64](rhs.udata[3])
  307. let a32 = cast[uint64](lhs.udata[1])
  308. let a00 = cast[uint64](lhs.udata[0])
  309. let b32 = cast[uint64](rhs.udata[1])
  310. let b00 = cast[uint64](rhs.udata[0])
  311. result = makeInt128(high64(lhs) * low64(rhs) + low64(lhs) * high64(rhs) + a32 * b32, a00 * b00)
  312. result = result + toInt128(a32 * b00) shl 32
  313. result = result + toInt128(a00 * b32) shl 32
  314. proc `*=`*(a: var Int128, b: Int128) =
  315. a = a * b
  316. import bitops
  317. proc fastLog2*(a: Int128): int =
  318. if a.udata[3] != 0:
  319. return 96 + fastLog2(a.udata[3])
  320. if a.udata[2] != 0:
  321. return 64 + fastLog2(a.udata[2])
  322. if a.udata[1] != 0:
  323. return 32 + fastLog2(a.udata[1])
  324. if a.udata[0] != 0:
  325. return fastLog2(a.udata[0])
  326. proc divMod*(dividend, divisor: Int128): tuple[quotient, remainder: Int128] =
  327. assert(divisor != Zero)
  328. let isNegativeA = isNegative(dividend)
  329. let isNegativeB = isNegative(divisor)
  330. var dividend = abs(dividend)
  331. let divisor = abs(divisor)
  332. if divisor > dividend:
  333. result.quotient = Zero
  334. if isNegativeA:
  335. result.remainder = -dividend
  336. else:
  337. result.remainder = dividend
  338. return
  339. if divisor == dividend:
  340. if isNegativeA xor isNegativeB:
  341. result.quotient = NegOne
  342. else:
  343. result.quotient = One
  344. result.remainder = Zero
  345. return
  346. var denominator = divisor
  347. var quotient = Zero
  348. # Left aligns the MSB of the denominator and the dividend.
  349. let shift = fastLog2(dividend) - fastLog2(denominator)
  350. denominator = denominator shl shift
  351. # Uses shift-subtract algorithm to divide dividend by denominator. The
  352. # remainder will be left in dividend.
  353. for i in 0..shift:
  354. quotient = quotient shl 1
  355. if dividend >= denominator:
  356. dividend = dividend - denominator
  357. quotient = bitor(quotient, One)
  358. denominator = denominator shr 1
  359. if isNegativeA xor isNegativeB:
  360. result.quotient = -quotient
  361. else:
  362. result.quotient = quotient
  363. if isNegativeA:
  364. result.remainder = -dividend
  365. else:
  366. result.remainder = dividend
  367. proc `div`*(a,b: Int128): Int128 =
  368. let (a,b) = divMod(a,b)
  369. return a
  370. proc `mod`*(a,b: Int128): Int128 =
  371. let (a,b) = divMod(a,b)
  372. return b
  373. proc addInt128*(result: var string; value: Int128) =
  374. let initialSize = result.len
  375. if value == Zero:
  376. result.add "0"
  377. elif value == low(Int128):
  378. result.add "-170141183460469231731687303715884105728"
  379. else:
  380. let isNegative = isNegative(value)
  381. var value = abs(value)
  382. while value > Zero:
  383. let (quot, rem) = divMod(value, Ten)
  384. result.add "0123456789"[rem.toInt64]
  385. value = quot
  386. if isNegative:
  387. result.add '-'
  388. var i = initialSize
  389. var j = high(result)
  390. while i < j:
  391. swap(result[i], result[j])
  392. i += 1
  393. j -= 1
  394. proc `$`*(a: Int128): string =
  395. result.addInt128(a)
  396. proc parseDecimalInt128*(arg: string, pos: int = 0): Int128 =
  397. assert(pos < arg.len)
  398. assert(arg[pos] in {'-','0'..'9'})
  399. var isNegative = false
  400. var pos = pos
  401. if arg[pos] == '-':
  402. isNegative = true
  403. pos += 1
  404. result = Zero
  405. while pos < arg.len and arg[pos] in '0'..'9':
  406. result = result * Ten
  407. result.inc(uint32(arg[pos]) - uint32('0'))
  408. pos += 1
  409. if isNegative:
  410. result = -result
  411. # fluff
  412. proc `<`*(a: Int128, b: BiggestInt): bool =
  413. cmp(a,toInt128(b)) < 0
  414. proc `<`*(a: BiggestInt, b: Int128): bool =
  415. cmp(toInt128(a), b) < 0
  416. proc `<=`*(a: Int128, b: BiggestInt): bool =
  417. cmp(a,toInt128(b)) <= 0
  418. proc `<=`*(a: BiggestInt, b: Int128): bool =
  419. cmp(toInt128(a), b) <= 0
  420. proc `==`*(a: Int128, b: BiggestInt): bool =
  421. a == toInt128(b)
  422. proc `==`*(a: BiggestInt, b: Int128): bool =
  423. toInt128(a) == b
  424. proc `-`*(a: BiggestInt, b: Int128): Int128 =
  425. toInt128(a) - b
  426. proc `-`*(a: Int128, b: BiggestInt): Int128 =
  427. a - toInt128(b)
  428. proc `+`*(a: BiggestInt, b: Int128): Int128 =
  429. toInt128(a) + b
  430. proc `+`*(a: Int128, b: BiggestInt): Int128 =
  431. a + toInt128(b)
  432. proc toFloat64*(arg: Int128): float64 =
  433. let isNegative = isNegative(arg)
  434. let arg = abs(arg)
  435. let a = float64(bitconcat(arg.udata[1], arg.udata[0]))
  436. let b = float64(bitconcat(arg.udata[3], arg.udata[2]))
  437. result = a + 18446744073709551616'f64 * b # a + 2^64 * b
  438. if isNegative:
  439. result = -result
  440. proc ldexp(x: float64, exp: cint): float64 {.importc: "ldexp", header: "<math.h>".}
  441. template bitor(a,b,c: Int128): Int128 = bitor(bitor(a,b), c)
  442. proc toInt128*(arg: float64): Int128 =
  443. let isNegative = arg < 0
  444. let v0 = ldexp(abs(arg), -100)
  445. let w0 = uint64(trunc(v0))
  446. let v1 = ldexp(v0 - float64(w0), 50)
  447. let w1 = uint64(trunc(v1))
  448. let v2 = ldexp(v1 - float64(w1), 50)
  449. let w2 = uint64(trunc(v2))
  450. let res = bitor(toInt128(w0) shl 100, toInt128(w1) shl 50, toInt128(w2))
  451. if isNegative:
  452. return -res
  453. else:
  454. return res
  455. proc maskUInt64*(arg: Int128): Int128 {.noinit, inline.} =
  456. result.udata[0] = arg.udata[0]
  457. result.udata[1] = arg.udata[1]
  458. result.udata[2] = 0
  459. result.udata[3] = 0
  460. proc maskUInt32*(arg: Int128): Int128 {.noinit, inline.} =
  461. result.udata[0] = arg.udata[0]
  462. result.udata[1] = 0
  463. result.udata[2] = 0
  464. result.udata[3] = 0
  465. proc maskUInt16*(arg: Int128): Int128 {.noinit, inline.} =
  466. result.udata[0] = arg.udata[0] and 0xffff
  467. result.udata[1] = 0
  468. result.udata[2] = 0
  469. result.udata[3] = 0
  470. proc maskUInt8*(arg: Int128): Int128 {.noinit, inline.} =
  471. result.udata[0] = arg.udata[0] and 0xff
  472. result.udata[1] = 0
  473. result.udata[2] = 0
  474. result.udata[3] = 0
  475. proc maskBytes*(arg: Int128, numbytes: int): Int128 {.noinit.} =
  476. case numbytes
  477. of 1:
  478. return maskUInt8(arg)
  479. of 2:
  480. return maskUInt16(arg)
  481. of 4:
  482. return maskUInt32(arg)
  483. of 8:
  484. return maskUInt64(arg)
  485. else:
  486. assert(false, "masking only implemented for 1, 2, 4 and 8 bytes")
  487. when isMainModule:
  488. let (a,b) = divMod(Ten,Ten)
  489. doAssert $One == "1"
  490. doAssert $Ten == "10"
  491. doAssert $Zero == "0"
  492. let c = parseDecimalInt128("12345678989876543210123456789")
  493. doAssert $c == "12345678989876543210123456789"
  494. var d : array[39, Int128]
  495. d[0] = parseDecimalInt128("1")
  496. d[1] = parseDecimalInt128("10")
  497. d[2] = parseDecimalInt128("100")
  498. d[3] = parseDecimalInt128("1000")
  499. d[4] = parseDecimalInt128("10000")
  500. d[5] = parseDecimalInt128("100000")
  501. d[6] = parseDecimalInt128("1000000")
  502. d[7] = parseDecimalInt128("10000000")
  503. d[8] = parseDecimalInt128("100000000")
  504. d[9] = parseDecimalInt128("1000000000")
  505. d[10] = parseDecimalInt128("10000000000")
  506. d[11] = parseDecimalInt128("100000000000")
  507. d[12] = parseDecimalInt128("1000000000000")
  508. d[13] = parseDecimalInt128("10000000000000")
  509. d[14] = parseDecimalInt128("100000000000000")
  510. d[15] = parseDecimalInt128("1000000000000000")
  511. d[16] = parseDecimalInt128("10000000000000000")
  512. d[17] = parseDecimalInt128("100000000000000000")
  513. d[18] = parseDecimalInt128("1000000000000000000")
  514. d[19] = parseDecimalInt128("10000000000000000000")
  515. d[20] = parseDecimalInt128("100000000000000000000")
  516. d[21] = parseDecimalInt128("1000000000000000000000")
  517. d[22] = parseDecimalInt128("10000000000000000000000")
  518. d[23] = parseDecimalInt128("100000000000000000000000")
  519. d[24] = parseDecimalInt128("1000000000000000000000000")
  520. d[25] = parseDecimalInt128("10000000000000000000000000")
  521. d[26] = parseDecimalInt128("100000000000000000000000000")
  522. d[27] = parseDecimalInt128("1000000000000000000000000000")
  523. d[28] = parseDecimalInt128("10000000000000000000000000000")
  524. d[29] = parseDecimalInt128("100000000000000000000000000000")
  525. d[30] = parseDecimalInt128("1000000000000000000000000000000")
  526. d[31] = parseDecimalInt128("10000000000000000000000000000000")
  527. d[32] = parseDecimalInt128("100000000000000000000000000000000")
  528. d[33] = parseDecimalInt128("1000000000000000000000000000000000")
  529. d[34] = parseDecimalInt128("10000000000000000000000000000000000")
  530. d[35] = parseDecimalInt128("100000000000000000000000000000000000")
  531. d[36] = parseDecimalInt128("1000000000000000000000000000000000000")
  532. d[37] = parseDecimalInt128("10000000000000000000000000000000000000")
  533. d[38] = parseDecimalInt128("100000000000000000000000000000000000000")
  534. for i in 0..<d.len:
  535. for j in 0..<d.len:
  536. doAssert(cmp(d[i], d[j]) == cmp(i,j))
  537. if i + j < d.len:
  538. doAssert d[i] * d[j] == d[i+j]
  539. if i - j >= 0:
  540. doAssert d[i] div d[j] == d[i-j]
  541. var sum: Int128
  542. for it in d:
  543. sum += it
  544. doAssert $sum == "111111111111111111111111111111111111111"
  545. for it in d.mitems:
  546. it = -it
  547. for i in 0..<d.len:
  548. for j in 0..<d.len:
  549. doAssert(cmp(d[i], d[j]) == -cmp(i,j))
  550. if i + j < d.len:
  551. doAssert d[i] * d[j] == -d[i+j]
  552. if i - j >= 0:
  553. doAssert d[i] div d[j] == -d[i-j]
  554. doAssert $high(Int128) == "170141183460469231731687303715884105727"
  555. doAssert $low(Int128) == "-170141183460469231731687303715884105728"
  556. var ma = 100'i64
  557. var mb = 13
  558. doAssert toInt128(ma) * toInt128(0) == toInt128(0)
  559. doAssert toInt128(-ma) * toInt128(0) == toInt128(0)
  560. # sign correctness
  561. doAssert divMod(toInt128( ma),toInt128( mb)) == (toInt128( ma div mb), toInt128( ma mod mb))
  562. doAssert divMod(toInt128(-ma),toInt128( mb)) == (toInt128(-ma div mb), toInt128(-ma mod mb))
  563. doAssert divMod(toInt128( ma),toInt128(-mb)) == (toInt128( ma div -mb), toInt128( ma mod -mb))
  564. doAssert divMod(toInt128(-ma),toInt128(-mb)) == (toInt128(-ma div -mb), toInt128(-ma mod -mb))
  565. doAssert divMod(toInt128( mb),toInt128( mb)) == (toInt128( mb div mb), toInt128( mb mod mb))
  566. doAssert divMod(toInt128(-mb),toInt128( mb)) == (toInt128(-mb div mb), toInt128(-mb mod mb))
  567. doAssert divMod(toInt128( mb),toInt128(-mb)) == (toInt128( mb div -mb), toInt128( mb mod -mb))
  568. doAssert divMod(toInt128(-mb),toInt128(-mb)) == (toInt128(-mb div -mb), toInt128(-mb mod -mb))
  569. doAssert divMod(toInt128( mb),toInt128( ma)) == (toInt128( mb div ma), toInt128( mb mod ma))
  570. doAssert divMod(toInt128(-mb),toInt128( ma)) == (toInt128(-mb div ma), toInt128(-mb mod ma))
  571. doAssert divMod(toInt128( mb),toInt128(-ma)) == (toInt128( mb div -ma), toInt128( mb mod -ma))
  572. doAssert divMod(toInt128(-mb),toInt128(-ma)) == (toInt128(-mb div -ma), toInt128(-mb mod -ma))
  573. let e = parseDecimalInt128("70997106675279150998592376708984375")
  574. let strArray = [
  575. # toHex(e shr 0), toHex(e shr 1), toHex(e shr 2), toHex(e shr 3)
  576. "000dac6d782d266a37300c32591eee37", "0006d636bc1693351b9806192c8f771b", "00036b1b5e0b499a8dcc030c9647bb8d", "0001b58daf05a4cd46e601864b23ddc6",
  577. "0000dac6d782d266a37300c32591eee3", "00006d636bc1693351b9806192c8f771", "000036b1b5e0b499a8dcc030c9647bb8", "00001b58daf05a4cd46e601864b23ddc",
  578. "00000dac6d782d266a37300c32591eee", "000006d636bc1693351b9806192c8f77", "0000036b1b5e0b499a8dcc030c9647bb", "000001b58daf05a4cd46e601864b23dd",
  579. "000000dac6d782d266a37300c32591ee", "0000006d636bc1693351b9806192c8f7", "00000036b1b5e0b499a8dcc030c9647b", "0000001b58daf05a4cd46e601864b23d",
  580. "0000000dac6d782d266a37300c32591e", "00000006d636bc1693351b9806192c8f", "000000036b1b5e0b499a8dcc030c9647", "00000001b58daf05a4cd46e601864b23",
  581. "00000000dac6d782d266a37300c32591", "000000006d636bc1693351b9806192c8", "0000000036b1b5e0b499a8dcc030c964", "000000001b58daf05a4cd46e601864b2",
  582. "000000000dac6d782d266a37300c3259", "0000000006d636bc1693351b9806192c", "00000000036b1b5e0b499a8dcc030c96", "0000000001b58daf05a4cd46e601864b",
  583. "0000000000dac6d782d266a37300c325", "00000000006d636bc1693351b9806192", "000000000036b1b5e0b499a8dcc030c9", "00000000001b58daf05a4cd46e601864",
  584. "00000000000dac6d782d266a37300c32", "000000000006d636bc1693351b980619", "0000000000036b1b5e0b499a8dcc030c", "000000000001b58daf05a4cd46e60186",
  585. "000000000000dac6d782d266a37300c3", "0000000000006d636bc1693351b98061", "00000000000036b1b5e0b499a8dcc030", "0000000000001b58daf05a4cd46e6018",
  586. "0000000000000dac6d782d266a37300c", "00000000000006d636bc1693351b9806", "000000000000036b1b5e0b499a8dcc03", "00000000000001b58daf05a4cd46e601",
  587. "00000000000000dac6d782d266a37300", "000000000000006d636bc1693351b980", "0000000000000036b1b5e0b499a8dcc0", "000000000000001b58daf05a4cd46e60",
  588. "000000000000000dac6d782d266a3730", "0000000000000006d636bc1693351b98", "00000000000000036b1b5e0b499a8dcc", "0000000000000001b58daf05a4cd46e6",
  589. "0000000000000000dac6d782d266a373", "00000000000000006d636bc1693351b9", "000000000000000036b1b5e0b499a8dc", "00000000000000001b58daf05a4cd46e",
  590. "00000000000000000dac6d782d266a37", "000000000000000006d636bc1693351b", "0000000000000000036b1b5e0b499a8d", "000000000000000001b58daf05a4cd46",
  591. "000000000000000000dac6d782d266a3", "0000000000000000006d636bc1693351", "00000000000000000036b1b5e0b499a8", "0000000000000000001b58daf05a4cd4",
  592. "0000000000000000000dac6d782d266a", "00000000000000000006d636bc169335", "000000000000000000036b1b5e0b499a", "00000000000000000001b58daf05a4cd",
  593. "00000000000000000000dac6d782d266", "000000000000000000006d636bc16933", "0000000000000000000036b1b5e0b499", "000000000000000000001b58daf05a4c",
  594. "000000000000000000000dac6d782d26", "0000000000000000000006d636bc1693", "00000000000000000000036b1b5e0b49", "0000000000000000000001b58daf05a4",
  595. "0000000000000000000000dac6d782d2", "00000000000000000000006d636bc169", "000000000000000000000036b1b5e0b4", "00000000000000000000001b58daf05a",
  596. "00000000000000000000000dac6d782d", "000000000000000000000006d636bc16", "0000000000000000000000036b1b5e0b", "000000000000000000000001b58daf05",
  597. "000000000000000000000000dac6d782", "0000000000000000000000006d636bc1", "00000000000000000000000036b1b5e0", "0000000000000000000000001b58daf0",
  598. "0000000000000000000000000dac6d78", "00000000000000000000000006d636bc", "000000000000000000000000036b1b5e", "00000000000000000000000001b58daf",
  599. "00000000000000000000000000dac6d7", "000000000000000000000000006d636b", "0000000000000000000000000036b1b5", "000000000000000000000000001b58da",
  600. "000000000000000000000000000dac6d", "0000000000000000000000000006d636", "00000000000000000000000000036b1b", "0000000000000000000000000001b58d",
  601. "0000000000000000000000000000dac6", "00000000000000000000000000006d63", "000000000000000000000000000036b1", "00000000000000000000000000001b58",
  602. "00000000000000000000000000000dac", "000000000000000000000000000006d6", "0000000000000000000000000000036b", "000000000000000000000000000001b5",
  603. "000000000000000000000000000000da", "0000000000000000000000000000006d", "00000000000000000000000000000036", "0000000000000000000000000000001b",
  604. "0000000000000000000000000000000d", "00000000000000000000000000000006", "00000000000000000000000000000003", "00000000000000000000000000000001",
  605. "00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000",
  606. "00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000",
  607. "00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000", "00000000000000000000000000000000",
  608. ]
  609. for i in 0 ..< 128:
  610. let str1 = toHex(e shr i)
  611. let str2 = strArray[i]
  612. doAssert str1 == str2
  613. let strArray2 = [
  614. "000dac6d782d266a37300c32591eee37", "001b58daf05a4cd46e601864b23ddc6e", "0036b1b5e0b499a8dcc030c9647bb8dc", "006d636bc1693351b9806192c8f771b8",
  615. "00dac6d782d266a37300c32591eee370", "01b58daf05a4cd46e601864b23ddc6e0", "036b1b5e0b499a8dcc030c9647bb8dc0", "06d636bc1693351b9806192c8f771b80",
  616. "0dac6d782d266a37300c32591eee3700", "1b58daf05a4cd46e601864b23ddc6e00", "36b1b5e0b499a8dcc030c9647bb8dc00", "6d636bc1693351b9806192c8f771b800",
  617. "dac6d782d266a37300c32591eee37000", "b58daf05a4cd46e601864b23ddc6e000", "6b1b5e0b499a8dcc030c9647bb8dc000", "d636bc1693351b9806192c8f771b8000",
  618. "ac6d782d266a37300c32591eee370000", "58daf05a4cd46e601864b23ddc6e0000", "b1b5e0b499a8dcc030c9647bb8dc0000", "636bc1693351b9806192c8f771b80000",
  619. "c6d782d266a37300c32591eee3700000", "8daf05a4cd46e601864b23ddc6e00000", "1b5e0b499a8dcc030c9647bb8dc00000", "36bc1693351b9806192c8f771b800000",
  620. "6d782d266a37300c32591eee37000000", "daf05a4cd46e601864b23ddc6e000000", "b5e0b499a8dcc030c9647bb8dc000000", "6bc1693351b9806192c8f771b8000000",
  621. "d782d266a37300c32591eee370000000", "af05a4cd46e601864b23ddc6e0000000", "5e0b499a8dcc030c9647bb8dc0000000", "bc1693351b9806192c8f771b80000000",
  622. "782d266a37300c32591eee3700000000", "f05a4cd46e601864b23ddc6e00000000", "e0b499a8dcc030c9647bb8dc00000000", "c1693351b9806192c8f771b800000000",
  623. "82d266a37300c32591eee37000000000", "05a4cd46e601864b23ddc6e000000000", "0b499a8dcc030c9647bb8dc000000000", "1693351b9806192c8f771b8000000000",
  624. "2d266a37300c32591eee370000000000", "5a4cd46e601864b23ddc6e0000000000", "b499a8dcc030c9647bb8dc0000000000", "693351b9806192c8f771b80000000000",
  625. "d266a37300c32591eee3700000000000", "a4cd46e601864b23ddc6e00000000000", "499a8dcc030c9647bb8dc00000000000", "93351b9806192c8f771b800000000000",
  626. "266a37300c32591eee37000000000000", "4cd46e601864b23ddc6e000000000000", "99a8dcc030c9647bb8dc000000000000", "3351b9806192c8f771b8000000000000",
  627. "66a37300c32591eee370000000000000", "cd46e601864b23ddc6e0000000000000", "9a8dcc030c9647bb8dc0000000000000", "351b9806192c8f771b80000000000000",
  628. "6a37300c32591eee3700000000000000", "d46e601864b23ddc6e00000000000000", "a8dcc030c9647bb8dc00000000000000", "51b9806192c8f771b800000000000000",
  629. "a37300c32591eee37000000000000000", "46e601864b23ddc6e000000000000000", "8dcc030c9647bb8dc000000000000000", "1b9806192c8f771b8000000000000000",
  630. "37300c32591eee370000000000000000", "6e601864b23ddc6e0000000000000000", "dcc030c9647bb8dc0000000000000000", "b9806192c8f771b80000000000000000",
  631. "7300c32591eee3700000000000000000", "e601864b23ddc6e00000000000000000", "cc030c9647bb8dc00000000000000000", "9806192c8f771b800000000000000000",
  632. "300c32591eee37000000000000000000", "601864b23ddc6e000000000000000000", "c030c9647bb8dc000000000000000000", "806192c8f771b8000000000000000000",
  633. "00c32591eee370000000000000000000", "01864b23ddc6e0000000000000000000", "030c9647bb8dc0000000000000000000", "06192c8f771b80000000000000000000",
  634. "0c32591eee3700000000000000000000", "1864b23ddc6e00000000000000000000", "30c9647bb8dc00000000000000000000", "6192c8f771b800000000000000000000",
  635. "c32591eee37000000000000000000000", "864b23ddc6e000000000000000000000", "0c9647bb8dc000000000000000000000", "192c8f771b8000000000000000000000",
  636. "32591eee370000000000000000000000", "64b23ddc6e0000000000000000000000", "c9647bb8dc0000000000000000000000", "92c8f771b80000000000000000000000",
  637. "2591eee3700000000000000000000000", "4b23ddc6e00000000000000000000000", "9647bb8dc00000000000000000000000", "2c8f771b800000000000000000000000",
  638. "591eee37000000000000000000000000", "b23ddc6e000000000000000000000000", "647bb8dc000000000000000000000000", "c8f771b8000000000000000000000000",
  639. "91eee370000000000000000000000000", "23ddc6e0000000000000000000000000", "47bb8dc0000000000000000000000000", "8f771b80000000000000000000000000",
  640. "1eee3700000000000000000000000000", "3ddc6e00000000000000000000000000", "7bb8dc00000000000000000000000000", "f771b800000000000000000000000000",
  641. "eee37000000000000000000000000000", "ddc6e000000000000000000000000000", "bb8dc000000000000000000000000000", "771b8000000000000000000000000000",
  642. "ee370000000000000000000000000000", "dc6e0000000000000000000000000000", "b8dc0000000000000000000000000000", "71b80000000000000000000000000000",
  643. "e3700000000000000000000000000000", "c6e00000000000000000000000000000", "8dc00000000000000000000000000000", "1b800000000000000000000000000000",
  644. "37000000000000000000000000000000", "6e000000000000000000000000000000", "dc000000000000000000000000000000", "b8000000000000000000000000000000",
  645. "70000000000000000000000000000000", "e0000000000000000000000000000000", "c0000000000000000000000000000000", "80000000000000000000000000000000",
  646. ]
  647. for i in 0 ..< 128:
  648. let str1 = toHex(e shl i)
  649. let str2 = strArray2[i]
  650. doAssert str1 == str2