Merge branch 'odin-lang:master' into attr_error

This commit is contained in:
jon lipstate
2023-05-30 08:23:28 -07:00
committed by GitHub
205 changed files with 19817 additions and 10362 deletions
+12 -12
View File
@@ -104,13 +104,13 @@ jobs:
run: ./odin check examples/all -vet -strict-style -target:linux_arm64
timeout-minutes: 10
build_windows:
runs-on: windows-2019
runs-on: windows-2022
steps:
- uses: actions/checkout@v1
- name: build Odin
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
./build.bat 1
- name: Odin version
run: ./odin version
@@ -121,65 +121,65 @@ jobs:
- name: Odin check
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin check examples/demo -vet
timeout-minutes: 10
- name: Odin run
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin run examples/demo
timeout-minutes: 10
- name: Odin run -debug
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin run examples/demo -debug
timeout-minutes: 10
- name: Odin check examples/all
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin check examples/all -strict-style
timeout-minutes: 10
- name: Core library tests
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\core
call build.bat
timeout-minutes: 10
- name: Vendor library tests
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\vendor
call build.bat
timeout-minutes: 10
- name: Odin internals tests
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\internal
call build.bat
timeout-minutes: 10
- name: Odin documentation tests
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\documentation
call build.bat
timeout-minutes: 10
- name: core:math/big tests
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
cd tests\core\math\big
call build.bat
timeout-minutes: 10
- name: Odin check examples/all for Windows 32bits
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin check examples/all -strict-style -target:windows_i386
timeout-minutes: 10
+3 -3
View File
@@ -7,18 +7,18 @@ on:
jobs:
build_windows:
runs-on: windows-2019
runs-on: windows-2022
steps:
- uses: actions/checkout@v1
- name: build Odin
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
./build.bat 1 1
- name: Odin run
shell: cmd
run: |
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat
odin run examples/demo
- name: Copy artifacts
run: |
+9 -4
View File
@@ -4,14 +4,12 @@ set -eu
: ${CXX=clang++}
: ${CPPFLAGS=}
: ${CXXFLAGS=}
: ${INCLUDE_DIRECTORIES=}
: ${LDFLAGS=}
: ${ODIN_VERSION=dev-$(date +"%Y-%m")}
: ${GIT_SHA=}
CPPFLAGS="$CPPFLAGS -DODIN_VERSION_RAW=\"$ODIN_VERSION\""
CXXFLAGS="$CXXFLAGS -std=c++14"
INCLUDE_DIRECTORIES="$INCLUDE_DIRECTORIES -Isrc/"
LDFLAGS="$LDFLAGS -pthread -lm -lstdc++"
if [ -d ".git" ]; then
@@ -137,7 +135,14 @@ build_odin() {
EXTRAFLAGS="-O3"
;;
release-native)
EXTRAFLAGS="-O3 -march=native"
local ARCH=$(uname -m)
if [ "${ARCH}" == "arm64" ]; then
# Use preferred flag for Arm (ie arm64 / aarch64 / etc)
EXTRAFLAGS="-O3 -mcpu=native"
else
# Use preferred flag for x86 / amd64
EXTRAFLAGS="-O3 -march=native"
fi
;;
nightly)
EXTRAFLAGS="-DNIGHTLY -O3"
@@ -148,7 +153,7 @@ build_odin() {
esac
set -x
$CXX src/main.cpp src/libtommath.cpp $DISABLED_WARNINGS $CPPFLAGS $CXXFLAGS $INCLUDE_DIRECTORIES $EXTRAFLAGS $LDFLAGS -o odin
$CXX src/main.cpp src/libtommath.cpp $DISABLED_WARNINGS $CPPFLAGS $CXXFLAGS $EXTRAFLAGS $LDFLAGS -o odin
set +x
}
+5
View File
@@ -38,6 +38,11 @@ buffer_init_string :: proc(b: ^Buffer, s: string) {
}
buffer_init_allocator :: proc(b: ^Buffer, len, cap: int, allocator := context.allocator) {
if b.buf == nil {
b.buf = make([dynamic]byte, len, cap, allocator)
return
}
b.buf.allocator = allocator
reserve(&b.buf, cap)
resize(&b.buf, len)
+4 -8
View File
@@ -177,12 +177,10 @@ decompress_slice_to_string :: proc(input: []u8, model := DEFAULT_MODEL, allocato
max_output_size := decompress_bound(len(input), model)
buf: [dynamic]u8
if !resize(&buf, max_output_size) {
return "", .Out_Of_Memory
}
resize(&buf, max_output_size) or_return
length, result := decompress_slice_to_output_buffer(input, buf[:])
resize(&buf, length)
resize(&buf, length) or_return
return string(buf[:]), result
}
decompress :: proc{decompress_slice_to_output_buffer, decompress_slice_to_string}
@@ -307,12 +305,10 @@ compress_string :: proc(input: string, model := DEFAULT_MODEL, allocator := cont
max_output_size := compress_bound(len(input))
buf: [dynamic]u8
if !resize(&buf, max_output_size) {
return {}, .Out_Of_Memory
}
resize(&buf, max_output_size) or_return
length, result := compress_string_to_buffer(input, buf[:])
resize(&buf, length)
resize(&buf, length) or_return
return buf[:length], result
}
compress :: proc{compress_string_to_buffer, compress_string}
+142 -83
View File
@@ -27,27 +27,28 @@ Bit_Array_Iterator :: struct {
word_idx: int,
bit_idx: uint,
}
/*
In:
- ba: ^Bit_Array - the array to iterate over
Wraps a `Bit_Array` into an Iterator
Out:
- it: ^Bit_Array_Iterator - the iterator that holds iteration state
Inputs:
- ba: Pointer to the Bit_Array
Returns:
- it: Iterator struct
*/
make_iterator :: proc (ba: ^Bit_Array) -> (it: Bit_Array_Iterator) {
return Bit_Array_Iterator { array = ba }
}
/*
In:
- it: ^Bit_Array_Iterator - the iterator struct that holds the state.
Returns the next bit, including its set-state. ok=false once exhausted
Out:
- set: bool - the state of the bit at `index`
- index: int - the next bit of the Bit_Array referenced by `it`.
- ok: bool - `true` if the iterator returned a valid index,
`false` if there were no more bits
Inputs:
- it: The iterator that holds the state.
Returns:
- set: `true` if the bit at `index` is set.
- index: The next bit of the Bit_Array referenced by `it`.
- ok: `true` if the iterator can continue, `false` if the iterator is done
*/
iterate_by_all :: proc (it: ^Bit_Array_Iterator) -> (set: bool, index: int, ok: bool) {
index = it.word_idx * NUM_BITS + int(it.bit_idx) + it.array.bias
@@ -64,39 +65,51 @@ iterate_by_all :: proc (it: ^Bit_Array_Iterator) -> (set: bool, index: int, ok:
return set, index, true
}
/*
In:
- it: ^Bit_Array_Iterator - the iterator struct that holds the state.
Returns the next Set Bit, for example if `0b1010`, then the iterator will return index={1, 3} over two calls.
Out:
- index: int - the next set bit of the Bit_Array referenced by `it`.
- ok: bool - `true` if the iterator returned a valid index,
`false` if there were no more bits set
Inputs:
- it: The iterator that holds the state.
Returns:
- index: The next *set* bit of the Bit_Array referenced by `it`.
- ok: `true` if the iterator can continue, `false` if the iterator is done
*/
iterate_by_set :: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) {
return iterate_internal_(it, true)
}
/*
In:
- it: ^Bit_Array_Iterator - the iterator struct that holds the state.
Returns the next Unset Bit, for example if `0b1010`, then the iterator will return index={0, 2} over two calls.
Out:
- index: int - the next unset bit of the Bit_Array referenced by `it`.
- ok: bool - `true` if the iterator returned a valid index,
`false` if there were no more unset bits
Inputs:
- it: The iterator that holds the state.
Returns:
- index: The next *unset* bit of the Bit_Array referenced by `it`.
- ok: `true` if the iterator can continue, `false` if the iterator is done
*/
iterate_by_unset:: proc (it: ^Bit_Array_Iterator) -> (index: int, ok: bool) {
return iterate_internal_(it, false)
}
/*
Iterates through set/unset bits
*Private*
Inputs:
- it: The iterator that holds the state.
- ITERATE_SET_BITS: `true` for returning only set bits, false for returning only unset bits
Returns:
- index: The next *unset* bit of the Bit_Array referenced by `it`.
- ok: `true` if the iterator can continue, `false` if the iterator is done
*/
@(private="file")
iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) -> (index: int, ok: bool) {
word := it.array.bits[it.word_idx] if len(it.array.bits) > it.word_idx else 0
when ! ITERATE_SET_BITS { word = ~word }
// if the word is empty or we have already gone over all the bits in it,
// If the word is empty or we have already gone over all the bits in it,
// b.bit_idx is greater than the index of any set bit in the word,
// meaning that word >> b.bit_idx == 0.
for it.word_idx < len(it.array.bits) && word >> it.bit_idx == 0 {
@@ -106,14 +119,14 @@ iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) ->
when ! ITERATE_SET_BITS { word = ~word }
}
// if we are iterating the set bits, reaching the end of the array means we have no more bits to check
// If we are iterating the set bits, reaching the end of the array means we have no more bits to check
when ITERATE_SET_BITS {
if it.word_idx >= len(it.array.bits) {
return 0, false
}
}
// reaching here means that the word has some set bits
// Reaching here means that the word has some set bits
it.bit_idx += uint(intrinsics.count_trailing_zeros(word >> it.bit_idx))
index = it.word_idx * NUM_BITS + int(it.bit_idx) + it.array.bias
@@ -124,24 +137,21 @@ iterate_internal_ :: proc (it: ^Bit_Array_Iterator, $ITERATE_SET_BITS: bool) ->
}
return index, index <= it.array.max_index
}
/*
In:
- ba: ^Bit_Array - a pointer to the Bit Array
- index: The bit index. Can be an enum member.
Gets the state of a bit in the bit-array
Out:
- res: The bit you're interested in.
- ok: Whether the index was valid. Returns `false` if the index is smaller than the bias.
Inputs:
- ba: Pointer to the Bit_Array
- index: Which bit in the array
The `ok` return value may be ignored.
Returns:
- res: `true` if the bit at `index` is set.
- ok: Whether the index was valid. Returns `false` if the index is smaller than the bias.
*/
get :: proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator) -> (res: bool, ok: bool) {
get :: proc(ba: ^Bit_Array, #any_int index: uint) -> (res: bool, ok: bool) #optional_ok {
idx := int(index) - ba.bias
if ba == nil || int(index) < ba.bias { return false, false }
context.allocator = allocator
leg_index := idx >> INDEX_SHIFT
bit_index := idx & INDEX_MASK
@@ -157,18 +167,36 @@ get :: proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator
return res, true
}
/*
In:
- ba: ^Bit_Array - a pointer to the Bit Array
- index: The bit index. Can be an enum member.
Gets the state of a bit in the bit-array
Out:
- ok: Whether or not we managed to set requested bit.
*Bypasses all Checks*
`set` automatically resizes the Bit Array to accommodate the requested index if needed.
Inputs:
- ba: Pointer to the Bit_Array
- index: Which bit in the array
Returns:
- `true` if bit is set
*/
set :: proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator) -> (ok: bool) {
unsafe_get :: #force_inline proc(ba: ^Bit_Array, #any_int index: uint) -> bool #no_bounds_check {
return bool((ba.bits[index >> INDEX_SHIFT] >> uint(index & INDEX_MASK)) & 1)
}
/*
Sets the state of a bit in the bit-array
*Conditionally Allocates (Resizes backing data when `index > len(ba.bits)`)*
Inputs:
- ba: Pointer to the Bit_Array
- index: Which bit in the array
- set_to: `true` sets the bit on, `false` to turn it off
- allocator: (default is context.allocator)
Returns:
- ok: Whether the set was successful, `false` on allocation failure or bad index
*/
set :: proc(ba: ^Bit_Array, #any_int index: uint, set_to: bool = true, allocator := context.allocator) -> (ok: bool) {
idx := int(index) - ba.bias
@@ -181,65 +209,97 @@ set :: proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator
resize_if_needed(ba, leg_index) or_return
ba.max_index = max(idx, ba.max_index)
ba.bits[leg_index] |= 1 << uint(bit_index)
if set_to{ ba.bits[leg_index] |= 1 << uint(bit_index) }
else { ba.bits[leg_index] &= ~(1 << uint(bit_index)) }
return true
}
/*
In:
- ba: ^Bit_Array - a pointer to the Bit Array
- index: The bit index. Can be an enum member.
Sets the state of a bit in the bit-array
Out:
- ok: Whether or not we managed to unset requested bit.
*Bypasses all checks*
`unset` automatically resizes the Bit Array to accommodate the requested index if needed.
Inputs:
- ba: Pointer to the Bit_Array
- index: Which bit in the array
*/
unset :: proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator) -> (ok: bool) {
idx := int(index) - ba.bias
if ba == nil || int(index) < ba.bias { return false }
context.allocator = allocator
leg_index := idx >> INDEX_SHIFT
bit_index := idx & INDEX_MASK
resize_if_needed(ba, leg_index) or_return
ba.max_index = max(idx, ba.max_index)
ba.bits[leg_index] &= ~(1 << uint(bit_index))
return true
unsafe_set :: proc(ba: ^Bit_Array, bit: int) #no_bounds_check {
ba.bits[bit >> INDEX_SHIFT] |= 1 << uint(bit & INDEX_MASK)
}
/*
A helper function to create a Bit Array with optional bias, in case your smallest index is non-zero (including negative).
Unsets the state of a bit in the bit-array. (Convienence wrapper for `set`)
*Conditionally Allocates (Resizes backing data when `index > len(ba.bits)`)*
Inputs:
- ba: Pointer to the Bit_Array
- index: Which bit in the array
- allocator: (default is context.allocator)
Returns:
- ok: Whether the unset was successful, `false` on allocation failure or bad index
*/
create :: proc(max_index: int, min_index := 0, allocator := context.allocator) -> (res: ^Bit_Array, ok: bool) #optional_ok {
unset :: #force_inline proc(ba: ^Bit_Array, #any_int index: uint, allocator := context.allocator) -> (ok: bool) {
return set(ba, index, false, allocator)
}
/*
Unsets the state of a bit in the bit-array
*Bypasses all Checks*
Inputs:
- ba: Pointer to the Bit_Array
- index: Which bit in the array
*/
unsafe_unset :: proc(b: ^Bit_Array, bit: int) #no_bounds_check {
b.bits[bit >> INDEX_SHIFT] &= ~(1 << uint(bit & INDEX_MASK))
}
/*
A helper function to create a Bit Array with optional bias, in case your smallest index is non-zero (including negative).
*Allocates (`new(Bit_Array) & make(ba.bits)`)*
Inputs:
- max_index: maximum starting index
- min_index: minimum starting index (used as a bias)
- allocator: (default is context.allocator)
Returns:
- ba: Allocates a bit_Array, backing data is set to `max-min / 64` indices, rounded up (eg 65 - 0 allocates for [2]u64).
*/
create :: proc(max_index: int, min_index: int = 0, allocator := context.allocator) -> (res: ^Bit_Array, ok: bool) #optional_ok {
context.allocator = allocator
size_in_bits := max_index - min_index
if size_in_bits < 1 { return {}, false }
legs := size_in_bits >> INDEX_SHIFT
if size_in_bits & INDEX_MASK > 0 {legs+=1}
bits, err := make([dynamic]u64, legs)
ok = err == mem.Allocator_Error.None
res = new(Bit_Array)
res.bits = bits
res.bias = min_index
res.max_index = max_index
res.free_pointer = true
return res, resize_if_needed(res, legs)
return
}
/*
Sets all bits to `false`.
Sets all values in the Bit_Array to zero.
Inputs:
- ba: The target Bit_Array
*/
clear :: proc(ba: ^Bit_Array) {
if ba == nil { return }
mem.zero_slice(ba.bits[:])
}
/*
Releases the memory used by the Bit Array.
Deallocates the Bit_Array and its backing storage
Inputs:
- ba: The target Bit_Array
*/
destroy :: proc(ba: ^Bit_Array) {
if ba == nil { return }
@@ -248,9 +308,8 @@ destroy :: proc(ba: ^Bit_Array) {
free(ba)
}
}
/*
Resizes the Bit Array. For internal use.
Resizes the Bit Array. For internal use. Provisions needed capacity+1
If you want to reserve the memory for a given-sized Bit Array up front, you can use `create`.
*/
@(private="file")
+11 -11
View File
@@ -14,7 +14,7 @@ Queue :: struct($T: typeid) {
DEFAULT_CAPACITY :: 16
// Procedure to initialize a queue
init :: proc(q: ^$Q/Queue($T), capacity := DEFAULT_CAPACITY, allocator := context.allocator) -> bool {
init :: proc(q: ^$Q/Queue($T), capacity := DEFAULT_CAPACITY, allocator := context.allocator) -> runtime.Allocator_Error {
if q.data.allocator.procedure == nil {
q.data.allocator = allocator
}
@@ -55,11 +55,11 @@ space :: proc(q: $Q/Queue($T)) -> int {
}
// Reserve enough space for at least the specified capacity
reserve :: proc(q: ^$Q/Queue($T), capacity: int) -> bool {
reserve :: proc(q: ^$Q/Queue($T), capacity: int) -> runtime.Allocator_Error {
if uint(capacity) > q.len {
return _grow(q, uint(capacity))
}
return true
return nil
}
@@ -112,25 +112,25 @@ peek_back :: proc(q: ^$Q/Queue($T), loc := #caller_location) -> ^T {
}
// Push an element to the back of the queue
push_back :: proc(q: ^$Q/Queue($T), elem: T) -> bool {
push_back :: proc(q: ^$Q/Queue($T), elem: T) -> (ok: bool, err: runtime.Allocator_Error) {
if space(q^) == 0 {
_grow(q) or_return
}
idx := (q.offset+uint(q.len))%builtin.len(q.data)
q.data[idx] = elem
q.len += 1
return true
return true, nil
}
// Push an element to the front of the queue
push_front :: proc(q: ^$Q/Queue($T), elem: T) -> bool {
push_front :: proc(q: ^$Q/Queue($T), elem: T) -> (ok: bool, err: runtime.Allocator_Error) {
if space(q^) == 0 {
_grow(q) or_return
}
q.offset = uint(q.offset - 1 + builtin.len(q.data)) % builtin.len(q.data)
q.len += 1
q.data[q.offset] = elem
return true
return true, nil
}
@@ -173,7 +173,7 @@ pop_front_safe :: proc(q: ^$Q/Queue($T)) -> (elem: T, ok: bool) {
}
// Push multiple elements to the front of the queue
push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T) -> bool {
push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T) -> (ok: bool, err: runtime.Allocator_Error) {
n := uint(builtin.len(elems))
if space(q^) < int(n) {
_grow(q, q.len + n) or_return
@@ -188,7 +188,7 @@ push_back_elems :: proc(q: ^$Q/Queue($T), elems: ..T) -> bool {
copy(q.data[insert_from:], elems[:insert_to])
copy(q.data[:insert_from], elems[insert_to:])
q.len += n
return true
return true, nil
}
// Consume `n` elements from the front of the queue
@@ -225,7 +225,7 @@ clear :: proc(q: ^$Q/Queue($T)) {
// Internal growinh procedure
_grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0) -> bool {
_grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0) -> runtime.Allocator_Error {
new_capacity := max(min_capacity, uint(8), uint(builtin.len(q.data))*2)
n := uint(builtin.len(q.data))
builtin.resize(&q.data, int(new_capacity)) or_return
@@ -234,5 +234,5 @@ _grow :: proc(q: ^$Q/Queue($T), min_capacity: uint = 0) -> bool {
copy(q.data[new_capacity-diff:], q.data[q.offset:][:diff])
q.offset += new_capacity - n
}
return true
return nil
}
+73
View File
@@ -0,0 +1,73 @@
package hex
import "core:strings"
encode :: proc(src: []byte, allocator := context.allocator) -> []byte #no_bounds_check {
dst := make([]byte, len(src) * 2, allocator)
for i, j := 0, 0; i < len(src); i += 1 {
v := src[i]
dst[j] = HEXTABLE[v>>4]
dst[j+1] = HEXTABLE[v&0x0f]
j += 2
}
return dst
}
decode :: proc(src: []byte, allocator := context.allocator) -> (dst: []byte, ok: bool) #no_bounds_check {
if len(src) % 2 == 1 {
return
}
dst = make([]byte, len(src) / 2, allocator)
for i, j := 0, 1; j < len(src); j += 2 {
p := src[j-1]
q := src[j]
a := hex_digit(p) or_return
b := hex_digit(q) or_return
dst[i] = (a << 4) | b
i += 1
}
return dst, true
}
// Decodes the given sequence into one byte.
// Should be called with one byte worth of the source, eg: 0x23 -> '#'.
decode_sequence :: proc(str: string) -> (res: byte, ok: bool) {
str := str
if strings.has_prefix(str, "0x") || strings.has_prefix(str, "0X") {
str = str[2:]
}
if len(str) != 2 {
return 0, false
}
upper := hex_digit(str[0]) or_return
lower := hex_digit(str[1]) or_return
return upper << 4 | lower, true
}
@(private)
HEXTABLE := [16]byte {
'0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'a', 'b',
'c', 'd', 'e', 'f',
}
@(private)
hex_digit :: proc(char: byte) -> (u8, bool) {
switch char {
case '0' ..= '9': return char - '0', true
case 'a' ..= 'f': return char - 'a' + 10, true
case 'A' ..= 'F': return char - 'A' + 10, true
case: return 0, false
}
}
+3 -3
View File
@@ -153,7 +153,7 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
case complex128: r, i = f64(real(z)), f64(imag(z))
case: return .Unsupported_Type
}
io.write_byte(w, '[') or_return
io.write_f64(w, r) or_return
io.write_string(w, ", ") or_return
@@ -165,8 +165,8 @@ marshal_to_writer :: proc(w: io.Writer, v: any, opt: ^Marshal_Options) -> (err:
case runtime.Type_Info_String:
switch s in a {
case string: io.write_quoted_string(w, s) or_return
case cstring: io.write_quoted_string(w, string(s)) or_return
case string: io.write_quoted_string(w, s, '"', nil, true) or_return
case cstring: io.write_quoted_string(w, string(s), '"', nil, true) or_return
}
case runtime.Type_Info_Boolean:
+10 -1
View File
@@ -2,6 +2,7 @@ package json
import "core:mem"
import "core:unicode/utf8"
import "core:unicode/utf16"
import "core:strconv"
Parser :: struct {
@@ -403,11 +404,19 @@ unquote_string :: proc(token: Token, spec: Specification, allocator := context.a
}
i += 6
// If this is a surrogate pair, decode as such by taking the next rune too.
if r >= utf8.SURROGATE_MIN && r <= utf8.SURROGATE_HIGH_MAX && len(s) > i + 2 && s[i:i+2] == "\\u" {
r2 := get_u4_rune(s[i:])
if r2 >= utf8.SURROGATE_LOW_MIN && r2 <= utf8.SURROGATE_MAX {
i += 6
r = utf16.decode_surrogate_pair(r, r2)
}
}
buf, buf_width := utf8.encode_rune(r)
copy(b[w:], buf[:buf_width])
w += buf_width
case '0':
if spec != .JSON {
b[w] = '\x00'
+4 -12
View File
@@ -2647,18 +2647,10 @@ fmt_arg :: proc(fi: ^Info, arg: any, verb: rune) {
}
}
custom_types: switch a in arg {
case runtime.Source_Code_Location:
if fi.hash && verb == 'v' {
io.write_string(fi.writer, a.file_path, &fi.n)
io.write_byte(fi.writer, '(', &fi.n)
io.write_i64(fi.writer, i64(a.line), 10, &fi.n)
io.write_byte(fi.writer, ':', &fi.n)
io.write_i64(fi.writer, i64(a.column), 10, &fi.n)
io.write_byte(fi.writer, ')', &fi.n)
return
}
arg_info := type_info_of(arg.id)
if info, ok := arg_info.variant.(runtime.Type_Info_Named); ok {
fmt_named(fi, arg, verb, info)
return
}
base_arg := arg
+5 -5
View File
@@ -634,7 +634,7 @@ alpha_add_if_missing :: proc(img: ^Image, alpha_key := Alpha_Key{}, allocator :=
buf := bytes.Buffer{}
// Can we allocate the return buffer?
if !resize(&buf.buf, bytes_wanted) {
if resize(&buf.buf, bytes_wanted) != nil {
delete(buf.buf)
return false
}
@@ -826,7 +826,7 @@ alpha_drop_if_present :: proc(img: ^Image, options := Options{}, alpha_key := Al
buf := bytes.Buffer{}
// Can we allocate the return buffer?
if !resize(&buf.buf, bytes_wanted) {
if resize(&buf.buf, bytes_wanted) != nil {
delete(buf.buf)
return false
}
@@ -1075,7 +1075,7 @@ apply_palette_rgb :: proc(img: ^Image, palette: [256]RGB_Pixel, allocator := con
// Can we allocate the return buffer?
buf := bytes.Buffer{}
bytes_wanted := compute_buffer_size(img.width, img.height, 3, 8)
if !resize(&buf.buf, bytes_wanted) {
if resize(&buf.buf, bytes_wanted) != nil {
delete(buf.buf)
return false
}
@@ -1112,7 +1112,7 @@ apply_palette_rgba :: proc(img: ^Image, palette: [256]RGBA_Pixel, allocator := c
// Can we allocate the return buffer?
buf := bytes.Buffer{}
bytes_wanted := compute_buffer_size(img.width, img.height, 4, 8)
if !resize(&buf.buf, bytes_wanted) {
if resize(&buf.buf, bytes_wanted) != nil {
delete(buf.buf)
return false
}
@@ -1147,7 +1147,7 @@ expand_grayscale :: proc(img: ^Image, allocator := context.allocator) -> (ok: bo
// Can we allocate the return buffer?
buf := bytes.Buffer{}
bytes_wanted := compute_buffer_size(img.width, img.height, img.channels + 2, img.depth)
if !resize(&buf.buf, bytes_wanted) {
if resize(&buf.buf, bytes_wanted) != nil {
delete(buf.buf)
return false
}
+5 -5
View File
@@ -731,7 +731,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
// We need to create a new image buffer
dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 8)
t := bytes.Buffer{}
if !resize(&t.buf, dest_raw_size) {
if resize(&t.buf, dest_raw_size) != nil {
return {}, .Unable_To_Allocate_Or_Resize
}
@@ -812,7 +812,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
// We need to create a new image buffer
dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 16)
t := bytes.Buffer{}
if !resize(&t.buf, dest_raw_size) {
if resize(&t.buf, dest_raw_size) != nil {
return {}, .Unable_To_Allocate_Or_Resize
}
@@ -1011,7 +1011,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
// We need to create a new image buffer
dest_raw_size := compute_buffer_size(int(header.width), int(header.height), out_image_channels, 8)
t := bytes.Buffer{}
if !resize(&t.buf, dest_raw_size) {
if resize(&t.buf, dest_raw_size) != nil {
return {}, .Unable_To_Allocate_Or_Resize
}
@@ -1522,7 +1522,7 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH
bytes_per_channel := depth == 16 ? 2 : 1
num_bytes := compute_buffer_size(width, height, channels, depth == 16 ? 16 : 8)
if !resize(&img.pixels.buf, num_bytes) {
if resize(&img.pixels.buf, num_bytes) != nil {
return .Unable_To_Allocate_Or_Resize
}
@@ -1564,7 +1564,7 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH
if x > 0 && y > 0 {
temp: bytes.Buffer
temp_len := compute_buffer_size(x, y, channels, depth == 16 ? 16 : 8)
if !resize(&temp.buf, temp_len) {
if resize(&temp.buf, temp_len) != nil {
return .Unable_To_Allocate_Or_Resize
}
+2 -2
View File
@@ -53,7 +53,7 @@ save_to_buffer :: proc(output: ^bytes.Buffer, img: ^Image, options := Options{}
// Calculate and allocate maximum size. We'll reclaim space to actually written output at the end.
max_size := pixels * (img.channels + 1) + size_of(image.QOI_Header) + size_of(u64be)
if !resize(&output.buf, max_size) {
if resize(&output.buf, max_size) != nil {
return .Unable_To_Allocate_Or_Resize
}
@@ -233,7 +233,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
bytes_needed := image.compute_buffer_size(int(header.width), int(header.height), img.channels, 8)
if !resize(&img.pixels.buf, bytes_needed) {
if resize(&img.pixels.buf, bytes_needed) != nil {
return img, .Unable_To_Allocate_Or_Resize
}
+2 -2
View File
@@ -57,7 +57,7 @@ save_to_buffer :: proc(output: ^bytes.Buffer, img: ^Image, options := Options{}
// Calculate and allocate necessary space.
necessary := pixels * img.channels + size_of(image.TGA_Header)
if !resize(&output.buf, necessary) {
if resize(&output.buf, necessary) != nil {
return .Unable_To_Allocate_Or_Resize
}
@@ -292,7 +292,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
return img, nil
}
if !resize(&img.pixels.buf, dest_channels * img.width * img.height) {
if resize(&img.pixels.buf, dest_channels * img.width * img.height) != nil {
return img, .Unable_To_Allocate_Or_Resize
}
+1
View File
@@ -192,6 +192,7 @@ type_map_info :: proc($T: typeid/map[$K]$V) -> ^runtime.Map_Info ---
type_map_cell_info :: proc($T: typeid) -> ^runtime.Map_Cell_Info ---
type_convert_variants_to_pointers :: proc($T: typeid) -> typeid where type_is_union(T) ---
type_merge :: proc($U, $V: typeid) -> typeid where type_is_union(U), type_is_union(V) ---
constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
+21 -8
View File
@@ -2,6 +2,7 @@ package io
import "core:strconv"
import "core:unicode/utf8"
import "core:unicode/utf16"
read_ptr :: proc(r: Reader, p: rawptr, byte_size: int, n_read: ^int = nil) -> (n: int, err: Error) {
return read(r, ([^]byte)(p)[:byte_size], n_read)
@@ -146,7 +147,7 @@ write_encoded_rune :: proc(w: Writer, r: rune, write_quote := true, n_written: ^
return
}
write_escaped_rune :: proc(w: Writer, r: rune, quote: byte, html_safe := false, n_written: ^int = nil) -> (n: int, err: Error) {
write_escaped_rune :: proc(w: Writer, r: rune, quote: byte, html_safe := false, n_written: ^int = nil, for_json := false) -> (n: int, err: Error) {
is_printable :: proc(r: rune) -> bool {
if r <= 0xff {
switch r {
@@ -163,7 +164,7 @@ write_escaped_rune :: proc(w: Writer, r: rune, quote: byte, html_safe := false,
defer if n_written != nil {
n_written^ += n
}
if html_safe {
switch r {
case '<', '>', '&':
@@ -211,17 +212,29 @@ write_escaped_rune :: proc(w: Writer, r: rune, quote: byte, html_safe := false,
write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf], &n) or_return
}
case:
write_byte(w, '\\', &n) or_return
write_byte(w, 'U', &n) or_return
for s := 28; s >= 0; s -= 4 {
write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf], &n) or_return
if for_json {
buf: [2]u16
utf16.encode(buf[:], []rune{c})
for bc in buf {
write_byte(w, '\\', &n) or_return
write_byte(w, 'u', &n) or_return
for s := 12; s >= 0; s -= 4 {
write_byte(w, DIGITS_LOWER[bc>>uint(s) & 0xf], &n) or_return
}
}
} else {
write_byte(w, '\\', &n) or_return
write_byte(w, 'U', &n) or_return
for s := 24; s >= 0; s -= 4 {
write_byte(w, DIGITS_LOWER[c>>uint(s) & 0xf], &n) or_return
}
}
}
}
return
}
write_quoted_string :: proc(w: Writer, str: string, quote: byte = '"', n_written: ^int = nil) -> (n: int, err: Error) {
write_quoted_string :: proc(w: Writer, str: string, quote: byte = '"', n_written: ^int = nil, for_json := false) -> (n: int, err: Error) {
defer if n_written != nil {
n_written^ += n
}
@@ -240,7 +253,7 @@ write_quoted_string :: proc(w: Writer, str: string, quote: byte = '"', n_written
continue
}
n_wrapper(write_escaped_rune(w, r, quote), &n) or_return
n_wrapper(write_escaped_rune(w, r, quote, false, nil, for_json), &n) or_return
}
write_byte(w, quote, &n) or_return
+154 -77
View File
@@ -37,68 +37,96 @@ overflowing_sub :: intrinsics.overflow_sub
overflowing_mul :: intrinsics.overflow_mul
log2 :: proc(x: $T) -> T where intrinsics.type_is_integer(T), intrinsics.type_is_unsigned(T) {
@(require_results)
log2 :: proc "contextless" (x: $T) -> T where intrinsics.type_is_integer(T), intrinsics.type_is_unsigned(T) {
return (8*size_of(T)-1) - count_leading_zeros(x)
}
rotate_left8 :: proc(x: u8, k: int) -> u8 {
@(require_results)
rotate_left8 :: proc "contextless" (x: u8, k: int) -> u8 {
n :: 8
s := uint(k) & (n-1)
return x <<s | x>>(n-s)
}
rotate_left16 :: proc(x: u16, k: int) -> u16 {
@(require_results)
rotate_left16 :: proc "contextless" (x: u16, k: int) -> u16 {
n :: 16
s := uint(k) & (n-1)
return x <<s | x>>(n-s)
}
rotate_left32 :: proc(x: u32, k: int) -> u32 {
@(require_results)
rotate_left32 :: proc "contextless" (x: u32, k: int) -> u32 {
n :: 32
s := uint(k) & (n-1)
return x <<s | x>>(n-s)
}
rotate_left64 :: proc(x: u64, k: int) -> u64 {
@(require_results)
rotate_left64 :: proc "contextless" (x: u64, k: int) -> u64 {
n :: 64
s := uint(k) & (n-1)
return x <<s | x>>(n-s)
}
rotate_left :: proc(x: uint, k: int) -> uint {
@(require_results)
rotate_left :: proc "contextless" (x: uint, k: int) -> uint {
n :: 8*size_of(uint)
s := uint(k) & (n-1)
return x <<s | x>>(n-s)
}
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_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
@(require_results)
from_be_u8 :: proc "contextless" (i: u8) -> u8 { return i }
@(require_results)
from_be_u16 :: proc "contextless" (i: u16) -> u16 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
@(require_results)
from_be_u32 :: proc "contextless" (i: u32) -> u32 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
@(require_results)
from_be_u64 :: proc "contextless" (i: u64) -> u64 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
@(require_results)
from_be_uint :: proc "contextless" (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_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
@(require_results)
from_le_u8 :: proc "contextless" (i: u8) -> u8 { return i }
@(require_results)
from_le_u16 :: proc "contextless" (i: u16) -> u16 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
@(require_results)
from_le_u32 :: proc "contextless" (i: u32) -> u32 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
@(require_results)
from_le_u64 :: proc "contextless" (i: u64) -> u64 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
@(require_results)
from_le_uint :: proc "contextless" (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_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
@(require_results)
to_be_u8 :: proc "contextless" (i: u8) -> u8 { return i }
@(require_results)
to_be_u16 :: proc "contextless" (i: u16) -> u16 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
@(require_results)
to_be_u32 :: proc "contextless" (i: u32) -> u32 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
@(require_results)
to_be_u64 :: proc "contextless" (i: u64) -> u64 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
@(require_results)
to_be_uint :: proc "contextless" (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_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
@(require_results)
to_le_u8 :: proc "contextless" (i: u8) -> u8 { return i }
@(require_results)
to_le_u16 :: proc "contextless" (i: u16) -> u16 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
@(require_results)
to_le_u32 :: proc "contextless" (i: u32) -> u32 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
@(require_results)
to_le_u64 :: proc "contextless" (i: u64) -> u64 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
@(require_results)
to_le_uint :: proc "contextless" (i: uint) -> uint { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
len_u8 :: proc(x: u8) -> int {
@(require_results)
len_u8 :: proc "contextless" (x: u8) -> int {
return int(len_u8_table[x])
}
len_u16 :: proc(x: u16) -> (n: int) {
@(require_results)
len_u16 :: proc "contextless" (x: u16) -> (n: int) {
x := x
if x >= 1<<8 {
x >>= 8
@@ -106,7 +134,8 @@ len_u16 :: proc(x: u16) -> (n: int) {
}
return n + int(len_u8_table[x])
}
len_u32 :: proc(x: u32) -> (n: int) {
@(require_results)
len_u32 :: proc "contextless" (x: u32) -> (n: int) {
x := x
if x >= 1<<16 {
x >>= 16
@@ -118,7 +147,8 @@ len_u32 :: proc(x: u32) -> (n: int) {
}
return n + int(len_u8_table[x])
}
len_u64 :: proc(x: u64) -> (n: int) {
@(require_results)
len_u64 :: proc "contextless" (x: u64) -> (n: int) {
x := x
if x >= 1<<32 {
x >>= 32
@@ -134,7 +164,8 @@ len_u64 :: proc(x: u64) -> (n: int) {
}
return n + int(len_u8_table[x])
}
len_uint :: proc(x: uint) -> (n: int) {
@(require_results)
len_uint :: proc "contextless" (x: uint) -> (n: int) {
when size_of(uint) == size_of(u64) {
return len_u64(u64(x))
} else {
@@ -146,21 +177,24 @@ len_uint :: proc(x: uint) -> (n: int) {
len :: proc{len_u8, len_u16, len_u32, len_u64, len_uint}
add_u32 :: proc(x, y, carry: u32) -> (sum, carry_out: u32) {
@(require_results)
add_u32 :: proc "contextless" (x, y, carry: u32) -> (sum, carry_out: u32) {
tmp_carry, tmp_carry2: bool
sum, tmp_carry = intrinsics.overflow_add(x, y)
sum, tmp_carry2 = intrinsics.overflow_add(sum, carry)
carry_out = u32(tmp_carry | tmp_carry2)
return
}
add_u64 :: proc(x, y, carry: u64) -> (sum, carry_out: u64) {
@(require_results)
add_u64 :: proc "contextless" (x, y, carry: u64) -> (sum, carry_out: u64) {
tmp_carry, tmp_carry2: bool
sum, tmp_carry = intrinsics.overflow_add(x, y)
sum, tmp_carry2 = intrinsics.overflow_add(sum, carry)
carry_out = u64(tmp_carry | tmp_carry2)
return
}
add_uint :: proc(x, y, carry: uint) -> (sum, carry_out: uint) {
@(require_results)
add_uint :: proc "contextless" (x, y, carry: uint) -> (sum, carry_out: uint) {
when size_of(uint) == size_of(u64) {
a, b := add_u64(u64(x), u64(y), u64(carry))
} else {
@@ -172,21 +206,24 @@ add_uint :: proc(x, y, carry: uint) -> (sum, carry_out: uint) {
add :: proc{add_u32, add_u64, add_uint}
sub_u32 :: proc(x, y, borrow: u32) -> (diff, borrow_out: u32) {
@(require_results)
sub_u32 :: proc "contextless" (x, y, borrow: u32) -> (diff, borrow_out: u32) {
tmp_borrow, tmp_borrow2: bool
diff, tmp_borrow = intrinsics.overflow_sub(x, y)
diff, tmp_borrow2 = intrinsics.overflow_sub(diff, borrow)
borrow_out = u32(tmp_borrow | tmp_borrow2)
return
}
sub_u64 :: proc(x, y, borrow: u64) -> (diff, borrow_out: u64) {
@(require_results)
sub_u64 :: proc "contextless" (x, y, borrow: u64) -> (diff, borrow_out: u64) {
tmp_borrow, tmp_borrow2: bool
diff, tmp_borrow = intrinsics.overflow_sub(x, y)
diff, tmp_borrow2 = intrinsics.overflow_sub(diff, borrow)
borrow_out = u64(tmp_borrow | tmp_borrow2)
return
}
sub_uint :: proc(x, y, borrow: uint) -> (diff, borrow_out: uint) {
@(require_results)
sub_uint :: proc "contextless" (x, y, borrow: uint) -> (diff, borrow_out: uint) {
when size_of(uint) == size_of(u64) {
a, b := sub_u64(u64(x), u64(y), u64(borrow))
} else {
@@ -198,18 +235,21 @@ sub_uint :: proc(x, y, borrow: uint) -> (diff, borrow_out: uint) {
sub :: proc{sub_u32, sub_u64, sub_uint}
mul_u32 :: proc(x, y: u32) -> (hi, lo: u32) {
@(require_results)
mul_u32 :: proc "contextless" (x, y: u32) -> (hi, lo: u32) {
z := u64(x) * u64(y)
hi, lo = u32(z>>32), u32(z)
return
}
mul_u64 :: proc(x, y: u64) -> (hi, lo: u64) {
@(require_results)
mul_u64 :: proc "contextless" (x, y: u64) -> (hi, lo: u64) {
prod_wide := u128(x) * u128(y)
hi, lo = u64(prod_wide>>64), u64(prod_wide)
return
}
mul_uint :: proc(x, y: uint) -> (hi, lo: uint) {
@(require_results)
mul_uint :: proc "contextless" (x, y: uint) -> (hi, lo: uint) {
when size_of(uint) == size_of(u32) {
a, b := mul_u32(u32(x), u32(y))
} else {
@@ -222,13 +262,15 @@ mul_uint :: proc(x, y: uint) -> (hi, lo: uint) {
mul :: proc{mul_u32, mul_u64, mul_uint}
div_u32 :: proc(hi, lo, y: u32) -> (quo, rem: u32) {
@(require_results)
div_u32 :: proc "odin" (hi, lo, y: u32) -> (quo, rem: u32) {
assert(y != 0 && y <= hi)
z := u64(hi)<<32 | u64(lo)
quo, rem = u32(z/u64(y)), u32(z%u64(y))
return
}
div_u64 :: proc(hi, lo, y: u64) -> (quo, rem: u64) {
@(require_results)
div_u64 :: proc "odin" (hi, lo, y: u64) -> (quo, rem: u64) {
y := y
two32 :: 1 << 32
mask32 :: two32 - 1
@@ -273,7 +315,8 @@ div_u64 :: proc(hi, lo, y: u64) -> (quo, rem: u64) {
return q1*two32 + q0, (un21*two32 + un0 - q0*y) >> s
}
div_uint :: proc(hi, lo, y: uint) -> (quo, rem: uint) {
@(require_results)
div_uint :: proc "odin" (hi, lo, y: uint) -> (quo, rem: uint) {
when size_of(uint) == size_of(u32) {
a, b := div_u32(u32(hi), u32(lo), u32(y))
} else {
@@ -286,16 +329,26 @@ div :: proc{div_u32, div_u64, div_uint}
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_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 }
@(require_results)
is_power_of_two_u8 :: proc "contextless" (i: u8) -> bool { return i > 0 && (i & (i-1)) == 0 }
@(require_results)
is_power_of_two_i8 :: proc "contextless" (i: i8) -> bool { return i > 0 && (i & (i-1)) == 0 }
@(require_results)
is_power_of_two_u16 :: proc "contextless" (i: u16) -> bool { return i > 0 && (i & (i-1)) == 0 }
@(require_results)
is_power_of_two_i16 :: proc "contextless" (i: i16) -> bool { return i > 0 && (i & (i-1)) == 0 }
@(require_results)
is_power_of_two_u32 :: proc "contextless" (i: u32) -> bool { return i > 0 && (i & (i-1)) == 0 }
@(require_results)
is_power_of_two_i32 :: proc "contextless" (i: i32) -> bool { return i > 0 && (i & (i-1)) == 0 }
@(require_results)
is_power_of_two_u64 :: proc "contextless" (i: u64) -> bool { return i > 0 && (i & (i-1)) == 0 }
@(require_results)
is_power_of_two_i64 :: proc "contextless" (i: i64) -> bool { return i > 0 && (i & (i-1)) == 0 }
@(require_results)
is_power_of_two_uint :: proc "contextless" (i: uint) -> bool { return i > 0 && (i & (i-1)) == 0 }
@(require_results)
is_power_of_two_int :: proc "contextless" (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,
@@ -320,44 +373,56 @@ len_u8_table := [256]u8{
}
bitfield_extract_u8 :: proc(value: u8, offset, bits: uint) -> u8 { return (value >> offset) & u8(1<<bits - 1) }
bitfield_extract_u16 :: proc(value: u16, offset, bits: uint) -> u16 { return (value >> offset) & u16(1<<bits - 1) }
bitfield_extract_u32 :: proc(value: u32, offset, bits: uint) -> u32 { return (value >> offset) & u32(1<<bits - 1) }
bitfield_extract_u64 :: proc(value: u64, offset, bits: uint) -> u64 { return (value >> offset) & u64(1<<bits - 1) }
bitfield_extract_u128 :: proc(value: u128, offset, bits: uint) -> u128 { return (value >> offset) & u128(1<<bits - 1) }
bitfield_extract_uint :: proc(value: uint, offset, bits: uint) -> uint { return (value >> offset) & uint(1<<bits - 1) }
@(require_results)
bitfield_extract_u8 :: proc "contextless" (value: u8, offset, bits: uint) -> u8 { return (value >> offset) & u8(1<<bits - 1) }
@(require_results)
bitfield_extract_u16 :: proc "contextless" (value: u16, offset, bits: uint) -> u16 { return (value >> offset) & u16(1<<bits - 1) }
@(require_results)
bitfield_extract_u32 :: proc "contextless" (value: u32, offset, bits: uint) -> u32 { return (value >> offset) & u32(1<<bits - 1) }
@(require_results)
bitfield_extract_u64 :: proc "contextless" (value: u64, offset, bits: uint) -> u64 { return (value >> offset) & u64(1<<bits - 1) }
@(require_results)
bitfield_extract_u128 :: proc "contextless" (value: u128, offset, bits: uint) -> u128 { return (value >> offset) & u128(1<<bits - 1) }
@(require_results)
bitfield_extract_uint :: proc "contextless" (value: uint, offset, bits: uint) -> uint { return (value >> offset) & uint(1<<bits - 1) }
bitfield_extract_i8 :: proc(value: i8, offset, bits: uint) -> i8 {
@(require_results)
bitfield_extract_i8 :: proc "contextless" (value: i8, offset, bits: uint) -> i8 {
v := (u8(value) >> offset) & u8(1<<bits - 1)
m := u8(1<<(bits-1))
r := (v~m) - m
return i8(r)
}
bitfield_extract_i16 :: proc(value: i16, offset, bits: uint) -> i16 {
@(require_results)
bitfield_extract_i16 :: proc "contextless" (value: i16, offset, bits: uint) -> i16 {
v := (u16(value) >> offset) & u16(1<<bits - 1)
m := u16(1<<(bits-1))
r := (v~m) - m
return i16(r)
}
bitfield_extract_i32 :: proc(value: i32, offset, bits: uint) -> i32 {
@(require_results)
bitfield_extract_i32 :: proc "contextless" (value: i32, offset, bits: uint) -> i32 {
v := (u32(value) >> offset) & u32(1<<bits - 1)
m := u32(1<<(bits-1))
r := (v~m) - m
return i32(r)
}
bitfield_extract_i64 :: proc(value: i64, offset, bits: uint) -> i64 {
@(require_results)
bitfield_extract_i64 :: proc "contextless" (value: i64, offset, bits: uint) -> i64 {
v := (u64(value) >> offset) & u64(1<<bits - 1)
m := u64(1<<(bits-1))
r := (v~m) - m
return i64(r)
}
bitfield_extract_i128 :: proc(value: i128, offset, bits: uint) -> i128 {
@(require_results)
bitfield_extract_i128 :: proc "contextless" (value: i128, offset, bits: uint) -> i128 {
v := (u128(value) >> offset) & u128(1<<bits - 1)
m := u128(1<<(bits-1))
r := (v~m) - m
return i128(r)
}
bitfield_extract_int :: proc(value: int, offset, bits: uint) -> int {
@(require_results)
bitfield_extract_int :: proc "contextless" (value: int, offset, bits: uint) -> int {
v := (uint(value) >> offset) & uint(1<<bits - 1)
m := uint(1<<(bits-1))
r := (v~m) - m
@@ -381,52 +446,64 @@ bitfield_extract :: proc{
}
bitfield_insert_u8 :: proc(base, insert: u8, offset, bits: uint) -> u8 {
@(require_results)
bitfield_insert_u8 :: proc "contextless" (base, insert: u8, offset, bits: uint) -> u8 {
mask := u8(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
bitfield_insert_u16 :: proc(base, insert: u16, offset, bits: uint) -> u16 {
@(require_results)
bitfield_insert_u16 :: proc "contextless" (base, insert: u16, offset, bits: uint) -> u16 {
mask := u16(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
bitfield_insert_u32 :: proc(base, insert: u32, offset, bits: uint) -> u32 {
@(require_results)
bitfield_insert_u32 :: proc "contextless" (base, insert: u32, offset, bits: uint) -> u32 {
mask := u32(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
bitfield_insert_u64 :: proc(base, insert: u64, offset, bits: uint) -> u64 {
@(require_results)
bitfield_insert_u64 :: proc "contextless" (base, insert: u64, offset, bits: uint) -> u64 {
mask := u64(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
bitfield_insert_u128 :: proc(base, insert: u128, offset, bits: uint) -> u128 {
@(require_results)
bitfield_insert_u128 :: proc "contextless" (base, insert: u128, offset, bits: uint) -> u128 {
mask := u128(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
bitfield_insert_uint :: proc(base, insert: uint, offset, bits: uint) -> uint {
@(require_results)
bitfield_insert_uint :: proc "contextless" (base, insert: uint, offset, bits: uint) -> uint {
mask := uint(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
bitfield_insert_i8 :: proc(base, insert: i8, offset, bits: uint) -> i8 {
@(require_results)
bitfield_insert_i8 :: proc "contextless" (base, insert: i8, offset, bits: uint) -> i8 {
mask := i8(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
bitfield_insert_i16 :: proc(base, insert: i16, offset, bits: uint) -> i16 {
@(require_results)
bitfield_insert_i16 :: proc "contextless" (base, insert: i16, offset, bits: uint) -> i16 {
mask := i16(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
bitfield_insert_i32 :: proc(base, insert: i32, offset, bits: uint) -> i32 {
@(require_results)
bitfield_insert_i32 :: proc "contextless" (base, insert: i32, offset, bits: uint) -> i32 {
mask := i32(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
bitfield_insert_i64 :: proc(base, insert: i64, offset, bits: uint) -> i64 {
@(require_results)
bitfield_insert_i64 :: proc "contextless" (base, insert: i64, offset, bits: uint) -> i64 {
mask := i64(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
bitfield_insert_i128 :: proc(base, insert: i128, offset, bits: uint) -> i128 {
@(require_results)
bitfield_insert_i128 :: proc "contextless" (base, insert: i128, offset, bits: uint) -> i128 {
mask := i128(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
bitfield_insert_int :: proc(base, insert: int, offset, bits: uint) -> int {
@(require_results)
bitfield_insert_int :: proc "contextless" (base, insert: int, offset, bits: uint) -> int {
mask := int(1<<bits - 1)
return (base &~ (mask<<offset)) | ((insert&mask) << offset)
}
+67 -32
View File
@@ -11,11 +11,13 @@ import "core:time"
// with additional enum based call
// Modeled after the parabola y = x^2
@(require_results)
quadratic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p * p
}
// Modeled after the parabola y = -x^2 + 2x
@(require_results)
quadratic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return -(p * (p - 2))
}
@@ -23,6 +25,7 @@ quadratic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(
// Modeled after the piecewise quadratic
// y = (1/2)((2x)^2) ; [0, 0.5)
// y = -(1/2)((2x-1)*(2x-3) - 1) ; [0.5, 1]
@(require_results)
quadratic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 {
return 2 * p * p
@@ -32,11 +35,13 @@ quadratic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_flo
}
// Modeled after the cubic y = x^3
@(require_results)
cubic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p * p * p
}
// Modeled after the cubic y = (x - 1)^3 + 1
@(require_results)
cubic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
f := p - 1
return f * f * f + 1
@@ -45,6 +50,7 @@ cubic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
// Modeled after the piecewise cubic
// y = (1/2)((2x)^3) ; [0, 0.5)
// y = (1/2)((2x-2)^3 + 2) ; [0.5, 1]
@(require_results)
cubic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 {
return 4 * p * p * p
@@ -55,11 +61,13 @@ cubic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T
}
// Modeled after the quartic x^4
@(require_results)
quartic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p * p * p * p
}
// Modeled after the quartic y = 1 - (x - 1)^4
@(require_results)
quartic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
f := p - 1
return f * f * f * (1 - p) + 1
@@ -68,6 +76,7 @@ quartic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T)
// Modeled after the piecewise quartic
// y = (1/2)((2x)^4) ; [0, 0.5)
// y = -(1/2)((2x-2)^4 - 2) ; [0.5, 1]
@(require_results)
quartic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 {
return 8 * p * p * p * p
@@ -78,11 +87,13 @@ quartic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float
}
// Modeled after the quintic y = x^5
@(require_results)
quintic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p * p * p * p * p
}
// Modeled after the quintic y = (x - 1)^5 + 1
@(require_results)
quintic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
f := p - 1
return f * f * f * f * f + 1
@@ -91,6 +102,7 @@ quintic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T)
// Modeled after the piecewise quintic
// y = (1/2)((2x)^5) ; [0, 0.5)
// y = (1/2)((2x-2)^5 + 2) ; [0.5, 1]
@(require_results)
quintic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 {
return 16 * p * p * p * p * p
@@ -101,26 +113,31 @@ quintic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float
}
// Modeled after quarter-cycle of sine wave
@(require_results)
sine_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return math.sin((p - 1) * PI_2) + 1
}
// Modeled after quarter-cycle of sine wave (different phase)
@(require_results)
sine_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return math.sin(p * PI_2)
}
// Modeled after half sine wave
@(require_results)
sine_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return 0.5 * (1 - math.cos(p * math.PI))
}
// Modeled after shifted quadrant IV of unit circle
@(require_results)
circular_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return 1 - math.sqrt(1 - (p * p))
}
// Modeled after shifted quadrant II of unit circle
@(require_results)
circular_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return math.sqrt((2 - p) * p)
}
@@ -128,6 +145,7 @@ circular_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T
// Modeled after the piecewise circular function
// y = (1/2)(1 - sqrt(1 - 4x^2)) ; [0, 0.5)
// y = (1/2)(sqrt(-(2x - 3)*(2x - 1)) + 1) ; [0.5, 1]
@(require_results)
circular_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 {
return 0.5 * (1 - math.sqrt(1 - 4 * (p * p)))
@@ -137,11 +155,13 @@ circular_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_floa
}
// Modeled after the exponential function y = 2^(10(x - 1))
@(require_results)
exponential_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p == 0.0 ? p : math.pow(2, 10 * (p - 1))
}
// Modeled after the exponential function y = -2^(-10x) + 1
@(require_results)
exponential_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p == 1.0 ? p : 1 - math.pow(2, -10 * p)
}
@@ -149,6 +169,7 @@ exponential_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_floa
// Modeled after the piecewise exponential
// y = (1/2)2^(10(2x - 1)) ; [0,0.5)
// y = -(1/2)*2^(-10(2x - 1))) + 1 ; [0.5,1]
@(require_results)
exponential_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p == 0.0 || p == 1.0 {
return p
@@ -162,11 +183,13 @@ exponential_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_f
}
// Modeled after the damped sine wave y = sin(13pi/2*x)*pow(2, 10 * (x - 1))
@(require_results)
elastic_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return math.sin(13 * PI_2 * p) * math.pow(2, 10 * (p - 1))
}
// Modeled after the damped sine wave y = sin(-13pi/2*(x + 1))*pow(2, -10x) + 1
@(require_results)
elastic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return math.sin(-13 * PI_2 * (p + 1)) * math.pow(2, -10 * p) + 1
}
@@ -174,6 +197,7 @@ elastic_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T)
// Modeled after the piecewise exponentially-damped sine wave:
// y = (1/2)*sin(13pi/2*(2*x))*pow(2, 10 * ((2*x) - 1)) ; [0,0.5)
// y = (1/2)*(sin(-13pi/2*((2x-1)+1))*pow(2,-10(2*x-1)) + 2) ; [0.5, 1]
@(require_results)
elastic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 {
return 0.5 * math.sin(13 * PI_2 * (2 * p)) * math.pow(2, 10 * ((2 * p) - 1))
@@ -183,11 +207,13 @@ elastic_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float
}
// Modeled after the overshooting cubic y = x^3-x*sin(x*pi)
@(require_results)
back_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return p * p * p - p * math.sin(p * math.PI)
}
// Modeled after overshooting cubic y = 1-((1-x)^3-(1-x)*sin((1-x)*pi))
@(require_results)
back_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
f := 1 - p
return 1 - (f * f * f - f * math.sin(f * math.PI))
@@ -196,6 +222,7 @@ back_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
// Modeled after the piecewise overshooting cubic function:
// y = (1/2)*((2x)^3-(2x)*sin(2*x*pi)) ; [0, 0.5)
// y = (1/2)*(1-((1-x)^3-(1-x)*sin((1-x)*pi))+1) ; [0.5, 1]
@(require_results)
back_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 {
f := 2 * p
@@ -206,10 +233,12 @@ back_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T)
}
}
@(require_results)
bounce_in :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
return 1 - bounce_out(1 - p)
}
@(require_results)
bounce_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 4/11.0 {
return (121 * p * p)/16.0
@@ -222,6 +251,7 @@ bounce_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T)
}
}
@(require_results)
bounce_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
if p < 0.5 {
return 0.5 * bounce_in(p*2)
@@ -276,50 +306,51 @@ Ease :: enum {
Bounce_In_Out,
}
@(require_results)
ease :: proc "contextless" (type: Ease, p: $T) -> T
where intrinsics.type_is_float(T) {
switch type {
case .Linear: return p
case .Quadratic_In: return quadratic_in(p)
case .Quadratic_Out: return quadratic_out(p)
case .Quadratic_In_Out: return quadratic_in_out(p)
case .Linear: return p
case .Cubic_In: return cubic_in(p)
case .Cubic_Out: return cubic_out(p)
case .Cubic_In_Out: return cubic_in_out(p)
case .Quadratic_In: return quadratic_in(p)
case .Quadratic_Out: return quadratic_out(p)
case .Quadratic_In_Out: return quadratic_in_out(p)
case .Quartic_In: return quartic_in(p)
case .Quartic_Out: return quartic_out(p)
case .Quartic_In_Out: return quartic_in_out(p)
case .Cubic_In: return cubic_in(p)
case .Cubic_Out: return cubic_out(p)
case .Cubic_In_Out: return cubic_in_out(p)
case .Quintic_In: return quintic_in(p)
case .Quintic_Out: return quintic_out(p)
case .Quintic_In_Out: return quintic_in_out(p)
case .Quartic_In: return quartic_in(p)
case .Quartic_Out: return quartic_out(p)
case .Quartic_In_Out: return quartic_in_out(p)
case .Sine_In: return sine_in(p)
case .Sine_Out: return sine_out(p)
case .Sine_In_Out: return sine_in_out(p)
case .Quintic_In: return quintic_in(p)
case .Quintic_Out: return quintic_out(p)
case .Quintic_In_Out: return quintic_in_out(p)
case .Circular_In: return circular_in(p)
case .Circular_Out: return circular_out(p)
case .Circular_In_Out: return circular_in_out(p)
case .Sine_In: return sine_in(p)
case .Sine_Out: return sine_out(p)
case .Sine_In_Out: return sine_in_out(p)
case .Exponential_In: return exponential_in(p)
case .Exponential_Out: return exponential_out(p)
case .Exponential_In_Out: return exponential_in_out(p)
case .Circular_In: return circular_in(p)
case .Circular_Out: return circular_out(p)
case .Circular_In_Out: return circular_in_out(p)
case .Elastic_In: return elastic_in(p)
case .Elastic_Out: return elastic_out(p)
case .Elastic_In_Out: return elastic_in_out(p)
case .Exponential_In: return exponential_in(p)
case .Exponential_Out: return exponential_out(p)
case .Exponential_In_Out: return exponential_in_out(p)
case .Back_In: return back_in(p)
case .Back_Out: return back_out(p)
case .Back_In_Out: return back_in_out(p)
case .Elastic_In: return elastic_in(p)
case .Elastic_Out: return elastic_out(p)
case .Elastic_In_Out: return elastic_in_out(p)
case .Bounce_In: return bounce_in(p)
case .Bounce_Out: return bounce_out(p)
case .Bounce_In_Out: return bounce_in_out(p)
case .Back_In: return back_in(p)
case .Back_Out: return back_out(p)
case .Back_In_Out: return back_in_out(p)
case .Bounce_In: return bounce_in(p)
case .Bounce_Out: return bounce_out(p)
case .Bounce_In_Out: return bounce_in_out(p)
}
// in case type was invalid
@@ -353,6 +384,7 @@ Flux_Tween :: struct($T: typeid) {
}
// init flux map to a float type and a wanted cap
@(require_results)
flux_init :: proc($T: typeid, value_capacity := 8) -> Flux_Map(T) where intrinsics.type_is_float(T) {
return {
values = make(map[^T]Flux_Tween(T), value_capacity),
@@ -374,6 +406,7 @@ flux_clear :: proc(flux: ^Flux_Map($T)) where intrinsics.type_is_float(T) {
// append / overwrite existing tween value to parameters
// rest is initialized in flux_tween_init, inside update
// return value can be used to set callbacks
@(require_results)
flux_to :: proc(
flux: ^Flux_Map($T),
value: ^T,
@@ -475,6 +508,7 @@ flux_update :: proc(flux: ^Flux_Map($T), dt: f64) where intrinsics.type_is_float
// stop a specific key inside the map
// returns true when it successfully removed the key
@(require_results)
flux_stop :: proc(flux: ^Flux_Map($T), key: ^T) -> bool where intrinsics.type_is_float(T) {
if key in flux.values {
delete_key(&flux.values, key)
@@ -486,6 +520,7 @@ flux_stop :: proc(flux: ^Flux_Map($T), key: ^T) -> bool where intrinsics.type_is
// returns the amount of time left for the tween animation, if the key exists in the map
// returns 0 if the tween doesnt exist on the map
@(require_results)
flux_tween_time_left :: proc(flux: Flux_Map($T), key: ^T) -> f64 {
if tween, ok := flux.values[key]; ok {
return ((1 - tween.progress) * tween.rate) + tween.delay
+11
View File
@@ -50,39 +50,48 @@ to_f64 :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> f64 {
}
@(require_results)
add :: proc(x, y: $T/Fixed) -> T {
return {x.i + y.i}
}
@(require_results)
sub :: proc(x, y: $T/Fixed) -> T {
return {x.i - y.i}
}
@(require_results)
mul :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) {
z.i = intrinsics.fixed_point_mul(x.i, y.i, Fraction_Width)
return
}
@(require_results)
mul_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) {
z.i = intrinsics.fixed_point_mul_sat(x.i, y.i, Fraction_Width)
return
}
@(require_results)
div :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) {
z.i = intrinsics.fixed_point_div(x.i, y.i, Fraction_Width)
return
}
@(require_results)
div_sat :: proc(x, y: $T/Fixed($Backing, $Fraction_Width)) -> (z: T) {
z.i = intrinsics.fixed_point_div_sat(x.i, y.i, Fraction_Width)
return
}
@(require_results)
floor :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing {
return x.i >> Fraction_Width
}
@(require_results)
ceil :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing {
Integer :: 8*size_of(Backing) - Fraction_Width
return (x.i + (1 << Integer-1)) >> Fraction_Width
}
@(require_results)
round :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing {
Integer :: 8*size_of(Backing) - Fraction_Width
return (x.i + (1 << (Integer - 1))) >> Fraction_Width
@@ -90,6 +99,7 @@ round :: proc(x: $T/Fixed($Backing, $Fraction_Width)) -> Backing {
@(require_results)
append :: proc(dst: []byte, x: $T/Fixed($Backing, $Fraction_Width)) -> string {
x := x
buf: [48]byte
@@ -123,6 +133,7 @@ append :: proc(dst: []byte, x: $T/Fixed($Backing, $Fraction_Width)) -> string {
}
@(require_results)
to_string :: proc(x: $T/Fixed($Backing, $Fraction_Width), allocator := context.allocator) -> string {
buf: [48]byte
s := append(buf[:], x)
+124 -65
View File
@@ -3,7 +3,8 @@ package linalg
import "core:builtin"
import "core:math"
to_radians :: proc(degrees: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
@(require_results)
to_radians :: proc "contextless" (degrees: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = degrees[i] * RAD_PER_DEG
@@ -14,7 +15,8 @@ to_radians :: proc(degrees: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
return
}
to_degrees :: proc(radians: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
@(require_results)
to_degrees :: proc "contextless" (radians: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = radians[i] * DEG_PER_RAD
@@ -25,7 +27,8 @@ to_degrees :: proc(radians: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
return
}
min_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
@(require_results)
min_double :: proc "contextless" (a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = builtin.min(a[i], b[i])
@@ -36,7 +39,8 @@ min_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
return
}
min_single :: proc(a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) {
@(require_results)
min_single :: proc "contextless" (a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
N :: len(T)
@@ -56,13 +60,15 @@ min_single :: proc(a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T))
return
}
min_triple :: proc(a, b, c: $T) -> T where IS_NUMERIC(ELEM_TYPE(T)) {
@(require_results)
min_triple :: proc "contextless" (a, b, c: $T) -> T where IS_NUMERIC(ELEM_TYPE(T)) {
return min_double(a, min_double(b, c))
}
min :: proc{min_single, min_double, min_triple}
max_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
@(require_results)
max_double :: proc "contextless" (a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = builtin.max(a[i], b[i])
@@ -73,7 +79,8 @@ max_double :: proc(a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
return
}
max_single :: proc(a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) {
@(require_results)
max_single :: proc "contextless" (a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
N :: len(T)
@@ -95,13 +102,15 @@ max_single :: proc(a: $T) -> (out: ELEM_TYPE(T)) where IS_NUMERIC(ELEM_TYPE(T))
return
}
max_triple :: proc(a, b, c: $T) -> T where IS_NUMERIC(ELEM_TYPE(T)) {
@(require_results)
max_triple :: proc "contextless" (a, b, c: $T) -> T where IS_NUMERIC(ELEM_TYPE(T)) {
return max_double(a, max_double(b, c))
}
max :: proc{max_single, max_double, max_triple}
abs :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
@(require_results)
abs :: proc "contextless" (a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = auto_cast builtin.abs(a[i])
@@ -112,7 +121,8 @@ abs :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
return
}
sign :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
@(require_results)
sign :: proc "contextless" (a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = #force_inline math.sign(a[i])
@@ -123,7 +133,8 @@ sign :: proc(a: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
return
}
clamp :: proc(x, a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
@(require_results)
clamp :: proc "contextless" (x, a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = builtin.clamp(x[i], a[i], b[i])
@@ -135,11 +146,13 @@ clamp :: proc(x, a, b: $T) -> (out: T) where IS_NUMERIC(ELEM_TYPE(T)) {
}
saturate :: proc(x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
saturate :: proc "contextless" (x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
return clamp(x, 0.0, 1.0)
}
lerp :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
lerp :: proc "contextless" (a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = a[i]*(1-t[i]) + b[i]*t[i]
@@ -149,7 +162,8 @@ lerp :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
}
return
}
mix :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
mix :: proc "contextless" (a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = a[i]*(1-t[i]) + b[i]*t[i]
@@ -160,11 +174,13 @@ mix :: proc(a, b, t: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
unlerp :: proc(a, b, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
unlerp :: proc "contextless" (a, b, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
return (x - a) / (b - a)
}
step :: proc(e, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
step :: proc "contextless" (e, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = x[i] < e[i] ? 0.0 : 1.0
@@ -175,18 +191,21 @@ step :: proc(e, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
smoothstep :: proc(e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
smoothstep :: proc "contextless" (e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
t := saturate(unlerp(e0, e1, x))
return t * t * (3.0 - 2.0 * t)
}
smootherstep :: proc(e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
smootherstep :: proc "contextless" (e0, e1, x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
t := saturate(unlerp(e0, e1, x))
return t * t * t * (t * (6*t - 15) + 10)
}
sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
sqrt :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.sqrt(x[i])
@@ -197,7 +216,8 @@ sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
inverse_sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
inverse_sqrt :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = 1.0/math.sqrt(x[i])
@@ -208,7 +228,8 @@ inverse_sqrt :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
cos :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
cos :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.cos(x[i])
@@ -219,7 +240,8 @@ cos :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
sin :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
sin :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.sin(x[i])
@@ -230,7 +252,8 @@ sin :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
tan :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
tan :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.tan(x[i])
@@ -241,7 +264,8 @@ tan :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
acos :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
acos :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.acos(x[i])
@@ -252,7 +276,8 @@ acos :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
asin :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
asin :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.asin(x[i])
@@ -263,7 +288,8 @@ asin :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
atan :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
atan :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.atan(x[i])
@@ -273,7 +299,8 @@ atan :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
}
return
}
atan2 :: proc(y, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
atan2 :: proc "contextless" (y, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.atan2(y[i], x[i])
@@ -285,7 +312,8 @@ atan2 :: proc(y, x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
}
ln :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
ln :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.ln(x[i])
@@ -296,7 +324,8 @@ ln :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
log2 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
log2 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = INVLN2 * math.ln(x[i])
@@ -307,7 +336,8 @@ log2 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
log10 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
log10 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = INVLN10 * math.ln(x[i])
@@ -318,7 +348,8 @@ log10 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
log :: proc(x, b: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
log :: proc "contextless" (x, b: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.ln(x[i]) / math.ln(cast(ELEM_TYPE(T))b[i])
@@ -329,7 +360,8 @@ log :: proc(x, b: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
exp :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
exp :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.exp(x[i])
@@ -340,7 +372,8 @@ exp :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
exp2 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
exp2 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.exp(LN2 * x[i])
@@ -351,7 +384,8 @@ exp2 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
exp10 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
exp10 :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.exp(LN10 * x[i])
@@ -362,7 +396,8 @@ exp10 :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
pow :: proc(x, e: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
pow :: proc "contextless" (x, e: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = math.pow(x[i], e[i])
@@ -374,7 +409,8 @@ pow :: proc(x, e: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
}
ceil :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
ceil :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = #force_inline math.ceil(x[i])
@@ -385,7 +421,8 @@ ceil :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
floor :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
floor :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = #force_inline math.floor(x[i])
@@ -396,7 +433,8 @@ floor :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
round :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
round :: proc "contextless" (x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
when IS_ARRAY(T) {
for i in 0..<len(T) {
out[i] = #force_inline math.round(x[i])
@@ -407,30 +445,36 @@ round :: proc(x: $T) -> (out: T) where IS_FLOAT(ELEM_TYPE(T)) {
return
}
fract :: proc(x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
fract :: proc "contextless" (x: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
f := #force_inline floor(x)
return x - f
}
mod :: proc(x, m: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
mod :: proc "contextless" (x, m: $T) -> T where IS_FLOAT(ELEM_TYPE(T)) {
f := #force_inline floor(x / m)
return x - f * m
}
face_forward :: proc(N, I, N_ref: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
face_forward :: proc "contextless" (N, I, N_ref: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) {
return dot(N_ref, I) < 0 ? N : -N
}
distance :: proc(p0, p1: $V/[$N]$E) -> E where IS_NUMERIC(E) {
@(require_results)
distance :: proc "contextless" (p0, p1: $V/[$N]$E) -> E where IS_NUMERIC(E) {
return length(p1 - p0)
}
reflect :: proc(I, N: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) {
@(require_results)
reflect :: proc "contextless" (I, N: $T) -> (out: T) where IS_ARRAY(T), IS_FLOAT(ELEM_TYPE(T)) {
b := N * (2 * dot(N, I))
return I - b
}
refract :: proc(I, Normal: $V/[$N]$E, eta: E) -> (out: V) where IS_ARRAY(V), IS_FLOAT(ELEM_TYPE(V)) {
@(require_results)
refract :: proc "contextless" (I, Normal: $V/[$N]$E, eta: E) -> (out: V) where IS_ARRAY(V), IS_FLOAT(ELEM_TYPE(V)) {
dv := dot(Normal, I)
k := 1 - eta*eta * (1 - dv*dv)
a := I * eta
@@ -441,33 +485,39 @@ refract :: proc(I, Normal: $V/[$N]$E, eta: E) -> (out: V) where IS_ARRAY(V), IS_
is_nan_single :: proc(x: $T) -> bool where IS_FLOAT(T) {
@(require_results)
is_nan_single :: proc "contextless" (x: $T) -> bool where IS_FLOAT(T) {
return #force_inline math.is_nan(x)
}
is_nan_array :: proc(x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) {
@(require_results)
is_nan_array :: proc "contextless" (x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) {
for i in 0..<N {
out[i] = #force_inline is_nan(x[i])
}
return
}
is_inf_single :: proc(x: $T) -> bool where IS_FLOAT(T) {
@(require_results)
is_inf_single :: proc "contextless" (x: $T) -> bool where IS_FLOAT(T) {
return #force_inline math.is_inf(x)
}
is_inf_array :: proc(x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) {
@(require_results)
is_inf_array :: proc "contextless" (x: $A/[$N]$T) -> (out: [N]bool) where IS_FLOAT(T) {
for i in 0..<N {
out[i] = #force_inline is_inf(x[i])
}
return
}
classify_single :: proc(x: $T) -> math.Float_Class where IS_FLOAT(T) {
@(require_results)
classify_single :: proc "contextless" (x: $T) -> math.Float_Class where IS_FLOAT(T) {
return #force_inline math.classify(x)
}
classify_array :: proc(x: $A/[$N]$T) -> (out: [N]math.Float_Class) where IS_FLOAT(T) {
@(require_results)
classify_array :: proc "contextless" (x: $A/[$N]$T) -> (out: [N]math.Float_Class) where IS_FLOAT(T) {
for i in 0..<N {
out[i] = #force_inline classify_single(x[i])
}
@@ -479,44 +529,50 @@ is_inf :: proc{is_inf_single, is_inf_array}
classify :: proc{classify_single, classify_array}
less_than_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x < y }
less_than_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x <= y }
greater_than_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x > y }
greater_than_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x >= y }
equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x == y }
not_equal_single :: proc(x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x != y }
@(require_results) less_than_single :: proc "contextless" (x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x < y }
@(require_results) less_than_equal_single :: proc "contextless" (x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x <= y }
@(require_results) greater_than_single :: proc "contextless" (x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x > y }
@(require_results) greater_than_equal_single :: proc "contextless" (x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x >= y }
@(require_results) equal_single :: proc "contextless" (x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x == y }
@(require_results) not_equal_single :: proc "contextless" (x, y: $T) -> (out: bool) where !IS_ARRAY(T), IS_FLOAT(T) { return x != y }
less_than_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
@(require_results)
less_than_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N {
out[i] = x[i] < y[i]
}
return
}
less_than_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
@(require_results)
less_than_equal_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N {
out[i] = x[i] <= y[i]
}
return
}
greater_than_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
@(require_results)
greater_than_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N {
out[i] = x[i] > y[i]
}
return
}
greater_than_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
@(require_results)
greater_than_equal_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N {
out[i] = x[i] >= y[i]
}
return
}
equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
@(require_results)
equal_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N {
out[i] = x[i] == y[i]
}
return
}
not_equal_array :: proc(x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
@(require_results)
not_equal_array :: proc "contextless" (x, y: $A/[$N]$T) -> (out: [N]bool) where IS_ARRAY(A), IS_FLOAT(ELEM_TYPE(A)) {
for i in 0..<N {
out[i] = x[i] != y[i]
}
@@ -530,7 +586,8 @@ greater_than_equal :: proc{greater_than_equal_single, greater_than_equal_array}
equal :: proc{equal_single, equal_array}
not_equal :: proc{not_equal_single, not_equal_array}
any :: proc(x: $A/[$N]bool) -> (out: bool) {
@(require_results)
any :: proc "contextless" (x: $A/[$N]bool) -> (out: bool) {
for e in x {
if e {
return true
@@ -538,7 +595,8 @@ any :: proc(x: $A/[$N]bool) -> (out: bool) {
}
return false
}
all :: proc(x: $A/[$N]bool) -> (out: bool) {
@(require_results)
all :: proc "contextless" (x: $A/[$N]bool) -> (out: bool) {
for e in x {
if !e {
return false
@@ -546,7 +604,8 @@ all :: proc(x: $A/[$N]bool) -> (out: bool) {
}
return true
}
not :: proc(x: $A/[$N]bool) -> (out: A) {
@(require_results)
not :: proc "contextless" (x: $A/[$N]bool) -> (out: A) {
for e, i in x {
out[i] = !e
}
+94 -56
View File
@@ -38,23 +38,28 @@ DEG_PER_RAD :: 360.0/TAU
@private ELEM_TYPE :: intrinsics.type_elem_type
scalar_dot :: proc(a, b: $T) -> T where IS_FLOAT(T), !IS_ARRAY(T) {
@(require_results)
scalar_dot :: proc "contextless" (a, b: $T) -> T where IS_FLOAT(T), !IS_ARRAY(T) {
return a * b
}
vector_dot :: proc(a, b: $T/[$N]$E) -> (c: E) where IS_NUMERIC(E) #no_bounds_check {
@(require_results)
vector_dot :: proc "contextless" (a, b: $T/[$N]$E) -> (c: E) where IS_NUMERIC(E) #no_bounds_check {
for i in 0..<N {
c += a[i] * b[i]
}
return
}
quaternion64_dot :: proc(a, b: $T/quaternion64) -> (c: f16) {
@(require_results)
quaternion64_dot :: proc "contextless" (a, b: $T/quaternion64) -> (c: f16) {
return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z
}
quaternion128_dot :: proc(a, b: $T/quaternion128) -> (c: f32) {
@(require_results)
quaternion128_dot :: proc "contextless" (a, b: $T/quaternion128) -> (c: f32) {
return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z
}
quaternion256_dot :: proc(a, b: $T/quaternion256) -> (c: f64) {
@(require_results)
quaternion256_dot :: proc "contextless" (a, b: $T/quaternion256) -> (c: f64) {
return a.w*a.w + a.x*b.x + a.y*b.y + a.z*b.z
}
@@ -63,27 +68,32 @@ dot :: proc{scalar_dot, vector_dot, quaternion64_dot, quaternion128_dot, quatern
inner_product :: dot
outer_product :: builtin.outer_product
quaternion_inverse :: proc(q: $Q) -> Q where IS_QUATERNION(Q) {
@(require_results)
quaternion_inverse :: proc "contextless" (q: $Q) -> Q where IS_QUATERNION(Q) {
return conj(q) * quaternion(1.0/dot(q, q), 0, 0, 0)
}
scalar_cross :: proc(a, b: $T) -> T where IS_FLOAT(T), !IS_ARRAY(T) {
@(require_results)
scalar_cross :: proc "contextless" (a, b: $T) -> T where IS_FLOAT(T), !IS_ARRAY(T) {
return a * b
}
vector_cross2 :: proc(a, b: $T/[2]$E) -> E where IS_NUMERIC(E) {
@(require_results)
vector_cross2 :: proc "contextless" (a, b: $T/[2]$E) -> E where IS_NUMERIC(E) {
return a[0]*b[1] - b[0]*a[1]
}
vector_cross3 :: proc(a, b: $T/[3]$E) -> (c: T) where IS_NUMERIC(E) {
@(require_results)
vector_cross3 :: proc "contextless" (a, b: $T/[3]$E) -> (c: T) where IS_NUMERIC(E) {
c[0] = a[1]*b[2] - b[1]*a[2]
c[1] = a[2]*b[0] - b[2]*a[0]
c[2] = a[0]*b[1] - b[0]*a[1]
return
}
quaternion_cross :: proc(q1, q2: $Q) -> (q3: Q) where IS_QUATERNION(Q) {
@(require_results)
quaternion_cross :: proc "contextless" (q1, q2: $Q) -> (q3: Q) where IS_QUATERNION(Q) {
q3.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y
q3.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z
q3.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x
@@ -94,49 +104,59 @@ quaternion_cross :: proc(q1, q2: $Q) -> (q3: Q) where IS_QUATERNION(Q) {
vector_cross :: proc{scalar_cross, vector_cross2, vector_cross3}
cross :: proc{scalar_cross, vector_cross2, vector_cross3, quaternion_cross}
vector_normalize :: proc(v: $T/[$N]$E) -> T where IS_FLOAT(E) {
@(require_results)
vector_normalize :: proc "contextless" (v: $T/[$N]$E) -> T where IS_FLOAT(E) {
return v / length(v)
}
quaternion_normalize :: proc(q: $Q) -> Q where IS_QUATERNION(Q) {
@(require_results)
quaternion_normalize :: proc "contextless" (q: $Q) -> Q where IS_QUATERNION(Q) {
return q/abs(q)
}
normalize :: proc{vector_normalize, quaternion_normalize}
vector_normalize0 :: proc(v: $T/[$N]$E) -> T where IS_FLOAT(E) {
@(require_results)
vector_normalize0 :: proc "contextless" (v: $T/[$N]$E) -> T where IS_FLOAT(E) {
m := length(v)
return 0 if m == 0 else v/m
}
quaternion_normalize0 :: proc(q: $Q) -> Q where IS_QUATERNION(Q) {
@(require_results)
quaternion_normalize0 :: proc "contextless" (q: $Q) -> Q where IS_QUATERNION(Q) {
m := abs(q)
return 0 if m == 0 else q/m
}
normalize0 :: proc{vector_normalize0, quaternion_normalize0}
vector_length :: proc(v: $T/[$N]$E) -> E where IS_FLOAT(E) {
@(require_results)
vector_length :: proc "contextless" (v: $T/[$N]$E) -> E where IS_FLOAT(E) {
return math.sqrt(dot(v, v))
}
vector_length2 :: proc(v: $T/[$N]$E) -> E where IS_NUMERIC(E) {
@(require_results)
vector_length2 :: proc "contextless" (v: $T/[$N]$E) -> E where IS_NUMERIC(E) {
return dot(v, v)
}
quaternion_length :: proc(q: $Q) -> Q where IS_QUATERNION(Q) {
@(require_results)
quaternion_length :: proc "contextless" (q: $Q) -> Q where IS_QUATERNION(Q) {
return abs(q)
}
quaternion_length2 :: proc(q: $Q) -> Q where IS_QUATERNION(Q) {
@(require_results)
quaternion_length2 :: proc "contextless" (q: $Q) -> Q where IS_QUATERNION(Q) {
return dot(q, q)
}
scalar_triple_product :: proc(a, b, c: $T/[$N]$E) -> E where IS_NUMERIC(E) {
@(require_results)
scalar_triple_product :: proc "contextless" (a, b, c: $T/[$N]$E) -> E where IS_NUMERIC(E) {
// a . (b x c)
// b . (c x a)
// c . (a x b)
return dot(a, cross(b, c))
}
vector_triple_product :: proc(a, b, c: $T/[$N]$E) -> T where IS_NUMERIC(E) {
@(require_results)
vector_triple_product :: proc "contextless" (a, b, c: $T/[$N]$E) -> T where IS_NUMERIC(E) {
// a x (b x c)
// (a . c)b - (a . b)c
return cross(a, cross(b, c))
@@ -146,11 +166,13 @@ vector_triple_product :: proc(a, b, c: $T/[$N]$E) -> T where IS_NUMERIC(E) {
length :: proc{vector_length, quaternion_length}
length2 :: proc{vector_length2, quaternion_length2}
projection :: proc(x, normal: $T/[$N]$E) -> T where IS_NUMERIC(E) {
@(require_results)
projection :: proc "contextless" (x, normal: $T/[$N]$E) -> T where IS_NUMERIC(E) {
return dot(x, normal) / dot(normal, normal) * normal
}
identity :: proc($T: typeid/[$N][N]$E) -> (m: T) #no_bounds_check {
@(require_results)
identity :: proc "contextless" ($T: typeid/[$N][N]$E) -> (m: T) #no_bounds_check {
for i in 0..<N {
m[i][i] = E(1)
}
@@ -160,32 +182,38 @@ identity :: proc($T: typeid/[$N][N]$E) -> (m: T) #no_bounds_check {
trace :: builtin.matrix_trace
transpose :: builtin.transpose
matrix_mul :: proc(a, b: $M/matrix[$N, N]$E) -> (c: M)
@(require_results)
matrix_mul :: proc "contextless" (a, b: $M/matrix[$N, N]$E) -> (c: M)
where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check {
return a * b
}
matrix_comp_mul :: proc(a, b: $M/matrix[$I, $J]$E) -> (c: M)
@(require_results)
matrix_comp_mul :: proc "contextless" (a, b: $M/matrix[$I, $J]$E) -> (c: M)
where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check {
return hadamard_product(a, b)
}
matrix_mul_differ :: proc(a: $A/matrix[$I, $J]$E, b: $B/matrix[J, $K]E) -> (c: matrix[I, K]E)
@(require_results)
matrix_mul_differ :: proc "contextless" (a: $A/matrix[$I, $J]$E, b: $B/matrix[J, $K]E) -> (c: matrix[I, K]E)
where !IS_ARRAY(E), IS_NUMERIC(E), I != K #no_bounds_check {
return a * b
}
matrix_mul_vector :: proc(a: $A/matrix[$I, $J]$E, b: $B/[J]E) -> (c: B)
@(require_results)
matrix_mul_vector :: proc "contextless" (a: $A/matrix[$I, $J]$E, b: $B/[J]E) -> (c: B)
where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check {
return a * b
}
quaternion_mul_quaternion :: proc(q1, q2: $Q) -> Q where IS_QUATERNION(Q) {
@(require_results)
quaternion_mul_quaternion :: proc "contextless" (q1, q2: $Q) -> Q where IS_QUATERNION(Q) {
return q1 * q2
}
quaternion64_mul_vector3 :: proc(q: $Q/quaternion64, v: $V/[3]$F/f16) -> V {
@(require_results)
quaternion64_mul_vector3 :: proc "contextless" (q: $Q/quaternion64, v: $V/[3]$F/f16) -> V {
Raw_Quaternion :: struct {xyz: [3]f16, r: f16}
q := transmute(Raw_Quaternion)q
@@ -194,7 +222,8 @@ quaternion64_mul_vector3 :: proc(q: $Q/quaternion64, v: $V/[3]$F/f16) -> V {
t := cross(2*q.xyz, v)
return V(v + q.r*t + cross(q.xyz, t))
}
quaternion128_mul_vector3 :: proc(q: $Q/quaternion128, v: $V/[3]$F/f32) -> V {
@(require_results)
quaternion128_mul_vector3 :: proc "contextless" (q: $Q/quaternion128, v: $V/[3]$F/f32) -> V {
Raw_Quaternion :: struct {xyz: [3]f32, r: f32}
q := transmute(Raw_Quaternion)q
@@ -203,7 +232,8 @@ quaternion128_mul_vector3 :: proc(q: $Q/quaternion128, v: $V/[3]$F/f32) -> V {
t := cross(2*q.xyz, v)
return V(v + q.r*t + cross(q.xyz, t))
}
quaternion256_mul_vector3 :: proc(q: $Q/quaternion256, v: $V/[3]$F/f64) -> V {
@(require_results)
quaternion256_mul_vector3 :: proc "contextless" (q: $Q/quaternion256, v: $V/[3]$F/f64) -> V {
Raw_Quaternion :: struct {xyz: [3]f64, r: f64}
q := transmute(Raw_Quaternion)q
@@ -224,10 +254,12 @@ mul :: proc{
quaternion_mul_quaternion,
}
vector_to_ptr :: proc(v: ^$V/[$N]$E) -> ^E where IS_NUMERIC(E), N > 0 #no_bounds_check {
@(require_results)
vector_to_ptr :: proc "contextless" (v: ^$V/[$N]$E) -> ^E where IS_NUMERIC(E), N > 0 #no_bounds_check {
return &v[0]
}
matrix_to_ptr :: proc(m: ^$A/matrix[$I, $J]$E) -> ^E where IS_NUMERIC(E), I > 0, J > 0 #no_bounds_check {
@(require_results)
matrix_to_ptr :: proc "contextless" (m: ^$A/matrix[$I, $J]$E) -> ^E where IS_NUMERIC(E), I > 0, J > 0 #no_bounds_check {
return &m[0, 0]
}
@@ -239,7 +271,8 @@ to_ptr :: proc{vector_to_ptr, matrix_to_ptr}
// Splines
vector_slerp :: proc(x, y: $T/[$N]$E, a: E) -> T {
@(require_results)
vector_slerp :: proc "contextless" (x, y: $T/[$N]$E, a: E) -> T {
cos_alpha := dot(x, y)
alpha := math.acos(cos_alpha)
sin_alpha := math.sin(alpha)
@@ -250,7 +283,8 @@ vector_slerp :: proc(x, y: $T/[$N]$E, a: E) -> T {
return x * t1 + y * t2
}
catmull_rom :: proc(v1, v2, v3, v4: $T/[$N]$E, s: E) -> T {
@(require_results)
catmull_rom :: proc "contextless" (v1, v2, v3, v4: $T/[$N]$E, s: E) -> T {
s2 := s*s
s3 := s2*s
@@ -262,7 +296,8 @@ catmull_rom :: proc(v1, v2, v3, v4: $T/[$N]$E, s: E) -> T {
return (f1 * v1 + f2 * v2 + f3 * v3 + f4 * v4) * 0.5
}
hermite :: proc(v1, t1, v2, t2: $T/[$N]$E, s: E) -> T {
@(require_results)
hermite :: proc "contextless" (v1, t1, v2, t2: $T/[$N]$E, s: E) -> T {
s2 := s*s
s3 := s2*s
@@ -274,20 +309,23 @@ hermite :: proc(v1, t1, v2, t2: $T/[$N]$E, s: E) -> T {
return f1 * v1 + f2 * v2 + f3 * t1 + f4 * t2
}
cubic :: proc(v1, v2, v3, v4: $T/[$N]$E, s: E) -> T {
@(require_results)
cubic :: proc "contextless" (v1, v2, v3, v4: $T/[$N]$E, s: E) -> T {
return ((v1 * s + v2) * s + v3) * s + v4
}
array_cast :: proc(v: $A/[$N]$T, $Elem_Type: typeid) -> (w: [N]Elem_Type) #no_bounds_check {
@(require_results)
array_cast :: proc "contextless" (v: $A/[$N]$T, $Elem_Type: typeid) -> (w: [N]Elem_Type) #no_bounds_check {
for i in 0..<N {
w[i] = Elem_Type(v[i])
}
return
}
matrix_cast :: proc(v: $A/matrix[$M, $N]$T, $Elem_Type: typeid) -> (w: matrix[M, N]Elem_Type) #no_bounds_check {
@(require_results)
matrix_cast :: proc "contextless" (v: $A/matrix[$M, $N]$T, $Elem_Type: typeid) -> (w: matrix[M, N]Elem_Type) #no_bounds_check {
for j in 0..<N {
for i in 0..<M {
w[i, j] = Elem_Type(v[i, j])
@@ -296,24 +334,24 @@ matrix_cast :: proc(v: $A/matrix[$M, $N]$T, $Elem_Type: typeid) -> (w: matrix[M,
return
}
to_f32 :: #force_inline proc(v: $A/[$N]$T) -> [N]f32 { return array_cast(v, f32) }
to_f64 :: #force_inline proc(v: $A/[$N]$T) -> [N]f64 { return array_cast(v, f64) }
@(require_results) to_f32 :: #force_inline proc(v: $A/[$N]$T) -> [N]f32 { return array_cast(v, f32) }
@(require_results) to_f64 :: #force_inline proc(v: $A/[$N]$T) -> [N]f64 { return array_cast(v, f64) }
to_i8 :: #force_inline proc(v: $A/[$N]$T) -> [N]i8 { return array_cast(v, i8) }
to_i16 :: #force_inline proc(v: $A/[$N]$T) -> [N]i16 { return array_cast(v, i16) }
to_i32 :: #force_inline proc(v: $A/[$N]$T) -> [N]i32 { return array_cast(v, i32) }
to_i64 :: #force_inline proc(v: $A/[$N]$T) -> [N]i64 { return array_cast(v, i64) }
to_int :: #force_inline proc(v: $A/[$N]$T) -> [N]int { return array_cast(v, int) }
@(require_results) to_i8 :: #force_inline proc(v: $A/[$N]$T) -> [N]i8 { return array_cast(v, i8) }
@(require_results) to_i16 :: #force_inline proc(v: $A/[$N]$T) -> [N]i16 { return array_cast(v, i16) }
@(require_results) to_i32 :: #force_inline proc(v: $A/[$N]$T) -> [N]i32 { return array_cast(v, i32) }
@(require_results) to_i64 :: #force_inline proc(v: $A/[$N]$T) -> [N]i64 { return array_cast(v, i64) }
@(require_results) to_int :: #force_inline proc(v: $A/[$N]$T) -> [N]int { return array_cast(v, int) }
to_u8 :: #force_inline proc(v: $A/[$N]$T) -> [N]u8 { return array_cast(v, u8) }
to_u16 :: #force_inline proc(v: $A/[$N]$T) -> [N]u16 { return array_cast(v, u16) }
to_u32 :: #force_inline proc(v: $A/[$N]$T) -> [N]u32 { return array_cast(v, u32) }
to_u64 :: #force_inline proc(v: $A/[$N]$T) -> [N]u64 { return array_cast(v, u64) }
to_uint :: #force_inline proc(v: $A/[$N]$T) -> [N]uint { return array_cast(v, uint) }
@(require_results) to_u8 :: #force_inline proc(v: $A/[$N]$T) -> [N]u8 { return array_cast(v, u8) }
@(require_results) to_u16 :: #force_inline proc(v: $A/[$N]$T) -> [N]u16 { return array_cast(v, u16) }
@(require_results) to_u32 :: #force_inline proc(v: $A/[$N]$T) -> [N]u32 { return array_cast(v, u32) }
@(require_results) to_u64 :: #force_inline proc(v: $A/[$N]$T) -> [N]u64 { return array_cast(v, u64) }
@(require_results) to_uint :: #force_inline proc(v: $A/[$N]$T) -> [N]uint { return array_cast(v, uint) }
to_complex32 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex32 { return array_cast(v, complex32) }
to_complex64 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex64 { return array_cast(v, complex64) }
to_complex128 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex128 { return array_cast(v, complex128) }
to_quaternion64 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion64 { return array_cast(v, quaternion64) }
to_quaternion128 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion128 { return array_cast(v, quaternion128) }
to_quaternion256 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion256 { return array_cast(v, quaternion256) }
@(require_results) to_complex32 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex32 { return array_cast(v, complex32) }
@(require_results) to_complex64 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex64 { return array_cast(v, complex64) }
@(require_results) to_complex128 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex128 { return array_cast(v, complex128) }
@(require_results) to_quaternion64 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion64 { return array_cast(v, quaternion64) }
@(require_results) to_quaternion128 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion128 { return array_cast(v, quaternion128) }
@(require_results) to_quaternion256 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion256 { return array_cast(v, quaternion256) }
File diff suppressed because it is too large Load Diff
+50 -48
View File
@@ -2,30 +2,31 @@ package math_linalg_glsl
import "core:math"
cos_f32 :: proc "c" (x: f32) -> f32 { return math.cos(x) }
sin_f32 :: proc "c" (x: f32) -> f32 { return math.sin(x) }
tan_f32 :: proc "c" (x: f32) -> f32 { return math.tan(x) }
acos_f32 :: proc "c" (x: f32) -> f32 { return math.acos(x) }
asin_f32 :: proc "c" (x: f32) -> f32 { return math.asin(x) }
atan_f32 :: proc "c" (x: f32) -> f32 { return math.atan(x) }
atan2_f32 :: proc "c" (y, x: f32) -> f32 { return math.atan2(y, x) }
cosh_f32 :: proc "c" (x: f32) -> f32 { return math.cosh(x) }
sinh_f32 :: proc "c" (x: f32) -> f32 { return math.sinh(x) }
tanh_f32 :: proc "c" (x: f32) -> f32 { return math.tanh(x) }
acosh_f32 :: proc "c" (x: f32) -> f32 { return math.acosh(x) }
asinh_f32 :: proc "c" (x: f32) -> f32 { return math.asinh(x) }
atanh_f32 :: proc "c" (x: f32) -> f32 { return math.atanh(x) }
sqrt_f32 :: proc "c" (x: f32) -> f32 { return math.sqrt(x) }
inversesqrt_f32 :: proc "c" (x: f32) -> f32 { return 1.0/math.sqrt(x) }
pow_f32 :: proc "c" (x, y: f32) -> f32 { return math.pow(x, y) }
exp_f32 :: proc "c" (x: f32) -> f32 { return math.exp(x) }
log_f32 :: proc "c" (x: f32) -> f32 { return math.ln(x) }
exp2_f32 :: proc "c" (x: f32) -> f32 { return math.pow(f32(2), x) }
sign_f32 :: proc "c" (x: f32) -> f32 { return math.sign(x) }
floor_f32 :: proc "c" (x: f32) -> f32 { return math.floor(x) }
round_f32 :: proc "c" (x: f32) -> f32 { return math.round(x) }
ceil_f32 :: proc "c" (x: f32) -> f32 { return math.ceil(x) }
mod_f32 :: proc "c" (x, y: f32) -> f32 { return math.mod(x, y) }
@(require_results) cos_f32 :: proc "c" (x: f32) -> f32 { return math.cos(x) }
@(require_results) sin_f32 :: proc "c" (x: f32) -> f32 { return math.sin(x) }
@(require_results) tan_f32 :: proc "c" (x: f32) -> f32 { return math.tan(x) }
@(require_results) acos_f32 :: proc "c" (x: f32) -> f32 { return math.acos(x) }
@(require_results) asin_f32 :: proc "c" (x: f32) -> f32 { return math.asin(x) }
@(require_results) atan_f32 :: proc "c" (x: f32) -> f32 { return math.atan(x) }
@(require_results) atan2_f32 :: proc "c" (y, x: f32) -> f32 { return math.atan2(y, x) }
@(require_results) cosh_f32 :: proc "c" (x: f32) -> f32 { return math.cosh(x) }
@(require_results) sinh_f32 :: proc "c" (x: f32) -> f32 { return math.sinh(x) }
@(require_results) tanh_f32 :: proc "c" (x: f32) -> f32 { return math.tanh(x) }
@(require_results) acosh_f32 :: proc "c" (x: f32) -> f32 { return math.acosh(x) }
@(require_results) asinh_f32 :: proc "c" (x: f32) -> f32 { return math.asinh(x) }
@(require_results) atanh_f32 :: proc "c" (x: f32) -> f32 { return math.atanh(x) }
@(require_results) sqrt_f32 :: proc "c" (x: f32) -> f32 { return math.sqrt(x) }
@(require_results) inversesqrt_f32 :: proc "c" (x: f32) -> f32 { return 1.0/math.sqrt(x) }
@(require_results) pow_f32 :: proc "c" (x, y: f32) -> f32 { return math.pow(x, y) }
@(require_results) exp_f32 :: proc "c" (x: f32) -> f32 { return math.exp(x) }
@(require_results) log_f32 :: proc "c" (x: f32) -> f32 { return math.ln(x) }
@(require_results) exp2_f32 :: proc "c" (x: f32) -> f32 { return math.pow(f32(2), x) }
@(require_results) sign_f32 :: proc "c" (x: f32) -> f32 { return math.sign(x) }
@(require_results) floor_f32 :: proc "c" (x: f32) -> f32 { return math.floor(x) }
@(require_results) round_f32 :: proc "c" (x: f32) -> f32 { return math.round(x) }
@(require_results) ceil_f32 :: proc "c" (x: f32) -> f32 { return math.ceil(x) }
@(require_results) mod_f32 :: proc "c" (x, y: f32) -> f32 { return math.mod(x, y) }
@(require_results)
fract_f32 :: proc "c" (x: f32) -> f32 {
if x >= 0 {
return x - math.trunc(x)
@@ -33,30 +34,31 @@ fract_f32 :: proc "c" (x: f32) -> f32 {
return math.trunc(-x) + x
}
cos_f64 :: proc "c" (x: f64) -> f64 { return math.cos(x) }
sin_f64 :: proc "c" (x: f64) -> f64 { return math.sin(x) }
tan_f64 :: proc "c" (x: f64) -> f64 { return math.tan(x) }
acos_f64 :: proc "c" (x: f64) -> f64 { return math.acos(x) }
asin_f64 :: proc "c" (x: f64) -> f64 { return math.asin(x) }
atan_f64 :: proc "c" (x: f64) -> f64 { return math.atan(x) }
atan2_f64 :: proc "c" (y, x: f64) -> f64 { return math.atan2(y, x) }
cosh_f64 :: proc "c" (x: f64) -> f64 { return math.cosh(x) }
sinh_f64 :: proc "c" (x: f64) -> f64 { return math.sinh(x) }
tanh_f64 :: proc "c" (x: f64) -> f64 { return math.tanh(x) }
acosh_f64 :: proc "c" (x: f64) -> f64 { return math.acosh(x) }
asinh_f64 :: proc "c" (x: f64) -> f64 { return math.asinh(x) }
atanh_f64 :: proc "c" (x: f64) -> f64 { return math.atanh(x) }
sqrt_f64 :: proc "c" (x: f64) -> f64 { return math.sqrt(x) }
inversesqrt_f64 :: proc "c" (x: f64) -> f64 { return 1.0/math.sqrt(x) }
pow_f64 :: proc "c" (x, y: f64) -> f64 { return math.pow(x, y) }
exp_f64 :: proc "c" (x: f64) -> f64 { return math.exp(x) }
log_f64 :: proc "c" (x: f64) -> f64 { return math.ln(x) }
exp2_f64 :: proc "c" (x: f64) -> f64 { return math.pow(f64(2), x) }
sign_f64 :: proc "c" (x: f64) -> f64 { return math.sign(x) }
floor_f64 :: proc "c" (x: f64) -> f64 { return math.floor(x) }
round_f64 :: proc "c" (x: f64) -> f64 { return math.round(x) }
ceil_f64 :: proc "c" (x: f64) -> f64 { return math.ceil(x) }
mod_f64 :: proc "c" (x, y: f64) -> f64 { return math.mod(x, y) }
@(require_results) cos_f64 :: proc "c" (x: f64) -> f64 { return math.cos(x) }
@(require_results) sin_f64 :: proc "c" (x: f64) -> f64 { return math.sin(x) }
@(require_results) tan_f64 :: proc "c" (x: f64) -> f64 { return math.tan(x) }
@(require_results) acos_f64 :: proc "c" (x: f64) -> f64 { return math.acos(x) }
@(require_results) asin_f64 :: proc "c" (x: f64) -> f64 { return math.asin(x) }
@(require_results) atan_f64 :: proc "c" (x: f64) -> f64 { return math.atan(x) }
@(require_results) atan2_f64 :: proc "c" (y, x: f64) -> f64 { return math.atan2(y, x) }
@(require_results) cosh_f64 :: proc "c" (x: f64) -> f64 { return math.cosh(x) }
@(require_results) sinh_f64 :: proc "c" (x: f64) -> f64 { return math.sinh(x) }
@(require_results) tanh_f64 :: proc "c" (x: f64) -> f64 { return math.tanh(x) }
@(require_results) acosh_f64 :: proc "c" (x: f64) -> f64 { return math.acosh(x) }
@(require_results) asinh_f64 :: proc "c" (x: f64) -> f64 { return math.asinh(x) }
@(require_results) atanh_f64 :: proc "c" (x: f64) -> f64 { return math.atanh(x) }
@(require_results) sqrt_f64 :: proc "c" (x: f64) -> f64 { return math.sqrt(x) }
@(require_results) inversesqrt_f64 :: proc "c" (x: f64) -> f64 { return 1.0/math.sqrt(x) }
@(require_results) pow_f64 :: proc "c" (x, y: f64) -> f64 { return math.pow(x, y) }
@(require_results) exp_f64 :: proc "c" (x: f64) -> f64 { return math.exp(x) }
@(require_results) log_f64 :: proc "c" (x: f64) -> f64 { return math.ln(x) }
@(require_results) exp2_f64 :: proc "c" (x: f64) -> f64 { return math.pow(f64(2), x) }
@(require_results) sign_f64 :: proc "c" (x: f64) -> f64 { return math.sign(x) }
@(require_results) floor_f64 :: proc "c" (x: f64) -> f64 { return math.floor(x) }
@(require_results) round_f64 :: proc "c" (x: f64) -> f64 { return math.round(x) }
@(require_results) ceil_f64 :: proc "c" (x: f64) -> f64 { return math.ceil(x) }
@(require_results) mod_f64 :: proc "c" (x, y: f64) -> f64 { return math.mod(x, y) }
@(require_results)
fract_f64 :: proc "c" (x: f64) -> f64 {
if x >= 0 {
return x - math.trunc(x)
File diff suppressed because it is too large Load Diff
+58 -56
View File
@@ -2,34 +2,35 @@ package math_linalg_hlsl
import "core:math"
cos_float :: proc "c" (x: float) -> float { return math.cos(x) }
sin_float :: proc "c" (x: float) -> float { return math.sin(x) }
tan_float :: proc "c" (x: float) -> float { return math.tan(x) }
acos_float :: proc "c" (x: float) -> float { return math.acos(x) }
asin_float :: proc "c" (x: float) -> float { return math.asin(x) }
atan_float :: proc "c" (x: float) -> float { return math.atan(x) }
atan2_float :: proc "c" (y, x: float) -> float { return math.atan2(y, x) }
cosh_float :: proc "c" (x: float) -> float { return math.cosh(x) }
sinh_float :: proc "c" (x: float) -> float { return math.sinh(x) }
tanh_float :: proc "c" (x: float) -> float { return math.tanh(x) }
acosh_float :: proc "c" (x: float) -> float { return math.acosh(x) }
asinh_float :: proc "c" (x: float) -> float { return math.asinh(x) }
atanh_float :: proc "c" (x: float) -> float { return math.atanh(x) }
sqrt_float :: proc "c" (x: float) -> float { return math.sqrt(x) }
rsqrt_float :: proc "c" (x: float) -> float { return 1.0/math.sqrt(x) }
rcp_float :: proc "c" (x: float) -> float { return 1.0/x }
pow_float :: proc "c" (x, y: float) -> float { return math.pow(x, y) }
exp_float :: proc "c" (x: float) -> float { return math.exp(x) }
log_float :: proc "c" (x: float) -> float { return math.ln(x) }
log2_float :: proc "c" (x: float) -> float { return math.log(x, 2) }
log10_float :: proc "c" (x: float) -> float { return math.log(x, 10) }
exp2_float :: proc "c" (x: float) -> float { return math.pow(float(2), x) }
sign_float :: proc "c" (x: float) -> float { return math.sign(x) }
floor_float :: proc "c" (x: float) -> float { return math.floor(x) }
round_float :: proc "c" (x: float) -> float { return math.round(x) }
ceil_float :: proc "c" (x: float) -> float { return math.ceil(x) }
isnan_float :: proc "c" (x: float) -> bool { return math.classify(x) == .NaN}
fmod_float :: proc "c" (x, y: float) -> float { return math.mod(x, y) }
@(require_results) cos_float :: proc "c" (x: float) -> float { return math.cos(x) }
@(require_results) sin_float :: proc "c" (x: float) -> float { return math.sin(x) }
@(require_results) tan_float :: proc "c" (x: float) -> float { return math.tan(x) }
@(require_results) acos_float :: proc "c" (x: float) -> float { return math.acos(x) }
@(require_results) asin_float :: proc "c" (x: float) -> float { return math.asin(x) }
@(require_results) atan_float :: proc "c" (x: float) -> float { return math.atan(x) }
@(require_results) atan2_float :: proc "c" (y, x: float) -> float { return math.atan2(y, x) }
@(require_results) cosh_float :: proc "c" (x: float) -> float { return math.cosh(x) }
@(require_results) sinh_float :: proc "c" (x: float) -> float { return math.sinh(x) }
@(require_results) tanh_float :: proc "c" (x: float) -> float { return math.tanh(x) }
@(require_results) acosh_float :: proc "c" (x: float) -> float { return math.acosh(x) }
@(require_results) asinh_float :: proc "c" (x: float) -> float { return math.asinh(x) }
@(require_results) atanh_float :: proc "c" (x: float) -> float { return math.atanh(x) }
@(require_results) sqrt_float :: proc "c" (x: float) -> float { return math.sqrt(x) }
@(require_results) rsqrt_float :: proc "c" (x: float) -> float { return 1.0/math.sqrt(x) }
@(require_results) rcp_float :: proc "c" (x: float) -> float { return 1.0/x }
@(require_results) pow_float :: proc "c" (x, y: float) -> float { return math.pow(x, y) }
@(require_results) exp_float :: proc "c" (x: float) -> float { return math.exp(x) }
@(require_results) log_float :: proc "c" (x: float) -> float { return math.ln(x) }
@(require_results) log2_float :: proc "c" (x: float) -> float { return math.log(x, 2) }
@(require_results) log10_float :: proc "c" (x: float) -> float { return math.log(x, 10) }
@(require_results) exp2_float :: proc "c" (x: float) -> float { return math.pow(float(2), x) }
@(require_results) sign_float :: proc "c" (x: float) -> float { return math.sign(x) }
@(require_results) floor_float :: proc "c" (x: float) -> float { return math.floor(x) }
@(require_results) round_float :: proc "c" (x: float) -> float { return math.round(x) }
@(require_results) ceil_float :: proc "c" (x: float) -> float { return math.ceil(x) }
@(require_results) isnan_float :: proc "c" (x: float) -> bool { return math.classify(x) == .NaN}
@(require_results) fmod_float :: proc "c" (x, y: float) -> float { return math.mod(x, y) }
@(require_results)
frac_float :: proc "c" (x: float) -> float {
if x >= 0 {
return x - math.trunc(x)
@@ -38,34 +39,35 @@ frac_float :: proc "c" (x: float) -> float {
}
cos_double :: proc "c" (x: double) -> double { return math.cos(x) }
sin_double :: proc "c" (x: double) -> double { return math.sin(x) }
tan_double :: proc "c" (x: double) -> double { return math.tan(x) }
acos_double :: proc "c" (x: double) -> double { return math.acos(x) }
asin_double :: proc "c" (x: double) -> double { return math.asin(x) }
atan_double :: proc "c" (x: double) -> double { return math.atan(x) }
atan2_double :: proc "c" (y, x: double) -> double { return math.atan2(y, x) }
cosh_double :: proc "c" (x: double) -> double { return math.cosh(x) }
sinh_double :: proc "c" (x: double) -> double { return math.sinh(x) }
tanh_double :: proc "c" (x: double) -> double { return math.tanh(x) }
acosh_double :: proc "c" (x: double) -> double { return math.acosh(x) }
asinh_double :: proc "c" (x: double) -> double { return math.asinh(x) }
atanh_double :: proc "c" (x: double) -> double { return math.atanh(x) }
sqrt_double :: proc "c" (x: double) -> double { return math.sqrt(x) }
rsqrt_double :: proc "c" (x: double) -> double { return 1.0/math.sqrt(x) }
rcp_double :: proc "c" (x: double) -> double { return 1.0/x }
pow_double :: proc "c" (x, y: double) -> double { return math.pow(x, y) }
exp_double :: proc "c" (x: double) -> double { return math.exp(x) }
log_double :: proc "c" (x: double) -> double { return math.ln(x) }
log2_double :: proc "c" (x: double) -> double { return math.log(x, 2) }
log10_double :: proc "c" (x: double) -> double { return math.log(x, 10) }
exp2_double :: proc "c" (x: double) -> double { return math.pow(double(2), x) }
sign_double :: proc "c" (x: double) -> double { return math.sign(x) }
floor_double :: proc "c" (x: double) -> double { return math.floor(x) }
round_double :: proc "c" (x: double) -> double { return math.round(x) }
ceil_double :: proc "c" (x: double) -> double { return math.ceil(x) }
isnan_double :: proc "c" (x: double) -> bool { return math.classify(x) == .NaN}
fmod_double :: proc "c" (x, y: double) -> double { return math.mod(x, y) }
@(require_results) cos_double :: proc "c" (x: double) -> double { return math.cos(x) }
@(require_results) sin_double :: proc "c" (x: double) -> double { return math.sin(x) }
@(require_results) tan_double :: proc "c" (x: double) -> double { return math.tan(x) }
@(require_results) acos_double :: proc "c" (x: double) -> double { return math.acos(x) }
@(require_results) asin_double :: proc "c" (x: double) -> double { return math.asin(x) }
@(require_results) atan_double :: proc "c" (x: double) -> double { return math.atan(x) }
@(require_results) atan2_double :: proc "c" (y, x: double) -> double { return math.atan2(y, x) }
@(require_results) cosh_double :: proc "c" (x: double) -> double { return math.cosh(x) }
@(require_results) sinh_double :: proc "c" (x: double) -> double { return math.sinh(x) }
@(require_results) tanh_double :: proc "c" (x: double) -> double { return math.tanh(x) }
@(require_results) acosh_double :: proc "c" (x: double) -> double { return math.acosh(x) }
@(require_results) asinh_double :: proc "c" (x: double) -> double { return math.asinh(x) }
@(require_results) atanh_double :: proc "c" (x: double) -> double { return math.atanh(x) }
@(require_results) sqrt_double :: proc "c" (x: double) -> double { return math.sqrt(x) }
@(require_results) rsqrt_double :: proc "c" (x: double) -> double { return 1.0/math.sqrt(x) }
@(require_results) rcp_double :: proc "c" (x: double) -> double { return 1.0/x }
@(require_results) pow_double :: proc "c" (x, y: double) -> double { return math.pow(x, y) }
@(require_results) exp_double :: proc "c" (x: double) -> double { return math.exp(x) }
@(require_results) log_double :: proc "c" (x: double) -> double { return math.ln(x) }
@(require_results) log2_double :: proc "c" (x: double) -> double { return math.log(x, 2) }
@(require_results) log10_double :: proc "c" (x: double) -> double { return math.log(x, 10) }
@(require_results) exp2_double :: proc "c" (x: double) -> double { return math.pow(double(2), x) }
@(require_results) sign_double :: proc "c" (x: double) -> double { return math.sign(x) }
@(require_results) floor_double :: proc "c" (x: double) -> double { return math.floor(x) }
@(require_results) round_double :: proc "c" (x: double) -> double { return math.round(x) }
@(require_results) ceil_double :: proc "c" (x: double) -> double { return math.ceil(x) }
@(require_results) isnan_double :: proc "c" (x: double) -> bool { return math.classify(x) == .NaN}
@(require_results) fmod_double :: proc "c" (x, y: double) -> double { return math.mod(x, y) }
@(require_results)
frac_double :: proc "c" (x: double) -> double {
if x >= 0 {
return x - math.trunc(x)
File diff suppressed because it is too large Load Diff
+200 -100
View File
@@ -2,7 +2,8 @@ package linalg
import "core:math"
euler_angles_from_matrix3_f16 :: proc(m: Matrix3f16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) {
switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m)
@@ -19,7 +20,8 @@ euler_angles_from_matrix3_f16 :: proc(m: Matrix3f16, order: Euler_Angle_Order) -
}
return
}
euler_angles_from_matrix4_f16 :: proc(m: Matrix4f16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) {
switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m)
@@ -36,7 +38,8 @@ euler_angles_from_matrix4_f16 :: proc(m: Matrix4f16, order: Euler_Angle_Order) -
}
return
}
euler_angles_from_quaternion_f16 :: proc(m: Quaternionf16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_from_quaternion_f16 :: proc "contextless" (m: Quaternionf16, order: Euler_Angle_Order) -> (t1, t2, t3: f16) {
switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m)
@@ -54,7 +57,8 @@ euler_angles_from_quaternion_f16 :: proc(m: Quaternionf16, order: Euler_Angle_Or
return
}
matrix3_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_f16 :: proc "contextless" (t1, t2, t3: f16, order: Euler_Angle_Order) -> (m: Matrix3f16) {
switch order {
case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3);
case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3);
@@ -71,7 +75,8 @@ matrix3_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order)
}
return
}
matrix4_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_f16 :: proc "contextless" (t1, t2, t3: f16, order: Euler_Angle_Order) -> (m: Matrix4f16) {
switch order {
case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3);
case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3);
@@ -89,7 +94,8 @@ matrix4_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order)
return
}
quaternion_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Order) -> Quaternionf16 {
@(require_results)
quaternion_from_euler_angles_f16 :: proc "contextless" (t1, t2, t3: f16, order: Euler_Angle_Order) -> Quaternionf16 {
X :: quaternion_from_euler_angle_x
Y :: quaternion_from_euler_angle_y
Z :: quaternion_from_euler_angle_z
@@ -117,17 +123,21 @@ quaternion_from_euler_angles_f16 :: proc(t1, t2, t3: f16, order: Euler_Angle_Ord
// Quaternionf16s
quaternion_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (q: Quaternionf16) {
@(require_results)
quaternion_from_euler_angle_x_f16 :: proc "contextless" (angle_x: f16) -> (q: Quaternionf16) {
return quaternion_angle_axis_f16(angle_x, {1, 0, 0})
}
quaternion_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (q: Quaternionf16) {
@(require_results)
quaternion_from_euler_angle_y_f16 :: proc "contextless" (angle_y: f16) -> (q: Quaternionf16) {
return quaternion_angle_axis_f16(angle_y, {0, 1, 0})
}
quaternion_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (q: Quaternionf16) {
@(require_results)
quaternion_from_euler_angle_z_f16 :: proc "contextless" (angle_z: f16) -> (q: Quaternionf16) {
return quaternion_angle_axis_f16(angle_z, {0, 0, 1})
}
quaternion_from_pitch_yaw_roll_f16 :: proc(pitch, yaw, roll: f16) -> Quaternionf16 {
@(require_results)
quaternion_from_pitch_yaw_roll_f16 :: proc "contextless" (pitch, yaw, roll: f16) -> Quaternionf16 {
a, b, c := pitch, yaw, roll
ca, sa := math.cos(a*0.5), math.sin(a*0.5)
@@ -142,11 +152,13 @@ quaternion_from_pitch_yaw_roll_f16 :: proc(pitch, yaw, roll: f16) -> Quaternionf
return q
}
roll_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 {
@(require_results)
roll_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> f16 {
return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z)
}
pitch_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 {
@(require_results)
pitch_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> f16 {
y := 2 * (q.y*q.z + q.w*q.w)
x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z
@@ -157,52 +169,66 @@ pitch_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 {
return math.atan2(y, x)
}
yaw_from_quaternion_f16 :: proc(q: Quaternionf16) -> f16 {
@(require_results)
yaw_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> f16 {
return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1))
}
pitch_yaw_roll_from_quaternion_f16 :: proc(q: Quaternionf16) -> (pitch, yaw, roll: f16) {
@(require_results)
pitch_yaw_roll_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (pitch, yaw, roll: f16) {
pitch = pitch_from_quaternion(q)
yaw = yaw_from_quaternion(q)
roll = roll_from_quaternion(q)
return
}
euler_angles_xyz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_xyz_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_yxz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_yxz_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_xzx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_xzx_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_xyx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_xyx_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_yxy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_yxy_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_yzy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_yzy_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_zyz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_zyz_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_zxz_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_zxz_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_xzy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_xzy_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_yzx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_yzx_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_zyx_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_zyx_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_zxy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_zxy_from_quaternion_f16 :: proc "contextless" (q: Quaternionf16) -> (t1, t2, t3: f16) {
return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q))
}
@@ -210,7 +236,8 @@ euler_angles_zxy_from_quaternion_f16 :: proc(q: Quaternionf16) -> (t1, t2, t3: f
// Matrix3
matrix3_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angle_x_f16 :: proc "contextless" (angle_x: f16) -> (m: Matrix3f16) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
m[0, 0] = 1
m[1, 1] = +cos_x
@@ -219,7 +246,8 @@ matrix3_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (m: Matrix3f16) {
m[2, 2] = +cos_x
return
}
matrix3_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angle_y_f16 :: proc "contextless" (angle_y: f16) -> (m: Matrix3f16) {
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = +cos_y
m[0, 2] = -sin_y
@@ -228,7 +256,8 @@ matrix3_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (m: Matrix3f16) {
m[2, 2] = +cos_y
return
}
matrix3_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angle_z_f16 :: proc "contextless" (angle_z: f16) -> (m: Matrix3f16) {
cos_z, sin_z := math.cos(angle_z), math.sin(angle_z)
m[0, 0] = +cos_z
m[0, 1] = +sin_z
@@ -239,7 +268,8 @@ matrix3_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (m: Matrix3f16) {
}
matrix3_from_derived_euler_angle_x_f16 :: proc(angle_x: f16, angular_velocity_x: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_derived_euler_angle_x_f16 :: proc "contextless" (angle_x: f16, angular_velocity_x: f16) -> (m: Matrix3f16) {
cos_x := math.cos(angle_x) * angular_velocity_x
sin_x := math.sin(angle_x) * angular_velocity_x
m[0, 0] = 1
@@ -249,7 +279,8 @@ matrix3_from_derived_euler_angle_x_f16 :: proc(angle_x: f16, angular_velocity_x:
m[2, 2] = +cos_x
return
}
matrix3_from_derived_euler_angle_y_f16 :: proc(angle_y: f16, angular_velocity_y: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_derived_euler_angle_y_f16 :: proc "contextless" (angle_y: f16, angular_velocity_y: f16) -> (m: Matrix3f16) {
cos_y := math.cos(angle_y) * angular_velocity_y
sin_y := math.sin(angle_y) * angular_velocity_y
m[0, 0] = +cos_y
@@ -259,7 +290,8 @@ matrix3_from_derived_euler_angle_y_f16 :: proc(angle_y: f16, angular_velocity_y:
m[2, 2] = +cos_y
return
}
matrix3_from_derived_euler_angle_z_f16 :: proc(angle_z: f16, angular_velocity_z: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_derived_euler_angle_z_f16 :: proc "contextless" (angle_z: f16, angular_velocity_z: f16) -> (m: Matrix3f16) {
cos_z := math.cos(angle_z) * angular_velocity_z
sin_z := math.sin(angle_z) * angular_velocity_z
m[0, 0] = +cos_z
@@ -271,7 +303,8 @@ matrix3_from_derived_euler_angle_z_f16 :: proc(angle_z: f16, angular_velocity_z:
}
matrix3_from_euler_angles_xy_f16 :: proc(angle_x, angle_y: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_xy_f16 :: proc "contextless" (angle_x, angle_y: f16) -> (m: Matrix3f16) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y
@@ -286,7 +319,8 @@ matrix3_from_euler_angles_xy_f16 :: proc(angle_x, angle_y: f16) -> (m: Matrix3f1
}
matrix3_from_euler_angles_yx_f16 :: proc(angle_y, angle_x: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_yx_f16 :: proc "contextless" (angle_y, angle_x: f16) -> (m: Matrix3f16) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y
@@ -300,21 +334,26 @@ matrix3_from_euler_angles_yx_f16 :: proc(angle_y, angle_x: f16) -> (m: Matrix3f1
return
}
matrix3_from_euler_angles_xz_f16 :: proc(angle_x, angle_z: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_xz_f16 :: proc "contextless" (angle_x, angle_z: f16) -> (m: Matrix3f16) {
return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z))
}
matrix3_from_euler_angles_zx_f16 :: proc(angle_z, angle_x: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_zx_f16 :: proc "contextless" (angle_z, angle_x: f16) -> (m: Matrix3f16) {
return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x))
}
matrix3_from_euler_angles_yz_f16 :: proc(angle_y, angle_z: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_yz_f16 :: proc "contextless" (angle_y, angle_z: f16) -> (m: Matrix3f16) {
return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z))
}
matrix3_from_euler_angles_zy_f16 :: proc(angle_z, angle_y: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_zy_f16 :: proc "contextless" (angle_z, angle_y: f16) -> (m: Matrix3f16) {
return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y))
}
matrix3_from_euler_angles_xyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_xyz_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(-t1)
c2 := math.cos(-t2)
c3 := math.cos(-t3)
@@ -334,7 +373,8 @@ matrix3_from_euler_angles_xyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return
}
matrix3_from_euler_angles_yxz_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_yxz_f16 :: proc "contextless" (yaw, pitch, roll: f16) -> (m: Matrix3f16) {
ch := math.cos(yaw)
sh := math.sin(yaw)
cp := math.cos(pitch)
@@ -354,7 +394,8 @@ matrix3_from_euler_angles_yxz_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix3f
return
}
matrix3_from_euler_angles_xzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_xzx_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -374,7 +415,8 @@ matrix3_from_euler_angles_xzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return
}
matrix3_from_euler_angles_xyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_xyx_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -394,7 +436,8 @@ matrix3_from_euler_angles_xyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return
}
matrix3_from_euler_angles_yxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_yxy_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -414,7 +457,8 @@ matrix3_from_euler_angles_yxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return
}
matrix3_from_euler_angles_yzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_yzy_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -434,7 +478,8 @@ matrix3_from_euler_angles_yzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return
}
matrix3_from_euler_angles_zyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_zyz_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -454,7 +499,8 @@ matrix3_from_euler_angles_zyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return
}
matrix3_from_euler_angles_zxz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_zxz_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -475,7 +521,8 @@ matrix3_from_euler_angles_zxz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
}
matrix3_from_euler_angles_xzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_xzy_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -495,7 +542,8 @@ matrix3_from_euler_angles_xzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return
}
matrix3_from_euler_angles_yzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_yzx_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -515,7 +563,8 @@ matrix3_from_euler_angles_yzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return
}
matrix3_from_euler_angles_zyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_zyx_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -535,7 +584,8 @@ matrix3_from_euler_angles_zyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
return
}
matrix3_from_euler_angles_zxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_euler_angles_zxy_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix3f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -556,7 +606,8 @@ matrix3_from_euler_angles_zxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix3f16) {
}
matrix3_from_yaw_pitch_roll_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix3f16) {
@(require_results)
matrix3_from_yaw_pitch_roll_f16 :: proc "contextless" (yaw, pitch, roll: f16) -> (m: Matrix3f16) {
ch := math.cos(yaw)
sh := math.sin(yaw)
cp := math.cos(pitch)
@@ -576,7 +627,8 @@ matrix3_from_yaw_pitch_roll_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix3f16
return m
}
euler_angles_xyz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_xyz_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[1, 2], m[2, 2])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1])
T2 := math.atan2(-m[0, 2], C2)
@@ -589,7 +641,8 @@ euler_angles_xyz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_yxz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_yxz_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[0, 2], m[2, 2])
C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1])
T2 := math.atan2(-m[1, 2], C2)
@@ -602,7 +655,8 @@ euler_angles_yxz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_xzx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_xzx_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[2, 0], m[1, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0])
@@ -615,7 +669,8 @@ euler_angles_xzx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_xyx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_xyx_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[1, 0], -m[2, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0])
@@ -628,7 +683,8 @@ euler_angles_xyx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_yxy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_yxy_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[0, 1], m[2, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1])
@@ -641,7 +697,8 @@ euler_angles_yxy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_yzy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_yzy_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[2, 1], -m[0, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1])
@@ -653,7 +710,8 @@ euler_angles_yzy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
t3 = T3
return
}
euler_angles_zyz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_zyz_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[1, 2], m[0, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2])
@@ -666,7 +724,8 @@ euler_angles_zyz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_zxz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_zxz_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[0, 2], -m[1, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2])
@@ -679,7 +738,8 @@ euler_angles_zxz_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_xzy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_xzy_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[2, 1], m[1, 1])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2])
T2 := math.atan2(-m[0, 1], C2)
@@ -692,7 +752,8 @@ euler_angles_xzy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_yzx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_yzx_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(-m[2, 0], m[0, 0])
C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2])
T2 := math.atan2(m[1, 0], C2)
@@ -705,7 +766,8 @@ euler_angles_yzx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_zyx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_zyx_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[1, 0], m[0, 0])
C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2])
T2 := math.atan2(-m[2, 0], C2)
@@ -718,7 +780,8 @@ euler_angles_zyx_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_zxy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_zxy_from_matrix3_f16 :: proc "contextless" (m: Matrix3f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(-m[0, 1], m[1, 1])
C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2])
T2 := math.atan2(m[2, 1], C2)
@@ -735,7 +798,8 @@ euler_angles_zxy_from_matrix3_f16 :: proc(m: Matrix3f16) -> (t1, t2, t3: f16) {
// Matrix4
matrix4_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angle_x_f16 :: proc "contextless" (angle_x: f16) -> (m: Matrix4f16) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
m[0, 0] = 1
m[1, 1] = +cos_x
@@ -745,7 +809,8 @@ matrix4_from_euler_angle_x_f16 :: proc(angle_x: f16) -> (m: Matrix4f16) {
m[3, 3] = 1
return
}
matrix4_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angle_y_f16 :: proc "contextless" (angle_y: f16) -> (m: Matrix4f16) {
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = +cos_y
m[0, 2] = -sin_y
@@ -755,7 +820,8 @@ matrix4_from_euler_angle_y_f16 :: proc(angle_y: f16) -> (m: Matrix4f16) {
m[3, 3] = 1
return
}
matrix4_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angle_z_f16 :: proc "contextless" (angle_z: f16) -> (m: Matrix4f16) {
cos_z, sin_z := math.cos(angle_z), math.sin(angle_z)
m[0, 0] = +cos_z
m[0, 1] = +sin_z
@@ -767,7 +833,8 @@ matrix4_from_euler_angle_z_f16 :: proc(angle_z: f16) -> (m: Matrix4f16) {
}
matrix4_from_derived_euler_angle_x_f16 :: proc(angle_x: f16, angular_velocity_x: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_derived_euler_angle_x_f16 :: proc "contextless" (angle_x: f16, angular_velocity_x: f16) -> (m: Matrix4f16) {
cos_x := math.cos(angle_x) * angular_velocity_x
sin_x := math.sin(angle_x) * angular_velocity_x
m[0, 0] = 1
@@ -778,7 +845,8 @@ matrix4_from_derived_euler_angle_x_f16 :: proc(angle_x: f16, angular_velocity_x:
m[3, 3] = 1
return
}
matrix4_from_derived_euler_angle_y_f16 :: proc(angle_y: f16, angular_velocity_y: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_derived_euler_angle_y_f16 :: proc "contextless" (angle_y: f16, angular_velocity_y: f16) -> (m: Matrix4f16) {
cos_y := math.cos(angle_y) * angular_velocity_y
sin_y := math.sin(angle_y) * angular_velocity_y
m[0, 0] = +cos_y
@@ -789,7 +857,8 @@ matrix4_from_derived_euler_angle_y_f16 :: proc(angle_y: f16, angular_velocity_y:
m[3, 3] = 1
return
}
matrix4_from_derived_euler_angle_z_f16 :: proc(angle_z: f16, angular_velocity_z: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_derived_euler_angle_z_f16 :: proc "contextless" (angle_z: f16, angular_velocity_z: f16) -> (m: Matrix4f16) {
cos_z := math.cos(angle_z) * angular_velocity_z
sin_z := math.sin(angle_z) * angular_velocity_z
m[0, 0] = +cos_z
@@ -802,7 +871,8 @@ matrix4_from_derived_euler_angle_z_f16 :: proc(angle_z: f16, angular_velocity_z:
}
matrix4_from_euler_angles_xy_f16 :: proc(angle_x, angle_y: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_xy_f16 :: proc "contextless" (angle_x, angle_y: f16) -> (m: Matrix4f16) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y
@@ -818,7 +888,8 @@ matrix4_from_euler_angles_xy_f16 :: proc(angle_x, angle_y: f16) -> (m: Matrix4f1
}
matrix4_from_euler_angles_yx_f16 :: proc(angle_y, angle_x: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_yx_f16 :: proc "contextless" (angle_y, angle_x: f16) -> (m: Matrix4f16) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y
@@ -833,21 +904,26 @@ matrix4_from_euler_angles_yx_f16 :: proc(angle_y, angle_x: f16) -> (m: Matrix4f1
return
}
matrix4_from_euler_angles_xz_f16 :: proc(angle_x, angle_z: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_xz_f16 :: proc "contextless" (angle_x, angle_z: f16) -> (m: Matrix4f16) {
return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z))
}
matrix4_from_euler_angles_zx_f16 :: proc(angle_z, angle_x: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_zx_f16 :: proc "contextless" (angle_z, angle_x: f16) -> (m: Matrix4f16) {
return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x))
}
matrix4_from_euler_angles_yz_f16 :: proc(angle_y, angle_z: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_yz_f16 :: proc "contextless" (angle_y, angle_z: f16) -> (m: Matrix4f16) {
return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z))
}
matrix4_from_euler_angles_zy_f16 :: proc(angle_z, angle_y: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_zy_f16 :: proc "contextless" (angle_z, angle_y: f16) -> (m: Matrix4f16) {
return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y))
}
matrix4_from_euler_angles_xyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_xyz_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(-t1)
c2 := math.cos(-t2)
c3 := math.cos(-t3)
@@ -874,7 +950,8 @@ matrix4_from_euler_angles_xyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return
}
matrix4_from_euler_angles_yxz_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_yxz_f16 :: proc "contextless" (yaw, pitch, roll: f16) -> (m: Matrix4f16) {
ch := math.cos(yaw)
sh := math.sin(yaw)
cp := math.cos(pitch)
@@ -901,7 +978,8 @@ matrix4_from_euler_angles_yxz_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix4f
return
}
matrix4_from_euler_angles_xzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_xzx_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -928,7 +1006,8 @@ matrix4_from_euler_angles_xzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return
}
matrix4_from_euler_angles_xyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_xyx_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -955,7 +1034,8 @@ matrix4_from_euler_angles_xyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return
}
matrix4_from_euler_angles_yxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_yxy_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -982,7 +1062,8 @@ matrix4_from_euler_angles_yxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return
}
matrix4_from_euler_angles_yzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_yzy_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1009,7 +1090,8 @@ matrix4_from_euler_angles_yzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return
}
matrix4_from_euler_angles_zyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_zyz_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1036,7 +1118,8 @@ matrix4_from_euler_angles_zyz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return
}
matrix4_from_euler_angles_zxz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_zxz_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1064,7 +1147,8 @@ matrix4_from_euler_angles_zxz_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
}
matrix4_from_euler_angles_xzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_xzy_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1091,7 +1175,8 @@ matrix4_from_euler_angles_xzy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return
}
matrix4_from_euler_angles_yzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_yzx_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1118,7 +1203,8 @@ matrix4_from_euler_angles_yzx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return
}
matrix4_from_euler_angles_zyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_zyx_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1145,7 +1231,8 @@ matrix4_from_euler_angles_zyx_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
return
}
matrix4_from_euler_angles_zxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_euler_angles_zxy_f16 :: proc "contextless" (t1, t2, t3: f16) -> (m: Matrix4f16) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1173,7 +1260,8 @@ matrix4_from_euler_angles_zxy_f16 :: proc(t1, t2, t3: f16) -> (m: Matrix4f16) {
}
matrix4_from_yaw_pitch_roll_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix4f16) {
@(require_results)
matrix4_from_yaw_pitch_roll_f16 :: proc "contextless" (yaw, pitch, roll: f16) -> (m: Matrix4f16) {
ch := math.cos(yaw)
sh := math.sin(yaw)
cp := math.cos(pitch)
@@ -1200,7 +1288,8 @@ matrix4_from_yaw_pitch_roll_f16 :: proc(yaw, pitch, roll: f16) -> (m: Matrix4f16
return m
}
euler_angles_xyz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_xyz_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[1, 2], m[2, 2])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1])
T2 := math.atan2(-m[0, 2], C2)
@@ -1213,7 +1302,8 @@ euler_angles_xyz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_yxz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_yxz_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[0, 2], m[2, 2])
C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1])
T2 := math.atan2(-m[1, 2], C2)
@@ -1226,7 +1316,8 @@ euler_angles_yxz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_xzx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_xzx_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[2, 0], m[1, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0])
@@ -1239,7 +1330,8 @@ euler_angles_xzx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_xyx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_xyx_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[1, 0], -m[2, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0])
@@ -1252,7 +1344,8 @@ euler_angles_xyx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_yxy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_yxy_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[0, 1], m[2, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1])
@@ -1265,7 +1358,8 @@ euler_angles_yxy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_yzy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_yzy_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[2, 1], -m[0, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1])
@@ -1277,7 +1371,8 @@ euler_angles_yzy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
t3 = T3
return
}
euler_angles_zyz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_zyz_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[1, 2], m[0, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2])
@@ -1290,7 +1385,8 @@ euler_angles_zyz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_zxz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_zxz_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[0, 2], -m[1, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2])
@@ -1303,7 +1399,8 @@ euler_angles_zxz_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_xzy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_xzy_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[2, 1], m[1, 1])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2])
T2 := math.atan2(-m[0, 1], C2)
@@ -1316,7 +1413,8 @@ euler_angles_xzy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_yzx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_yzx_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(-m[2, 0], m[0, 0])
C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2])
T2 := math.atan2(m[1, 0], C2)
@@ -1329,7 +1427,8 @@ euler_angles_yzx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_zyx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_zyx_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(m[1, 0], m[0, 0])
C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2])
T2 := math.atan2(-m[2, 0], C2)
@@ -1342,7 +1441,8 @@ euler_angles_zyx_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
return
}
euler_angles_zxy_from_matrix4_f16 :: proc(m: Matrix4f16) -> (t1, t2, t3: f16) {
@(require_results)
euler_angles_zxy_from_matrix4_f16 :: proc "contextless" (m: Matrix4f16) -> (t1, t2, t3: f16) {
T1 := math.atan2(-m[0, 1], m[1, 1])
C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2])
T2 := math.atan2(m[2, 1], C2)
+200 -100
View File
@@ -2,7 +2,8 @@ package linalg
import "core:math"
euler_angles_from_matrix3_f32 :: proc(m: Matrix3f32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) {
switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m)
@@ -19,7 +20,8 @@ euler_angles_from_matrix3_f32 :: proc(m: Matrix3f32, order: Euler_Angle_Order) -
}
return
}
euler_angles_from_matrix4_f32 :: proc(m: Matrix4f32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) {
switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m)
@@ -36,7 +38,8 @@ euler_angles_from_matrix4_f32 :: proc(m: Matrix4f32, order: Euler_Angle_Order) -
}
return
}
euler_angles_from_quaternion_f32 :: proc(m: Quaternionf32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_from_quaternion_f32 :: proc "contextless" (m: Quaternionf32, order: Euler_Angle_Order) -> (t1, t2, t3: f32) {
switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m)
@@ -54,7 +57,8 @@ euler_angles_from_quaternion_f32 :: proc(m: Quaternionf32, order: Euler_Angle_Or
return
}
matrix3_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Order) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_f32 :: proc "contextless" (t1, t2, t3: f32, order: Euler_Angle_Order) -> (m: Matrix3f32) {
switch order {
case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3);
case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3);
@@ -71,7 +75,8 @@ matrix3_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Order)
}
return
}
matrix4_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Order) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_f32 :: proc "contextless" (t1, t2, t3: f32, order: Euler_Angle_Order) -> (m: Matrix4f32) {
switch order {
case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3);
case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3);
@@ -89,7 +94,8 @@ matrix4_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Order)
return
}
quaternion_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Order) -> Quaternionf32 {
@(require_results)
quaternion_from_euler_angles_f32 :: proc "contextless" (t1, t2, t3: f32, order: Euler_Angle_Order) -> Quaternionf32 {
X :: quaternion_from_euler_angle_x
Y :: quaternion_from_euler_angle_y
Z :: quaternion_from_euler_angle_z
@@ -117,17 +123,21 @@ quaternion_from_euler_angles_f32 :: proc(t1, t2, t3: f32, order: Euler_Angle_Ord
// Quaternionf32s
quaternion_from_euler_angle_x_f32 :: proc(angle_x: f32) -> (q: Quaternionf32) {
@(require_results)
quaternion_from_euler_angle_x_f32 :: proc "contextless" (angle_x: f32) -> (q: Quaternionf32) {
return quaternion_angle_axis_f32(angle_x, {1, 0, 0})
}
quaternion_from_euler_angle_y_f32 :: proc(angle_y: f32) -> (q: Quaternionf32) {
@(require_results)
quaternion_from_euler_angle_y_f32 :: proc "contextless" (angle_y: f32) -> (q: Quaternionf32) {
return quaternion_angle_axis_f32(angle_y, {0, 1, 0})
}
quaternion_from_euler_angle_z_f32 :: proc(angle_z: f32) -> (q: Quaternionf32) {
@(require_results)
quaternion_from_euler_angle_z_f32 :: proc "contextless" (angle_z: f32) -> (q: Quaternionf32) {
return quaternion_angle_axis_f32(angle_z, {0, 0, 1})
}
quaternion_from_pitch_yaw_roll_f32 :: proc(pitch, yaw, roll: f32) -> Quaternionf32 {
@(require_results)
quaternion_from_pitch_yaw_roll_f32 :: proc "contextless" (pitch, yaw, roll: f32) -> Quaternionf32 {
a, b, c := pitch, yaw, roll
ca, sa := math.cos(a*0.5), math.sin(a*0.5)
@@ -142,11 +152,13 @@ quaternion_from_pitch_yaw_roll_f32 :: proc(pitch, yaw, roll: f32) -> Quaternionf
return q
}
roll_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 {
@(require_results)
roll_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> f32 {
return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z)
}
pitch_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 {
@(require_results)
pitch_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> f32 {
y := 2 * (q.y*q.z + q.w*q.w)
x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z
@@ -157,52 +169,66 @@ pitch_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 {
return math.atan2(y, x)
}
yaw_from_quaternion_f32 :: proc(q: Quaternionf32) -> f32 {
@(require_results)
yaw_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> f32 {
return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1))
}
pitch_yaw_roll_from_quaternion_f32 :: proc(q: Quaternionf32) -> (pitch, yaw, roll: f32) {
@(require_results)
pitch_yaw_roll_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (pitch, yaw, roll: f32) {
pitch = pitch_from_quaternion(q)
yaw = yaw_from_quaternion(q)
roll = roll_from_quaternion(q)
return
}
euler_angles_xyz_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_xyz_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_yxz_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_yxz_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_xzx_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_xzx_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_xyx_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_xyx_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_yxy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_yxy_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_yzy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_yzy_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_zyz_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_zyz_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_zxz_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_zxz_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_xzy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_xzy_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_yzx_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_yzx_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_zyx_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_zyx_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_zxy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_zxy_from_quaternion_f32 :: proc "contextless" (q: Quaternionf32) -> (t1, t2, t3: f32) {
return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q))
}
@@ -210,7 +236,8 @@ euler_angles_zxy_from_quaternion_f32 :: proc(q: Quaternionf32) -> (t1, t2, t3: f
// Matrix3
matrix3_from_euler_angle_x_f32 :: proc(angle_x: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angle_x_f32 :: proc "contextless" (angle_x: f32) -> (m: Matrix3f32) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
m[0, 0] = 1
m[1, 1] = +cos_x
@@ -219,7 +246,8 @@ matrix3_from_euler_angle_x_f32 :: proc(angle_x: f32) -> (m: Matrix3f32) {
m[2, 2] = +cos_x
return
}
matrix3_from_euler_angle_y_f32 :: proc(angle_y: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angle_y_f32 :: proc "contextless" (angle_y: f32) -> (m: Matrix3f32) {
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = +cos_y
m[0, 2] = -sin_y
@@ -228,7 +256,8 @@ matrix3_from_euler_angle_y_f32 :: proc(angle_y: f32) -> (m: Matrix3f32) {
m[2, 2] = +cos_y
return
}
matrix3_from_euler_angle_z_f32 :: proc(angle_z: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angle_z_f32 :: proc "contextless" (angle_z: f32) -> (m: Matrix3f32) {
cos_z, sin_z := math.cos(angle_z), math.sin(angle_z)
m[0, 0] = +cos_z
m[0, 1] = +sin_z
@@ -239,7 +268,8 @@ matrix3_from_euler_angle_z_f32 :: proc(angle_z: f32) -> (m: Matrix3f32) {
}
matrix3_from_derived_euler_angle_x_f32 :: proc(angle_x: f32, angular_velocity_x: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_derived_euler_angle_x_f32 :: proc "contextless" (angle_x: f32, angular_velocity_x: f32) -> (m: Matrix3f32) {
cos_x := math.cos(angle_x) * angular_velocity_x
sin_x := math.sin(angle_x) * angular_velocity_x
m[0, 0] = 1
@@ -249,7 +279,8 @@ matrix3_from_derived_euler_angle_x_f32 :: proc(angle_x: f32, angular_velocity_x:
m[2, 2] = +cos_x
return
}
matrix3_from_derived_euler_angle_y_f32 :: proc(angle_y: f32, angular_velocity_y: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_derived_euler_angle_y_f32 :: proc "contextless" (angle_y: f32, angular_velocity_y: f32) -> (m: Matrix3f32) {
cos_y := math.cos(angle_y) * angular_velocity_y
sin_y := math.sin(angle_y) * angular_velocity_y
m[0, 0] = +cos_y
@@ -259,7 +290,8 @@ matrix3_from_derived_euler_angle_y_f32 :: proc(angle_y: f32, angular_velocity_y:
m[2, 2] = +cos_y
return
}
matrix3_from_derived_euler_angle_z_f32 :: proc(angle_z: f32, angular_velocity_z: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_derived_euler_angle_z_f32 :: proc "contextless" (angle_z: f32, angular_velocity_z: f32) -> (m: Matrix3f32) {
cos_z := math.cos(angle_z) * angular_velocity_z
sin_z := math.sin(angle_z) * angular_velocity_z
m[0, 0] = +cos_z
@@ -271,7 +303,8 @@ matrix3_from_derived_euler_angle_z_f32 :: proc(angle_z: f32, angular_velocity_z:
}
matrix3_from_euler_angles_xy_f32 :: proc(angle_x, angle_y: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_xy_f32 :: proc "contextless" (angle_x, angle_y: f32) -> (m: Matrix3f32) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y
@@ -286,7 +319,8 @@ matrix3_from_euler_angles_xy_f32 :: proc(angle_x, angle_y: f32) -> (m: Matrix3f3
}
matrix3_from_euler_angles_yx_f32 :: proc(angle_y, angle_x: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_yx_f32 :: proc "contextless" (angle_y, angle_x: f32) -> (m: Matrix3f32) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y
@@ -300,21 +334,26 @@ matrix3_from_euler_angles_yx_f32 :: proc(angle_y, angle_x: f32) -> (m: Matrix3f3
return
}
matrix3_from_euler_angles_xz_f32 :: proc(angle_x, angle_z: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_xz_f32 :: proc "contextless" (angle_x, angle_z: f32) -> (m: Matrix3f32) {
return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z))
}
matrix3_from_euler_angles_zx_f32 :: proc(angle_z, angle_x: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_zx_f32 :: proc "contextless" (angle_z, angle_x: f32) -> (m: Matrix3f32) {
return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x))
}
matrix3_from_euler_angles_yz_f32 :: proc(angle_y, angle_z: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_yz_f32 :: proc "contextless" (angle_y, angle_z: f32) -> (m: Matrix3f32) {
return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z))
}
matrix3_from_euler_angles_zy_f32 :: proc(angle_z, angle_y: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_zy_f32 :: proc "contextless" (angle_z, angle_y: f32) -> (m: Matrix3f32) {
return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y))
}
matrix3_from_euler_angles_xyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_xyz_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(-t1)
c2 := math.cos(-t2)
c3 := math.cos(-t3)
@@ -334,7 +373,8 @@ matrix3_from_euler_angles_xyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return
}
matrix3_from_euler_angles_yxz_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_yxz_f32 :: proc "contextless" (yaw, pitch, roll: f32) -> (m: Matrix3f32) {
ch := math.cos(yaw)
sh := math.sin(yaw)
cp := math.cos(pitch)
@@ -354,7 +394,8 @@ matrix3_from_euler_angles_yxz_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix3f
return
}
matrix3_from_euler_angles_xzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_xzx_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -374,7 +415,8 @@ matrix3_from_euler_angles_xzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return
}
matrix3_from_euler_angles_xyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_xyx_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -394,7 +436,8 @@ matrix3_from_euler_angles_xyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return
}
matrix3_from_euler_angles_yxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_yxy_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -414,7 +457,8 @@ matrix3_from_euler_angles_yxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return
}
matrix3_from_euler_angles_yzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_yzy_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -434,7 +478,8 @@ matrix3_from_euler_angles_yzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return
}
matrix3_from_euler_angles_zyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_zyz_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -454,7 +499,8 @@ matrix3_from_euler_angles_zyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return
}
matrix3_from_euler_angles_zxz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_zxz_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -475,7 +521,8 @@ matrix3_from_euler_angles_zxz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
}
matrix3_from_euler_angles_xzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_xzy_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -495,7 +542,8 @@ matrix3_from_euler_angles_xzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return
}
matrix3_from_euler_angles_yzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_yzx_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -515,7 +563,8 @@ matrix3_from_euler_angles_yzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return
}
matrix3_from_euler_angles_zyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_zyx_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -535,7 +584,8 @@ matrix3_from_euler_angles_zyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
return
}
matrix3_from_euler_angles_zxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_euler_angles_zxy_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix3f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -556,7 +606,8 @@ matrix3_from_euler_angles_zxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix3f32) {
}
matrix3_from_yaw_pitch_roll_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix3f32) {
@(require_results)
matrix3_from_yaw_pitch_roll_f32 :: proc "contextless" (yaw, pitch, roll: f32) -> (m: Matrix3f32) {
ch := math.cos(yaw)
sh := math.sin(yaw)
cp := math.cos(pitch)
@@ -576,7 +627,8 @@ matrix3_from_yaw_pitch_roll_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix3f32
return m
}
euler_angles_xyz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_xyz_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[1, 2], m[2, 2])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1])
T2 := math.atan2(-m[0, 2], C2)
@@ -589,7 +641,8 @@ euler_angles_xyz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_yxz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_yxz_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[0, 2], m[2, 2])
C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1])
T2 := math.atan2(-m[1, 2], C2)
@@ -602,7 +655,8 @@ euler_angles_yxz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_xzx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_xzx_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[2, 0], m[1, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0])
@@ -615,7 +669,8 @@ euler_angles_xzx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_xyx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_xyx_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[1, 0], -m[2, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0])
@@ -628,7 +683,8 @@ euler_angles_xyx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_yxy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_yxy_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[0, 1], m[2, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1])
@@ -641,7 +697,8 @@ euler_angles_yxy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_yzy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_yzy_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[2, 1], -m[0, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1])
@@ -653,7 +710,8 @@ euler_angles_yzy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
t3 = T3
return
}
euler_angles_zyz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_zyz_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[1, 2], m[0, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2])
@@ -666,7 +724,8 @@ euler_angles_zyz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_zxz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_zxz_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[0, 2], -m[1, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2])
@@ -679,7 +738,8 @@ euler_angles_zxz_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_xzy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_xzy_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[2, 1], m[1, 1])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2])
T2 := math.atan2(-m[0, 1], C2)
@@ -692,7 +752,8 @@ euler_angles_xzy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_yzx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_yzx_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(-m[2, 0], m[0, 0])
C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2])
T2 := math.atan2(m[1, 0], C2)
@@ -705,7 +766,8 @@ euler_angles_yzx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_zyx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_zyx_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[1, 0], m[0, 0])
C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2])
T2 := math.atan2(-m[2, 0], C2)
@@ -718,7 +780,8 @@ euler_angles_zyx_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_zxy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_zxy_from_matrix3_f32 :: proc "contextless" (m: Matrix3f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(-m[0, 1], m[1, 1])
C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2])
T2 := math.atan2(m[2, 1], C2)
@@ -735,7 +798,8 @@ euler_angles_zxy_from_matrix3_f32 :: proc(m: Matrix3f32) -> (t1, t2, t3: f32) {
// Matrix4
matrix4_from_euler_angle_x_f32 :: proc(angle_x: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angle_x_f32 :: proc "contextless" (angle_x: f32) -> (m: Matrix4f32) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
m[0, 0] = 1
m[1, 1] = +cos_x
@@ -745,7 +809,8 @@ matrix4_from_euler_angle_x_f32 :: proc(angle_x: f32) -> (m: Matrix4f32) {
m[3, 3] = 1
return
}
matrix4_from_euler_angle_y_f32 :: proc(angle_y: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angle_y_f32 :: proc "contextless" (angle_y: f32) -> (m: Matrix4f32) {
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = +cos_y
m[0, 2] = -sin_y
@@ -755,7 +820,8 @@ matrix4_from_euler_angle_y_f32 :: proc(angle_y: f32) -> (m: Matrix4f32) {
m[3, 3] = 1
return
}
matrix4_from_euler_angle_z_f32 :: proc(angle_z: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angle_z_f32 :: proc "contextless" (angle_z: f32) -> (m: Matrix4f32) {
cos_z, sin_z := math.cos(angle_z), math.sin(angle_z)
m[0, 0] = +cos_z
m[0, 1] = +sin_z
@@ -767,7 +833,8 @@ matrix4_from_euler_angle_z_f32 :: proc(angle_z: f32) -> (m: Matrix4f32) {
}
matrix4_from_derived_euler_angle_x_f32 :: proc(angle_x: f32, angular_velocity_x: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_derived_euler_angle_x_f32 :: proc "contextless" (angle_x: f32, angular_velocity_x: f32) -> (m: Matrix4f32) {
cos_x := math.cos(angle_x) * angular_velocity_x
sin_x := math.sin(angle_x) * angular_velocity_x
m[0, 0] = 1
@@ -778,7 +845,8 @@ matrix4_from_derived_euler_angle_x_f32 :: proc(angle_x: f32, angular_velocity_x:
m[3, 3] = 1
return
}
matrix4_from_derived_euler_angle_y_f32 :: proc(angle_y: f32, angular_velocity_y: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_derived_euler_angle_y_f32 :: proc "contextless" (angle_y: f32, angular_velocity_y: f32) -> (m: Matrix4f32) {
cos_y := math.cos(angle_y) * angular_velocity_y
sin_y := math.sin(angle_y) * angular_velocity_y
m[0, 0] = +cos_y
@@ -789,7 +857,8 @@ matrix4_from_derived_euler_angle_y_f32 :: proc(angle_y: f32, angular_velocity_y:
m[3, 3] = 1
return
}
matrix4_from_derived_euler_angle_z_f32 :: proc(angle_z: f32, angular_velocity_z: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_derived_euler_angle_z_f32 :: proc "contextless" (angle_z: f32, angular_velocity_z: f32) -> (m: Matrix4f32) {
cos_z := math.cos(angle_z) * angular_velocity_z
sin_z := math.sin(angle_z) * angular_velocity_z
m[0, 0] = +cos_z
@@ -802,7 +871,8 @@ matrix4_from_derived_euler_angle_z_f32 :: proc(angle_z: f32, angular_velocity_z:
}
matrix4_from_euler_angles_xy_f32 :: proc(angle_x, angle_y: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_xy_f32 :: proc "contextless" (angle_x, angle_y: f32) -> (m: Matrix4f32) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y
@@ -818,7 +888,8 @@ matrix4_from_euler_angles_xy_f32 :: proc(angle_x, angle_y: f32) -> (m: Matrix4f3
}
matrix4_from_euler_angles_yx_f32 :: proc(angle_y, angle_x: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_yx_f32 :: proc "contextless" (angle_y, angle_x: f32) -> (m: Matrix4f32) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y
@@ -833,21 +904,26 @@ matrix4_from_euler_angles_yx_f32 :: proc(angle_y, angle_x: f32) -> (m: Matrix4f3
return
}
matrix4_from_euler_angles_xz_f32 :: proc(angle_x, angle_z: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_xz_f32 :: proc "contextless" (angle_x, angle_z: f32) -> (m: Matrix4f32) {
return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z))
}
matrix4_from_euler_angles_zx_f32 :: proc(angle_z, angle_x: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_zx_f32 :: proc "contextless" (angle_z, angle_x: f32) -> (m: Matrix4f32) {
return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x))
}
matrix4_from_euler_angles_yz_f32 :: proc(angle_y, angle_z: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_yz_f32 :: proc "contextless" (angle_y, angle_z: f32) -> (m: Matrix4f32) {
return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z))
}
matrix4_from_euler_angles_zy_f32 :: proc(angle_z, angle_y: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_zy_f32 :: proc "contextless" (angle_z, angle_y: f32) -> (m: Matrix4f32) {
return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y))
}
matrix4_from_euler_angles_xyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_xyz_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(-t1)
c2 := math.cos(-t2)
c3 := math.cos(-t3)
@@ -874,7 +950,8 @@ matrix4_from_euler_angles_xyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return
}
matrix4_from_euler_angles_yxz_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_yxz_f32 :: proc "contextless" (yaw, pitch, roll: f32) -> (m: Matrix4f32) {
ch := math.cos(yaw)
sh := math.sin(yaw)
cp := math.cos(pitch)
@@ -901,7 +978,8 @@ matrix4_from_euler_angles_yxz_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix4f
return
}
matrix4_from_euler_angles_xzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_xzx_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -928,7 +1006,8 @@ matrix4_from_euler_angles_xzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return
}
matrix4_from_euler_angles_xyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_xyx_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -955,7 +1034,8 @@ matrix4_from_euler_angles_xyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return
}
matrix4_from_euler_angles_yxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_yxy_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -982,7 +1062,8 @@ matrix4_from_euler_angles_yxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return
}
matrix4_from_euler_angles_yzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_yzy_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1009,7 +1090,8 @@ matrix4_from_euler_angles_yzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return
}
matrix4_from_euler_angles_zyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_zyz_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1036,7 +1118,8 @@ matrix4_from_euler_angles_zyz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return
}
matrix4_from_euler_angles_zxz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_zxz_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1064,7 +1147,8 @@ matrix4_from_euler_angles_zxz_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
}
matrix4_from_euler_angles_xzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_xzy_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1091,7 +1175,8 @@ matrix4_from_euler_angles_xzy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return
}
matrix4_from_euler_angles_yzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_yzx_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1118,7 +1203,8 @@ matrix4_from_euler_angles_yzx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return
}
matrix4_from_euler_angles_zyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_zyx_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1145,7 +1231,8 @@ matrix4_from_euler_angles_zyx_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
return
}
matrix4_from_euler_angles_zxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_euler_angles_zxy_f32 :: proc "contextless" (t1, t2, t3: f32) -> (m: Matrix4f32) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1173,7 +1260,8 @@ matrix4_from_euler_angles_zxy_f32 :: proc(t1, t2, t3: f32) -> (m: Matrix4f32) {
}
matrix4_from_yaw_pitch_roll_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix4f32) {
@(require_results)
matrix4_from_yaw_pitch_roll_f32 :: proc "contextless" (yaw, pitch, roll: f32) -> (m: Matrix4f32) {
ch := math.cos(yaw)
sh := math.sin(yaw)
cp := math.cos(pitch)
@@ -1200,7 +1288,8 @@ matrix4_from_yaw_pitch_roll_f32 :: proc(yaw, pitch, roll: f32) -> (m: Matrix4f32
return m
}
euler_angles_xyz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_xyz_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[1, 2], m[2, 2])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1])
T2 := math.atan2(-m[0, 2], C2)
@@ -1213,7 +1302,8 @@ euler_angles_xyz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_yxz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_yxz_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[0, 2], m[2, 2])
C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1])
T2 := math.atan2(-m[1, 2], C2)
@@ -1226,7 +1316,8 @@ euler_angles_yxz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_xzx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_xzx_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[2, 0], m[1, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0])
@@ -1239,7 +1330,8 @@ euler_angles_xzx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_xyx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_xyx_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[1, 0], -m[2, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0])
@@ -1252,7 +1344,8 @@ euler_angles_xyx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_yxy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_yxy_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[0, 1], m[2, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1])
@@ -1265,7 +1358,8 @@ euler_angles_yxy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_yzy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_yzy_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[2, 1], -m[0, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1])
@@ -1277,7 +1371,8 @@ euler_angles_yzy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
t3 = T3
return
}
euler_angles_zyz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_zyz_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[1, 2], m[0, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2])
@@ -1290,7 +1385,8 @@ euler_angles_zyz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_zxz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_zxz_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[0, 2], -m[1, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2])
@@ -1303,7 +1399,8 @@ euler_angles_zxz_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_xzy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_xzy_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[2, 1], m[1, 1])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2])
T2 := math.atan2(-m[0, 1], C2)
@@ -1316,7 +1413,8 @@ euler_angles_xzy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_yzx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_yzx_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(-m[2, 0], m[0, 0])
C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2])
T2 := math.atan2(m[1, 0], C2)
@@ -1329,7 +1427,8 @@ euler_angles_yzx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_zyx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_zyx_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(m[1, 0], m[0, 0])
C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2])
T2 := math.atan2(-m[2, 0], C2)
@@ -1342,7 +1441,8 @@ euler_angles_zyx_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
return
}
euler_angles_zxy_from_matrix4_f32 :: proc(m: Matrix4f32) -> (t1, t2, t3: f32) {
@(require_results)
euler_angles_zxy_from_matrix4_f32 :: proc "contextless" (m: Matrix4f32) -> (t1, t2, t3: f32) {
T1 := math.atan2(-m[0, 1], m[1, 1])
C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2])
T2 := math.atan2(m[2, 1], C2)
+200 -100
View File
@@ -2,7 +2,8 @@ package linalg
import "core:math"
euler_angles_from_matrix3_f64 :: proc(m: Matrix3f64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) {
switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix3(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix3(m)
@@ -19,7 +20,8 @@ euler_angles_from_matrix3_f64 :: proc(m: Matrix3f64, order: Euler_Angle_Order) -
}
return
}
euler_angles_from_matrix4_f64 :: proc(m: Matrix4f64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) {
switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_matrix4(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_matrix4(m)
@@ -36,7 +38,8 @@ euler_angles_from_matrix4_f64 :: proc(m: Matrix4f64, order: Euler_Angle_Order) -
}
return
}
euler_angles_from_quaternion_f64 :: proc(m: Quaternionf64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_from_quaternion_f64 :: proc "contextless" (m: Quaternionf64, order: Euler_Angle_Order) -> (t1, t2, t3: f64) {
switch order {
case .XYZ: t1, t2, t3 = euler_angles_xyz_from_quaternion(m)
case .XZY: t1, t2, t3 = euler_angles_xzy_from_quaternion(m)
@@ -54,7 +57,8 @@ euler_angles_from_quaternion_f64 :: proc(m: Quaternionf64, order: Euler_Angle_Or
return
}
matrix3_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Order) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_f64 :: proc "contextless" (t1, t2, t3: f64, order: Euler_Angle_Order) -> (m: Matrix3f64) {
switch order {
case .XYZ: return matrix3_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3);
case .XZY: return matrix3_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3);
@@ -71,7 +75,8 @@ matrix3_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Order)
}
return
}
matrix4_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Order) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_f64 :: proc "contextless" (t1, t2, t3: f64, order: Euler_Angle_Order) -> (m: Matrix4f64) {
switch order {
case .XYZ: return matrix4_from_euler_angles_xyz(t1, t2, t3) // m1, m2, m3 = X(t1), Y(t2), Z(t3);
case .XZY: return matrix4_from_euler_angles_xzy(t1, t2, t3) // m1, m2, m3 = X(t1), Z(t2), Y(t3);
@@ -89,7 +94,8 @@ matrix4_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Order)
return
}
quaternion_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Order) -> Quaternionf64 {
@(require_results)
quaternion_from_euler_angles_f64 :: proc "contextless" (t1, t2, t3: f64, order: Euler_Angle_Order) -> Quaternionf64 {
X :: quaternion_from_euler_angle_x
Y :: quaternion_from_euler_angle_y
Z :: quaternion_from_euler_angle_z
@@ -117,17 +123,21 @@ quaternion_from_euler_angles_f64 :: proc(t1, t2, t3: f64, order: Euler_Angle_Ord
// Quaternionf64s
quaternion_from_euler_angle_x_f64 :: proc(angle_x: f64) -> (q: Quaternionf64) {
@(require_results)
quaternion_from_euler_angle_x_f64 :: proc "contextless" (angle_x: f64) -> (q: Quaternionf64) {
return quaternion_angle_axis_f64(angle_x, {1, 0, 0})
}
quaternion_from_euler_angle_y_f64 :: proc(angle_y: f64) -> (q: Quaternionf64) {
@(require_results)
quaternion_from_euler_angle_y_f64 :: proc "contextless" (angle_y: f64) -> (q: Quaternionf64) {
return quaternion_angle_axis_f64(angle_y, {0, 1, 0})
}
quaternion_from_euler_angle_z_f64 :: proc(angle_z: f64) -> (q: Quaternionf64) {
@(require_results)
quaternion_from_euler_angle_z_f64 :: proc "contextless" (angle_z: f64) -> (q: Quaternionf64) {
return quaternion_angle_axis_f64(angle_z, {0, 0, 1})
}
quaternion_from_pitch_yaw_roll_f64 :: proc(pitch, yaw, roll: f64) -> Quaternionf64 {
@(require_results)
quaternion_from_pitch_yaw_roll_f64 :: proc "contextless" (pitch, yaw, roll: f64) -> Quaternionf64 {
a, b, c := pitch, yaw, roll
ca, sa := math.cos(a*0.5), math.sin(a*0.5)
@@ -142,11 +152,13 @@ quaternion_from_pitch_yaw_roll_f64 :: proc(pitch, yaw, roll: f64) -> Quaternionf
return q
}
roll_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 {
@(require_results)
roll_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> f64 {
return math.atan2(2 * q.x*q.y + q.w*q.z, q.w*q.w + q.x*q.x - q.y*q.y - q.z*q.z)
}
pitch_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 {
@(require_results)
pitch_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> f64 {
y := 2 * (q.y*q.z + q.w*q.w)
x := q.w*q.w - q.x*q.x - q.y*q.y + q.z*q.z
@@ -157,52 +169,66 @@ pitch_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 {
return math.atan2(y, x)
}
yaw_from_quaternion_f64 :: proc(q: Quaternionf64) -> f64 {
@(require_results)
yaw_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> f64 {
return math.asin(clamp(-2 * (q.x*q.z - q.w*q.y), -1, 1))
}
pitch_yaw_roll_from_quaternion_f64 :: proc(q: Quaternionf64) -> (pitch, yaw, roll: f64) {
@(require_results)
pitch_yaw_roll_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (pitch, yaw, roll: f64) {
pitch = pitch_from_quaternion(q)
yaw = yaw_from_quaternion(q)
roll = roll_from_quaternion(q)
return
}
euler_angles_xyz_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_xyz_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_xyz_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_yxz_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_yxz_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_yxz_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_xzx_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_xzx_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_xzx_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_xyx_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_xyx_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_xyx_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_yxy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_yxy_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_yxy_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_yzy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_yzy_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_yzy_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_zyz_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_zyz_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_zyz_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_zxz_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_zxz_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_zxz_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_xzy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_xzy_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_xzy_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_yzx_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_yzx_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_yzx_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_zyx_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_zyx_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_zyx_from_matrix4(matrix4_from_quaternion(q))
}
euler_angles_zxy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_zxy_from_quaternion_f64 :: proc "contextless" (q: Quaternionf64) -> (t1, t2, t3: f64) {
return euler_angles_zxy_from_matrix4(matrix4_from_quaternion(q))
}
@@ -210,7 +236,8 @@ euler_angles_zxy_from_quaternion_f64 :: proc(q: Quaternionf64) -> (t1, t2, t3: f
// Matrix3
matrix3_from_euler_angle_x_f64 :: proc(angle_x: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angle_x_f64 :: proc "contextless" (angle_x: f64) -> (m: Matrix3f64) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
m[0, 0] = 1
m[1, 1] = +cos_x
@@ -219,7 +246,8 @@ matrix3_from_euler_angle_x_f64 :: proc(angle_x: f64) -> (m: Matrix3f64) {
m[2, 2] = +cos_x
return
}
matrix3_from_euler_angle_y_f64 :: proc(angle_y: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angle_y_f64 :: proc "contextless" (angle_y: f64) -> (m: Matrix3f64) {
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = +cos_y
m[0, 2] = -sin_y
@@ -228,7 +256,8 @@ matrix3_from_euler_angle_y_f64 :: proc(angle_y: f64) -> (m: Matrix3f64) {
m[2, 2] = +cos_y
return
}
matrix3_from_euler_angle_z_f64 :: proc(angle_z: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angle_z_f64 :: proc "contextless" (angle_z: f64) -> (m: Matrix3f64) {
cos_z, sin_z := math.cos(angle_z), math.sin(angle_z)
m[0, 0] = +cos_z
m[0, 1] = +sin_z
@@ -239,7 +268,8 @@ matrix3_from_euler_angle_z_f64 :: proc(angle_z: f64) -> (m: Matrix3f64) {
}
matrix3_from_derived_euler_angle_x_f64 :: proc(angle_x: f64, angular_velocity_x: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_derived_euler_angle_x_f64 :: proc "contextless" (angle_x: f64, angular_velocity_x: f64) -> (m: Matrix3f64) {
cos_x := math.cos(angle_x) * angular_velocity_x
sin_x := math.sin(angle_x) * angular_velocity_x
m[0, 0] = 1
@@ -249,7 +279,8 @@ matrix3_from_derived_euler_angle_x_f64 :: proc(angle_x: f64, angular_velocity_x:
m[2, 2] = +cos_x
return
}
matrix3_from_derived_euler_angle_y_f64 :: proc(angle_y: f64, angular_velocity_y: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_derived_euler_angle_y_f64 :: proc "contextless" (angle_y: f64, angular_velocity_y: f64) -> (m: Matrix3f64) {
cos_y := math.cos(angle_y) * angular_velocity_y
sin_y := math.sin(angle_y) * angular_velocity_y
m[0, 0] = +cos_y
@@ -259,7 +290,8 @@ matrix3_from_derived_euler_angle_y_f64 :: proc(angle_y: f64, angular_velocity_y:
m[2, 2] = +cos_y
return
}
matrix3_from_derived_euler_angle_z_f64 :: proc(angle_z: f64, angular_velocity_z: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_derived_euler_angle_z_f64 :: proc "contextless" (angle_z: f64, angular_velocity_z: f64) -> (m: Matrix3f64) {
cos_z := math.cos(angle_z) * angular_velocity_z
sin_z := math.sin(angle_z) * angular_velocity_z
m[0, 0] = +cos_z
@@ -271,7 +303,8 @@ matrix3_from_derived_euler_angle_z_f64 :: proc(angle_z: f64, angular_velocity_z:
}
matrix3_from_euler_angles_xy_f64 :: proc(angle_x, angle_y: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_xy_f64 :: proc "contextless" (angle_x, angle_y: f64) -> (m: Matrix3f64) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y
@@ -286,7 +319,8 @@ matrix3_from_euler_angles_xy_f64 :: proc(angle_x, angle_y: f64) -> (m: Matrix3f6
}
matrix3_from_euler_angles_yx_f64 :: proc(angle_y, angle_x: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_yx_f64 :: proc "contextless" (angle_y, angle_x: f64) -> (m: Matrix3f64) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y
@@ -300,21 +334,26 @@ matrix3_from_euler_angles_yx_f64 :: proc(angle_y, angle_x: f64) -> (m: Matrix3f6
return
}
matrix3_from_euler_angles_xz_f64 :: proc(angle_x, angle_z: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_xz_f64 :: proc "contextless" (angle_x, angle_z: f64) -> (m: Matrix3f64) {
return mul(matrix3_from_euler_angle_x(angle_x), matrix3_from_euler_angle_z(angle_z))
}
matrix3_from_euler_angles_zx_f64 :: proc(angle_z, angle_x: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_zx_f64 :: proc "contextless" (angle_z, angle_x: f64) -> (m: Matrix3f64) {
return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_x(angle_x))
}
matrix3_from_euler_angles_yz_f64 :: proc(angle_y, angle_z: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_yz_f64 :: proc "contextless" (angle_y, angle_z: f64) -> (m: Matrix3f64) {
return mul(matrix3_from_euler_angle_y(angle_y), matrix3_from_euler_angle_z(angle_z))
}
matrix3_from_euler_angles_zy_f64 :: proc(angle_z, angle_y: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_zy_f64 :: proc "contextless" (angle_z, angle_y: f64) -> (m: Matrix3f64) {
return mul(matrix3_from_euler_angle_z(angle_z), matrix3_from_euler_angle_y(angle_y))
}
matrix3_from_euler_angles_xyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_xyz_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(-t1)
c2 := math.cos(-t2)
c3 := math.cos(-t3)
@@ -334,7 +373,8 @@ matrix3_from_euler_angles_xyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return
}
matrix3_from_euler_angles_yxz_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_yxz_f64 :: proc "contextless" (yaw, pitch, roll: f64) -> (m: Matrix3f64) {
ch := math.cos(yaw)
sh := math.sin(yaw)
cp := math.cos(pitch)
@@ -354,7 +394,8 @@ matrix3_from_euler_angles_yxz_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix3f
return
}
matrix3_from_euler_angles_xzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_xzx_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -374,7 +415,8 @@ matrix3_from_euler_angles_xzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return
}
matrix3_from_euler_angles_xyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_xyx_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -394,7 +436,8 @@ matrix3_from_euler_angles_xyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return
}
matrix3_from_euler_angles_yxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_yxy_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -414,7 +457,8 @@ matrix3_from_euler_angles_yxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return
}
matrix3_from_euler_angles_yzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_yzy_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -434,7 +478,8 @@ matrix3_from_euler_angles_yzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return
}
matrix3_from_euler_angles_zyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_zyz_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -454,7 +499,8 @@ matrix3_from_euler_angles_zyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return
}
matrix3_from_euler_angles_zxz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_zxz_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -475,7 +521,8 @@ matrix3_from_euler_angles_zxz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
}
matrix3_from_euler_angles_xzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_xzy_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -495,7 +542,8 @@ matrix3_from_euler_angles_xzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return
}
matrix3_from_euler_angles_yzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_yzx_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -515,7 +563,8 @@ matrix3_from_euler_angles_yzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return
}
matrix3_from_euler_angles_zyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_zyx_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -535,7 +584,8 @@ matrix3_from_euler_angles_zyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
return
}
matrix3_from_euler_angles_zxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_euler_angles_zxy_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix3f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -556,7 +606,8 @@ matrix3_from_euler_angles_zxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix3f64) {
}
matrix3_from_yaw_pitch_roll_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix3f64) {
@(require_results)
matrix3_from_yaw_pitch_roll_f64 :: proc "contextless" (yaw, pitch, roll: f64) -> (m: Matrix3f64) {
ch := math.cos(yaw)
sh := math.sin(yaw)
cp := math.cos(pitch)
@@ -576,7 +627,8 @@ matrix3_from_yaw_pitch_roll_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix3f64
return m
}
euler_angles_xyz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_xyz_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[1, 2], m[2, 2])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1])
T2 := math.atan2(-m[0, 2], C2)
@@ -589,7 +641,8 @@ euler_angles_xyz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_yxz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_yxz_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[0, 2], m[2, 2])
C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1])
T2 := math.atan2(-m[1, 2], C2)
@@ -602,7 +655,8 @@ euler_angles_yxz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_xzx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_xzx_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[2, 0], m[1, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0])
@@ -615,7 +669,8 @@ euler_angles_xzx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_xyx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_xyx_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[1, 0], -m[2, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0])
@@ -628,7 +683,8 @@ euler_angles_xyx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_yxy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_yxy_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[0, 1], m[2, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1])
@@ -641,7 +697,8 @@ euler_angles_yxy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_yzy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_yzy_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[2, 1], -m[0, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1])
@@ -653,7 +710,8 @@ euler_angles_yzy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
t3 = T3
return
}
euler_angles_zyz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_zyz_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[1, 2], m[0, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2])
@@ -666,7 +724,8 @@ euler_angles_zyz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_zxz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_zxz_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[0, 2], -m[1, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2])
@@ -679,7 +738,8 @@ euler_angles_zxz_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_xzy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_xzy_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[2, 1], m[1, 1])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2])
T2 := math.atan2(-m[0, 1], C2)
@@ -692,7 +752,8 @@ euler_angles_xzy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_yzx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_yzx_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(-m[2, 0], m[0, 0])
C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2])
T2 := math.atan2(m[1, 0], C2)
@@ -705,7 +766,8 @@ euler_angles_yzx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_zyx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_zyx_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[1, 0], m[0, 0])
C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2])
T2 := math.atan2(-m[2, 0], C2)
@@ -718,7 +780,8 @@ euler_angles_zyx_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_zxy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_zxy_from_matrix3_f64 :: proc "contextless" (m: Matrix3f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(-m[0, 1], m[1, 1])
C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2])
T2 := math.atan2(m[2, 1], C2)
@@ -735,7 +798,8 @@ euler_angles_zxy_from_matrix3_f64 :: proc(m: Matrix3f64) -> (t1, t2, t3: f64) {
// Matrix4
matrix4_from_euler_angle_x_f64 :: proc(angle_x: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angle_x_f64 :: proc "contextless" (angle_x: f64) -> (m: Matrix4f64) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
m[0, 0] = 1
m[1, 1] = +cos_x
@@ -745,7 +809,8 @@ matrix4_from_euler_angle_x_f64 :: proc(angle_x: f64) -> (m: Matrix4f64) {
m[3, 3] = 1
return
}
matrix4_from_euler_angle_y_f64 :: proc(angle_y: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angle_y_f64 :: proc "contextless" (angle_y: f64) -> (m: Matrix4f64) {
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = +cos_y
m[0, 2] = -sin_y
@@ -755,7 +820,8 @@ matrix4_from_euler_angle_y_f64 :: proc(angle_y: f64) -> (m: Matrix4f64) {
m[3, 3] = 1
return
}
matrix4_from_euler_angle_z_f64 :: proc(angle_z: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angle_z_f64 :: proc "contextless" (angle_z: f64) -> (m: Matrix4f64) {
cos_z, sin_z := math.cos(angle_z), math.sin(angle_z)
m[0, 0] = +cos_z
m[0, 1] = +sin_z
@@ -767,7 +833,8 @@ matrix4_from_euler_angle_z_f64 :: proc(angle_z: f64) -> (m: Matrix4f64) {
}
matrix4_from_derived_euler_angle_x_f64 :: proc(angle_x: f64, angular_velocity_x: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_derived_euler_angle_x_f64 :: proc "contextless" (angle_x: f64, angular_velocity_x: f64) -> (m: Matrix4f64) {
cos_x := math.cos(angle_x) * angular_velocity_x
sin_x := math.sin(angle_x) * angular_velocity_x
m[0, 0] = 1
@@ -778,7 +845,8 @@ matrix4_from_derived_euler_angle_x_f64 :: proc(angle_x: f64, angular_velocity_x:
m[3, 3] = 1
return
}
matrix4_from_derived_euler_angle_y_f64 :: proc(angle_y: f64, angular_velocity_y: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_derived_euler_angle_y_f64 :: proc "contextless" (angle_y: f64, angular_velocity_y: f64) -> (m: Matrix4f64) {
cos_y := math.cos(angle_y) * angular_velocity_y
sin_y := math.sin(angle_y) * angular_velocity_y
m[0, 0] = +cos_y
@@ -789,7 +857,8 @@ matrix4_from_derived_euler_angle_y_f64 :: proc(angle_y: f64, angular_velocity_y:
m[3, 3] = 1
return
}
matrix4_from_derived_euler_angle_z_f64 :: proc(angle_z: f64, angular_velocity_z: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_derived_euler_angle_z_f64 :: proc "contextless" (angle_z: f64, angular_velocity_z: f64) -> (m: Matrix4f64) {
cos_z := math.cos(angle_z) * angular_velocity_z
sin_z := math.sin(angle_z) * angular_velocity_z
m[0, 0] = +cos_z
@@ -802,7 +871,8 @@ matrix4_from_derived_euler_angle_z_f64 :: proc(angle_z: f64, angular_velocity_z:
}
matrix4_from_euler_angles_xy_f64 :: proc(angle_x, angle_y: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_xy_f64 :: proc "contextless" (angle_x, angle_y: f64) -> (m: Matrix4f64) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y
@@ -818,7 +888,8 @@ matrix4_from_euler_angles_xy_f64 :: proc(angle_x, angle_y: f64) -> (m: Matrix4f6
}
matrix4_from_euler_angles_yx_f64 :: proc(angle_y, angle_x: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_yx_f64 :: proc "contextless" (angle_y, angle_x: f64) -> (m: Matrix4f64) {
cos_x, sin_x := math.cos(angle_x), math.sin(angle_x)
cos_y, sin_y := math.cos(angle_y), math.sin(angle_y)
m[0, 0] = cos_y
@@ -833,21 +904,26 @@ matrix4_from_euler_angles_yx_f64 :: proc(angle_y, angle_x: f64) -> (m: Matrix4f6
return
}
matrix4_from_euler_angles_xz_f64 :: proc(angle_x, angle_z: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_xz_f64 :: proc "contextless" (angle_x, angle_z: f64) -> (m: Matrix4f64) {
return mul(matrix4_from_euler_angle_x(angle_x), matrix4_from_euler_angle_z(angle_z))
}
matrix4_from_euler_angles_zx_f64 :: proc(angle_z, angle_x: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_zx_f64 :: proc "contextless" (angle_z, angle_x: f64) -> (m: Matrix4f64) {
return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_x(angle_x))
}
matrix4_from_euler_angles_yz_f64 :: proc(angle_y, angle_z: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_yz_f64 :: proc "contextless" (angle_y, angle_z: f64) -> (m: Matrix4f64) {
return mul(matrix4_from_euler_angle_y(angle_y), matrix4_from_euler_angle_z(angle_z))
}
matrix4_from_euler_angles_zy_f64 :: proc(angle_z, angle_y: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_zy_f64 :: proc "contextless" (angle_z, angle_y: f64) -> (m: Matrix4f64) {
return mul(matrix4_from_euler_angle_z(angle_z), matrix4_from_euler_angle_y(angle_y))
}
matrix4_from_euler_angles_xyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_xyz_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(-t1)
c2 := math.cos(-t2)
c3 := math.cos(-t3)
@@ -874,7 +950,8 @@ matrix4_from_euler_angles_xyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return
}
matrix4_from_euler_angles_yxz_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_yxz_f64 :: proc "contextless" (yaw, pitch, roll: f64) -> (m: Matrix4f64) {
ch := math.cos(yaw)
sh := math.sin(yaw)
cp := math.cos(pitch)
@@ -901,7 +978,8 @@ matrix4_from_euler_angles_yxz_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix4f
return
}
matrix4_from_euler_angles_xzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_xzx_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -928,7 +1006,8 @@ matrix4_from_euler_angles_xzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return
}
matrix4_from_euler_angles_xyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_xyx_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -955,7 +1034,8 @@ matrix4_from_euler_angles_xyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return
}
matrix4_from_euler_angles_yxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_yxy_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -982,7 +1062,8 @@ matrix4_from_euler_angles_yxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return
}
matrix4_from_euler_angles_yzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_yzy_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1009,7 +1090,8 @@ matrix4_from_euler_angles_yzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return
}
matrix4_from_euler_angles_zyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_zyz_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1036,7 +1118,8 @@ matrix4_from_euler_angles_zyz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return
}
matrix4_from_euler_angles_zxz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_zxz_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1064,7 +1147,8 @@ matrix4_from_euler_angles_zxz_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
}
matrix4_from_euler_angles_xzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_xzy_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1091,7 +1175,8 @@ matrix4_from_euler_angles_xzy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return
}
matrix4_from_euler_angles_yzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_yzx_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1118,7 +1203,8 @@ matrix4_from_euler_angles_yzx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return
}
matrix4_from_euler_angles_zyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_zyx_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1145,7 +1231,8 @@ matrix4_from_euler_angles_zyx_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
return
}
matrix4_from_euler_angles_zxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_euler_angles_zxy_f64 :: proc "contextless" (t1, t2, t3: f64) -> (m: Matrix4f64) {
c1 := math.cos(t1)
s1 := math.sin(t1)
c2 := math.cos(t2)
@@ -1173,7 +1260,8 @@ matrix4_from_euler_angles_zxy_f64 :: proc(t1, t2, t3: f64) -> (m: Matrix4f64) {
}
matrix4_from_yaw_pitch_roll_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix4f64) {
@(require_results)
matrix4_from_yaw_pitch_roll_f64 :: proc "contextless" (yaw, pitch, roll: f64) -> (m: Matrix4f64) {
ch := math.cos(yaw)
sh := math.sin(yaw)
cp := math.cos(pitch)
@@ -1200,7 +1288,8 @@ matrix4_from_yaw_pitch_roll_f64 :: proc(yaw, pitch, roll: f64) -> (m: Matrix4f64
return m
}
euler_angles_xyz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_xyz_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[1, 2], m[2, 2])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 1]*m[0, 1])
T2 := math.atan2(-m[0, 2], C2)
@@ -1213,7 +1302,8 @@ euler_angles_xyz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_yxz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_yxz_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[0, 2], m[2, 2])
C2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 1]*m[1, 1])
T2 := math.atan2(-m[1, 2], C2)
@@ -1226,7 +1316,8 @@ euler_angles_yxz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_xzx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_xzx_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[2, 0], m[1, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0])
@@ -1239,7 +1330,8 @@ euler_angles_xzx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_xyx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_xyx_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[1, 0], -m[2, 0])
S2 := math.sqrt(m[0, 1]*m[0, 1] + m[0, 2]*m[0, 2])
T2 := math.atan2(S2, m[0, 0])
@@ -1252,7 +1344,8 @@ euler_angles_xyx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_yxy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_yxy_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[0, 1], m[2, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1])
@@ -1265,7 +1358,8 @@ euler_angles_yxy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_yzy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_yzy_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[2, 1], -m[0, 1])
S2 := math.sqrt(m[1, 0]*m[1, 0] + m[1, 2]*m[1, 2])
T2 := math.atan2(S2, m[1, 1])
@@ -1277,7 +1371,8 @@ euler_angles_yzy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
t3 = T3
return
}
euler_angles_zyz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_zyz_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[1, 2], m[0, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2])
@@ -1290,7 +1385,8 @@ euler_angles_zyz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_zxz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_zxz_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[0, 2], -m[1, 2])
S2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 1]*m[2, 1])
T2 := math.atan2(S2, m[2, 2])
@@ -1303,7 +1399,8 @@ euler_angles_zxz_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_xzy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_xzy_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[2, 1], m[1, 1])
C2 := math.sqrt(m[0, 0]*m[0, 0] + m[0, 2]*m[0, 2])
T2 := math.atan2(-m[0, 1], C2)
@@ -1316,7 +1413,8 @@ euler_angles_xzy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_yzx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_yzx_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(-m[2, 0], m[0, 0])
C2 := math.sqrt(m[1, 1]*m[1, 1] + m[1, 2]*m[1, 2])
T2 := math.atan2(m[1, 0], C2)
@@ -1329,7 +1427,8 @@ euler_angles_yzx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_zyx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_zyx_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(m[1, 0], m[0, 0])
C2 := math.sqrt(m[2, 1]*m[2, 1] + m[2, 2]*m[2, 2])
T2 := math.atan2(-m[2, 0], C2)
@@ -1342,7 +1441,8 @@ euler_angles_zyx_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
return
}
euler_angles_zxy_from_matrix4_f64 :: proc(m: Matrix4f64) -> (t1, t2, t3: f64) {
@(require_results)
euler_angles_zxy_from_matrix4_f64 :: proc "contextless" (m: Matrix4f64) -> (t1, t2, t3: f64) {
T1 := math.atan2(-m[0, 1], m[1, 1])
C2 := math.sqrt(m[2, 0]*m[2, 0] + m[2, 2]*m[2, 2])
T2 := math.atan2(m[2, 1], C2)
+64 -32
View File
@@ -37,110 +37,142 @@ Vector4_Components :: enum u8 {
a = 3,
}
scalar_f32_swizzle1 :: proc(f: f32, c0: Scalar_Components) -> f32 {
@(require_results)
scalar_f32_swizzle1 :: proc "contextless" (f: f32, c0: Scalar_Components) -> f32 {
return f
}
scalar_f32_swizzle2 :: proc(f: f32, c0, c1: Scalar_Components) -> Vector2f32 {
@(require_results)
scalar_f32_swizzle2 :: proc "contextless" (f: f32, c0, c1: Scalar_Components) -> Vector2f32 {
return {f, f}
}
scalar_f32_swizzle3 :: proc(f: f32, c0, c1, c2: Scalar_Components) -> Vector3f32 {
@(require_results)
scalar_f32_swizzle3 :: proc "contextless" (f: f32, c0, c1, c2: Scalar_Components) -> Vector3f32 {
return {f, f, f}
}
scalar_f32_swizzle4 :: proc(f: f32, c0, c1, c2, c3: Scalar_Components) -> Vector4f32 {
@(require_results)
scalar_f32_swizzle4 :: proc "contextless" (f: f32, c0, c1, c2, c3: Scalar_Components) -> Vector4f32 {
return {f, f, f, f}
}
vector2f32_swizzle1 :: proc(v: Vector2f32, c0: Vector2_Components) -> f32 {
@(require_results)
vector2f32_swizzle1 :: proc "contextless" (v: Vector2f32, c0: Vector2_Components) -> f32 {
return v[c0]
}
vector2f32_swizzle2 :: proc(v: Vector2f32, c0, c1: Vector2_Components) -> Vector2f32 {
@(require_results)
vector2f32_swizzle2 :: proc "contextless" (v: Vector2f32, c0, c1: Vector2_Components) -> Vector2f32 {
return {v[c0], v[c1]}
}
vector2f32_swizzle3 :: proc(v: Vector2f32, c0, c1, c2: Vector2_Components) -> Vector3f32 {
@(require_results)
vector2f32_swizzle3 :: proc "contextless" (v: Vector2f32, c0, c1, c2: Vector2_Components) -> Vector3f32 {
return {v[c0], v[c1], v[c2]}
}
vector2f32_swizzle4 :: proc(v: Vector2f32, c0, c1, c2, c3: Vector2_Components) -> Vector4f32 {
@(require_results)
vector2f32_swizzle4 :: proc "contextless" (v: Vector2f32, c0, c1, c2, c3: Vector2_Components) -> Vector4f32 {
return {v[c0], v[c1], v[c2], v[c3]}
}
vector3f32_swizzle1 :: proc(v: Vector3f32, c0: Vector3_Components) -> f32 {
@(require_results)
vector3f32_swizzle1 :: proc "contextless" (v: Vector3f32, c0: Vector3_Components) -> f32 {
return v[c0]
}
vector3f32_swizzle2 :: proc(v: Vector3f32, c0, c1: Vector3_Components) -> Vector2f32 {
@(require_results)
vector3f32_swizzle2 :: proc "contextless" (v: Vector3f32, c0, c1: Vector3_Components) -> Vector2f32 {
return {v[c0], v[c1]}
}
vector3f32_swizzle3 :: proc(v: Vector3f32, c0, c1, c2: Vector3_Components) -> Vector3f32 {
@(require_results)
vector3f32_swizzle3 :: proc "contextless" (v: Vector3f32, c0, c1, c2: Vector3_Components) -> Vector3f32 {
return {v[c0], v[c1], v[c2]}
}
vector3f32_swizzle4 :: proc(v: Vector3f32, c0, c1, c2, c3: Vector3_Components) -> Vector4f32 {
@(require_results)
vector3f32_swizzle4 :: proc "contextless" (v: Vector3f32, c0, c1, c2, c3: Vector3_Components) -> Vector4f32 {
return {v[c0], v[c1], v[c2], v[c3]}
}
vector4f32_swizzle1 :: proc(v: Vector4f32, c0: Vector4_Components) -> f32 {
@(require_results)
vector4f32_swizzle1 :: proc "contextless" (v: Vector4f32, c0: Vector4_Components) -> f32 {
return v[c0]
}
vector4f32_swizzle2 :: proc(v: Vector4f32, c0, c1: Vector4_Components) -> Vector2f32 {
@(require_results)
vector4f32_swizzle2 :: proc "contextless" (v: Vector4f32, c0, c1: Vector4_Components) -> Vector2f32 {
return {v[c0], v[c1]}
}
vector4f32_swizzle3 :: proc(v: Vector4f32, c0, c1, c2: Vector4_Components) -> Vector3f32 {
@(require_results)
vector4f32_swizzle3 :: proc "contextless" (v: Vector4f32, c0, c1, c2: Vector4_Components) -> Vector3f32 {
return {v[c0], v[c1], v[c2]}
}
vector4f32_swizzle4 :: proc(v: Vector4f32, c0, c1, c2, c3: Vector4_Components) -> Vector4f32 {
@(require_results)
vector4f32_swizzle4 :: proc "contextless" (v: Vector4f32, c0, c1, c2, c3: Vector4_Components) -> Vector4f32 {
return {v[c0], v[c1], v[c2], v[c3]}
}
scalar_f64_swizzle1 :: proc(f: f64, c0: Scalar_Components) -> f64 {
@(require_results)
scalar_f64_swizzle1 :: proc "contextless" (f: f64, c0: Scalar_Components) -> f64 {
return f
}
scalar_f64_swizzle2 :: proc(f: f64, c0, c1: Scalar_Components) -> Vector2f64 {
@(require_results)
scalar_f64_swizzle2 :: proc "contextless" (f: f64, c0, c1: Scalar_Components) -> Vector2f64 {
return {f, f}
}
scalar_f64_swizzle3 :: proc(f: f64, c0, c1, c2: Scalar_Components) -> Vector3f64 {
@(require_results)
scalar_f64_swizzle3 :: proc "contextless" (f: f64, c0, c1, c2: Scalar_Components) -> Vector3f64 {
return {f, f, f}
}
scalar_f64_swizzle4 :: proc(f: f64, c0, c1, c2, c3: Scalar_Components) -> Vector4f64 {
@(require_results)
scalar_f64_swizzle4 :: proc "contextless" (f: f64, c0, c1, c2, c3: Scalar_Components) -> Vector4f64 {
return {f, f, f, f}
}
vector2f64_swizzle1 :: proc(v: Vector2f64, c0: Vector2_Components) -> f64 {
@(require_results)
vector2f64_swizzle1 :: proc "contextless" (v: Vector2f64, c0: Vector2_Components) -> f64 {
return v[c0]
}
vector2f64_swizzle2 :: proc(v: Vector2f64, c0, c1: Vector2_Components) -> Vector2f64 {
@(require_results)
vector2f64_swizzle2 :: proc "contextless" (v: Vector2f64, c0, c1: Vector2_Components) -> Vector2f64 {
return {v[c0], v[c1]}
}
vector2f64_swizzle3 :: proc(v: Vector2f64, c0, c1, c2: Vector2_Components) -> Vector3f64 {
@(require_results)
vector2f64_swizzle3 :: proc "contextless" (v: Vector2f64, c0, c1, c2: Vector2_Components) -> Vector3f64 {
return {v[c0], v[c1], v[c2]}
}
vector2f64_swizzle4 :: proc(v: Vector2f64, c0, c1, c2, c3: Vector2_Components) -> Vector4f64 {
@(require_results)
vector2f64_swizzle4 :: proc "contextless" (v: Vector2f64, c0, c1, c2, c3: Vector2_Components) -> Vector4f64 {
return {v[c0], v[c1], v[c2], v[c3]}
}
vector3f64_swizzle1 :: proc(v: Vector3f64, c0: Vector3_Components) -> f64 {
@(require_results)
vector3f64_swizzle1 :: proc "contextless" (v: Vector3f64, c0: Vector3_Components) -> f64 {
return v[c0]
}
vector3f64_swizzle2 :: proc(v: Vector3f64, c0, c1: Vector3_Components) -> Vector2f64 {
@(require_results)
vector3f64_swizzle2 :: proc "contextless" (v: Vector3f64, c0, c1: Vector3_Components) -> Vector2f64 {
return {v[c0], v[c1]}
}
vector3f64_swizzle3 :: proc(v: Vector3f64, c0, c1, c2: Vector3_Components) -> Vector3f64 {
@(require_results)
vector3f64_swizzle3 :: proc "contextless" (v: Vector3f64, c0, c1, c2: Vector3_Components) -> Vector3f64 {
return {v[c0], v[c1], v[c2]}
}
vector3f64_swizzle4 :: proc(v: Vector3f64, c0, c1, c2, c3: Vector3_Components) -> Vector4f64 {
@(require_results)
vector3f64_swizzle4 :: proc "contextless" (v: Vector3f64, c0, c1, c2, c3: Vector3_Components) -> Vector4f64 {
return {v[c0], v[c1], v[c2], v[c3]}
}
vector4f64_swizzle1 :: proc(v: Vector4f64, c0: Vector4_Components) -> f64 {
@(require_results)
vector4f64_swizzle1 :: proc "contextless" (v: Vector4f64, c0: Vector4_Components) -> f64 {
return v[c0]
}
vector4f64_swizzle2 :: proc(v: Vector4f64, c0, c1: Vector4_Components) -> Vector2f64 {
@(require_results)
vector4f64_swizzle2 :: proc "contextless" (v: Vector4f64, c0, c1: Vector4_Components) -> Vector2f64 {
return {v[c0], v[c1]}
}
vector4f64_swizzle3 :: proc(v: Vector4f64, c0, c1, c2: Vector4_Components) -> Vector3f64 {
@(require_results)
vector4f64_swizzle3 :: proc "contextless" (v: Vector4f64, c0, c1, c2: Vector4_Components) -> Vector3f64 {
return {v[c0], v[c1], v[c2]}
}
vector4f64_swizzle4 :: proc(v: Vector4f64, c0, c1, c2, c3: Vector4_Components) -> Vector4f64 {
@(require_results)
vector4f64_swizzle4 :: proc "contextless" (v: Vector4f64, c0, c1, c2, c3: Vector4_Components) -> Vector4f64 {
return {v[c0], v[c1], v[c2], v[c3]}
}
+391 -249
View File
File diff suppressed because it is too large Load Diff
+27 -23
View File
@@ -5,54 +5,58 @@ import "core:intrinsics"
@(default_calling_convention="none")
foreign _ {
@(link_name="llvm.sin.f16")
@(link_name="llvm.sin.f16", require_results)
sin_f16 :: proc(θ: f16) -> f16 ---
@(link_name="llvm.sin.f32")
@(link_name="llvm.sin.f32", require_results)
sin_f32 :: proc(θ: f32) -> f32 ---
@(link_name="llvm.sin.f64")
@(link_name="llvm.sin.f64", require_results)
sin_f64 :: proc(θ: f64) -> f64 ---
@(link_name="llvm.cos.f16")
@(link_name="llvm.cos.f16", require_results)
cos_f16 :: proc(θ: f16) -> f16 ---
@(link_name="llvm.cos.f32")
@(link_name="llvm.cos.f32", require_results)
cos_f32 :: proc(θ: f32) -> f32 ---
@(link_name="llvm.cos.f64")
@(link_name="llvm.cos.f64", require_results)
cos_f64 :: proc(θ: f64) -> f64 ---
@(link_name="llvm.pow.f16")
@(link_name="llvm.pow.f16", require_results)
pow_f16 :: proc(x, power: f16) -> f16 ---
@(link_name="llvm.pow.f32")
@(link_name="llvm.pow.f32", require_results)
pow_f32 :: proc(x, power: f32) -> f32 ---
@(link_name="llvm.pow.f64")
@(link_name="llvm.pow.f64", require_results)
pow_f64 :: proc(x, power: f64) -> f64 ---
@(link_name="llvm.fmuladd.f16")
@(link_name="llvm.fmuladd.f16", require_results)
fmuladd_f16 :: proc(a, b, c: f16) -> f16 ---
@(link_name="llvm.fmuladd.f32")
@(link_name="llvm.fmuladd.f32", require_results)
fmuladd_f32 :: proc(a, b, c: f32) -> f32 ---
@(link_name="llvm.fmuladd.f64")
@(link_name="llvm.fmuladd.f64", require_results)
fmuladd_f64 :: proc(a, b, c: f64) -> f64 ---
@(link_name="llvm.exp.f16")
@(link_name="llvm.exp.f16", require_results)
exp_f16 :: proc(x: f16) -> f16 ---
@(link_name="llvm.exp.f32")
@(link_name="llvm.exp.f32", require_results)
exp_f32 :: proc(x: f32) -> f32 ---
@(link_name="llvm.exp.f64")
@(link_name="llvm.exp.f64", require_results)
exp_f64 :: proc(x: f64) -> f64 ---
}
@(require_results)
sqrt_f16 :: proc "contextless" (x: f16) -> f16 {
return intrinsics.sqrt(x)
}
@(require_results)
sqrt_f32 :: proc "contextless" (x: f32) -> f32 {
return intrinsics.sqrt(x)
}
@(require_results)
sqrt_f64 :: proc "contextless" (x: f64) -> f64 {
return intrinsics.sqrt(x)
}
@(require_results)
ln_f64 :: proc "contextless" (x: f64) -> f64 {
// The original C code, the long comment, and the constants
// below are from FreeBSD's /usr/src/lib/msun/src/e_log.c
@@ -154,14 +158,14 @@ ln_f64 :: proc "contextless" (x: f64) -> f64 {
return k*LN2_HI - ((hfsq - (s*(hfsq+R) + k*LN2_LO)) - f)
}
ln_f16 :: proc "contextless" (x: f16) -> f16 { return #force_inline f16(ln_f64(f64(x))) }
ln_f32 :: proc "contextless" (x: f32) -> f32 { return #force_inline f32(ln_f64(f64(x))) }
ln_f16le :: proc "contextless" (x: f16le) -> f16le { return #force_inline f16le(ln_f64(f64(x))) }
ln_f16be :: proc "contextless" (x: f16be) -> f16be { return #force_inline f16be(ln_f64(f64(x))) }
ln_f32le :: proc "contextless" (x: f32le) -> f32le { return #force_inline f32le(ln_f64(f64(x))) }
ln_f32be :: proc "contextless" (x: f32be) -> f32be { return #force_inline f32be(ln_f64(f64(x))) }
ln_f64le :: proc "contextless" (x: f64le) -> f64le { return #force_inline f64le(ln_f64(f64(x))) }
ln_f64be :: proc "contextless" (x: f64be) -> f64be { return #force_inline f64be(ln_f64(f64(x))) }
@(require_results) ln_f16 :: proc "contextless" (x: f16) -> f16 { return #force_inline f16(ln_f64(f64(x))) }
@(require_results) ln_f32 :: proc "contextless" (x: f32) -> f32 { return #force_inline f32(ln_f64(f64(x))) }
@(require_results) ln_f16le :: proc "contextless" (x: f16le) -> f16le { return #force_inline f16le(ln_f64(f64(x))) }
@(require_results) ln_f16be :: proc "contextless" (x: f16be) -> f16be { return #force_inline f16be(ln_f64(f64(x))) }
@(require_results) ln_f32le :: proc "contextless" (x: f32le) -> f32le { return #force_inline f32le(ln_f64(f64(x))) }
@(require_results) ln_f32be :: proc "contextless" (x: f32be) -> f32be { return #force_inline f32be(ln_f64(f64(x))) }
@(require_results) ln_f64le :: proc "contextless" (x: f64le) -> f64le { return #force_inline f64le(ln_f64(f64(x))) }
@(require_results) ln_f64be :: proc "contextless" (x: f64be) -> f64be { return #force_inline f64be(ln_f64(f64(x))) }
ln :: proc{
ln_f16, ln_f16le, ln_f16be,
ln_f32, ln_f32le, ln_f32be,
+27 -26
View File
@@ -7,46 +7,47 @@ foreign import "odin_env"
@(default_calling_convention="c")
foreign odin_env {
@(link_name="sin")
@(link_name="sin", require_results)
sin_f64 :: proc(θ: f64) -> f64 ---
@(link_name="cos")
@(link_name="cos", require_results)
cos_f64 :: proc(θ: f64) -> f64 ---
@(link_name="pow")
@(link_name="pow", require_results)
pow_f64 :: proc(x, power: f64) -> f64 ---
@(link_name="fmuladd")
@(link_name="fmuladd", require_results)
fmuladd_f64 :: proc(a, b, c: f64) -> f64 ---
@(link_name="ln")
@(link_name="ln", require_results)
ln_f64 :: proc(x: f64) -> f64 ---
@(link_name="exp")
@(link_name="exp", require_results)
exp_f64 :: proc(x: f64) -> f64 ---
}
@(require_results)
sqrt_f64 :: proc "contextless" (x: f64) -> f64 {
return intrinsics.sqrt(x)
}
sqrt_f16 :: proc "c" (x: f16) -> f16 { return f16(sqrt_f64(f64(x))) }
sin_f16 :: proc "c" (θ: f16) -> f16 { return f16(sin_f64(f64(θ))) }
cos_f16 :: proc "c" (θ: f16) -> f16 { return f16(cos_f64(f64(θ))) }
pow_f16 :: proc "c" (x, power: f16) -> f16 { return f16(pow_f64(f64(x), f64(power))) }
fmuladd_f16 :: proc "c" (a, b, c: f16) -> f16 { return f16(fmuladd_f64(f64(a), f64(a), f64(c))) }
ln_f16 :: proc "c" (x: f16) -> f16 { return f16(ln_f64(f64(x))) }
exp_f16 :: proc "c" (x: f16) -> f16 { return f16(exp_f64(f64(x))) }
@(require_results) sqrt_f16 :: proc "c" (x: f16) -> f16 { return f16(sqrt_f64(f64(x))) }
@(require_results) sin_f16 :: proc "c" (θ: f16) -> f16 { return f16(sin_f64(f64(θ))) }
@(require_results) cos_f16 :: proc "c" (θ: f16) -> f16 { return f16(cos_f64(f64(θ))) }
@(require_results) pow_f16 :: proc "c" (x, power: f16) -> f16 { return f16(pow_f64(f64(x), f64(power))) }
@(require_results) fmuladd_f16 :: proc "c" (a, b, c: f16) -> f16 { return f16(fmuladd_f64(f64(a), f64(a), f64(c))) }
@(require_results) ln_f16 :: proc "c" (x: f16) -> f16 { return f16(ln_f64(f64(x))) }
@(require_results) exp_f16 :: proc "c" (x: f16) -> f16 { return f16(exp_f64(f64(x))) }
sqrt_f32 :: proc "c" (x: f32) -> f32 { return f32(sqrt_f64(f64(x))) }
sin_f32 :: proc "c" (θ: f32) -> f32 { return f32(sin_f64(f64(θ))) }
cos_f32 :: proc "c" (θ: f32) -> f32 { return f32(cos_f64(f64(θ))) }
pow_f32 :: proc "c" (x, power: f32) -> f32 { return f32(pow_f64(f64(x), f64(power))) }
fmuladd_f32 :: proc "c" (a, b, c: f32) -> f32 { return f32(fmuladd_f64(f64(a), f64(a), f64(c))) }
ln_f32 :: proc "c" (x: f32) -> f32 { return f32(ln_f64(f64(x))) }
exp_f32 :: proc "c" (x: f32) -> f32 { return f32(exp_f64(f64(x))) }
@(require_results) sqrt_f32 :: proc "c" (x: f32) -> f32 { return f32(sqrt_f64(f64(x))) }
@(require_results) sin_f32 :: proc "c" (θ: f32) -> f32 { return f32(sin_f64(f64(θ))) }
@(require_results) cos_f32 :: proc "c" (θ: f32) -> f32 { return f32(cos_f64(f64(θ))) }
@(require_results) pow_f32 :: proc "c" (x, power: f32) -> f32 { return f32(pow_f64(f64(x), f64(power))) }
@(require_results) fmuladd_f32 :: proc "c" (a, b, c: f32) -> f32 { return f32(fmuladd_f64(f64(a), f64(a), f64(c))) }
@(require_results) ln_f32 :: proc "c" (x: f32) -> f32 { return f32(ln_f64(f64(x))) }
@(require_results) exp_f32 :: proc "c" (x: f32) -> f32 { return f32(exp_f64(f64(x))) }
ln_f16le :: proc "contextless" (x: f16le) -> f16le { return #force_inline f16le(ln_f64(f64(x))) }
ln_f16be :: proc "contextless" (x: f16be) -> f16be { return #force_inline f16be(ln_f64(f64(x))) }
ln_f32le :: proc "contextless" (x: f32le) -> f32le { return #force_inline f32le(ln_f64(f64(x))) }
ln_f32be :: proc "contextless" (x: f32be) -> f32be { return #force_inline f32be(ln_f64(f64(x))) }
ln_f64le :: proc "contextless" (x: f64le) -> f64le { return #force_inline f64le(ln_f64(f64(x))) }
ln_f64be :: proc "contextless" (x: f64be) -> f64be { return #force_inline f64be(ln_f64(f64(x))) }
@(require_results) ln_f16le :: proc "contextless" (x: f16le) -> f16le { return #force_inline f16le(ln_f64(f64(x))) }
@(require_results) ln_f16be :: proc "contextless" (x: f16be) -> f16be { return #force_inline f16be(ln_f64(f64(x))) }
@(require_results) ln_f32le :: proc "contextless" (x: f32le) -> f32le { return #force_inline f32le(ln_f64(f64(x))) }
@(require_results) ln_f32be :: proc "contextless" (x: f32be) -> f32be { return #force_inline f32be(ln_f64(f64(x))) }
@(require_results) ln_f64le :: proc "contextless" (x: f64le) -> f64le { return #force_inline f64le(ln_f64(f64(x))) }
@(require_results) ln_f64be :: proc "contextless" (x: f64be) -> f64be { return #force_inline f64be(ln_f64(f64(x))) }
ln :: proc{
ln_f16, ln_f16le, ln_f16be,
ln_f32, ln_f32le, ln_f32be,
+14 -12
View File
@@ -117,13 +117,14 @@ erf :: proc{
erf_f64,
}
erf_f16 :: proc "contextless" (x: f16) -> f16 { return f16(erf_f64(f64(x))) }
erf_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(erf_f64(f64(x))) }
erf_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(erf_f64(f64(x))) }
erf_f32 :: proc "contextless" (x: f32) -> f32 { return f32(erf_f64(f64(x))) }
erf_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(erf_f64(f64(x))) }
erf_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(erf_f64(f64(x))) }
@(require_results) erf_f16 :: proc "contextless" (x: f16) -> f16 { return f16(erf_f64(f64(x))) }
@(require_results) erf_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(erf_f64(f64(x))) }
@(require_results) erf_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(erf_f64(f64(x))) }
@(require_results) erf_f32 :: proc "contextless" (x: f32) -> f32 { return f32(erf_f64(f64(x))) }
@(require_results) erf_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(erf_f64(f64(x))) }
@(require_results) erf_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(erf_f64(f64(x))) }
@(require_results)
erf_f64 :: proc "contextless" (x: f64) -> f64 {
erx :: 0h3FEB0AC160000000
// Coefficients for approximation to erf in [0, 0.84375]
@@ -268,13 +269,14 @@ erfc :: proc{
erfc_f64,
}
erfc_f16 :: proc "contextless" (x: f16) -> f16 { return f16(erfc_f64(f64(x))) }
erfc_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(erfc_f64(f64(x))) }
erfc_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(erfc_f64(f64(x))) }
erfc_f32 :: proc "contextless" (x: f32) -> f32 { return f32(erfc_f64(f64(x))) }
erfc_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(erfc_f64(f64(x))) }
erfc_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(erfc_f64(f64(x))) }
@(require_results) erfc_f16 :: proc "contextless" (x: f16) -> f16 { return f16(erfc_f64(f64(x))) }
@(require_results) erfc_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(erfc_f64(f64(x))) }
@(require_results) erfc_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(erfc_f64(f64(x))) }
@(require_results) erfc_f32 :: proc "contextless" (x: f32) -> f32 { return f32(erfc_f64(f64(x))) }
@(require_results) erfc_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(erfc_f64(f64(x))) }
@(require_results) erfc_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(erfc_f64(f64(x))) }
@(require_results)
erfc_f64 :: proc "contextless" (x: f64) -> f64 {
erx :: 0h3FEB0AC160000000
// Coefficients for approximation to erf in [0, 0.84375]
+10 -9
View File
@@ -65,7 +65,7 @@ package math
// The polynomial is valid for 33 <= x <= 172; larger values are only used
// in reciprocal and produce denormalized floats. The lower precision there
// masks any imprecision in the polynomial.
@(private="file")
@(private="file", require_results)
stirling :: proc "contextless" (x: f64) -> (f64, f64) {
@(static) gamS := [?]f64{
+7.87311395793093628397e-04,
@@ -93,6 +93,7 @@ stirling :: proc "contextless" (x: f64) -> (f64, f64) {
return y1, SQRT_TWO_PI * w * y2
}
@(require_results)
gamma_f64 :: proc "contextless" (x: f64) -> f64 {
is_neg_int :: proc "contextless" (x: f64) -> bool {
if x < 0 {
@@ -210,14 +211,14 @@ gamma_f64 :: proc "contextless" (x: f64) -> f64 {
}
gamma_f16 :: proc "contextless" (x: f16) -> f16 { return f16(gamma_f64(f64(x))) }
gamma_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(gamma_f64(f64(x))) }
gamma_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(gamma_f64(f64(x))) }
gamma_f32 :: proc "contextless" (x: f32) -> f32 { return f32(gamma_f64(f64(x))) }
gamma_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(gamma_f64(f64(x))) }
gamma_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(gamma_f64(f64(x))) }
gamma_f64le :: proc "contextless" (x: f64le) -> f64le { return f64le(gamma_f64(f64(x))) }
gamma_f64be :: proc "contextless" (x: f64be) -> f64be { return f64be(gamma_f64(f64(x))) }
@(require_results) gamma_f16 :: proc "contextless" (x: f16) -> f16 { return f16(gamma_f64(f64(x))) }
@(require_results) gamma_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(gamma_f64(f64(x))) }
@(require_results) gamma_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(gamma_f64(f64(x))) }
@(require_results) gamma_f32 :: proc "contextless" (x: f32) -> f32 { return f32(gamma_f64(f64(x))) }
@(require_results) gamma_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(gamma_f64(f64(x))) }
@(require_results) gamma_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(gamma_f64(f64(x))) }
@(require_results) gamma_f64le :: proc "contextless" (x: f64le) -> f64le { return f64le(gamma_f64(f64(x))) }
@(require_results) gamma_f64be :: proc "contextless" (x: f64be) -> f64be { return f64be(gamma_f64(f64(x))) }
gamma :: proc{
gamma_f16, gamma_f16le, gamma_f16be,
+10 -8
View File
@@ -80,7 +80,9 @@ package math
//
@(require_results)
lgamma_f64 :: proc "contextless" (x: f64) -> (lgamma: f64, sign: int) {
@(require_results)
sin_pi :: proc "contextless" (x: f64) -> f64 {
if x < 0.25 {
return -sin(PI * x)
@@ -345,14 +347,14 @@ lgamma_f64 :: proc "contextless" (x: f64) -> (lgamma: f64, sign: int) {
}
lgamma_f16 :: proc "contextless" (x: f16) -> (lgamma: f16, sign: int) { r, s := lgamma_f64(f64(x)); return f16(r), s }
lgamma_f32 :: proc "contextless" (x: f32) -> (lgamma: f32, sign: int) { r, s := lgamma_f64(f64(x)); return f32(r), s }
lgamma_f16le :: proc "contextless" (x: f16le) -> (lgamma: f16le, sign: int) { r, s := lgamma_f64(f64(x)); return f16le(r), s }
lgamma_f16be :: proc "contextless" (x: f16be) -> (lgamma: f16be, sign: int) { r, s := lgamma_f64(f64(x)); return f16be(r), s }
lgamma_f32le :: proc "contextless" (x: f32le) -> (lgamma: f32le, sign: int) { r, s := lgamma_f64(f64(x)); return f32le(r), s }
lgamma_f32be :: proc "contextless" (x: f32be) -> (lgamma: f32be, sign: int) { r, s := lgamma_f64(f64(x)); return f32be(r), s }
lgamma_f64le :: proc "contextless" (x: f64le) -> (lgamma: f64le, sign: int) { r, s := lgamma_f64(f64(x)); return f64le(r), s }
lgamma_f64be :: proc "contextless" (x: f64be) -> (lgamma: f64be, sign: int) { r, s := lgamma_f64(f64(x)); return f64be(r), s }
@(require_results) lgamma_f16 :: proc "contextless" (x: f16) -> (lgamma: f16, sign: int) { r, s := lgamma_f64(f64(x)); return f16(r), s }
@(require_results) lgamma_f32 :: proc "contextless" (x: f32) -> (lgamma: f32, sign: int) { r, s := lgamma_f64(f64(x)); return f32(r), s }
@(require_results) lgamma_f16le :: proc "contextless" (x: f16le) -> (lgamma: f16le, sign: int) { r, s := lgamma_f64(f64(x)); return f16le(r), s }
@(require_results) lgamma_f16be :: proc "contextless" (x: f16be) -> (lgamma: f16be, sign: int) { r, s := lgamma_f64(f64(x)); return f16be(r), s }
@(require_results) lgamma_f32le :: proc "contextless" (x: f32le) -> (lgamma: f32le, sign: int) { r, s := lgamma_f64(f64(x)); return f32le(r), s }
@(require_results) lgamma_f32be :: proc "contextless" (x: f32be) -> (lgamma: f32be, sign: int) { r, s := lgamma_f64(f64(x)); return f32be(r), s }
@(require_results) lgamma_f64le :: proc "contextless" (x: f64le) -> (lgamma: f64le, sign: int) { r, s := lgamma_f64(f64(x)); return f64le(r), s }
@(require_results) lgamma_f64be :: proc "contextless" (x: f64be) -> (lgamma: f64be, sign: int) { r, s := lgamma_f64(f64(x)); return f64be(r), s }
lgamma :: proc{
lgamma_f16, lgamma_f16le, lgamma_f16be,
+9 -8
View File
@@ -90,15 +90,16 @@ log1p :: proc {
log1p_f64le,
log1p_f64be,
}
log1p_f16 :: proc "contextless" (x: f16) -> f16 { return f16(log1p_f64(f64(x))) }
log1p_f32 :: proc "contextless" (x: f32) -> f32 { return f32(log1p_f64(f64(x))) }
log1p_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(log1p_f64(f64(x))) }
log1p_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(log1p_f64(f64(x))) }
log1p_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(log1p_f64(f64(x))) }
log1p_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(log1p_f64(f64(x))) }
log1p_f64le :: proc "contextless" (x: f64le) -> f64le { return f64le(log1p_f64(f64(x))) }
log1p_f64be :: proc "contextless" (x: f64be) -> f64be { return f64be(log1p_f64(f64(x))) }
@(require_results) log1p_f16 :: proc "contextless" (x: f16) -> f16 { return f16(log1p_f64(f64(x))) }
@(require_results) log1p_f32 :: proc "contextless" (x: f32) -> f32 { return f32(log1p_f64(f64(x))) }
@(require_results) log1p_f16le :: proc "contextless" (x: f16le) -> f16le { return f16le(log1p_f64(f64(x))) }
@(require_results) log1p_f16be :: proc "contextless" (x: f16be) -> f16be { return f16be(log1p_f64(f64(x))) }
@(require_results) log1p_f32le :: proc "contextless" (x: f32le) -> f32le { return f32le(log1p_f64(f64(x))) }
@(require_results) log1p_f32be :: proc "contextless" (x: f32be) -> f32be { return f32be(log1p_f64(f64(x))) }
@(require_results) log1p_f64le :: proc "contextless" (x: f64le) -> f64le { return f64le(log1p_f64(f64(x))) }
@(require_results) log1p_f64be :: proc "contextless" (x: f64be) -> f64be { return f64be(log1p_f64(f64(x))) }
@(require_results)
log1p_f64 :: proc "contextless" (x: f64) -> f64 {
SQRT2_M1 :: 0h3fda827999fcef34 // sqrt(2)-1
SQRT2_HALF_M1 :: 0hbfd2bec333018866 // sqrt(2)/2-1
+9
View File
@@ -20,6 +20,7 @@ Vec4 :: [4]f64
/*
2D Simplex noise, standard lattice orientation.
*/
@(require_results)
noise_2d :: proc(seed: i64, coord: Vec2) -> (value: f32) {
// Get points for A2* lattice
skew := SKEW_2D * (coord.x + coord.y)
@@ -35,6 +36,7 @@ noise_2d :: proc(seed: i64, coord: Vec2) -> (value: f32) {
unless your map is centered around an equator. It's a subtle
difference, but the option is here to make it an easy choice.
*/
@(require_results)
noise_2d_improve_x :: proc(seed: i64, coord: Vec2) -> (value: f32) {
// Skew transform and rotation baked into one.
xx := coord.x * ROOT_2_OVER_2
@@ -51,6 +53,7 @@ noise_2d_improve_x :: proc(seed: i64, coord: Vec2) -> (value: f32) {
If Z is vertical in world coordinates, call `noise_3d_improve_xz(x, y, Z)`.
For a time varied animation, call `noise_3d_improve_xz(x, y, T)`.
*/
@(require_results)
noise_3d_improve_xy :: proc(seed: i64, coord: Vec3) -> (value: f32) {
/*
Re-orient the cubic lattices without skewing, so Z points up the main lattice diagonal,
@@ -75,6 +78,7 @@ noise_3d_improve_xy :: proc(seed: i64, coord: Vec3) -> (value: f32) {
If Z is vertical in world coordinates, call `noise_3d_improve_xz(x, Z, y)` or use `noise_3d_improve_xy`.
For a time varied animation, call `noise_3d_improve_xz(x, T, y)` or use `noise_3d_improve_xy`.
*/
@(require_results)
noise_3d_improve_xz :: proc(seed: i64, coord: Vec3) -> (value: f32) {
/*
Re-orient the cubic lattices without skewing, so Y points up the main lattice diagonal,
@@ -96,6 +100,7 @@ noise_3d_improve_xz :: proc(seed: i64, coord: Vec3) -> (value: f32) {
Use `noise_3d_improve_xy` or `noise_3d_improve_xz` instead, wherever appropriate.
They have less diagonal bias. This function's best use is as a fallback.
*/
@(require_results)
noise_3d_fallback :: proc(seed: i64, coord: Vec3) -> (value: f32) {
/*
Re-orient the cubic lattices via rotation, to produce a familiar look.
@@ -114,6 +119,7 @@ noise_3d_fallback :: proc(seed: i64, coord: Vec3) -> (value: f32) {
Recommended for time-varied animations which texture a 3D object (W=time)
in a space where Z is vertical.
*/
@(require_results)
noise_4d_improve_xyz_improve_xy :: proc(seed: i64, coord: Vec4) -> (value: f32) {
xy := coord.x + coord.y
s2 := xy * -0.21132486540518699998
@@ -133,6 +139,7 @@ noise_4d_improve_xyz_improve_xy :: proc(seed: i64, coord: Vec4) -> (value: f32)
Recommended for time-varied animations which texture a 3D object (W=time)
in a space where Y is vertical.
*/
@(require_results)
noise_4d_improve_xyz_improve_xz :: proc(seed: i64, coord: Vec4) -> (value: f32) {
xz := coord.x + coord.z
s2 := xz * -0.21132486540518699998
@@ -152,6 +159,7 @@ noise_4d_improve_xyz_improve_xz :: proc(seed: i64, coord: Vec4) -> (value: f32)
Recommended for time-varied animations which texture a 3D object (W=time)
where there isn't a clear distinction between horizontal and vertical
*/
@(require_results)
noise_4d_improve_xyz :: proc(seed: i64, coord: Vec4) -> (value: f32) {
xyz := coord.x + coord.y + coord.z
ww := coord.w * 0.2236067977499788
@@ -164,6 +172,7 @@ noise_4d_improve_xyz :: proc(seed: i64, coord: Vec4) -> (value: f32) {
/*
4D OpenSimplex2 noise, fallback lattice orientation.
*/
@(require_results)
noise_4d_fallback :: proc(seed: i64, coord: Vec4) -> (value: f32) {
// Get points for A4 lattice
skew := f64(SKEW_4D) * (coord.x + coord.y + coord.z + coord.w)
+26
View File
@@ -7,6 +7,7 @@ float32_uniform :: float32_range
// Triangular Distribution
// See: http://wikipedia.org/wiki/Triangular_distribution
@(require_results)
float64_triangular :: proc(lo, hi: f64, mode: Maybe(f64), r: ^Rand = nil) -> f64 {
if hi-lo == 0 {
return lo
@@ -24,6 +25,7 @@ float64_triangular :: proc(lo, hi: f64, mode: Maybe(f64), r: ^Rand = nil) -> f64
}
// Triangular Distribution
// See: http://wikipedia.org/wiki/Triangular_distribution
@(require_results)
float32_triangular :: proc(lo, hi: f32, mode: Maybe(f32), r: ^Rand = nil) -> f32 {
if hi-lo == 0 {
return lo
@@ -41,20 +43,24 @@ float32_triangular :: proc(lo, hi: f32, mode: Maybe(f32), r: ^Rand = nil) -> f32
// Normal/Gaussian Distribution
@(require_results)
float64_normal :: proc(mean, stddev: f64, r: ^Rand = nil) -> f64 {
return norm_float64(r) * stddev + mean
}
// Normal/Gaussian Distribution
@(require_results)
float32_normal :: proc(mean, stddev: f32, r: ^Rand = nil) -> f32 {
return f32(float64_normal(f64(mean), f64(stddev), r))
}
// Log Normal Distribution
@(require_results)
float64_log_normal :: proc(mean, stddev: f64, r: ^Rand = nil) -> f64 {
return math.exp(float64_normal(mean, stddev, r))
}
// Log Normal Distribution
@(require_results)
float32_log_normal :: proc(mean, stddev: f32, r: ^Rand = nil) -> f32 {
return f32(float64_log_normal(f64(mean), f64(stddev), r))
}
@@ -65,6 +71,7 @@ float32_log_normal :: proc(mean, stddev: f32, r: ^Rand = nil) -> f32 {
// Return values range from
// 0 to positive infinity if lambda > 0
// negative infinity to 0 if lambda <= 0
@(require_results)
float64_exponential :: proc(lambda: f64, r: ^Rand = nil) -> f64 {
return - math.ln(1 - float64(r)) / lambda
}
@@ -73,6 +80,7 @@ float64_exponential :: proc(lambda: f64, r: ^Rand = nil) -> f64 {
// Return values range from
// 0 to positive infinity if lambda > 0
// negative infinity to 0 if lambda <= 0
@(require_results)
float32_exponential :: proc(lambda: f32, r: ^Rand = nil) -> f32 {
return f32(float64_exponential(f64(lambda), r))
}
@@ -87,6 +95,7 @@ float32_exponential :: proc(lambda: f32, r: ^Rand = nil) -> f32 {
// math.gamma(alpha) * math.pow(beta, alpha)
//
// mean is alpha*beta, variance is math.pow(alpha*beta, 2)
@(require_results)
float64_gamma :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
if alpha <= 0 || beta <= 0 {
panic(#procedure + ": alpha and beta must be > 0.0")
@@ -152,6 +161,7 @@ float64_gamma :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
// math.gamma(alpha) * math.pow(beta, alpha)
//
// mean is alpha*beta, variance is math.pow(alpha*beta, 2)
@(require_results)
float32_gamma :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
return f32(float64_gamma(f64(alpha), f64(beta), r))
}
@@ -162,6 +172,7 @@ float32_gamma :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
// Required: alpha > 0 and beta > 0
//
// Return values range between 0 and 1
@(require_results)
float64_beta :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
if alpha <= 0 || beta <= 0 {
panic(#procedure + ": alpha and beta must be > 0.0")
@@ -178,6 +189,7 @@ float64_beta :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
// Required: alpha > 0 and beta > 0
//
// Return values range between 0 and 1
@(require_results)
float32_beta :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
return f32(float64_beta(f64(alpha), f64(beta), r))
}
@@ -185,22 +197,26 @@ float32_beta :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
// Pareto distribution, `alpha` is the shape parameter.
// https://wikipedia.org/wiki/Pareto_distribution
@(require_results)
float64_pareto :: proc(alpha: f64, r: ^Rand = nil) -> f64 {
return math.pow(1 - float64(r), -1.0 / alpha)
}
// Pareto distribution, `alpha` is the shape parameter.
// https://wikipedia.org/wiki/Pareto_distribution
@(require_results)
float32_pareto :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
return f32(float64_pareto(f64(alpha), r))
}
// Weibull distribution, `alpha` is the scale parameter, `beta` is the shape parameter.
@(require_results)
float64_weibull :: proc(alpha, beta: f64, r: ^Rand = nil) -> f64 {
u := 1 - float64(r)
return alpha * math.pow(-math.ln(u), 1.0/beta)
}
// Weibull distribution, `alpha` is the scale parameter, `beta` is the shape parameter.
@(require_results)
float32_weibull :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
return f32(float64_weibull(f64(alpha), f64(beta), r))
}
@@ -210,6 +226,7 @@ float32_weibull :: proc(alpha, beta: f32, r: ^Rand = nil) -> f32 {
// `mean_angle` is the in mean angle between 0 and 2pi radians
// `kappa` is the concentration parameter which must be >= 0
// When `kappa` is zero, the Distribution is a uniform Distribution over the range 0 to 2pi
@(require_results)
float64_von_mises :: proc(mean_angle, kappa: f64, r: ^Rand = nil) -> f64 {
// Fisher, N.I., "Statistical Analysis of Circular Data", Cambridge University Press, 1993.
@@ -245,6 +262,7 @@ float64_von_mises :: proc(mean_angle, kappa: f64, r: ^Rand = nil) -> f64 {
// `mean_angle` is the in mean angle between 0 and 2pi radians
// `kappa` is the concentration parameter which must be >= 0
// When `kappa` is zero, the Distribution is a uniform Distribution over the range 0 to 2pi
@(require_results)
float32_von_mises :: proc(mean_angle, kappa: f32, r: ^Rand = nil) -> f32 {
return f32(float64_von_mises(f64(mean_angle), f64(kappa), r))
}
@@ -252,6 +270,7 @@ float32_von_mises :: proc(mean_angle, kappa: f32, r: ^Rand = nil) -> f32 {
// Cauchy-Lorentz Distribution
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
@(require_results)
float64_cauchy_lorentz :: proc(x_0, gamma: f64, r: ^Rand = nil) -> f64 {
assert(gamma > 0)
@@ -261,6 +280,7 @@ float64_cauchy_lorentz :: proc(x_0, gamma: f64, r: ^Rand = nil) -> f64 {
}
// Cauchy-Lorentz Distribution
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
@(require_results)
float32_cauchy_lorentz :: proc(x_0, gamma: f32, r: ^Rand = nil) -> f32 {
return f32(float64_cauchy_lorentz(f64(x_0), f64(gamma), r))
}
@@ -268,12 +288,14 @@ float32_cauchy_lorentz :: proc(x_0, gamma: f32, r: ^Rand = nil) -> f32 {
// Log Cauchy-Lorentz Distribution
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
@(require_results)
float64_log_cauchy_lorentz :: proc(x_0, gamma: f64, r: ^Rand = nil) -> f64 {
assert(gamma > 0)
return math.exp(math.tan(math.PI * (float64(r) - 0.5))*gamma + x_0)
}
// Log Cauchy-Lorentz Distribution
// `x_0` is the location, `gamma` is the scale where `gamma` > 0
@(require_results)
float32_log_cauchy_lorentz :: proc(x_0, gamma: f32, r: ^Rand = nil) -> f32 {
return f32(float64_log_cauchy_lorentz(f64(x_0), f64(gamma), r))
}
@@ -281,6 +303,7 @@ float32_log_cauchy_lorentz :: proc(x_0, gamma: f32, r: ^Rand = nil) -> f32 {
// Laplace Distribution
// `b` is the scale where `b` > 0
@(require_results)
float64_laplace :: proc(mean, b: f64, r: ^Rand = nil) -> f64 {
assert(b > 0)
p := float64(r)-0.5
@@ -288,6 +311,7 @@ float64_laplace :: proc(mean, b: f64, r: ^Rand = nil) -> f64 {
}
// Laplace Distribution
// `b` is the scale where `b` > 0
@(require_results)
float32_laplace :: proc(mean, b: f32, r: ^Rand = nil) -> f32 {
return f32(float64_laplace(f64(mean), f64(b), r))
}
@@ -296,6 +320,7 @@ float32_laplace :: proc(mean, b: f32, r: ^Rand = nil) -> f32 {
// Gompertz Distribution
// `eta` is the shape, `b` is the scale
// Both `eta` and `b` must be > 0
@(require_results)
float64_gompertz :: proc(eta, b: f64, r: ^Rand = nil) -> f64 {
if eta <= 0 || b <= 0 {
panic(#procedure + ": eta and b must be > 0.0")
@@ -307,6 +332,7 @@ float64_gompertz :: proc(eta, b: f64, r: ^Rand = nil) -> f64 {
// Gompertz Distribution
// `eta` is the shape, `b` is the scale
// Both `eta` and `b` must be > 0
@(require_results)
float32_gompertz :: proc(eta, b: f32, r: ^Rand = nil) -> f32 {
return f32(float64_gompertz(f64(eta), f64(b), r))
}
+1
View File
@@ -15,6 +15,7 @@ import "core:math"
// https://www.jstatsoft.org/index.php/jss/article/view/v005i08/ziggurat.pdf [pdf]
// https://www.jstatsoft.org/article/view/v005i08 [web page]
//
@(require_results)
exp_float64 :: proc(r: ^Rand = nil) -> f64 {
re :: 7.69711747013104972
+1
View File
@@ -17,6 +17,7 @@ import "core:math"
// https://www.jstatsoft.org/index.php/jss/article/view/v005i08/ziggurat.pdf [pdf]
// https://www.jstatsoft.org/article/view/v005i08 [web page]
//
@(require_results)
norm_float64 :: proc(r: ^Rand = nil) -> f64 {
rn :: 3.442619855899
+18 -7
View File
@@ -16,6 +16,7 @@ set_global_seed :: proc(seed: u64) {
init(&global_rand, seed)
}
@(require_results)
create :: proc(seed: u64) -> Rand {
r: Rand
init(&r, seed)
@@ -60,14 +61,17 @@ _random :: proc(r: ^Rand) -> u32 {
return (xor_shifted >> rot) | (xor_shifted << ((-rot) & 31))
}
@(require_results)
uint32 :: proc(r: ^Rand = nil) -> u32 { return _random(r) }
@(require_results)
uint64 :: proc(r: ^Rand = nil) -> u64 {
a := u64(_random(r))
b := u64(_random(r))
return (a<<32) | b
}
@(require_results)
uint128 :: proc(r: ^Rand = nil) -> u128 {
a := u128(_random(r))
b := u128(_random(r))
@@ -76,10 +80,11 @@ uint128 :: proc(r: ^Rand = nil) -> u128 {
return (a<<96) | (b<<64) | (c<<32) | d
}
int31 :: proc(r: ^Rand = nil) -> i32 { return i32(uint32(r) << 1 >> 1) }
int63 :: proc(r: ^Rand = nil) -> i64 { return i64(uint64(r) << 1 >> 1) }
int127 :: proc(r: ^Rand = nil) -> i128 { return i128(uint128(r) << 1 >> 1) }
@(require_results) int31 :: proc(r: ^Rand = nil) -> i32 { return i32(uint32(r) << 1 >> 1) }
@(require_results) int63 :: proc(r: ^Rand = nil) -> i64 { return i64(uint64(r) << 1 >> 1) }
@(require_results) int127 :: proc(r: ^Rand = nil) -> i128 { return i128(uint128(r) << 1 >> 1) }
@(require_results)
int31_max :: proc(n: i32, r: ^Rand = nil) -> i32 {
if n <= 0 {
panic("Invalid argument to int31_max")
@@ -95,6 +100,7 @@ int31_max :: proc(n: i32, r: ^Rand = nil) -> i32 {
return v % n
}
@(require_results)
int63_max :: proc(n: i64, r: ^Rand = nil) -> i64 {
if n <= 0 {
panic("Invalid argument to int63_max")
@@ -110,6 +116,7 @@ int63_max :: proc(n: i64, r: ^Rand = nil) -> i64 {
return v % n
}
@(require_results)
int127_max :: proc(n: i128, r: ^Rand = nil) -> i128 {
if n <= 0 {
panic("Invalid argument to int127_max")
@@ -125,6 +132,7 @@ int127_max :: proc(n: i128, r: ^Rand = nil) -> i128 {
return v % n
}
@(require_results)
int_max :: proc(n: int, r: ^Rand = nil) -> int {
if n <= 0 {
panic("Invalid argument to int_max")
@@ -137,13 +145,14 @@ int_max :: proc(n: int, r: ^Rand = nil) -> int {
}
// Uniform random distribution [0, 1)
float64 :: proc(r: ^Rand = nil) -> f64 { return f64(int63_max(1<<53, r)) / (1 << 53) }
@(require_results) float64 :: proc(r: ^Rand = nil) -> f64 { return f64(int63_max(1<<53, r)) / (1 << 53) }
// Uniform random distribution [0, 1)
float32 :: proc(r: ^Rand = nil) -> f32 { return f32(float64(r)) }
@(require_results) float32 :: proc(r: ^Rand = nil) -> f32 { return f32(float64(r)) }
float64_range :: proc(lo, hi: f64, r: ^Rand = nil) -> f64 { return (hi-lo)*float64(r) + lo }
float32_range :: proc(lo, hi: f32, r: ^Rand = nil) -> f32 { return (hi-lo)*float32(r) + lo }
@(require_results) float64_range :: proc(lo, hi: f64, r: ^Rand = nil) -> f64 { return (hi-lo)*float64(r) + lo }
@(require_results) float32_range :: proc(lo, hi: f32, r: ^Rand = nil) -> f32 { return (hi-lo)*float32(r) + lo }
@(require_results)
read :: proc(p: []byte, r: ^Rand = nil) -> (n: int) {
pos := i8(0)
val := i64(0)
@@ -160,6 +169,7 @@ read :: proc(p: []byte, r: ^Rand = nil) -> (n: int) {
}
// perm returns a slice of n ints in a pseudo-random permutation of integers in the range [0, n)
@(require_results)
perm :: proc(n: int, r: ^Rand = nil, allocator := context.allocator) -> []int {
m := make([]int, n, allocator)
for i := 0; i < n; i += 1 {
@@ -184,6 +194,7 @@ shuffle :: proc(array: $T/[]$E, r: ^Rand = nil) {
}
// Returns a random element from the given slice
@(require_results)
choice :: proc(array: $T/[]$E, r: ^Rand = nil) -> (res: E) {
n := i64(len(array))
if n < 1 {
+1
View File
@@ -2,6 +2,7 @@ package rand
import "core:sys/darwin"
@(require_results)
_system_random :: proc() -> u32 {
for {
value: u32
+1
View File
@@ -2,6 +2,7 @@ package rand
import "core:sys/unix"
@(require_results)
_system_random :: proc() -> u32 {
for {
value: u32
+1
View File
@@ -2,6 +2,7 @@ package rand
import win32 "core:sys/windows"
@(require_results)
_system_random :: proc() -> u32 {
value: u32
status := win32.BCryptGenRandom(nil, ([^]u8)(&value), 4, win32.BCRYPT_USE_SYSTEM_PREFERRED_RNG)
+33 -33
View File
@@ -60,15 +60,18 @@ DEFAULT_PAGE_SIZE ::
16 * 1024 when ODIN_OS == .Darwin && ODIN_ARCH == .arm64 else
4 * 1024
alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> rawptr {
data, _ := runtime.mem_alloc(size, alignment, allocator, loc)
return raw_data(data)
@(require_results)
alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (rawptr, Allocator_Error) {
data, err := runtime.mem_alloc(size, alignment, allocator, loc)
return raw_data(data), err
}
@(require_results)
alloc_bytes :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
return runtime.mem_alloc(size, alignment, allocator, loc)
}
@(require_results)
alloc_bytes_non_zeroed :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
return runtime.mem_alloc_non_zeroed(size, alignment, allocator, loc)
}
@@ -93,15 +96,18 @@ free_all :: proc(allocator := context.allocator, loc := #caller_location) -> All
return runtime.mem_free_all(allocator, loc)
}
resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> rawptr {
data, _ := runtime.mem_resize(ptr, old_size, new_size, alignment, allocator, loc)
return raw_data(data)
@(require_results)
resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (rawptr, Allocator_Error) {
data, err := runtime.mem_resize(ptr, old_size, new_size, alignment, allocator, loc)
return raw_data(data), err
}
@(require_results)
resize_bytes :: proc(old_data: []byte, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
return runtime.mem_resize(raw_data(old_data), len(old_data), new_size, alignment, allocator, loc)
}
@(require_results)
query_features :: proc(allocator: Allocator, loc := #caller_location) -> (set: Allocator_Mode_Set) {
if allocator.procedure != nil {
allocator.procedure(allocator.data, .Query_Features, 0, 0, &set, 0, loc)
@@ -110,6 +116,7 @@ query_features :: proc(allocator: Allocator, loc := #caller_location) -> (set: A
return nil
}
@(require_results)
query_info :: proc(pointer: rawptr, allocator: Allocator, loc := #caller_location) -> (props: Allocator_Query_Info) {
props.pointer = pointer
if allocator.procedure != nil {
@@ -146,14 +153,17 @@ delete :: proc{
}
@(require_results)
new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) {
return new_aligned(T, align_of(T), allocator, loc)
}
@(require_results)
new_aligned :: proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) {
data := alloc_bytes(size_of(T), alignment, allocator, loc) or_return
t = (^T)(raw_data(data))
return
}
@(require_results)
new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) {
backing := alloc_bytes(size_of(T), align_of(T), allocator, loc) or_return
t = (^T)(raw_data(backing))
@@ -164,6 +174,7 @@ new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_locat
return nil, .Out_Of_Memory
}
@(require_results)
make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (slice: T, err: Allocator_Error) {
runtime.make_slice_error_loc(loc, len)
data := alloc_bytes(size_of(E)*len, alignment, allocator, loc) or_return
@@ -173,15 +184,19 @@ make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocat
slice = transmute(T)Raw_Slice{raw_data(data), len}
return
}
@(require_results)
make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) {
return make_aligned(T, len, align_of(E), allocator, loc)
}
@(require_results)
make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) {
return make_dynamic_array_len_cap(T, 0, 16, allocator, loc)
}
@(require_results)
make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) {
return make_dynamic_array_len_cap(T, len, len, allocator, loc)
}
@(require_results)
make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) {
runtime.make_dynamic_array_error_loc(loc, len, cap)
data := alloc_bytes(size_of(E)*cap, align_of(E), allocator, loc) or_return
@@ -192,14 +207,15 @@ make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #a
array = transmute(T)s
return
}
make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = 1<<runtime.MAP_MIN_LOG2_CAPACITY, allocator := context.allocator, loc := #caller_location) -> T {
@(require_results)
make_map :: proc($T: typeid/map[$K]$E, #any_int cap: int = 1<<runtime.MAP_MIN_LOG2_CAPACITY, allocator := context.allocator, loc := #caller_location) -> (m: T, err: Allocator_Error) {
runtime.make_map_expr_error_loc(loc, cap)
context.allocator = allocator
m: T
reserve_map(&m, cap, loc)
return m
err = reserve_map(&m, cap, loc)
return
}
@(require_results)
make_multi_pointer :: proc($T: typeid/[^]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (mp: T, err: Allocator_Error) {
runtime.make_slice_error_loc(loc, len)
data := alloc_bytes(size_of(E)*len, align_of(E), allocator, loc) or_return
@@ -220,30 +236,14 @@ make :: proc{
}
default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> rawptr {
if old_memory == nil {
return alloc(new_size, alignment, allocator, loc)
}
if new_size == 0 {
free(old_memory, allocator, loc)
return nil
}
if new_size == old_size {
return old_memory
}
new_memory := alloc(new_size, alignment, allocator, loc)
if new_memory == nil {
return nil
}
copy(new_memory, old_memory, min(old_size, new_size))
free(old_memory, allocator, loc)
return new_memory
@(require_results)
default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> (res: rawptr, err: Allocator_Error) {
data: []byte
data, err = default_resize_bytes_align(([^]byte)(old_memory)[:old_size], new_size, alignment, allocator, loc)
res = raw_data(data)
return
}
@(require_results)
default_resize_bytes_align :: proc(old_data: []byte, new_size, alignment: int, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) {
old_memory := raw_data(old_data)
old_size := len(old_data)
+19 -3
View File
@@ -2,6 +2,7 @@ package mem
import "core:intrinsics"
import "core:runtime"
import "core:sync"
nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
size, alignment: int,
@@ -46,6 +47,7 @@ init_arena :: proc(a: ^Arena, data: []byte) {
a.temp_count = 0
}
@(require_results)
arena_allocator :: proc(arena: ^Arena) -> Allocator {
return Allocator{
procedure = arena_allocator_proc,
@@ -100,6 +102,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
return nil, nil
}
@(require_results)
begin_arena_temp_memory :: proc(a: ^Arena) -> Arena_Temp_Memory {
tmp: Arena_Temp_Memory
tmp.arena = a
@@ -286,6 +289,7 @@ scratch_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
return nil, nil
}
@(require_results)
scratch_allocator :: proc(allocator: ^Scratch_Allocator) -> Allocator {
return Allocator{
procedure = scratch_allocator_proc,
@@ -325,6 +329,7 @@ init_stack :: proc(s: ^Stack, data: []byte) {
s.peak_used = 0
}
@(require_results)
stack_allocator :: proc(stack: ^Stack) -> Allocator {
return Allocator{
procedure = stack_allocator_proc,
@@ -490,6 +495,7 @@ init_small_stack :: proc(s: ^Small_Stack, data: []byte) {
s.peak_used = 0
}
@(require_results)
small_stack_allocator :: proc(stack: ^Small_Stack) -> Allocator {
return Allocator{
procedure = small_stack_allocator_proc,
@@ -673,6 +679,7 @@ dynamic_pool_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode
}
@(require_results)
dynamic_pool_allocator :: proc(pool: ^Dynamic_Pool) -> Allocator {
return Allocator{
procedure = dynamic_pool_allocator_proc,
@@ -705,12 +712,13 @@ dynamic_pool_destroy :: proc(using pool: ^Dynamic_Pool) {
}
dynamic_pool_alloc :: proc(pool: ^Dynamic_Pool, bytes: int) -> rawptr {
@(require_results)
dynamic_pool_alloc :: proc(pool: ^Dynamic_Pool, bytes: int) -> (rawptr, Allocator_Error) {
data, err := dynamic_pool_alloc_bytes(pool, bytes)
assert(err == nil)
return raw_data(data)
return raw_data(data), err
}
@(require_results)
dynamic_pool_alloc_bytes :: proc(using pool: ^Dynamic_Pool, bytes: int) -> ([]byte, Allocator_Error) {
cycle_new_block :: proc(using pool: ^Dynamic_Pool) -> (err: Allocator_Error) {
if block_allocator.procedure == nil {
@@ -836,6 +844,7 @@ panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
return nil, nil
}
@(require_results)
panic_allocator :: proc() -> Allocator {
return Allocator{
procedure = panic_allocator_proc,
@@ -860,6 +869,7 @@ Tracking_Allocator :: struct {
backing: Allocator,
allocation_map: map[rawptr]Tracking_Allocator_Entry,
bad_free_array: [dynamic]Tracking_Allocator_Bad_Free_Entry,
mutex: sync.Mutex,
clear_on_free_all: bool,
}
@@ -880,11 +890,14 @@ tracking_allocator_destroy :: proc(t: ^Tracking_Allocator) {
tracking_allocator_clear :: proc(t: ^Tracking_Allocator) {
sync.mutex_lock(&t.mutex)
clear(&t.allocation_map)
clear(&t.bad_free_array)
sync.mutex_unlock(&t.mutex)
}
@(require_results)
tracking_allocator :: proc(data: ^Tracking_Allocator) -> Allocator {
return Allocator{
data = data,
@@ -896,6 +909,9 @@ tracking_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
size, alignment: int,
old_memory: rawptr, old_size: int, loc := #caller_location) -> (result: []byte, err: Allocator_Error) {
data := (^Tracking_Allocator)(allocator_data)
sync.mutex_guard(&data.mutex)
if mode == .Query_Info {
info := (^Allocator_Query_Info)(old_memory)
if info != nil && info.pointer != nil {
+28
View File
@@ -53,14 +53,17 @@ compare :: proc "contextless" (a, b: []byte) -> int {
return res
}
@(require_results)
compare_byte_ptrs :: proc "contextless" (a, b: ^byte, n: int) -> int #no_bounds_check {
return runtime.memory_compare(a, b, n)
}
@(require_results)
check_zero :: proc(data: []byte) -> bool {
return check_zero_ptr(raw_data(data), len(data))
}
@(require_results)
check_zero_ptr :: proc(ptr: rawptr, len: int) -> bool {
switch {
case len <= 0:
@@ -101,11 +104,13 @@ check_zero_ptr :: proc(ptr: rawptr, len: int) -> bool {
return true
}
@(require_results)
simple_equal :: proc "contextless" (a, b: $T) -> bool where intrinsics.type_is_simple_compare(T) {
a, b := a, b
return compare_byte_ptrs((^byte)(&a), (^byte)(&b), size_of(T)) == 0
}
@(require_results)
compare_ptrs :: proc "contextless" (a, b: rawptr, n: int) -> int {
return compare_byte_ptrs((^byte)(a), (^byte)(b), n)
}
@@ -113,20 +118,24 @@ compare_ptrs :: proc "contextless" (a, b: rawptr, n: int) -> int {
ptr_offset :: intrinsics.ptr_offset
ptr_sub :: intrinsics.ptr_sub
@(require_results)
slice_ptr :: proc "contextless" (ptr: ^$T, len: int) -> []T {
return ([^]T)(ptr)[:len]
}
@(require_results)
byte_slice :: #force_inline proc "contextless" (data: rawptr, #any_int len: int) -> []byte {
return ([^]u8)(data)[:max(len, 0)]
}
@(require_results)
slice_to_bytes :: proc "contextless" (slice: $E/[]$T) -> []byte {
s := transmute(Raw_Slice)slice
s.len *= size_of(T)
return transmute([]byte)s
}
@(require_results)
slice_data_cast :: proc "contextless" ($T: typeid/[]$A, slice: $S/[]$B) -> T {
when size_of(A) == 0 || size_of(B) == 0 {
return nil
@@ -137,11 +146,13 @@ slice_data_cast :: proc "contextless" ($T: typeid/[]$A, slice: $S/[]$B) -> T {
}
}
@(require_results)
slice_to_components :: proc "contextless" (slice: $E/[]$T) -> (data: ^T, len: int) {
s := transmute(Raw_Slice)slice
return (^T)(s.data), s.len
}
@(require_results)
buffer_from_slice :: proc "contextless" (backing: $T/[]$E) -> [dynamic]E {
return transmute([dynamic]E)Raw_Dynamic_Array{
data = raw_data(backing),
@@ -154,10 +165,12 @@ buffer_from_slice :: proc "contextless" (backing: $T/[]$E) -> [dynamic]E {
}
}
@(require_results)
ptr_to_bytes :: proc "contextless" (ptr: ^$T, len := 1) -> []byte {
return transmute([]byte)Raw_Slice{ptr, len*size_of(T)}
}
@(require_results)
any_to_bytes :: proc "contextless" (val: any) -> []byte {
ti := type_info_of(val.id)
size := ti != nil ? ti.size : 0
@@ -165,6 +178,7 @@ any_to_bytes :: proc "contextless" (val: any) -> []byte {
}
@(require_results)
is_power_of_two :: proc "contextless" (x: uintptr) -> bool {
if x <= 0 {
return false
@@ -172,10 +186,12 @@ is_power_of_two :: proc "contextless" (x: uintptr) -> bool {
return (x & (x-1)) == 0
}
@(require_results)
align_forward :: proc(ptr: rawptr, align: uintptr) -> rawptr {
return rawptr(align_forward_uintptr(uintptr(ptr), align))
}
@(require_results)
align_forward_uintptr :: proc(ptr, align: uintptr) -> uintptr {
assert(is_power_of_two(align))
@@ -187,33 +203,41 @@ align_forward_uintptr :: proc(ptr, align: uintptr) -> uintptr {
return p
}
@(require_results)
align_forward_int :: proc(ptr, align: int) -> int {
return int(align_forward_uintptr(uintptr(ptr), uintptr(align)))
}
@(require_results)
align_forward_uint :: proc(ptr, align: uint) -> uint {
return uint(align_forward_uintptr(uintptr(ptr), uintptr(align)))
}
@(require_results)
align_backward :: proc(ptr: rawptr, align: uintptr) -> rawptr {
return rawptr(align_backward_uintptr(uintptr(ptr), align))
}
@(require_results)
align_backward_uintptr :: proc(ptr, align: uintptr) -> uintptr {
return align_forward_uintptr(ptr - align + 1, align)
}
@(require_results)
align_backward_int :: proc(ptr, align: int) -> int {
return int(align_backward_uintptr(uintptr(ptr), uintptr(align)))
}
@(require_results)
align_backward_uint :: proc(ptr, align: uint) -> uint {
return uint(align_backward_uintptr(uintptr(ptr), uintptr(align)))
}
@(require_results)
context_from_allocator :: proc(a: Allocator) -> type_of(context) {
context.allocator = a
return context
}
@(require_results)
reinterpret_copy :: proc "contextless" ($T: typeid, ptr: rawptr) -> (value: T) {
copy(&value, ptr, size_of(T))
return
@@ -222,6 +246,7 @@ reinterpret_copy :: proc "contextless" ($T: typeid, ptr: rawptr) -> (value: T) {
Fixed_Byte_Buffer :: distinct [dynamic]byte
@(require_results)
make_fixed_byte_buffer :: proc "contextless" (backing: []byte) -> Fixed_Byte_Buffer {
s := transmute(Raw_Slice)backing
d: Raw_Dynamic_Array
@@ -237,11 +262,13 @@ make_fixed_byte_buffer :: proc "contextless" (backing: []byte) -> Fixed_Byte_Buf
@(require_results)
align_formula :: proc "contextless" (size, align: int) -> int {
result := size + align-1
return result - result%align
}
@(require_results)
calc_padding_with_header :: proc "contextless" (ptr: uintptr, align: uintptr, header_size: int) -> int {
p, a := ptr, align
modulo := p & (a-1)
@@ -267,6 +294,7 @@ calc_padding_with_header :: proc "contextless" (ptr: uintptr, align: uintptr, he
@(require_results, deprecated="prefer 'slice.clone'")
clone_slice :: proc(slice: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> (new_slice: T) {
new_slice, _ = make(T, len(slice), allocator, loc)
runtime.copy(new_slice, slice)
+4
View File
@@ -392,6 +392,10 @@ load_resolv_conf :: proc(resolv_conf_path: string, allocator := context.allocato
}
addr := parse_address(server_ip_str)
if addr == nil {
continue
}
endpoint := Endpoint{
addr,
53,
+19 -2
View File
@@ -303,8 +303,25 @@ _set_option :: proc(s: Any_Socket, option: Socket_Option, value: any, loc := #ca
@(private)
_set_blocking :: proc(socket: Any_Socket, should_block: bool) -> (err: Network_Error) {
// TODO: Implement
unimplemented()
socket := any_socket_to_socket(socket)
flags, getfl_err := os.fcntl(int(socket), os.F_GETFL, 0)
if getfl_err != os.ERROR_NONE {
return Set_Blocking_Error(getfl_err)
}
if should_block {
flags &= ~int(os.O_NONBLOCK)
} else {
flags |= int(os.O_NONBLOCK)
}
_, setfl_err := os.fcntl(int(socket), os.F_SETFL, flags)
if setfl_err != os.ERROR_NONE {
return Set_Blocking_Error(setfl_err)
}
return nil
}
@private
+14 -40
View File
@@ -19,7 +19,7 @@ package net
import "core:strings"
import "core:strconv"
import "core:unicode/utf8"
import "core:mem"
import "core:encoding/hex"
split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host, path: string, queries: map[string]string) {
s := url
@@ -36,9 +36,11 @@ split_url :: proc(url: string, allocator := context.allocator) -> (scheme, host,
s = s[:i]
if query_str != "" {
queries_parts := strings.split(query_str, "&")
defer delete(queries_parts)
queries = make(map[string]string, len(queries_parts), allocator)
for q in queries_parts {
parts := strings.split(q, "=")
defer delete(parts)
switch len(parts) {
case 1: queries[parts[0]] = "" // NOTE(tetra): Query not set to anything, was but present.
case 2: queries[parts[0]] = parts[1] // NOTE(tetra): Query set to something.
@@ -76,13 +78,19 @@ join_url :: proc(scheme, host, path: string, queries: map[string]string, allocat
}
if len(queries) > 0 do write_string(&b, "?")
query_length := len(queries)
if query_length > 0 do write_string(&b, "?")
i := 0
for query_name, query_value in queries {
write_string(&b, query_name)
if query_value != "" {
write_string(&b, "=")
write_string(&b, query_value)
}
if i < query_length - 1 {
write_string(&b, "&")
}
i += 1
}
return to_string(b)
@@ -119,12 +127,10 @@ percent_decode :: proc(encoded_string: string, allocator := context.allocator) -
builder_grow(&b, len(encoded_string))
defer if !ok do builder_destroy(&b)
stack_buf: [4]u8
pending := mem.buffer_from_slice(stack_buf[:])
s := encoded_string
for len(s) > 0 {
i := index_rune(s, '%')
i := index_byte(s, '%')
if i == -1 {
write_string(&b, s) // no '%'s; the string is already decoded
break
@@ -137,47 +143,15 @@ percent_decode :: proc(encoded_string: string, allocator := context.allocator) -
s = s[1:]
if s[0] == '%' {
write_rune(&b, '%')
write_byte(&b, '%')
s = s[1:]
continue
}
if len(s) < 2 do return // percent without encoded value
n: int
n, _ = strconv.parse_int(s[:2], 16)
switch n {
case 0x20: write_rune(&b, ' ')
case 0x21: write_rune(&b, '!')
case 0x23: write_rune(&b, '#')
case 0x24: write_rune(&b, '$')
case 0x25: write_rune(&b, '%')
case 0x26: write_rune(&b, '&')
case 0x27: write_rune(&b, '\'')
case 0x28: write_rune(&b, '(')
case 0x29: write_rune(&b, ')')
case 0x2A: write_rune(&b, '*')
case 0x2B: write_rune(&b, '+')
case 0x2C: write_rune(&b, ',')
case 0x2F: write_rune(&b, '/')
case 0x3A: write_rune(&b, ':')
case 0x3B: write_rune(&b, ';')
case 0x3D: write_rune(&b, '=')
case 0x3F: write_rune(&b, '?')
case 0x40: write_rune(&b, '@')
case 0x5B: write_rune(&b, '[')
case 0x5D: write_rune(&b, ']')
case:
// utf-8 bytes
// TODO(tetra): Audit this - 4 bytes???
append(&pending, s[0])
append(&pending, s[1])
if len(pending) == 4 {
r, _ := utf8.decode_rune(pending[:])
write_rune(&b, r)
clear(&pending)
}
}
val := hex.decode_sequence(s[:2]) or_return
write_byte(&b, val)
s = s[2:]
}
+5 -1
View File
@@ -82,7 +82,11 @@ clone_node :: proc(node: ^Node) -> ^Node {
panic("Cannot clone this node type")
}
res := cast(^Node)mem.alloc(size, align)
res := cast(^Node)(mem.alloc(size, align) or_else nil)
if res == nil {
// allocation failure
return nil
}
src: rawptr = node
if node.derived != nil {
src = (^rawptr)(&node.derived)^
+27 -10
View File
@@ -220,6 +220,7 @@ file_size :: proc(fd: Handle) -> (i64, Errno) {
@(private)
MAX_RW :: 1<<30
ERROR_EOF :: 38
@(private)
pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
@@ -228,11 +229,6 @@ pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
buf = buf[:MAX_RW]
}
curr_offset, e := seek(fd, offset, 1)
if e != 0 {
return 0, e
}
defer seek(fd, curr_offset, 0)
o := win32.OVERLAPPED{
OffsetHigh = u32(offset>>32),
@@ -243,6 +239,7 @@ pread :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
h := win32.HANDLE(fd)
done: win32.DWORD
e: Errno
if !win32.ReadFile(h, raw_data(buf), u32(len(buf)), &done, &o) {
e = Errno(win32.GetLastError())
done = 0
@@ -256,11 +253,6 @@ pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
buf = buf[:MAX_RW]
}
curr_offset, e := seek(fd, offset, 1)
if e != 0 {
return 0, e
}
defer seek(fd, curr_offset, 0)
o := win32.OVERLAPPED{
OffsetHigh = u32(offset>>32),
@@ -269,6 +261,7 @@ pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
h := win32.HANDLE(fd)
done: win32.DWORD
e: Errno
if !win32.WriteFile(h, raw_data(buf), u32(len(buf)), &done, &o) {
e = Errno(win32.GetLastError())
done = 0
@@ -276,6 +269,16 @@ pwrite :: proc(fd: Handle, data: []byte, offset: i64) -> (int, Errno) {
return int(done), e
}
/*
read_at returns n: 0, err: 0 on EOF
on Windows, read_at changes the position of the file cursor, on *nix, it does not.
bytes: [8]u8{}
read_at(fd, bytes, 0)
read(fd, bytes)
will read from the location twice on *nix, and from two different locations on Windows
*/
read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
if offset < 0 {
return 0, ERROR_NEGATIVE_OFFSET
@@ -284,6 +287,10 @@ read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
b, offset := data, offset
for len(b) > 0 {
m, e := pread(fd, b, offset)
if e == ERROR_EOF {
err = 0
break
}
if e != 0 {
err = e
break
@@ -294,6 +301,16 @@ read_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
}
return
}
/*
on Windows, write_at changes the position of the file cursor, on *nix, it does not.
bytes: [8]u8{}
write_at(fd, bytes, 0)
write(fd, bytes)
will write to the location twice on *nix, and to two different locations on Windows
*/
write_at :: proc(fd: Handle, data: []byte, offset: i64) -> (n: int, err: Errno) {
if offset < 0 {
return 0, ERROR_NEGATIVE_OFFSET
+1 -1
View File
@@ -194,7 +194,7 @@ heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
ptr := uintptr(aligned_mem)
aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
diff := int(aligned_ptr - ptr)
if (size + diff) > space {
if (size + diff) > space || allocated_mem == nil {
return nil, .Out_Of_Memory
}
+1 -1
View File
@@ -3,7 +3,7 @@ package os2
import "core:runtime"
_get_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) {
_lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) {
//TODO
return
}
+39 -86
View File
@@ -9,19 +9,20 @@ import "core:sys/unix"
INVALID_HANDLE :: -1
_O_RDONLY :: 0o0
_O_WRONLY :: 0o1
_O_RDWR :: 0o2
_O_CREAT :: 0o100
_O_EXCL :: 0o200
_O_TRUNC :: 0o1000
_O_APPEND :: 0o2000
_O_NONBLOCK :: 0o4000
_O_LARGEFILE :: 0o100000
_O_DIRECTORY :: 0o200000
_O_NOFOLLOW :: 0o400000
_O_SYNC :: 0o4010000
_O_CLOEXEC :: 0o2000000
_O_RDONLY :: 0o00000000
_O_WRONLY :: 0o00000001
_O_RDWR :: 0o00000002
_O_CREAT :: 0o00000100
_O_EXCL :: 0o00000200
_O_NOCTTY :: 0o00000400
_O_TRUNC :: 0o00001000
_O_APPEND :: 0o00002000
_O_NONBLOCK :: 0o00004000
_O_LARGEFILE :: 0o00100000
_O_DIRECTORY :: 0o00200000
_O_NOFOLLOW :: 0o00400000
_O_SYNC :: 0o04010000
_O_CLOEXEC :: 0o02000000
_O_PATH :: 0o10000000
_AT_FDCWD :: -100
@@ -40,9 +41,12 @@ _file_allocator :: proc() -> runtime.Allocator {
_open :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (^File, Error) {
runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
name_cstr := _name_to_cstring(name)
name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
flags_i: int
// Just default to using O_NOCTTY because needing to open a controlling
// terminal would be incredibly rare. This has no effect on files while
// allowing us to open serial devices.
flags_i: int = _O_NOCTTY
switch flags & O_RDONLY|O_WRONLY|O_RDWR {
case O_RDONLY: flags_i = _O_RDONLY
case O_WRONLY: flags_i = _O_WRONLY
@@ -56,7 +60,7 @@ _open :: proc(name: string, flags: File_Flags, perm: File_Mode) -> (^File, Error
flags_i |= (_O_TRUNC * int(.Trunc in flags))
flags_i |= (_O_CLOEXEC * int(.Close_On_Exec in flags))
fd := unix.sys_open(name_cstr, flags_i, int(perm))
fd := unix.sys_open(name_cstr, flags_i, uint(perm))
if fd < 0 {
return nil, _get_platform_error(fd)
}
@@ -196,10 +200,7 @@ _truncate :: proc(f: ^File, size: i64) -> Error {
}
_remove :: proc(name: string) -> Error {
name_cstr, allocated := _name_to_cstring(name)
defer if allocated {
delete(name_cstr)
}
name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
fd := unix.sys_open(name_cstr, int(File_Flags.Read))
if fd < 0 {
@@ -214,40 +215,22 @@ _remove :: proc(name: string) -> Error {
}
_rename :: proc(old_name, new_name: string) -> Error {
old_name_cstr, old_allocated := _name_to_cstring(old_name)
new_name_cstr, new_allocated := _name_to_cstring(new_name)
defer if old_allocated {
delete(old_name_cstr)
}
defer if new_allocated {
delete(new_name_cstr)
}
old_name_cstr := strings.clone_to_cstring(old_name, context.temp_allocator)
new_name_cstr := strings.clone_to_cstring(new_name, context.temp_allocator)
return _ok_or_error(unix.sys_rename(old_name_cstr, new_name_cstr))
}
_link :: proc(old_name, new_name: string) -> Error {
old_name_cstr, old_allocated := _name_to_cstring(old_name)
new_name_cstr, new_allocated := _name_to_cstring(new_name)
defer if old_allocated {
delete(old_name_cstr)
}
defer if new_allocated {
delete(new_name_cstr)
}
old_name_cstr := strings.clone_to_cstring(old_name, context.temp_allocator)
new_name_cstr := strings.clone_to_cstring(new_name, context.temp_allocator)
return _ok_or_error(unix.sys_link(old_name_cstr, new_name_cstr))
}
_symlink :: proc(old_name, new_name: string) -> Error {
old_name_cstr, old_allocated := _name_to_cstring(old_name)
new_name_cstr, new_allocated := _name_to_cstring(new_name)
defer if old_allocated {
delete(old_name_cstr)
}
defer if new_allocated {
delete(new_name_cstr)
}
old_name_cstr := strings.clone_to_cstring(old_name, context.temp_allocator)
new_name_cstr := strings.clone_to_cstring(new_name, context.temp_allocator)
return _ok_or_error(unix.sys_symlink(old_name_cstr, new_name_cstr))
}
@@ -271,26 +254,17 @@ _read_link_cstr :: proc(name_cstr: cstring, allocator: runtime.Allocator) -> (st
}
_read_link :: proc(name: string, allocator: runtime.Allocator) -> (string, Error) {
name_cstr, allocated := _name_to_cstring(name)
defer if allocated {
delete(name_cstr)
}
name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
return _read_link_cstr(name_cstr, allocator)
}
_unlink :: proc(name: string) -> Error {
name_cstr, allocated := _name_to_cstring(name)
defer if allocated {
delete(name_cstr)
}
name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
return _ok_or_error(unix.sys_unlink(name_cstr))
}
_chdir :: proc(name: string) -> Error {
name_cstr, allocated := _name_to_cstring(name)
defer if allocated {
delete(name_cstr)
}
name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
return _ok_or_error(unix.sys_chdir(name_cstr))
}
@@ -299,32 +273,23 @@ _fchdir :: proc(f: ^File) -> Error {
}
_chmod :: proc(name: string, mode: File_Mode) -> Error {
name_cstr, allocated := _name_to_cstring(name)
defer if allocated {
delete(name_cstr)
}
return _ok_or_error(unix.sys_chmod(name_cstr, int(mode)))
name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
return _ok_or_error(unix.sys_chmod(name_cstr, uint(mode)))
}
_fchmod :: proc(f: ^File, mode: File_Mode) -> Error {
return _ok_or_error(unix.sys_fchmod(f.impl.fd, int(mode)))
return _ok_or_error(unix.sys_fchmod(f.impl.fd, uint(mode)))
}
// NOTE: will throw error without super user priviledges
_chown :: proc(name: string, uid, gid: int) -> Error {
name_cstr, allocated := _name_to_cstring(name)
defer if allocated {
delete(name_cstr)
}
name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
return _ok_or_error(unix.sys_chown(name_cstr, uid, gid))
}
// NOTE: will throw error without super user priviledges
_lchown :: proc(name: string, uid, gid: int) -> Error {
name_cstr, allocated := _name_to_cstring(name)
defer if allocated {
delete(name_cstr)
}
name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
return _ok_or_error(unix.sys_lchown(name_cstr, uid, gid))
}
@@ -334,10 +299,7 @@ _fchown :: proc(f: ^File, uid, gid: int) -> Error {
}
_chtimes :: proc(name: string, atime, mtime: time.Time) -> Error {
name_cstr, allocated := _name_to_cstring(name)
defer if allocated {
delete(name_cstr)
}
name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
times := [2]Unix_File_Time {
{ atime._nsec, 0 },
{ mtime._nsec, 0 },
@@ -354,18 +316,12 @@ _fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error {
}
_exists :: proc(name: string) -> bool {
name_cstr, allocated := _name_to_cstring(name)
defer if allocated {
delete(name_cstr)
}
name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
return unix.sys_access(name_cstr, F_OK) == 0
}
_is_file :: proc(name: string) -> bool {
name_cstr, allocated := _name_to_cstring(name)
defer if allocated {
delete(name_cstr)
}
name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
s: _Stat
res := unix.sys_stat(name_cstr, &s)
if res < 0 {
@@ -384,10 +340,7 @@ _is_file_fd :: proc(fd: int) -> bool {
}
_is_dir :: proc(name: string) -> bool {
name_cstr, allocated := _name_to_cstring(name)
defer if allocated {
delete(name_cstr)
}
name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
s: _Stat
res := unix.sys_stat(name_cstr, &s)
if res < 0 {
+1 -1
View File
@@ -166,7 +166,7 @@ _heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
ptr := uintptr(aligned_mem)
aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
diff := int(aligned_ptr - ptr)
if (size + diff) > space {
if (size + diff) > space || allocated_mem == nil {
return nil, .Out_Of_Memory
}
+1 -1
View File
@@ -52,7 +52,7 @@ _heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
ptr := uintptr(aligned_mem)
aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
diff := int(aligned_ptr - ptr)
if (size + diff) > space {
if (size + diff) > space || allocated_mem == nil {
return nil, .Out_Of_Memory
}
+5 -17
View File
@@ -31,11 +31,8 @@ _mkdir :: proc(path: string, perm: File_Mode) -> Error {
return .Invalid_Argument
}
path_cstr, allocated := _name_to_cstring(path)
defer if allocated {
delete(path_cstr)
}
return _ok_or_error(unix.sys_mkdir(path_cstr, int(perm & 0o777)))
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
return _ok_or_error(unix.sys_mkdir(path_cstr, uint(perm & 0o777)))
}
_mkdir_all :: proc(path: string, perm: File_Mode) -> Error {
@@ -49,7 +46,7 @@ _mkdir_all :: proc(path: string, perm: File_Mode) -> Error {
new_dfd := unix.sys_openat(dfd, cstring(&path[0]), _OPENDIR_FLAGS)
switch new_dfd {
case -ENOENT:
if res := unix.sys_mkdirat(dfd, cstring(&path[0]), perm); res < 0 {
if res := unix.sys_mkdirat(dfd, cstring(&path[0]), uint(perm)); res < 0 {
return _get_platform_error(res)
}
has_created^ = true
@@ -83,9 +80,6 @@ _mkdir_all :: proc(path: string, perm: File_Mode) -> Error {
} else {
path_bytes = make([]u8, len(path) + 1, context.temp_allocator)
}
defer if allocated {
delete(path_bytes)
}
// NULL terminate the byte slice to make it a valid cstring
copy(path_bytes, path)
@@ -182,10 +176,7 @@ _remove_all :: proc(path: string) -> Error {
return nil
}
path_cstr, allocated := _name_to_cstring(path)
defer if allocated {
delete(path_cstr)
}
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
fd := unix.sys_open(path_cstr, _OPENDIR_FLAGS)
switch fd {
@@ -222,10 +213,7 @@ _getwd :: proc(allocator: runtime.Allocator) -> (string, Error) {
}
_setwd :: proc(dir: string) -> Error {
dir_cstr, allocated := _name_to_cstring(dir)
defer if allocated {
delete(dir_cstr)
}
dir_cstr := strings.clone_to_cstring(dir, context.temp_allocator)
return _ok_or_error(unix.sys_chdir(dir_cstr))
}
+5 -12
View File
@@ -3,6 +3,7 @@ package os2
import "core:time"
import "core:runtime"
import "core:strings"
import "core:sys/unix"
import "core:path/filepath"
@@ -112,10 +113,7 @@ _fstat_internal :: proc(fd: int, allocator: runtime.Allocator) -> (File_Info, Er
// NOTE: _stat and _lstat are using _fstat to avoid a race condition when populating fullpath
_stat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) {
name_cstr, allocated := _name_to_cstring(name)
defer if allocated {
delete(name_cstr)
}
name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
fd := unix.sys_open(name_cstr, _O_RDONLY)
if fd < 0 {
@@ -126,10 +124,8 @@ _stat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error)
}
_lstat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) {
name_cstr, allocated := _name_to_cstring(name)
defer if allocated {
delete(name_cstr)
}
name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
fd := unix.sys_open(name_cstr, _O_RDONLY | _O_PATH | _O_NOFOLLOW)
if fd < 0 {
return {}, _get_platform_error(fd)
@@ -143,10 +139,7 @@ _same_file :: proc(fi1, fi2: File_Info) -> bool {
}
_stat_internal :: proc(name: string) -> (s: _Stat, res: int) {
name_cstr, allocated := _name_to_cstring(name)
defer if allocated {
delete(name_cstr)
}
name_cstr := strings.clone_to_cstring(name, context.temp_allocator)
res = unix.sys_stat(name_cstr, &s)
return
}
+6 -6
View File
@@ -8,12 +8,12 @@ user_cache_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error
case .Windows:
dir = get_env("LocalAppData", allocator)
if dir != "" {
dir = strings.clone_safe(dir, allocator) or_return
dir = strings.clone(dir, allocator) or_return
}
case .Darwin:
dir = get_env("HOME", allocator)
if dir != "" {
dir = strings.concatenate_safe({dir, "/Library/Caches"}, allocator) or_return
dir = strings.concatenate({dir, "/Library/Caches"}, allocator) or_return
}
case: // All other UNIX systems
dir = get_env("XDG_CACHE_HOME", allocator)
@@ -22,7 +22,7 @@ user_cache_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error
if dir == "" {
return
}
dir = strings.concatenate_safe({dir, "/.cache"}, allocator) or_return
dir = strings.concatenate({dir, "/.cache"}, allocator) or_return
}
}
if dir == "" {
@@ -36,12 +36,12 @@ user_config_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Erro
case .Windows:
dir = get_env("AppData", allocator)
if dir != "" {
dir = strings.clone_safe(dir, allocator) or_return
dir = strings.clone(dir, allocator) or_return
}
case .Darwin:
dir = get_env("HOME", allocator)
if dir != "" {
dir = strings.concatenate_safe({dir, "/Library/Application Support"}, allocator) or_return
dir = strings.concatenate({dir, "/Library/Application Support"}, allocator) or_return
}
case: // All other UNIX systems
dir = get_env("XDG_CACHE_HOME", allocator)
@@ -50,7 +50,7 @@ user_config_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Erro
if dir == "" {
return
}
dir = strings.concatenate_safe({dir, "/.config"}, allocator) or_return
dir = strings.concatenate({dir, "/.config"}, allocator) or_return
}
}
if dir == "" {
+22 -3
View File
@@ -267,6 +267,8 @@ SHUT_RD :: 0
SHUT_WR :: 1
SHUT_RDWR :: 2
F_GETFL: int : 3 /* Get file flags */
F_SETFL: int : 4 /* Set file flags */
// "Argv" arguments converted to Odin strings
args := _alloc_command_line_arguments()
@@ -413,7 +415,7 @@ F_OK :: 0 // Test for file existance
F_GETPATH :: 50 // return the full path of the fd
foreign libc {
@(link_name="__error") __error :: proc() -> ^int ---
@(link_name="__error") __error :: proc() -> ^c.int ---
@(link_name="open") _unix_open :: proc(path: cstring, flags: i32, mode: u16) -> Handle ---
@(link_name="close") _unix_close :: proc(handle: Handle) -> c.int ---
@@ -438,7 +440,7 @@ foreign libc {
@(link_name="closedir") _unix_closedir :: proc(dirp: Dir) -> c.int ---
@(link_name="rewinddir") _unix_rewinddir :: proc(dirp: Dir) ---
@(link_name="__fcntl") _unix__fcntl :: proc(fd: Handle, cmd: c.int, buf: ^byte) -> c.int ---
@(link_name="__fcntl") _unix__fcntl :: proc(fd: Handle, cmd: c.int, #c_vararg args: ..any) -> c.int ---
@(link_name="rename") _unix_rename :: proc(old: cstring, new: cstring) -> c.int ---
@(link_name="remove") _unix_remove :: proc(path: cstring) -> c.int ---
@@ -464,6 +466,7 @@ foreign libc {
@(link_name="connect") _unix_connect :: proc(socket: int, addr: rawptr, addr_len: socklen_t) -> int ---
@(link_name="bind") _unix_bind :: proc(socket: int, addr: rawptr, addr_len: socklen_t) -> int ---
@(link_name="setsockopt") _unix_setsockopt :: proc(socket: int, level: int, opt_name: int, opt_val: rawptr, opt_len: socklen_t) -> int ---
@(link_name="getsockopt") _unix_getsockopt :: proc(socket: int, level: int, opt_name: int, opt_val: rawptr, opt_len: socklen_t) -> int ---
@(link_name="recvfrom") _unix_recvfrom :: proc(socket: int, buffer: rawptr, buffer_len: c.size_t, flags: int, addr: rawptr, addr_len: ^socklen_t) -> c.ssize_t ---
@(link_name="recv") _unix_recv :: proc(socket: int, buffer: rawptr, buffer_len: c.size_t, flags: int) -> c.ssize_t ---
@(link_name="sendto") _unix_sendto :: proc(socket: int, buffer: rawptr, buffer_len: c.size_t, flags: int, addr: rawptr, addr_len: socklen_t) -> c.ssize_t ---
@@ -489,7 +492,7 @@ foreign dl {
}
get_last_error :: proc "contextless" () -> int {
return __error()^
return int(__error()^)
}
get_last_error_string :: proc() -> string {
@@ -1016,6 +1019,14 @@ setsockopt :: proc(sd: Socket, level: int, optname: int, optval: rawptr, optlen:
return ERROR_NONE
}
getsockopt :: proc(sd: Socket, level: int, optname: int, optval: rawptr, optlen: socklen_t) -> Errno {
result := _unix_getsockopt(int(sd), level, optname, optval, optlen)
if result < 0 {
return Errno(get_last_error())
}
return ERROR_NONE
}
recvfrom :: proc(sd: Socket, data: []byte, flags: int, addr: ^SOCKADDR, addr_size: ^socklen_t) -> (u32, Errno) {
result := _unix_recvfrom(int(sd), raw_data(data), len(data), flags, addr, addr_size)
if result < 0 {
@@ -1055,3 +1066,11 @@ shutdown :: proc(sd: Socket, how: int) -> (Errno) {
}
return ERROR_NONE
}
fcntl :: proc(fd: int, cmd: int, arg: int) -> (int, Errno) {
result := _unix__fcntl(Handle(fd), c.int(cmd), c.int(arg))
if result < 0 {
return 0, Errno(get_last_error())
}
return int(result), ERROR_NONE
}
+12 -5
View File
@@ -67,16 +67,15 @@ Buffer :: struct {
BUFFER_DEFAULT_SIZE :: 0x10_0000
context_create :: proc(filename: string) -> (ctx: Context, ok: bool) #optional_ok {
context_create_with_scale :: proc(filename: string, precise_time: bool, timestamp_scale: f64) -> (ctx: Context, ok: bool) #optional_ok {
fd, err := os.open(filename, os.O_WRONLY | os.O_APPEND | os.O_CREATE | os.O_TRUNC, 0o600)
if err != os.ERROR_NONE {
return
}
ctx.fd = fd
freq, freq_ok := time.tsc_frequency()
ctx.precise_time = freq_ok
ctx.timestamp_scale = ((1 / f64(freq)) * 1_000_000) if freq_ok else 1
ctx.fd = fd
ctx.precise_time = precise_time
ctx.timestamp_scale = timestamp_scale
temp := [size_of(Manual_Header)]u8{}
_build_header(temp[:], ctx.timestamp_scale)
@@ -85,6 +84,14 @@ context_create :: proc(filename: string) -> (ctx: Context, ok: bool) #optional_o
return
}
context_create_with_sleep :: proc(filename: string, sleep := 2 * time.Second) -> (ctx: Context, ok: bool) #optional_ok {
freq, freq_ok := time.tsc_frequency(sleep)
timestamp_scale: f64 = ((1 / f64(freq)) * 1_000_000) if freq_ok else 1
return context_create_with_scale(filename, freq_ok, timestamp_scale)
}
context_create :: proc{context_create_with_scale, context_create_with_sleep}
context_destroy :: proc(ctx: ^Context) {
if ctx == nil {
return
+80 -77
View File
@@ -6,7 +6,7 @@ import "core:intrinsics"
Maybe :: union($T: typeid) {T}
@builtin
@(builtin, require_results)
container_of :: #force_inline proc "contextless" (ptr: $P/^$Field_Type, $T: typeid, $field_name: string) -> ^T
where intrinsics.type_has_field(T, field_name),
intrinsics.type_field_type(T, field_name) == Field_Type {
@@ -179,17 +179,18 @@ delete :: proc{
// The new built-in procedure allocates memory. The first argument is a type, not a value, and the value
// return is a pointer to a newly allocated value of that type using the specified allocator, default is context.allocator
@builtin
@(builtin, require_results)
new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) #optional_allocator_error {
return new_aligned(T, align_of(T), allocator, loc)
}
@(require_results)
new_aligned :: proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) {
data := mem_alloc_bytes(size_of(T), alignment, allocator, loc) or_return
t = (^T)(raw_data(data))
return
}
@builtin
@(builtin, require_results)
new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> (t: ^T, err: Allocator_Error) #optional_allocator_error {
t_data := mem_alloc_bytes(size_of(T), align_of(T), allocator, loc) or_return
t = (^T)(raw_data(t_data))
@@ -201,6 +202,7 @@ new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_locat
DEFAULT_RESERVE_CAPACITY :: 16
@(require_results)
make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error {
make_slice_error_loc(loc, len)
data, err := mem_alloc_bytes(size_of(E)*len, alignment, allocator, loc)
@@ -211,19 +213,19 @@ make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocat
return transmute(T)s, err
}
@(builtin)
@(builtin, require_results)
make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error {
return make_aligned(T, len, align_of(E), allocator, loc)
}
@(builtin)
@(builtin, require_results)
make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error {
return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc)
}
@(builtin)
@(builtin, require_results)
make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_allocator_error {
return make_dynamic_array_len_cap(T, len, len, allocator, loc)
}
@(builtin)
@(builtin, require_results)
make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
make_dynamic_array_error_loc(loc, len, cap)
data := mem_alloc_bytes(size_of(E)*cap, align_of(E), allocator, loc) or_return
@@ -234,7 +236,7 @@ make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #a
array = transmute(T)s
return
}
@(builtin)
@(builtin, require_results)
make_map :: proc($T: typeid/map[$K]$E, #any_int capacity: int = 1<<MAP_MIN_LOG2_CAPACITY, allocator := context.allocator, loc := #caller_location) -> (m: T, err: Allocator_Error) #optional_allocator_error {
make_map_expr_error_loc(loc, capacity)
context.allocator = allocator
@@ -242,7 +244,7 @@ make_map :: proc($T: typeid/map[$K]$E, #any_int capacity: int = 1<<MAP_MIN_LOG2_
err = reserve_map(&m, capacity, loc)
return
}
@(builtin)
@(builtin, require_results)
make_multi_pointer :: proc($T: typeid/[^]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (mp: T, err: Allocator_Error) #optional_allocator_error {
make_slice_error_loc(loc, len)
data := mem_alloc_bytes(size_of(E)*len, align_of(E), allocator, loc) or_return
@@ -287,10 +289,9 @@ reserve_map :: proc(m: ^$T/map[$K]$V, capacity: int, loc := #caller_location) ->
Shrinks the capacity of a map down to the current length.
*/
@builtin
shrink_map :: proc(m: ^$T/map[$K]$V, loc := #caller_location) -> (did_shrink: bool) {
shrink_map :: proc(m: ^$T/map[$K]$V, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
if m != nil {
err := map_shrink_dynamic((^Raw_Map)(m), map_info(T), loc)
did_shrink = err == nil
return map_shrink_dynamic((^Raw_Map)(m), map_info(T), loc)
}
return
}
@@ -313,18 +314,18 @@ delete_key :: proc(m: ^$T/map[$K]$V, key: K) -> (deleted_key: K, deleted_value:
@builtin
append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> int {
append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
if array == nil {
return 0
return 0, nil
}
when size_of(E) == 0 {
array := (^Raw_Dynamic_Array)(array)
array.len += 1
return 1
return 1, nil
} else {
if cap(array) < len(array)+1 {
cap := 2 * cap(array) + max(8, 1)
_ = reserve(array, cap, loc)
err = reserve(array, cap, loc) // do not 'or_return' here as it could be a partial success
}
if cap(array)-len(array) > 0 {
a := (^Raw_Dynamic_Array)(array)
@@ -334,31 +335,31 @@ append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) ->
data[a.len] = arg
}
a.len += 1
return 1
return 1, err
}
return 0
return 0, err
}
}
@builtin
append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> int {
append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
if array == nil {
return 0
return 0, nil
}
arg_len := len(args)
if arg_len <= 0 {
return 0
return 0, nil
}
when size_of(E) == 0 {
array := (^Raw_Dynamic_Array)(array)
array.len += arg_len
return arg_len
return arg_len, nil
} else {
if cap(array) < len(array)+arg_len {
cap := 2 * cap(array) + max(8, arg_len)
_ = reserve(array, cap, loc)
err = reserve(array, cap, loc) // do not 'or_return' here as it could be a partial success
}
arg_len = min(cap(array)-len(array), arg_len)
if arg_len > 0 {
@@ -370,13 +371,13 @@ append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location)
}
a.len += arg_len
}
return arg_len
return arg_len, err
}
}
// The append_string built-in procedure appends a string to the end of a [dynamic]u8 like type
@builtin
append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> int {
append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
args := transmute([]E)arg
return append_elems(array=array, args=args, loc=loc)
}
@@ -384,9 +385,14 @@ append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #ca
// The append_string built-in procedure appends multiple strings to the end of a [dynamic]u8 like type
@builtin
append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) -> (n: int) {
append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
n_arg: int
for arg in args {
n += append(array = array, args = transmute([]E)(arg), loc = loc)
n_arg, err = append(array = array, args = transmute([]E)(arg), loc = loc)
n += n_arg
if err != nil {
return
}
}
return
}
@@ -396,18 +402,18 @@ append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_
@builtin
append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> int {
append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
if array == nil {
return 0
return 0, nil
}
prev_len := len(array)
resize(array, len(array)+1)
return len(array)-prev_len
resize(array, len(array)+1, loc) or_return
return len(array)-prev_len, nil
}
@builtin
inject_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #caller_location) -> (ok: bool) #no_bounds_check {
inject_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
if array == nil {
return
}
@@ -415,18 +421,17 @@ inject_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #calle
m :: 1
new_size := n + m
if resize(array, new_size, loc) {
when size_of(E) != 0 {
copy(array[index + m:], array[index:])
array[index] = arg
}
ok = true
resize(array, new_size, loc) or_return
when size_of(E) != 0 {
copy(array[index + m:], array[index:])
array[index] = arg
}
ok = true
return
}
@builtin
inject_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #caller_location) -> (ok: bool) #no_bounds_check {
inject_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
if array == nil {
return
}
@@ -439,18 +444,17 @@ inject_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #c
m := len(args)
new_size := n + m
if resize(array, new_size, loc) {
when size_of(E) != 0 {
copy(array[index + m:], array[index:])
copy(array[index:], args)
}
ok = true
resize(array, new_size, loc) or_return
when size_of(E) != 0 {
copy(array[index + m:], array[index:])
copy(array[index:], args)
}
ok = true
return
}
@builtin
inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool) #no_bounds_check {
inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
if array == nil {
return
}
@@ -463,11 +467,10 @@ inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string
m := len(arg)
new_size := n + m
if resize(array, new_size, loc) {
copy(array[index+m:], array[index:])
copy(array[index:], arg)
ok = true
}
resize(array, new_size, loc) or_return
copy(array[index+m:], array[index:])
copy(array[index:], arg)
ok = true
return
}
@@ -476,11 +479,12 @@ inject_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string
@builtin
assign_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #caller_location) -> (ok: bool) #no_bounds_check {
assign_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
if index < len(array) {
array[index] = arg
ok = true
} else if resize(array, index+1, loc) {
} else {
resize(array, index+1, loc) or_return
array[index] = arg
ok = true
}
@@ -489,11 +493,12 @@ assign_at_elem :: proc(array: ^$T/[dynamic]$E, index: int, arg: E, loc := #calle
@builtin
assign_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #caller_location) -> (ok: bool) #no_bounds_check {
assign_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
if index+len(args) < len(array) {
copy(array[index:], args)
ok = true
} else if resize(array, index+1+len(args), loc) {
} else {
resize(array, index+1+len(args), loc) or_return
copy(array[index:], args)
ok = true
}
@@ -502,13 +507,14 @@ assign_at_elems :: proc(array: ^$T/[dynamic]$E, index: int, args: ..E, loc := #c
@builtin
assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool) #no_bounds_check {
assign_at_elem_string :: proc(array: ^$T/[dynamic]$E/u8, index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
if len(args) == 0 {
ok = true
} else if index+len(args) < len(array) {
copy(array[index:], args)
ok = true
} else if resize(array, index+1+len(args), loc) {
} else {
resize(array, index+1+len(args), loc) or_return
copy(array[index:], args)
ok = true
}
@@ -528,14 +534,14 @@ clear_dynamic_array :: proc "contextless" (array: ^$T/[dynamic]$E) {
}
@builtin
reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> bool {
reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #caller_location) -> Allocator_Error {
if array == nil {
return false
return nil
}
a := (^Raw_Dynamic_Array)(array)
if capacity <= a.cap {
return true
return nil
}
if a.allocator.procedure == nil {
@@ -547,26 +553,26 @@ reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, capacity: int, loc := #cal
new_size := capacity * size_of(E)
allocator := a.allocator
new_data, err := mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc)
if new_data == nil || err != nil {
return false
new_data := mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
if new_data == nil && new_size > 0 {
return .Out_Of_Memory
}
a.data = raw_data(new_data)
a.cap = capacity
return true
return nil
}
@builtin
resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> bool {
resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller_location) -> Allocator_Error {
if array == nil {
return false
return nil
}
a := (^Raw_Dynamic_Array)(array)
if length <= a.cap {
a.len = max(length, 0)
return true
return nil
}
if a.allocator.procedure == nil {
@@ -578,15 +584,15 @@ resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller
new_size := length * size_of(E)
allocator := a.allocator
new_data, err := mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc)
if new_data == nil || err != nil {
return false
new_data := mem_resize(a.data, old_size, new_size, align_of(E), allocator, loc) or_return
if new_data == nil && new_size > 0 {
return .Out_Of_Memory
}
a.data = raw_data(new_data)
a.len = length
a.cap = length
return true
return nil
}
/*
@@ -598,7 +604,7 @@ resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, length: int, loc := #caller
If `len(array) < new_cap`, then `len(array)` will be left unchanged.
*/
shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, new_cap := -1, loc := #caller_location) -> (did_shrink: bool) {
shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, new_cap := -1, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {
if array == nil {
return
}
@@ -618,15 +624,12 @@ shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, new_cap := -1, loc := #call
old_size := a.cap * size_of(E)
new_size := new_cap * size_of(E)
new_data, err := mem_resize(a.data, old_size, new_size, align_of(E), a.allocator, loc)
if err != nil {
return
}
new_data := mem_resize(a.data, old_size, new_size, align_of(E), a.allocator, loc) or_return
a.data = raw_data(new_data)
a.len = min(new_cap, a.len)
a.cap = new_cap
return true
return true, nil
}
@builtin
+19 -19
View File
@@ -37,12 +37,12 @@ inverse :: proc{
matrix4x4_inverse,
}
@(builtin)
@(builtin, require_results)
hermitian_adjoint :: proc "contextless" (m: $M/matrix[$N, N]$T) -> M where intrinsics.type_is_complex(T), N >= 1 {
return conj(transpose(m))
}
@(builtin)
@(builtin, require_results)
matrix_trace :: proc "contextless" (m: $M/matrix[$N, N]$T) -> (trace: T) {
for i in 0..<N {
trace += m[i, i]
@@ -50,7 +50,7 @@ matrix_trace :: proc "contextless" (m: $M/matrix[$N, N]$T) -> (trace: T) {
return
}
@(builtin)
@(builtin, require_results)
matrix_minor :: proc "contextless" (m: $M/matrix[$N, N]$T, row, column: int) -> (minor: T) where N > 1 {
K :: N-1
cut_down: matrix[K, K]T
@@ -66,23 +66,23 @@ matrix_minor :: proc "contextless" (m: $M/matrix[$N, N]$T, row, column: int) ->
@(builtin)
@(builtin, require_results)
matrix1x1_determinant :: proc "contextless" (m: $M/matrix[1, 1]$T) -> (det: T) {
return m[0, 0]
}
@(builtin)
@(builtin, require_results)
matrix2x2_determinant :: proc "contextless" (m: $M/matrix[2, 2]$T) -> (det: T) {
return m[0, 0]*m[1, 1] - m[0, 1]*m[1, 0]
}
@(builtin)
@(builtin, require_results)
matrix3x3_determinant :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (det: T) {
a := +m[0, 0] * (m[1, 1] * m[2, 2] - m[1, 2] * m[2, 1])
b := -m[0, 1] * (m[1, 0] * m[2, 2] - m[1, 2] * m[2, 0])
c := +m[0, 2] * (m[1, 0] * m[2, 1] - m[1, 1] * m[2, 0])
return a + b + c
}
@(builtin)
@(builtin, require_results)
matrix4x4_determinant :: proc "contextless" (m: $M/matrix[4, 4]$T) -> (det: T) {
a := adjugate(m)
#no_bounds_check for i in 0..<4 {
@@ -94,13 +94,13 @@ matrix4x4_determinant :: proc "contextless" (m: $M/matrix[4, 4]$T) -> (det: T) {
@(builtin)
@(builtin, require_results)
matrix1x1_adjugate :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
y = x
return
}
@(builtin)
@(builtin, require_results)
matrix2x2_adjugate :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
y[0, 0] = +x[1, 1]
y[0, 1] = -x[1, 0]
@@ -109,7 +109,7 @@ matrix2x2_adjugate :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
return
}
@(builtin)
@(builtin, require_results)
matrix3x3_adjugate :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2])
y[0, 1] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2])
@@ -124,7 +124,7 @@ matrix3x3_adjugate :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
}
@(builtin)
@(builtin, require_results)
matrix4x4_adjugate :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
for i in 0..<4 {
for j in 0..<4 {
@@ -135,13 +135,13 @@ matrix4x4_adjugate :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
return
}
@(builtin)
@(builtin, require_results)
matrix1x1_inverse_transpose :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
y[0, 0] = 1/x[0, 0]
return
}
@(builtin)
@(builtin, require_results)
matrix2x2_inverse_transpose :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0]
when intrinsics.type_is_integer(T) {
@@ -159,7 +159,7 @@ matrix2x2_inverse_transpose :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y:
return
}
@(builtin)
@(builtin, require_results)
matrix3x3_inverse_transpose :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
a := adjugate(x)
d := determinant(x)
@@ -180,7 +180,7 @@ matrix3x3_inverse_transpose :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y:
return
}
@(builtin)
@(builtin, require_results)
matrix4x4_inverse_transpose :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
a := adjugate(x)
d: T
@@ -204,13 +204,13 @@ matrix4x4_inverse_transpose :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y:
return
}
@(builtin)
@(builtin, require_results)
matrix1x1_inverse :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
y[0, 0] = 1/x[0, 0]
return
}
@(builtin)
@(builtin, require_results)
matrix2x2_inverse :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0]
when intrinsics.type_is_integer(T) {
@@ -228,7 +228,7 @@ matrix2x2_inverse :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
return
}
@(builtin)
@(builtin, require_results)
matrix3x3_inverse :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
a := adjugate(x)
d := determinant(x)
@@ -249,7 +249,7 @@ matrix3x3_inverse :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bou
return
}
@(builtin)
@(builtin, require_results)
matrix4x4_inverse :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
a := adjugate(x)
d: T
+7 -5
View File
@@ -50,6 +50,7 @@ Raw_SOA_Footer_Dynamic_Array :: struct {
allocator: Allocator,
}
@(builtin, require_results)
raw_soa_footer_slice :: proc(array: ^$T/#soa[]$E) -> (footer: ^Raw_SOA_Footer_Slice) {
if array == nil {
return nil
@@ -58,6 +59,7 @@ raw_soa_footer_slice :: proc(array: ^$T/#soa[]$E) -> (footer: ^Raw_SOA_Footer_Sl
footer = (^Raw_SOA_Footer_Slice)(uintptr(array) + field_count*size_of(rawptr))
return
}
@(builtin, require_results)
raw_soa_footer_dynamic_array :: proc(array: ^$T/#soa[dynamic]$E) -> (footer: ^Raw_SOA_Footer_Dynamic_Array) {
if array == nil {
return nil
@@ -78,7 +80,7 @@ raw_soa_footer :: proc{
@builtin
@(builtin, require_results)
make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
if length <= 0 {
return
@@ -137,26 +139,26 @@ make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, alloc
return
}
@builtin
@(builtin, require_results)
make_soa_slice :: proc($T: typeid/#soa[]$E, length: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
return make_soa_aligned(T, length, align_of(E), allocator, loc)
}
@builtin
@(builtin, require_results)
make_soa_dynamic_array :: proc($T: typeid/#soa[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (array: T) {
context.allocator = allocator
reserve_soa(&array, DEFAULT_RESERVE_CAPACITY, loc)
return
}
@builtin
@(builtin, require_results)
make_soa_dynamic_array_len :: proc($T: typeid/#soa[dynamic]$E, #any_int length: int, allocator := context.allocator, loc := #caller_location) -> (array: T) {
context.allocator = allocator
resize_soa(&array, length, loc)
return
}
@builtin
@(builtin, require_results)
make_soa_dynamic_array_len_cap :: proc($T: typeid/#soa[dynamic]$E, #any_int length, capacity: int, allocator := context.allocator, loc := #caller_location) -> (array: T) {
context.allocator = allocator
if reserve_soa(&array, capacity, loc) {
+90 -25
View File
@@ -251,6 +251,26 @@ map_hash_is_valid :: #force_inline proc "contextless" (hash: Map_Hash) -> bool {
return (hash != 0) & (hash & TOMBSTONE_MASK == 0)
}
@(require_results)
map_seed :: #force_inline proc "contextless" (m: Raw_Map) -> uintptr {
return map_seed_from_map_data(map_data(m))
}
// splitmix for uintptr
@(require_results)
map_seed_from_map_data :: #force_inline proc "contextless" (data: uintptr) -> uintptr {
when size_of(uintptr) == size_of(u64) {
mix := data + 0x9e3779b97f4a7c15
mix = (mix ~ (mix >> 30)) * 0xbf58476d1ce4e5b9
mix = (mix ~ (mix >> 27)) * 0x94d049bb133111eb
return mix ~ (mix >> 31)
} else {
mix := data + 0x9e3779b9
mix = (mix ~ (mix >> 16)) * 0x21f0aaad
mix = (mix ~ (mix >> 15)) * 0x735a2d97
return mix ~ (mix >> 15)
}
}
// Computes the desired position in the array. This is just index % capacity,
// but a procedure as there's some math involved here to recover the capacity.
@@ -394,32 +414,71 @@ map_insert_hash_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^
tk := map_cell_index_dynamic(sk, info.ks, 1)
tv := map_cell_index_dynamic(sv, info.vs, 1)
for {
hp := &hs[pos]
element_hash := hp^
if map_hash_is_empty(element_hash) {
k_dst := map_cell_index_dynamic(ks, info.ks, pos)
v_dst := map_cell_index_dynamic(vs, info.vs, pos)
intrinsics.mem_copy_non_overlapping(rawptr(k_dst), rawptr(k), size_of_k)
intrinsics.mem_copy_non_overlapping(rawptr(v_dst), rawptr(v), size_of_v)
kp := map_cell_index_dynamic(ks, info.ks, pos)
vp := map_cell_index_dynamic(vs, info.vs, pos)
intrinsics.mem_copy_non_overlapping(rawptr(kp), rawptr(k), size_of_k)
intrinsics.mem_copy_non_overlapping(rawptr(vp), rawptr(v), size_of_v)
hp^ = h
return result if result != 0 else v_dst
return result if result != 0 else vp
}
if map_hash_is_deleted(element_hash) {
next_pos := (pos + 1) & mask
// backward shift
for !map_hash_is_empty(hs[next_pos]) {
probe_distance := map_probe_distance(m^, hs[next_pos], next_pos)
if probe_distance == 0 {
break
}
probe_distance -= 1
kp := map_cell_index_dynamic(ks, info.ks, pos)
vp := map_cell_index_dynamic(vs, info.vs, pos)
kn := map_cell_index_dynamic(ks, info.ks, next_pos)
vn := map_cell_index_dynamic(vs, info.vs, next_pos)
if distance > probe_distance {
if result == 0 {
result = vp
}
// move stored into pos; store next
intrinsics.mem_copy_non_overlapping(rawptr(kp), rawptr(k), size_of_k)
intrinsics.mem_copy_non_overlapping(rawptr(vp), rawptr(v), size_of_v)
hs[pos] = h
intrinsics.mem_copy_non_overlapping(rawptr(k), rawptr(kn), size_of_k)
intrinsics.mem_copy_non_overlapping(rawptr(v), rawptr(vn), size_of_v)
h = hs[next_pos]
} else {
// move next back 1
intrinsics.mem_copy_non_overlapping(rawptr(kp), rawptr(kn), size_of_k)
intrinsics.mem_copy_non_overlapping(rawptr(vp), rawptr(vn), size_of_v)
hs[pos] = hs[next_pos]
distance = probe_distance
}
hs[next_pos] = 0
pos = (pos + 1) & mask
next_pos = (next_pos + 1) & mask
distance += 1
}
kp := map_cell_index_dynamic(ks, info.ks, pos)
vp := map_cell_index_dynamic(vs, info.vs, pos)
intrinsics.mem_copy_non_overlapping(rawptr(kp), rawptr(k), size_of_k)
intrinsics.mem_copy_non_overlapping(rawptr(vp), rawptr(v), size_of_v)
hs[pos] = h
return result if result != 0 else vp
}
if probe_distance := map_probe_distance(m^, element_hash, pos); distance > probe_distance {
if map_hash_is_deleted(element_hash) {
k_dst := map_cell_index_dynamic(ks, info.ks, pos)
v_dst := map_cell_index_dynamic(vs, info.vs, pos)
intrinsics.mem_copy_non_overlapping(rawptr(k_dst), rawptr(k), size_of_k)
intrinsics.mem_copy_non_overlapping(rawptr(v_dst), rawptr(v), size_of_v)
hp^ = h
return result if result != 0 else v_dst
}
if result == 0 {
result = map_cell_index_dynamic(vs, info.vs, pos)
}
@@ -503,6 +562,7 @@ map_reserve_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_
}
k := map_cell_index_dynamic(ks, info.ks, i)
v := map_cell_index_dynamic(vs, info.vs, i)
hash = info.key_hasher(rawptr(k), map_seed(resized))
_ = map_insert_hash_dynamic(&resized, info, hash, k, v)
// Only need to do this comparison on each actually added pair, so do not
// fold it into the for loop comparator as a micro-optimization.
@@ -550,6 +610,7 @@ map_shrink_dynamic :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_I
k := map_cell_index_dynamic(ks, info.ks, i)
v := map_cell_index_dynamic(vs, info.vs, i)
hash = info.key_hasher(rawptr(k), map_seed(shrunk))
_ = map_insert_hash_dynamic(&shrunk, info, hash, k, v)
// Only need to do this comparison on each actually added pair, so do not
// fold it into the for loop comparator as a micro-optimization.
@@ -581,7 +642,7 @@ map_lookup_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info,
if map_len(m) == 0 {
return 0, false
}
h := info.key_hasher(rawptr(k), 0)
h := info.key_hasher(rawptr(k), map_seed(m))
p := map_desired_position(m, h)
d := uintptr(0)
c := (uintptr(1) << map_log2_cap(m)) - 1
@@ -604,7 +665,7 @@ map_exists_dynamic :: proc "contextless" (m: Raw_Map, #no_alias info: ^Map_Info,
if map_len(m) == 0 {
return false
}
h := info.key_hasher(rawptr(k), 0)
h := info.key_hasher(rawptr(k), map_seed(m))
p := map_desired_position(m, h)
d := uintptr(0)
c := (uintptr(1) << map_log2_cap(m)) - 1
@@ -637,7 +698,6 @@ map_erase_dynamic :: #force_inline proc "contextless" (#no_alias m: ^Raw_Map, #n
{ // coalesce tombstones
// HACK NOTE(bill): This is an ugly bodge but it is coalescing the tombstone slots
// TODO(bill): we should do backward shift deletion and not rely on tombstone slots
mask := (uintptr(1)<<map_log2_cap(m^)) - 1
curr_index := uintptr(index)
@@ -711,7 +771,7 @@ map_get :: proc "contextless" (m: $T/map[$K]$V, key: K) -> (stored_key: K, store
info := intrinsics.type_map_info(T)
key := key
h := info.key_hasher(&key, 0)
h := info.key_hasher(&key, map_seed(m))
pos := map_desired_position(rm, h)
distance := uintptr(0)
mask := (uintptr(1) << map_log2_cap(rm)) - 1
@@ -762,15 +822,15 @@ __dynamic_map_get :: proc "contextless" (#no_alias m: ^Raw_Map, #no_alias info:
}
// IMPORTANT: USED WITHIN THE COMPILER
__dynamic_map_check_grow :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, loc := #caller_location) -> Allocator_Error {
__dynamic_map_check_grow :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, loc := #caller_location) -> (err: Allocator_Error, has_grown: bool) {
if m.len >= map_resize_threshold(m^) {
return map_grow_dynamic(m, info, loc)
return map_grow_dynamic(m, info, loc), true
}
return nil
return nil, false
}
__dynamic_map_set_without_hash :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, key, value: rawptr, loc := #caller_location) -> rawptr {
return __dynamic_map_set(m, info, info.key_hasher(key, 0), key, value, loc)
return __dynamic_map_set(m, info, info.key_hasher(key, map_seed(m^)), key, value, loc)
}
@@ -781,9 +841,14 @@ __dynamic_map_set :: proc "odin" (#no_alias m: ^Raw_Map, #no_alias info: ^Map_In
return found
}
if __dynamic_map_check_grow(m, info, loc) != nil {
hash := hash
err, has_grown := __dynamic_map_check_grow(m, info, loc)
if err != nil {
return nil
}
if has_grown {
hash = info.key_hasher(key, map_seed(m^))
}
result := map_insert_hash_dynamic(m, info, hash, uintptr(key), uintptr(value))
m.len += 1
+36
View File
@@ -500,6 +500,42 @@ string_decode_rune :: #force_inline proc "contextless" (s: string) -> (rune, int
return rune(s0&MASK4)<<18 | rune(b1&MASKX)<<12 | rune(b2&MASKX)<<6 | rune(b3&MASKX), 4
}
string_decode_last_rune :: proc "contextless" (s: string) -> (rune, int) {
RUNE_ERROR :: '\ufffd'
RUNE_SELF :: 0x80
UTF_MAX :: 4
r: rune
size: int
start, end, limit: int
end = len(s)
if end == 0 {
return RUNE_ERROR, 0
}
start = end-1
r = rune(s[start])
if r < RUNE_SELF {
return r, 1
}
limit = max(end - UTF_MAX, 0)
for start-=1; start >= limit; start-=1 {
if (s[start] & 0xc0) != RUNE_SELF {
break
}
}
start = max(start, 0)
r, size = string_decode_rune(s[start:end])
if start+size != end {
return RUNE_ERROR, 1
}
return r, size
}
abs_f16 :: #force_inline proc "contextless" (x: f16) -> f16 {
return -x if x < 0 else x
}
+1 -1
View File
@@ -112,7 +112,7 @@ _windows_default_alloc_or_resize :: proc "contextless" (size, alignment: int, ol
ptr := uintptr(aligned_mem)
aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
diff := int(aligned_ptr - ptr)
if (size + diff) > space {
if (size + diff) > space || allocated_mem == nil {
return nil, .Out_Of_Memory
}
+67 -19
View File
@@ -13,6 +13,7 @@ _ :: mem
/*
Turn a pointer and a length into a slice.
*/
@(require_results)
from_ptr :: proc "contextless" (ptr: ^$T, count: int) -> []T {
return ([^]T)(ptr)[:count]
}
@@ -20,6 +21,7 @@ from_ptr :: proc "contextless" (ptr: ^$T, count: int) -> []T {
/*
Turn a pointer and a length into a byte slice.
*/
@(require_results)
bytes_from_ptr :: proc "contextless" (ptr: rawptr, byte_count: int) -> []byte {
return ([^]byte)(ptr)[:byte_count]
}
@@ -29,6 +31,7 @@ bytes_from_ptr :: proc "contextless" (ptr: rawptr, byte_count: int) -> []byte {
See `slice.reinterpret` to go the other way.
*/
@(require_results)
to_bytes :: proc "contextless" (s: []$T) -> []byte {
return ([^]byte)(raw_data(s))[:len(s) * size_of(T)]
}
@@ -51,10 +54,15 @@ to_bytes :: proc "contextless" (s: []$T) -> []byte {
assert(len(large_items) == 1) // only enough bytes to make 1 x i64; two would need at least 8 bytes.
```
*/
@(require_results)
reinterpret :: proc "contextless" ($T: typeid/[]$U, s: []$V) -> []U {
bytes := to_bytes(s)
n := len(bytes) / size_of(U)
return ([^]U)(raw_data(bytes))[:n]
when size_of(U) == 0 || size_of(V) == 0 {
return nil
} else {
bytes := to_bytes(s)
n := len(bytes) / size_of(U)
return ([^]U)(raw_data(bytes))[:n]
}
}
@@ -82,11 +90,13 @@ reverse :: proc(array: $T/[]$E) {
}
@(require_results)
contains :: proc(array: $T/[]$E, value: E) -> bool where intrinsics.type_is_comparable(E) {
_, found := linear_search(array, value)
return found
}
@(require_results)
linear_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
where intrinsics.type_is_comparable(T) #no_bounds_check {
for x, i in array {
@@ -97,6 +107,7 @@ linear_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
return -1, false
}
@(require_results)
linear_search_proc :: proc(array: $A/[]$T, f: proc(T) -> bool) -> (index: int, found: bool) #no_bounds_check {
for x, i in array {
if f(x) {
@@ -106,6 +117,7 @@ linear_search_proc :: proc(array: $A/[]$T, f: proc(T) -> bool) -> (index: int, f
return -1, false
}
@(require_results)
binary_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
where intrinsics.type_is_ordered(T) #no_bounds_check {
@@ -146,6 +158,7 @@ binary_search :: proc(array: $A/[]$T, key: T) -> (index: int, found: bool)
}
@(require_results)
equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_comparable(E) {
if len(a) != len(b) {
return false
@@ -162,6 +175,7 @@ equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_comparable(E) {
}
}
@(require_results)
simple_equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_simple_compare(E) {
if len(a) != len(b) {
return false
@@ -176,6 +190,7 @@ simple_equal :: proc(a, b: $T/[]$E) -> bool where intrinsics.type_is_simple_comp
slice.prefix_length([]u8{1, 2, 3, 4}, []u8{1, 2, 3}) -> 3
slice.prefix_length([]u8{1, 2, 3, 4}, []u8{2, 3, 4}) -> 0
*/
@(require_results)
prefix_length :: proc(a, b: $T/[]$E) -> (n: int) where intrinsics.type_is_comparable(E) {
_len := builtin.min(len(a), len(b))
@@ -185,6 +200,7 @@ prefix_length :: proc(a, b: $T/[]$E) -> (n: int) where intrinsics.type_is_compar
return
}
@(require_results)
has_prefix :: proc(array: $T/[]$E, needle: E) -> bool where intrinsics.type_is_comparable(E) {
n := len(needle)
if len(array) >= n {
@@ -194,6 +210,7 @@ has_prefix :: proc(array: $T/[]$E, needle: E) -> bool where intrinsics.type_is_c
}
@(require_results)
has_suffix :: proc(array: $T/[]$E, needle: E) -> bool where intrinsics.type_is_comparable(E) {
array := array
m, n := len(array), len(needle)
@@ -232,7 +249,8 @@ swap_with_slice :: proc(a, b: $T/[]$E, loc := #caller_location) {
ptr_swap_non_overlapping(raw_data(a), raw_data(b), len(a)*size_of(E))
}
concatenate :: proc(a: []$T/[]$E, allocator := context.allocator) -> (res: T) {
@(require_results)
concatenate :: proc(a: []$T/[]$E, allocator := context.allocator) -> (res: T, err: mem.Allocator_Error) #optional_allocator_error {
if len(a) == 0 {
return
}
@@ -240,7 +258,7 @@ concatenate :: proc(a: []$T/[]$E, allocator := context.allocator) -> (res: T) {
for s in a {
n += len(s)
}
res = make(T, n, allocator)
res = make(T, n, allocator) or_return
i := 0
for s in a {
i += copy(res[i:], s)
@@ -249,22 +267,24 @@ concatenate :: proc(a: []$T/[]$E, allocator := context.allocator) -> (res: T) {
}
// copies a slice into a new slice
clone :: proc(a: $T/[]$E, allocator := context.allocator) -> []E {
d := make([]E, len(a), allocator)
@(require_results)
clone :: proc(a: $T/[]$E, allocator := context.allocator) -> ([]E, mem.Allocator_Error) #optional_allocator_error {
d, err := make([]E, len(a), allocator)
copy(d[:], a)
return d
return d, err
}
// copies slice into a new dynamic array
clone_to_dynamic :: proc(a: $T/[]$E, allocator := context.allocator) -> [dynamic]E {
d := make([dynamic]E, len(a), allocator)
clone_to_dynamic :: proc(a: $T/[]$E, allocator := context.allocator) -> ([dynamic]E, mem.Allocator_Error) #optional_allocator_error {
d, err := make([dynamic]E, len(a), allocator)
copy(d[:], a)
return d
return d, err
}
to_dynamic :: clone_to_dynamic
// Converts slice into a dynamic array without cloning or allocating memory
@(require_results)
into_dynamic :: proc(a: $T/[]$E) -> [dynamic]E {
s := transmute(mem.Raw_Slice)a
d := mem.Raw_Dynamic_Array{
@@ -277,43 +297,51 @@ into_dynamic :: proc(a: $T/[]$E) -> [dynamic]E {
}
@(require_results)
length :: proc(a: $T/[]$E) -> int {
return len(a)
}
@(require_results)
is_empty :: proc(a: $T/[]$E) -> bool {
return len(a) == 0
}
@(require_results)
split_at :: proc(array: $T/[]$E, index: int) -> (a, b: T) {
return array[:index], array[index:]
}
@(require_results)
split_first :: proc(array: $T/[]$E) -> (first: E, rest: T) {
return array[0], array[1:]
}
@(require_results)
split_last :: proc(array: $T/[]$E) -> (rest: T, last: E) {
n := len(array)-1
return array[:n], array[n]
}
@(require_results)
first :: proc(array: $T/[]$E) -> E {
return array[0]
}
@(require_results)
last :: proc(array: $T/[]$E) -> E {
return array[len(array)-1]
}
@(require_results)
first_ptr :: proc(array: $T/[]$E) -> ^E {
if len(array) != 0 {
return &array[0]
}
return nil
}
@(require_results)
last_ptr :: proc(array: $T/[]$E) -> ^E {
if len(array) != 0 {
return &array[len(array)-1]
@@ -321,6 +349,7 @@ last_ptr :: proc(array: $T/[]$E) -> ^E {
return nil
}
@(require_results)
get :: proc(array: $T/[]$E, index: int) -> (value: E, ok: bool) {
if uint(index) < len(array) {
value = array[index]
@@ -328,6 +357,7 @@ get :: proc(array: $T/[]$E, index: int) -> (value: E, ok: bool) {
}
return
}
@(require_results)
get_ptr :: proc(array: $T/[]$E, index: int) -> (value: ^E, ok: bool) {
if uint(index) < len(array) {
value = &array[index]
@@ -336,19 +366,22 @@ get_ptr :: proc(array: $T/[]$E, index: int) -> (value: ^E, ok: bool) {
return
}
@(require_results)
as_ptr :: proc(array: $T/[]$E) -> [^]E {
return raw_data(array)
}
mapper :: proc(s: $S/[]$U, f: proc(U) -> $V, allocator := context.allocator) -> []V {
r := make([]V, len(s), allocator)
@(require_results)
mapper :: proc(s: $S/[]$U, f: proc(U) -> $V, allocator := context.allocator) -> (r: []V, err: mem.Allocator_Error) #optional_allocator_error {
r = make([]V, len(s), allocator) or_return
for v, i in s {
r[i] = f(v)
}
return r
return
}
@(require_results)
reduce :: proc(s: $S/[]$U, initializer: $V, f: proc(V, U) -> V) -> V {
r := initializer
for v in s {
@@ -357,6 +390,7 @@ reduce :: proc(s: $S/[]$U, initializer: $V, f: proc(V, U) -> V) -> V {
return r
}
@(require_results)
filter :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -> S {
r := make([dynamic]U, 0, 0, allocator)
for v in s {
@@ -367,10 +401,11 @@ filter :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -
return r[:]
}
scanner :: proc (s: $S/[]$U, initializer: $V, f: proc(V, U) -> V, allocator := context.allocator) -> []V {
if len(s) == 0 { return {} }
@(require_results)
scanner :: proc (s: $S/[]$U, initializer: $V, f: proc(V, U) -> V, allocator := context.allocator) -> (res: []V, err: mem.Allocator_Error) #optional_allocator_error {
if len(s) == 0 { return }
res := make([]V, len(s), allocator)
res = make([]V, len(s), allocator) or_return
p := as_ptr(s)
q := as_ptr(res)
r := initializer
@@ -382,10 +417,11 @@ scanner :: proc (s: $S/[]$U, initializer: $V, f: proc(V, U) -> V, allocator := c
q = q[1:]
}
return res
return
}
@(require_results)
min :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok {
if len(s) != 0 {
res = s[0]
@@ -396,6 +432,7 @@ min :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T
}
return
}
@(require_results)
max :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok {
if len(s) != 0 {
res = s[0]
@@ -407,6 +444,7 @@ max :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T
return
}
@(require_results)
min_max :: proc(s: $S/[]$T) -> (min, max: T, ok: bool) where intrinsics.type_is_ordered(T) {
if len(s) != 0 {
min, max = s[0], s[0]
@@ -419,6 +457,7 @@ min_max :: proc(s: $S/[]$T) -> (min, max: T, ok: bool) where intrinsics.type_is_
return
}
@(require_results)
any_of :: proc(s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable(T) {
for v in s {
if v == value {
@@ -428,6 +467,7 @@ any_of :: proc(s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable
return false
}
@(require_results)
none_of :: proc(s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable(T) {
for v in s {
if v == value {
@@ -437,6 +477,7 @@ none_of :: proc(s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparabl
return true
}
@(require_results)
all_of :: proc(s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable(T) {
if len(s) == 0 {
return false
@@ -450,6 +491,7 @@ all_of :: proc(s: $S/[]$T, value: T) -> bool where intrinsics.type_is_comparable
}
@(require_results)
any_of_proc :: proc(s: $S/[]$T, f: proc(T) -> bool) -> bool {
for v in s {
if f(v) {
@@ -459,6 +501,7 @@ any_of_proc :: proc(s: $S/[]$T, f: proc(T) -> bool) -> bool {
return false
}
@(require_results)
none_of_proc :: proc(s: $S/[]$T, f: proc(T) -> bool) -> bool {
for v in s {
if f(v) {
@@ -468,6 +511,7 @@ none_of_proc :: proc(s: $S/[]$T, f: proc(T) -> bool) -> bool {
return true
}
@(require_results)
all_of_proc :: proc(s: $S/[]$T, f: proc(T) -> bool) -> bool {
if len(s) == 0 {
return false
@@ -481,6 +525,7 @@ all_of_proc :: proc(s: $S/[]$T, f: proc(T) -> bool) -> bool {
}
@(require_results)
count :: proc(s: $S/[]$T, value: T) -> (n: int) where intrinsics.type_is_comparable(T) {
for v in s {
if v == value {
@@ -490,6 +535,7 @@ count :: proc(s: $S/[]$T, value: T) -> (n: int) where intrinsics.type_is_compara
return
}
@(require_results)
count_proc :: proc(s: $S/[]$T, f: proc(T) -> bool) -> (n: int) {
for v in s {
if f(v) {
@@ -500,6 +546,7 @@ count_proc :: proc(s: $S/[]$T, f: proc(T) -> bool) -> (n: int) {
}
@(require_results)
dot_product :: proc(a, b: $S/[]$T) -> (r: T, ok: bool)
where intrinsics.type_is_numeric(T) {
if len(a) != len(b) {
@@ -513,6 +560,7 @@ dot_product :: proc(a, b: $S/[]$T) -> (r: T, ok: bool)
// Convert a pointer to an enumerated array to a slice of the element type
@(require_results)
enumerated_array :: proc(ptr: ^$T) -> []intrinsics.type_elem_type(T)
where intrinsics.type_is_enumerated_array(T) {
return ([^]intrinsics.type_elem_type(T))(ptr)[:len(T)]
+8 -1
View File
@@ -6,6 +6,7 @@ Ordering :: enum {
Greater = +1,
}
@(require_results)
cmp :: proc(a, b: $E) -> Ordering where ORD(E) {
switch {
case a < b:
@@ -16,6 +17,7 @@ cmp :: proc(a, b: $E) -> Ordering where ORD(E) {
return .Equal
}
@(require_results)
cmp_proc :: proc($E: typeid) -> (proc(E, E) -> Ordering) where ORD(E) {
return proc(a, b: E) -> Ordering {
switch {
@@ -144,6 +146,7 @@ stable_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
}
}
@(require_results)
is_sorted :: proc(array: $T/[]$E) -> bool where ORD(E) {
for i := len(array)-1; i > 0; i -= 1 {
if array[i] < array[i-1] {
@@ -153,6 +156,7 @@ is_sorted :: proc(array: $T/[]$E) -> bool where ORD(E) {
return true
}
@(require_results)
is_sorted_by :: proc(array: $T/[]$E, less: proc(i, j: E) -> bool) -> bool {
for i := len(array)-1; i > 0; i -= 1 {
if less(array[i], array[i-1]) {
@@ -163,6 +167,8 @@ is_sorted_by :: proc(array: $T/[]$E, less: proc(i, j: E) -> bool) -> bool {
}
is_sorted_by_cmp :: is_sorted_cmp
@(require_results)
is_sorted_cmp :: proc(array: $T/[]$E, cmp: proc(i, j: E) -> Ordering) -> bool {
for i := len(array)-1; i > 0; i -= 1 {
if cmp(array[i], array[i-1]) == .Less {
@@ -215,6 +221,7 @@ reverse_sort_by_key :: proc(data: $T/[]$E, key: proc(E) -> $K) where ORD(K) {
})
}
@(require_results)
is_sorted_by_key :: proc(array: $T/[]$E, key: proc(E) -> $K) -> bool where ORD(K) {
for i := len(array)-1; i > 0; i -= 1 {
if key(array[i]) < key(array[i-1]) {
@@ -224,7 +231,7 @@ is_sorted_by_key :: proc(array: $T/[]$E, key: proc(E) -> $K) -> bool where ORD(K
return true
}
@(private)
@(private, require_results)
_max_depth :: proc(n: int) -> (depth: int) { // 2*ceil(log2(n+1))
for i := n; i > 0; i >>= 1 {
depth += 1
+3 -3
View File
@@ -41,7 +41,7 @@ Returns:
*/
@(deprecated="Prefer clone. It now returns an optional allocator error")
clone_safe :: proc(s: string, allocator := context.allocator, loc := #caller_location) -> (res: string, err: mem.Allocator_Error) {
return clone(s, allocator, loc)
return clone(s, allocator, loc)
}
/*
Clones a string and appends a null-byte to make it a cstring
@@ -629,7 +629,7 @@ Returns:
*/
@(deprecated="Prefer join. It now returns an optional allocator error")
join_safe :: proc(a: []string, sep: string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) {
return join(a, sep, allocator)
return join(a, sep, allocator)
}
/*
Returns a combined string from the slice of strings `a` without a separator
@@ -689,7 +689,7 @@ The concatenated string, and an error if allocation fails
*/
@(deprecated="Prefer concatenate. It now returns an optional allocator error")
concatenate_safe :: proc(a: []string, allocator := context.allocator) -> (res: string, err: mem.Allocator_Error) {
return concatenate(a, allocator)
return concatenate(a, allocator)
}
/*
Returns a substring of the input string `s` with the specified rune offset and length
+7 -3
View File
@@ -3,7 +3,6 @@
package sync
import "core:c"
import "core:os"
import "core:time"
FUTEX_WAIT :: 1
@@ -14,11 +13,16 @@ FUTEX_PRIVATE_FLAG :: 128
FUTEX_WAIT_PRIVATE :: (FUTEX_WAIT | FUTEX_PRIVATE_FLAG)
FUTEX_WAKE_PRIVATE :: (FUTEX_WAKE | FUTEX_PRIVATE_FLAG)
ETIMEDOUT :: 60
foreign import libc "system:c"
foreign libc {
@(link_name="futex")
_unix_futex :: proc "c" (f: ^Futex, op: c.int, val: u32, timeout: rawptr) -> c.int ---
@(link_name="__errno") __errno :: proc() -> ^int ---
}
_futex_wait :: proc "contextless" (f: ^Futex, expected: u32) -> bool {
@@ -28,7 +32,7 @@ _futex_wait :: proc "contextless" (f: ^Futex, expected: u32) -> bool {
return true
}
if os.Errno(os.get_last_error()) == os.ETIMEDOUT {
if __errno()^ == ETIMEDOUT {
return false
}
@@ -54,7 +58,7 @@ _futex_wait_with_timeout :: proc "contextless" (f: ^Futex, expected: u32, durati
return true
}
if os.Errno(os.get_last_error()) == os.ETIMEDOUT {
if __errno()^ == ETIMEDOUT {
return false
}
+8 -2
View File
@@ -2,8 +2,14 @@
//+private
package sync
import "core:os"
foreign import libc "system:c"
@(default_calling_convention="c")
foreign libc {
@(link_name="getthrid", private="file")
_unix_getthrid :: proc() -> int ---
}
_current_thread_id :: proc "contextless" () -> int {
return os.current_thread_id()
return _unix_getthrid()
}
+9 -2
View File
@@ -38,7 +38,7 @@ cpu_name: Maybe(string)
@(init, private)
init_cpu_features :: proc "c" () {
is_set :: #force_inline proc "c" (hwc: u32, value: u32) -> bool {
return hwc&value != 0
return hwc&(1 << value) != 0
}
try_set :: #force_inline proc "c" (set: ^CPU_Features, feature: CPU_Feature, hwc: u32, value: u32) {
if is_set(hwc, value) {
@@ -74,8 +74,15 @@ init_cpu_features :: proc "c" () {
return
}
// In certain rare cases (reason unknown), XGETBV generates an
// illegal instruction, even if OSXSAVE is set per CPUID.
//
// When Chrome ran into this problem, the problem went away
// after they started checking both OSXSAVE and XSAVE.
//
// See: crbug.com/375968
os_supports_avx := false
if .os_xsave in set {
if .os_xsave in set && is_set(26, ecx1) {
eax, _ := xgetbv(0)
os_supports_avx = is_set(1, eax) && is_set(2, eax)
}
+22 -22
View File
@@ -968,7 +968,7 @@ prestat_t :: struct {
},
}
@(default_calling_convention="c")
@(default_calling_convention="contextless")
foreign wasi {
/**
* Read command-line argument data.
@@ -1306,7 +1306,7 @@ foreign wasi {
* Returns the number of arguments and the size of the argument string
* data, or an error.
*/
args_sizes_get :: proc "c" () -> (num_args, size_of_args: size_t, err: errno_t) {
args_sizes_get :: proc "contextless" () -> (num_args, size_of_args: size_t, err: errno_t) {
err = wasi_args_sizes_get(&num_args, &size_of_args)
return
}
@@ -1316,7 +1316,7 @@ args_sizes_get :: proc "c" () -> (num_args, size_of_args: size_t, err: errno_t)
* Returns the number of environment variable arguments and the size of the
* environment variable data.
*/
environ_sizes_get :: proc "c" () -> (num_envs, size_of_envs: size_t, err: errno_t) {
environ_sizes_get :: proc "contextless" () -> (num_envs, size_of_envs: size_t, err: errno_t) {
err = wasi_environ_sizes_get(&num_envs, &size_of_envs)
return
}
@@ -1328,7 +1328,7 @@ environ_sizes_get :: proc "c" () -> (num_envs, size_of_envs: size_t, err: errno_
* @return
* The resolution of the clock, or an error if one happened.
*/
clock_res_get :: proc "c" (
clock_res_get :: proc "contextless" (
/**
* The clock for which to return the resolution.
*/
@@ -1343,7 +1343,7 @@ clock_res_get :: proc "c" (
* @return
* The time value of the clock.
*/
clock_time_get :: proc "c" (
clock_time_get :: proc "contextless" (
/**
* The clock for which to return the time.
*/
@@ -1362,7 +1362,7 @@ clock_time_get :: proc "c" (
* @return
* The buffer where the file descriptor's attributes are stored.
*/
fd_fdstat_get :: proc "c" (
fd_fdstat_get :: proc "contextless" (
fd: fd_t,
) -> (stat: fdstat_t, err: errno_t) {
err = wasi_fd_fdstat_get(fd, &stat)
@@ -1373,7 +1373,7 @@ fd_fdstat_get :: proc "c" (
* @return
* The buffer where the file's attributes are stored.
*/
fd_filestat_get :: proc "c" (
fd_filestat_get :: proc "contextless" (
fd: fd_t,
) -> (stat: filestat_t, err: errno_t) {
err = wasi_fd_filestat_get(fd, &stat)
@@ -1389,7 +1389,7 @@ fd_filestat_get :: proc "c" (
* @return
* The number of bytes read.
*/
fd_pread :: proc "c" (
fd_pread :: proc "contextless" (
fd: fd_t,
/**
* List of scatter/gather vectors in which to store data.
@@ -1408,7 +1408,7 @@ fd_pread :: proc "c" (
* @return
* The buffer where the description is stored.
*/
fd_prestat_get :: proc "c" (
fd_prestat_get :: proc "contextless" (
fd: fd_t,
) -> (desc: prestat_t, err: errno_t) {
err = wasi_fd_prestat_get(fd, &desc)
@@ -1420,7 +1420,7 @@ fd_prestat_get :: proc "c" (
* @return
* The number of bytes written.
*/
fd_pwrite :: proc "c" (
fd_pwrite :: proc "contextless" (
fd: fd_t,
/**
* List of scatter/gather vectors from which to retrieve data.
@@ -1440,7 +1440,7 @@ fd_pwrite :: proc "c" (
* @return
* The number of bytes read.
*/
fd_read :: proc "c" (
fd_read :: proc "contextless" (
fd: fd_t,
/**
* List of scatter/gather vectors to which to store data.
@@ -1463,7 +1463,7 @@ fd_read :: proc "c" (
* @return
* The number of bytes stored in the read buffer. If less than the size of the read buffer, the end of the directory has been reached.
*/
fd_readdir :: proc "c" (
fd_readdir :: proc "contextless" (
fd: fd_t,
/**
* The buffer where directory entries are stored
@@ -1483,7 +1483,7 @@ fd_readdir :: proc "c" (
* @return
* The new offset of the file descriptor, relative to the start of the file.
*/
fd_seek :: proc "c" (
fd_seek :: proc "contextless" (
fd: fd_t,
/**
* The number of bytes to move.
@@ -1503,7 +1503,7 @@ fd_seek :: proc "c" (
* @return
* The current offset of the file descriptor, relative to the start of the file.
*/
fd_tell :: proc "c" (
fd_tell :: proc "contextless" (
fd: fd_t,
) -> (offset: filesize_t, err: errno_t) {
err = wasi_fd_tell(fd, &offset)
@@ -1513,7 +1513,7 @@ fd_tell :: proc "c" (
* Write to a file descriptor.
* Note: This is similar to `writev` in POSIX.
*/
fd_write :: proc "c" (
fd_write :: proc "contextless" (
fd: fd_t,
/**
* List of scatter/gather vectors from which to retrieve data.
@@ -1529,7 +1529,7 @@ fd_write :: proc "c" (
* @return
* The buffer where the file's attributes are stored.
*/
path_filestat_get :: proc "c" (
path_filestat_get :: proc "contextless" (
fd: fd_t,
/**
* Flags determining the method of how the path is resolved.
@@ -1554,7 +1554,7 @@ path_filestat_get :: proc "c" (
* @return
* The file descriptor of the file that has been opened.
*/
path_open :: proc "c" (
path_open :: proc "contextless" (
fd: fd_t,
/**
* Flags determining the method of how the path is resolved.
@@ -1591,7 +1591,7 @@ path_open :: proc "c" (
* @return
* The number of bytes placed in the buffer.
*/
path_readlink :: proc "c" (
path_readlink :: proc "contextless" (
fd: fd_t,
/**
* The path of the symbolic link from which to read.
@@ -1610,7 +1610,7 @@ path_readlink :: proc "c" (
* @return
* The number of events stored.
*/
poll_oneoff :: proc "c" (
poll_oneoff :: proc "contextless" (
/**
* The events to which to subscribe.
*/
@@ -1634,7 +1634,7 @@ poll_oneoff :: proc "c" (
* @return
* Number of bytes stored in ri_data and message flags.
*/
sock_recv :: proc "c" (
sock_recv :: proc "contextless" (
fd: fd_t,
/**
* List of scatter/gather vectors to which to store data.
@@ -1655,7 +1655,7 @@ sock_recv :: proc "c" (
* @return
* Number of bytes transmitted.
*/
sock_send :: proc "c" (
sock_send :: proc "contextless" (
fd: fd_t,
/**
* List of scatter/gather vectors to which to retrieve data
@@ -1675,7 +1675,7 @@ sock_send :: proc "c" (
@(default_calling_convention="c")
@(default_calling_convention="contextless")
foreign wasi {
@(link_name="args_sizes_get")
wasi_args_sizes_get :: proc(
+2 -1
View File
@@ -2,6 +2,7 @@
package sys_windows
foreign import kernel32 "system:Kernel32.lib"
foreign import one_core "system:OneCore.lib"
FOREGROUND_BLUE :: WORD(0x0001)
FOREGROUND_GREEN :: WORD(0x0002)
@@ -891,7 +892,7 @@ WIN32_MEMORY_REGION_INFORMATION_u_s_Bitfield :: distinct ULONG
}*/
@(default_calling_convention="stdcall")
foreign kernel32 {
foreign one_core {
QueryVirtualMemoryInformation :: proc(
Process: HANDLE,
VirtualAddress: PVOID,
+3 -1
View File
@@ -52,6 +52,8 @@ foreign user32 {
TranslateMessage :: proc(lpMsg: ^MSG) -> BOOL ---
DispatchMessageW :: proc(lpMsg: ^MSG) -> LRESULT ---
WaitMessage :: proc() -> BOOL ---
PeekMessageA :: proc(lpMsg: ^MSG, hWnd: HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT, wRemoveMsg: UINT) -> BOOL ---
PeekMessageW :: proc(lpMsg: ^MSG, hWnd: HWND, wMsgFilterMin: UINT, wMsgFilterMax: UINT, wRemoveMsg: UINT) -> BOOL ---
@@ -222,6 +224,7 @@ foreign user32 {
GetWindowInfo :: proc(hwnd: HWND, pwi: PWINDOWINFO) -> BOOL ---
GetWindowPlacement :: proc(hWnd: HWND, lpwndpl: ^WINDOWPLACEMENT) -> BOOL ---
SetWindowPlacement :: proc(hwnd: HWND, lpwndpl: ^WINDOWPLACEMENT) -> BOOL ---
SetWindowRgn :: proc(hWnd: HWND, hRgn: HRGN, bRedraw: BOOL) -> int ---
CreateRectRgnIndirect :: proc(lprect: ^RECT) -> HRGN ---
GetSystemMetricsForDpi :: proc(nIndex: int, dpi: UINT) -> int ---
@@ -463,7 +466,6 @@ WINDOWPLACEMENT :: struct {
ptMinPosition: POINT,
ptMaxPosition: POINT,
rcNormalPosition: RECT,
rcDevice: RECT,
}
WINDOWINFO :: struct {
+2 -2
View File
@@ -219,7 +219,7 @@ selection_delete :: proc(s: ^State) {
translate_position :: proc(s: ^State, pos: int, t: Translation) -> int {
is_continuation_byte :: proc(b: byte) -> bool {
return b <= 0x80 && b < 0xc0
return b >= 0x80 && b < 0xc0
}
is_space :: proc(b: byte) -> bool {
return b == ' ' || b == '\t' || b == '\n'
@@ -410,4 +410,4 @@ perform_command :: proc(s: ^State, cmd: Command) {
case .Select_Line_Start: select_to(s, .Soft_Line_Start)
case .Select_Line_End: select_to(s, .Soft_Line_End)
}
}
}
+2 -2
View File
@@ -70,7 +70,7 @@ has_invariant_tsc :: proc "contextless" () -> bool {
return false
}
tsc_frequency :: proc "contextless" () -> (u64, bool) {
tsc_frequency :: proc "contextless" (fallback_sleep := 2 * Second) -> (u64, bool) {
if !has_invariant_tsc() {
return 0, false
}
@@ -81,7 +81,7 @@ tsc_frequency :: proc "contextless" () -> (u64, bool) {
tsc_begin := intrinsics.read_cycle_counter()
tick_begin := tick_now()
sleep(2 * Second)
sleep(fallback_sleep)
tsc_end := intrinsics.read_cycle_counter()
tick_end := tick_now()
+6
View File
@@ -170,6 +170,12 @@ day :: proc "contextless" (t: Time) -> (day: int) {
return
}
weekday :: proc "contextless" (t: Time) -> (weekday: Weekday) {
abs := _time_abs(t)
sec := (abs + u64(Weekday.Monday) * SECONDS_PER_DAY) % SECONDS_PER_WEEK
return Weekday(int(sec) / SECONDS_PER_DAY)
}
clock :: proc { clock_from_time, clock_from_duration, clock_from_stopwatch }
clock_from_time :: proc "contextless" (t: Time) -> (hour, min, sec: int) {
+23 -18
View File
@@ -10,6 +10,11 @@ UTF_MAX :: 4
SURROGATE_MIN :: 0xd800
SURROGATE_MAX :: 0xdfff
// A high/leading surrogate is in range SURROGATE_MIN..SURROGATE_HIGH_MAX,
// A low/trailing surrogate is in range SURROGATE_LOW_MIN..SURROGATE_MAX.
SURROGATE_HIGH_MAX :: 0xdbff
SURROGATE_LOW_MIN :: 0xdc00
T1 :: 0b0000_0000
TX :: 0b1000_0000
T2 :: 0b1100_0000
@@ -54,7 +59,7 @@ accept_sizes := [256]u8{
0xf5..=0xff = 0xf1,
}
encode_rune :: proc(c: rune) -> ([4]u8, int) {
encode_rune :: proc "contextless" (c: rune) -> ([4]u8, int) {
r := c
buf: [4]u8
@@ -95,10 +100,10 @@ decode_rune :: proc{
decode_rune_in_string,
decode_rune_in_bytes,
}
decode_rune_in_string :: #force_inline proc(s: string) -> (rune, int) {
decode_rune_in_string :: #force_inline proc "contextless" (s: string) -> (rune, int) {
return decode_rune_in_bytes(transmute([]u8)s)
}
decode_rune_in_bytes :: proc(s: []u8) -> (rune, int) {
decode_rune_in_bytes :: proc "contextless" (s: []u8) -> (rune, int) {
n := len(s)
if n < 1 {
return RUNE_ERROR, 0
@@ -135,7 +140,7 @@ decode_rune_in_bytes :: proc(s: []u8) -> (rune, int) {
return rune(s0&MASK4)<<18 | rune(b1&MASKX)<<12 | rune(b2&MASKX)<<6 | rune(b3&MASKX), 4
}
string_to_runes :: proc(s: string, allocator := context.allocator) -> (runes: []rune) {
string_to_runes :: proc "odin" (s: string, allocator := context.allocator) -> (runes: []rune) {
n := rune_count_in_string(s)
runes = make([]rune, n, allocator)
@@ -147,7 +152,7 @@ string_to_runes :: proc(s: string, allocator := context.allocator) -> (runes: []
return
}
runes_to_string :: proc(runes: []rune, allocator := context.allocator) -> string {
runes_to_string :: proc "odin" (runes: []rune, allocator := context.allocator) -> string {
byte_count := 0
for r in runes {
_, w := encode_rune(r)
@@ -171,10 +176,10 @@ decode_last_rune :: proc{
decode_last_rune_in_bytes,
}
decode_last_rune_in_string :: #force_inline proc(s: string) -> (rune, int) {
decode_last_rune_in_string :: #force_inline proc "contextless" (s: string) -> (rune, int) {
return decode_last_rune_in_bytes(transmute([]u8)s)
}
decode_last_rune_in_bytes :: proc(s: []u8) -> (rune, int) {
decode_last_rune_in_bytes :: proc "contextless" (s: []u8) -> (rune, int) {
r: rune
size: int
start, end, limit: int
@@ -206,7 +211,7 @@ decode_last_rune_in_bytes :: proc(s: []u8) -> (rune, int) {
return r, size
}
rune_at_pos :: proc(s: string, pos: int) -> rune {
rune_at_pos :: proc "contextless" (s: string, pos: int) -> rune {
if pos < 0 {
return RUNE_ERROR
}
@@ -221,7 +226,7 @@ rune_at_pos :: proc(s: string, pos: int) -> rune {
return RUNE_ERROR
}
rune_string_at_pos :: proc(s: string, pos: int) -> string {
rune_string_at_pos :: proc "contextless" (s: string, pos: int) -> string {
if pos < 0 {
return ""
}
@@ -237,14 +242,14 @@ rune_string_at_pos :: proc(s: string, pos: int) -> string {
return ""
}
rune_at :: proc(s: string, byte_index: int) -> rune {
rune_at :: proc "contextless" (s: string, byte_index: int) -> rune {
r, _ := decode_rune_in_string(s[byte_index:])
return r
}
// Returns the byte position of rune at position pos in s with an optional start byte position.
// Returns -1 if it runs out of the string.
rune_offset :: proc(s: string, pos: int, start: int = 0) -> int {
rune_offset :: proc "contextless" (s: string, pos: int, start: int = 0) -> int {
if pos < 0 {
return -1
}
@@ -259,7 +264,7 @@ rune_offset :: proc(s: string, pos: int, start: int = 0) -> int {
return -1
}
valid_rune :: proc(r: rune) -> bool {
valid_rune :: proc "contextless" (r: rune) -> bool {
if r < 0 {
return false
} else if SURROGATE_MIN <= r && r <= SURROGATE_MAX {
@@ -270,7 +275,7 @@ valid_rune :: proc(r: rune) -> bool {
return true
}
valid_string :: proc(s: string) -> bool {
valid_string :: proc "contextless" (s: string) -> bool {
n := len(s)
for i := 0; i < n; {
si := s[i]
@@ -303,7 +308,7 @@ valid_string :: proc(s: string) -> bool {
return true
}
rune_start :: #force_inline proc(b: u8) -> bool {
rune_start :: #force_inline proc "contextless" (b: u8) -> bool {
return b&0xc0 != 0x80
}
@@ -315,7 +320,7 @@ rune_count :: proc{
rune_count_in_string :: #force_inline proc(s: string) -> int {
return rune_count_in_bytes(transmute([]u8)s)
}
rune_count_in_bytes :: proc(s: []u8) -> int {
rune_count_in_bytes :: proc "contextless" (s: []u8) -> int {
count := 0
n := len(s)
@@ -354,7 +359,7 @@ rune_count_in_bytes :: proc(s: []u8) -> int {
}
rune_size :: proc(r: rune) -> int {
rune_size :: proc "contextless" (r: rune) -> int {
switch {
case r < 0: return -1
case r <= 1<<7 - 1: return 1
@@ -375,7 +380,7 @@ full_rune :: proc{
// full_rune_in_bytes reports if the bytes in b begin with a full utf-8 encoding of a rune or not
// An invalid encoding is considered a full rune since it will convert as an error rune of width 1 (RUNE_ERROR)
full_rune_in_bytes :: proc(b: []byte) -> bool {
full_rune_in_bytes :: proc "contextless" (b: []byte) -> bool {
n := len(b)
if n == 0 {
return false
@@ -395,7 +400,7 @@ full_rune_in_bytes :: proc(b: []byte) -> bool {
// full_rune_in_string reports if the bytes in s begin with a full utf-8 encoding of a rune or not
// An invalid encoding is considered a full rune since it will convert as an error rune of width 1 (RUNE_ERROR)
full_rune_in_string :: proc(s: string) -> bool {
full_rune_in_string :: proc "contextless" (s: string) -> bool {
return full_rune_in_bytes(transmute([]byte)s)
}
+2
View File
@@ -24,6 +24,7 @@ import vk "vendor:vulkan"
import NS "vendor:darwin/Foundation"
import MTL "vendor:darwin/Metal"
import MTK "vendor:darwin/MetalKit"
import CA "vendor:darwin/QuartzCore"
// NOTE(bill): only one can be checked at a time
@@ -53,6 +54,7 @@ _ :: vk
_ :: NS
_ :: MTL
_ :: MTK
_ :: CA
_ :: lua_5_4
+1 -3
View File
@@ -2145,10 +2145,8 @@ or_return_operator :: proc() {
return -345 * z, zerr
}
// If the other return values need to be set depending on what the end value is,
// the 'defer if' idiom is can be used
defer if err != nil {
n = -1
fmt.println("Error in", #procedure, ":" , err)
}
n = 123
+28 -6
View File
@@ -262,6 +262,7 @@ struct BuildContext {
String microarch;
BuildModeKind build_mode;
bool generate_docs;
bool custom_optimization_level;
i32 optimization_level;
bool show_timings;
TimingsExportFormat export_timings_format;
@@ -1272,6 +1273,12 @@ gb_internal void init_build_context(TargetMetrics *cross_target) {
gb_exit(1);
}
if (bc->ODIN_DEBUG && !bc->custom_optimization_level) {
// NOTE(bill): when building with `-debug` but not specifying an optimization level
// default to `-o:none` to improve the debug symbol generation by default
bc->optimization_level = -1; // -o:none
}
bc->optimization_level = gb_clamp(bc->optimization_level, -1, 2);
// ENFORCE DYNAMIC MAP CALLS
@@ -1285,9 +1292,6 @@ gb_internal void init_build_context(TargetMetrics *cross_target) {
break;
}
}
#undef LINK_FLAG_X64
#undef LINK_FLAG_386
}
#if defined(GB_SYSTEM_WINDOWS)
@@ -1497,13 +1501,23 @@ gb_internal bool init_build_paths(String init_filename) {
} else if (is_arch_wasm()) {
output_extension = STR_LIT("wasm");
} else if (build_context.build_mode == BuildMode_Executable) {
// By default use a .bin executable extension.
output_extension = STR_LIT("bin");
// By default use no executable extension.
output_extension = make_string(nullptr, 0);
String const single_file_extension = str_lit(".odin");
if (build_context.metrics.os == TargetOs_windows) {
output_extension = STR_LIT("exe");
} else if (build_context.cross_compiling && selected_target_metrics->metrics == &target_essence_amd64) {
output_extension = make_string(nullptr, 0);
// Do nothing: we don't want the .bin extension
// when cross compiling
} else if (path_is_directory(last_path_element(bc->build_paths[BuildPath_Main_Package].basename))) {
// Add .bin extension to avoid collision
// with package directory name
output_extension = STR_LIT("bin");
} else if (string_ends_with(init_filename, single_file_extension) && path_is_directory(remove_extension_from_path(init_filename))) {
// Add bin extension if compiling single-file package
// with same output name as a directory
output_extension = STR_LIT("bin");
}
} else if (build_context.build_mode == BuildMode_DynamicLibrary) {
// By default use a .so shared library extension.
@@ -1615,6 +1629,14 @@ gb_internal bool init_build_paths(String init_filename) {
return false;
}
if (!write_directory(bc->build_paths[BuildPath_Output].basename)) {
String output_file = path_to_string(ha, bc->build_paths[BuildPath_Output]);
defer (gb_free(ha, output_file.text));
gb_printf_err("No write permissions for output path: %.*s\n", LIT(output_file));
return false;
}
if (bc->target_features_string.len != 0) {
enable_target_feature({}, bc->target_features_string);
}
+83
View File
@@ -4843,6 +4843,89 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
}
operand->mode = Addressing_Type;
break;
case BuiltinProc_type_merge:
{
operand->mode = Addressing_Type;
operand->type = t_invalid;
Operand x = {};
Operand y = {};
check_expr_or_type(c, &x, ce->args[0]);
check_expr_or_type(c, &y, ce->args[1]);
if (x.mode != Addressing_Type) {
error(x.expr, "Expected a type for '%.*s'", LIT(builtin_name));
return false;
}
if (y.mode != Addressing_Type) {
error(y.expr, "Expected a type for '%.*s'", LIT(builtin_name));
return false;
}
if (is_type_polymorphic(x.type)) {
gbString t = type_to_string(x.type);
error(x.expr, "Expected a non-polymorphic type for '%.*s', got %s", LIT(builtin_name), t);
gb_string_free(t);
return false;
}
if (is_type_polymorphic(y.type)) {
gbString t = type_to_string(y.type);
error(y.expr, "Expected a non-polymorphic type for '%.*s', got %s", LIT(builtin_name), t);
gb_string_free(t);
return false;
}
if (!is_type_union(x.type)) {
gbString t = type_to_string(x.type);
error(x.expr, "Expected a union type for '%.*s', got %s", LIT(builtin_name), t);
gb_string_free(t);
return false;
}
if (!is_type_union(y.type)) {
gbString t = type_to_string(y.type);
error(x.expr, "Expected a union type for '%.*s', got %s", LIT(builtin_name), t);
gb_string_free(t);
return false;
}
Type *ux = base_type(x.type);
Type *uy = base_type(y.type);
GB_ASSERT(ux->kind == Type_Union);
GB_ASSERT(uy->kind == Type_Union);
i64 custom_align = gb_max(ux->Union.custom_align, uy->Union.custom_align);
if (ux->Union.kind != uy->Union.kind) {
error(x.expr, "Union kinds must match, got %s vs %s", union_type_kind_strings[ux->Union.kind], union_type_kind_strings[uy->Union.kind]);
}
Type *merged_union = alloc_type_union();
merged_union->Union.node = call;
merged_union->Union.scope = create_scope(c->info, c->scope);
merged_union->Union.kind = ux->Union.kind;
merged_union->Union.custom_align = custom_align;
auto variants = array_make<Type *>(permanent_allocator(), 0, ux->Union.variants.count+uy->Union.variants.count);
for (Type *t : ux->Union.variants) {
array_add(&variants, t);
}
for (Type *t : uy->Union.variants) {
bool ok = true;
for (Type *other_t : ux->Union.variants) {
if (are_types_identical(other_t, t)) {
ok = false;
break;
}
}
if (ok) {
array_add(&variants, t);
}
}
merged_union->Union.variants = slice_from_array(variants);
operand->mode = Addressing_Type;
operand->type = merged_union;
}
break;
case BuiltinProc_type_is_boolean:
case BuiltinProc_type_is_integer:
+14 -10
View File
@@ -43,14 +43,20 @@ gb_internal Type *check_init_variable(CheckerContext *ctx, Entity *e, Operand *o
}
if (operand->mode == Addressing_Type) {
if (e->type != nullptr && is_type_typeid(e->type)) {
if (e->type != nullptr && is_type_typeid(e->type) && !is_type_polymorphic(operand->type)) {
add_type_info_type(ctx, operand->type);
add_type_and_value(ctx, operand->expr, Addressing_Value, e->type, exact_value_typeid(operand->type));
return e->type;
} else {
ERROR_BLOCK();
gbString t = type_to_string(operand->type);
defer (gb_string_free(t));
error(operand->expr, "Cannot assign a type '%s' to variable '%.*s'", t, LIT(e->token.string));
if (is_type_polymorphic(operand->type)) {
error(operand->expr, "Cannot assign a non-specialized polymorphic type '%s' to variable '%.*s'", t, LIT(e->token.string));
} else {
error(operand->expr, "Cannot assign a type '%s' to variable '%.*s'", t, LIT(e->token.string));
}
if (e->type == nullptr) {
error_line("\tThe type of the variable '%.*s' cannot be inferred as a type does not have a default type\n", LIT(e->token.string));
}
@@ -59,20 +65,17 @@ gb_internal Type *check_init_variable(CheckerContext *ctx, Entity *e, Operand *o
}
}
if (e->type == nullptr) {
// NOTE(bill): Use the type of the operand
Type *t = operand->type;
if (is_type_untyped(t)) {
if (t == t_invalid || is_type_untyped_nil(t)) {
error(e->token, "Invalid use of untyped nil in %.*s", LIT(context_name));
if (is_type_untyped_uninit(t)) {
error(e->token, "Invalid use of --- in %.*s", LIT(context_name));
e->type = t_invalid;
return nullptr;
}
if (t == t_invalid || is_type_untyped_undef(t)) {
error(e->token, "Invalid use of --- in %.*s", LIT(context_name));
} else if (t == t_invalid || is_type_untyped_nil(t)) {
error(e->token, "Invalid use of untyped nil in %.*s", LIT(context_name));
e->type = t_invalid;
return nullptr;
}
@@ -119,7 +122,7 @@ gb_internal void check_init_variables(CheckerContext *ctx, Entity **lhs, isize l
// an extra allocation
TEMPORARY_ALLOCATOR_GUARD();
auto operands = array_make<Operand>(temporary_allocator(), 0, 2*lhs_count);
check_unpack_arguments(ctx, lhs, lhs_count, &operands, inits, true, false);
check_unpack_arguments(ctx, lhs, lhs_count, &operands, inits, UnpackFlag_AllowOk|UnpackFlag_AllowUndef);
isize rhs_count = operands.count;
isize max = gb_min(lhs_count, rhs_count);
@@ -947,6 +950,7 @@ gb_internal void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
if (ac.require_declaration) {
e->flags |= EntityFlag_Require;
pl->inlining = ProcInlining_no_inline;
}
+53 -31
View File
@@ -646,11 +646,8 @@ gb_internal i64 check_distance_between_types(CheckerContext *c, Operand *operand
Type *src = base_type(s);
Type *dst = base_type(type);
if (is_type_untyped_undef(src)) {
if (type_has_undef(dst)) {
return 1;
}
return -1;
if (is_type_untyped_uninit(src)) {
return 1;
}
if (is_type_untyped_nil(src)) {
@@ -993,13 +990,13 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ
if (is_type_untyped(operand->type)) {
Type *target_type = type;
if (type == nullptr || is_type_any(type)) {
if (type == nullptr && is_type_untyped_nil(operand->type)) {
error(operand->expr, "Use of untyped nil in %.*s", LIT(context_name));
if (type == nullptr && is_type_untyped_uninit(operand->type)) {
error(operand->expr, "Use of --- in %.*s", LIT(context_name));
operand->mode = Addressing_Invalid;
return;
}
if (type == nullptr && is_type_untyped_undef(operand->type)) {
error(operand->expr, "Use of --- in %.*s", LIT(context_name));
if (type == nullptr && is_type_untyped_nil(operand->type)) {
error(operand->expr, "Use of untyped nil in %.*s", LIT(context_name));
operand->mode = Addressing_Invalid;
return;
}
@@ -1067,7 +1064,7 @@ gb_internal void check_assignment(CheckerContext *c, Operand *operand, Type *typ
if (check_is_assignable_to(c, operand, type)) {
if (operand->mode == Addressing_Type && is_type_typeid(type)) {
add_type_info_type(c, operand->type);
add_type_info_type(c, operand->type);
add_type_and_value(c, operand->expr, Addressing_Value, type, exact_value_typeid(operand->type));
}
} else {
@@ -3969,7 +3966,7 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar
case Type_Union:
if (!is_operand_nil(*operand) && !is_operand_undef(*operand)) {
if (!is_operand_nil(*operand) && !is_operand_uninit(*operand)) {
TEMPORARY_ALLOCATOR_GUARD();
isize count = t->Union.variants.count;
@@ -4036,8 +4033,8 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar
error_line("\n\n");
return;
} else if (is_type_untyped_undef(operand->type) && type_has_undef(target_type)) {
target_type = t_untyped_undef;
} else if (is_type_untyped_uninit(operand->type)) {
target_type = t_untyped_uninit;
} else if (!is_type_untyped_nil(operand->type) || !type_has_nil(target_type)) {
begin_error_block();
defer (end_error_block());
@@ -4070,8 +4067,8 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar
default:
if (is_type_untyped_undef(operand->type) && type_has_undef(target_type)) {
target_type = t_untyped_undef;
if (is_type_untyped_uninit(operand->type)) {
target_type = t_untyped_uninit;
} else if (is_type_untyped_nil(operand->type) && type_has_nil(target_type)) {
target_type = t_untyped_nil;
} else {
@@ -4083,8 +4080,8 @@ gb_internal void convert_to_typed(CheckerContext *c, Operand *operand, Type *tar
}
if (is_type_any(target_type) && is_type_untyped(operand->type)) {
if (is_type_untyped_nil(operand->type) && is_type_untyped_undef(operand->type)) {
if (is_type_untyped_nil(operand->type) && is_type_untyped_uninit(operand->type)) {
} else {
target_type = default_type(operand->type);
}
@@ -5144,8 +5141,20 @@ gb_internal bool check_assignment_arguments(CheckerContext *ctx, Array<Operand>
}
typedef u32 UnpackFlags;
enum UnpackFlag : u32 {
UnpackFlag_None = 0,
UnpackFlag_AllowOk = 1<<0,
UnpackFlag_IsVariadic = 1<<1,
UnpackFlag_AllowUndef = 1<<2,
};
gb_internal bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count, Array<Operand> *operands, Slice<Ast *> const &rhs, UnpackFlags flags) {
bool allow_ok = (flags & UnpackFlag_AllowOk) != 0;
bool is_variadic = (flags & UnpackFlag_IsVariadic) != 0;
bool allow_undef = (flags & UnpackFlag_AllowUndef) != 0;
gb_internal bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize lhs_count, Array<Operand> *operands, Slice<Ast *> const &rhs, bool allow_ok, bool is_variadic) {
bool optional_ok = false;
isize tuple_index = 0;
for_array(i, rhs) {
@@ -5184,7 +5193,16 @@ gb_internal bool check_unpack_arguments(CheckerContext *ctx, Entity **lhs, isize
}
}
check_expr_base(c, &o, rhs[i], type_hint);
Ast *rhs_expr = unparen_expr(rhs[i]);
if (allow_undef && rhs_expr != nullptr && rhs_expr->kind == Ast_Uninit) {
// NOTE(bill): Just handle this very specific logic here
o.type = t_untyped_uninit;
o.mode = Addressing_Value;
o.expr = rhs[i];
add_type_and_value(c, rhs[i], o.mode, o.type, o.value);
} else {
check_expr_base(c, &o, rhs[i], type_hint);
}
if (o.mode == Addressing_NoValue) {
error_operand_no_value(&o);
o.mode = Addressing_Invalid;
@@ -5968,7 +5986,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op
lhs = populate_proc_parameter_list(c, proc_type, &lhs_count, &is_variadic);
}
if (operand->mode != Addressing_ProcGroup) {
check_unpack_arguments(c, lhs, lhs_count, &operands, args, false, is_variadic);
check_unpack_arguments(c, lhs, lhs_count, &operands, args, is_variadic ? UnpackFlag_IsVariadic : UnpackFlag_None);
}
}
@@ -6025,7 +6043,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op
isize lhs_count = -1;
bool is_variadic = false;
lhs = populate_proc_parameter_list(c, e->type, &lhs_count, &is_variadic);
check_unpack_arguments(c, lhs, lhs_count, &operands, args, false, is_variadic);
check_unpack_arguments(c, lhs, lhs_count, &operands, args, is_variadic ? UnpackFlag_IsVariadic : UnpackFlag_None);
CallArgumentData data = {};
CallArgumentError err = call_checker(c, call, e->type, e, operands, CallArgumentMode_ShowErrors, &data);
@@ -6101,7 +6119,7 @@ gb_internal CallArgumentData check_call_arguments(CheckerContext *c, Operand *op
}
check_unpack_arguments(c, lhs, lhs_count, &operands, args, false, false);
check_unpack_arguments(c, lhs, lhs_count, &operands, args, UnpackFlag_None);
if (lhs != nullptr) {
gb_free(heap_allocator(), lhs);
@@ -6462,7 +6480,7 @@ gb_internal CallArgumentError check_polymorphic_record_type(CheckerContext *c, O
lhs_count = params->variables.count;
}
check_unpack_arguments(c, lhs, lhs_count, &operands, ce->args, false, false);
check_unpack_arguments(c, lhs, lhs_count, &operands, ce->args, UnpackFlag_None);
}
}
@@ -7146,11 +7164,11 @@ gb_internal bool check_set_index_data(Operand *o, Type *t, bool indirection, i64
}
gb_internal bool ternary_compare_types(Type *x, Type *y) {
if (is_type_untyped_undef(x) && type_has_undef(y)) {
if (is_type_untyped_uninit(x)) {
return true;
} else if (is_type_untyped_nil(x) && type_has_nil(y)) {
return true;
} else if (is_type_untyped_undef(y) && type_has_undef(x)) {
} else if (is_type_untyped_uninit(y)) {
return true;
} else if (is_type_untyped_nil(y) && type_has_nil(x)) {
return true;
@@ -7687,7 +7705,7 @@ gb_internal ExprKind check_ternary_if_expr(CheckerContext *c, Operand *o, Ast *n
}
o->type = x.type;
if (is_type_untyped_nil(o->type) || is_type_untyped_undef(o->type)) {
if (is_type_untyped_nil(o->type) || is_type_untyped_uninit(o->type)) {
o->type = y.type;
}
@@ -7887,8 +7905,11 @@ gb_internal ExprKind check_or_return_expr(CheckerContext *c, Operand *o, Ast *no
rhs.type = right_type;
rhs.mode = Addressing_Value;
// TODO(bill): better error message
if (!check_is_assignable_to(c, &rhs, end_type)) {
if (is_type_boolean(right_type) && is_type_boolean(end_type)) {
// NOTE(bill): allow implicit conversion between boolean types
// within 'or_return' to improve the experience using third-party code
} else if (!check_is_assignable_to(c, &rhs, end_type)) {
// TODO(bill): better error message
gbString a = type_to_string(right_type);
gbString b = type_to_string(end_type);
gbString ret_type = type_to_string(result_type);
@@ -9577,9 +9598,10 @@ gb_internal ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast
check_ident(c, o, node, nullptr, type_hint, false);
case_end;
case_ast_node(u, Undef, node);
case_ast_node(u, Uninit, node);
o->mode = Addressing_Value;
o->type = t_untyped_undef;
o->type = t_untyped_uninit;
error(node, "Use of --- outside of variable declaration");
case_end;
@@ -10142,7 +10164,7 @@ gb_internal gbString write_expr_to_string(gbString str, Ast *node, bool shorthan
str = string_append_string(str, bd->name.string);
case_end;
case_ast_node(ud, Undef, node);
case_ast_node(ud, Uninit, node);
str = gb_string_appendc(str, "---");
case_end;
+26 -2
View File
@@ -402,6 +402,12 @@ gb_internal Type *check_assignment_variable(CheckerContext *ctx, Operand *lhs, O
Type *assignment_type = lhs->type;
if (rhs->mode == Addressing_Type && is_type_polymorphic(rhs->type)) {
gbString t = type_to_string(rhs->type);
error(rhs->expr, "Invalid use of a non-specialized polymorphic type '%s'", t);
gb_string_free(t);
}
switch (lhs->mode) {
case Addressing_Invalid:
return nullptr;
@@ -1455,6 +1461,7 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
bool is_map = false;
bool use_by_reference_for_value = false;
bool is_soa = false;
bool is_reverse = rs->reverse;
Ast *expr = unparen_expr(rs->expr);
@@ -1470,6 +1477,10 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
}
array_add(&vals, x.type);
array_add(&vals, t_int);
if (is_reverse) {
error(node, "#reverse for is not supported with ranges, prefer an explicit for loop with init, condition, and post arguments");
}
} else {
Operand operand = {Addressing_Invalid};
check_expr_base(ctx, &operand, expr, nullptr);
@@ -1482,6 +1493,9 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
gb_string_free(t);
goto skip_expr_range_stmt;
} else {
if (is_reverse) {
error(node, "#reverse for is not supported for enum types");
}
array_add(&vals, operand.type);
array_add(&vals, t_int);
add_type_info_type(ctx, operand.type);
@@ -1495,7 +1509,11 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
if (is_type_string(t) && t->Basic.kind != Basic_cstring) {
array_add(&vals, t_rune);
array_add(&vals, t_int);
add_package_dependency(ctx, "runtime", "string_decode_rune");
if (is_reverse) {
add_package_dependency(ctx, "runtime", "string_decode_last_rune");
} else {
add_package_dependency(ctx, "runtime", "string_decode_rune");
}
}
break;
@@ -1528,6 +1546,9 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
is_map = true;
array_add(&vals, t->Map.key);
array_add(&vals, t->Map.value);
if (is_reverse) {
error(node, "#reverse for is not supported for map types, as maps are unordered");
}
break;
case Type_Tuple:
@@ -1564,6 +1585,9 @@ gb_internal void check_range_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags)
break;
}
if (is_reverse) {
error(node, "#reverse for is not supported for multiple return valued parameters");
}
}
break;
@@ -2170,7 +2194,7 @@ gb_internal void check_return_stmt(CheckerContext *ctx, Ast *node) {
auto operands = array_make<Operand>(heap_allocator(), 0, 2*rs->results.count);
defer (array_free(&operands));
check_unpack_arguments(ctx, result_entities, result_count, &operands, rs->results, true, false);
check_unpack_arguments(ctx, result_entities, result_count, &operands, rs->results, UnpackFlag_AllowOk);
if (result_count == 0 && rs->results.count > 0) {
error(rs->results[0], "No return values expected");
+3 -3
View File
@@ -135,7 +135,7 @@ gb_internal void check_struct_fields(CheckerContext *ctx, Ast *node, Slice<Entit
type = t_invalid;
}
if (is_type_untyped(type)) {
if (is_type_untyped_undef(type)) {
if (is_type_untyped_uninit(type)) {
error(params[i], "Cannot determine parameter type from ---");
} else {
error(params[i], "Cannot determine parameter type from a nil");
@@ -473,7 +473,7 @@ gb_internal Type *check_record_polymorphic_params(CheckerContext *ctx, Ast *poly
type = t_invalid;
}
if (is_type_untyped(type)) {
if (is_type_untyped_undef(type)) {
if (is_type_untyped_uninit(type)) {
error(params[i], "Cannot determine parameter type from ---");
} else {
error(params[i], "Cannot determine parameter type from a nil");
@@ -1528,7 +1528,7 @@ gb_internal Type *check_get_params(CheckerContext *ctx, Scope *scope, Ast *_para
type = t_invalid;
}
if (is_type_untyped(type)) {
if (is_type_untyped_undef(type)) {
if (is_type_untyped_uninit(type)) {
error(param, "Cannot determine parameter type from ---");
} else {
error(param, "Cannot determine parameter type from a nil");
+2 -2
View File
@@ -27,8 +27,8 @@ gb_internal bool is_operand_value(Operand o) {
gb_internal bool is_operand_nil(Operand o) {
return o.mode == Addressing_Value && o.type == t_untyped_nil;
}
gb_internal bool is_operand_undef(Operand o) {
return o.mode == Addressing_Value && o.type == t_untyped_undef;
gb_internal bool is_operand_uninit(Operand o) {
return o.mode == Addressing_Value && o.type == t_untyped_uninit;
}
gb_internal bool check_rtti_type_disallowed(Token const &token, Type *type, char const *format) {
+2
View File
@@ -203,6 +203,7 @@ BuiltinProc__type_begin,
BuiltinProc_type_elem_type,
BuiltinProc_type_convert_variants_to_pointers,
BuiltinProc_type_merge,
BuiltinProc__type_simple_boolean_begin,
BuiltinProc_type_is_boolean,
@@ -501,6 +502,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT("type_core_type"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_elem_type"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_convert_variants_to_pointers"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_merge"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
{STR_LIT("type_is_boolean"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+68 -12
View File
@@ -30,6 +30,7 @@ struct OdinDocWriter {
PtrMap<AstPackage *, OdinDocPkgIndex> pkg_cache;
PtrMap<Entity *, OdinDocEntityIndex> entity_cache;
PtrMap<Type *, OdinDocTypeIndex> type_cache;
PtrMap<Type *, Type *> stable_type_cache;
OdinDocWriterItemTracker<OdinDocFile> files;
OdinDocWriterItemTracker<OdinDocPkg> pkgs;
@@ -51,6 +52,7 @@ gb_internal void odin_doc_writer_item_tracker_init(OdinDocWriterItemTracker<T> *
gb_internal void odin_doc_writer_prepare(OdinDocWriter *w) {
debugf("odin_doc_writer_prepare\n");
w->state = OdinDocWriterState_Preparing;
string_map_init(&w->string_cache);
@@ -59,6 +61,7 @@ gb_internal void odin_doc_writer_prepare(OdinDocWriter *w) {
map_init(&w->pkg_cache);
map_init(&w->entity_cache);
map_init(&w->type_cache);
map_init(&w->stable_type_cache);
odin_doc_writer_item_tracker_init(&w->files, 1);
odin_doc_writer_item_tracker_init(&w->pkgs, 1);
@@ -70,6 +73,7 @@ gb_internal void odin_doc_writer_prepare(OdinDocWriter *w) {
gb_internal void odin_doc_writer_destroy(OdinDocWriter *w) {
debugf("odin_doc_writer_destroy\n");
gb_free(heap_allocator(), w->data);
string_map_destroy(&w->string_cache);
@@ -77,6 +81,7 @@ gb_internal void odin_doc_writer_destroy(OdinDocWriter *w) {
map_destroy(&w->pkg_cache);
map_destroy(&w->entity_cache);
map_destroy(&w->type_cache);
map_destroy(&w->stable_type_cache);
}
@@ -102,6 +107,7 @@ gb_internal isize odin_doc_writer_calc_total_size(OdinDocWriter *w) {
}
gb_internal void odin_doc_writer_start_writing(OdinDocWriter *w) {
debugf("odin_doc_writer_start_writing\n");
w->state = OdinDocWriterState_Writing;
string_map_clear(&w->string_cache);
@@ -138,6 +144,7 @@ gb_internal void odin_doc_writer_assign_tracker(OdinDocArray<T> *array, OdinDocW
gb_internal void odin_doc_writer_end_writing(OdinDocWriter *w) {
debugf("odin_doc_writer_end_writing\n");
OdinDocHeader *h = w->header;
gb_memmove(h->base.magic, OdinDocHeader_MagicString, gb_strlen(OdinDocHeader_MagicString));
@@ -471,22 +478,60 @@ gb_internal OdinDocArray<OdinDocEntityIndex> odin_doc_add_entity_as_slice(OdinDo
return odin_write_item_as_slice(w, index);
}
gb_internal OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) {
if (type == nullptr) {
return 0;
}
// Type **mapped_type = map_get(&w->stable_type_cache, type); // may map to itself
// if (mapped_type && *mapped_type) {
// type = *mapped_type;
// }
OdinDocTypeIndex *found = map_get(&w->type_cache, type);
if (found) {
return *found;
}
for (auto const &entry : w->type_cache) {
// NOTE(bill): THIS IS SLOW
Type *other = entry.key;
if (are_types_identical_unique_tuples(type, other)) {
OdinDocTypeIndex index = entry.value;
map_set(&w->type_cache, type, index);
return index;
Type *x = type;
Type *y = entry.key;
if (x == y) {
goto do_set;
}
if (!x | !y) {
continue;
}
if (x->kind == Type_Named) {
Entity *e = x->Named.type_name;
if (e->TypeName.is_type_alias) {
x = x->Named.base;
}
}
if (y->kind == Type_Named) {
Entity *e = y->Named.type_name;
if (e->TypeName.is_type_alias) {
y = y->Named.base;
}
}
if (x->kind != y->kind) {
continue;
}
if (!are_types_identical_internal(x, y, true)) {
continue;
}
do_set:
OdinDocTypeIndex index = entry.value;
map_set(&w->type_cache, type, index);
map_set(&w->stable_type_cache, type, entry.key);
return index;
}
@@ -495,6 +540,7 @@ gb_internal OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) {
OdinDocTypeIndex type_index = 0;
type_index = odin_doc_write_item(w, &w->types, &doc_type, &dst);
map_set(&w->type_cache, type, type_index);
map_set(&w->stable_type_cache, type, type);
switch (type->kind) {
case Type_Basic:
@@ -856,13 +902,12 @@ gb_internal OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e)
break;
}
if (e->flags & EntityFlag_Param) {
if (e->flags & EntityFlag_Using) { flags |= OdinDocEntityFlag_Param_Using; }
if (e->flags & EntityFlag_ConstInput) { flags |= OdinDocEntityFlag_Param_Const; }
if (e->flags & EntityFlag_Ellipsis) { flags |= OdinDocEntityFlag_Param_Ellipsis; }
if (e->flags & EntityFlag_NoAlias) { flags |= OdinDocEntityFlag_Param_NoAlias; }
if (e->flags & EntityFlag_AnyInt) { flags |= OdinDocEntityFlag_Param_AnyInt; }
}
if (e->flags & EntityFlag_Using) { flags |= OdinDocEntityFlag_Param_Using; }
if (e->flags & EntityFlag_ConstInput) { flags |= OdinDocEntityFlag_Param_Const; }
if (e->flags & EntityFlag_Ellipsis) { flags |= OdinDocEntityFlag_Param_Ellipsis; }
if (e->flags & EntityFlag_NoAlias) { flags |= OdinDocEntityFlag_Param_NoAlias; }
if (e->flags & EntityFlag_AnyInt) { flags |= OdinDocEntityFlag_Param_AnyInt; }
if (e->scope && (e->scope->flags & (ScopeFlag_File|ScopeFlag_Pkg)) && !is_entity_exported(e)) {
flags |= OdinDocEntityFlag_Private;
}
@@ -910,6 +955,8 @@ gb_internal OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e)
}
gb_internal void odin_doc_update_entities(OdinDocWriter *w) {
debugf("odin_doc_update_entities %s\n", w->state ? "preparing" : "writing");
{
// NOTE(bill): Double pass, just in case entities are created on odin_doc_type
auto entities = array_make<Entity *>(heap_allocator(), 0, w->entity_cache.count);
@@ -974,6 +1021,8 @@ gb_internal OdinDocArray<OdinDocScopeEntry> odin_doc_add_pkg_entries(OdinDocWrit
return {};
}
debugf("odin_doc_add_pkg_entries %s -> package %.*s\n", w->state ? "preparing" : "writing", LIT(pkg->name));
auto entries = array_make<OdinDocScopeEntry>(heap_allocator(), 0, w->entity_cache.count);
defer (array_free(&entries));
@@ -1017,6 +1066,8 @@ gb_internal OdinDocArray<OdinDocScopeEntry> odin_doc_add_pkg_entries(OdinDocWrit
gb_internal void odin_doc_write_docs(OdinDocWriter *w) {
debugf("odin_doc_write_docs %s", w->state ? "preparing" : "writing");
auto pkgs = array_make<AstPackage *>(heap_allocator(), 0, w->info->packages.count);
defer (array_free(&pkgs));
for (auto const &entry : w->info->packages) {
@@ -1032,6 +1083,7 @@ gb_internal void odin_doc_write_docs(OdinDocWriter *w) {
}
}
debugf("odin_doc_update_entities sort pkgs %s\n", w->state ? "preparing" : "writing");
gb_sort_array(pkgs.data, pkgs.count, cmp_ast_package_by_name);
for_array(i, pkgs) {
@@ -1092,6 +1144,7 @@ gb_internal void odin_doc_write_docs(OdinDocWriter *w) {
gb_internal void odin_doc_write_to_file(OdinDocWriter *w, char const *filename) {
debugf("odin_doc_write_to_file %s\n", filename);
gbFile f = {};
gbFileError err = gb_file_open_mode(&f, gbFileMode_Write, filename);
if (err != gbFileError_None) {
@@ -1102,6 +1155,7 @@ gb_internal void odin_doc_write_to_file(OdinDocWriter *w, char const *filename)
defer (gb_file_close(&f));
if (gb_file_write(&f, w->data, w->data_len)) {
err = gb_file_truncate(&f, w->data_len);
debugf("Wrote .odin-doc file to: %s\n", filename);
gb_printf("Wrote .odin-doc file to: %s\n", filename);
}
}
@@ -1112,6 +1166,8 @@ gb_internal void odin_doc_write(CheckerInfo *info, char const *filename) {
defer (odin_doc_writer_destroy(w));
w->info = info;
debugf("odin_doc_write %s\n", filename);
odin_doc_writer_prepare(w);
odin_doc_write_docs(w);
+14 -3
View File
@@ -8,8 +8,9 @@ struct ErrorCollector {
BlockingMutex string_mutex;
RecursiveMutex block_mutex;
Array<u8> error_buffer;
Array<String> errors;
RecursiveMutex error_buffer_mutex;
Array<u8> error_buffer;
Array<String> errors;
};
gb_global ErrorCollector global_error_collector;
@@ -119,6 +120,7 @@ gb_internal void begin_error_block(void) {
}
gb_internal void end_error_block(void) {
mutex_lock(&global_error_collector.error_buffer_mutex);
isize n = global_error_collector.error_buffer.count;
if (n > 0) {
u8 *text = global_error_collector.error_buffer.data;
@@ -150,11 +152,16 @@ gb_internal void end_error_block(void) {
text = gb_alloc_array(permanent_allocator(), u8, n+1);
gb_memmove(text, global_error_collector.error_buffer.data, n);
text[n] = 0;
mutex_lock(&global_error_collector.error_out_mutex);
String s = {text, n};
array_add(&global_error_collector.errors, s);
mutex_unlock(&global_error_collector.error_out_mutex);
global_error_collector.error_buffer.count = 0;
}
mutex_unlock(&global_error_collector.error_buffer_mutex);
global_error_collector.in_block.store(false);
mutex_unlock(&global_error_collector.block_mutex);
}
@@ -172,11 +179,15 @@ gb_internal ERROR_OUT_PROC(default_error_out_va) {
isize len = gb_snprintf_va(buf, gb_size_of(buf), fmt, va);
isize n = len-1;
if (global_error_collector.in_block) {
mutex_lock(&global_error_collector.error_buffer_mutex);
isize cap = global_error_collector.error_buffer.count + n;
array_reserve(&global_error_collector.error_buffer, cap);
u8 *data = global_error_collector.error_buffer.data + global_error_collector.error_buffer.count;
gb_memmove(data, buf, n);
global_error_collector.error_buffer.count += n;
mutex_unlock(&global_error_collector.error_buffer_mutex);
} else {
mutex_lock(&global_error_collector.error_out_mutex);
{
+27 -10
View File
@@ -1179,7 +1179,11 @@ namespace lbAbiArm64 {
if (is_register(type)) {
args[i] = non_struct(c, type);
} else if (is_homogenous_aggregate(c, type, &homo_base_type, &homo_member_count)) {
args[i] = lb_arg_type_direct(type, LLVMArrayType(homo_base_type, homo_member_count), nullptr, nullptr);
if (is_homogenous_aggregate_small_enough(homo_base_type, homo_member_count)) {
args[i] = lb_arg_type_direct(type, LLVMArrayType(homo_base_type, homo_member_count), nullptr, nullptr);
} else {
args[i] = lb_arg_type_indirect(type, nullptr);;
}
} else {
i64 size = lb_sizeof(type);
if (size <= 16) {
@@ -1213,7 +1217,7 @@ namespace lbAbiWasm {
The approach taken optimizes for passing things in multiple
registers/arguments if possible rather than by pointer.
*/
gb_internal Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count);
gb_internal Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention);
gb_internal LB_ABI_COMPUTE_RETURN_TYPE(compute_return_type);
enum {MAX_DIRECT_STRUCT_SIZE = 32};
@@ -1221,7 +1225,7 @@ namespace lbAbiWasm {
gb_internal LB_ABI_INFO(abi_info) {
lbFunctionType *ft = gb_alloc_item(permanent_allocator(), lbFunctionType);
ft->ctx = c;
ft->args = compute_arg_types(c, arg_types, arg_count);
ft->args = compute_arg_types(c, arg_types, arg_count, calling_convention);
ft->ret = compute_return_type(ft, c, return_type, return_is_defined, return_is_tuple);
ft->calling_convention = calling_convention;
return ft;
@@ -1258,13 +1262,26 @@ namespace lbAbiWasm {
return false;
}
gb_internal bool type_can_be_direct(LLVMTypeRef type) {
gb_internal bool type_can_be_direct(LLVMTypeRef type, ProcCallingConvention calling_convention) {
LLVMTypeKind kind = LLVMGetTypeKind(type);
i64 sz = lb_sizeof(type);
if (sz == 0) {
return false;
}
if (sz <= MAX_DIRECT_STRUCT_SIZE) {
if (calling_convention == ProcCC_CDecl) {
// WASM Basic C ABI:
// https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md#function-signatures
if (kind == LLVMArrayTypeKind) {
return false;
} else if (kind == LLVMStructTypeKind) {
unsigned count = LLVMCountStructElementTypes(type);
if (count == 1) {
return type_can_be_direct(LLVMStructGetTypeAtIndex(type, 0), calling_convention);
}
} else if (is_basic_register_type(type)) {
return true;
}
} else if (sz <= MAX_DIRECT_STRUCT_SIZE) {
if (kind == LLVMArrayTypeKind) {
if (is_basic_register_type(OdinLLVMGetArrayElementType(type))) {
return true;
@@ -1284,7 +1301,7 @@ namespace lbAbiWasm {
return false;
}
gb_internal lbArgType is_struct(LLVMContextRef c, LLVMTypeRef type) {
gb_internal lbArgType is_struct(LLVMContextRef c, LLVMTypeRef type, ProcCallingConvention calling_convention) {
LLVMTypeKind kind = LLVMGetTypeKind(type);
GB_ASSERT(kind == LLVMArrayTypeKind || kind == LLVMStructTypeKind);
@@ -1292,21 +1309,21 @@ namespace lbAbiWasm {
if (sz == 0) {
return lb_arg_type_ignore(type);
}
if (type_can_be_direct(type)) {
if (type_can_be_direct(type, calling_convention)) {
return lb_arg_type_direct(type);
}
return lb_arg_type_indirect(type, nullptr);
}
gb_internal Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count) {
gb_internal Array<lbArgType> compute_arg_types(LLVMContextRef c, LLVMTypeRef *arg_types, unsigned arg_count, ProcCallingConvention calling_convention) {
auto args = array_make<lbArgType>(lb_function_type_args_allocator(), arg_count);
for (unsigned i = 0; i < arg_count; i++) {
LLVMTypeRef t = arg_types[i];
LLVMTypeKind kind = LLVMGetTypeKind(t);
if (kind == LLVMStructTypeKind || kind == LLVMArrayTypeKind) {
args[i] = is_struct(c, t);
args[i] = is_struct(c, t, calling_convention);
} else {
args[i] = non_struct(c, t, false);
}
@@ -1318,7 +1335,7 @@ namespace lbAbiWasm {
if (!return_is_defined) {
return lb_arg_type_direct(LLVMVoidTypeInContext(c));
} else if (lb_is_type_kind(return_type, LLVMStructTypeKind) || lb_is_type_kind(return_type, LLVMArrayTypeKind)) {
if (type_can_be_direct(return_type)) {
if (type_can_be_direct(return_type, ft->calling_convention)) {
return lb_arg_type_direct(return_type);
}
+26 -15
View File
@@ -720,6 +720,7 @@ gb_internal lbValue lb_map_set_proc_for_type(lbModule *m, Type *type) {
lbBlock *check_grow_block = lb_create_block(p, "check-grow");
lbBlock *grow_fail_block = lb_create_block(p, "grow-fail");
lbBlock *insert_block = lb_create_block(p, "insert");
lbBlock *rehash_block = lb_create_block(p, "rehash");
lb_emit_if(p, lb_emit_comp_against_nil(p, Token_NotEq, found_ptr), found_block, check_grow_block);
lb_start_block(p, found_block);
@@ -737,12 +738,19 @@ gb_internal lbValue lb_map_set_proc_for_type(lbModule *m, Type *type) {
args[0] = lb_emit_conv(p, map_ptr, t_rawptr);
args[1] = map_info;
args[2] = lb_emit_load(p, location_ptr);
lbValue grow_err = lb_emit_runtime_call(p, "__dynamic_map_check_grow", args);
lbValue grow_err_and_has_grown = lb_emit_runtime_call(p, "__dynamic_map_check_grow", args);
lbValue grow_err = lb_emit_struct_ev(p, grow_err_and_has_grown, 0);
lbValue has_grown = lb_emit_struct_ev(p, grow_err_and_has_grown, 1);
lb_emit_if(p, lb_emit_comp_against_nil(p, Token_NotEq, grow_err), grow_fail_block, insert_block);
lb_start_block(p, grow_fail_block);
LLVMBuildRet(p->builder, LLVMConstNull(lb_type(m, t_rawptr)));
lb_emit_if(p, has_grown, grow_fail_block, rehash_block);
lb_start_block(p, rehash_block);
lbValue key = lb_emit_load(p, key_ptr);
hash = lb_gen_map_key_hash(p, map_ptr, key, nullptr);
}
lb_start_block(p, insert_block);
@@ -916,7 +924,7 @@ gb_internal lbValue lb_const_hash(lbModule *m, lbValue key, Type *key_type) {
return hashed_key;
}
gb_internal lbValue lb_gen_map_key_hash(lbProcedure *p, lbValue key, Type *key_type, lbValue *key_ptr_) {
gb_internal lbValue lb_gen_map_key_hash(lbProcedure *p, lbValue const &map_ptr, lbValue key, lbValue *key_ptr_) {
TEMPORARY_ALLOCATOR_GUARD();
lbValue key_ptr = lb_address_from_load_or_generate_local(p, key);
@@ -924,13 +932,22 @@ gb_internal lbValue lb_gen_map_key_hash(lbProcedure *p, lbValue key, Type *key_t
if (key_ptr_) *key_ptr_ = key_ptr;
Type* key_type = base_type(type_deref(map_ptr.type))->Map.key;
lbValue hashed_key = lb_const_hash(p->module, key, key_type);
if (hashed_key.value == nullptr) {
lbValue hasher = lb_hasher_proc_for_type(p->module, key_type);
lbValue seed = {};
{
auto args = array_make<lbValue>(temporary_allocator(), 1);
args[0] = lb_map_data_uintptr(p, lb_emit_load(p, map_ptr));
seed = lb_emit_runtime_call(p, "map_seed_from_map_data", args);
}
auto args = array_make<lbValue>(temporary_allocator(), 2);
args[0] = key_ptr;
args[1] = lb_const_int(p->module, t_uintptr, 0);
args[1] = seed;
hashed_key = lb_emit_call(p, hasher, args);
}
@@ -945,7 +962,7 @@ gb_internal lbValue lb_internal_dynamic_map_get_ptr(lbProcedure *p, lbValue cons
lbValue ptr = {};
lbValue key_ptr = {};
lbValue hash = lb_gen_map_key_hash(p, key, map_type->Map.key, &key_ptr);
lbValue hash = lb_gen_map_key_hash(p, map_ptr, key, &key_ptr);
if (build_context.dynamic_map_calls) {
auto args = array_make<lbValue>(temporary_allocator(), 4);
@@ -976,7 +993,7 @@ gb_internal void lb_internal_dynamic_map_set(lbProcedure *p, lbValue const &map_
GB_ASSERT(map_type->kind == Type_Map);
lbValue key_ptr = {};
lbValue hash = lb_gen_map_key_hash(p, map_key, map_type->Map.key, &key_ptr);
lbValue hash = lb_gen_map_key_hash(p, map_ptr, map_key, &key_ptr);
lbValue v = lb_emit_conv(p, map_value, map_type->Map.value);
lbValue value_ptr = lb_address_from_load_or_generate_local(p, v);
@@ -1129,12 +1146,7 @@ gb_internal lbProcedure *lb_create_startup_runtime(lbModule *main_module, lbProc
lbValue init = lb_build_expr(p, init_expr);
if (init.value == nullptr) {
LLVMTypeRef global_type = llvm_addr_type(p->module, var.var);
if (is_type_untyped_undef(init.type)) {
// LLVMSetInitializer(var.var.value, LLVMGetUndef(global_type));
LLVMSetInitializer(var.var.value, LLVMConstNull(global_type));
var.is_initialized = true;
continue;
} else if (is_type_untyped_nil(init.type)) {
if (is_type_untyped_nil(init.type)) {
LLVMSetInitializer(var.var.value, LLVMConstNull(global_type));
var.is_initialized = true;
continue;
@@ -1365,7 +1377,7 @@ gb_internal WORKER_TASK_PROC(lb_llvm_emit_worker_proc) {
gb_internal void lb_llvm_function_pass_per_function_internal(lbModule *module, lbProcedure *p, lbFunctionPassManagerKind pass_manager_kind = lbFunctionPassManager_default) {
LLVMPassManagerRef pass_manager = module->function_pass_managers[pass_manager_kind];
lb_run_function_pass_manager(pass_manager, p);
lb_run_function_pass_manager(pass_manager, p, pass_manager_kind);
}
gb_internal WORKER_TASK_PROC(lb_llvm_function_pass_per_module) {
@@ -1899,7 +1911,7 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star
LLVMVerifyFunction(p->value, LLVMAbortProcessAction);
}
lb_run_function_pass_manager(default_function_pass_manager, p);
lb_run_function_pass_manager(default_function_pass_manager, p, lbFunctionPassManager_default);
return p;
}
@@ -2363,8 +2375,7 @@ gb_internal bool lb_generate_code(lbGenerator *gen) {
}
}
}
if (!var.is_initialized &&
(is_type_untyped_nil(tav.type) || is_type_untyped_undef(tav.type))) {
if (!var.is_initialized && is_type_untyped_nil(tav.type)) {
var.is_initialized = true;
}
}
+1 -1
View File
@@ -477,7 +477,7 @@ gb_internal String lb_get_const_string(lbModule *m, lbValue value);
gb_internal lbValue lb_generate_local_array(lbProcedure *p, Type *elem_type, i64 count, bool zero_init=true);
gb_internal lbValue lb_generate_global_array(lbModule *m, Type *elem_type, i64 count, String prefix, i64 id);
gb_internal lbValue lb_gen_map_key_hash(lbProcedure *p, lbValue key, Type *key_type, lbValue *key_ptr_);
gb_internal lbValue lb_gen_map_key_hash(lbProcedure *p, lbValue const &map_ptr, lbValue key, lbValue *key_ptr_);
gb_internal lbValue lb_gen_map_cell_info_ptr(lbModule *m, Type *type);
gb_internal lbValue lb_gen_map_info_ptr(lbModule *m, Type *map_type);
+1 -1
View File
@@ -1,6 +1,6 @@
gb_internal bool lb_is_const(lbValue value) {
LLVMValueRef v = value.value;
if (is_type_untyped_nil(value.type) || is_type_untyped_undef(value.type)) {
if (is_type_untyped_nil(value.type)) {
// TODO(bill): Is this correct behaviour?
return true;
}
+1 -1
View File
@@ -282,7 +282,7 @@ gb_internal LLVMMetadataRef lb_debug_type_internal(lbModule *m, Type *type) {
case Basic_UntypedString: GB_PANIC("Basic_UntypedString"); break;
case Basic_UntypedRune: GB_PANIC("Basic_UntypedRune"); break;
case Basic_UntypedNil: GB_PANIC("Basic_UntypedNil"); break;
case Basic_UntypedUndef: GB_PANIC("Basic_UntypedUndef"); break;
case Basic_UntypedUninit: GB_PANIC("Basic_UntypedUninit"); break;
default: GB_PANIC("Basic Unhandled"); break;
}

Some files were not shown because too many files have changed in this diff Show More