integers.odin 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. package strconv
  2. Int_Flag :: enum {
  3. Prefix,
  4. Plus,
  5. }
  6. Int_Flags :: bit_set[Int_Flag]
  7. MAX_BASE :: 32
  8. digits := "0123456789abcdefghijklmnopqrstuvwxyz"
  9. /*
  10. Determines whether the given unsigned 64-bit integer is a negative value by interpreting it as a signed integer with the specified bit size.
  11. **Inputs**
  12. - x: The unsigned 64-bit integer to check for negativity
  13. - is_signed: A boolean indicating if the input should be treated as a signed integer
  14. - bit_size: The bit size of the signed integer representation (8, 16, 32, or 64)
  15. **Returns**
  16. - u: The absolute value of the input integer
  17. - neg: A boolean indicating whether the input integer is negative
  18. */
  19. is_integer_negative :: proc(x: u64, is_signed: bool, bit_size: int) -> (u: u64, neg: bool) {
  20. u = x
  21. if is_signed {
  22. switch bit_size {
  23. case 8:
  24. i := i8(u)
  25. neg = i < 0
  26. u = u64(abs(i64(i)))
  27. case 16:
  28. i := i16(u)
  29. neg = i < 0
  30. u = u64(abs(i64(i)))
  31. case 32:
  32. i := i32(u)
  33. neg = i < 0
  34. u = u64(abs(i64(i)))
  35. case 64:
  36. i := i64(u)
  37. neg = i < 0
  38. u = u64(abs(i))
  39. case:
  40. panic("is_integer_negative: Unknown integer size")
  41. }
  42. }
  43. return
  44. }
  45. /*
  46. Appends the string representation of an integer to a buffer with specified base, flags, and digit set.
  47. **Inputs**
  48. - buf: The buffer to append the integer representation to
  49. - x: The integer value to convert
  50. - base: The base for the integer representation (2 <= base <= MAX_BASE)
  51. - is_signed: A boolean indicating if the input should be treated as a signed integer
  52. - bit_size: The bit size of the signed integer representation (8, 16, 32, or 64)
  53. - digits: The digit set used for the integer representation
  54. - flags: The Int_Flags bit set to control integer formatting
  55. **Returns**
  56. - The string containing the integer representation appended to the buffer
  57. */
  58. append_bits :: proc(buf: []byte, x: u64, base: int, is_signed: bool, bit_size: int, digits: string, flags: Int_Flags) -> string {
  59. if base < 2 || base > MAX_BASE {
  60. panic("strconv: illegal base passed to append_bits")
  61. }
  62. a: [129]byte
  63. i := len(a)
  64. u, neg := is_integer_negative(x, is_signed, bit_size)
  65. b := u64(base)
  66. for u >= b {
  67. i-=1; a[i] = digits[u % b]
  68. u /= b
  69. }
  70. i-=1; a[i] = digits[u % b]
  71. if .Prefix in flags {
  72. ok := true
  73. switch base {
  74. case 2: i-=1; a[i] = 'b'
  75. case 8: i-=1; a[i] = 'o'
  76. // case 10: i-=1; a[i] = 'd';
  77. case 12: i-=1; a[i] = 'z'
  78. case 16: i-=1; a[i] = 'x'
  79. case: ok = false
  80. }
  81. if ok {
  82. i-=1; a[i] = '0'
  83. }
  84. }
  85. switch {
  86. case neg:
  87. i-=1; a[i] = '-'
  88. case .Plus in flags:
  89. i-=1; a[i] = '+'
  90. }
  91. out := a[i:]
  92. copy(buf, out)
  93. return string(buf[0:len(out)])
  94. }
  95. /*
  96. Determines whether the given unsigned 128-bit integer is a negative value by interpreting it as a signed integer with the specified bit size.
  97. **Inputs**
  98. - x: The unsigned 128-bit integer to check for negativity
  99. - is_signed: A boolean indicating if the input should be treated as a signed integer
  100. - bit_size: The bit size of the signed integer representation (8, 16, 32, 64, or 128)
  101. **Returns**
  102. - u: The absolute value of the input integer
  103. - neg: A boolean indicating whether the input integer is negative
  104. */
  105. is_integer_negative_128 :: proc(x: u128, is_signed: bool, bit_size: int) -> (u: u128, neg: bool) {
  106. u = x
  107. if is_signed {
  108. switch bit_size {
  109. case 8:
  110. i := i8(u)
  111. neg = i < 0
  112. u = u128(abs(i128(i)))
  113. case 16:
  114. i := i16(u)
  115. neg = i < 0
  116. u = u128(abs(i128(i)))
  117. case 32:
  118. i := i32(u)
  119. neg = i < 0
  120. u = u128(abs(i128(i)))
  121. case 64:
  122. i := i64(u)
  123. neg = i < 0
  124. u = u128(abs(i128(i)))
  125. case 128:
  126. i := i128(u)
  127. neg = i < 0
  128. u = u128(abs(i))
  129. case:
  130. panic("is_integer_negative: Unknown integer size")
  131. }
  132. }
  133. return
  134. }
  135. /*
  136. Appends the string representation of a 128-bit integer to a buffer with specified base, flags, and digit set.
  137. **Inputs**
  138. - buf: The buffer to append the integer representation to
  139. - x: The 128-bit integer value to convert
  140. - base: The base for the integer representation (2 <= base <= MAX_BASE)
  141. - is_signed: A boolean indicating if the input should be treated as a signed integer
  142. - bit_size: The bit size of the signed integer representation (8, 16, 32, 64, or 128)
  143. - digits: The digit set used for the integer representation
  144. - flags: The Int_Flags bit set to control integer formatting
  145. **Returns**
  146. - The string containing the integer representation appended to the buffer
  147. */
  148. append_bits_128 :: proc(buf: []byte, x: u128, base: int, is_signed: bool, bit_size: int, digits: string, flags: Int_Flags) -> string {
  149. if base < 2 || base > MAX_BASE {
  150. panic("strconv: illegal base passed to append_bits")
  151. }
  152. a: [140]byte
  153. i := len(a)
  154. u, neg := is_integer_negative_128(x, is_signed, bit_size)
  155. b := u128(base)
  156. for u >= b && i >= 0 {
  157. i-=1
  158. // rem: u128;
  159. // u = runtime.udivmod128(u, b, &rem);
  160. // u /= b;
  161. rem := u % b
  162. u /= b
  163. idx := u32(rem)
  164. a[i] = digits[idx]
  165. }
  166. i-=1; a[i] = digits[u64(u % b)]
  167. if .Prefix in flags {
  168. ok := true
  169. switch base {
  170. case 2: i-=1; a[i] = 'b'
  171. case 8: i-=1; a[i] = 'o'
  172. case 10: i-=1; a[i] = 'd'
  173. case 12: i-=1; a[i] = 'z'
  174. case 16: i-=1; a[i] = 'x'
  175. case: ok = false
  176. }
  177. if ok {
  178. i-=1; a[i] = '0'
  179. }
  180. }
  181. switch {
  182. case neg:
  183. i-=1; a[i] = '-'
  184. case .Plus in flags:
  185. i-=1; a[i] = '+'
  186. }
  187. out := a[i:]
  188. copy(buf, out)
  189. return string(buf[0:len(out)])
  190. }