bits.odin 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. U8_MIN :: u8(0);
  2. U16_MIN :: u16(0);
  3. U32_MIN :: u32(0);
  4. U64_MIN :: u64(0);
  5. U128_MIN :: u128(0);
  6. I8_MIN :: i8(-0x80);
  7. I16_MIN :: i16(-0x8000);
  8. I32_MIN :: i32(-0x8000_0000);
  9. I64_MIN :: i64(-0x8000_0000_0000_0000);
  10. I128_MIN :: i128(-0x8000_0000_0000_0000_0000_0000_0000_0000);
  11. U8_MAX :: ~u8(0);
  12. U16_MAX :: ~u16(0);
  13. U32_MAX :: ~u32(0);
  14. U64_MAX :: ~u64(0);
  15. U128_MAX :: ~u128(0);
  16. I8_MAX :: i8(0x7f);
  17. I16_MAX :: i16(0x7fff);
  18. I32_MAX :: i32(0x7fff_ffff);
  19. I64_MAX :: i64(0x7fff_ffff_ffff_ffff);
  20. I128_MAX :: i128(0x7fff_ffff_ffff_ffff_ffff_ffff_ffff_ffff);
  21. count_ones :: proc(i: u8) -> u8 { __llvm_ctpop :: proc(u8) -> u8 #foreign __llvm_core "llvm.ctpop.i8"; return __llvm_ctpop(i); }
  22. count_ones :: proc(i: i8) -> i8 { __llvm_ctpop :: proc(i8) -> i8 #foreign __llvm_core "llvm.ctpop.i8"; return __llvm_ctpop(i); }
  23. count_ones :: proc(i: u16) -> u16 { __llvm_ctpop :: proc(u16) -> u16 #foreign __llvm_core "llvm.ctpop.i16"; return __llvm_ctpop(i); }
  24. count_ones :: proc(i: i16) -> i16 { __llvm_ctpop :: proc(i16) -> i16 #foreign __llvm_core "llvm.ctpop.i16"; return __llvm_ctpop(i); }
  25. count_ones :: proc(i: u32) -> u32 { __llvm_ctpop :: proc(u32) -> u32 #foreign __llvm_core "llvm.ctpop.i32"; return __llvm_ctpop(i); }
  26. count_ones :: proc(i: i32) -> i32 { __llvm_ctpop :: proc(i32) -> i32 #foreign __llvm_core "llvm.ctpop.i32"; return __llvm_ctpop(i); }
  27. count_ones :: proc(i: u64) -> u64 { __llvm_ctpop :: proc(u64) -> u64 #foreign __llvm_core "llvm.ctpop.i64"; return __llvm_ctpop(i); }
  28. count_ones :: proc(i: i64) -> i64 { __llvm_ctpop :: proc(i64) -> i64 #foreign __llvm_core "llvm.ctpop.i64"; return __llvm_ctpop(i); }
  29. count_ones :: proc(i: u128) -> u128 { __llvm_ctpop :: proc(u128) -> u128 #foreign __llvm_core "llvm.ctpop.i128";return __llvm_ctpop(i); }
  30. count_ones :: proc(i: i128) -> i128 { __llvm_ctpop :: proc(i128) -> i128 #foreign __llvm_core "llvm.ctpop.i128";return __llvm_ctpop(i); }
  31. count_ones :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(count_ones(u32(i))); } else { return uint(count_ones(u64(i))); } }
  32. count_ones :: proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(count_ones(i32(i))); } else { return int(count_ones(i64(i))); } }
  33. count_zeros :: proc(i: u8) -> u8 { return 8 - count_ones(i); }
  34. count_zeros :: proc(i: i8) -> i8 { return 8 - count_ones(i); }
  35. count_zeros :: proc(i: u16) -> u16 { return 16 - count_ones(i); }
  36. count_zeros :: proc(i: i16) -> i16 { return 16 - count_ones(i); }
  37. count_zeros :: proc(i: u32) -> u32 { return 32 - count_ones(i); }
  38. count_zeros :: proc(i: i32) -> i32 { return 32 - count_ones(i); }
  39. count_zeros :: proc(i: u64) -> u64 { return 64 - count_ones(i); }
  40. count_zeros :: proc(i: i64) -> i64 { return 64 - count_ones(i); }
  41. count_zeros :: proc(i: u128) -> u128 { return 128 - count_ones(i); }
  42. count_zeros :: proc(i: i128) -> i128 { return 128 - count_ones(i); }
  43. count_zeros :: proc(i: uint) -> uint { return 8*size_of(uint) - count_ones(i); }
  44. count_zeros :: proc(i: int) -> int { return 8*size_of(int) - count_ones(i); }
  45. rotate_left :: proc(i: u8, s: uint) -> u8 { return (i << s)|(i >> (8*size_of(u8) - s)); }
  46. rotate_left :: proc(i: i8, s: uint) -> i8 { return (i << s)|(i >> (8*size_of(i8) - s)); }
  47. rotate_left :: proc(i: u16, s: uint) -> u16 { return (i << s)|(i >> (8*size_of(u16) - s)); }
  48. rotate_left :: proc(i: i16, s: uint) -> i16 { return (i << s)|(i >> (8*size_of(i16) - s)); }
  49. rotate_left :: proc(i: u32, s: uint) -> u32 { return (i << s)|(i >> (8*size_of(u32) - s)); }
  50. rotate_left :: proc(i: i32, s: uint) -> i32 { return (i << s)|(i >> (8*size_of(i32) - s)); }
  51. rotate_left :: proc(i: u64, s: uint) -> u64 { return (i << s)|(i >> (8*size_of(u64) - s)); }
  52. rotate_left :: proc(i: i64, s: uint) -> i64 { return (i << s)|(i >> (8*size_of(i64) - s)); }
  53. rotate_left :: proc(i: u128, s: uint) -> u128 { return (i << s)|(i >> (8*size_of(u128) - s)); }
  54. rotate_left :: proc(i: i128, s: uint) -> i128 { return (i << s)|(i >> (8*size_of(i128) - s)); }
  55. rotate_left :: proc(i: uint, s: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(rotate_left(u32(i), s)); } else { return uint(rotate_left(u64(i), s)); } }
  56. rotate_left :: proc(i: int, s: uint) -> int { when size_of(int) == size_of(i32) { return int(rotate_left(i32(i), s)); } else { return int(rotate_left(i64(i), s)); } }
  57. rotate_right :: proc(i: u8, s: uint) -> u8 { return (i >> s)|(i << (8*size_of(u8) - s)); }
  58. rotate_right :: proc(i: i8, s: uint) -> i8 { return (i >> s)|(i << (8*size_of(i8) - s)); }
  59. rotate_right :: proc(i: u16, s: uint) -> u16 { return (i >> s)|(i << (8*size_of(u16) - s)); }
  60. rotate_right :: proc(i: i16, s: uint) -> i16 { return (i >> s)|(i << (8*size_of(i16) - s)); }
  61. rotate_right :: proc(i: u32, s: uint) -> u32 { return (i >> s)|(i << (8*size_of(u32) - s)); }
  62. rotate_right :: proc(i: i32, s: uint) -> i32 { return (i >> s)|(i << (8*size_of(i32) - s)); }
  63. rotate_right :: proc(i: u64, s: uint) -> u64 { return (i >> s)|(i << (8*size_of(u64) - s)); }
  64. rotate_right :: proc(i: i64, s: uint) -> i64 { return (i >> s)|(i << (8*size_of(i64) - s)); }
  65. rotate_right :: proc(i: u128, s: uint) -> u128 { return (i >> s)|(i << (8*size_of(u128) - s)); }
  66. rotate_right :: proc(i: i128, s: uint) -> i128 { return (i >> s)|(i << (8*size_of(i128) - s)); }
  67. rotate_right :: proc(i: uint, s: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(rotate_right(u32(i), s)); } else { return uint(rotate_right(u64(i), s)); } }
  68. rotate_right :: proc(i: int, s: uint) -> int { when size_of(int) == size_of(i32) { return int(rotate_right(i32(i), s)); } else { return int(rotate_right(i64(i), s)); } }
  69. leading_zeros :: proc(i: u8) -> u8 { __llvm_ctlz :: proc(u8, bool) -> u8 #foreign __llvm_core "llvm.ctlz.i8"; return __llvm_ctlz(i, false); }
  70. leading_zeros :: proc(i: i8) -> i8 { __llvm_ctlz :: proc(i8, bool) -> i8 #foreign __llvm_core "llvm.ctlz.i8"; return __llvm_ctlz(i, false); }
  71. leading_zeros :: proc(i: u16) -> u16 { __llvm_ctlz :: proc(u16, bool) -> u16 #foreign __llvm_core "llvm.ctlz.i16"; return __llvm_ctlz(i, false); }
  72. leading_zeros :: proc(i: i16) -> i16 { __llvm_ctlz :: proc(i16, bool) -> i16 #foreign __llvm_core "llvm.ctlz.i16"; return __llvm_ctlz(i, false); }
  73. leading_zeros :: proc(i: u32) -> u32 { __llvm_ctlz :: proc(u32, bool) -> u32 #foreign __llvm_core "llvm.ctlz.i32"; return __llvm_ctlz(i, false); }
  74. leading_zeros :: proc(i: i32) -> i32 { __llvm_ctlz :: proc(i32, bool) -> i32 #foreign __llvm_core "llvm.ctlz.i32"; return __llvm_ctlz(i, false); }
  75. leading_zeros :: proc(i: u64) -> u64 { __llvm_ctlz :: proc(u64, bool) -> u64 #foreign __llvm_core "llvm.ctlz.i64"; return __llvm_ctlz(i, false); }
  76. leading_zeros :: proc(i: i64) -> i64 { __llvm_ctlz :: proc(i64, bool) -> i64 #foreign __llvm_core "llvm.ctlz.i64"; return __llvm_ctlz(i, false); }
  77. leading_zeros :: proc(i: u128) -> u128 { __llvm_ctlz :: proc(u128, bool) -> u128 #foreign __llvm_core "llvm.ctlz.i128";return __llvm_ctlz(i, false); }
  78. leading_zeros :: proc(i: i128) -> i128 { __llvm_ctlz :: proc(i128, bool) -> i128 #foreign __llvm_core "llvm.ctlz.i128";return __llvm_ctlz(i, false); }
  79. leading_zeros :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(leading_zeros(u32(i))); } else { return uint(leading_zeros(u64(i))); } }
  80. leading_zeros :: proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(leading_zeros(i32(i))); } else { return int(leading_zeros(i64(i))); } }
  81. trailing_zeros :: proc(i: u8) -> u8 { __llvm_cttz :: proc(u8, bool) -> u8 #foreign __llvm_core "llvm.cttz.i8"; return __llvm_cttz(i, false); }
  82. trailing_zeros :: proc(i: i8) -> i8 { __llvm_cttz :: proc(i8, bool) -> i8 #foreign __llvm_core "llvm.cttz.i8"; return __llvm_cttz(i, false); }
  83. trailing_zeros :: proc(i: u16) -> u16 { __llvm_cttz :: proc(u16, bool) -> u16 #foreign __llvm_core "llvm.cttz.i16"; return __llvm_cttz(i, false); }
  84. trailing_zeros :: proc(i: i16) -> i16 { __llvm_cttz :: proc(i16, bool) -> i16 #foreign __llvm_core "llvm.cttz.i16"; return __llvm_cttz(i, false); }
  85. trailing_zeros :: proc(i: u32) -> u32 { __llvm_cttz :: proc(u32, bool) -> u32 #foreign __llvm_core "llvm.cttz.i32"; return __llvm_cttz(i, false); }
  86. trailing_zeros :: proc(i: i32) -> i32 { __llvm_cttz :: proc(i32, bool) -> i32 #foreign __llvm_core "llvm.cttz.i32"; return __llvm_cttz(i, false); }
  87. trailing_zeros :: proc(i: u64) -> u64 { __llvm_cttz :: proc(u64, bool) -> u64 #foreign __llvm_core "llvm.cttz.i64"; return __llvm_cttz(i, false); }
  88. trailing_zeros :: proc(i: i64) -> i64 { __llvm_cttz :: proc(i64, bool) -> i64 #foreign __llvm_core "llvm.cttz.i64"; return __llvm_cttz(i, false); }
  89. trailing_zeros :: proc(i: u128) -> u128 { __llvm_cttz :: proc(u128, bool) -> u128 #foreign __llvm_core "llvm.cttz.i128";return __llvm_cttz(i, false); }
  90. trailing_zeros :: proc(i: i128) -> i128 { __llvm_cttz :: proc(i128, bool) -> i128 #foreign __llvm_core "llvm.cttz.i128";return __llvm_cttz(i, false); }
  91. trailing_zeros :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(trailing_zeros(u32(i))); } else { return uint(trailing_zeros(u64(i))); } }
  92. trailing_zeros :: proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(trailing_zeros(i32(i))); } else { return int(trailing_zeros(i64(i))); } }
  93. reverse_bits :: proc(i: u8) -> u8 { __llvm_bitreverse :: proc(u8) -> u8 #foreign __llvm_core "llvm.bitreverse.i8"; return __llvm_bitreverse(i); }
  94. reverse_bits :: proc(i: i8) -> i8 { __llvm_bitreverse :: proc(i8) -> i8 #foreign __llvm_core "llvm.bitreverse.i8"; return __llvm_bitreverse(i); }
  95. reverse_bits :: proc(i: u16) -> u16 { __llvm_bitreverse :: proc(u16) -> u16 #foreign __llvm_core "llvm.bitreverse.i16"; return __llvm_bitreverse(i); }
  96. reverse_bits :: proc(i: i16) -> i16 { __llvm_bitreverse :: proc(i16) -> i16 #foreign __llvm_core "llvm.bitreverse.i16"; return __llvm_bitreverse(i); }
  97. reverse_bits :: proc(i: u32) -> u32 { __llvm_bitreverse :: proc(u32) -> u32 #foreign __llvm_core "llvm.bitreverse.i32"; return __llvm_bitreverse(i); }
  98. reverse_bits :: proc(i: i32) -> i32 { __llvm_bitreverse :: proc(i32) -> i32 #foreign __llvm_core "llvm.bitreverse.i32"; return __llvm_bitreverse(i); }
  99. reverse_bits :: proc(i: u64) -> u64 { __llvm_bitreverse :: proc(u64) -> u64 #foreign __llvm_core "llvm.bitreverse.i64"; return __llvm_bitreverse(i); }
  100. reverse_bits :: proc(i: i64) -> i64 { __llvm_bitreverse :: proc(i64) -> i64 #foreign __llvm_core "llvm.bitreverse.i64"; return __llvm_bitreverse(i); }
  101. reverse_bits :: proc(i: u128) -> u128 { __llvm_bitreverse :: proc(u128) -> u128 #foreign __llvm_core "llvm.bitreverse.i128";return __llvm_bitreverse(i); }
  102. reverse_bits :: proc(i: i128) -> i128 { __llvm_bitreverse :: proc(i128) -> i128 #foreign __llvm_core "llvm.bitreverse.i128";return __llvm_bitreverse(i); }
  103. reverse_bits :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(reverse_bits(u32(i))); } else { return uint(reverse_bits(u64(i))); } }
  104. reverse_bits :: proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(reverse_bits(i32(i))); } else { return int(reverse_bits(i64(i))); } }
  105. byte_swap :: proc(u16) -> u16 #foreign __llvm_core "llvm.bswap.i16";
  106. byte_swap :: proc(i16) -> i16 #foreign __llvm_core "llvm.bswap.i16";
  107. byte_swap :: proc(u32) -> u32 #foreign __llvm_core "llvm.bswap.i32";
  108. byte_swap :: proc(i32) -> i32 #foreign __llvm_core "llvm.bswap.i32";
  109. byte_swap :: proc(u64) -> u64 #foreign __llvm_core "llvm.bswap.i64";
  110. byte_swap :: proc(i64) -> i64 #foreign __llvm_core "llvm.bswap.i64";
  111. byte_swap :: proc(u128) -> u128 #foreign __llvm_core "llvm.bswap.i128";
  112. byte_swap :: proc(i128) -> i128 #foreign __llvm_core "llvm.bswap.i128";
  113. byte_swap :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { return uint(byte_swap(u32(i))); } else { return uint(byte_swap(u64(i))); } }
  114. byte_swap :: proc(i: int) -> int { when size_of(int) == size_of(i32) { return int(byte_swap(i32(i))); } else { return int(byte_swap(i64(i))); } }
  115. from_be :: proc(i: u8) -> u8 { return i; }
  116. from_be :: proc(i: i8) -> i8 { return i; }
  117. from_be :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  118. from_be :: proc(i: i16) -> i16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  119. from_be :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  120. from_be :: proc(i: i32) -> i32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  121. from_be :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  122. from_be :: proc(i: i64) -> i64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  123. from_be :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  124. from_be :: proc(i: i128) -> i128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  125. from_be :: proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  126. from_be :: proc(i: int) -> int { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  127. from_le :: proc(i: u8) -> u8 { return i; }
  128. from_le :: proc(i: i8) -> i8 { return i; }
  129. from_le :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  130. from_le :: proc(i: i16) -> i16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  131. from_le :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  132. from_le :: proc(i: i32) -> i32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  133. from_le :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  134. from_le :: proc(i: i64) -> i64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  135. from_le :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  136. from_le :: proc(i: i128) -> i128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  137. from_le :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  138. from_le :: proc(i: int) -> int { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  139. to_be :: proc(i: u8) -> u8 { return i; }
  140. to_be :: proc(i: i8) -> i8 { return i; }
  141. to_be :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  142. to_be :: proc(i: i16) -> i16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  143. to_be :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  144. to_be :: proc(i: i32) -> i32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  145. to_be :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  146. to_be :: proc(i: i64) -> i64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  147. to_be :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  148. to_be :: proc(i: i128) -> i128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  149. to_be :: proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  150. to_be :: proc(i: int) -> int { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
  151. to_le :: proc(i: u8) -> u8 { return i; }
  152. to_le :: proc(i: i8) -> i8 { return i; }
  153. to_le :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  154. to_le :: proc(i: i16) -> i16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  155. to_le :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  156. to_le :: proc(i: i32) -> i32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  157. to_le :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  158. to_le :: proc(i: i64) -> i64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  159. to_le :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  160. to_le :: proc(i: i128) -> i128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  161. to_le :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  162. to_le :: proc(i: int) -> int { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
  163. overflowing_add :: proc(lhs, rhs: u8) -> (u8, bool) { op :: proc(u8, u8) -> (u8, bool) #foreign __llvm_core "llvm.uadd.with.overflow.i8"; return op(lhs, rhs); }
  164. overflowing_add :: proc(lhs, rhs: i8) -> (i8, bool) { op :: proc(i8, i8) -> (i8, bool) #foreign __llvm_core "llvm.sadd.with.overflow.i8"; return op(lhs, rhs); }
  165. overflowing_add :: proc(lhs, rhs: u16) -> (u16, bool) { op :: proc(u16, u16) -> (u16, bool) #foreign __llvm_core "llvm.uadd.with.overflow.i16"; return op(lhs, rhs); }
  166. overflowing_add :: proc(lhs, rhs: i16) -> (i16, bool) { op :: proc(i16, i16) -> (i16, bool) #foreign __llvm_core "llvm.sadd.with.overflow.i16"; return op(lhs, rhs); }
  167. overflowing_add :: proc(lhs, rhs: u32) -> (u32, bool) { op :: proc(u32, u32) -> (u32, bool) #foreign __llvm_core "llvm.uadd.with.overflow.i32"; return op(lhs, rhs); }
  168. overflowing_add :: proc(lhs, rhs: i32) -> (i32, bool) { op :: proc(i32, i32) -> (i32, bool) #foreign __llvm_core "llvm.sadd.with.overflow.i32"; return op(lhs, rhs); }
  169. overflowing_add :: proc(lhs, rhs: u64) -> (u64, bool) { op :: proc(u64, u64) -> (u64, bool) #foreign __llvm_core "llvm.uadd.with.overflow.i64"; return op(lhs, rhs); }
  170. overflowing_add :: proc(lhs, rhs: i64) -> (i64, bool) { op :: proc(i64, i64) -> (i64, bool) #foreign __llvm_core "llvm.sadd.with.overflow.i64"; return op(lhs, rhs); }
  171. overflowing_add :: proc(lhs, rhs: u128) -> (u128, bool) { op :: proc(u128, u128) -> (u128, bool) #foreign __llvm_core "llvm.uadd.with.overflow.i128"; return op(lhs, rhs); }
  172. overflowing_add :: proc(lhs, rhs: i128) -> (i128, bool) { op :: proc(i128, i128) -> (i128, bool) #foreign __llvm_core "llvm.sadd.with.overflow.i128"; return op(lhs, rhs); }
  173. overflowing_add :: proc(lhs, rhs: uint) -> (uint, bool) {
  174. when size_of(uint) == size_of(u32) {
  175. x, ok := overflowing_add(u32(lhs), u32(rhs));
  176. return uint(x), ok;
  177. } else {
  178. x, ok := overflowing_add(u64(lhs), u64(rhs));
  179. return uint(x), ok;
  180. }
  181. }
  182. overflowing_add :: proc(lhs, rhs: int) -> (int, bool) {
  183. when size_of(int) == size_of(i32) {
  184. x, ok := overflowing_add(i32(lhs), i32(rhs));
  185. return int(x), ok;
  186. } else {
  187. x, ok := overflowing_add(i64(lhs), i64(rhs));
  188. return int(x), ok;
  189. }
  190. }
  191. overflowing_sub :: proc(lhs, rhs: u8) -> (u8, bool) { op :: proc(u8, u8) -> (u8, bool) #foreign __llvm_core "llvm.usub.with.overflow.i8"; return op(lhs, rhs); }
  192. overflowing_sub :: proc(lhs, rhs: i8) -> (i8, bool) { op :: proc(i8, i8) -> (i8, bool) #foreign __llvm_core "llvm.ssub.with.overflow.i8"; return op(lhs, rhs); }
  193. overflowing_sub :: proc(lhs, rhs: u16) -> (u16, bool) { op :: proc(u16, u16) -> (u16, bool) #foreign __llvm_core "llvm.usub.with.overflow.i16"; return op(lhs, rhs); }
  194. overflowing_sub :: proc(lhs, rhs: i16) -> (i16, bool) { op :: proc(i16, i16) -> (i16, bool) #foreign __llvm_core "llvm.ssub.with.overflow.i16"; return op(lhs, rhs); }
  195. overflowing_sub :: proc(lhs, rhs: u32) -> (u32, bool) { op :: proc(u32, u32) -> (u32, bool) #foreign __llvm_core "llvm.usub.with.overflow.i32"; return op(lhs, rhs); }
  196. overflowing_sub :: proc(lhs, rhs: i32) -> (i32, bool) { op :: proc(i32, i32) -> (i32, bool) #foreign __llvm_core "llvm.ssub.with.overflow.i32"; return op(lhs, rhs); }
  197. overflowing_sub :: proc(lhs, rhs: u64) -> (u64, bool) { op :: proc(u64, u64) -> (u64, bool) #foreign __llvm_core "llvm.usub.with.overflow.i64"; return op(lhs, rhs); }
  198. overflowing_sub :: proc(lhs, rhs: i64) -> (i64, bool) { op :: proc(i64, i64) -> (i64, bool) #foreign __llvm_core "llvm.ssub.with.overflow.i64"; return op(lhs, rhs); }
  199. overflowing_sub :: proc(lhs, rhs: u128) -> (u128, bool) { op :: proc(u128, u128) -> (u128, bool) #foreign __llvm_core "llvm.usub.with.overflow.i128"; return op(lhs, rhs); }
  200. overflowing_sub :: proc(lhs, rhs: i128) -> (i128, bool) { op :: proc(i128, i128) -> (i128, bool) #foreign __llvm_core "llvm.ssub.with.overflow.i128"; return op(lhs, rhs); }
  201. overflowing_sub :: proc(lhs, rhs: uint) -> (uint, bool) {
  202. when size_of(uint) == size_of(u32) {
  203. x, ok := overflowing_sub(u32(lhs), u32(rhs));
  204. return uint(x), ok;
  205. } else {
  206. x, ok := overflowing_sub(u64(lhs), u64(rhs));
  207. return uint(x), ok;
  208. }
  209. }
  210. overflowing_sub :: proc(lhs, rhs: int) -> (int, bool) {
  211. when size_of(int) == size_of(i32) {
  212. x, ok := overflowing_sub(i32(lhs), i32(rhs));
  213. return int(x), ok;
  214. } else {
  215. x, ok := overflowing_sub(i64(lhs), i64(rhs));
  216. return int(x), ok;
  217. }
  218. }
  219. overflowing_mul :: proc(lhs, rhs: u8) -> (u8, bool) { op :: proc(u8, u8) -> (u8, bool) #foreign __llvm_core "llvm.umul.with.overflow.i8"; return op(lhs, rhs); }
  220. overflowing_mul :: proc(lhs, rhs: i8) -> (i8, bool) { op :: proc(i8, i8) -> (i8, bool) #foreign __llvm_core "llvm.smul.with.overflow.i8"; return op(lhs, rhs); }
  221. overflowing_mul :: proc(lhs, rhs: u16) -> (u16, bool) { op :: proc(u16, u16) -> (u16, bool) #foreign __llvm_core "llvm.umul.with.overflow.i16"; return op(lhs, rhs); }
  222. overflowing_mul :: proc(lhs, rhs: i16) -> (i16, bool) { op :: proc(i16, i16) -> (i16, bool) #foreign __llvm_core "llvm.smul.with.overflow.i16"; return op(lhs, rhs); }
  223. overflowing_mul :: proc(lhs, rhs: u32) -> (u32, bool) { op :: proc(u32, u32) -> (u32, bool) #foreign __llvm_core "llvm.umul.with.overflow.i32"; return op(lhs, rhs); }
  224. overflowing_mul :: proc(lhs, rhs: i32) -> (i32, bool) { op :: proc(i32, i32) -> (i32, bool) #foreign __llvm_core "llvm.smul.with.overflow.i32"; return op(lhs, rhs); }
  225. overflowing_mul :: proc(lhs, rhs: u64) -> (u64, bool) { op :: proc(u64, u64) -> (u64, bool) #foreign __llvm_core "llvm.umul.with.overflow.i64"; return op(lhs, rhs); }
  226. overflowing_mul :: proc(lhs, rhs: i64) -> (i64, bool) { op :: proc(i64, i64) -> (i64, bool) #foreign __llvm_core "llvm.smul.with.overflow.i64"; return op(lhs, rhs); }
  227. overflowing_mul :: proc(lhs, rhs: u128) -> (u128, bool) { op :: proc(u128, u128) -> (u128, bool) #foreign __llvm_core "llvm.umul.with.overflow.i128"; return op(lhs, rhs); }
  228. overflowing_mul :: proc(lhs, rhs: i128) -> (i128, bool) { op :: proc(i128, i128) -> (i128, bool) #foreign __llvm_core "llvm.smul.with.overflow.i128"; return op(lhs, rhs); }
  229. overflowing_mul :: proc(lhs, rhs: uint) -> (uint, bool) {
  230. when size_of(uint) == size_of(u32) {
  231. x, ok := overflowing_mul(u32(lhs), u32(rhs));
  232. return uint(x), ok;
  233. } else {
  234. x, ok := overflowing_mul(u64(lhs), u64(rhs));
  235. return uint(x), ok;
  236. }
  237. }
  238. overflowing_mul :: proc(lhs, rhs: int) -> (int, bool) {
  239. when size_of(int) == size_of(i32) {
  240. x, ok := overflowing_mul(i32(lhs), i32(rhs));
  241. return int(x), ok;
  242. } else {
  243. x, ok := overflowing_mul(i64(lhs), i64(rhs));
  244. return int(x), ok;
  245. }
  246. }
  247. is_power_of_two :: proc(i: u8) -> bool { return i > 0 && (i & (i-1)) == 0; }
  248. is_power_of_two :: proc(i: i8) -> bool { return i > 0 && (i & (i-1)) == 0; }
  249. is_power_of_two :: proc(i: u16) -> bool { return i > 0 && (i & (i-1)) == 0; }
  250. is_power_of_two :: proc(i: i16) -> bool { return i > 0 && (i & (i-1)) == 0; }
  251. is_power_of_two :: proc(i: u32) -> bool { return i > 0 && (i & (i-1)) == 0; }
  252. is_power_of_two :: proc(i: i32) -> bool { return i > 0 && (i & (i-1)) == 0; }
  253. is_power_of_two :: proc(i: u64) -> bool { return i > 0 && (i & (i-1)) == 0; }
  254. is_power_of_two :: proc(i: i64) -> bool { return i > 0 && (i & (i-1)) == 0; }
  255. is_power_of_two :: proc(i: u128) -> bool { return i > 0 && (i & (i-1)) == 0; }
  256. is_power_of_two :: proc(i: i128) -> bool { return i > 0 && (i & (i-1)) == 0; }
  257. is_power_of_two :: proc(i: uint) -> bool { return i > 0 && (i & (i-1)) == 0; }
  258. is_power_of_two :: proc(i: int) -> bool { return i > 0 && (i & (i-1)) == 0; }