diff --git a/core/_preload.odin b/core/_preload.odin index 42b02e0ef..deb492161 100644 --- a/core/_preload.odin +++ b/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) { diff --git a/core/atomics.odin b/core/atomics.odin index 5118e6447..b1dccbb89 100644 --- a/core/atomics.odin +++ b/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; } diff --git a/core/bits.odin b/core/bits.odin index d973de86e..869e380e4 100644 --- a/core/bits.odin +++ b/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.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_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.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_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.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_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.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_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.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 :: 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_uint :: proc(i: uint) -> uint { when size_of(uint) == size_of(u32) { - x, ok := overflowing_add(u32(lhs), u32(rhs)); - return uint(x), ok; + return uint(byte_swap32(u32(i))); } else { - x, ok := overflowing_add(u64(lhs), u64(rhs)); - return uint(x), ok; - } -} -overflowing_add :: proc(lhs, rhs: int) -> (int, bool) { - when size_of(int) == size_of(i32) { - x, ok := overflowing_add(i32(lhs), i32(rhs)); - return int(x), ok; - } else { - x, ok := overflowing_add(i64(lhs), i64(rhs)); - return int(x), ok; + return uint(byte_swap64(u64(i))); } } -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) { +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_sub(u32(lhs), u32(rhs)); + x, ok := overflowing_add_u32(u32(lhs), u32(rhs)); return uint(x), ok; } else { - x, ok := overflowing_sub(u64(lhs), u64(rhs)); + x, ok := overflowing_add_u64(u64(lhs), u64(rhs)); return uint(x), ok; } } -overflowing_sub :: 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_sub(i32(lhs), i32(rhs)); + x, ok := overflowing_add_i32(i32(lhs), i32(rhs)); return int(x), ok; } else { - x, ok := overflowing_sub(i64(lhs), i64(rhs)); + x, ok := overflowing_add_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_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_mul(u32(lhs), u32(rhs)); + x, ok := overflowing_sub_u32(u32(lhs), u32(rhs)); return uint(x), ok; } else { - x, ok := overflowing_mul(u64(lhs), u64(rhs)); + x, ok := overflowing_sub_u64(u64(lhs), u64(rhs)); return uint(x), ok; } } -overflowing_mul :: 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_mul(i32(lhs), i32(rhs)); + x, ok := overflowing_sub_i32(i32(lhs), i32(rhs)); return int(x), ok; } else { - x, ok := overflowing_mul(i64(lhs), i64(rhs)); + x, ok := overflowing_sub_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_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(u32(lhs), u32(rhs)); + return uint(x), ok; + } else { + x, ok := overflowing_mul_u64(u64(lhs), u64(rhs)); + return uint(x), ok; + } +} +overflowing_mul_int :: proc(lhs, rhs: int) -> (int, bool) { + when size_of(int) == size_of(i32) { + x, ok := overflowing_mul_i32(i32(lhs), i32(rhs)); + return int(x), ok; + } else { + x, ok := overflowing_mul_i64(i64(lhs), i64(rhs)); + return int(x), ok; + } +} + +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, +] diff --git a/core/fmt.odin b/core/fmt.odin index 690365327..c1191f500 100644 --- a/core/fmt.odin +++ b/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 == '%' { diff --git a/core/math.odin b/core/math.odin index 4aa5423b0..54f44c1d0 100644 --- a/core/math.odin +++ b/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]; -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 -remainder :: proc(x, y: f32) -> f32 { return x - round(x/y) * y; } -remainder :: proc(x, y: f64) -> f64 { return x - round(x/y) * y; } +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]; -mod :: proc(x, y: f32) -> f32 { +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_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_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_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; diff --git a/core/mem.odin b/core/mem.odin index 9d0adb05c..34666a80a 100644 --- a/core/mem.odin +++ b/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); diff --git a/core/opengl.odin b/core/opengl.odin index 0103e36ad..6869c64ff 100644 --- a/core/opengl.odin +++ b/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"); diff --git a/core/os.odin b/core/os.odin index 9b441c64a..50f1081a0 100644 --- a/core/os.odin +++ b/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)); } diff --git a/core/sort.odin b/core/sort.odin index d58d0cf99..e5f690066 100644 --- a/core/sort.odin +++ b/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; diff --git a/core/sys/wgl.odin b/core/sys/wgl.odin index 66ff838bc..8f3b69324 100644 --- a/core/sys/wgl.odin +++ b/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 ---; diff --git a/core/sys/windows.odin b/core/sys/windows.odin index b3bec0939..8fdf66734 100644 --- a/core/sys/windows.odin +++ b/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; } diff --git a/core/utf16.odin b/core/utf16.odin index 2268fd049..a375f416c 100644 --- a/core/utf16.odin +++ b/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); diff --git a/core/utf8.odin b/core/utf8.odin index 1863d6c9d..d108fec91 100644 --- a/core/utf8.odin +++ b/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); diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 21a4f7cfe..1c4c33747 100644 --- a/src/check_expr.cpp +++ b/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); diff --git a/src/checker.cpp b/src/checker.cpp index 78afab4ad..7c9f20135 100644 --- a/src/checker.cpp +++ b/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) { diff --git a/src/main.cpp b/src/main.cpp index d3124528c..7f24a7d4d 100644 --- a/src/main.cpp +++ b/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"