Make core library use procedure groupings rather than normal overloading

This commit is contained in:
gingerBill
2017-12-04 22:01:51 +00:00
parent ebb2a9812c
commit f0de994059
16 changed files with 423 additions and 375 deletions
+5 -3
View File
@@ -376,7 +376,7 @@ clear_map :: inline proc "contextless" (m: ^$T/map[$K]$V) {
clear :: proc[clear_dynamic_array, clear_map]; 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; if array == nil do return false;
a := cast(^raw.Dynamic_Array)array; a := cast(^raw.Dynamic_Array)array;
@@ -453,7 +453,7 @@ __get_map_key :: proc "contextless" (key: $K) -> __Map_Key {
return 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); 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)); 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 { 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) { __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) { __bounds_check_error_loc :: inline proc "contextless" (using loc := #caller_location, index, count: int) {
+28 -28
View File
@@ -13,90 +13,90 @@ sfence :: proc() { win32.write_barrier(); }
lfence :: proc() { win32.read_barrier(); } lfence :: proc() { win32.read_barrier(); }
load :: proc(a: ^i32) -> i32 { load_i32 :: proc(a: ^i32) -> i32 {
return a^; return a^;
} }
store :: proc(a: ^i32, value: i32) { store_i32 :: proc(a: ^i32, value: i32) {
a^ = value; 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); 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); 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); 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); 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); return win32.interlocked_or(a, operand);
} }
spin_lock :: proc(a: ^i32, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default spin_lock_i32 :: proc(a: ^i32, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
old_value := compare_exchange(a, 1, 0); old_value := compare_exchange_i32(a, 1, 0);
counter := 0; counter := 0;
for old_value != 0 && (time_out < 0 || counter < time_out) { for old_value != 0 && (time_out < 0 || counter < time_out) {
counter += 1; counter += 1;
yield_thread(); yield_thread();
old_value = compare_exchange(a, 1, 0); old_value = compare_exchange_i32(a, 1, 0);
mfence(); mfence();
} }
return old_value == 0; return old_value == 0;
} }
spin_unlock :: proc(a: ^i32) { spin_unlock_i32 :: proc(a: ^i32) {
store(a, 0); store_i32(a, 0);
mfence(); mfence();
} }
try_acquire_lock :: proc(a: ^i32) -> bool { try_acquire_lock_i32 :: proc(a: ^i32) -> bool {
yield_thread(); yield_thread();
old_value := compare_exchange(a, 1, 0); old_value := compare_exchange_i32(a, 1, 0);
mfence(); mfence();
return old_value == 0; return old_value == 0;
} }
load :: proc(a: ^i64) -> i64 { load_i64 :: proc(a: ^i64) -> i64 {
return a^; return a^;
} }
store :: proc(a: ^i64, value: i64) { store_i64 :: proc(a: ^i64, value: i64) {
a^ = value; 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); 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); 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); 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); 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); return win32.interlocked_or64(a, operand);
} }
spin_lock :: proc(a: ^i64, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default spin_lock_i64 :: proc(a: ^i64, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
old_value := compare_exchange(a, 1, 0); old_value := compare_exchange_i64(a, 1, 0);
counter := 0; counter := 0;
for old_value != 0 && (time_out < 0 || counter < time_out) { for old_value != 0 && (time_out < 0 || counter < time_out) {
counter += 1; counter += 1;
yield_thread(); yield_thread();
old_value = compare_exchange(a, 1, 0); old_value = compare_exchange_i64(a, 1, 0);
mfence(); mfence();
} }
return old_value == 0; return old_value == 0;
} }
spin_unlock :: proc(a: ^i64) { spin_unlock_i64 :: proc(a: ^i64) {
store(a, 0); store_i64(a, 0);
mfence(); mfence();
} }
try_acquire_lock :: proc(a: ^i64) -> bool { try_acquire_lock_i64 :: proc(a: ^i64) -> bool {
yield_thread(); yield_thread();
old_value := compare_exchange(a, 1, 0); old_value := compare_exchange_i64(a, 1, 0);
mfence(); mfence();
return old_value == 0; return old_value == 0;
} }
+214 -266
View File
@@ -23,306 +23,254 @@ I64_MAX :: -I64_MIN - 1;
I128_MAX :: -I128_MIN - 1; I128_MAX :: -I128_MIN - 1;
foreign __llvm_core { foreign __llvm_core {
@(link_name="llvm.ctpop.i8") __llvm_ctpop :: proc(u8) -> u8 ---; @(link_name="llvm.ctpop.i8") __llvm_ctpop8 :: proc(u8) -> u8 ---;
@(link_name="llvm.ctpop.i8") __llvm_ctpop :: proc(i8) -> i8 ---; @(link_name="llvm.ctpop.i16") __llvm_ctpop16 :: proc(u16) -> u16 ---;
@(link_name="llvm.ctpop.i16") __llvm_ctpop :: proc(u16) -> u16 ---; @(link_name="llvm.ctpop.i32") __llvm_ctpop32 :: proc(u32) -> u32 ---;
@(link_name="llvm.ctpop.i16") __llvm_ctpop :: proc(i16) -> i16 ---; @(link_name="llvm.ctpop.i64") __llvm_ctpop64 :: proc(u64) -> u64 ---;
@(link_name="llvm.ctpop.i32") __llvm_ctpop :: proc(u32) -> u32 ---; @(link_name="llvm.ctpop.i128") __llvm_ctpop128 :: proc(u128) -> u128 ---;
@(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_ctlz8 :: proc(u8, bool) -> u8 ---;
@(link_name="llvm.ctlz.i8") __llvm_ctlz :: proc(i8, bool) -> i8 ---; @(link_name="llvm.ctlz.i16") __llvm_ctlz16 :: proc(u16, bool) -> u16 ---;
@(link_name="llvm.ctlz.i16") __llvm_ctlz :: proc(u16, bool) -> u16 ---; @(link_name="llvm.ctlz.i32") __llvm_ctlz32 :: proc(u32, bool) -> u32 ---;
@(link_name="llvm.ctlz.i16") __llvm_ctlz :: proc(i16, bool) -> i16 ---; @(link_name="llvm.ctlz.i64") __llvm_ctlz64 :: proc(u64, bool) -> u64 ---;
@(link_name="llvm.ctlz.i32") __llvm_ctlz :: proc(u32, bool) -> u32 ---; @(link_name="llvm.ctlz.i128") __llvm_ctlz128 :: proc(u128, bool) -> u128 ---;
@(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_cttz8 :: proc(u8, bool) -> u8 ---;
@(link_name="llvm.cttz.i8") __llvm_cttz :: proc(i8, bool) -> i8 ---; @(link_name="llvm.cttz.i16") __llvm_cttz16 :: proc(u16, bool) -> u16 ---;
@(link_name="llvm.cttz.i16") __llvm_cttz :: proc(u16, bool) -> u16 ---; @(link_name="llvm.cttz.i32") __llvm_cttz32 :: proc(u32, bool) -> u32 ---;
@(link_name="llvm.cttz.i16") __llvm_cttz :: proc(i16, bool) -> i16 ---; @(link_name="llvm.cttz.i64") __llvm_cttz64 :: proc(u64, bool) -> u64 ---;
@(link_name="llvm.cttz.i32") __llvm_cttz :: proc(u32, bool) -> u32 ---; @(link_name="llvm.cttz.i128") __llvm_cttz128 :: proc(u128, bool) -> u128 ---;
@(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_bitreverse8 :: proc(u8) -> u8 ---;
@(link_name="llvm.bitreverse.i8") __llvm_bitreverse :: proc(i8) -> i8 ---; @(link_name="llvm.bitreverse.i16") __llvm_bitreverse16 :: proc(u16) -> u16 ---;
@(link_name="llvm.bitreverse.i16") __llvm_bitreverse :: proc(u16) -> u16 ---; @(link_name="llvm.bitreverse.i32") __llvm_bitreverse32 :: proc(u32) -> u32 ---;
@(link_name="llvm.bitreverse.i16") __llvm_bitreverse :: proc(i16) -> i16 ---; @(link_name="llvm.bitreverse.i64") __llvm_bitreverse64 :: proc(u64) -> u64 ---;
@(link_name="llvm.bitreverse.i32") __llvm_bitreverse :: proc(u32) -> u32 ---; @(link_name="llvm.bitreverse.i128") __llvm_bitreverse128 :: proc(u128) -> u128 ---;
@(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_swap16 :: proc(u16) -> u16 ---;
@(link_name="llvm.bswap.i16") byte_swap :: proc(i16) -> i16 ---; @(link_name="llvm.bswap.i32") byte_swap32 :: proc(u32) -> u32 ---;
@(link_name="llvm.bswap.i32") byte_swap :: proc(u32) -> u32 ---; @(link_name="llvm.bswap.i64") byte_swap64 :: proc(u64) -> u64 ---;
@(link_name="llvm.bswap.i32") byte_swap :: proc(i32) -> i32 ---; @(link_name="llvm.bswap.i128") byte_swap128 :: proc(u128) -> u128 ---;
@(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 ---;
} }
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); } byte_swap_uint :: proc(i: uint) -> uint {
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) {
when size_of(uint) == size_of(u32) { when size_of(uint) == size_of(u32) {
x, ok := overflowing_add(u32(lhs), u32(rhs)); return uint(byte_swap32(u32(i)));
return uint(x), ok;
} else { } else {
x, ok := overflowing_add(u64(lhs), u64(rhs)); return uint(byte_swap64(u64(i)));
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;
} }
} }
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); } byte_swap :: proc[byte_swap16, byte_swap32, byte_swap64, byte_swap128, byte_swap_uint];
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); } count_ones8 :: proc(i: u8) -> u8 { return __llvm_ctpop8(i); }
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); } count_ones16 :: proc(i: u16) -> u16 { return __llvm_ctpop16(i); }
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); } count_ones32 :: proc(i: u32) -> u32 { return __llvm_ctpop32(i); }
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); } count_ones64 :: proc(i: u64) -> u64 { return __llvm_ctpop64(i); }
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); } count_ones128 :: proc(i: u128) -> u128 { return __llvm_ctpop128(i); }
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); } count_zeros8 :: proc(i: u8) -> u8 { return 8 - count_ones8(i); }
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); } count_zeros16 :: proc(i: u16) -> u16 { return 16 - count_ones16(i); }
overflowing_sub :: proc(lhs, rhs: uint) -> (uint, bool) { 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) { 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; return uint(x), ok;
} else { } else {
x, ok := overflowing_sub(u64(lhs), u64(rhs)); x, ok := overflowing_add_u64(u64(lhs), u64(rhs));
return uint(x), ok; 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) { 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; return int(x), ok;
} else { } else {
x, ok := overflowing_sub(i64(lhs), i64(rhs)); x, ok := overflowing_add_i64(i64(lhs), i64(rhs));
return int(x), ok; 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_add :: proc[
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_add_u8, overflowing_add_i8,
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_add_u16, overflowing_add_i16,
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_add_u32, overflowing_add_i32,
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_add_u64, overflowing_add_i64,
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_add_u128, overflowing_add_i128,
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_add_uint, overflowing_add_int,
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_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_mul :: proc(lhs, rhs: uint) -> (uint, bool) { 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) { 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; return uint(x), ok;
} else { } else {
x, ok := overflowing_mul(u64(lhs), u64(rhs)); x, ok := overflowing_sub_u64(u64(lhs), u64(rhs));
return uint(x), ok; 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) { 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; return int(x), ok;
} else { } else {
x, ok := overflowing_mul(i64(lhs), i64(rhs)); x, ok := overflowing_sub_i64(i64(lhs), i64(rhs));
return int(x), ok; return int(x), ok;
} }
} }
is_power_of_two :: proc(i: u8) -> bool { return i > 0 && (i & (i-1)) == 0; } overflowing_sub :: proc[
is_power_of_two :: proc(i: i8) -> bool { return i > 0 && (i & (i-1)) == 0; } overflowing_sub_u8, overflowing_sub_i8,
is_power_of_two :: proc(i: u16) -> bool { return i > 0 && (i & (i-1)) == 0; } overflowing_sub_u16, overflowing_sub_i16,
is_power_of_two :: proc(i: i16) -> bool { return i > 0 && (i & (i-1)) == 0; } overflowing_sub_u32, overflowing_sub_i32,
is_power_of_two :: proc(i: u32) -> bool { return i > 0 && (i & (i-1)) == 0; } overflowing_sub_u64, overflowing_sub_i64,
is_power_of_two :: proc(i: i32) -> bool { return i > 0 && (i & (i-1)) == 0; } overflowing_sub_u128, overflowing_sub_i128,
is_power_of_two :: proc(i: u64) -> bool { return i > 0 && (i & (i-1)) == 0; } overflowing_sub_uint, overflowing_sub_int,
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; } 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); }
is_power_of_two :: proc(i: int) -> bool { return i > 0 && (i & (i-1)) == 0; } 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,
]
+2 -2
View File
@@ -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 if fi.minus { // right pad
write_string(fi.buf, s); write_string(fi.buf, s);
fmt_write_padding(fi, width); fmt_write_padding(fi, width);
@@ -1126,7 +1126,7 @@ sbprintf :: proc(b: ^String_Buffer, fmt: string, args: ...any) -> string {
break; break;
} }
verb, w := utf8.decode_rune(fmt[i..]); verb, w := utf8.decode_rune_from_string(fmt[i..]);
i += w; i += w;
if verb == '%' { if verb == '%' {
+144 -50
View File
@@ -25,51 +25,49 @@ Mat2 :: [2][2]f32;
Mat3 :: [3][3]f32; Mat3 :: [3][3]f32;
Mat4 :: [4][4]f32; Mat4 :: [4][4]f32;
Complex :: complex64; Quat :: struct {x, y, z: f32, w: f32 = 1};
@(default_calling_convention="c") @(default_calling_convention="c")
foreign __llvm_core { foreign __llvm_core {
@(link_name="llvm.sqrt.f32") @(link_name="llvm.sqrt.f32")
sqrt :: proc(x: f32) -> f32 ---; sqrt_f32 :: proc(x: f32) -> f32 ---;
@(link_name="llvm.sqrt.f64") @(link_name="llvm.sqrt.f64")
sqrt :: proc(x: f64) -> f64 ---; sqrt_f64 :: proc(x: f64) -> f64 ---;
@(link_name="llvm.sin.f32") @(link_name="llvm.sin.f32")
sin :: proc(θ: f32) -> f32 ---; sin_f32 :: proc(θ: f32) -> f32 ---;
@(link_name="llvm.sin.f64") @(link_name="llvm.sin.f64")
sin :: proc(θ: f64) -> f64 ---; sin_f64 :: proc(θ: f64) -> f64 ---;
@(link_name="llvm.cos.f32") @(link_name="llvm.cos.f32")
cos :: proc(θ: f32) -> f32 ---; cos_f32 :: proc(θ: f32) -> f32 ---;
@(link_name="llvm.cos.f64") @(link_name="llvm.cos.f64")
cos :: proc(θ: f64) -> f64 ---; cos_f64 :: proc(θ: f64) -> f64 ---;
@(link_name="llvm.pow.f32") @(link_name="llvm.pow.f32")
pow :: proc(x, power: f32) -> f32 ---; pow_f32 :: proc(x, power: f32) -> f32 ---;
@(link_name="llvm.pow.f64") @(link_name="llvm.pow.f64")
pow :: proc(x, power: f64) -> f64 ---; pow_f64 :: proc(x, power: f64) -> f64 ---;
@(link_name="llvm.fmuladd.f32") @(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") @(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_f32 :: proc "c" (θ: f32) -> f32 { return sin(θ)/cos(θ); }
tan :: proc "c" (θ: f64) -> f64 { 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_f32 :: 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_f64 :: proc(a, b, x: f64) -> (t: f64) { return (x-a)/(b-a); }
sign :: proc(x: f32) -> f32 { return x >= 0 ? +1 : -1; } sign_f32 :: proc(x: f32) -> f32 { return x >= 0 ? +1 : -1; }
sign :: proc(x: f64) -> f64 { return x >= 0 ? +1 : -1; } sign_f64 :: proc(x: f64) -> f64 { return x >= 0 ? +1 : -1; }
copy_sign_f32 :: proc(x, y: f32) -> f32 {
copy_sign :: proc(x, y: f32) -> f32 {
ix := transmute(u32)x; ix := transmute(u32)x;
iy := transmute(u32)y; iy := transmute(u32)y;
ix &= 0x7fff_ffff; ix &= 0x7fff_ffff;
@@ -77,7 +75,7 @@ copy_sign :: proc(x, y: f32) -> f32 {
return transmute(f32)ix; return transmute(f32)ix;
} }
copy_sign :: proc(x, y: f64) -> f64 { copy_sign_f64 :: proc(x, y: f64) -> f64 {
ix := transmute(u64)x; ix := transmute(u64)x;
iy := transmute(u64)y; iy := transmute(u64)y;
ix &= 0x7fff_ffff_ffff_ff; ix &= 0x7fff_ffff_ffff_ff;
@@ -85,19 +83,34 @@ copy_sign :: proc(x, y: f64) -> f64 {
return transmute(f64)ix; 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 sqrt :: proc[sqrt_f32, sqrt_f64];
floor :: proc(x: f64) -> f64 { return x >= 0 ? f64(i64(x)) : f64(i64(x-0.5)); } // TODO: Get accurate versions 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; } round_f32 :: proc(x: f32) -> f32 { return x >= 0 ? floor(x + 0.5) : ceil(x - 0.5); }
remainder :: proc(x, y: f64) -> f64 { return x - round(x/y) * y; } 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; result: f32;
y = abs(y); y = abs(y);
result = remainder(abs(x), y); result = remainder(abs(x), y);
@@ -106,7 +119,7 @@ mod :: proc(x, y: f32) -> f32 {
} }
return copy_sign(result, x); return copy_sign(result, x);
} }
mod :: proc(x, y: f64) -> f64 { mod_f64 :: proc(x, y: f64) -> f64 {
result: f64; result: f64;
y = abs(y); y = abs(y);
result = remainder(abs(x), y); result = remainder(abs(x), y);
@@ -115,6 +128,8 @@ mod :: proc(x, y: f64) -> f64 {
} }
return copy_sign(result, x); return copy_sign(result, x);
} }
mod :: proc[mod_f32, mod_f64];
to_radians :: proc(degrees: f32) -> f32 { return degrees * TAU / 360; } 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 { dot :: proc(a, b: $T/[$N]$E) -> E {
res: 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; 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]; 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); i := swizzle(a, 1, 2, 0) * swizzle(b, 2, 0, 1);
j := swizzle(a, 2, 0, 1) * swizzle(b, 1, 2, 0); j := swizzle(a, 2, 0, 1) * swizzle(b, 1, 2, 0);
return T(i - j); return T(i - j);
} }
cross :: proc[cross2, cross3];
length :: proc(v: $T/[$N]$E) -> E { return sqrt(dot(v, v)); } 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 { identity :: proc(T: type/[$N][N]$E) -> T {
return Mat4{ m: T;
{1, 0, 0, 0}, for i in 0..N do m[i][i] = E(1);
{0, 1, 0, 0}, return m;
{0, 0, 1, 0},
{0, 0, 0, 1},
};
} }
transpose :: proc(m: Mat4) -> Mat4 { transpose :: proc(m: Mat4) -> Mat4 {
@@ -168,7 +196,7 @@ transpose :: proc(m: Mat4) -> Mat4 {
return m; return m;
} }
mul :: proc(a, b: Mat4) -> Mat4 { mat4_mul :: proc(a, b: Mat4) -> Mat4 {
c: Mat4; c: Mat4;
for j in 0..4 { for j in 0..4 {
for i in 0..4 { for i in 0..4 {
@@ -181,7 +209,7 @@ mul :: proc(a, b: Mat4) -> Mat4 {
return c; return c;
} }
mul :: proc(m: Mat4, v: Vec4) -> Vec4 { mat4_mul_vec4 :: proc(m: Mat4, v: Vec4) -> Vec4 {
return 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][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], 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; o: Mat4;
sf00 := m[2][2] * m[3][3] - m[3][2] * m[2][3]; 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 { mat4_translate :: proc(v: Vec3) -> Mat4 {
m := mat4_identity(); m := identity(Mat4);
m[3][0] = v[0]; m[3][0] = v[0];
m[3][1] = v[1]; m[3][1] = v[1];
m[3][2] = v[2]; m[3][2] = v[2];
@@ -276,7 +305,7 @@ mat4_rotate :: proc(v: Vec3, angle_radians: f32) -> Mat4 {
a := norm(v); a := norm(v);
t := a * (1-c); t := a * (1-c);
rot := mat4_identity(); rot := identity(Mat4);
rot[0][0] = c + t[0]*a[0]; rot[0][0] = c + t[0]*a[0];
rot[0][1] = 0 + t[0]*a[1] + s*a[2]; 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; return rot;
} }
scale :: proc(m: Mat4, v: Vec3) -> Mat4 { scale_vec3 :: proc(m: Mat4, v: Vec3) -> Mat4 {
m[0][0] *= v[0]; m[0][0] *= v[0];
m[1][1] *= v[1]; m[1][1] *= v[1];
m[2][2] *= v[2]; m[2][2] *= v[2];
return m; return m;
} }
scale :: proc(m: Mat4, s: f32) -> Mat4 { scale_f32 :: proc(m: Mat4, s: f32) -> Mat4 {
m[0][0] *= s; m[0][0] *= s;
m[1][1] *= s; m[1][1] *= s;
m[2][2] *= s; m[2][2] *= s;
return m; return m;
} }
scale :: proc[scale_vec3, scale_f32];
look_at :: proc(eye, centre, up: Vec3) -> Mat4 { look_at :: proc(eye, centre, up: Vec3) -> Mat4 {
f := norm(centre - eye); 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 { ortho3d :: proc(left, right, bottom, top, near, far: f32) -> Mat4 {
m := mat4_identity(); m := identity(Mat4);
m[0][0] = +2.0 / (right - left); m[0][0] = +2.0 / (right - left);
m[1][1] = +2.0 / (top - bottom); m[1][1] = +2.0 / (top - bottom);
m[2][2] = -2.0 / (far - near); 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; F32_DIG :: 6;
+5 -3
View File
@@ -1,10 +1,12 @@
import "core:raw.odin" import "core:raw.odin"
foreign __llvm_core { foreign __llvm_core {
@(link_name = "llvm.bswap.i16") swap :: proc(b: u16) -> u16 ---; @(link_name = "llvm.bswap.i16") swap16 :: proc(b: u16) -> u16 ---;
@(link_name = "llvm.bswap.i32") swap :: proc(b: u32) -> u32 ---; @(link_name = "llvm.bswap.i32") swap32 :: proc(b: u32) -> u32 ---;
@(link_name = "llvm.bswap.i64") swap :: proc(b: u64) -> u64 ---; @(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 { set :: proc "contextless" (data: rawptr, value: i32, len: int) -> rawptr {
return __mem_set(data, value, len); return __mem_set(data, value, len);
+3 -3
View File
@@ -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")); _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 { if name[len(name)-1] == 0 {
name = name[..len(name)-1]; name = name[..len(name)-1];
} }
// NOTE(bill): null terminated // NOTE(bill): null terminated
assert((&name[0] + len(name))^ == 0); assert((&name[0] + len(name))^ == 0);
res := wgl.get_proc_address(&name[0]); res := wgl.get_gl_proc_address(&name[0]);
if res == nil { if res == nil {
res = win32.get_proc_address(_libgl, &name[0]); res = win32.get_proc_address(_libgl, &name[0]);
} }
@@ -122,7 +122,7 @@ get_proc_address :: proc(name: string) -> rawptr {
init :: proc() { init :: proc() {
set_proc_address :: proc(p: rawptr, name: string) { set_proc_address :: proc(p: rawptr, name: string) {
x := cast(^rawptr)p; x := cast(^rawptr)p;
x^ = get_proc_address(name); x^ = get_gl_proc_address(name);
} }
set_proc_address(&GenBuffers, "glGenBuffers\x00"); set_proc_address(&GenBuffers, "glGenBuffers\x00");
+2 -2
View File
@@ -53,10 +53,10 @@ write_entire_file :: proc(name: string, data: []byte, truncate := true) -> (succ
return write_err != 0; 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)); 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)); return read(fd, mem.slice_ptr(cast(^byte)data, len));
} }
+3 -3
View File
@@ -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); assert(f != nil);
count := len(array); 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); assert(f != nil);
a := array; a := array;
n := len(a); n := len(a);
@@ -98,7 +98,7 @@ _log2 :: proc(n: int) -> int {
return res; 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) { merge_slices :: proc(arr1, arr2, out: A, f: proc(T, T) -> int) {
N1, N2 := len(arr1), len(arr2); N1, N2 := len(arr1), len(arr2);
i, j := 0, 0; i, j := 0, 0;
+1 -1
View File
@@ -72,7 +72,7 @@ foreign opengl32 {
make_current :: proc(hdc: Hdc, hglrc: Hglrc) -> Bool ---; make_current :: proc(hdc: Hdc, hglrc: Hglrc) -> Bool ---;
@(link_name="wglGetProcAddress") @(link_name="wglGetProcAddress")
get_proc_address :: proc(c_str: ^byte) -> rawptr ---; get_gl_proc_address :: proc(c_str: ^byte) -> rawptr ---;
@(link_name="wglDeleteContext") @(link_name="wglDeleteContext")
delete_context :: proc(hglrc: Hglrc) -> Bool ---; delete_context :: proc(hglrc: Hglrc) -> Bool ---;
+5 -5
View File
@@ -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="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="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="FreeLibrary") free_library :: proc(h: Hmodule) ---;
@(link_name="GetProcAddress") get_proc_address :: proc(h: Hmodule, c_str: ^byte) -> rawptr ---; @(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; return r;
} }
HIWORD :: proc(wParam: Wparam) -> u16 { return u16((u32(wParam) >> 16) & 0xffff); } HIWORD_W :: proc(wParam: Wparam) -> u16 { return u16((u32(wParam) >> 16) & 0xffff); }
HIWORD :: proc(lParam: Lparam) -> u16 { return u16((u32(lParam) >> 16) & 0xffff); } HIWORD_L :: proc(lParam: Lparam) -> u16 { return u16((u32(lParam) >> 16) & 0xffff); }
LOWORD :: proc(wParam: Wparam) -> u16 { return u16(wParam); } LOWORD_W :: proc(wParam: Wparam) -> u16 { return u16(wParam); }
LOWORD :: proc(lParam: Lparam) -> u16 { return u16(lParam); } 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; } is_key_down :: inline proc(key: Key_Code) -> bool { return get_async_key_state(i32(key)) < 0; }
+2 -2
View File
@@ -57,8 +57,8 @@ encode :: proc(d: []u16, s: []rune) -> int {
} }
encode :: proc(d: []u16, s: string) -> int { encode_string :: proc(d: []u16, s: string) -> int {
n := utf8.rune_count(s); n := utf8.rune_count_from_string(s);
for r in s do if r >= _surr_self do n += 1; for r in s do if r >= _surr_self do n += 1;
max_n := min(len(d), n); max_n := min(len(d), n);
+3 -3
View File
@@ -92,7 +92,7 @@ encode_rune :: proc(r: rune) -> ([4]u8, int) {
return buf, 4; 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) { decode_rune :: proc(s: []u8) -> (rune, int) {
n := len(s); n := len(s);
if n < 1 { 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) { decode_last_rune :: proc(s: []u8) -> (rune, int) {
r: rune; r: rune;
size: int; 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_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 { rune_count :: proc(s: []u8) -> int {
count := 0; count := 0;
n := len(s); n := len(s);
+3 -2
View File
@@ -4459,8 +4459,9 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
} }
if (operand->mode == Addressing_Overload) { if (operand->mode == Addressing_Overload) {
GB_ASSERT(operand->overload_entities != nullptr && // GB_ASSERT_MSG(operand->overload_entities != nullptr &&
operand->overload_count > 0); // operand->overload_count > 0,
// "%p %td", operand->overload_entities, operand->overload_count);
isize overload_count = operand->overload_count; isize overload_count = operand->overload_count;
Entity ** procs = operand->overload_entities; Entity ** procs = operand->overload_entities;
ValidIndexAndScore *valids = gb_alloc_array(heap_allocator(), ValidIndexAndScore, overload_count); ValidIndexAndScore *valids = gb_alloc_array(heap_allocator(), ValidIndexAndScore, overload_count);
+1 -1
View File
@@ -780,7 +780,7 @@ Entity *scope_insert_entity(Scope *s, Entity *entity) {
HashKey key = hash_string(name); HashKey key = hash_string(name);
Entity **found = map_get(&s->elements, key); Entity **found = map_get(&s->elements, key);
#if 1 #ifndef DISABLE_PROCEDURE_OVERLOADING
// IMPORTANT NOTE(bill): Procedure overloading code // IMPORTANT NOTE(bill): Procedure overloading code
Entity *prev = nullptr; Entity *prev = nullptr;
if (found) { if (found) {
+2 -1
View File
@@ -1,7 +1,8 @@
#define ALLOW_ARRAY_PROGRAMMING #define ALLOW_ARRAY_PROGRAMMING
// #define DISABLE_PROCEDURE_OVERLOADING
// #define NO_ARRAY_BOUNDS_CHECK // #define NO_ARRAY_BOUNDS_CHECK
#include "common.cpp" #include "common.cpp"
#include "timings.cpp" #include "timings.cpp"
#include "build_settings.cpp" #include "build_settings.cpp"