mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-18 11:52:22 -07:00
Merge branch 'odin-lang:master' into attr_error
This commit is contained in:
+12
-12
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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}
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
+370
-185
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+27
-23
@@ -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,
|
||||
|
||||
@@ -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
@@ -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]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -2,6 +2,7 @@ package rand
|
||||
|
||||
import "core:sys/darwin"
|
||||
|
||||
@(require_results)
|
||||
_system_random :: proc() -> u32 {
|
||||
for {
|
||||
value: u32
|
||||
|
||||
@@ -2,6 +2,7 @@ package rand
|
||||
|
||||
import "core:sys/unix"
|
||||
|
||||
@(require_results)
|
||||
_system_random :: proc() -> u32 {
|
||||
for {
|
||||
value: u32
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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:]
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,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,
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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()
|
||||
|
||||
@@ -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
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,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;
|
||||
}
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user