Browse Source

Make core library use procedure groupings rather than normal overloading

gingerBill 7 years ago
parent
commit
f0de994059
16 changed files with 420 additions and 372 deletions
  1. 5 3
      core/_preload.odin
  2. 28 28
      core/atomics.odin
  3. 211 263
      core/bits.odin
  4. 2 2
      core/fmt.odin
  5. 144 50
      core/math.odin
  6. 5 3
      core/mem.odin
  7. 3 3
      core/opengl.odin
  8. 2 2
      core/os.odin
  9. 3 3
      core/sort.odin
  10. 1 1
      core/sys/wgl.odin
  11. 5 5
      core/sys/windows.odin
  12. 2 2
      core/utf16.odin
  13. 3 3
      core/utf8.odin
  14. 3 2
      src/check_expr.cpp
  15. 1 1
      src/checker.cpp
  16. 2 1
      src/main.cpp

+ 5 - 3
core/_preload.odin

@@ -376,7 +376,7 @@ clear_map :: inline proc "contextless" (m: ^$T/map[$K]$V) {
 
 clear :: proc[clear_dynamic_array, clear_map];
 
-reserve :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> bool {
+reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> bool {
 	if array == nil do return false;
 	a := cast(^raw.Dynamic_Array)array;
 
@@ -453,7 +453,7 @@ __get_map_key :: proc "contextless" (key: $K) -> __Map_Key {
 	return map_key;
 }
 
-reserve :: proc(m: ^$T/map[$K]$V, capacity: int) {
+reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int) {
 	if m != nil do __dynamic_map_reserve(__get_map_header(m), capacity);
 }
 
@@ -461,6 +461,8 @@ delete :: proc(m: ^$T/map[$K]$V, key: K) {
 	if m != nil do __dynamic_map_delete(__get_map_header(m), __get_map_key(key));
 }
 
+reserve :: proc[reserve_dynamic_array, reserve_map];
+
 
 
 new  :: inline proc(T: type, loc := #caller_location) -> ^T {
@@ -705,7 +707,7 @@ __type_assertion_check :: proc "contextless" (ok: bool, file: string, line, colu
 }
 
 __string_decode_rune :: inline proc "contextless" (s: string) -> (rune, int) {
-	return utf8.decode_rune(s);
+	return utf8.decode_rune_from_string(s);
 }
 
 __bounds_check_error_loc :: inline proc "contextless" (using loc := #caller_location, index, count: int) {

+ 28 - 28
core/atomics.odin

@@ -13,90 +13,90 @@ sfence       :: proc() { win32.write_barrier(); }
 lfence       :: proc() { win32.read_barrier(); }
 
 
-load :: proc(a: ^i32) -> i32 {
+load_i32 :: proc(a: ^i32) -> i32 {
 	return a^;
 }
-store :: proc(a: ^i32, value: i32) {
+store_i32 :: proc(a: ^i32, value: i32) {
 	a^ = value;
 }
-compare_exchange :: proc(a: ^i32, expected, desired: i32) -> i32 {
+compare_exchange_i32 :: proc(a: ^i32, expected, desired: i32) -> i32 {
 	return win32.interlocked_compare_exchange(a, desired, expected);
 }
-exchanged :: proc(a: ^i32, desired: i32) -> i32 {
+exchanged_i32 :: proc(a: ^i32, desired: i32) -> i32 {
 	return win32.interlocked_exchange(a, desired);
 }
-fetch_add :: proc(a: ^i32, operand: i32) -> i32 {
+fetch_add_i32 :: proc(a: ^i32, operand: i32) -> i32 {
 	return win32.interlocked_exchange_add(a, operand);
 
 }
-fetch_and :: proc(a: ^i32, operand: i32) -> i32 {
+fetch_and_i32 :: proc(a: ^i32, operand: i32) -> i32 {
 	return win32.interlocked_and(a, operand);
 }
-fetch_or :: proc(a: ^i32, operand: i32) -> i32 {
+fetch_or_i32 :: proc(a: ^i32, operand: i32) -> i32 {
 	return win32.interlocked_or(a, operand);
 }
-spin_lock :: proc(a: ^i32, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
-	old_value := compare_exchange(a, 1, 0);
+spin_lock_i32 :: proc(a: ^i32, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
+	old_value := compare_exchange_i32(a, 1, 0);
 	counter := 0;
 	for old_value != 0 && (time_out < 0 || counter < time_out) {
 		counter += 1;
 		yield_thread();
-		old_value = compare_exchange(a, 1, 0);
+		old_value = compare_exchange_i32(a, 1, 0);
 		mfence();
 	}
 	return old_value == 0;
 }
-spin_unlock :: proc(a: ^i32) {
-	store(a, 0);
+spin_unlock_i32 :: proc(a: ^i32) {
+	store_i32(a, 0);
 	mfence();
 }
-try_acquire_lock :: proc(a: ^i32) -> bool {
+try_acquire_lock_i32 :: proc(a: ^i32) -> bool {
 	yield_thread();
-	old_value := compare_exchange(a, 1, 0);
+	old_value := compare_exchange_i32(a, 1, 0);
 	mfence();
 	return old_value == 0;
 }
 
 
-load :: proc(a: ^i64) -> i64 {
+load_i64 :: proc(a: ^i64) -> i64 {
 	return a^;
 }
-store :: proc(a: ^i64, value: i64) {
+store_i64 :: proc(a: ^i64, value: i64) {
 	a^ = value;
 }
-compare_exchange :: proc(a: ^i64, expected, desired: i64) -> i64 {
+compare_exchange_i64 :: proc(a: ^i64, expected, desired: i64) -> i64 {
 	return win32.interlocked_compare_exchange64(a, desired, expected);
 }
-exchanged :: proc(a: ^i64, desired: i64) -> i64 {
+exchanged_i64 :: proc(a: ^i64, desired: i64) -> i64 {
 	return win32.interlocked_exchange64(a, desired);
 }
-fetch_add :: proc(a: ^i64, operand: i64) -> i64 {
+fetch_add_i64 :: proc(a: ^i64, operand: i64) -> i64 {
 	return win32.interlocked_exchange_add64(a, operand);
 }
-fetch_and :: proc(a: ^i64, operand: i64) -> i64 {
+fetch_and_i64 :: proc(a: ^i64, operand: i64) -> i64 {
 	return win32.interlocked_and64(a, operand);
 }
-fetch_or :: proc(a: ^i64, operand: i64) -> i64 {
+fetch_or_i64 :: proc(a: ^i64, operand: i64) -> i64 {
 	return win32.interlocked_or64(a, operand);
 }
-spin_lock :: proc(a: ^i64, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
-	old_value := compare_exchange(a, 1, 0);
+spin_lock_i64 :: proc(a: ^i64, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
+	old_value := compare_exchange_i64(a, 1, 0);
 	counter := 0;
 	for old_value != 0 && (time_out < 0 || counter < time_out) {
 		counter += 1;
 		yield_thread();
-		old_value = compare_exchange(a, 1, 0);
+		old_value = compare_exchange_i64(a, 1, 0);
 		mfence();
 	}
 	return old_value == 0;
 }
-spin_unlock :: proc(a: ^i64) {
-	store(a, 0);
+spin_unlock_i64 :: proc(a: ^i64) {
+	store_i64(a, 0);
 	mfence();
 }
-try_acquire_lock :: proc(a: ^i64) -> bool {
+try_acquire_lock_i64 :: proc(a: ^i64) -> bool {
 	yield_thread();
-	old_value := compare_exchange(a, 1, 0);
+	old_value := compare_exchange_i64(a, 1, 0);
 	mfence();
 	return old_value == 0;
 }

+ 211 - 263
core/bits.odin

@@ -23,306 +23,254 @@ I64_MAX  ::  -I64_MIN - 1;
 I128_MAX :: -I128_MIN - 1;
 
 foreign __llvm_core {
-	@(link_name="llvm.ctpop.i8")        __llvm_ctpop :: proc(u8)   ->   u8 ---;
-	@(link_name="llvm.ctpop.i8")        __llvm_ctpop :: proc(i8)   ->   i8 ---;
-	@(link_name="llvm.ctpop.i16")       __llvm_ctpop :: proc(u16)  ->  u16 ---;
-	@(link_name="llvm.ctpop.i16")       __llvm_ctpop :: proc(i16)  ->  i16 ---;
-	@(link_name="llvm.ctpop.i32")       __llvm_ctpop :: proc(u32)  ->  u32 ---;
-	@(link_name="llvm.ctpop.i32")       __llvm_ctpop :: proc(i32)  ->  i32 ---;
-	@(link_name="llvm.ctpop.i64")       __llvm_ctpop :: proc(u64)  ->  u64 ---;
-	@(link_name="llvm.ctpop.i64")       __llvm_ctpop :: proc(i64)  ->  i64 ---;
-	@(link_name="llvm.ctpop.i128")      __llvm_ctpop :: proc(u128) -> u128 ---;
-	@(link_name="llvm.ctpop.i128")      __llvm_ctpop :: proc(i128) -> i128 ---;
-
-	@(link_name="llvm.ctlz.i8")         __llvm_ctlz :: proc(u8,   bool) ->   u8 ---;
-	@(link_name="llvm.ctlz.i8")         __llvm_ctlz :: proc(i8,   bool) ->   i8 ---;
-	@(link_name="llvm.ctlz.i16")        __llvm_ctlz :: proc(u16,  bool) ->  u16 ---;
-	@(link_name="llvm.ctlz.i16")        __llvm_ctlz :: proc(i16,  bool) ->  i16 ---;
-	@(link_name="llvm.ctlz.i32")        __llvm_ctlz :: proc(u32,  bool) ->  u32 ---;
-	@(link_name="llvm.ctlz.i32")        __llvm_ctlz :: proc(i32,  bool) ->  i32 ---;
-	@(link_name="llvm.ctlz.i64")        __llvm_ctlz :: proc(u64,  bool) ->  u64 ---;
-	@(link_name="llvm.ctlz.i64")        __llvm_ctlz :: proc(i64,  bool) ->  i64 ---;
-	@(link_name="llvm.ctlz.i128")       __llvm_ctlz :: proc(u128, bool) -> u128 ---;
-	@(link_name="llvm.ctlz.i128")       __llvm_ctlz :: proc(i128, bool) -> i128 ---;
-
-	@(link_name="llvm.cttz.i8")         __llvm_cttz :: proc(u8,   bool) ->   u8 ---;
-	@(link_name="llvm.cttz.i8")         __llvm_cttz :: proc(i8,   bool) ->   i8 ---;
-	@(link_name="llvm.cttz.i16")        __llvm_cttz :: proc(u16,  bool) ->  u16 ---;
-	@(link_name="llvm.cttz.i16")        __llvm_cttz :: proc(i16,  bool) ->  i16 ---;
-	@(link_name="llvm.cttz.i32")        __llvm_cttz :: proc(u32,  bool) ->  u32 ---;
-	@(link_name="llvm.cttz.i32")        __llvm_cttz :: proc(i32,  bool) ->  i32 ---;
-	@(link_name="llvm.cttz.i64")        __llvm_cttz :: proc(u64,  bool) ->  u64 ---;
-	@(link_name="llvm.cttz.i64")        __llvm_cttz :: proc(i64,  bool) ->  i64 ---;
-	@(link_name="llvm.cttz.i128")       __llvm_cttz :: proc(u128, bool) -> u128 ---;
-	@(link_name="llvm.cttz.i128")       __llvm_cttz :: proc(i128, bool) -> i128 ---;
-
-	@(link_name="llvm.bitreverse.i8")   __llvm_bitreverse :: proc(u8)   ->   u8 ---;
-	@(link_name="llvm.bitreverse.i8")   __llvm_bitreverse :: proc(i8)   ->   i8 ---;
-	@(link_name="llvm.bitreverse.i16")  __llvm_bitreverse :: proc(u16)  ->  u16 ---;
-	@(link_name="llvm.bitreverse.i16")  __llvm_bitreverse :: proc(i16)  ->  i16 ---;
-	@(link_name="llvm.bitreverse.i32")  __llvm_bitreverse :: proc(u32)  ->  u32 ---;
-	@(link_name="llvm.bitreverse.i32")  __llvm_bitreverse :: proc(i32)  ->  i32 ---;
-	@(link_name="llvm.bitreverse.i64")  __llvm_bitreverse :: proc(u64)  ->  u64 ---;
-	@(link_name="llvm.bitreverse.i64")  __llvm_bitreverse :: proc(i64)  ->  i64 ---;
-	@(link_name="llvm.bitreverse.i128") __llvm_bitreverse :: proc(u128) -> u128 ---;
-	@(link_name="llvm.bitreverse.i128") __llvm_bitreverse :: proc(i128) -> i128 ---;
-
-	@(link_name="llvm.bswap.i16")  byte_swap :: proc(u16)  ->  u16 ---;
-	@(link_name="llvm.bswap.i16")  byte_swap :: proc(i16)  ->  i16 ---;
-	@(link_name="llvm.bswap.i32")  byte_swap :: proc(u32)  ->  u32 ---;
-	@(link_name="llvm.bswap.i32")  byte_swap :: proc(i32)  ->  i32 ---;
-	@(link_name="llvm.bswap.i64")  byte_swap :: proc(u64)  ->  u64 ---;
-	@(link_name="llvm.bswap.i64")  byte_swap :: proc(i64)  ->  i64 ---;
-	@(link_name="llvm.bswap.i128") byte_swap :: proc(u128) -> u128 ---;
-	@(link_name="llvm.bswap.i128") byte_swap :: proc(i128) -> i128 ---;
+	@(link_name="llvm.ctpop.i8")        __llvm_ctpop8   :: proc(u8)   ->   u8 ---;
+	@(link_name="llvm.ctpop.i16")       __llvm_ctpop16  :: proc(u16)  ->  u16 ---;
+	@(link_name="llvm.ctpop.i32")       __llvm_ctpop32  :: proc(u32)  ->  u32 ---;
+	@(link_name="llvm.ctpop.i64")       __llvm_ctpop64  :: proc(u64)  ->  u64 ---;
+	@(link_name="llvm.ctpop.i128")      __llvm_ctpop128 :: proc(u128) -> u128 ---;
+
+	@(link_name="llvm.ctlz.i8")         __llvm_ctlz8   :: proc(u8,   bool) ->   u8 ---;
+	@(link_name="llvm.ctlz.i16")        __llvm_ctlz16  :: proc(u16,  bool) ->  u16 ---;
+	@(link_name="llvm.ctlz.i32")        __llvm_ctlz32  :: proc(u32,  bool) ->  u32 ---;
+	@(link_name="llvm.ctlz.i64")        __llvm_ctlz64  :: proc(u64,  bool) ->  u64 ---;
+	@(link_name="llvm.ctlz.i128")       __llvm_ctlz128 :: proc(u128, bool) -> u128 ---;
+
+	@(link_name="llvm.cttz.i8")         __llvm_cttz8   :: proc(u8,   bool) ->   u8 ---;
+	@(link_name="llvm.cttz.i16")        __llvm_cttz16  :: proc(u16,  bool) ->  u16 ---;
+	@(link_name="llvm.cttz.i32")        __llvm_cttz32  :: proc(u32,  bool) ->  u32 ---;
+	@(link_name="llvm.cttz.i64")        __llvm_cttz64  :: proc(u64,  bool) ->  u64 ---;
+	@(link_name="llvm.cttz.i128")       __llvm_cttz128 :: proc(u128, bool) -> u128 ---;
+
+	@(link_name="llvm.bitreverse.i8")   __llvm_bitreverse8   :: proc(u8)   ->   u8 ---;
+	@(link_name="llvm.bitreverse.i16")  __llvm_bitreverse16  :: proc(u16)  ->  u16 ---;
+	@(link_name="llvm.bitreverse.i32")  __llvm_bitreverse32  :: proc(u32)  ->  u32 ---;
+	@(link_name="llvm.bitreverse.i64")  __llvm_bitreverse64  :: proc(u64)  ->  u64 ---;
+	@(link_name="llvm.bitreverse.i128") __llvm_bitreverse128 :: proc(u128) -> u128 ---;
+
+	@(link_name="llvm.bswap.i16")  byte_swap16  :: proc(u16)  ->  u16 ---;
+	@(link_name="llvm.bswap.i32")  byte_swap32  :: proc(u32)  ->  u32 ---;
+	@(link_name="llvm.bswap.i64")  byte_swap64  :: proc(u64)  ->  u64 ---;
+	@(link_name="llvm.bswap.i128") byte_swap128 :: proc(u128) -> u128 ---;
+}
+
+byte_swap_uint :: proc(i: uint) -> uint {
+	when size_of(uint) == size_of(u32) {
+		return uint(byte_swap32(u32(i)));
+	} else {
+		return uint(byte_swap64(u64(i)));
+	}
 }
-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))); } }
-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))); } }
-
-count_ones :: proc(i:   u8) ->   u8 { return __llvm_ctpop(i); }
-count_ones :: proc(i:   i8) ->   i8 { return __llvm_ctpop(i); }
-count_ones :: proc(i:  u16) ->  u16 { return __llvm_ctpop(i); }
-count_ones :: proc(i:  i16) ->  i16 { return __llvm_ctpop(i); }
-count_ones :: proc(i:  u32) ->  u32 { return __llvm_ctpop(i); }
-count_ones :: proc(i:  i32) ->  i32 { return __llvm_ctpop(i); }
-count_ones :: proc(i:  u64) ->  u64 { return __llvm_ctpop(i); }
-count_ones :: proc(i:  i64) ->  i64 { return __llvm_ctpop(i); }
-count_ones :: proc(i: u128) -> u128 { return __llvm_ctpop(i); }
-count_ones :: proc(i: i128) -> i128 { return __llvm_ctpop(i); }
-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))); } }
-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))); } }
-
-count_zeros :: proc(i:   u8) ->   u8 { return   8 - count_ones(i); }
-count_zeros :: proc(i:   i8) ->   i8 { return   8 - count_ones(i); }
-count_zeros :: proc(i:  u16) ->  u16 { return  16 - count_ones(i); }
-count_zeros :: proc(i:  i16) ->  i16 { return  16 - count_ones(i); }
-count_zeros :: proc(i:  u32) ->  u32 { return  32 - count_ones(i); }
-count_zeros :: proc(i:  i32) ->  i32 { return  32 - count_ones(i); }
-count_zeros :: proc(i:  u64) ->  u64 { return  64 - count_ones(i); }
-count_zeros :: proc(i:  i64) ->  i64 { return  64 - count_ones(i); }
-count_zeros :: proc(i: u128) -> u128 { return 128 - count_ones(i); }
-count_zeros :: proc(i: i128) -> i128 { return 128 - count_ones(i); }
-count_zeros :: proc(i: uint) -> uint { return 8*size_of(uint) - count_ones(i); }
-count_zeros :: proc(i:  int) ->  int { return 8*size_of(int)  - count_ones(i); }
-
-
-rotate_left :: proc(i: u8,   s: uint) ->   u8 { return (i << s)|(i >> (8*size_of(u8)   - s)); }
-rotate_left :: proc(i: i8,   s: uint) ->   i8 { return (i << s)|(i >> (8*size_of(i8)   - s)); }
-rotate_left :: proc(i: u16,  s: uint) ->  u16 { return (i << s)|(i >> (8*size_of(u16)  - s)); }
-rotate_left :: proc(i: i16,  s: uint) ->  i16 { return (i << s)|(i >> (8*size_of(i16)  - s)); }
-rotate_left :: proc(i: u32,  s: uint) ->  u32 { return (i << s)|(i >> (8*size_of(u32)  - s)); }
-rotate_left :: proc(i: i32,  s: uint) ->  i32 { return (i << s)|(i >> (8*size_of(i32)  - s)); }
-rotate_left :: proc(i: u64,  s: uint) ->  u64 { return (i << s)|(i >> (8*size_of(u64)  - s)); }
-rotate_left :: proc(i: i64,  s: uint) ->  i64 { return (i << s)|(i >> (8*size_of(i64)  - s)); }
-rotate_left :: proc(i: u128, s: uint) -> u128 { return (i << s)|(i >> (8*size_of(u128) - s)); }
-rotate_left :: proc(i: i128, s: uint) -> i128 { return (i << s)|(i >> (8*size_of(i128) - s)); }
-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)); } }
-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)); } }
-
-
-rotate_right :: proc(i: u8,   s: uint) ->   u8 { return (i >> s)|(i << (8*size_of(u8)   - s)); }
-rotate_right :: proc(i: i8,   s: uint) ->   i8 { return (i >> s)|(i << (8*size_of(i8)   - s)); }
-rotate_right :: proc(i: u16,  s: uint) ->  u16 { return (i >> s)|(i << (8*size_of(u16)  - s)); }
-rotate_right :: proc(i: i16,  s: uint) ->  i16 { return (i >> s)|(i << (8*size_of(i16)  - s)); }
-rotate_right :: proc(i: u32,  s: uint) ->  u32 { return (i >> s)|(i << (8*size_of(u32)  - s)); }
-rotate_right :: proc(i: i32,  s: uint) ->  i32 { return (i >> s)|(i << (8*size_of(i32)  - s)); }
-rotate_right :: proc(i: u64,  s: uint) ->  u64 { return (i >> s)|(i << (8*size_of(u64)  - s)); }
-rotate_right :: proc(i: i64,  s: uint) ->  i64 { return (i >> s)|(i << (8*size_of(i64)  - s)); }
-rotate_right :: proc(i: u128, s: uint) -> u128 { return (i >> s)|(i << (8*size_of(u128) - s)); }
-rotate_right :: proc(i: i128, s: uint) -> i128 { return (i >> s)|(i << (8*size_of(i128) - s)); }
-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)); } }
-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)); } }
-
-leading_zeros :: proc(i:   u8) ->   u8 { return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:   i8) ->   i8 { return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  u16) ->  u16 { return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  i16) ->  i16 { return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  u32) ->  u32 { return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  i32) ->  i32 { return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  u64) ->  u64 { return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i:  i64) ->  i64 { return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i: u128) -> u128 { return __llvm_ctlz(i, false); }
-leading_zeros :: proc(i: i128) -> i128 { return __llvm_ctlz(i, false); }
-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))); } }
-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))); } }
-
-trailing_zeros :: proc(i:   u8) ->   u8 { return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:   i8) ->   i8 { return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  u16) ->  u16 { return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  i16) ->  i16 { return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  u32) ->  u32 { return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  i32) ->  i32 { return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  u64) ->  u64 { return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i:  i64) ->  i64 { return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i: u128) -> u128 { return __llvm_cttz(i, false); }
-trailing_zeros :: proc(i: i128) -> i128 { return __llvm_cttz(i, false); }
-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))); } }
-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))); } }
-
-
-reverse_bits :: proc(i:   u8) ->   u8 { return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:   i8) ->   i8 { return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  u16) ->  u16 { return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  i16) ->  i16 { return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  u32) ->  u32 { return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  i32) ->  i32 { return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  u64) ->  u64 { return __llvm_bitreverse(i); }
-reverse_bits :: proc(i:  i64) ->  i64 { return __llvm_bitreverse(i); }
-reverse_bits :: proc(i: u128) -> u128 { return __llvm_bitreverse(i); }
-reverse_bits :: proc(i: i128) -> i128 { return __llvm_bitreverse(i); }
-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))); } }
-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))); } }
-
-from_be :: proc(i:   u8) ->   u8 { return i; }
-from_be :: proc(i:   i8) ->   i8 { return i; }
-from_be :: proc(i:  u16) ->  u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-from_be :: proc(i:  i16) ->  i16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-from_be :: proc(i:  u32) ->  u32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-from_be :: proc(i:  i32) ->  i32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-from_be :: proc(i:  u64) ->  u64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-from_be :: proc(i:  i64) ->  i64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-from_be :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-from_be :: proc(i: i128) -> i128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-from_be :: proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-from_be :: proc(i:  int) ->  int { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-
-from_le :: proc(i:   u8) ->   u8 { return i; }
-from_le :: proc(i:   i8) ->   i8 { return i; }
-from_le :: proc(i:  u16) ->  u16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-from_le :: proc(i:  i16) ->  i16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-from_le :: proc(i:  u32) ->  u32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-from_le :: proc(i:  i32) ->  i32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-from_le :: proc(i:  u64) ->  u64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-from_le :: proc(i:  i64) ->  i64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-from_le :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-from_le :: proc(i: i128) -> i128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-from_le :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-from_le :: proc(i:  int) ->  int { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-
-to_be :: proc(i:   u8) ->   u8 { return i; }
-to_be :: proc(i:   i8) ->   i8 { return i; }
-to_be :: proc(i:  u16) ->  u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-to_be :: proc(i:  i16) ->  i16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-to_be :: proc(i:  u32) ->  u32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-to_be :: proc(i:  i32) ->  i32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-to_be :: proc(i:  u64) ->  u64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-to_be :: proc(i:  i64) ->  i64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-to_be :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-to_be :: proc(i: i128) -> i128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-to_be :: proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-to_be :: proc(i:  int) ->  int { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
-
-
-to_le :: proc(i:   u8) ->   u8 { return i; }
-to_le :: proc(i:   i8) ->   i8 { return i; }
-to_le :: proc(i:  u16) ->  u16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-to_le :: proc(i:  i16) ->  i16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-to_le :: proc(i:  u32) ->  u32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-to_le :: proc(i:  i32) ->  i32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-to_le :: proc(i:  u64) ->  u64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-to_le :: proc(i:  i64) ->  i64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-to_le :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-to_le :: proc(i: i128) -> i128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-to_le :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-to_le :: proc(i:  int) ->  int { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
-
-
-overflowing_add :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i8")   op :: proc(u8, u8)     -> (u8, bool)   ---; return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i8")   op :: proc(i8, i8)     -> (i8, bool)   ---; return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i16")  op :: proc(u16, u16)   -> (u16, bool)  ---; return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i16")  op :: proc(i16, i16)   -> (i16, bool)  ---; return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i32")  op :: proc(u32, u32)   -> (u32, bool)  ---; return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i32")  op :: proc(i32, i32)   -> (i32, bool)  ---; return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i64")  op :: proc(u64, u64)   -> (u64, bool)  ---; return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i64")  op :: proc(i64, i64)   -> (i64, bool)  ---; return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i128") op :: proc(u128, u128) -> (u128, bool) ---; return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i128") op :: proc(i128, i128) -> (i128, bool) ---; return op(lhs, rhs); }
-overflowing_add :: proc(lhs, rhs: uint) -> (uint, bool) {
+
+byte_swap :: proc[byte_swap16, byte_swap32, byte_swap64, byte_swap128, byte_swap_uint];
+
+count_ones8   :: proc(i:   u8) ->   u8 { return __llvm_ctpop8(i); }
+count_ones16  :: proc(i:  u16) ->  u16 { return __llvm_ctpop16(i); }
+count_ones32  :: proc(i:  u32) ->  u32 { return __llvm_ctpop32(i); }
+count_ones64  :: proc(i:  u64) ->  u64 { return __llvm_ctpop64(i); }
+count_ones128 :: proc(i: u128) -> u128 { return __llvm_ctpop128(i); }
+
+count_zeros8   :: proc(i:   u8) ->   u8 { return   8 - count_ones8(i); }
+count_zeros16  :: proc(i:  u16) ->  u16 { return  16 - count_ones16(i); }
+count_zeros32  :: proc(i:  u32) ->  u32 { return  32 - count_ones32(i); }
+count_zeros64  :: proc(i:  u64) ->  u64 { return  64 - count_ones64(i); }
+count_zeros128 :: proc(i: u128) -> u128 { return 128 - count_ones128(i); }
+
+
+rotate_left8   :: proc(i: u8,   s: uint) ->   u8 { return (i << s)|(i >> (8*size_of(u8)   - s)); }
+rotate_left16  :: proc(i: u16,  s: uint) ->  u16 { return (i << s)|(i >> (8*size_of(u16)  - s)); }
+rotate_left32  :: proc(i: u32,  s: uint) ->  u32 { return (i << s)|(i >> (8*size_of(u32)  - s)); }
+rotate_left64  :: proc(i: u64,  s: uint) ->  u64 { return (i << s)|(i >> (8*size_of(u64)  - s)); }
+rotate_left128 :: proc(i: u128, s: uint) -> u128 { return (i << s)|(i >> (8*size_of(u128) - s)); }
+
+
+rotate_right8   :: proc(i: u8,   s: uint) ->   u8 { return (i >> s)|(i << (8*size_of(u8)   - s)); }
+rotate_right16  :: proc(i: u16,  s: uint) ->  u16 { return (i >> s)|(i << (8*size_of(u16)  - s)); }
+rotate_right32  :: proc(i: u32,  s: uint) ->  u32 { return (i >> s)|(i << (8*size_of(u32)  - s)); }
+rotate_right64  :: proc(i: u64,  s: uint) ->  u64 { return (i >> s)|(i << (8*size_of(u64)  - s)); }
+rotate_right128 :: proc(i: u128, s: uint) -> u128 { return (i >> s)|(i << (8*size_of(u128) - s)); }
+
+leading_zeros8   :: proc(i:   u8) ->   u8 { return __llvm_ctlz8(i, false); }
+leading_zeros16  :: proc(i:  u16) ->  u16 { return __llvm_ctlz16(i, false); }
+leading_zeros32  :: proc(i:  u32) ->  u32 { return __llvm_ctlz32(i, false); }
+leading_zeros64  :: proc(i:  u64) ->  u64 { return __llvm_ctlz64(i, false); }
+leading_zeros128 :: proc(i: u128) -> u128 { return __llvm_ctlz128(i, false); }
+
+trailing_zeros8   :: proc(i:   u8) ->   u8 { return __llvm_cttz8(i, false); }
+trailing_zeros16  :: proc(i:  u16) ->  u16 { return __llvm_cttz16(i, false); }
+trailing_zeros32  :: proc(i:  u32) ->  u32 { return __llvm_cttz32(i, false); }
+trailing_zeros64  :: proc(i:  u64) ->  u64 { return __llvm_cttz64(i, false); }
+trailing_zeros128 :: proc(i: u128) -> u128 { return __llvm_cttz128(i, false); }
+
+
+reverse_bits8   :: proc(i:   u8) ->   u8 { return __llvm_bitreverse8(i); }
+reverse_bits16  :: proc(i:  u16) ->  u16 { return __llvm_bitreverse16(i); }
+reverse_bits32  :: proc(i:  u32) ->  u32 { return __llvm_bitreverse32(i); }
+reverse_bits64  :: proc(i:  u64) ->  u64 { return __llvm_bitreverse64(i); }
+reverse_bits128 :: proc(i: u128) -> u128 { return __llvm_bitreverse128(i); }
+
+from_be_u8   :: proc(i:   u8) ->   u8 { return i; }
+from_be_u16  :: proc(i:  u16) ->  u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
+from_be_u32  :: proc(i:  u32) ->  u32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
+from_be_u64  :: proc(i:  u64) ->  u64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
+from_be_u128 :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
+from_be_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
+
+from_le_u8   :: proc(i:   u8) ->   u8 { return i; }
+from_le_u16  :: proc(i:  u16) ->  u16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
+from_le_u32  :: proc(i:  u32) ->  u32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
+from_le_u64  :: proc(i:  u64) ->  u64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
+from_le_u128 :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
+from_le_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
+
+to_be_u8   :: proc(i:   u8) ->   u8 { return i; }
+to_be_u16  :: proc(i:  u16) ->  u16 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
+to_be_u32  :: proc(i:  u32) ->  u32 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
+to_be_u64  :: proc(i:  u64) ->  u64 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
+to_be_u128 :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
+to_be_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i; } else { return byte_swap(i); } }
+
+
+to_le_u8   :: proc(i:   u8) ->   u8 { return i; }
+to_le_u16  :: proc(i:  u16) ->  u16 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
+to_le_u32  :: proc(i:  u32) ->  u32 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
+to_le_u64  :: proc(i:  u64) ->  u64 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
+to_le_u128 :: proc(i: u128) -> u128 { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
+to_le_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i; } else { return byte_swap(i); } }
+
+
+overflowing_add_u8   :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i8")   op :: proc(u8, u8)     -> (u8, bool)   ---; return op(lhs, rhs); }
+overflowing_add_i8   :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i8")   op :: proc(i8, i8)     -> (i8, bool)   ---; return op(lhs, rhs); }
+overflowing_add_u16  :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i16")  op :: proc(u16, u16)   -> (u16, bool)  ---; return op(lhs, rhs); }
+overflowing_add_i16  :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i16")  op :: proc(i16, i16)   -> (i16, bool)  ---; return op(lhs, rhs); }
+overflowing_add_u32  :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i32")  op :: proc(u32, u32)   -> (u32, bool)  ---; return op(lhs, rhs); }
+overflowing_add_i32  :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i32")  op :: proc(i32, i32)   -> (i32, bool)  ---; return op(lhs, rhs); }
+overflowing_add_u64  :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i64")  op :: proc(u64, u64)   -> (u64, bool)  ---; return op(lhs, rhs); }
+overflowing_add_i64  :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i64")  op :: proc(i64, i64)   -> (i64, bool)  ---; return op(lhs, rhs); }
+overflowing_add_u128 :: proc(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core @(link_name="llvm.uadd.with.overflow.i128") op :: proc(u128, u128) -> (u128, bool) ---; return op(lhs, rhs); }
+overflowing_add_i128 :: proc(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core @(link_name="llvm.sadd.with.overflow.i128") op :: proc(i128, i128) -> (i128, bool) ---; return op(lhs, rhs); }
+overflowing_add_uint :: proc(lhs, rhs: uint) -> (uint, bool) {
 	when size_of(uint) == size_of(u32) {
-		x, ok := overflowing_add(u32(lhs), u32(rhs));
+		x, ok := overflowing_add_u32(u32(lhs), u32(rhs));
 		return uint(x), ok;
 	} else {
-		x, ok := overflowing_add(u64(lhs), u64(rhs));
+		x, ok := overflowing_add_u64(u64(lhs), u64(rhs));
 		return uint(x), ok;
 	}
 }
-overflowing_add :: proc(lhs, rhs: int) -> (int, bool) {
+overflowing_add_int :: proc(lhs, rhs: int) -> (int, bool) {
 	when size_of(int) == size_of(i32) {
-		x, ok := overflowing_add(i32(lhs), i32(rhs));
+		x, ok := overflowing_add_i32(i32(lhs), i32(rhs));
 		return int(x), ok;
 	} else {
-		x, ok := overflowing_add(i64(lhs), i64(rhs));
+		x, ok := overflowing_add_i64(i64(lhs), i64(rhs));
 		return int(x), ok;
 	}
 }
 
-overflowing_sub :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i8")   op :: proc(u8, u8)     -> (u8, bool)   ---; return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i8")   op :: proc(i8, i8)     -> (i8, bool)   ---; return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i16")  op :: proc(u16, u16)   -> (u16, bool)  ---; return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i16")  op :: proc(i16, i16)   -> (i16, bool)  ---; return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i32")  op :: proc(u32, u32)   -> (u32, bool)  ---; return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i32")  op :: proc(i32, i32)   -> (i32, bool)  ---; return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i64")  op :: proc(u64, u64)   -> (u64, bool)  ---; return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i64")  op :: proc(i64, i64)   -> (i64, bool)  ---; return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i128") op :: proc(u128, u128) -> (u128, bool) ---; return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i128") op :: proc(i128, i128) -> (i128, bool) ---; return op(lhs, rhs); }
-overflowing_sub :: proc(lhs, rhs: uint) -> (uint, bool) {
+overflowing_add :: proc[
+	overflowing_add_u8,   overflowing_add_i8,
+	overflowing_add_u16,  overflowing_add_i16,
+	overflowing_add_u32,  overflowing_add_i32,
+	overflowing_add_u64,  overflowing_add_i64,
+	overflowing_add_u128, overflowing_add_i128,
+	overflowing_add_uint, overflowing_add_int,
+];
+
+overflowing_sub_u8   :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i8")   op :: proc(u8, u8)     -> (u8, bool)   ---; return op(lhs, rhs); }
+overflowing_sub_i8   :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i8")   op :: proc(i8, i8)     -> (i8, bool)   ---; return op(lhs, rhs); }
+overflowing_sub_u16  :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i16")  op :: proc(u16, u16)   -> (u16, bool)  ---; return op(lhs, rhs); }
+overflowing_sub_i16  :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i16")  op :: proc(i16, i16)   -> (i16, bool)  ---; return op(lhs, rhs); }
+overflowing_sub_u32  :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i32")  op :: proc(u32, u32)   -> (u32, bool)  ---; return op(lhs, rhs); }
+overflowing_sub_i32  :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i32")  op :: proc(i32, i32)   -> (i32, bool)  ---; return op(lhs, rhs); }
+overflowing_sub_u64  :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i64")  op :: proc(u64, u64)   -> (u64, bool)  ---; return op(lhs, rhs); }
+overflowing_sub_i64  :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i64")  op :: proc(i64, i64)   -> (i64, bool)  ---; return op(lhs, rhs); }
+overflowing_sub_u128 :: proc(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core @(link_name="llvm.usub.with.overflow.i128") op :: proc(u128, u128) -> (u128, bool) ---; return op(lhs, rhs); }
+overflowing_sub_i128 :: proc(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core @(link_name="llvm.ssub.with.overflow.i128") op :: proc(i128, i128) -> (i128, bool) ---; return op(lhs, rhs); }
+overflowing_sub_uint :: proc(lhs, rhs: uint) -> (uint, bool) {
 	when size_of(uint) == size_of(u32) {
-		x, ok := overflowing_sub(u32(lhs), u32(rhs));
+		x, ok := overflowing_sub_u32(u32(lhs), u32(rhs));
 		return uint(x), ok;
 	} else {
-		x, ok := overflowing_sub(u64(lhs), u64(rhs));
+		x, ok := overflowing_sub_u64(u64(lhs), u64(rhs));
 		return uint(x), ok;
 	}
 }
-overflowing_sub :: proc(lhs, rhs: int) -> (int, bool) {
+overflowing_sub_int :: proc(lhs, rhs: int) -> (int, bool) {
 	when size_of(int) == size_of(i32) {
-		x, ok := overflowing_sub(i32(lhs), i32(rhs));
+		x, ok := overflowing_sub_i32(i32(lhs), i32(rhs));
 		return int(x), ok;
 	} else {
-		x, ok := overflowing_sub(i64(lhs), i64(rhs));
+		x, ok := overflowing_sub_i64(i64(lhs), i64(rhs));
 		return int(x), ok;
 	}
 }
 
-overflowing_mul :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i8")   op :: proc(u8, u8)     -> (u8, bool)   ---; return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i8")   op :: proc(i8, i8)     -> (i8, bool)   ---; return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i16")  op :: proc(u16, u16)   -> (u16, bool)  ---; return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i16")  op :: proc(i16, i16)   -> (i16, bool)  ---; return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i32")  op :: proc(u32, u32)   -> (u32, bool)  ---; return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i32")  op :: proc(i32, i32)   -> (i32, bool)  ---; return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i64")  op :: proc(u64, u64)   -> (u64, bool)  ---; return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i64")  op :: proc(i64, i64)   -> (i64, bool)  ---; return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i128") op :: proc(u128, u128) -> (u128, bool) ---; return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i128") op :: proc(i128, i128) -> (i128, bool) ---; return op(lhs, rhs); }
-overflowing_mul :: proc(lhs, rhs: uint) -> (uint, bool) {
+overflowing_sub :: proc[
+	overflowing_sub_u8,   overflowing_sub_i8,
+	overflowing_sub_u16,  overflowing_sub_i16,
+	overflowing_sub_u32,  overflowing_sub_i32,
+	overflowing_sub_u64,  overflowing_sub_i64,
+	overflowing_sub_u128, overflowing_sub_i128,
+	overflowing_sub_uint, overflowing_sub_int,
+];
+
+
+overflowing_mul_u8   :: proc(lhs, rhs:   u8) -> (u8, bool)   { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i8")   op :: proc(u8, u8)     -> (u8, bool)   ---; return op(lhs, rhs); }
+overflowing_mul_i8   :: proc(lhs, rhs:   i8) -> (i8, bool)   { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i8")   op :: proc(i8, i8)     -> (i8, bool)   ---; return op(lhs, rhs); }
+overflowing_mul_u16  :: proc(lhs, rhs:  u16) -> (u16, bool)  { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i16")  op :: proc(u16, u16)   -> (u16, bool)  ---; return op(lhs, rhs); }
+overflowing_mul_i16  :: proc(lhs, rhs:  i16) -> (i16, bool)  { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i16")  op :: proc(i16, i16)   -> (i16, bool)  ---; return op(lhs, rhs); }
+overflowing_mul_u32  :: proc(lhs, rhs:  u32) -> (u32, bool)  { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i32")  op :: proc(u32, u32)   -> (u32, bool)  ---; return op(lhs, rhs); }
+overflowing_mul_i32  :: proc(lhs, rhs:  i32) -> (i32, bool)  { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i32")  op :: proc(i32, i32)   -> (i32, bool)  ---; return op(lhs, rhs); }
+overflowing_mul_u64  :: proc(lhs, rhs:  u64) -> (u64, bool)  { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i64")  op :: proc(u64, u64)   -> (u64, bool)  ---; return op(lhs, rhs); }
+overflowing_mul_i64  :: proc(lhs, rhs:  i64) -> (i64, bool)  { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i64")  op :: proc(i64, i64)   -> (i64, bool)  ---; return op(lhs, rhs); }
+overflowing_mul_u128 :: proc(lhs, rhs: u128) -> (u128, bool) { foreign __llvm_core @(link_name="llvm.umul.with.overflow.i128") op :: proc(u128, u128) -> (u128, bool) ---; return op(lhs, rhs); }
+overflowing_mul_i128 :: proc(lhs, rhs: i128) -> (i128, bool) { foreign __llvm_core @(link_name="llvm.smul.with.overflow.i128") op :: proc(i128, i128) -> (i128, bool) ---; return op(lhs, rhs); }
+overflowing_mul_uint :: proc(lhs, rhs: uint) -> (uint, bool) {
 	when size_of(uint) == size_of(u32) {
-		x, ok := overflowing_mul(u32(lhs), u32(rhs));
+		x, ok := overflowing_mul_u32(u32(lhs), u32(rhs));
 		return uint(x), ok;
 	} else {
-		x, ok := overflowing_mul(u64(lhs), u64(rhs));
+		x, ok := overflowing_mul_u64(u64(lhs), u64(rhs));
 		return uint(x), ok;
 	}
 }
-overflowing_mul :: proc(lhs, rhs: int) -> (int, bool) {
+overflowing_mul_int :: proc(lhs, rhs: int) -> (int, bool) {
 	when size_of(int) == size_of(i32) {
-		x, ok := overflowing_mul(i32(lhs), i32(rhs));
+		x, ok := overflowing_mul_i32(i32(lhs), i32(rhs));
 		return int(x), ok;
 	} else {
-		x, ok := overflowing_mul(i64(lhs), i64(rhs));
+		x, ok := overflowing_mul_i64(i64(lhs), i64(rhs));
 		return int(x), ok;
 	}
 }
 
-is_power_of_two :: proc(i:   u8) -> bool { return i > 0 && (i & (i-1)) == 0; }
-is_power_of_two :: proc(i:   i8) -> bool { return i > 0 && (i & (i-1)) == 0; }
-is_power_of_two :: proc(i:  u16) -> bool { return i > 0 && (i & (i-1)) == 0; }
-is_power_of_two :: proc(i:  i16) -> bool { return i > 0 && (i & (i-1)) == 0; }
-is_power_of_two :: proc(i:  u32) -> bool { return i > 0 && (i & (i-1)) == 0; }
-is_power_of_two :: proc(i:  i32) -> bool { return i > 0 && (i & (i-1)) == 0; }
-is_power_of_two :: proc(i:  u64) -> bool { return i > 0 && (i & (i-1)) == 0; }
-is_power_of_two :: proc(i:  i64) -> bool { return i > 0 && (i & (i-1)) == 0; }
-is_power_of_two :: proc(i: u128) -> bool { return i > 0 && (i & (i-1)) == 0; }
-is_power_of_two :: proc(i: i128) -> bool { return i > 0 && (i & (i-1)) == 0; }
-is_power_of_two :: proc(i: uint) -> bool { return i > 0 && (i & (i-1)) == 0; }
-is_power_of_two :: proc(i:  int) -> bool { return i > 0 && (i & (i-1)) == 0; }
+overflowing_mul :: proc[
+	overflowing_mul_u8,   overflowing_mul_i8,
+	overflowing_mul_u16,  overflowing_mul_i16,
+	overflowing_mul_u32,  overflowing_mul_i32,
+	overflowing_mul_u64,  overflowing_mul_i64,
+	overflowing_mul_u128, overflowing_mul_i128,
+	overflowing_mul_uint, overflowing_mul_int,
+];
+
+is_power_of_two_u8   :: proc(i:   u8) -> bool { return i > 0 && (i & (i-1)) == 0; }
+is_power_of_two_i8   :: proc(i:   i8) -> bool { return i > 0 && (i & (i-1)) == 0; }
+is_power_of_two_u16  :: proc(i:  u16) -> bool { return i > 0 && (i & (i-1)) == 0; }
+is_power_of_two_i16  :: proc(i:  i16) -> bool { return i > 0 && (i & (i-1)) == 0; }
+is_power_of_two_u32  :: proc(i:  u32) -> bool { return i > 0 && (i & (i-1)) == 0; }
+is_power_of_two_i32  :: proc(i:  i32) -> bool { return i > 0 && (i & (i-1)) == 0; }
+is_power_of_two_u64  :: proc(i:  u64) -> bool { return i > 0 && (i & (i-1)) == 0; }
+is_power_of_two_i64  :: proc(i:  i64) -> bool { return i > 0 && (i & (i-1)) == 0; }
+is_power_of_two_u128 :: proc(i: u128) -> bool { return i > 0 && (i & (i-1)) == 0; }
+is_power_of_two_i128 :: proc(i: i128) -> bool { return i > 0 && (i & (i-1)) == 0; }
+is_power_of_two_uint :: proc(i: uint) -> bool { return i > 0 && (i & (i-1)) == 0; }
+is_power_of_two_int  :: proc(i:  int) -> bool { return i > 0 && (i & (i-1)) == 0; }
+
+is_power_of_two :: proc[
+	is_power_of_two_u8,   is_power_of_two_i8,
+	is_power_of_two_u16,  is_power_of_two_i16,
+	is_power_of_two_u32,  is_power_of_two_i32,
+	is_power_of_two_u64,  is_power_of_two_i64,
+	is_power_of_two_u128, is_power_of_two_i128,
+	is_power_of_two_uint, is_power_of_two_int,
+]

+ 2 - 2
core/fmt.odin

@@ -534,7 +534,7 @@ _pad :: proc(fi: ^Fmt_Info, s: string) {
 	}
 
 
-	width := fi.width - utf8.rune_count(s);
+	width := fi.width - utf8.rune_count_from_string(s);
 	if fi.minus { // right pad
 		write_string(fi.buf, s);
 		fmt_write_padding(fi, width);
@@ -1126,7 +1126,7 @@ sbprintf :: proc(b: ^String_Buffer, fmt: string, args: ...any) -> string {
 			break;
 		}
 
-		verb, w := utf8.decode_rune(fmt[i..]);
+		verb, w := utf8.decode_rune_from_string(fmt[i..]);
 		i += w;
 
 		if verb == '%' {

+ 144 - 50
core/math.odin

@@ -25,51 +25,49 @@ Mat2 :: [2][2]f32;
 Mat3 :: [3][3]f32;
 Mat4 :: [4][4]f32;
 
-Complex :: complex64;
+Quat :: struct {x, y, z: f32, w: f32 = 1};
 
 @(default_calling_convention="c")
 foreign __llvm_core {
 	@(link_name="llvm.sqrt.f32")
-	sqrt :: proc(x: f32) -> f32 ---;
+	sqrt_f32 :: proc(x: f32) -> f32 ---;
 	@(link_name="llvm.sqrt.f64")
-	sqrt :: proc(x: f64) -> f64 ---;
+	sqrt_f64 :: proc(x: f64) -> f64 ---;
 
 	@(link_name="llvm.sin.f32")
-	sin :: proc(θ: f32) -> f32 ---;
+	sin_f32 :: proc(θ: f32) -> f32 ---;
 	@(link_name="llvm.sin.f64")
-	sin :: proc(θ: f64) -> f64 ---;
+	sin_f64 :: proc(θ: f64) -> f64 ---;
 
 	@(link_name="llvm.cos.f32")
-	cos :: proc(θ: f32) -> f32 ---;
+	cos_f32 :: proc(θ: f32) -> f32 ---;
 	@(link_name="llvm.cos.f64")
-	cos :: proc(θ: f64) -> f64 ---;
+	cos_f64 :: proc(θ: f64) -> f64 ---;
 
 	@(link_name="llvm.pow.f32")
-	pow :: proc(x, power: f32) -> f32 ---;
+	pow_f32 :: proc(x, power: f32) -> f32 ---;
 	@(link_name="llvm.pow.f64")
-	pow :: proc(x, power: f64) -> f64 ---;
+	pow_f64 :: proc(x, power: f64) -> f64 ---;
 
 	@(link_name="llvm.fmuladd.f32")
-	fmuladd :: proc(a, b, c: f32) -> f32 ---;
+	fmuladd_f32 :: proc(a, b, c: f32) -> f32 ---;
 	@(link_name="llvm.fmuladd.f64")
-	fmuladd :: proc(a, b, c: f64) -> f64 ---;
+	fmuladd_f64 :: proc(a, b, c: f64) -> f64 ---;
 }
 
-tan :: proc "c" (θ: f32) -> f32 { return sin(θ)/cos(θ); }
-tan :: proc "c" (θ: f64) -> f64 { return sin(θ)/cos(θ); }
+tan_f32 :: proc "c" (θ: f32) -> f32 { return sin(θ)/cos(θ); }
+tan_f64 :: proc "c" (θ: f64) -> f64 { return sin(θ)/cos(θ); }
 
-lerp   :: proc(a, b: $T, t: $E) -> (x: T) { return a*(1-t) + b*t; }
+lerp :: proc(a, b: $T, t: $E) -> (x: T) { return a*(1-t) + b*t; }
 
-unlerp :: proc(a, b, x: f32) -> (t: f32) { return (x-a)/(b-a); }
-unlerp :: proc(a, b, x: f64) -> (t: f64) { return (x-a)/(b-a); }
+unlerp_f32 :: proc(a, b, x: f32) -> (t: f32) { return (x-a)/(b-a); }
+unlerp_f64 :: proc(a, b, x: f64) -> (t: f64) { return (x-a)/(b-a); }
 
 
-sign :: proc(x: f32) -> f32 { return x >= 0 ? +1 : -1; }
-sign :: proc(x: f64) -> f64 { return x >= 0 ? +1 : -1; }
+sign_f32 :: proc(x: f32) -> f32 { return x >= 0 ? +1 : -1; }
+sign_f64 :: proc(x: f64) -> f64 { return x >= 0 ? +1 : -1; }
 
-
-
-copy_sign :: proc(x, y: f32) -> f32 {
+copy_sign_f32 :: proc(x, y: f32) -> f32 {
 	ix := transmute(u32)x;
 	iy := transmute(u32)y;
 	ix &= 0x7fff_ffff;
@@ -77,7 +75,7 @@ copy_sign :: proc(x, y: f32) -> f32 {
 	return transmute(f32)ix;
 }
 
-copy_sign :: proc(x, y: f64) -> f64 {
+copy_sign_f64 :: proc(x, y: f64) -> f64 {
 	ix := transmute(u64)x;
 	iy := transmute(u64)y;
 	ix &= 0x7fff_ffff_ffff_ff;
@@ -85,19 +83,34 @@ copy_sign :: proc(x, y: f64) -> f64 {
 	return transmute(f64)ix;
 }
 
-round :: proc(x: f32) -> f32 { return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5); }
-round :: proc(x: f64) -> f64 { return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5); }
 
-floor :: proc(x: f32) -> f32 { return x >= 0 ? f32(i64(x)) : f32(i64(x-0.5)); } // TODO: Get accurate versions
-floor :: proc(x: f64) -> f64 { return x >= 0 ? f64(i64(x)) : f64(i64(x-0.5)); } // TODO: Get accurate versions
+sqrt      :: proc[sqrt_f32, sqrt_f64];
+sin       :: proc[sin_f32, sin_f64];
+cos       :: proc[cos_f32, cos_f64];
+tan       :: proc[tan_f32, tan_f64];
+pow       :: proc[pow_f32, pow_f64];
+fmuladd   :: proc[fmuladd_f32, fmuladd_f64];
+sign      :: proc[sign_f32, sign_f64];
+copy_sign :: proc[copy_sign_f32, copy_sign_f64];
+
+
+round_f32 :: proc(x: f32) -> f32 { return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5); }
+round_f64 :: proc(x: f64) -> f64 { return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5); }
+round :: proc[round_f32, round_f64];
+
+floor_f32 :: proc(x: f32) -> f32 { return x >= 0 ? f32(i64(x)) : f32(i64(x-0.5)); } // TODO: Get accurate versions
+floor_f64 :: proc(x: f64) -> f64 { return x >= 0 ? f64(i64(x)) : f64(i64(x-0.5)); } // TODO: Get accurate versions
+floor :: proc[floor_f32, floor_f64];
 
-ceil :: proc(x: f32) -> f32 { return x < 0 ? f32(i64(x)) : f32(i64(x+1)); }// TODO: Get accurate versions
-ceil :: proc(x: f64) -> f64 { return x < 0 ? f64(i64(x)) : f64(i64(x+1)); }// TODO: Get accurate versions
+ceil_f32 :: proc(x: f32) -> f32 { return x < 0 ? f32(i64(x)) : f32(i64(x+1)); }// TODO: Get accurate versions
+ceil_f64 :: proc(x: f64) -> f64 { return x < 0 ? f64(i64(x)) : f64(i64(x+1)); }// TODO: Get accurate versions
+ceil :: proc[ceil_f32, ceil_f64];
 
-remainder :: proc(x, y: f32) -> f32 { return x - round(x/y) * y; }
-remainder :: proc(x, y: f64) -> f64 { return x - round(x/y) * y; }
+remainder_f32 :: proc(x, y: f32) -> f32 { return x - round(x/y) * y; }
+remainder_f64 :: proc(x, y: f64) -> f64 { return x - round(x/y) * y; }
+remainder :: proc[remainder_f32, remainder_f64];
 
-mod :: proc(x, y: f32) -> f32 {
+mod_f32 :: proc(x, y: f32) -> f32 {
 	result: f32;
 	y = abs(y);
 	result = remainder(abs(x), y);
@@ -106,7 +119,7 @@ mod :: proc(x, y: f32) -> f32 {
 	}
 	return copy_sign(result, x);
 }
-mod :: proc(x, y: f64) -> f64 {
+mod_f64 :: proc(x, y: f64) -> f64 {
 	result: f64;
 	y = abs(y);
 	result = remainder(abs(x), y);
@@ -115,6 +128,8 @@ mod :: proc(x, y: f64) -> f64 {
 	}
 	return copy_sign(result, x);
 }
+mod :: proc[mod_f32, mod_f64];
+
 
 
 to_radians :: proc(degrees: f32) -> f32 { return degrees * TAU / 360; }
@@ -122,21 +137,37 @@ to_degrees :: proc(radians: f32) -> f32 { return radians * 360 / TAU; }
 
 
 
+
+mul :: proc[
+	mat4_mul, mat4_mul_vec4,
+	quat_mul, quat_mulf,
+];
+
+div :: proc[
+	quat_div, quat_divf,
+];
+
+inverse :: proc[mat4_inverse, quat_inverse];
+
+
 dot :: proc(a, b: $T/[$N]$E) -> E {
 	res: E;
-	for i in 0..N { res += a[i] * b[i]; }
+	for i in 0..N {
+		res += a[i] * b[i];
+	}
 	return res;
 }
 
-cross :: proc(a, b: $T/[2]$E) -> E {
+cross2 :: proc(a, b: $T/[2]$E) -> E {
 	return a[0]*b[1] - a[1]*b[0];
 }
 
-cross :: proc(a, b: $T/[3]$E) -> T {
+cross3 :: proc(a, b: $T/[3]$E) -> T {
 	i := swizzle(a, 1, 2, 0) * swizzle(b, 2, 0, 1);
 	j := swizzle(a, 2, 0, 1) * swizzle(b, 1, 2, 0);
 	return T(i - j);
 }
+cross :: proc[cross2, cross3];
 
 
 length :: proc(v: $T/[$N]$E) -> E { return sqrt(dot(v, v)); }
@@ -150,13 +181,10 @@ norm0 :: proc(v: $T/[$N]$E) -> T {
 
 
 
-mat4_identity :: proc() -> Mat4 {
-	return Mat4{
-		{1, 0, 0, 0},
-		{0, 1, 0, 0},
-		{0, 0, 1, 0},
-		{0, 0, 0, 1},
-	};
+identity :: proc(T: type/[$N][N]$E) -> T {
+	m: T;
+	for i in 0..N do m[i][i] = E(1);
+	return m;
 }
 
 transpose :: proc(m: Mat4) -> Mat4 {
@@ -168,7 +196,7 @@ transpose :: proc(m: Mat4) -> Mat4 {
 	return m;
 }
 
-mul :: proc(a, b: Mat4) -> Mat4 {
+mat4_mul :: proc(a, b: Mat4) -> Mat4 {
 	c: Mat4;
 	for j in 0..4 {
 		for i in 0..4 {
@@ -181,7 +209,7 @@ mul :: proc(a, b: Mat4) -> Mat4 {
 	return c;
 }
 
-mul :: proc(m: Mat4, v: Vec4) -> Vec4 {
+mat4_mul_vec4 :: proc(m: Mat4, v: Vec4) -> Vec4 {
 	return Vec4{
 		m[0][0]*v[0] + m[1][0]*v[1] + m[2][0]*v[2] + m[3][0]*v[3],
 		m[0][1]*v[0] + m[1][1]*v[1] + m[2][1]*v[2] + m[3][1]*v[3],
@@ -190,7 +218,8 @@ mul :: proc(m: Mat4, v: Vec4) -> Vec4 {
 	};
 }
 
-inverse :: proc(m: Mat4) -> Mat4 {
+
+mat4_inverse :: proc(m: Mat4) -> Mat4 {
 	o: Mat4;
 
 	sf00 := m[2][2] * m[3][3] - m[3][2] * m[2][3];
@@ -261,7 +290,7 @@ inverse :: proc(m: Mat4) -> Mat4 {
 
 
 mat4_translate :: proc(v: Vec3) -> Mat4 {
-	m := mat4_identity();
+	m := identity(Mat4);
 	m[3][0] = v[0];
 	m[3][1] = v[1];
 	m[3][2] = v[2];
@@ -276,7 +305,7 @@ mat4_rotate :: proc(v: Vec3, angle_radians: f32) -> Mat4 {
 	a := norm(v);
 	t := a * (1-c);
 
-	rot := mat4_identity();
+	rot := identity(Mat4);
 
 	rot[0][0] = c + t[0]*a[0];
 	rot[0][1] = 0 + t[0]*a[1] + s*a[2];
@@ -296,20 +325,22 @@ mat4_rotate :: proc(v: Vec3, angle_radians: f32) -> Mat4 {
 	return rot;
 }
 
-scale :: proc(m: Mat4, v: Vec3) -> Mat4 {
+scale_vec3 :: proc(m: Mat4, v: Vec3) -> Mat4 {
 	m[0][0] *= v[0];
 	m[1][1] *= v[1];
 	m[2][2] *= v[2];
 	return m;
 }
 
-scale :: proc(m: Mat4, s: f32) -> Mat4 {
+scale_f32 :: proc(m: Mat4, s: f32) -> Mat4 {
 	m[0][0] *= s;
 	m[1][1] *= s;
 	m[2][2] *= s;
 	return m;
 }
 
+scale :: proc[scale_vec3, scale_f32];
+
 
 look_at :: proc(eye, centre, up: Vec3) -> Mat4 {
 	f := norm(centre - eye);
@@ -338,7 +369,7 @@ perspective :: proc(fovy, aspect, near, far: f32) -> Mat4 {
 
 
 ortho3d :: proc(left, right, bottom, top, near, far: f32) -> Mat4 {
-	m := mat4_identity();
+	m := identity(Mat4);
 	m[0][0] = +2.0 / (right - left);
 	m[1][1] = +2.0 / (top - bottom);
 	m[2][2] = -2.0 / (far - near);
@@ -349,6 +380,69 @@ ortho3d :: proc(left, right, bottom, top, near, far: f32) -> Mat4 {
 }
 
 
+// Quaternion operations
+
+conj :: proc(q: Quat) -> Quat {
+	return Quat{-q.x, -q.y, -q.z, q.w};
+}
+
+quat_mul :: proc(q0, q1: Quat) -> Quat {
+	d: Quat;
+	d.x = q0.w * q1.x + q0.x * q1.w + q0.y * q1.z - q0.z * q1.y;
+	d.y = q0.w * q1.y - q0.x * q1.z + q0.y * q1.w + q0.z * q1.x;
+	d.z = q0.w * q1.z + q0.x * q1.y - q0.y * q1.x + q0.z * q1.w;
+	d.w = q0.w * q1.w - q0.x * q1.x - q0.y * q1.y - q0.z * q1.z;
+	return d;
+}
+
+quat_mulf :: proc(q: Quat, f: f32) -> Quat { return Quat{q.x*f, q.y*f, q.z*f, q.w*f}; }
+quat_divf :: proc(q: Quat, f: f32) -> Quat { return Quat{q.x/f, q.y/f, q.z/f, q.w/f}; }
+
+quat_div     :: proc(q0, q1: Quat) -> Quat { return mul(q0, quat_inverse(q1)); }
+quat_inverse :: proc(q: Quat) -> Quat { return div(conj(q), quat_dot(q, q)); }
+quat_dot     :: proc(q0, q1: Quat) -> f32 { return q0.x*q1.x + q0.y*q1.y + q0.z*q1.z + q0.w*q1.w; }
+
+quat_norm :: proc(q: Quat) -> Quat {
+	m := sqrt(quat_dot(q, q));
+	return div(q, m);
+}
+
+axis_angle :: proc(axis: Vec3, angle_radians: f32) -> Quat {
+	v := norm(axis) * sin(0.5*angle_radians);
+	w := cos(0.5*angle_radians);
+	return Quat{v.x, v.y, v.z, w};
+}
+
+euler_angles :: proc(pitch, yaw, roll: f32) -> Quat {
+	p := axis_angle(Vec3{1, 0, 0}, pitch);
+	y := axis_angle(Vec3{0, 1, 0}, pitch);
+	r := axis_angle(Vec3{0, 0, 1}, pitch);
+	return mul(mul(y, p), r);
+}
+
+quat_to_mat4 :: proc(q: Quat) -> Mat4 {
+	a := quat_norm(q);
+	xx := a.x*a.x; yy := a.y*a.y; zz := a.z*a.z;
+	xy := a.x*a.y; xz := a.x*a.z; yz := a.y*a.z;
+	wx := a.w*a.x; wy := a.w*a.y; wz := a.w*a.z;
+
+	m := identity(Mat4);
+
+	m[0][0] = 1 - 2*(yy + zz);
+	m[0][1] =     2*(xy + wz);
+	m[0][2] =     2*(xz - wy);
+
+	m[1][0] =     2*(xy - wz);
+	m[1][1] = 1 - 2*(xx + zz);
+	m[1][2] =     2*(yz + wx);
+
+	m[2][0] =     2*(xz + wy);
+	m[2][1] =     2*(yz - wx);
+	m[2][2] = 1 - 2*(xx + yy);
+	return m;
+}
+
+
 
 
 F32_DIG        :: 6;

+ 5 - 3
core/mem.odin

@@ -1,10 +1,12 @@
 import "core:raw.odin"
 
 foreign __llvm_core {
-	@(link_name = "llvm.bswap.i16") swap :: proc(b: u16) -> u16 ---;
-	@(link_name = "llvm.bswap.i32") swap :: proc(b: u32) -> u32 ---;
-	@(link_name = "llvm.bswap.i64") swap :: proc(b: u64) -> u64 ---;
+	@(link_name = "llvm.bswap.i16") swap16 :: proc(b: u16) -> u16 ---;
+	@(link_name = "llvm.bswap.i32") swap32 :: proc(b: u32) -> u32 ---;
+	@(link_name = "llvm.bswap.i64") swap64 :: proc(b: u64) -> u64 ---;
 }
+swap :: proc[swap16, swap32, swap64];
+
 
 set :: proc "contextless" (data: rawptr, value: i32, len: int) -> rawptr {
 	return __mem_set(data, value, len);

+ 3 - 3
core/opengl.odin

@@ -44,13 +44,13 @@ _string_data :: inline proc(s: string) -> ^u8 do return &s[0];
 
 _libgl := win32.load_library_a(_string_data("opengl32.dll\x00"));
 
-get_proc_address :: proc(name: string) -> rawptr {
+get_gl_proc_address :: proc(name: string) -> rawptr {
 	if name[len(name)-1] == 0 {
 		name = name[..len(name)-1];
 	}
 	// NOTE(bill): null terminated
 	assert((&name[0] + len(name))^ == 0);
-	res := wgl.get_proc_address(&name[0]);
+	res := wgl.get_gl_proc_address(&name[0]);
 	if res == nil {
 		res = win32.get_proc_address(_libgl, &name[0]);
 	}
@@ -122,7 +122,7 @@ get_proc_address :: proc(name: string) -> rawptr {
 init :: proc() {
 	set_proc_address :: proc(p: rawptr, name: string) {
 		x := cast(^rawptr)p;
-		x^ = get_proc_address(name);
+		x^ = get_gl_proc_address(name);
 	}
 
 	set_proc_address(&GenBuffers,              "glGenBuffers\x00");

+ 2 - 2
core/os.odin

@@ -53,10 +53,10 @@ write_entire_file :: proc(name: string, data: []byte, truncate := true) -> (succ
 	return write_err != 0;
 }
 
-write :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
+write_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
 	return write(fd, mem.slice_ptr(cast(^byte)data, len));
 }
 
-read :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
+read_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
 	return read(fd, mem.slice_ptr(cast(^byte)data, len));
 }

+ 3 - 3
core/sort.odin

@@ -1,4 +1,4 @@
-bubble_sort :: proc(array: $A/[]$T, f: proc(T, T) -> int) {
+bubble_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) {
 	assert(f != nil);
 	count := len(array);
 
@@ -45,7 +45,7 @@ bubble_sort :: proc(array: $A/[]$T) {
 	}
 }
 
-quick_sort :: proc(array: $A/[]$T, f: proc(T, T) -> int) {
+quick_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) {
 	assert(f != nil);
 	a := array;
 	n := len(a);
@@ -98,7 +98,7 @@ _log2 :: proc(n: int) -> int {
 	return res;
 }
 
-merge_sort :: proc(array: $A/[]$T, f: proc(T, T) -> int) {
+merge_sort_proc :: proc(array: $A/[]$T, f: proc(T, T) -> int) {
 	merge_slices :: proc(arr1, arr2, out: A, f: proc(T, T) -> int) {
 		N1, N2 := len(arr1), len(arr2);
 		i, j := 0, 0;

+ 1 - 1
core/sys/wgl.odin

@@ -72,7 +72,7 @@ foreign opengl32 {
 	make_current :: proc(hdc: Hdc, hglrc: Hglrc) -> Bool ---;
 
 	@(link_name="wglGetProcAddress")
-	get_proc_address :: proc(c_str: ^byte) -> rawptr ---;
+	get_gl_proc_address :: proc(c_str: ^byte) -> rawptr ---;
 
 	@(link_name="wglDeleteContext")
 	delete_context :: proc(hglrc: Hglrc) -> Bool ---;

+ 5 - 5
core/sys/windows.odin

@@ -530,7 +530,7 @@ foreign kernel32 {
 	@(link_name="CreateEventA") create_event_a :: proc(event_attributes: ^Security_Attributes, manual_reset, initial_state: Bool, name: ^byte) -> Handle ---;
 
 	@(link_name="LoadLibraryA")   load_library_a   :: proc(c_str: ^byte)  -> Hmodule ---;
-	@(link_name="LoadLibraryW")   load_library_a   :: proc(c_str: ^u16) -> Hmodule ---;
+	@(link_name="LoadLibraryW")   load_library_w   :: proc(c_str: ^u16) -> Hmodule ---;
 	@(link_name="FreeLibrary")    free_library     :: proc(h: Hmodule) ---;
 	@(link_name="GetProcAddress") get_proc_address :: proc(h: Hmodule, c_str: ^byte) -> rawptr ---;
 
@@ -663,10 +663,10 @@ get_query_performance_frequency :: proc() -> i64 {
 	return r;
 }
 
-HIWORD :: proc(wParam: Wparam) -> u16 { return u16((u32(wParam) >> 16) & 0xffff); }
-HIWORD :: proc(lParam: Lparam) -> u16 { return u16((u32(lParam) >> 16) & 0xffff); }
-LOWORD :: proc(wParam: Wparam) -> u16 { return u16(wParam); }
-LOWORD :: proc(lParam: Lparam) -> u16 { return u16(lParam); }
+HIWORD_W :: proc(wParam: Wparam) -> u16 { return u16((u32(wParam) >> 16) & 0xffff); }
+HIWORD_L :: proc(lParam: Lparam) -> u16 { return u16((u32(lParam) >> 16) & 0xffff); }
+LOWORD_W :: proc(wParam: Wparam) -> u16 { return u16(wParam); }
+LOWORD_L :: proc(lParam: Lparam) -> u16 { return u16(lParam); }
 
 is_key_down :: inline proc(key: Key_Code) -> bool { return get_async_key_state(i32(key)) < 0; }
 

+ 2 - 2
core/utf16.odin

@@ -57,8 +57,8 @@ encode :: proc(d: []u16, s: []rune) -> int {
 }
 
 
-encode :: proc(d: []u16, s: string) -> int {
-	n := utf8.rune_count(s);
+encode_string :: proc(d: []u16, s: string) -> int {
+	n := utf8.rune_count_from_string(s);
 	for r in s do if r >= _surr_self do n += 1;
 
 	max_n := min(len(d), n);

+ 3 - 3
core/utf8.odin

@@ -92,7 +92,7 @@ encode_rune :: proc(r: rune) -> ([4]u8, int) {
 	return buf, 4;
 }
 
-decode_rune :: inline proc(s: string) -> (rune, int) do return decode_rune(cast([]u8)s);
+decode_rune_from_string :: inline proc(s: string) -> (rune, int) do return decode_rune(cast([]u8)s);
 decode_rune :: proc(s: []u8) -> (rune, int) {
 	n := len(s);
 	if n < 1 {
@@ -132,7 +132,7 @@ decode_rune :: proc(s: []u8) -> (rune, int) {
 
 
 
-decode_last_rune :: inline proc(s: string) -> (rune, int) do return decode_last_rune(cast([]u8)s);
+decode_last_rune_from_string :: inline proc(s: string) -> (rune, int) do return decode_last_rune(cast([]u8)s);
 decode_last_rune :: proc(s: []u8) -> (rune, int) {
 	r: rune;
 	size: int;
@@ -213,7 +213,7 @@ valid_string :: proc(s: string) -> bool {
 
 rune_start :: inline proc(b: u8) -> bool do return b&0xc0 != 0x80;
 
-rune_count :: inline proc(s: string) -> int do return rune_count(cast([]u8)s);
+rune_count_from_string :: inline proc(s: string) -> int do return rune_count(cast([]u8)s);
 rune_count :: proc(s: []u8) -> int {
 	count := 0;
 	n := len(s);

+ 3 - 2
src/check_expr.cpp

@@ -4459,8 +4459,9 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
 	}
 
 	if (operand->mode == Addressing_Overload) {
-		GB_ASSERT(operand->overload_entities != nullptr &&
-		          operand->overload_count > 0);
+		// GB_ASSERT_MSG(operand->overload_entities != nullptr &&
+		//               operand->overload_count > 0,
+		//               "%p %td", operand->overload_entities, operand->overload_count);
 		isize               overload_count = operand->overload_count;
 		Entity **           procs          = operand->overload_entities;
 		ValidIndexAndScore *valids         = gb_alloc_array(heap_allocator(), ValidIndexAndScore, overload_count);

+ 1 - 1
src/checker.cpp

@@ -780,7 +780,7 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) {
 	HashKey key = hash_string(name);
 	Entity **found = map_get(&s->elements, key);
 
-#if 1
+#ifndef DISABLE_PROCEDURE_OVERLOADING
 	// IMPORTANT NOTE(bill): Procedure overloading code
 	Entity *prev = nullptr;
 	if (found) {

+ 2 - 1
src/main.cpp

@@ -1,7 +1,8 @@
 #define ALLOW_ARRAY_PROGRAMMING
-
+// #define DISABLE_PROCEDURE_OVERLOADING
 // #define NO_ARRAY_BOUNDS_CHECK
 
+
 #include "common.cpp"
 #include "timings.cpp"
 #include "build_settings.cpp"