tvarnums.nim 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. discard """
  2. output: "Success!"
  3. """
  4. # Test variable length binary integers
  5. import
  6. strutils
  7. type
  8. TBuffer = array[0..10, int8]
  9. proc toVarNum(x: int32, b: var TBuffer) =
  10. # encoding: first bit indicates end of number (0 if at end)
  11. # second bit of the first byte denotes the sign (1 --> negative)
  12. var a = x
  13. if x != low(x):
  14. # low(int) is a special case,
  15. # because abs() does not work here!
  16. # we leave x as it is and use the check >% instead of >
  17. # for low(int) this is needed and positive numbers are not affected
  18. # anyway
  19. a = abs(x)
  20. # first 6 bits:
  21. b[0] = toU8(ord(a >% 63'i32) shl 7 or (ord(x < 0'i32) shl 6) or (int(a) and 63))
  22. a = (a shr 6'i32) and 0x03ffffff # skip first 6 bits
  23. var i = 1
  24. while a != 0'i32:
  25. b[i] = toU8(ord(a >% 127'i32) shl 7 or (int(a) and 127))
  26. inc(i)
  27. a = a shr 7'i32
  28. proc toVarNum64(x: int64, b: var TBuffer) =
  29. # encoding: first bit indicates end of number (0 if at end)
  30. # second bit of the first byte denotes the sign (1 --> negative)
  31. var a = x
  32. if x != low(x):
  33. # low(int) is a special case,
  34. # because abs() does not work here!
  35. # we leave x as it is and use the check >% instead of >
  36. # for low(int) this is needed and positive numbers are not affected
  37. # anyway
  38. a = abs(x)
  39. # first 6 bits:
  40. b[0] = toU8(ord(a >% 63'i64) shl 7 or (ord(x < 0'i64) shl 6) or int(a and 63))
  41. a = (a shr 6) and 0x03ffffffffffffff # skip first 6 bits
  42. var i = 1
  43. while a != 0'i64:
  44. b[i] = toU8(ord(a >% 127'i64) shl 7 or int(a and 127))
  45. inc(i)
  46. a = a shr 7
  47. proc toNum64(b: TBuffer): int64 =
  48. # treat first byte different:
  49. result = ze64(b[0]) and 63
  50. var
  51. i = 0
  52. Shift = 6'i64
  53. while (ze(b[i]) and 128) != 0:
  54. inc(i)
  55. result = result or ((ze64(b[i]) and 127) shl Shift)
  56. inc(Shift, 7)
  57. if (ze(b[0]) and 64) != 0: # sign bit set?
  58. result = not result +% 1
  59. # this is the same as ``- result``
  60. # but gives no overflow error for low(int)
  61. proc toNum(b: TBuffer): int32 =
  62. # treat first byte different:
  63. result = int32 ze(b[0]) and 63
  64. var
  65. i = 0
  66. Shift = 6'i32
  67. while (ze(b[i]) and 128) != 0:
  68. inc(i)
  69. result = result or ((int32(ze(b[i])) and 127'i32) shl Shift)
  70. Shift = Shift + 7'i32
  71. if (ze(b[0]) and (1 shl 6)) != 0: # sign bit set?
  72. result = (not result) +% 1'i32
  73. # this is the same as ``- result``
  74. # but gives no overflow error for low(int)
  75. proc toBinary(x: int64): string =
  76. result = newString(64)
  77. for i in 0..63:
  78. result[63-i] = chr((int(x shr i) and 1) + ord('0'))
  79. proc t64(i: int64) =
  80. var
  81. b: TBuffer
  82. toVarNum64(i, b)
  83. var x = toNum64(b)
  84. if x != i:
  85. writeLine(stdout, $i)
  86. writeLine(stdout, toBinary(i))
  87. writeLine(stdout, toBinary(x))
  88. proc t32(i: int32) =
  89. var
  90. b: TBuffer
  91. toVarNum(i, b)
  92. var x = toNum(b)
  93. if x != i:
  94. writeLine(stdout, toBinary(i))
  95. writeLine(stdout, toBinary(x))
  96. proc tm(i: int32) =
  97. var
  98. b: TBuffer
  99. toVarNum64(i, b)
  100. var x = toNum(b)
  101. if x != i:
  102. writeLine(stdout, toBinary(i))
  103. writeLine(stdout, toBinary(x))
  104. t32(0)
  105. t32(1)
  106. t32(-1)
  107. t32(-100_000)
  108. t32(100_000)
  109. t32(low(int32))
  110. t32(high(int32))
  111. t64(low(int64))
  112. t64(high(int64))
  113. t64(0)
  114. t64(-1)
  115. t64(1)
  116. t64(1000_000)
  117. t64(-1000_000)
  118. tm(0)
  119. tm(1)
  120. tm(-1)
  121. tm(-100_000)
  122. tm(100_000)
  123. tm(low(int32))
  124. tm(high(int32))
  125. writeLine(stdout, "Success!") #OUT Success!