aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--base/intrinsics/intrinsics.odin5
-rw-r--r--base/runtime/core_builtin_soa.odin115
-rw-r--r--base/runtime/os_specific.odin4
-rw-r--r--base/runtime/os_specific_bsd.odin8
-rw-r--r--base/runtime/os_specific_darwin.odin10
-rw-r--r--base/runtime/os_specific_freestanding.odin4
-rw-r--r--base/runtime/os_specific_haiku.odin6
-rw-r--r--base/runtime/os_specific_js.odin5
-rw-r--r--base/runtime/os_specific_linux.odin14
-rw-r--r--base/runtime/os_specific_orca.odin5
-rw-r--r--base/runtime/os_specific_wasi.odin8
-rw-r--r--base/runtime/os_specific_windows.odin6
-rw-r--r--core/container/small_array/small_array.odin2
-rw-r--r--core/encoding/cbor/tags.odin32
-rw-r--r--core/math/ease/ease.odin242
-rw-r--r--core/math/ease/ease_inverse.odin250
-rw-r--r--core/math/ease/flux.odin177
-rw-r--r--core/math/linalg/hlsl/linalg_hlsl.odin750
-rw-r--r--core/math/linalg/hlsl/linalg_hlsl_math.odin36
-rw-r--r--core/math/rand/rand.odin8
-rw-r--r--core/mem/mem.odin4
-rw-r--r--core/odin/parser/parser.odin17
-rw-r--r--core/os/os2/dir.odin14
-rw-r--r--core/os/os2/dir_windows.odin2
-rw-r--r--core/os/os2/errors.odin24
-rw-r--r--core/os/os2/file.odin201
-rw-r--r--core/os/os2/file_linux.odin14
-rw-r--r--core/os/os2/file_posix.odin12
-rw-r--r--core/os/os2/file_posix_other.odin2
-rw-r--r--core/os/os2/file_stream.odin21
-rw-r--r--core/os/os2/file_util.odin96
-rw-r--r--core/os/os2/file_wasi.odin12
-rw-r--r--core/os/os2/file_windows.odin15
-rw-r--r--core/os/os2/heap.odin3
-rw-r--r--core/os/os2/path_wasi.odin6
-rw-r--r--core/os/os2/process.odin2
-rw-r--r--core/os/os2/process_linux.odin5
-rw-r--r--core/os/os2/process_posix.odin4
-rw-r--r--core/os/os2/process_wasi.odin6
-rw-r--r--core/os/os2/process_windows.odin5
-rw-r--r--core/os/os2/stat.odin34
-rw-r--r--core/os/os2/stat_linux.odin2
-rw-r--r--core/os/os2/stat_posix.odin2
-rw-r--r--core/os/os2/stat_windows.odin8
-rw-r--r--core/os/os2/temp_file.odin17
-rw-r--r--core/sys/darwin/Foundation/NSApplication.odin16
-rw-r--r--core/sys/darwin/Foundation/NSEvent.odin29
-rw-r--r--core/sys/darwin/Foundation/NSWindow.odin106
-rw-r--r--core/testing/logging.odin28
-rw-r--r--core/testing/runner.odin5
-rw-r--r--core/text/scanner/scanner.odin4
-rw-r--r--examples/all/all_main.odin1
-rw-r--r--src/check_builtin.cpp54
-rw-r--r--src/check_expr.cpp64
-rw-r--r--src/check_type.cpp2
-rw-r--r--src/checker.cpp16
-rw-r--r--src/checker_builtin_procs.hpp21
-rw-r--r--src/llvm_backend.cpp23
-rw-r--r--src/llvm_backend_const.cpp15
-rw-r--r--src/main.cpp22
-rw-r--r--src/name_canonicalization.cpp10
-rw-r--r--src/parser.cpp14
-rw-r--r--src/types.cpp9
-rw-r--r--tests/core/runtime/test_core_runtime.odin59
-rw-r--r--vendor/raylib/raylib.odin1
65 files changed, 2352 insertions, 362 deletions
diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin
index 952f927bd..d34519f63 100644
--- a/base/intrinsics/intrinsics.odin
+++ b/base/intrinsics/intrinsics.odin
@@ -244,6 +244,11 @@ constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
constant_log2 :: proc($v: $T) -> T where type_is_integer(T) ---
+constant_floor :: proc($v: $T) -> T where type_is_integer(T) || type_is_float(T) ---
+constant_trunc :: proc($v: $T) -> T where type_is_integer(T) || type_is_float(T) ---
+constant_ceil :: proc($v: $T) -> T where type_is_integer(T) || type_is_float(T) ---
+constant_round :: proc($v: $T) -> T where type_is_integer(T) || type_is_float(T) ---
+
// SIMD related
simd_add :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_sub :: proc(a, b: #simd[N]T) -> #simd[N]T ---
diff --git a/base/runtime/core_builtin_soa.odin b/base/runtime/core_builtin_soa.odin
index 331254ac7..0ccc8fd9b 100644
--- a/base/runtime/core_builtin_soa.odin
+++ b/base/runtime/core_builtin_soa.odin
@@ -501,6 +501,121 @@ append_soa :: proc{
}
+// `append_nothing_soa` appends an empty value to a dynamic SOA array. It returns `1, nil` if successful, and `0, err` when it was not possible,
+// whatever `err` happens to be.
+@builtin
+append_nothing_soa :: proc(array: ^$T/#soa[dynamic]$E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
+ if array == nil {
+ return 0, nil
+ }
+ prev_len := len(array)
+ resize_soa(array, len(array)+1, loc) or_return
+ return len(array)-prev_len, nil
+}
+
+
+// `inject_at_elem_soa` injects an element in a dynamic SOA array at a specified index and moves the previous elements after that index "across"
+@builtin
+inject_at_elem_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int index: int, #no_broadcast arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
+ when !ODIN_NO_BOUNDS_CHECK {
+ ensure(index >= 0, "Index must be positive.", loc)
+ }
+ if array == nil {
+ return
+ }
+ n := max(len(array), index)
+ m :: 1
+ new_len := n + m
+
+ resize_soa(array, new_len, loc) or_return
+
+ when size_of(E) != 0 {
+ ti := type_info_base(type_info_of(typeid_of(T)))
+ si := &ti.variant.(Type_Info_Struct)
+
+ field_count := len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)
+
+ item_offset := 0
+
+ arg_copy := arg
+ arg_ptr := &arg_copy
+
+ for i in 0..<field_count {
+ data := (^uintptr)(uintptr(array) + uintptr(si.offsets[i]))^
+ type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
+ item_offset = align_forward_int(item_offset, type.align)
+
+ src := data + uintptr(index * type.size)
+ dst := data + uintptr((index + m) * type.size)
+ mem_copy(rawptr(dst), rawptr(src), (n - index) * type.size)
+
+ mem_copy(rawptr(src), rawptr(uintptr(arg_ptr) + uintptr(item_offset)), type.size)
+
+ item_offset += type.size
+ }
+ }
+
+ ok = true
+ return
+}
+
+// `inject_at_elems_soa` injects multiple elements in a dynamic SOA array at a specified index and moves the previous elements after that index "across"
+@builtin
+inject_at_elems_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
+ when !ODIN_NO_BOUNDS_CHECK {
+ ensure(index >= 0, "Index must be positive.", loc)
+ }
+ if array == nil {
+ return
+ }
+ if len(args) == 0 {
+ ok = true
+ return
+ }
+
+ n := max(len(array), index)
+ m := len(args)
+ new_len := n + m
+
+ resize_soa(array, new_len, loc) or_return
+
+ when size_of(E) != 0 {
+ ti := type_info_base(type_info_of(typeid_of(T)))
+ si := &ti.variant.(Type_Info_Struct)
+
+ field_count := len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)
+
+ item_offset := 0
+
+ args_ptr := &args[0]
+
+ for i in 0..<field_count {
+ data := (^uintptr)(uintptr(array) + uintptr(si.offsets[i]))^
+ type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
+ item_offset = align_forward_int(item_offset, type.align)
+
+ src := data + uintptr(index * type.size)
+ dst := data + uintptr((index + m) * type.size)
+ mem_copy(rawptr(dst), rawptr(src), (n - index) * type.size)
+
+ for j in 0..<len(args) {
+ d := rawptr(src + uintptr(j*type.size))
+ s := rawptr(uintptr(args_ptr) + uintptr(item_offset) + uintptr(j*size_of(E)))
+ mem_copy(d, s, type.size)
+ }
+
+ item_offset += type.size
+ }
+ }
+
+ ok = true
+ return
+}
+
+// `inject_at_soa` injects something into a dynamic SOA array at a specified index and moves the previous elements after that index "across"
+@builtin inject_at_soa :: proc{inject_at_elem_soa, inject_at_elems_soa}
+
+
delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
field_count :: len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)
when field_count != 0 {
diff --git a/base/runtime/os_specific.odin b/base/runtime/os_specific.odin
index 2807eaf90..b6c1288d0 100644
--- a/base/runtime/os_specific.odin
+++ b/base/runtime/os_specific.odin
@@ -5,3 +5,7 @@ _OS_Errno :: distinct int
stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
return _stderr_write(data)
}
+
+exit :: proc "contextless" (code: int) -> ! {
+ _exit(code)
+} \ No newline at end of file
diff --git a/base/runtime/os_specific_bsd.odin b/base/runtime/os_specific_bsd.odin
index 466001ada..de300f1e0 100644
--- a/base/runtime/os_specific_bsd.odin
+++ b/base/runtime/os_specific_bsd.odin
@@ -24,3 +24,11 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
}
return int(ret), 0
}
+
+_exit :: proc "contextless" (code: int) -> ! {
+ @(default_calling_convention="c")
+ foreign libc {
+ exit :: proc(status: i32) -> ! ---
+ }
+ exit(i32(code))
+} \ No newline at end of file
diff --git a/base/runtime/os_specific_darwin.odin b/base/runtime/os_specific_darwin.odin
index 907899d7c..37315240f 100644
--- a/base/runtime/os_specific_darwin.odin
+++ b/base/runtime/os_specific_darwin.odin
@@ -26,3 +26,13 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
return 0, _OS_Errno(__error()^)
}
}
+
+foreign import libc "system:System"
+
+_exit :: proc "contextless" (code: int) -> ! {
+ @(default_calling_convention="c")
+ foreign libc {
+ exit :: proc(status: i32) -> ! ---
+ }
+ exit(i32(code))
+} \ No newline at end of file
diff --git a/base/runtime/os_specific_freestanding.odin b/base/runtime/os_specific_freestanding.odin
index f975f61b8..b5a5fb146 100644
--- a/base/runtime/os_specific_freestanding.odin
+++ b/base/runtime/os_specific_freestanding.odin
@@ -6,3 +6,7 @@ package runtime
_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
return 0, -1
}
+
+_exit :: proc "contextless" (code: int) -> ! {
+ trap()
+} \ No newline at end of file
diff --git a/base/runtime/os_specific_haiku.odin b/base/runtime/os_specific_haiku.odin
index 0d1ec7a03..74ff58cde 100644
--- a/base/runtime/os_specific_haiku.odin
+++ b/base/runtime/os_specific_haiku.odin
@@ -19,3 +19,9 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
}
return int(ret), 0
}
+
+
+
+_exit :: proc "contextless" (code: int) -> ! {
+ trap()
+} \ No newline at end of file
diff --git a/base/runtime/os_specific_js.odin b/base/runtime/os_specific_js.odin
index f1d12c808..bd88b1871 100644
--- a/base/runtime/os_specific_js.odin
+++ b/base/runtime/os_specific_js.odin
@@ -11,3 +11,8 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
write(1, data)
return len(data), 0
}
+
+
+_exit :: proc "contextless" (code: int) -> ! {
+ trap()
+} \ No newline at end of file
diff --git a/base/runtime/os_specific_linux.odin b/base/runtime/os_specific_linux.odin
index d7b7371a7..dfe3c8841 100644
--- a/base/runtime/os_specific_linux.odin
+++ b/base/runtime/os_specific_linux.odin
@@ -24,3 +24,17 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
}
return ret, 0
}
+
+
+_exit :: proc "contextless" (code: int) -> ! {
+ SYS_exit_group ::
+ 231 when ODIN_ARCH == .amd64 else
+ 248 when ODIN_ARCH == .arm32 else
+ 94 when ODIN_ARCH == .arm64 else
+ 252 when ODIN_ARCH == .i386 else
+ 94 when ODIN_ARCH == .riscv64 else
+ 0
+
+ intrinsics.syscall(uintptr(SYS_exit_group), uintptr(i32(code)))
+ unreachable()
+}
diff --git a/base/runtime/os_specific_orca.odin b/base/runtime/os_specific_orca.odin
index 876d7d44b..491edcfa4 100644
--- a/base/runtime/os_specific_orca.odin
+++ b/base/runtime/os_specific_orca.odin
@@ -41,3 +41,8 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
return len(data), 0
}
+
+
+_exit :: proc "contextless" (code: int) -> ! {
+ trap()
+} \ No newline at end of file
diff --git a/base/runtime/os_specific_wasi.odin b/base/runtime/os_specific_wasi.odin
index aa562050c..194034865 100644
--- a/base/runtime/os_specific_wasi.odin
+++ b/base/runtime/os_specific_wasi.odin
@@ -23,6 +23,9 @@ foreign wasi {
argv: [^]cstring,
argv_buf: [^]byte,
) -> u16 ---
+
+ @(private="file")
+ proc_exit :: proc(rval: u32) -> ! ---
}
_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
@@ -53,3 +56,8 @@ _wasi_setup_args :: proc() {
delete(args_buf)
}
}
+
+
+_exit :: proc "contextless" (code: int) -> ! {
+ proc_exit(u32(code))
+} \ No newline at end of file
diff --git a/base/runtime/os_specific_windows.odin b/base/runtime/os_specific_windows.odin
index b966193ca..c5ca1e4c5 100644
--- a/base/runtime/os_specific_windows.odin
+++ b/base/runtime/os_specific_windows.odin
@@ -14,6 +14,8 @@ foreign kernel32 {
SetHandleInformation :: proc(hObject: rawptr, dwMask: u32, dwFlags: u32) -> b32 ---
WriteFile :: proc(hFile: rawptr, lpBuffer: rawptr, nNumberOfBytesToWrite: u32, lpNumberOfBytesWritten: ^u32, lpOverlapped: rawptr) -> b32 ---
GetLastError :: proc() -> u32 ---
+
+ ExitProcess :: proc(code: u32) -> ! ---
}
_stderr_write :: proc "contextless" (data: []byte) -> (n: int, err: _OS_Errno) #no_bounds_check {
@@ -49,3 +51,7 @@ _stderr_write :: proc "contextless" (data: []byte) -> (n: int, err: _OS_Errno) #
n = int(total_write)
return
}
+
+_exit :: proc "contextless" (code: int) -> ! {
+ ExitProcess(u32(code))
+} \ No newline at end of file
diff --git a/core/container/small_array/small_array.odin b/core/container/small_array/small_array.odin
index 1d9795db8..a7e046fcf 100644
--- a/core/container/small_array/small_array.odin
+++ b/core/container/small_array/small_array.odin
@@ -309,7 +309,7 @@ Example:
import "core:container/small_array"
import "core:fmt"
- non_zero_resize :: proc() {
+ non_zero_resize_example :: proc() {
a: small_array.Small_Array(5, int)
small_array.push_back(&a, 1)
diff --git a/core/encoding/cbor/tags.odin b/core/encoding/cbor/tags.odin
index be07b926a..fa456673d 100644
--- a/core/encoding/cbor/tags.odin
+++ b/core/encoding/cbor/tags.odin
@@ -130,9 +130,9 @@ tag_time_unmarshal :: proc(_: ^Tag_Implementation, d: Decoder, _: Tag_Number, v:
case .U8, .U16, .U32, .U64, .Neg_U8, .Neg_U16, .Neg_U32, .Neg_U64:
switch &dst in v {
case time.Time:
- i: i64
- _unmarshal_any_ptr(d, &i, hdr) or_return
- dst = time.unix(i64(i), 0)
+ secs: i64
+ _unmarshal_any_ptr(d, &secs, hdr) or_return
+ dst = time.unix(i64(secs), 0)
return
case:
return _unmarshal_value(d, v, hdr)
@@ -152,19 +152,23 @@ tag_time_unmarshal :: proc(_: ^Tag_Implementation, d: Decoder, _: Tag_Number, v:
case:
maj, add := _header_split(hdr)
- if maj == .Other {
- i := _decode_tiny_u8(add) or_return
-
- switch &dst in v {
- case time.Time:
- dst = time.unix(i64(i), 0)
- case:
- if _assign_int(v, i) { return }
- }
+ secs: u8
+ #partial switch maj {
+ case .Unsigned:
+ secs = _decode_tiny_u8(add) or_return
+ case .Other:
+ secs = u8(_decode_tiny_simple(add) or_return)
+ case:
+ return .Bad_Tag_Value
}
- // Only numbers and floats are allowed in this tag.
- return .Bad_Tag_Value
+ switch &dst in v {
+ case time.Time:
+ dst = time.unix(i64(secs), 0)
+ return
+ case:
+ if _assign_int(v, secs) { return }
+ }
}
return _unsupported(v, hdr)
diff --git a/core/math/ease/ease.odin b/core/math/ease/ease.odin
index c6dd56dbc..98d549c7a 100644
--- a/core/math/ease/ease.odin
+++ b/core/math/ease/ease.odin
@@ -1,9 +1,8 @@
-// Easing procedures and flux easing used for animations.
+// Easing procedures used for animations.
package ease
-import "core:math"
+@require import "core:math"
import "base:intrinsics"
-import "core:time"
@(private) PI_2 :: math.PI / 2
@@ -174,7 +173,7 @@ exponential_in_out :: proc "contextless" (p: $T) -> T where intrinsics.type_is_f
if p == 0.0 || p == 1.0 {
return p
}
-
+
if p < 0.5 {
return 0.5 * math.pow(2, (20 * p) - 10)
} else {
@@ -307,224 +306,51 @@ Ease :: enum {
}
@(require_results)
-ease :: proc "contextless" (type: Ease, p: $T) -> T
- where intrinsics.type_is_float(T) {
+ease :: proc "contextless" (type: Ease, p: $T) -> T where intrinsics.type_is_float(T) {
switch type {
- case .Linear: return p
+ 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 .Quadratic_In: return quadratic_in(p)
+ case .Quadratic_Out: return quadratic_out(p)
+ case .Quadratic_In_Out: return quadratic_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 .Cubic_In: return cubic_in(p)
+ case .Cubic_Out: return cubic_out(p)
+ case .Cubic_In_Out: return cubic_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 .Quartic_In: return quartic_in(p)
+ case .Quartic_Out: return quartic_out(p)
+ case .Quartic_In_Out: return quartic_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 .Quintic_In: return quintic_in(p)
+ case .Quintic_Out: return quintic_out(p)
+ case .Quintic_In_Out: return quintic_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 .Sine_In: return sine_in(p)
+ case .Sine_Out: return sine_out(p)
+ case .Sine_In_Out: return sine_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 .Circular_In: return circular_in(p)
+ case .Circular_Out: return circular_out(p)
+ case .Circular_In_Out: return circular_in_out(p)
- case .Exponential_In: return exponential_in(p)
- case .Exponential_Out: return exponential_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 .Elastic_In: return elastic_in(p)
- case .Elastic_Out: return elastic_out(p)
- case .Elastic_In_Out: return elastic_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 .Back_In: return back_in(p)
- case .Back_Out: return back_out(p)
- case .Back_In_Out: return back_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)
+ 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
return 0
}
-Flux_Map :: struct($T: typeid) {
- values: map[^T]Flux_Tween(T),
- keys_to_be_deleted: [dynamic]^T,
-}
-
-Flux_Tween :: struct($T: typeid) {
- value: ^T,
- start: T,
- diff: T,
- goal: T,
-
- delay: f64, // in seconds
- duration: time.Duration,
-
- progress: f64,
- rate: f64,
- type: Ease,
-
- inited: bool,
-
- // callbacks, data can be set, will be pushed to callback
- data: rawptr, // by default gets set to value input
- on_start: proc(flux: ^Flux_Map(T), data: rawptr),
- on_update: proc(flux: ^Flux_Map(T), data: rawptr),
- on_complete: proc(flux: ^Flux_Map(T), data: rawptr),
-}
-
-// 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),
- keys_to_be_deleted = make([dynamic]^T, 0, value_capacity),
- }
-}
-
-// delete map content
-flux_destroy :: proc(flux: Flux_Map($T)) where intrinsics.type_is_float(T) {
- delete(flux.values)
- delete(flux.keys_to_be_deleted)
-}
-
-// clear map content, stops all animations
-flux_clear :: proc(flux: ^Flux_Map($T)) where intrinsics.type_is_float(T) {
- clear(&flux.values)
-}
-
-// 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,
- goal: T,
- type: Ease = .Quadratic_Out,
- duration: time.Duration = time.Second,
- delay: f64 = 0,
-) -> (tween: ^Flux_Tween(T)) where intrinsics.type_is_float(T) {
- if res, ok := &flux.values[value]; ok {
- tween = res
- } else {
- flux.values[value] = {}
- tween = &flux.values[value]
- }
-
- tween^ = {
- value = value,
- goal = goal,
- duration = duration,
- delay = delay,
- type = type,
- data = value,
- }
-
- return
-}
-
-// init internal properties
-flux_tween_init :: proc(tween: ^Flux_Tween($T), duration: time.Duration) where intrinsics.type_is_float(T) {
- tween.inited = true
- tween.start = tween.value^
- tween.diff = tween.goal - tween.value^
- s := time.duration_seconds(duration)
- tween.rate = duration > 0 ? 1.0 / s : 0
- tween.progress = duration > 0 ? 0 : 1
-}
-
-// update all tweens, wait for their delay if one exists
-// calls callbacks in all stages, when they're filled
-// deletes tween from the map after completion
-flux_update :: proc(flux: ^Flux_Map($T), dt: f64) where intrinsics.type_is_float(T) {
- clear(&flux.keys_to_be_deleted)
-
- for key, &tween in flux.values {
- delay_remainder := f64(0)
-
- // Update delay if necessary.
- if tween.delay > 0 {
- tween.delay -= dt
-
- if tween.delay < 0 {
- // We finished the delay, but in doing so consumed part of this frame's `dt` budget.
- // Keep track of it so we can apply it to this tween without affecting others.
- delay_remainder = tween.delay
- // We're done with this delay.
- tween.delay = 0
- }
- }
-
- // We either had no delay, or the delay has been consumed.
- if tween.delay <= 0 {
- if !tween.inited {
- flux_tween_init(&tween, tween.duration)
-
- if tween.on_start != nil {
- tween.on_start(flux, tween.data)
- }
- }
-
- // If part of the `dt` budget was consumed this frame, then `delay_remainder` will be
- // that remainder, a negative value. Adding it to `dt` applies what's left of the `dt`
- // to the tween so it advances properly, instead of too much or little.
- tween.progress += tween.rate * (dt + delay_remainder)
- x := tween.progress >= 1 ? 1 : ease(tween.type, tween.progress)
- tween.value^ = tween.start + tween.diff * T(x)
-
- if tween.on_update != nil {
- tween.on_update(flux, tween.data)
- }
-
- if tween.progress >= 1 {
- // append keys to array that will be deleted after the loop
- append(&flux.keys_to_be_deleted, key)
-
- if tween.on_complete != nil {
- tween.on_complete(flux, tween.data)
- }
- }
- }
- }
-
- // loop through keys that should be deleted from the map
- if len(flux.keys_to_be_deleted) != 0 {
- for key in flux.keys_to_be_deleted {
- delete_key(&flux.values, key)
- }
- }
-}
-
-// 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)
- return true
- }
-
- return false
-}
-
-// 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
- } else {
- return 0
- }
-}
diff --git a/core/math/ease/ease_inverse.odin b/core/math/ease/ease_inverse.odin
new file mode 100644
index 000000000..12d6394eb
--- /dev/null
+++ b/core/math/ease/ease_inverse.odin
@@ -0,0 +1,250 @@
+// Inverse easing procedures
+// These are the mathematical inverses of the corresponding easing functions,
+// allowing you to reverse the transformation:
+// if y = ease_fn(x), then x = ease_fn_inverse(y) + some_imprecision
+package ease
+
+@require import "core:math"
+import "base:intrinsics"
+
+// Helper for handling negative bases with fractional exponents
+// since math.pow(negative, fraction) returns NaN
+@(private)
+_signed_pow :: proc "contextless" (x, exp: $T) -> T where intrinsics.type_is_float(T) {
+ if x >= 0 {
+ return math.pow(x, exp)
+ } else {
+ return -math.pow(-x, exp)
+ }
+}
+
+@(private) PI_2_INV :: 2 / math.PI
+
+// Inverse of quadratic_in
+// x = sqrt(y)
+@(require_results)
+quadratic_in_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ return math.sqrt(p)
+}
+
+// Inverse of quadratic_out
+// x = 1 - sqrt(1 - y)
+@(require_results)
+quadratic_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ return 1 - math.sqrt(1 - p)
+}
+
+// Inverse of quadratic_in_out
+// x = sqrt(y/2) ; [0, 0.5)
+// x = 1 - sqrt((1-y)/2) ; [0.5, 1]
+@(require_results)
+quadratic_in_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ if p < 0.5 {
+ return math.sqrt(p * 0.5)
+ } else {
+ return 1 - math.sqrt((1 - p) * 0.5)
+ }
+}
+
+// Inverse of cubic_in
+// x = y^(1/3)
+@(require_results)
+cubic_in_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ return math.pow(p, 1.0/3.0)
+}
+
+// Inverse of cubic_out
+// x = (y - 1)^(1/3) + 1
+@(require_results)
+cubic_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ return _signed_pow(p - 1, 1.0/3.0) + 1
+}
+
+// Inverse of cubic_in_out
+// x = (y/4)^(1/3) ; [0, 0.5)
+// x = ((y-1)*2)^(1/3)/2 + 1 ; [0.5, 1]
+@(require_results)
+cubic_in_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ if p < 0.5 {
+ return math.pow(p * 0.25, 1.0/3.0)
+ } else {
+ return _signed_pow((p - 1) * 2, 1.0/3.0) * 0.5 + 1
+ }
+}
+
+// Inverse of quartic_in
+// x = y^(1/4)
+@(require_results)
+quartic_in_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ return math.pow(p, 0.25)
+}
+
+// Inverse of quartic_out
+// x = 1 - (1 - y)^(1/4)
+@(require_results)
+quartic_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ return 1 - math.pow(1 - p, 0.25)
+}
+
+// Inverse of quartic_in_out
+// x = (y/8)^(1/4) ; [0, 0.5)
+// x = 1 - ((1-y)/8)^(1/4) ; [0.5, 1]
+@(require_results)
+quartic_in_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ if p < 0.5 {
+ return math.pow(p * 0.125, 0.25)
+ } else {
+ return 1 - math.pow((1 - p) * 0.125, 0.25)
+ }
+}
+
+// Inverse of quintic_in
+// x = y^(1/5)
+@(require_results)
+quintic_in_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ return math.pow(p, 0.2)
+}
+
+// Inverse of quintic_out
+// x = (y - 1)^(1/5) + 1
+@(require_results)
+quintic_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ return _signed_pow(p - 1, 0.2) + 1
+}
+
+// Inverse of quintic_in_out
+// x = (y/16)^(1/5) ; [0, 0.5)
+// x = ((y-1)*2)^(1/5)/2 + 1 ; [0.5, 1]
+@(require_results)
+quintic_in_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ if p < 0.5 {
+ return math.pow(0.0625 * p, 0.2)
+ } else {
+ return _signed_pow((p - 1) * 2, 0.2) * 0.5 + 1
+ }
+}
+
+// Inverse of sine_in
+// x = asin(y - 1) * 2/Ï€ + 1
+@(require_results)
+sine_in_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ return math.asin(p - 1) * PI_2_INV + 1
+}
+
+// Inverse of sine_out
+// x = asin(y) * 2/Ï€
+@(require_results)
+sine_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ return math.asin(p) * PI_2_INV
+}
+
+// Inverse of sine_in_out
+// x = acos(1 - 2y) / π
+@(require_results)
+sine_in_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ return math.acos(1 - 2*p) / math.PI
+}
+
+// Inverse of circular_in
+// x = sqrt(2y - y²)
+@(require_results)
+circular_in_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ return math.sqrt(2*p - p*p)
+}
+
+// Inverse of circular_out
+// x = 1 - sqrt(1 - y²)
+@(require_results)
+circular_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ return 1 - math.sqrt(1 - p*p)
+}
+
+// Inverse of circular_in_out
+// x = sqrt(1 - (1-2y)²) / 2 ; [0, 0.5)
+// x = 1 - sqrt(1 - (2y-1)²) / 2 ; [0.5, 1]
+@(require_results)
+circular_in_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ if p < 0.5 {
+ q := 1 - 2*p
+ return 0.5 * math.sqrt(1 - q*q)
+ } else {
+ q := 2*p - 1
+ return 1 - 0.5 * math.sqrt(1 - q*q)
+ }
+}
+
+// Inverse of exponential_in
+// x = logâ‚‚(y) / 10 + 1
+@(require_results)
+exponential_in_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ return p == 0.0 ? 0.0 : 0.1 * math.log2(p) + 1
+}
+
+// Inverse of exponential_out
+// x = -logâ‚‚(1 - y) / 10
+@(require_results)
+exponential_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ return p == 1.0 ? 1.0 : 0.1 * -math.log2(1 - p)
+}
+
+// Inverse of exponential_in_out
+// x = (logâ‚‚(2y) + 10) / 20 ; [0, 0.5)
+// x = (10 - logâ‚‚(2(1-y))) / 20 ; [0.5, 1]
+@(require_results)
+exponential_in_out_inverse :: proc "contextless" (p: $T) -> T where intrinsics.type_is_float(T) {
+ if p == 0.0 || p == 1.0 {
+ return p
+ }
+
+ if p < 0.5 {
+ return 0.05 * (math.log2(2*p) + 10)
+ } else {
+ return 0.05 * (10 - math.log2(2*(1-p)))
+ }
+}
+
+// Additional enum variant
+
+@(require_results)
+ease_inverse :: 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_inverse(p)
+ case .Quadratic_Out: return quadratic_out_inverse(p)
+ case .Quadratic_In_Out: return quadratic_in_out_inverse(p)
+
+ case .Cubic_In: return cubic_in_inverse(p)
+ case .Cubic_Out: return cubic_out_inverse(p)
+ case .Cubic_In_Out: return cubic_in_out_inverse(p)
+
+ case .Quartic_In: return quartic_in_inverse(p)
+ case .Quartic_Out: return quartic_out_inverse(p)
+ case .Quartic_In_Out: return quartic_in_out_inverse(p)
+
+ case .Quintic_In: return quintic_in_inverse(p)
+ case .Quintic_Out: return quintic_out_inverse(p)
+ case .Quintic_In_Out: return quintic_in_out_inverse(p)
+
+ case .Sine_In: return sine_in_inverse(p)
+ case .Sine_Out: return sine_out_inverse(p)
+ case .Sine_In_Out: return sine_in_out_inverse(p)
+
+ case .Circular_In: return circular_in_inverse(p)
+ case .Circular_Out: return circular_out_inverse(p)
+ case .Circular_In_Out: return circular_in_out_inverse(p)
+
+ case .Exponential_In: return exponential_in_inverse(p)
+ case .Exponential_Out: return exponential_out_inverse(p)
+ case .Exponential_In_Out: return exponential_in_out_inverse(p)
+
+ case .Elastic_In, .Elastic_Out, .Elastic_In_Out,
+ .Back_In, .Back_Out, .Back_In_Out,
+ .Bounce_In, .Bounce_Out, .Bounce_In_Out:
+ // These do not have simple closed-form inverses
+ return 0
+ }
+
+ // In case type was invalid
+ return 0
+}
diff --git a/core/math/ease/flux.odin b/core/math/ease/flux.odin
new file mode 100644
index 000000000..137f3dff6
--- /dev/null
+++ b/core/math/ease/flux.odin
@@ -0,0 +1,177 @@
+// Flux easing used for animations
+package ease
+
+import "core:time"
+
+Flux_Map :: struct($T: typeid) {
+ values: map[^T]Flux_Tween(T),
+ keys_to_be_deleted: [dynamic]^T,
+}
+
+Flux_Tween :: struct($T: typeid) {
+ value: ^T,
+ start: T,
+ diff: T,
+ goal: T,
+
+ delay: f64, // in seconds
+ duration: time.Duration,
+
+ progress: f64,
+ rate: f64,
+ type: Ease,
+
+ inited: bool,
+
+ // callbacks, data can be set, will be pushed to callback
+ data: rawptr, // by default gets set to value input
+ on_start: proc(flux: ^Flux_Map(T), data: rawptr),
+ on_update: proc(flux: ^Flux_Map(T), data: rawptr),
+ on_complete: proc(flux: ^Flux_Map(T), data: rawptr),
+}
+
+// init flux map to a float type and a wanted cap
+@(require_results)
+flux_init :: proc($T: typeid, value_capacity := 8, allocator := context.allocator, loc := #caller_location) -> Flux_Map(T) where intrinsics.type_is_float(T) {
+ return {
+ values = make(map[^T]Flux_Tween(T), value_capacity, allocator, loc),
+ keys_to_be_deleted = make([dynamic]^T, 0, value_capacity, allocator, loc),
+ }
+}
+
+// delete map content
+flux_destroy :: proc(flux: Flux_Map($T), allocator := context.allocator, loc := #caller_location) where intrinsics.type_is_float(T) {
+ delete(flux.values, allocator, loc)
+ delete(flux.keys_to_be_deleted, allocator, loc)
+}
+
+// clear map content, stops all animations
+flux_clear :: proc(flux: ^Flux_Map($T)) where intrinsics.type_is_float(T) {
+ clear(&flux.values)
+}
+
+// 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,
+ goal: T,
+ type: Ease = .Quadratic_Out,
+ duration: time.Duration = time.Second,
+ delay: f64 = 0,
+) -> (tween: ^Flux_Tween(T)) where intrinsics.type_is_float(T) {
+ if res, ok := &flux.values[value]; ok {
+ tween = res
+ } else {
+ flux.values[value] = {}
+ tween = &flux.values[value]
+ }
+
+ tween^ = {
+ value = value,
+ goal = goal,
+ duration = duration,
+ delay = delay,
+ type = type,
+ data = value,
+ }
+
+ return
+}
+
+// init internal properties
+flux_tween_init :: proc(tween: ^Flux_Tween($T), duration: time.Duration) where intrinsics.type_is_float(T) {
+ tween.inited = true
+ tween.start = tween.value^
+ tween.diff = tween.goal - tween.value^
+ s := time.duration_seconds(duration)
+ tween.rate = duration > 0 ? 1.0 / s : 0
+ tween.progress = duration > 0 ? 0 : 1
+}
+
+// update all tweens, wait for their delay if one exists
+// calls callbacks in all stages, when they're filled
+// deletes tween from the map after completion
+flux_update :: proc(flux: ^Flux_Map($T), dt: f64) where intrinsics.type_is_float(T) {
+ clear(&flux.keys_to_be_deleted)
+
+ for key, &tween in flux.values {
+ delay_remainder := f64(0)
+
+ // Update delay if necessary.
+ if tween.delay > 0 {
+ tween.delay -= dt
+
+ if tween.delay < 0 {
+ // We finished the delay, but in doing so consumed part of this frame's `dt` budget.
+ // Keep track of it so we can apply it to this tween without affecting others.
+ delay_remainder = tween.delay
+ // We're done with this delay.
+ tween.delay = 0
+ }
+ }
+
+ // We either had no delay, or the delay has been consumed.
+ if tween.delay <= 0 {
+ if !tween.inited {
+ flux_tween_init(&tween, tween.duration)
+
+ if tween.on_start != nil {
+ tween.on_start(flux, tween.data)
+ }
+ }
+
+ // If part of the `dt` budget was consumed this frame, then `delay_remainder` will be
+ // that remainder, a negative value. Adding it to `dt` applies what's left of the `dt`
+ // to the tween so it advances properly, instead of too much or little.
+ tween.progress += tween.rate * (dt + delay_remainder)
+ x := tween.progress >= 1 ? 1 : ease(tween.type, tween.progress)
+ tween.value^ = tween.start + tween.diff * T(x)
+
+ if tween.on_update != nil {
+ tween.on_update(flux, tween.data)
+ }
+
+ if tween.progress >= 1 {
+ // append keys to array that will be deleted after the loop
+ append(&flux.keys_to_be_deleted, key)
+
+ if tween.on_complete != nil {
+ tween.on_complete(flux, tween.data)
+ }
+ }
+ }
+ }
+
+ // loop through keys that should be deleted from the map
+ if len(flux.keys_to_be_deleted) != 0 {
+ for key in flux.keys_to_be_deleted {
+ delete_key(&flux.values, key)
+ }
+ }
+}
+
+// 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)
+ return true
+ }
+
+ return false
+}
+
+// returns the amount of time left for the tween animation, if the key exists in the map
+// returns 0 if the tween doesn't 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
+ } else {
+ return 0
+ }
+}
diff --git a/core/math/linalg/hlsl/linalg_hlsl.odin b/core/math/linalg/hlsl/linalg_hlsl.odin
index 5c78bd8b1..8666f6f60 100644
--- a/core/math/linalg/hlsl/linalg_hlsl.odin
+++ b/core/math/linalg/hlsl/linalg_hlsl.odin
@@ -22,6 +22,7 @@ FLOAT_EPSILON :: 1e-7
DOUBLE_EPSILON :: 1e-15
// Aliases (not distict) of types
+half :: f16
float :: f32
double :: f64
int :: builtin.i32
@@ -46,6 +47,30 @@ float4x1 :: matrix[4, 1]float
float4x2 :: matrix[4, 2]float
float4x3 :: matrix[4, 3]float
+// Half Precision (half) Floating Point Types
+
+half2 :: [2]half
+half3 :: [3]half
+half4 :: [4]half
+
+half1x1 :: matrix[1, 1]half
+half2x2 :: matrix[2, 2]half
+half3x3 :: matrix[3, 3]half
+half4x4 :: matrix[4, 4]half
+
+half1x2 :: matrix[1, 2]half
+half1x3 :: matrix[1, 3]half
+half1x4 :: matrix[1, 4]half
+half2x1 :: matrix[2, 1]half
+half2x3 :: matrix[2, 3]half
+half2x4 :: matrix[2, 4]half
+half3x1 :: matrix[3, 1]half
+half3x2 :: matrix[3, 2]half
+half3x4 :: matrix[3, 4]half
+half4x1 :: matrix[4, 1]half
+half4x2 :: matrix[4, 2]half
+half4x3 :: matrix[4, 3]half
+
float2 :: [2]float
float3 :: [3]float
float4 :: [4]float
@@ -106,8 +131,12 @@ int4x2 :: matrix[4, 2]int
int4x3 :: matrix[4, 3]int
cos :: proc{
+ cos_half,
cos_float,
cos_double,
+ cos_half2,
+ cos_half3,
+ cos_half4,
cos_float2,
cos_float3,
cos_float4,
@@ -115,6 +144,9 @@ cos :: proc{
cos_double3,
cos_double4,
}
+@(require_results) cos_half2 :: proc "c" (x: half2) -> half2 { return {cos(x.x), cos(x.y)} }
+@(require_results) cos_half3 :: proc "c" (x: half3) -> half3 { return {cos(x.x), cos(x.y), cos(x.z)} }
+@(require_results) cos_half4 :: proc "c" (x: half4) -> half4 { return {cos(x.x), cos(x.y), cos(x.z), cos(x.w)} }
@(require_results) cos_float2 :: proc "c" (x: float2) -> float2 { return {cos(x.x), cos(x.y)} }
@(require_results) cos_float3 :: proc "c" (x: float3) -> float3 { return {cos(x.x), cos(x.y), cos(x.z)} }
@(require_results) cos_float4 :: proc "c" (x: float4) -> float4 { return {cos(x.x), cos(x.y), cos(x.z), cos(x.w)} }
@@ -123,8 +155,12 @@ cos :: proc{
@(require_results) cos_double4 :: proc "c" (x: double4) -> double4 { return {cos(x.x), cos(x.y), cos(x.z), cos(x.w)} }
sin :: proc{
+ sin_half,
sin_float,
sin_double,
+ sin_half2,
+ sin_half3,
+ sin_half4,
sin_float2,
sin_float3,
sin_float4,
@@ -132,6 +168,9 @@ sin :: proc{
sin_double3,
sin_double4,
}
+@(require_results) sin_half2 :: proc "c" (x: half2) -> half2 { return {sin(x.x), sin(x.y)} }
+@(require_results) sin_half3 :: proc "c" (x: half3) -> half3 { return {sin(x.x), sin(x.y), sin(x.z)} }
+@(require_results) sin_half4 :: proc "c" (x: half4) -> half4 { return {sin(x.x), sin(x.y), sin(x.z), sin(x.w)} }
@(require_results) sin_float2 :: proc "c" (x: float2) -> float2 { return {sin(x.x), sin(x.y)} }
@(require_results) sin_float3 :: proc "c" (x: float3) -> float3 { return {sin(x.x), sin(x.y), sin(x.z)} }
@(require_results) sin_float4 :: proc "c" (x: float4) -> float4 { return {sin(x.x), sin(x.y), sin(x.z), sin(x.w)} }
@@ -140,8 +179,12 @@ sin :: proc{
@(require_results) sin_double4 :: proc "c" (x: double4) -> double4 { return {sin(x.x), sin(x.y), sin(x.z), sin(x.w)} }
tan :: proc{
+ tan_half,
tan_float,
tan_double,
+ tan_half2,
+ tan_half3,
+ tan_half4,
tan_float2,
tan_float3,
tan_float4,
@@ -149,6 +192,9 @@ tan :: proc{
tan_double3,
tan_double4,
}
+@(require_results) tan_half2 :: proc "c" (x: half2) -> half2 { return {tan(x.x), tan(x.y)} }
+@(require_results) tan_half3 :: proc "c" (x: half3) -> half3 { return {tan(x.x), tan(x.y), tan(x.z)} }
+@(require_results) tan_half4 :: proc "c" (x: half4) -> half4 { return {tan(x.x), tan(x.y), tan(x.z), tan(x.w)} }
@(require_results) tan_float2 :: proc "c" (x: float2) -> float2 { return {tan(x.x), tan(x.y)} }
@(require_results) tan_float3 :: proc "c" (x: float3) -> float3 { return {tan(x.x), tan(x.y), tan(x.z)} }
@(require_results) tan_float4 :: proc "c" (x: float4) -> float4 { return {tan(x.x), tan(x.y), tan(x.z), tan(x.w)} }
@@ -157,8 +203,12 @@ tan :: proc{
@(require_results) tan_double4 :: proc "c" (x: double4) -> double4 { return {tan(x.x), tan(x.y), tan(x.z), tan(x.w)} }
acos :: proc{
+ acos_half,
acos_float,
acos_double,
+ acos_half2,
+ acos_half3,
+ acos_half4,
acos_float2,
acos_float3,
acos_float4,
@@ -166,6 +216,9 @@ acos :: proc{
acos_double3,
acos_double4,
}
+@(require_results) acos_half2 :: proc "c" (x: half2) -> half2 { return {acos(x.x), acos(x.y)} }
+@(require_results) acos_half3 :: proc "c" (x: half3) -> half3 { return {acos(x.x), acos(x.y), acos(x.z)} }
+@(require_results) acos_half4 :: proc "c" (x: half4) -> half4 { return {acos(x.x), acos(x.y), acos(x.z), acos(x.w)} }
@(require_results) acos_float2 :: proc "c" (x: float2) -> float2 { return {acos(x.x), acos(x.y)} }
@(require_results) acos_float3 :: proc "c" (x: float3) -> float3 { return {acos(x.x), acos(x.y), acos(x.z)} }
@(require_results) acos_float4 :: proc "c" (x: float4) -> float4 { return {acos(x.x), acos(x.y), acos(x.z), acos(x.w)} }
@@ -174,8 +227,12 @@ acos :: proc{
@(require_results) acos_double4 :: proc "c" (x: double4) -> double4 { return {acos(x.x), acos(x.y), acos(x.z), acos(x.w)} }
asin :: proc{
+ asin_half,
asin_float,
asin_double,
+ asin_half2,
+ asin_half3,
+ asin_half4,
asin_float2,
asin_float3,
asin_float4,
@@ -183,6 +240,9 @@ asin :: proc{
asin_double3,
asin_double4,
}
+@(require_results) asin_half2 :: proc "c" (x: half2) -> half2 { return {asin(x.x), asin(x.y)} }
+@(require_results) asin_half3 :: proc "c" (x: half3) -> half3 { return {asin(x.x), asin(x.y), asin(x.z)} }
+@(require_results) asin_half4 :: proc "c" (x: half4) -> half4 { return {asin(x.x), asin(x.y), asin(x.z), asin(x.w)} }
@(require_results) asin_float2 :: proc "c" (x: float2) -> float2 { return {asin(x.x), asin(x.y)} }
@(require_results) asin_float3 :: proc "c" (x: float3) -> float3 { return {asin(x.x), asin(x.y), asin(x.z)} }
@(require_results) asin_float4 :: proc "c" (x: float4) -> float4 { return {asin(x.x), asin(x.y), asin(x.z), asin(x.w)} }
@@ -191,8 +251,12 @@ asin :: proc{
@(require_results) asin_double4 :: proc "c" (x: double4) -> double4 { return {asin(x.x), asin(x.y), asin(x.z), asin(x.w)} }
atan :: proc{
+ atan_half,
atan_float,
atan_double,
+ atan_half2,
+ atan_half3,
+ atan_half4,
atan_float2,
atan_float3,
atan_float4,
@@ -208,6 +272,9 @@ atan :: proc{
atan2_double3,
atan2_double4,
}
+@(require_results) atan_half2 :: proc "c" (x: half2) -> half2 { return {atan(x.x), atan(x.y)} }
+@(require_results) atan_half3 :: proc "c" (x: half3) -> half3 { return {atan(x.x), atan(x.y), atan(x.z)} }
+@(require_results) atan_half4 :: proc "c" (x: half4) -> half4 { return {atan(x.x), atan(x.y), atan(x.z), atan(x.w)} }
@(require_results) atan_float2 :: proc "c" (x: float2) -> float2 { return {atan(x.x), atan(x.y)} }
@(require_results) atan_float3 :: proc "c" (x: float3) -> float3 { return {atan(x.x), atan(x.y), atan(x.z)} }
@(require_results) atan_float4 :: proc "c" (x: float4) -> float4 { return {atan(x.x), atan(x.y), atan(x.z), atan(x.w)} }
@@ -216,8 +283,12 @@ atan :: proc{
@(require_results) atan_double4 :: proc "c" (x: double4) -> double4 { return {atan(x.x), atan(x.y), atan(x.z), atan(x.w)} }
atan2 :: proc{
+ atan2_half,
atan2_float,
atan2_double,
+ atan2_half2,
+ atan2_half3,
+ atan2_half4,
atan2_float2,
atan2_float3,
atan2_float4,
@@ -225,6 +296,9 @@ atan2 :: proc{
atan2_double3,
atan2_double4,
}
+@(require_results) atan2_half2 :: proc "c" (y, x: half2) -> half2 { return {atan2(y.x, x.x), atan2(y.y, x.y)} }
+@(require_results) atan2_half3 :: proc "c" (y, x: half3) -> half3 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z)} }
+@(require_results) atan2_half4 :: proc "c" (y, x: half4) -> half4 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z), atan2(y.w, x.w)} }
@(require_results) atan2_float2 :: proc "c" (y, x: float2) -> float2 { return {atan2(y.x, x.x), atan2(y.y, x.y)} }
@(require_results) atan2_float3 :: proc "c" (y, x: float3) -> float3 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z)} }
@(require_results) atan2_float4 :: proc "c" (y, x: float4) -> float4 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z), atan2(y.w, x.w)} }
@@ -235,8 +309,12 @@ atan2 :: proc{
cosh :: proc{
+ cosh_half,
cosh_float,
cosh_double,
+ cosh_half2,
+ cosh_half3,
+ cosh_half4,
cosh_float2,
cosh_float3,
cosh_float4,
@@ -244,6 +322,9 @@ cosh :: proc{
cosh_double3,
cosh_double4,
}
+@(require_results) cosh_half2 :: proc "c" (x: half2) -> half2 { return {cosh(x.x), cosh(x.y)} }
+@(require_results) cosh_half3 :: proc "c" (x: half3) -> half3 { return {cosh(x.x), cosh(x.y), cosh(x.z)} }
+@(require_results) cosh_half4 :: proc "c" (x: half4) -> half4 { return {cosh(x.x), cosh(x.y), cosh(x.z), cosh(x.w)} }
@(require_results) cosh_float2 :: proc "c" (x: float2) -> float2 { return {cosh(x.x), cosh(x.y)} }
@(require_results) cosh_float3 :: proc "c" (x: float3) -> float3 { return {cosh(x.x), cosh(x.y), cosh(x.z)} }
@(require_results) cosh_float4 :: proc "c" (x: float4) -> float4 { return {cosh(x.x), cosh(x.y), cosh(x.z), cosh(x.w)} }
@@ -253,8 +334,12 @@ cosh :: proc{
sinh :: proc{
+ sinh_half,
sinh_float,
sinh_double,
+ sinh_half2,
+ sinh_half3,
+ sinh_half4,
sinh_float2,
sinh_float3,
sinh_float4,
@@ -262,6 +347,9 @@ sinh :: proc{
sinh_double3,
sinh_double4,
}
+@(require_results) sinh_half2 :: proc "c" (x: half2) -> half2 { return {sinh(x.x), sinh(x.y)} }
+@(require_results) sinh_half3 :: proc "c" (x: half3) -> half3 { return {sinh(x.x), sinh(x.y), sinh(x.z)} }
+@(require_results) sinh_half4 :: proc "c" (x: half4) -> half4 { return {sinh(x.x), sinh(x.y), sinh(x.z), sinh(x.w)} }
@(require_results) sinh_float2 :: proc "c" (x: float2) -> float2 { return {sinh(x.x), sinh(x.y)} }
@(require_results) sinh_float3 :: proc "c" (x: float3) -> float3 { return {sinh(x.x), sinh(x.y), sinh(x.z)} }
@(require_results) sinh_float4 :: proc "c" (x: float4) -> float4 { return {sinh(x.x), sinh(x.y), sinh(x.z), sinh(x.w)} }
@@ -270,8 +358,12 @@ sinh :: proc{
@(require_results) sinh_double4 :: proc "c" (x: double4) -> double4 { return {sinh(x.x), sinh(x.y), sinh(x.z), sinh(x.w)} }
tanh :: proc{
+ tanh_half,
tanh_float,
tanh_double,
+ tanh_half2,
+ tanh_half3,
+ tanh_half4,
tanh_float2,
tanh_float3,
tanh_float4,
@@ -279,6 +371,9 @@ tanh :: proc{
tanh_double3,
tanh_double4,
}
+@(require_results) tanh_half2 :: proc "c" (x: half2) -> half2 { return {tanh(x.x), tanh(x.y)} }
+@(require_results) tanh_half3 :: proc "c" (x: half3) -> half3 { return {tanh(x.x), tanh(x.y), tanh(x.z)} }
+@(require_results) tanh_half4 :: proc "c" (x: half4) -> half4 { return {tanh(x.x), tanh(x.y), tanh(x.z), tanh(x.w)} }
@(require_results) tanh_float2 :: proc "c" (x: float2) -> float2 { return {tanh(x.x), tanh(x.y)} }
@(require_results) tanh_float3 :: proc "c" (x: float3) -> float3 { return {tanh(x.x), tanh(x.y), tanh(x.z)} }
@(require_results) tanh_float4 :: proc "c" (x: float4) -> float4 { return {tanh(x.x), tanh(x.y), tanh(x.z), tanh(x.w)} }
@@ -287,8 +382,12 @@ tanh :: proc{
@(require_results) tanh_double4 :: proc "c" (x: double4) -> double4 { return {tanh(x.x), tanh(x.y), tanh(x.z), tanh(x.w)} }
acosh :: proc{
+ acosh_half,
acosh_float,
acosh_double,
+ acosh_half2,
+ acosh_half3,
+ acosh_half4,
acosh_float2,
acosh_float3,
acosh_float4,
@@ -296,6 +395,9 @@ acosh :: proc{
acosh_double3,
acosh_double4,
}
+@(require_results) acosh_half2 :: proc "c" (x: half2) -> half2 { return {acosh(x.x), acosh(x.y)} }
+@(require_results) acosh_half3 :: proc "c" (x: half3) -> half3 { return {acosh(x.x), acosh(x.y), acosh(x.z)} }
+@(require_results) acosh_half4 :: proc "c" (x: half4) -> half4 { return {acosh(x.x), acosh(x.y), acosh(x.z), acosh(x.w)} }
@(require_results) acosh_float2 :: proc "c" (x: float2) -> float2 { return {acosh(x.x), acosh(x.y)} }
@(require_results) acosh_float3 :: proc "c" (x: float3) -> float3 { return {acosh(x.x), acosh(x.y), acosh(x.z)} }
@(require_results) acosh_float4 :: proc "c" (x: float4) -> float4 { return {acosh(x.x), acosh(x.y), acosh(x.z), acosh(x.w)} }
@@ -304,8 +406,12 @@ acosh :: proc{
@(require_results) acosh_double4 :: proc "c" (x: double4) -> double4 { return {acosh(x.x), acosh(x.y), acosh(x.z), acosh(x.w)} }
asinh :: proc{
+ asinh_half,
asinh_float,
asinh_double,
+ asinh_half2,
+ asinh_half3,
+ asinh_half4,
asinh_float2,
asinh_float3,
asinh_float4,
@@ -313,6 +419,9 @@ asinh :: proc{
asinh_double3,
asinh_double4,
}
+@(require_results) asinh_half2 :: proc "c" (x: half2) -> half2 { return {asinh(x.x), asinh(x.y)} }
+@(require_results) asinh_half3 :: proc "c" (x: half3) -> half3 { return {asinh(x.x), asinh(x.y), asinh(x.z)} }
+@(require_results) asinh_half4 :: proc "c" (x: half4) -> half4 { return {asinh(x.x), asinh(x.y), asinh(x.z), asinh(x.w)} }
@(require_results) asinh_float2 :: proc "c" (x: float2) -> float2 { return {asinh(x.x), asinh(x.y)} }
@(require_results) asinh_float3 :: proc "c" (x: float3) -> float3 { return {asinh(x.x), asinh(x.y), asinh(x.z)} }
@(require_results) asinh_float4 :: proc "c" (x: float4) -> float4 { return {asinh(x.x), asinh(x.y), asinh(x.z), asinh(x.w)} }
@@ -321,8 +430,12 @@ asinh :: proc{
@(require_results) asinh_double4 :: proc "c" (x: double4) -> double4 { return {asinh(x.x), asinh(x.y), asinh(x.z), asinh(x.w)} }
atanh :: proc{
+ atanh_half,
atanh_float,
atanh_double,
+ atanh_half2,
+ atanh_half3,
+ atanh_half4,
atanh_float2,
atanh_float3,
atanh_float4,
@@ -330,6 +443,9 @@ atanh :: proc{
atanh_double3,
atanh_double4,
}
+@(require_results) atanh_half2 :: proc "c" (x: half2) -> half2 { return {atanh(x.x), atanh(x.y)} }
+@(require_results) atanh_half3 :: proc "c" (x: half3) -> half3 { return {atanh(x.x), atanh(x.y), atanh(x.z)} }
+@(require_results) atanh_half4 :: proc "c" (x: half4) -> half4 { return {atanh(x.x), atanh(x.y), atanh(x.z), atanh(x.w)} }
@(require_results) atanh_float2 :: proc "c" (x: float2) -> float2 { return {atanh(x.x), atanh(x.y)} }
@(require_results) atanh_float3 :: proc "c" (x: float3) -> float3 { return {atanh(x.x), atanh(x.y), atanh(x.z)} }
@(require_results) atanh_float4 :: proc "c" (x: float4) -> float4 { return {atanh(x.x), atanh(x.y), atanh(x.z), atanh(x.w)} }
@@ -338,8 +454,12 @@ atanh :: proc{
@(require_results) atanh_double4 :: proc "c" (x: double4) -> double4 { return {atanh(x.x), atanh(x.y), atanh(x.z), atanh(x.w)} }
sqrt :: proc{
+ sqrt_half,
sqrt_float,
sqrt_double,
+ sqrt_half2,
+ sqrt_half3,
+ sqrt_half4,
sqrt_float2,
sqrt_float3,
sqrt_float4,
@@ -347,6 +467,9 @@ sqrt :: proc{
sqrt_double3,
sqrt_double4,
}
+@(require_results) sqrt_half2 :: proc "c" (x: half2) -> half2 { return {sqrt(x.x), sqrt(x.y)} }
+@(require_results) sqrt_half3 :: proc "c" (x: half3) -> half3 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z)} }
+@(require_results) sqrt_half4 :: proc "c" (x: half4) -> half4 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z), sqrt(x.w)} }
@(require_results) sqrt_float2 :: proc "c" (x: float2) -> float2 { return {sqrt(x.x), sqrt(x.y)} }
@(require_results) sqrt_float3 :: proc "c" (x: float3) -> float3 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z)} }
@(require_results) sqrt_float4 :: proc "c" (x: float4) -> float4 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z), sqrt(x.w)} }
@@ -355,8 +478,12 @@ sqrt :: proc{
@(require_results) sqrt_double4 :: proc "c" (x: double4) -> double4 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z), sqrt(x.w)} }
rsqrt :: proc{
+ rsqrt_half,
rsqrt_float,
rsqrt_double,
+ rsqrt_half2,
+ rsqrt_half3,
+ rsqrt_half4,
rsqrt_float2,
rsqrt_float3,
rsqrt_float4,
@@ -364,6 +491,9 @@ rsqrt :: proc{
rsqrt_double3,
rsqrt_double4,
}
+@(require_results) rsqrt_half2 :: proc "c" (x: half2) -> half2 { return {rsqrt(x.x), rsqrt(x.y)} }
+@(require_results) rsqrt_half3 :: proc "c" (x: half3) -> half3 { return {rsqrt(x.x), rsqrt(x.y), rsqrt(x.z)} }
+@(require_results) rsqrt_half4 :: proc "c" (x: half4) -> half4 { return {rsqrt(x.x), rsqrt(x.y), rsqrt(x.z), rsqrt(x.w)} }
@(require_results) rsqrt_float2 :: proc "c" (x: float2) -> float2 { return {rsqrt(x.x), rsqrt(x.y)} }
@(require_results) rsqrt_float3 :: proc "c" (x: float3) -> float3 { return {rsqrt(x.x), rsqrt(x.y), rsqrt(x.z)} }
@(require_results) rsqrt_float4 :: proc "c" (x: float4) -> float4 { return {rsqrt(x.x), rsqrt(x.y), rsqrt(x.z), rsqrt(x.w)} }
@@ -372,8 +502,12 @@ rsqrt :: proc{
@(require_results) rsqrt_double4 :: proc "c" (x: double4) -> double4 { return {rsqrt(x.x), rsqrt(x.y), rsqrt(x.z), rsqrt(x.w)} }
rcp :: proc{
+ rcp_half,
rcp_float,
rcp_double,
+ rcp_half2,
+ rcp_half3,
+ rcp_half4,
rcp_float2,
rcp_float3,
rcp_float4,
@@ -381,6 +515,9 @@ rcp :: proc{
rcp_double3,
rcp_double4,
}
+@(require_results) rcp_half2 :: proc "c" (x: half2) -> half2 { return {rcp(x.x), rcp(x.y)} }
+@(require_results) rcp_half3 :: proc "c" (x: half3) -> half3 { return {rcp(x.x), rcp(x.y), rcp(x.z)} }
+@(require_results) rcp_half4 :: proc "c" (x: half4) -> half4 { return {rcp(x.x), rcp(x.y), rcp(x.z), rcp(x.w)} }
@(require_results) rcp_float2 :: proc "c" (x: float2) -> float2 { return {rcp(x.x), rcp(x.y)} }
@(require_results) rcp_float3 :: proc "c" (x: float3) -> float3 { return {rcp(x.x), rcp(x.y), rcp(x.z)} }
@(require_results) rcp_float4 :: proc "c" (x: float4) -> float4 { return {rcp(x.x), rcp(x.y), rcp(x.z), rcp(x.w)} }
@@ -390,8 +527,12 @@ rcp :: proc{
pow :: proc{
+ pow_half,
pow_float,
pow_double,
+ pow_half2,
+ pow_half3,
+ pow_half4,
pow_float2,
pow_float3,
pow_float4,
@@ -399,6 +540,9 @@ pow :: proc{
pow_double3,
pow_double4,
}
+@(require_results) pow_half2 :: proc "c" (x, y: half2) -> half2 { return {pow(x.x, y.x), pow(x.y, y.y)} }
+@(require_results) pow_half3 :: proc "c" (x, y: half3) -> half3 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z)} }
+@(require_results) pow_half4 :: proc "c" (x, y: half4) -> half4 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z), pow(x.w, y.w)} }
@(require_results) pow_float2 :: proc "c" (x, y: float2) -> float2 { return {pow(x.x, y.x), pow(x.y, y.y)} }
@(require_results) pow_float3 :: proc "c" (x, y: float3) -> float3 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z)} }
@(require_results) pow_float4 :: proc "c" (x, y: float4) -> float4 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z), pow(x.w, y.w)} }
@@ -409,8 +553,12 @@ pow :: proc{
exp :: proc{
+ exp_half,
exp_float,
exp_double,
+ exp_half2,
+ exp_half3,
+ exp_half4,
exp_float2,
exp_float3,
exp_float4,
@@ -418,6 +566,9 @@ exp :: proc{
exp_double3,
exp_double4,
}
+@(require_results) exp_half2 :: proc "c" (x: half2) -> half2 { return {exp(x.x), exp(x.y)} }
+@(require_results) exp_half3 :: proc "c" (x: half3) -> half3 { return {exp(x.x), exp(x.y), exp(x.z)} }
+@(require_results) exp_half4 :: proc "c" (x: half4) -> half4 { return {exp(x.x), exp(x.y), exp(x.z), exp(x.w)} }
@(require_results) exp_float2 :: proc "c" (x: float2) -> float2 { return {exp(x.x), exp(x.y)} }
@(require_results) exp_float3 :: proc "c" (x: float3) -> float3 { return {exp(x.x), exp(x.y), exp(x.z)} }
@(require_results) exp_float4 :: proc "c" (x: float4) -> float4 { return {exp(x.x), exp(x.y), exp(x.z), exp(x.w)} }
@@ -428,8 +579,12 @@ exp :: proc{
log :: proc{
+ log_half,
log_float,
log_double,
+ log_half2,
+ log_half3,
+ log_half4,
log_float2,
log_float3,
log_float4,
@@ -437,6 +592,9 @@ log :: proc{
log_double3,
log_double4,
}
+@(require_results) log_half2 :: proc "c" (x: half2) -> half2 { return {log(x.x), log(x.y)} }
+@(require_results) log_half3 :: proc "c" (x: half3) -> half3 { return {log(x.x), log(x.y), log(x.z)} }
+@(require_results) log_half4 :: proc "c" (x: half4) -> half4 { return {log(x.x), log(x.y), log(x.z), log(x.w)} }
@(require_results) log_float2 :: proc "c" (x: float2) -> float2 { return {log(x.x), log(x.y)} }
@(require_results) log_float3 :: proc "c" (x: float3) -> float3 { return {log(x.x), log(x.y), log(x.z)} }
@(require_results) log_float4 :: proc "c" (x: float4) -> float4 { return {log(x.x), log(x.y), log(x.z), log(x.w)} }
@@ -446,8 +604,12 @@ log :: proc{
log2 :: proc{
+ log2_half,
log2_float,
log2_double,
+ log2_half2,
+ log2_half3,
+ log2_half4,
log2_float2,
log2_float3,
log2_float4,
@@ -455,6 +617,9 @@ log2 :: proc{
log2_double3,
log2_double4,
}
+@(require_results) log2_half2 :: proc "c" (x: half2) -> half2 { return {log2(x.x), log2(x.y)} }
+@(require_results) log2_half3 :: proc "c" (x: half3) -> half3 { return {log2(x.x), log2(x.y), log2(x.z)} }
+@(require_results) log2_half4 :: proc "c" (x: half4) -> half4 { return {log2(x.x), log2(x.y), log2(x.z), log2(x.w)} }
@(require_results) log2_float2 :: proc "c" (x: float2) -> float2 { return {log2(x.x), log2(x.y)} }
@(require_results) log2_float3 :: proc "c" (x: float3) -> float3 { return {log2(x.x), log2(x.y), log2(x.z)} }
@(require_results) log2_float4 :: proc "c" (x: float4) -> float4 { return {log2(x.x), log2(x.y), log2(x.z), log2(x.w)} }
@@ -465,8 +630,12 @@ log2 :: proc{
log10 :: proc{
+ log10_half,
log10_float,
log10_double,
+ log10_half2,
+ log10_half3,
+ log10_half4,
log10_float2,
log10_float3,
log10_float4,
@@ -474,6 +643,9 @@ log10 :: proc{
log10_double3,
log10_double4,
}
+@(require_results) log10_half2 :: proc "c" (x: half2) -> half2 { return {log10(x.x), log10(x.y)} }
+@(require_results) log10_half3 :: proc "c" (x: half3) -> half3 { return {log10(x.x), log10(x.y), log10(x.z)} }
+@(require_results) log10_half4 :: proc "c" (x: half4) -> half4 { return {log10(x.x), log10(x.y), log10(x.z), log10(x.w)} }
@(require_results) log10_float2 :: proc "c" (x: float2) -> float2 { return {log10(x.x), log10(x.y)} }
@(require_results) log10_float3 :: proc "c" (x: float3) -> float3 { return {log10(x.x), log10(x.y), log10(x.z)} }
@(require_results) log10_float4 :: proc "c" (x: float4) -> float4 { return {log10(x.x), log10(x.y), log10(x.z), log10(x.w)} }
@@ -485,8 +657,12 @@ log10 :: proc{
exp2 :: proc{
+ exp2_half,
exp2_float,
exp2_double,
+ exp2_half2,
+ exp2_half3,
+ exp2_half4,
exp2_float2,
exp2_float3,
exp2_float4,
@@ -494,6 +670,9 @@ exp2 :: proc{
exp2_double3,
exp2_double4,
}
+@(require_results) exp2_half2 :: proc "c" (x: half2) -> half2 { return {exp2(x.x), exp2(x.y)} }
+@(require_results) exp2_half3 :: proc "c" (x: half3) -> half3 { return {exp2(x.x), exp2(x.y), exp2(x.z)} }
+@(require_results) exp2_half4 :: proc "c" (x: half4) -> half4 { return {exp2(x.x), exp2(x.y), exp2(x.z), exp2(x.w)} }
@(require_results) exp2_float2 :: proc "c" (x: float2) -> float2 { return {exp2(x.x), exp2(x.y)} }
@(require_results) exp2_float3 :: proc "c" (x: float3) -> float3 { return {exp2(x.x), exp2(x.y), exp2(x.z)} }
@(require_results) exp2_float4 :: proc "c" (x: float4) -> float4 { return {exp2(x.x), exp2(x.y), exp2(x.z), exp2(x.w)} }
@@ -503,10 +682,14 @@ exp2 :: proc{
sign :: proc{
+ sign_half,
sign_int,
sign_uint,
sign_float,
sign_double,
+ sign_half2,
+ sign_half3,
+ sign_half4,
sign_float2,
sign_float3,
sign_float4,
@@ -522,6 +705,9 @@ sign :: proc{
}
@(require_results) sign_int :: proc "c" (x: int) -> int { return -1 if x < 0 else +1 if x > 0 else 0 }
@(require_results) sign_uint :: proc "c" (x: uint) -> uint { return +1 if x > 0 else 0 }
+@(require_results) sign_half2 :: proc "c" (x: half2) -> half2 { return {sign(x.x), sign(x.y)} }
+@(require_results) sign_half3 :: proc "c" (x: half3) -> half3 { return {sign(x.x), sign(x.y), sign(x.z)} }
+@(require_results) sign_half4 :: proc "c" (x: half4) -> half4 { return {sign(x.x), sign(x.y), sign(x.z), sign(x.w)} }
@(require_results) sign_float2 :: proc "c" (x: float2) -> float2 { return {sign(x.x), sign(x.y)} }
@(require_results) sign_float3 :: proc "c" (x: float3) -> float3 { return {sign(x.x), sign(x.y), sign(x.z)} }
@(require_results) sign_float4 :: proc "c" (x: float4) -> float4 { return {sign(x.x), sign(x.y), sign(x.z), sign(x.w)} }
@@ -536,8 +722,12 @@ sign :: proc{
@(require_results) sign_uint4 :: proc "c" (x: uint4) -> uint4 { return {sign(x.x), sign(x.y), sign(x.z), sign(x.w)} }
floor :: proc{
+ floor_half,
floor_float,
floor_double,
+ floor_half2,
+ floor_half3,
+ floor_half4,
floor_float2,
floor_float3,
floor_float4,
@@ -545,6 +735,9 @@ floor :: proc{
floor_double3,
floor_double4,
}
+@(require_results) floor_half2 :: proc "c" (x: half2) -> half2 { return {floor(x.x), floor(x.y)} }
+@(require_results) floor_half3 :: proc "c" (x: half3) -> half3 { return {floor(x.x), floor(x.y), floor(x.z)} }
+@(require_results) floor_half4 :: proc "c" (x: half4) -> half4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} }
@(require_results) floor_float2 :: proc "c" (x: float2) -> float2 { return {floor(x.x), floor(x.y)} }
@(require_results) floor_float3 :: proc "c" (x: float3) -> float3 { return {floor(x.x), floor(x.y), floor(x.z)} }
@(require_results) floor_float4 :: proc "c" (x: float4) -> float4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} }
@@ -553,8 +746,12 @@ floor :: proc{
@(require_results) floor_double4 :: proc "c" (x: double4) -> double4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} }
round :: proc{
+ round_half,
round_float,
round_double,
+ round_half2,
+ round_half3,
+ round_half4,
round_float2,
round_float3,
round_float4,
@@ -562,6 +759,9 @@ round :: proc{
round_double3,
round_double4,
}
+@(require_results) round_half2 :: proc "c" (x: half2) -> half2 { return {round(x.x), round(x.y)} }
+@(require_results) round_half3 :: proc "c" (x: half3) -> half3 { return {round(x.x), round(x.y), round(x.z)} }
+@(require_results) round_half4 :: proc "c" (x: half4) -> half4 { return {round(x.x), round(x.y), round(x.z), round(x.w)} }
@(require_results) round_float2 :: proc "c" (x: float2) -> float2 { return {round(x.x), round(x.y)} }
@(require_results) round_float3 :: proc "c" (x: float3) -> float3 { return {round(x.x), round(x.y), round(x.z)} }
@(require_results) round_float4 :: proc "c" (x: float4) -> float4 { return {round(x.x), round(x.y), round(x.z), round(x.w)} }
@@ -571,8 +771,12 @@ round :: proc{
ceil :: proc{
+ ceil_half,
ceil_float,
ceil_double,
+ ceil_half2,
+ ceil_half3,
+ ceil_half4,
ceil_float2,
ceil_float3,
ceil_float4,
@@ -580,6 +784,9 @@ ceil :: proc{
ceil_double3,
ceil_double4,
}
+@(require_results) ceil_half2 :: proc "c" (x: half2) -> half2 { return {ceil(x.x), ceil(x.y)} }
+@(require_results) ceil_half3 :: proc "c" (x: half3) -> half3 { return {ceil(x.x), ceil(x.y), ceil(x.z)} }
+@(require_results) ceil_half4 :: proc "c" (x: half4) -> half4 { return {ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w)} }
@(require_results) ceil_float2 :: proc "c" (x: float2) -> float2 { return {ceil(x.x), ceil(x.y)} }
@(require_results) ceil_float3 :: proc "c" (x: float3) -> float3 { return {ceil(x.x), ceil(x.y), ceil(x.z)} }
@(require_results) ceil_float4 :: proc "c" (x: float4) -> float4 { return {ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w)} }
@@ -588,6 +795,10 @@ ceil :: proc{
@(require_results) ceil_double4 :: proc "c" (x: double4) -> double4 { return {ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w)} }
+@(require_results) isfinite_half :: proc "c" (x: half) -> bool { return !isinf_half(x) }
+@(require_results) isfinite_half2 :: proc "c" (x: half2) -> bool2 { return {isfinite_half(x.x), isfinite_half(x.y)} }
+@(require_results) isfinite_half3 :: proc "c" (x: half3) -> bool3 { return {isfinite_half(x.x), isfinite_half(x.y), isfinite_half(x.z)} }
+@(require_results) isfinite_half4 :: proc "c" (x: half4) -> bool4 { return {isfinite_half(x.x), isfinite_half(x.y), isfinite_half(x.z), isfinite_half(x.w)} }
@(require_results) isfinite_float :: proc "c" (x: float) -> bool { return !isinf_float(x) }
@(require_results) isfinite_float2 :: proc "c" (x: float2) -> bool2 { return {isfinite_float(x.x), isfinite_float(x.y)} }
@(require_results) isfinite_float3 :: proc "c" (x: float3) -> bool3 { return {isfinite_float(x.x), isfinite_float(x.y), isfinite_float(x.z)} }
@@ -599,6 +810,10 @@ ceil :: proc{
// isfinite is the opposite of isinf and returns true if the number is neither positive-infinite or negative-infinite
isfinite :: proc{
+ isfinite_half,
+ isfinite_half2,
+ isfinite_half3,
+ isfinite_half4,
isfinite_float,
isfinite_float2,
isfinite_float3,
@@ -610,6 +825,10 @@ isfinite :: proc{
}
+@(require_results) isinf_half :: proc "c" (x: half) -> bool { return x * 0.5 == x }
+@(require_results) isinf_half2 :: proc "c" (x: half2) -> bool2 { return {isinf_half(x.x), isinf_half(x.y)} }
+@(require_results) isinf_half3 :: proc "c" (x: half3) -> bool3 { return {isinf_half(x.x), isinf_half(x.y), isinf_half(x.z)} }
+@(require_results) isinf_half4 :: proc "c" (x: half4) -> bool4 { return {isinf_half(x.x), isinf_half(x.y), isinf_half(x.z), isinf_half(x.w)} }
@(require_results) isinf_float :: proc "c" (x: float) -> bool { return x * 0.5 == x }
@(require_results) isinf_float2 :: proc "c" (x: float2) -> bool2 { return {isinf_float(x.x), isinf_float(x.y)} }
@(require_results) isinf_float3 :: proc "c" (x: float3) -> bool3 { return {isinf_float(x.x), isinf_float(x.y), isinf_float(x.z)} }
@@ -621,6 +840,10 @@ isfinite :: proc{
// isinf is the opposite of isfinite and returns true if the number is either positive-infinite or negative-infinite
isinf :: proc{
+ isinf_half,
+ isinf_half2,
+ isinf_half3,
+ isinf_half4,
isinf_float,
isinf_float2,
isinf_float3,
@@ -632,6 +855,9 @@ isinf :: proc{
}
+@(require_results) isnan_half2 :: proc "c" (x: half2) -> bool2 { return {isnan_half(x.x), isnan_half(x.y)} }
+@(require_results) isnan_half3 :: proc "c" (x: half3) -> bool3 { return {isnan_half(x.x), isnan_half(x.y), isnan_half(x.z)} }
+@(require_results) isnan_half4 :: proc "c" (x: half4) -> bool4 { return {isnan_half(x.x), isnan_half(x.y), isnan_half(x.z), isnan_half(x.w)} }
@(require_results) isnan_float2 :: proc "c" (x: float2) -> bool2 { return {isnan_float(x.x), isnan_float(x.y)} }
@(require_results) isnan_float3 :: proc "c" (x: float3) -> bool3 { return {isnan_float(x.x), isnan_float(x.y), isnan_float(x.z)} }
@(require_results) isnan_float4 :: proc "c" (x: float4) -> bool4 { return {isnan_float(x.x), isnan_float(x.y), isnan_float(x.z), isnan_float(x.w)} }
@@ -641,6 +867,10 @@ isinf :: proc{
// isnan returns true if the input value is the special case of Not-A-Number
isnan :: proc{
+ isnan_half,
+ isnan_half2,
+ isnan_half3,
+ isnan_half4,
isnan_float,
isnan_float2,
isnan_float3,
@@ -652,8 +882,12 @@ isnan :: proc{
}
fmod :: proc{
+ fmod_half,
fmod_float,
fmod_double,
+ fmod_half2,
+ fmod_half3,
+ fmod_half4,
fmod_float2,
fmod_float3,
fmod_float4,
@@ -661,6 +895,9 @@ fmod :: proc{
fmod_double3,
fmod_double4,
}
+@(require_results) fmod_half2 :: proc "c" (x, y: half2) -> half2 { return {fmod(x.x, y.x), fmod(x.y, y.y)} }
+@(require_results) fmod_half3 :: proc "c" (x, y: half3) -> half3 { return {fmod(x.x, y.x), fmod(x.y, y.y), fmod(x.z, y.z)} }
+@(require_results) fmod_half4 :: proc "c" (x, y: half4) -> half4 { return {fmod(x.x, y.x), fmod(x.y, y.y), fmod(x.z, y.z), fmod(x.w, y.w)} }
@(require_results) fmod_float2 :: proc "c" (x, y: float2) -> float2 { return {fmod(x.x, y.x), fmod(x.y, y.y)} }
@(require_results) fmod_float3 :: proc "c" (x, y: float3) -> float3 { return {fmod(x.x, y.x), fmod(x.y, y.y), fmod(x.z, y.z)} }
@(require_results) fmod_float4 :: proc "c" (x, y: float4) -> float4 { return {fmod(x.x, y.x), fmod(x.y, y.y), fmod(x.z, y.z), fmod(x.w, y.w)} }
@@ -670,8 +907,12 @@ fmod :: proc{
frac :: proc{
+ frac_half,
frac_float,
frac_double,
+ frac_half2,
+ frac_half3,
+ frac_half4,
frac_float2,
frac_float3,
frac_float4,
@@ -679,6 +920,9 @@ frac :: proc{
frac_double3,
frac_double4,
}
+@(require_results) frac_half2 :: proc "c" (x: half2) -> half2 { return {frac(x.x), frac(x.y)} }
+@(require_results) frac_half3 :: proc "c" (x: half3) -> half3 { return {frac(x.x), frac(x.y), frac(x.z)} }
+@(require_results) frac_half4 :: proc "c" (x: half4) -> half4 { return {frac(x.x), frac(x.y), frac(x.z), frac(x.w)} }
@(require_results) frac_float2 :: proc "c" (x: float2) -> float2 { return {frac(x.x), frac(x.y)} }
@(require_results) frac_float3 :: proc "c" (x: float3) -> float3 { return {frac(x.x), frac(x.y), frac(x.z)} }
@(require_results) frac_float4 :: proc "c" (x: float4) -> float4 { return {frac(x.x), frac(x.y), frac(x.z), frac(x.w)} }
@@ -689,8 +933,12 @@ frac :: proc{
radians :: proc{
+ radians_half,
radians_float,
radians_double,
+ radians_half2,
+ radians_half3,
+ radians_half4,
radians_float2,
radians_float3,
radians_float4,
@@ -698,8 +946,12 @@ radians :: proc{
radians_double3,
radians_double4,
}
+@(require_results) radians_half :: proc "c" (degrees: half) -> half { return degrees * TAU / 360.0 }
@(require_results) radians_float :: proc "c" (degrees: float) -> float { return degrees * TAU / 360.0 }
@(require_results) radians_double :: proc "c" (degrees: double) -> double { return degrees * TAU / 360.0 }
+@(require_results) radians_half2 :: proc "c" (degrees: half2) -> half2 { return degrees * TAU / 360.0 }
+@(require_results) radians_half3 :: proc "c" (degrees: half3) -> half3 { return degrees * TAU / 360.0 }
+@(require_results) radians_half4 :: proc "c" (degrees: half4) -> half4 { return degrees * TAU / 360.0 }
@(require_results) radians_float2 :: proc "c" (degrees: float2) -> float2 { return degrees * TAU / 360.0 }
@(require_results) radians_float3 :: proc "c" (degrees: float3) -> float3 { return degrees * TAU / 360.0 }
@(require_results) radians_float4 :: proc "c" (degrees: float4) -> float4 { return degrees * TAU / 360.0 }
@@ -709,8 +961,12 @@ radians :: proc{
degrees :: proc{
+ degrees_half,
degrees_float,
degrees_double,
+ degrees_half2,
+ degrees_half3,
+ degrees_half4,
degrees_float2,
degrees_float3,
degrees_float4,
@@ -718,8 +974,12 @@ degrees :: proc{
degrees_double3,
degrees_double4,
}
+@(require_results) degrees_half :: proc "c" (radians: half) -> half { return radians * 360.0 / TAU }
@(require_results) degrees_float :: proc "c" (radians: float) -> float { return radians * 360.0 / TAU }
@(require_results) degrees_double :: proc "c" (radians: double) -> double { return radians * 360.0 / TAU }
+@(require_results) degrees_half2 :: proc "c" (radians: half2) -> half2 { return radians * 360.0 / TAU }
+@(require_results) degrees_half3 :: proc "c" (radians: half3) -> half3 { return radians * 360.0 / TAU }
+@(require_results) degrees_half4 :: proc "c" (radians: half4) -> half4 { return radians * 360.0 / TAU }
@(require_results) degrees_float2 :: proc "c" (radians: float2) -> float2 { return radians * 360.0 / TAU }
@(require_results) degrees_float3 :: proc "c" (radians: float3) -> float3 { return radians * 360.0 / TAU }
@(require_results) degrees_float4 :: proc "c" (radians: float4) -> float4 { return radians * 360.0 / TAU }
@@ -728,10 +988,14 @@ degrees :: proc{
@(require_results) degrees_double4 :: proc "c" (radians: double4) -> double4 { return radians * 360.0 / TAU }
min :: proc{
+ min_half,
min_int,
min_uint,
min_float,
min_double,
+ min_half2,
+ min_half3,
+ min_half4,
min_float2,
min_float3,
min_float4,
@@ -747,8 +1011,12 @@ min :: proc{
}
@(require_results) min_int :: proc "c" (x, y: int) -> int { return builtin.min(x, y) }
@(require_results) min_uint :: proc "c" (x, y: uint) -> uint { return builtin.min(x, y) }
+@(require_results) min_half :: proc "c" (x, y: half) -> half { return builtin.min(x, y) }
@(require_results) min_float :: proc "c" (x, y: float) -> float { return builtin.min(x, y) }
@(require_results) min_double :: proc "c" (x, y: double) -> double { return builtin.min(x, y) }
+@(require_results) min_half2 :: proc "c" (x, y: half2) -> half2 { return {min(x.x, y.x), min(x.y, y.y)} }
+@(require_results) min_half3 :: proc "c" (x, y: half3) -> half3 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z)} }
+@(require_results) min_half4 :: proc "c" (x, y: half4) -> half4 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z), min(x.w, y.w)} }
@(require_results) min_float2 :: proc "c" (x, y: float2) -> float2 { return {min(x.x, y.x), min(x.y, y.y)} }
@(require_results) min_float3 :: proc "c" (x, y: float3) -> float3 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z)} }
@(require_results) min_float4 :: proc "c" (x, y: float4) -> float4 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z), min(x.w, y.w)} }
@@ -765,9 +1033,13 @@ min :: proc{
max :: proc{
max_int,
- max_uint,
+ max_uint,
+ max_half,
max_float,
max_double,
+ max_half2,
+ max_half3,
+ max_half4,
max_float2,
max_float3,
max_float4,
@@ -784,7 +1056,11 @@ max :: proc{
@(require_results) max_int :: proc "c" (x, y: int) -> int { return builtin.max(x, y) }
@(require_results) max_uint :: proc "c" (x, y: uint) -> uint { return builtin.max(x, y) }
@(require_results) max_float :: proc "c" (x, y: float) -> float { return builtin.max(x, y) }
+@(require_results) max_half :: proc "c" (x, y: half) -> half { return builtin.max(x, y) }
@(require_results) max_double :: proc "c" (x, y: double) -> double { return builtin.max(x, y) }
+@(require_results) max_half2 :: proc "c" (x, y: half2) -> half2 { return {max(x.x, y.x), max(x.y, y.y)} }
+@(require_results) max_half3 :: proc "c" (x, y: half3) -> half3 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z)} }
+@(require_results) max_half4 :: proc "c" (x, y: half4) -> half4 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z), max(x.w, y.w)} }
@(require_results) max_float2 :: proc "c" (x, y: float2) -> float2 { return {max(x.x, y.x), max(x.y, y.y)} }
@(require_results) max_float3 :: proc "c" (x, y: float3) -> float3 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z)} }
@(require_results) max_float4 :: proc "c" (x, y: float4) -> float4 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z), max(x.w, y.w)} }
@@ -803,8 +1079,12 @@ max :: proc{
clamp :: proc{
clamp_int,
clamp_uint,
- clamp_float,
+ clamp_half,
+ clamp_float,
clamp_double,
+ clamp_half2,
+ clamp_half3,
+ clamp_half4,
clamp_float2,
clamp_float3,
clamp_float4,
@@ -820,8 +1100,12 @@ clamp :: proc{
}
@(require_results) clamp_int :: proc "c" (x, y, z: int) -> int { return builtin.clamp(x, y, z) }
@(require_results) clamp_uint :: proc "c" (x, y, z: uint) -> uint { return builtin.clamp(x, y, z) }
+@(require_results) clamp_half :: proc "c" (x, y, z: half) -> half { return builtin.clamp(x, y, z) }
@(require_results) clamp_float :: proc "c" (x, y, z: float) -> float { return builtin.clamp(x, y, z) }
@(require_results) clamp_double :: proc "c" (x, y, z: double) -> double { return builtin.clamp(x, y, z) }
+@(require_results) clamp_half2 :: proc "c" (x, y, z: half2) -> half2 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y)} }
+@(require_results) clamp_half3 :: proc "c" (x, y, z: half3) -> half3 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z)} }
+@(require_results) clamp_half4 :: proc "c" (x, y, z: half4) -> half4 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z), clamp(x.w, y.w, z.w)} }
@(require_results) clamp_float2 :: proc "c" (x, y, z: float2) -> float2 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y)} }
@(require_results) clamp_float3 :: proc "c" (x, y, z: float3) -> float3 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z)} }
@(require_results) clamp_float4 :: proc "c" (x, y, z: float4) -> float4 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z), clamp(x.w, y.w, z.w)} }
@@ -838,8 +1122,12 @@ clamp :: proc{
saturate :: proc{
saturate_int,
saturate_uint,
+ saturate_half,
saturate_float,
saturate_double,
+ saturate_half2,
+ saturate_half3,
+ saturate_half4,
saturate_float2,
saturate_float3,
saturate_float4,
@@ -855,8 +1143,12 @@ saturate :: proc{
}
@(require_results) saturate_int :: proc "c" (v: int) -> int { return builtin.clamp(v, 0, 1) }
@(require_results) saturate_uint :: proc "c" (v: uint) -> uint { return builtin.clamp(v, 0, 1) }
+@(require_results) saturate_half :: proc "c" (v: half) -> half { return builtin.clamp(v, 0, 1) }
@(require_results) saturate_float :: proc "c" (v: float) -> float { return builtin.clamp(v, 0, 1) }
@(require_results) saturate_double :: proc "c" (v: double) -> double { return builtin.clamp(v, 0, 1) }
+@(require_results) saturate_half2 :: proc "c" (v: half2) -> half2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
+@(require_results) saturate_half3 :: proc "c" (v: half3) -> half3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
+@(require_results) saturate_half4 :: proc "c" (v: half4) -> half4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
@(require_results) saturate_float2 :: proc "c" (v: float2) -> float2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
@(require_results) saturate_float3 :: proc "c" (v: float3) -> float3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
@(require_results) saturate_float4 :: proc "c" (v: float4) -> float4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
@@ -872,8 +1164,12 @@ saturate :: proc{
lerp :: proc{
+ lerp_half,
lerp_float,
lerp_double,
+ lerp_half2,
+ lerp_half3,
+ lerp_half4,
lerp_float2,
lerp_float3,
lerp_float4,
@@ -881,8 +1177,12 @@ lerp :: proc{
lerp_double3,
lerp_double4,
}
+@(require_results) lerp_half :: proc "c" (x, y, t: half) -> half { return x*(1-t) + y*t }
@(require_results) lerp_float :: proc "c" (x, y, t: float) -> float { return x*(1-t) + y*t }
@(require_results) lerp_double :: proc "c" (x, y, t: double) -> double { return x*(1-t) + y*t }
+@(require_results) lerp_half2 :: proc "c" (x, y, t: half2) -> half2 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y)} }
+@(require_results) lerp_half3 :: proc "c" (x, y, t: half3) -> half3 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y), lerp(x.z, y.z, t.z)} }
+@(require_results) lerp_half4 :: proc "c" (x, y, t: half4) -> half4 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, y.y), lerp(x.z, y.z, t.z), lerp(x.w, y.w, t.w)} }
@(require_results) lerp_float2 :: proc "c" (x, y, t: float2) -> float2 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y)} }
@(require_results) lerp_float3 :: proc "c" (x, y, t: float3) -> float3 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y), lerp(x.z, y.z, t.z)} }
@(require_results) lerp_float4 :: proc "c" (x, y, t: float4) -> float4 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, y.y), lerp(x.z, y.z, t.z), lerp(x.w, y.w, t.w)} }
@@ -892,8 +1192,12 @@ lerp :: proc{
step :: proc{
+ step_half,
step_float,
step_double,
+ step_half2,
+ step_half3,
+ step_half4,
step_float2,
step_float3,
step_float4,
@@ -901,8 +1205,12 @@ step :: proc{
step_double3,
step_double4,
}
+@(require_results) step_half :: proc "c" (edge, x: half) -> half { return 0 if x < edge else 1 }
@(require_results) step_float :: proc "c" (edge, x: float) -> float { return 0 if x < edge else 1 }
@(require_results) step_double :: proc "c" (edge, x: double) -> double { return 0 if x < edge else 1 }
+@(require_results) step_half2 :: proc "c" (edge, x: half2) -> half2 { return {step(edge.x, x.x), step(edge.y, x.y)} }
+@(require_results) step_half3 :: proc "c" (edge, x: half3) -> half3 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z)} }
+@(require_results) step_half4 :: proc "c" (edge, x: half4) -> half4 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z), step(edge.w, x.w)} }
@(require_results) step_float2 :: proc "c" (edge, x: float2) -> float2 { return {step(edge.x, x.x), step(edge.y, x.y)} }
@(require_results) step_float3 :: proc "c" (edge, x: float3) -> float3 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z)} }
@(require_results) step_float4 :: proc "c" (edge, x: float4) -> float4 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z), step(edge.w, x.w)} }
@@ -911,8 +1219,12 @@ step :: proc{
@(require_results) step_double4 :: proc "c" (edge, x: double4) -> double4 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z), step(edge.w, x.w)} }
smoothstep :: proc{
+ smoothstep_half,
smoothstep_float,
smoothstep_double,
+ smoothstep_half2,
+ smoothstep_half3,
+ smoothstep_half4,
smoothstep_float2,
smoothstep_float3,
smoothstep_float4,
@@ -920,6 +1232,10 @@ smoothstep :: proc{
smoothstep_double3,
smoothstep_double4,
}
+@(require_results) smoothstep_half :: proc "c" (edge0, edge1, x: half) -> half {
+ y := clamp(((x-edge0) / (edge1 - edge0)), 0, 1)
+ return y * y * (3 - 2*y)
+}
@(require_results) smoothstep_float :: proc "c" (edge0, edge1, x: float) -> float {
y := clamp(((x-edge0) / (edge1 - edge0)), 0, 1)
return y * y * (3 - 2*y)
@@ -928,6 +1244,9 @@ smoothstep :: proc{
y := clamp(((x-edge0) / (edge1 - edge0)), 0, 1)
return y * y * (3 - 2*y)
}
+@(require_results) smoothstep_half2 :: proc "c" (edge0, edge1, x: half2) -> half2 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y)} }
+@(require_results) smoothstep_half3 :: proc "c" (edge0, edge1, x: half3) -> half3 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y), smoothstep(edge0.z, edge1.z, x.z)} }
+@(require_results) smoothstep_half4 :: proc "c" (edge0, edge1, x: half4) -> half4 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y), smoothstep(edge0.z, edge1.z, x.z), smoothstep(edge0.w, edge1.w, x.w)} }
@(require_results) smoothstep_float2 :: proc "c" (edge0, edge1, x: float2) -> float2 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y)} }
@(require_results) smoothstep_float3 :: proc "c" (edge0, edge1, x: float3) -> float3 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y), smoothstep(edge0.z, edge1.z, x.z)} }
@(require_results) smoothstep_float4 :: proc "c" (edge0, edge1, x: float4) -> float4 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y), smoothstep(edge0.z, edge1.z, x.z), smoothstep(edge0.w, edge1.w, x.w)} }
@@ -939,8 +1258,12 @@ smoothstep :: proc{
abs :: proc{
abs_int,
abs_uint,
+ abs_half,
abs_float,
abs_double,
+ abs_half2,
+ abs_half3,
+ abs_half4,
abs_float2,
abs_float3,
abs_float4,
@@ -956,8 +1279,12 @@ abs :: proc{
}
@(require_results) abs_int :: proc "c" (x: int) -> int { return builtin.abs(x) }
@(require_results) abs_uint :: proc "c" (x: uint) -> uint { return x }
+@(require_results) abs_half :: proc "c" (x: half) -> half { return builtin.abs(x) }
@(require_results) abs_float :: proc "c" (x: float) -> float { return builtin.abs(x) }
@(require_results) abs_double :: proc "c" (x: double) -> double { return builtin.abs(x) }
+@(require_results) abs_half2 :: proc "c" (x: half2) -> half2 { return {abs(x.x), abs(x.y)} }
+@(require_results) abs_half3 :: proc "c" (x: half3) -> half3 { return {abs(x.x), abs(x.y), abs(x.z)} }
+@(require_results) abs_half4 :: proc "c" (x: half4) -> half4 { return {abs(x.x), abs(x.y), abs(x.z), abs(x.w)} }
@(require_results) abs_float2 :: proc "c" (x: float2) -> float2 { return {abs(x.x), abs(x.y)} }
@(require_results) abs_float3 :: proc "c" (x: float3) -> float3 { return {abs(x.x), abs(x.y), abs(x.z)} }
@(require_results) abs_float4 :: proc "c" (x: float4) -> float4 { return {abs(x.x), abs(x.y), abs(x.z), abs(x.w)} }
@@ -974,8 +1301,12 @@ abs :: proc{
dot :: proc{
dot_int,
dot_uint,
+ dot_half,
dot_float,
dot_double,
+ dot_half2,
+ dot_half3,
+ dot_half4,
dot_float2,
dot_float3,
dot_float4,
@@ -991,8 +1322,12 @@ dot :: proc{
}
@(require_results) dot_int :: proc "c" (a, b: int) -> int { return a*b }
@(require_results) dot_uint :: proc "c" (a, b: uint) -> uint { return a*b }
+@(require_results) dot_half :: proc "c" (a, b: half) -> half { return a*b }
@(require_results) dot_float :: proc "c" (a, b: float) -> float { return a*b }
@(require_results) dot_double :: proc "c" (a, b: double) -> double { return a*b }
+@(require_results) dot_half2 :: proc "c" (a, b: half2) -> half { return a.x*b.x + a.y*b.y }
+@(require_results) dot_half3 :: proc "c" (a, b: half3) -> half { return a.x*b.x + a.y*b.y + a.z*b.z }
+@(require_results) dot_half4 :: proc "c" (a, b: half4) -> half { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w }
@(require_results) dot_float2 :: proc "c" (a, b: float2) -> float { return a.x*b.x + a.y*b.y }
@(require_results) dot_float3 :: proc "c" (a, b: float3) -> float { return a.x*b.x + a.y*b.y + a.z*b.z }
@(require_results) dot_float4 :: proc "c" (a, b: float4) -> float { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w }
@@ -1007,8 +1342,12 @@ dot :: proc{
@(require_results) dot_uint4 :: proc "c" (a, b: uint4) -> uint { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w }
length :: proc{
+ length_half,
length_float,
length_double,
+ length_half2,
+ length_half3,
+ length_half4,
length_float2,
length_float3,
length_float4,
@@ -1016,8 +1355,12 @@ length :: proc{
length_double3,
length_double4,
}
+@(require_results) length_half :: proc "c" (x: half) -> half { return builtin.abs(x) }
@(require_results) length_float :: proc "c" (x: float) -> float { return builtin.abs(x) }
@(require_results) length_double :: proc "c" (x: double) -> double { return builtin.abs(x) }
+@(require_results) length_half2 :: proc "c" (x: half2) -> half { return sqrt(x.x*x.x + x.y*x.y) }
+@(require_results) length_half3 :: proc "c" (x: half3) -> half { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z) }
+@(require_results) length_half4 :: proc "c" (x: half4) -> half { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z + x.w*x.w) }
@(require_results) length_float2 :: proc "c" (x: float2) -> float { return sqrt(x.x*x.x + x.y*x.y) }
@(require_results) length_float3 :: proc "c" (x: float3) -> float { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z) }
@(require_results) length_float4 :: proc "c" (x: float4) -> float { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z + x.w*x.w) }
@@ -1027,8 +1370,12 @@ length :: proc{
distance :: proc{
+ distance_half,
distance_float,
distance_double,
+ distance_half2,
+ distance_half3,
+ distance_half4,
distance_float2,
distance_float3,
distance_float4,
@@ -1036,8 +1383,12 @@ distance :: proc{
distance_double3,
distance_double4,
}
+@(require_results) distance_half :: proc "c" (x, y: half) -> half { return length(y-x) }
@(require_results) distance_float :: proc "c" (x, y: float) -> float { return length(y-x) }
@(require_results) distance_double :: proc "c" (x, y: double) -> double { return length(y-x) }
+@(require_results) distance_half2 :: proc "c" (x, y: half2) -> half { return length(y-x) }
+@(require_results) distance_half3 :: proc "c" (x, y: half3) -> half { return length(y-x) }
+@(require_results) distance_half4 :: proc "c" (x, y: half4) -> half { return length(y-x) }
@(require_results) distance_float2 :: proc "c" (x, y: float2) -> float { return length(y-x) }
@(require_results) distance_float3 :: proc "c" (x, y: float3) -> float { return length(y-x) }
@(require_results) distance_float4 :: proc "c" (x, y: float4) -> float { return length(y-x) }
@@ -1047,11 +1398,18 @@ distance :: proc{
cross :: proc{
+ cross_half3,
cross_float3,
cross_double3,
cross_int3,
}
+@(require_results) cross_half3 :: proc "c" (a, b: half3) -> (c: half3) {
+ c.x = a.y*b.z - b.y*a.z
+ c.y = a.z*b.x - b.z*a.x
+ c.z = a.x*b.y - b.x*a.y
+ return
+}
@(require_results) cross_float3 :: proc "c" (a, b: float3) -> (c: float3) {
c.x = a.y*b.z - b.y*a.z
c.y = a.z*b.x - b.z*a.x
@@ -1072,8 +1430,12 @@ cross :: proc{
}
normalize :: proc{
+ normalize_half,
normalize_float,
normalize_double,
+ normalize_half2,
+ normalize_half3,
+ normalize_half4,
normalize_float2,
normalize_float3,
normalize_float4,
@@ -1081,8 +1443,12 @@ normalize :: proc{
normalize_double3,
normalize_double4,
}
+@(require_results) normalize_half :: proc "c" (x: half) -> half { return 1.0 }
@(require_results) normalize_float :: proc "c" (x: float) -> float { return 1.0 }
@(require_results) normalize_double :: proc "c" (x: double) -> double { return 1.0 }
+@(require_results) normalize_half2 :: proc "c" (x: half2) -> half2 { return x / length(x) }
+@(require_results) normalize_half3 :: proc "c" (x: half3) -> half3 { return x / length(x) }
+@(require_results) normalize_half4 :: proc "c" (x: half4) -> half4 { return x / length(x) }
@(require_results) normalize_float2 :: proc "c" (x: float2) -> float2 { return x / length(x) }
@(require_results) normalize_float3 :: proc "c" (x: float3) -> float3 { return x / length(x) }
@(require_results) normalize_float4 :: proc "c" (x: float4) -> float4 { return x / length(x) }
@@ -1092,8 +1458,12 @@ normalize :: proc{
faceforward :: proc{
+ faceforward_half,
faceforward_float,
faceforward_double,
+ faceforward_half2,
+ faceforward_half3,
+ faceforward_half4,
faceforward_float2,
faceforward_float3,
faceforward_float4,
@@ -1101,8 +1471,12 @@ faceforward :: proc{
faceforward_double3,
faceforward_double4,
}
+@(require_results) faceforward_half :: proc "c" (N, I, Nref: half) -> half { return N if dot(I, Nref) < 0 else -N }
@(require_results) faceforward_float :: proc "c" (N, I, Nref: float) -> float { return N if dot(I, Nref) < 0 else -N }
@(require_results) faceforward_double :: proc "c" (N, I, Nref: double) -> double { return N if dot(I, Nref) < 0 else -N }
+@(require_results) faceforward_half2 :: proc "c" (N, I, Nref: half2) -> half2 { return N if dot(I, Nref) < 0 else -N }
+@(require_results) faceforward_half3 :: proc "c" (N, I, Nref: half3) -> half3 { return N if dot(I, Nref) < 0 else -N }
+@(require_results) faceforward_half4 :: proc "c" (N, I, Nref: half4) -> half4 { return N if dot(I, Nref) < 0 else -N }
@(require_results) faceforward_float2 :: proc "c" (N, I, Nref: float2) -> float2 { return N if dot(I, Nref) < 0 else -N }
@(require_results) faceforward_float3 :: proc "c" (N, I, Nref: float3) -> float3 { return N if dot(I, Nref) < 0 else -N }
@(require_results) faceforward_float4 :: proc "c" (N, I, Nref: float4) -> float4 { return N if dot(I, Nref) < 0 else -N }
@@ -1112,8 +1486,12 @@ faceforward :: proc{
reflect :: proc{
+ reflect_half,
reflect_float,
reflect_double,
+ reflect_half2,
+ reflect_half3,
+ reflect_half4,
reflect_float2,
reflect_float3,
reflect_float4,
@@ -1121,8 +1499,12 @@ reflect :: proc{
reflect_double3,
reflect_double4,
}
+@(require_results) reflect_half :: proc "c" (I, N: half) -> half { return I - 2*N*dot(N, I) }
@(require_results) reflect_float :: proc "c" (I, N: float) -> float { return I - 2*N*dot(N, I) }
@(require_results) reflect_double :: proc "c" (I, N: double) -> double { return I - 2*N*dot(N, I) }
+@(require_results) reflect_half2 :: proc "c" (I, N: half2) -> half2 { return I - 2*N*dot(N, I) }
+@(require_results) reflect_half3 :: proc "c" (I, N: half3) -> half3 { return I - 2*N*dot(N, I) }
+@(require_results) reflect_half4 :: proc "c" (I, N: half4) -> half4 { return I - 2*N*dot(N, I) }
@(require_results) reflect_float2 :: proc "c" (I, N: float2) -> float2 { return I - 2*N*dot(N, I) }
@(require_results) reflect_float3 :: proc "c" (I, N: float3) -> float3 { return I - 2*N*dot(N, I) }
@(require_results) reflect_float4 :: proc "c" (I, N: float4) -> float4 { return I - 2*N*dot(N, I) }
@@ -1134,8 +1516,12 @@ reflect :: proc{
refract :: proc{
+ refract_half,
refract_float,
refract_double,
+ refract_half2,
+ refract_half3,
+ refract_half4,
refract_float2,
refract_float3,
refract_float4,
@@ -1144,6 +1530,13 @@ refract :: proc{
refract_double4,
}
@(require_results)
+refract_half :: proc "c" (i, n, eta: half) -> half {
+ cosi := dot(-i, n)
+ cost2 := 1 - eta*eta*(1 - cosi*cosi)
+ t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n)
+ return t * half(int(cost2 > 0))
+}
+@(require_results)
refract_float :: proc "c" (i, n, eta: float) -> float {
cosi := dot(-i, n)
cost2 := 1 - eta*eta*(1 - cosi*cosi)
@@ -1158,6 +1551,27 @@ refract_double :: proc "c" (i, n, eta: double) -> double {
return t * double(int(cost2 > 0))
}
@(require_results)
+refract_half2 :: proc "c" (i, n, eta: half2) -> half2 {
+ cosi := dot(-i, n)
+ cost2 := 1 - eta*eta*(1 - cosi*cosi)
+ t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n)
+ return t * half2{half(int(cost2.x > 0)), half(int(cost2.y > 0))}
+}
+@(require_results)
+refract_half3 :: proc "c" (i, n, eta: half3) -> half3 {
+ cosi := dot(-i, n)
+ cost2 := 1 - eta*eta*(1 - cosi*cosi)
+ t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n)
+ return t * half3{half(int(cost2.x > 0)), half(int(cost2.y > 0)), half(int(cost2.z > 0))}
+}
+@(require_results)
+refract_half4 :: proc "c" (i, n, eta: half4) -> half4 {
+ cosi := dot(-i, n)
+ cost2 := 1 - eta*eta*(1 - cosi*cosi)
+ t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n)
+ return t * half4{half(int(cost2.x > 0)), half(int(cost2.y > 0)), half(int(cost2.z > 0)), half(int(cost2.w > 0))}
+}
+@(require_results)
refract_float2 :: proc "c" (i, n, eta: float2) -> float2 {
cosi := dot(-i, n)
cost2 := 1 - eta*eta*(1 - cosi*cosi)
@@ -1201,19 +1615,23 @@ refract_double4 :: proc "c" (i, n, eta: double4) -> double4 {
}
scalarTripleProduct :: proc{
+ scalarTripleProduct_half3,
scalarTripleProduct_float3,
scalarTripleProduct_double3,
scalarTripleProduct_int3,
}
+@(require_results) scalarTripleProduct_half3 :: proc "c" (a, b, c: half3) -> half { return dot(a, cross(b, c)) }
@(require_results) scalarTripleProduct_float3 :: proc "c" (a, b, c: float3) -> float { return dot(a, cross(b, c)) }
@(require_results) scalarTripleProduct_double3 :: proc "c" (a, b, c: double3) -> double { return dot(a, cross(b, c)) }
@(require_results) scalarTripleProduct_int3 :: proc "c" (a, b, c: int3) -> int { return dot(a, cross(b, c)) }
vectorTripleProduct :: proc {
+ vectorTripleProduct_half3,
vectorTripleProduct_float3,
vectorTripleProduct_double3,
vectorTripleProduct_int3,
}
+@(require_results) vectorTripleProduct_half3 :: proc "c" (a, b, c: half3) -> half3 { return cross(a, cross(b, c)) }
@(require_results) vectorTripleProduct_float3 :: proc "c" (a, b, c: float3) -> float3 { return cross(a, cross(b, c)) }
@(require_results) vectorTripleProduct_double3 :: proc "c" (a, b, c: double3) -> double3 { return cross(a, cross(b, c)) }
@(require_results) vectorTripleProduct_int3 :: proc "c" (a, b, c: int3) -> int3 { return cross(a, cross(b, c)) }
@@ -1222,35 +1640,43 @@ vectorTripleProduct :: proc {
// Vector Relational Procedures
lessThan :: proc{
+ lessThan_half,
lessThan_float,
lessThan_double,
lessThan_int,
lessThan_uint,
+ lessThan_half2,
lessThan_float2,
lessThan_double2,
lessThan_int2,
lessThan_uint2,
+ lessThan_half3,
lessThan_float3,
lessThan_double3,
lessThan_int3,
lessThan_uint3,
+ lessThan_half4,
lessThan_float4,
lessThan_double4,
lessThan_int4,
lessThan_uint4,
}
+@(require_results) lessThan_half :: proc "c" (a, b: half) -> bool { return a < b }
@(require_results) lessThan_float :: proc "c" (a, b: float) -> bool { return a < b }
@(require_results) lessThan_double :: proc "c" (a, b: double) -> bool { return a < b }
@(require_results) lessThan_int :: proc "c" (a, b: int) -> bool { return a < b }
@(require_results) lessThan_uint :: proc "c" (a, b: uint) -> bool { return a < b }
+@(require_results) lessThan_half2 :: proc "c" (a, b: half2) -> bool2 { return {a.x < b.x, a.y < b.y} }
@(require_results) lessThan_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x < b.x, a.y < b.y} }
@(require_results) lessThan_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x < b.x, a.y < b.y} }
@(require_results) lessThan_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x < b.x, a.y < b.y} }
@(require_results) lessThan_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x < b.x, a.y < b.y} }
+@(require_results) lessThan_half3 :: proc "c" (a, b: half3) -> bool3 { return {a.x < b.x, a.y < b.y, a.z < b.z} }
@(require_results) lessThan_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x < b.x, a.y < b.y, a.z < b.z} }
@(require_results) lessThan_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x < b.x, a.y < b.y, a.z < b.z} }
@(require_results) lessThan_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x < b.x, a.y < b.y, a.z < b.z} }
@(require_results) lessThan_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x < b.x, a.y < b.y, a.z < b.z} }
+@(require_results) lessThan_half4 :: proc "c" (a, b: half4) -> bool4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} }
@(require_results) lessThan_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} }
@(require_results) lessThan_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} }
@(require_results) lessThan_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} }
@@ -1258,35 +1684,43 @@ lessThan :: proc{
lessThanEqual :: proc{
+ lessThanEqual_half,
lessThanEqual_float,
lessThanEqual_double,
lessThanEqual_int,
lessThanEqual_uint,
+ lessThanEqual_half2,
lessThanEqual_float2,
lessThanEqual_double2,
lessThanEqual_int2,
lessThanEqual_uint2,
+ lessThanEqual_half3,
lessThanEqual_float3,
lessThanEqual_double3,
lessThanEqual_int3,
lessThanEqual_uint3,
+ lessThanEqual_half4,
lessThanEqual_float4,
lessThanEqual_double4,
lessThanEqual_int4,
lessThanEqual_uint4,
}
+@(require_results) lessThanEqual_half :: proc "c" (a, b: half) -> bool { return a <= b }
@(require_results) lessThanEqual_float :: proc "c" (a, b: float) -> bool { return a <= b }
@(require_results) lessThanEqual_double :: proc "c" (a, b: double) -> bool { return a <= b }
@(require_results) lessThanEqual_int :: proc "c" (a, b: int) -> bool { return a <= b }
@(require_results) lessThanEqual_uint :: proc "c" (a, b: uint) -> bool { return a <= b }
+@(require_results) lessThanEqual_half2 :: proc "c" (a, b: half2) -> bool2 { return {a.x <= b.x, a.y <= b.y} }
@(require_results) lessThanEqual_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x <= b.x, a.y <= b.y} }
@(require_results) lessThanEqual_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x <= b.x, a.y <= b.y} }
@(require_results) lessThanEqual_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x <= b.x, a.y <= b.y} }
@(require_results) lessThanEqual_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x <= b.x, a.y <= b.y} }
+@(require_results) lessThanEqual_half3 :: proc "c" (a, b: half3) -> bool3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} }
@(require_results) lessThanEqual_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} }
@(require_results) lessThanEqual_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} }
@(require_results) lessThanEqual_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} }
@(require_results) lessThanEqual_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} }
+@(require_results) lessThanEqual_half4 :: proc "c" (a, b: half4) -> bool4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} }
@(require_results) lessThanEqual_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} }
@(require_results) lessThanEqual_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} }
@(require_results) lessThanEqual_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} }
@@ -1294,35 +1728,43 @@ lessThanEqual :: proc{
greaterThan :: proc{
+ greaterThan_half,
greaterThan_float,
greaterThan_double,
greaterThan_int,
greaterThan_uint,
+ greaterThan_half2,
greaterThan_float2,
greaterThan_double2,
greaterThan_int2,
greaterThan_uint2,
+ greaterThan_half3,
greaterThan_float3,
greaterThan_double3,
greaterThan_int3,
greaterThan_uint3,
+ greaterThan_half4,
greaterThan_float4,
greaterThan_double4,
greaterThan_int4,
greaterThan_uint4,
}
+@(require_results) greaterThan_half :: proc "c" (a, b: half) -> bool { return a > b }
@(require_results) greaterThan_float :: proc "c" (a, b: float) -> bool { return a > b }
@(require_results) greaterThan_double :: proc "c" (a, b: double) -> bool { return a > b }
@(require_results) greaterThan_int :: proc "c" (a, b: int) -> bool { return a > b }
@(require_results) greaterThan_uint :: proc "c" (a, b: uint) -> bool { return a > b }
+@(require_results) greaterThan_half2 :: proc "c" (a, b: half2) -> bool2 { return {a.x > b.x, a.y > b.y} }
@(require_results) greaterThan_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x > b.x, a.y > b.y} }
@(require_results) greaterThan_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x > b.x, a.y > b.y} }
@(require_results) greaterThan_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x > b.x, a.y > b.y} }
@(require_results) greaterThan_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x > b.x, a.y > b.y} }
+@(require_results) greaterThan_half3 :: proc "c" (a, b: half3) -> bool3 { return {a.x > b.x, a.y > b.y, a.z > b.z} }
@(require_results) greaterThan_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x > b.x, a.y > b.y, a.z > b.z} }
@(require_results) greaterThan_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x > b.x, a.y > b.y, a.z > b.z} }
@(require_results) greaterThan_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x > b.x, a.y > b.y, a.z > b.z} }
@(require_results) greaterThan_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x > b.x, a.y > b.y, a.z > b.z} }
+@(require_results) greaterThan_half4 :: proc "c" (a, b: half4) -> bool4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} }
@(require_results) greaterThan_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} }
@(require_results) greaterThan_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} }
@(require_results) greaterThan_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} }
@@ -1330,35 +1772,43 @@ greaterThan :: proc{
greaterThanEqual :: proc{
+ greaterThanEqual_half,
greaterThanEqual_float,
greaterThanEqual_double,
greaterThanEqual_int,
greaterThanEqual_uint,
+ greaterThanEqual_half2,
greaterThanEqual_float2,
greaterThanEqual_double2,
greaterThanEqual_int2,
greaterThanEqual_uint2,
+ greaterThanEqual_half3,
greaterThanEqual_float3,
greaterThanEqual_double3,
greaterThanEqual_int3,
greaterThanEqual_uint3,
+ greaterThanEqual_half4,
greaterThanEqual_float4,
greaterThanEqual_double4,
greaterThanEqual_int4,
greaterThanEqual_uint4,
}
+@(require_results) greaterThanEqual_half :: proc "c" (a, b: half) -> bool { return a >= b }
@(require_results) greaterThanEqual_float :: proc "c" (a, b: float) -> bool { return a >= b }
@(require_results) greaterThanEqual_double :: proc "c" (a, b: double) -> bool { return a >= b }
@(require_results) greaterThanEqual_int :: proc "c" (a, b: int) -> bool { return a >= b }
@(require_results) greaterThanEqual_uint :: proc "c" (a, b: uint) -> bool { return a >= b }
+@(require_results) greaterThanEqual_half2 :: proc "c" (a, b: half2) -> bool2 { return {a.x >= b.x, a.y >= b.y} }
@(require_results) greaterThanEqual_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x >= b.x, a.y >= b.y} }
@(require_results) greaterThanEqual_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x >= b.x, a.y >= b.y} }
@(require_results) greaterThanEqual_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x >= b.x, a.y >= b.y} }
@(require_results) greaterThanEqual_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x >= b.x, a.y >= b.y} }
+@(require_results) greaterThanEqual_half3 :: proc "c" (a, b: half3) -> bool3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} }
@(require_results) greaterThanEqual_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} }
@(require_results) greaterThanEqual_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} }
@(require_results) greaterThanEqual_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} }
@(require_results) greaterThanEqual_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} }
+@(require_results) greaterThanEqual_half4 :: proc "c" (a, b: half4) -> bool4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} }
@(require_results) greaterThanEqual_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} }
@(require_results) greaterThanEqual_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} }
@(require_results) greaterThanEqual_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} }
@@ -1366,70 +1816,86 @@ greaterThanEqual :: proc{
equal :: proc{
+ equal_half,
equal_float,
equal_double,
equal_int,
equal_uint,
+ equal_half2,
equal_float2,
equal_double2,
equal_int2,
equal_uint2,
+ equal_half3,
equal_float3,
equal_double3,
equal_int3,
equal_uint3,
+ equal_half4,
equal_float4,
equal_double4,
equal_int4,
equal_uint4,
}
+@(require_results) equal_half :: proc "c" (a, b: half) -> bool { return a == b }
@(require_results) equal_float :: proc "c" (a, b: float) -> bool { return a == b }
@(require_results) equal_double :: proc "c" (a, b: double) -> bool { return a == b }
@(require_results) equal_int :: proc "c" (a, b: int) -> bool { return a == b }
@(require_results) equal_uint :: proc "c" (a, b: uint) -> bool { return a == b }
+@(require_results) equal_half2 :: proc "c" (a, b: half2) -> bool2 { return {a.x == b.x, a.y == b.y} }
@(require_results) equal_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x == b.x, a.y == b.y} }
@(require_results) equal_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x == b.x, a.y == b.y} }
@(require_results) equal_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x == b.x, a.y == b.y} }
@(require_results) equal_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x == b.x, a.y == b.y} }
+@(require_results) equal_half3 :: proc "c" (a, b: half3) -> bool3 { return {a.x == b.x, a.y == b.y, a.z == b.z} }
@(require_results) equal_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x == b.x, a.y == b.y, a.z == b.z} }
@(require_results) equal_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x == b.x, a.y == b.y, a.z == b.z} }
@(require_results) equal_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x == b.x, a.y == b.y, a.z == b.z} }
@(require_results) equal_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x == b.x, a.y == b.y, a.z == b.z} }
+@(require_results) equal_half4 :: proc "c" (a, b: half4) -> bool4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} }
@(require_results) equal_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} }
@(require_results) equal_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} }
@(require_results) equal_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} }
@(require_results) equal_uint4 :: proc "c" (a, b: uint4) -> bool4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} }
notEqual :: proc{
+ notEqual_half,
notEqual_float,
notEqual_double,
notEqual_int,
notEqual_uint,
+ notEqual_half2,
notEqual_float2,
notEqual_double2,
notEqual_int2,
notEqual_uint2,
+ notEqual_half3,
notEqual_float3,
notEqual_double3,
notEqual_int3,
notEqual_uint3,
+ notEqual_half4,
notEqual_float4,
notEqual_double4,
notEqual_int4,
notEqual_uint4,
}
+@(require_results) notEqual_half :: proc "c" (a, b: half) -> bool { return a != b }
@(require_results) notEqual_float :: proc "c" (a, b: float) -> bool { return a != b }
@(require_results) notEqual_double :: proc "c" (a, b: double) -> bool { return a != b }
@(require_results) notEqual_int :: proc "c" (a, b: int) -> bool { return a != b }
@(require_results) notEqual_uint :: proc "c" (a, b: uint) -> bool { return a != b }
+@(require_results) notEqual_half2 :: proc "c" (a, b: half2) -> bool2 { return {a.x != b.x, a.y != b.y} }
@(require_results) notEqual_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x != b.x, a.y != b.y} }
@(require_results) notEqual_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x != b.x, a.y != b.y} }
@(require_results) notEqual_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x != b.x, a.y != b.y} }
@(require_results) notEqual_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x != b.x, a.y != b.y} }
+@(require_results) notEqual_half3 :: proc "c" (a, b: half3) -> bool3 { return {a.x != b.x, a.y != b.y, a.z != b.z} }
@(require_results) notEqual_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x != b.x, a.y != b.y, a.z != b.z} }
@(require_results) notEqual_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x != b.x, a.y != b.y, a.z != b.z} }
@(require_results) notEqual_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x != b.x, a.y != b.y, a.z != b.z} }
@(require_results) notEqual_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x != b.x, a.y != b.y, a.z != b.z} }
+@(require_results) notEqual_half4 :: proc "c" (a, b: half4) -> bool4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} }
@(require_results) notEqual_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} }
@(require_results) notEqual_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} }
@(require_results) notEqual_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} }
@@ -1472,6 +1938,10 @@ not :: proc{
+@(require_results) inverse_half1x1 :: proc "c" (m: half1x1) -> half1x1 { return inverse_matrix1x1(m) }
+@(require_results) inverse_half2x2 :: proc "c" (m: half2x2) -> half2x2 { return inverse_matrix2x2(m) }
+@(require_results) inverse_half3x3 :: proc "c" (m: half3x3) -> half3x3 { return inverse_matrix3x3(m) }
+@(require_results) inverse_half4x4 :: proc "c" (m: half4x4) -> half4x4 { return inverse_matrix4x4(m) }
@(require_results) inverse_float1x1 :: proc "c" (m: float1x1) -> float1x1 { return inverse_matrix1x1(m) }
@(require_results) inverse_float2x2 :: proc "c" (m: float2x2) -> float2x2 { return inverse_matrix2x2(m) }
@(require_results) inverse_float3x3 :: proc "c" (m: float3x3) -> float3x3 { return inverse_matrix3x3(m) }
@@ -1482,6 +1952,10 @@ not :: proc{
@(require_results) inverse_double4x4 :: proc "c" (m: double4x4) -> double4x4 { return inverse_matrix4x4(m) }
inverse :: proc{
+ inverse_half1x1,
+ inverse_half2x2,
+ inverse_half3x3,
+ inverse_half4x4,
inverse_float1x1,
inverse_float2x2,
inverse_float3x3,
@@ -1807,12 +2281,176 @@ inverse_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bou
+ashalf :: proc{
+ ashalf_half,
+ ashalf_float,
+ ashalf_double,
+ ashalf_int,
+ ashalf_uint,
+ ashalf_half1x1,
+ ashalf_half2x2,
+ ashalf_half3x3,
+ ashalf_half4x4,
+ ashalf_half1x2,
+ ashalf_half1x3,
+ ashalf_half1x4,
+ ashalf_half2x1,
+ ashalf_half2x3,
+ ashalf_half2x4,
+ ashalf_half3x1,
+ ashalf_half3x2,
+ ashalf_half3x4,
+ ashalf_half4x1,
+ ashalf_half4x2,
+ ashalf_half4x3,
+ ashalf_half2,
+ ashalf_half3,
+ ashalf_half4,
+ ashalf_float1x1,
+ ashalf_float2x2,
+ ashalf_float3x3,
+ ashalf_float4x4,
+ ashalf_float1x2,
+ ashalf_float1x3,
+ ashalf_float1x4,
+ ashalf_float2x1,
+ ashalf_float2x3,
+ ashalf_float2x4,
+ ashalf_float3x1,
+ ashalf_float3x2,
+ ashalf_float3x4,
+ ashalf_float4x1,
+ ashalf_float4x2,
+ ashalf_float4x3,
+ ashalf_float2,
+ ashalf_float3,
+ ashalf_float4,
+ ashalf_int2,
+ ashalf_int3,
+ ashalf_int4,
+ ashalf_uint2,
+ ashalf_uint3,
+ ashalf_uint4,
+ ashalf_bool2,
+ ashalf_bool3,
+ ashalf_bool4,
+ ashalf_double1x1,
+ ashalf_double2x2,
+ ashalf_double3x3,
+ ashalf_double4x4,
+ ashalf_double1x2,
+ ashalf_double1x3,
+ ashalf_double1x4,
+ ashalf_double2x1,
+ ashalf_double2x3,
+ ashalf_double2x4,
+ ashalf_double3x1,
+ ashalf_double3x2,
+ ashalf_double3x4,
+ ashalf_double4x1,
+ ashalf_double4x2,
+ ashalf_double4x3,
+ ashalf_double2,
+ ashalf_double3,
+ ashalf_double4,
+}
+@(require_results) ashalf_half :: proc "c" (v: half) -> half { return half(v) }
+@(require_results) ashalf_float :: proc "c" (v: float) -> half { return half(v) }
+@(require_results) ashalf_double :: proc "c" (v: double) -> half { return half(v) }
+@(require_results) ashalf_int :: proc "c" (v: int) -> half { return half(v) }
+@(require_results) ashalf_uint :: proc "c" (v: uint) -> half { return half(v) }
+@(require_results) ashalf_half1x1 :: proc "c" (v: half1x1) -> half1x1 { return half1x1(v) }
+@(require_results) ashalf_half2x2 :: proc "c" (v: half2x2) -> half2x2 { return half2x2(v) }
+@(require_results) ashalf_half3x3 :: proc "c" (v: half3x3) -> half3x3 { return half3x3(v) }
+@(require_results) ashalf_half4x4 :: proc "c" (v: half4x4) -> half4x4 { return half4x4(v) }
+@(require_results) ashalf_half1x2 :: proc "c" (v: half1x2) -> half1x2 { return half1x2(v) }
+@(require_results) ashalf_half1x3 :: proc "c" (v: half1x3) -> half1x3 { return half1x3(v) }
+@(require_results) ashalf_half1x4 :: proc "c" (v: half1x4) -> half1x4 { return half1x4(v) }
+@(require_results) ashalf_half2x1 :: proc "c" (v: half2x1) -> half2x1 { return half2x1(v) }
+@(require_results) ashalf_half2x3 :: proc "c" (v: half2x3) -> half2x3 { return half2x3(v) }
+@(require_results) ashalf_half2x4 :: proc "c" (v: half2x4) -> half2x4 { return half2x4(v) }
+@(require_results) ashalf_half3x1 :: proc "c" (v: half3x1) -> half3x1 { return half3x1(v) }
+@(require_results) ashalf_half3x2 :: proc "c" (v: half3x2) -> half3x2 { return half3x2(v) }
+@(require_results) ashalf_half3x4 :: proc "c" (v: half3x4) -> half3x4 { return half3x4(v) }
+@(require_results) ashalf_half4x1 :: proc "c" (v: half4x1) -> half4x1 { return half4x1(v) }
+@(require_results) ashalf_half4x2 :: proc "c" (v: half4x2) -> half4x2 { return half4x2(v) }
+@(require_results) ashalf_half4x3 :: proc "c" (v: half4x3) -> half4x3 { return half4x3(v) }
+@(require_results) ashalf_half2 :: proc "c" (v: half2) -> half2 { return half2(v) }
+@(require_results) ashalf_half3 :: proc "c" (v: half3) -> half3 { return half3(v) }
+@(require_results) ashalf_half4 :: proc "c" (v: half4) -> half4 { return half4(v) }
+@(require_results) ashalf_float1x1 :: proc "c" (v: float1x1) -> half1x1 { return half1x1(v) }
+@(require_results) ashalf_float2x2 :: proc "c" (v: float2x2) -> half2x2 { return half2x2(v) }
+@(require_results) ashalf_float3x3 :: proc "c" (v: float3x3) -> half3x3 { return half3x3(v) }
+@(require_results) ashalf_float4x4 :: proc "c" (v: float4x4) -> half4x4 { return half4x4(v) }
+@(require_results) ashalf_float1x2 :: proc "c" (v: float1x2) -> half1x2 { return half1x2(v) }
+@(require_results) ashalf_float1x3 :: proc "c" (v: float1x3) -> half1x3 { return half1x3(v) }
+@(require_results) ashalf_float1x4 :: proc "c" (v: float1x4) -> half1x4 { return half1x4(v) }
+@(require_results) ashalf_float2x1 :: proc "c" (v: float2x1) -> half2x1 { return half2x1(v) }
+@(require_results) ashalf_float2x3 :: proc "c" (v: float2x3) -> half2x3 { return half2x3(v) }
+@(require_results) ashalf_float2x4 :: proc "c" (v: float2x4) -> half2x4 { return half2x4(v) }
+@(require_results) ashalf_float3x1 :: proc "c" (v: float3x1) -> half3x1 { return half3x1(v) }
+@(require_results) ashalf_float3x2 :: proc "c" (v: float3x2) -> half3x2 { return half3x2(v) }
+@(require_results) ashalf_float3x4 :: proc "c" (v: float3x4) -> half3x4 { return half3x4(v) }
+@(require_results) ashalf_float4x1 :: proc "c" (v: float4x1) -> half4x1 { return half4x1(v) }
+@(require_results) ashalf_float4x2 :: proc "c" (v: float4x2) -> half4x2 { return half4x2(v) }
+@(require_results) ashalf_float4x3 :: proc "c" (v: float4x3) -> half4x3 { return half4x3(v) }
+@(require_results) ashalf_float2 :: proc "c" (v: float2) -> half2 { return half2{half(v.x), half(v.y)} }
+@(require_results) ashalf_float3 :: proc "c" (v: float3) -> half3 { return half3{half(v.x), half(v.y), half(v.z)} }
+@(require_results) ashalf_float4 :: proc "c" (v: float4) -> half4 { return half4{half(v.x), half(v.y), half(v.z), half(v.w)} }
+@(require_results) ashalf_int2 :: proc "c" (v: int2) -> half2 { return half2{half(v.x), half(v.y)} }
+@(require_results) ashalf_int3 :: proc "c" (v: int3) -> half3 { return half3{half(v.x), half(v.y), half(v.z)} }
+@(require_results) ashalf_int4 :: proc "c" (v: int4) -> half4 { return half4{half(v.x), half(v.y), half(v.z), half(v.w)} }
+@(require_results) ashalf_uint2 :: proc "c" (v: uint2) -> half2 { return half2{half(v.x), half(v.y)} }
+@(require_results) ashalf_uint3 :: proc "c" (v: uint3) -> half3 { return half3{half(v.x), half(v.y), half(v.z)} }
+@(require_results) ashalf_uint4 :: proc "c" (v: uint4) -> half4 { return half4{half(v.x), half(v.y), half(v.z), half(v.w)} }
+@(require_results) ashalf_bool2 :: proc "c" (v: bool2) -> half2 { return half2{half(int(v.x)), half(int(v.y))} }
+@(require_results) ashalf_bool3 :: proc "c" (v: bool3) -> half3 { return half3{half(int(v.x)), half(int(v.y)), half(int(v.z))} }
+@(require_results) ashalf_bool4 :: proc "c" (v: bool4) -> half4 { return half4{half(int(v.x)), half(int(v.y)), half(int(v.z)), half(int(v.w))} }
+@(require_results) ashalf_double1x1 :: proc "c" (v: double1x1) -> half1x1 { return half1x1(v) }
+@(require_results) ashalf_double2x2 :: proc "c" (v: double2x2) -> half2x2 { return half2x2(v) }
+@(require_results) ashalf_double3x3 :: proc "c" (v: double3x3) -> half3x3 { return half3x3(v) }
+@(require_results) ashalf_double4x4 :: proc "c" (v: double4x4) -> half4x4 { return half4x4(v) }
+@(require_results) ashalf_double1x2 :: proc "c" (v: double1x2) -> half1x2 { return half1x2(v) }
+@(require_results) ashalf_double1x3 :: proc "c" (v: double1x3) -> half1x3 { return half1x3(v) }
+@(require_results) ashalf_double1x4 :: proc "c" (v: double1x4) -> half1x4 { return half1x4(v) }
+@(require_results) ashalf_double2x1 :: proc "c" (v: double2x1) -> half2x1 { return half2x1(v) }
+@(require_results) ashalf_double2x3 :: proc "c" (v: double2x3) -> half2x3 { return half2x3(v) }
+@(require_results) ashalf_double2x4 :: proc "c" (v: double2x4) -> half2x4 { return half2x4(v) }
+@(require_results) ashalf_double3x1 :: proc "c" (v: double3x1) -> half3x1 { return half3x1(v) }
+@(require_results) ashalf_double3x2 :: proc "c" (v: double3x2) -> half3x2 { return half3x2(v) }
+@(require_results) ashalf_double3x4 :: proc "c" (v: double3x4) -> half3x4 { return half3x4(v) }
+@(require_results) ashalf_double4x1 :: proc "c" (v: double4x1) -> half4x1 { return half4x1(v) }
+@(require_results) ashalf_double4x2 :: proc "c" (v: double4x2) -> half4x2 { return half4x2(v) }
+@(require_results) ashalf_double4x3 :: proc "c" (v: double4x3) -> half4x3 { return half4x3(v) }
+@(require_results) ashalf_double2 :: proc "c" (v: double2) -> half2 { return half2{half(v.x), half(v.y)} }
+@(require_results) ashalf_double3 :: proc "c" (v: double3) -> half3 { return half3{half(v.x), half(v.y), half(v.z)} }
+@(require_results) ashalf_double4 :: proc "c" (v: double4) -> half4 { return half4{half(v.x), half(v.y), half(v.z), half(v.w)} }
asfloat :: proc{
+ asfloat_half,
asfloat_float,
asfloat_double,
asfloat_int,
asfloat_uint,
+ asfloat_half1x1,
+ asfloat_half2x2,
+ asfloat_half3x3,
+ asfloat_half4x4,
+ asfloat_half1x2,
+ asfloat_half1x3,
+ asfloat_half1x4,
+ asfloat_half2x1,
+ asfloat_half2x3,
+ asfloat_half2x4,
+ asfloat_half3x1,
+ asfloat_half3x2,
+ asfloat_half3x4,
+ asfloat_half4x1,
+ asfloat_half4x2,
+ asfloat_half4x3,
+ asfloat_half2,
+ asfloat_half3,
+ asfloat_half4,
asfloat_float1x1,
asfloat_float2x2,
asfloat_float3x3,
@@ -1861,10 +2499,30 @@ asfloat :: proc{
asfloat_double3,
asfloat_double4,
}
+@(require_results) asfloat_half :: proc "c" (v: half) -> float { return float(v) }
@(require_results) asfloat_float :: proc "c" (v: float) -> float { return float(v) }
@(require_results) asfloat_double :: proc "c" (v: double) -> float { return float(v) }
@(require_results) asfloat_int :: proc "c" (v: int) -> float { return float(v) }
@(require_results) asfloat_uint :: proc "c" (v: uint) -> float { return float(v) }
+@(require_results) asfloat_half1x1 :: proc "c" (v: half1x1) -> float1x1 { return float1x1(v) }
+@(require_results) asfloat_half2x2 :: proc "c" (v: half2x2) -> float2x2 { return float2x2(v) }
+@(require_results) asfloat_half3x3 :: proc "c" (v: half3x3) -> float3x3 { return float3x3(v) }
+@(require_results) asfloat_half4x4 :: proc "c" (v: half4x4) -> float4x4 { return float4x4(v) }
+@(require_results) asfloat_half1x2 :: proc "c" (v: half1x2) -> float1x2 { return float1x2(v) }
+@(require_results) asfloat_half1x3 :: proc "c" (v: half1x3) -> float1x3 { return float1x3(v) }
+@(require_results) asfloat_half1x4 :: proc "c" (v: half1x4) -> float1x4 { return float1x4(v) }
+@(require_results) asfloat_half2x1 :: proc "c" (v: half2x1) -> float2x1 { return float2x1(v) }
+@(require_results) asfloat_half2x3 :: proc "c" (v: half2x3) -> float2x3 { return float2x3(v) }
+@(require_results) asfloat_half2x4 :: proc "c" (v: half2x4) -> float2x4 { return float2x4(v) }
+@(require_results) asfloat_half3x1 :: proc "c" (v: half3x1) -> float3x1 { return float3x1(v) }
+@(require_results) asfloat_half3x2 :: proc "c" (v: half3x2) -> float3x2 { return float3x2(v) }
+@(require_results) asfloat_half3x4 :: proc "c" (v: half3x4) -> float3x4 { return float3x4(v) }
+@(require_results) asfloat_half4x1 :: proc "c" (v: half4x1) -> float4x1 { return float4x1(v) }
+@(require_results) asfloat_half4x2 :: proc "c" (v: half4x2) -> float4x2 { return float4x2(v) }
+@(require_results) asfloat_half4x3 :: proc "c" (v: half4x3) -> float4x3 { return float4x3(v) }
+@(require_results) asfloat_half2 :: proc "c" (v: half2) -> float2 { return float2{float(v.x), float(v.y)} }
+@(require_results) asfloat_half3 :: proc "c" (v: half3) -> float3 { return float3{float(v.x), float(v.y), float(v.z)} }
+@(require_results) asfloat_half4 :: proc "c" (v: half4) -> float4 { return float4{float(v.x), float(v.y), float(v.z), float(v.w)} }
@(require_results) asfloat_float1x1 :: proc "c" (v: float1x1) -> float1x1 { return float1x1(v) }
@(require_results) asfloat_float2x2 :: proc "c" (v: float2x2) -> float2x2 { return float2x2(v) }
@(require_results) asfloat_float3x3 :: proc "c" (v: float3x3) -> float3x3 { return float3x3(v) }
@@ -1914,10 +2572,30 @@ asfloat :: proc{
@(require_results) asfloat_double4 :: proc "c" (v: double4) -> float4 { return float4{float(v.x), float(v.y), float(v.z), float(v.w)} }
asdouble :: proc{
+ asdouble_half,
asdouble_float,
asdouble_double,
asdouble_int,
asdouble_uint,
+ asdouble_half1x1,
+ asdouble_half2x2,
+ asdouble_half3x3,
+ asdouble_half4x4,
+ asdouble_half1x2,
+ asdouble_half1x3,
+ asdouble_half1x4,
+ asdouble_half2x1,
+ asdouble_half2x3,
+ asdouble_half2x4,
+ asdouble_half3x1,
+ asdouble_half3x2,
+ asdouble_half3x4,
+ asdouble_half4x1,
+ asdouble_half4x2,
+ asdouble_half4x3,
+ asdouble_half2,
+ asdouble_half3,
+ asdouble_half4,
asdouble_float1x1,
asdouble_float2x2,
asdouble_float3x3,
@@ -1966,10 +2644,30 @@ asdouble :: proc{
asdouble_double3,
asdouble_double4,
}
+@(require_results) asdouble_half :: proc "c" (v: half) -> double { return double(v) }
@(require_results) asdouble_float :: proc "c" (v: float) -> double { return double(v) }
@(require_results) asdouble_double :: proc "c" (v: double) -> double { return double(v) }
@(require_results) asdouble_int :: proc "c" (v: int) -> double { return double(v) }
@(require_results) asdouble_uint :: proc "c" (v: uint) -> double { return double(v) }
+@(require_results) asdouble_half1x1 :: proc "c" (v: half1x1) -> double1x1 { return double1x1(v) }
+@(require_results) asdouble_half2x2 :: proc "c" (v: half2x2) -> double2x2 { return double2x2(v) }
+@(require_results) asdouble_half3x3 :: proc "c" (v: half3x3) -> double3x3 { return double3x3(v) }
+@(require_results) asdouble_half4x4 :: proc "c" (v: half4x4) -> double4x4 { return double4x4(v) }
+@(require_results) asdouble_half1x2 :: proc "c" (v: half1x2) -> double1x2 { return double1x2(v) }
+@(require_results) asdouble_half1x3 :: proc "c" (v: half1x3) -> double1x3 { return double1x3(v) }
+@(require_results) asdouble_half1x4 :: proc "c" (v: half1x4) -> double1x4 { return double1x4(v) }
+@(require_results) asdouble_half2x1 :: proc "c" (v: half2x1) -> double2x1 { return double2x1(v) }
+@(require_results) asdouble_half2x3 :: proc "c" (v: half2x3) -> double2x3 { return double2x3(v) }
+@(require_results) asdouble_half2x4 :: proc "c" (v: half2x4) -> double2x4 { return double2x4(v) }
+@(require_results) asdouble_half3x1 :: proc "c" (v: half3x1) -> double3x1 { return double3x1(v) }
+@(require_results) asdouble_half3x2 :: proc "c" (v: half3x2) -> double3x2 { return double3x2(v) }
+@(require_results) asdouble_half3x4 :: proc "c" (v: half3x4) -> double3x4 { return double3x4(v) }
+@(require_results) asdouble_half4x1 :: proc "c" (v: half4x1) -> double4x1 { return double4x1(v) }
+@(require_results) asdouble_half4x2 :: proc "c" (v: half4x2) -> double4x2 { return double4x2(v) }
+@(require_results) asdouble_half4x3 :: proc "c" (v: half4x3) -> double4x3 { return double4x3(v) }
+@(require_results) asdouble_half2 :: proc "c" (v: half2) -> double2 { return double2{double(v.x), double(v.y)} }
+@(require_results) asdouble_half3 :: proc "c" (v: half3) -> double3 { return double3{double(v.x), double(v.y), double(v.z)} }
+@(require_results) asdouble_half4 :: proc "c" (v: half4) -> double4 { return double4{double(v.x), double(v.y), double(v.z), double(v.w)} }
@(require_results) asdouble_float1x1 :: proc "c" (v: float1x1) -> double1x1 { return double1x1(v) }
@(require_results) asdouble_float2x2 :: proc "c" (v: float2x2) -> double2x2 { return double2x2(v) }
@(require_results) asdouble_float3x3 :: proc "c" (v: float3x3) -> double3x3 { return double3x3(v) }
@@ -2019,10 +2717,30 @@ asdouble :: proc{
@(require_results) asdouble_double4 :: proc "c" (v: double4) -> double4 { return double4{double(v.x), double(v.y), double(v.z), double(v.w)} }
asint :: proc{
+ asint_half,
asint_float,
asint_double,
asint_int,
asint_uint,
+ asint_half1x1,
+ asint_half2x2,
+ asint_half3x3,
+ asint_half4x4,
+ asint_half1x2,
+ asint_half1x3,
+ asint_half1x4,
+ asint_half2x1,
+ asint_half2x3,
+ asint_half2x4,
+ asint_half3x1,
+ asint_half3x2,
+ asint_half3x4,
+ asint_half4x1,
+ asint_half4x2,
+ asint_half4x3,
+ asint_half2,
+ asint_half3,
+ asint_half4,
asint_float1x1,
asint_float2x2,
asint_float3x3,
@@ -2071,10 +2789,30 @@ asint :: proc{
asint_double3,
asint_double4,
}
+@(require_results) asint_half :: proc "c" (v: half) -> int { return int(v) }
@(require_results) asint_float :: proc "c" (v: float) -> int { return int(v) }
@(require_results) asint_double :: proc "c" (v: double) -> int { return int(v) }
@(require_results) asint_int :: proc "c" (v: int) -> int { return int(v) }
@(require_results) asint_uint :: proc "c" (v: uint) -> int { return int(v) }
+@(require_results) asint_half1x1 :: proc "c" (v: half1x1) -> int1x1 { return int1x1(v) }
+@(require_results) asint_half2x2 :: proc "c" (v: half2x2) -> int2x2 { return int2x2(v) }
+@(require_results) asint_half3x3 :: proc "c" (v: half3x3) -> int3x3 { return int3x3(v) }
+@(require_results) asint_half4x4 :: proc "c" (v: half4x4) -> int4x4 { return int4x4(v) }
+@(require_results) asint_half1x2 :: proc "c" (v: half1x2) -> int1x2 { return int1x2(v) }
+@(require_results) asint_half1x3 :: proc "c" (v: half1x3) -> int1x3 { return int1x3(v) }
+@(require_results) asint_half1x4 :: proc "c" (v: half1x4) -> int1x4 { return int1x4(v) }
+@(require_results) asint_half2x1 :: proc "c" (v: half2x1) -> int2x1 { return int2x1(v) }
+@(require_results) asint_half2x3 :: proc "c" (v: half2x3) -> int2x3 { return int2x3(v) }
+@(require_results) asint_half2x4 :: proc "c" (v: half2x4) -> int2x4 { return int2x4(v) }
+@(require_results) asint_half3x1 :: proc "c" (v: half3x1) -> int3x1 { return int3x1(v) }
+@(require_results) asint_half3x2 :: proc "c" (v: half3x2) -> int3x2 { return int3x2(v) }
+@(require_results) asint_half3x4 :: proc "c" (v: half3x4) -> int3x4 { return int3x4(v) }
+@(require_results) asint_half4x1 :: proc "c" (v: half4x1) -> int4x1 { return int4x1(v) }
+@(require_results) asint_half4x2 :: proc "c" (v: half4x2) -> int4x2 { return int4x2(v) }
+@(require_results) asint_half4x3 :: proc "c" (v: half4x3) -> int4x3 { return int4x3(v) }
+@(require_results) asint_half2 :: proc "c" (v: half2) -> int2 { return int2{int(v.x), int(v.y)} }
+@(require_results) asint_half3 :: proc "c" (v: half3) -> int3 { return int3{int(v.x), int(v.y), int(v.z)} }
+@(require_results) asint_half4 :: proc "c" (v: half4) -> int4 { return int4{int(v.x), int(v.y), int(v.z), int(v.w)} }
@(require_results) asint_float1x1 :: proc "c" (v: float1x1) -> int1x1 { return int1x1(v) }
@(require_results) asint_float2x2 :: proc "c" (v: float2x2) -> int2x2 { return int2x2(v) }
@(require_results) asint_float3x3 :: proc "c" (v: float3x3) -> int3x3 { return int3x3(v) }
@@ -2125,10 +2863,14 @@ asint :: proc{
asuint :: proc{
+ asuint_half,
asuint_float,
asuint_double,
asuint_int,
asuint_uint,
+ asuint_half2,
+ asuint_half3,
+ asuint_half4,
asuint_float2,
asuint_float3,
asuint_float4,
@@ -2145,10 +2887,14 @@ asuint :: proc{
asuint_double3,
asuint_double4,
}
+@(require_results) asuint_half :: proc "c" (v: half) -> uint { return uint(v) }
@(require_results) asuint_float :: proc "c" (v: float) -> uint { return uint(v) }
@(require_results) asuint_double :: proc "c" (v: double) -> uint { return uint(v) }
@(require_results) asuint_int :: proc "c" (v: int) -> uint { return uint(v) }
@(require_results) asuint_uint :: proc "c" (v: uint) -> uint { return uint(v) }
+@(require_results) asuint_half2 :: proc "c" (v: half2) -> uint2 { return uint2{uint(v.x), uint(v.y)} }
+@(require_results) asuint_half3 :: proc "c" (v: half3) -> uint3 { return uint3{uint(v.x), uint(v.y), uint(v.z)} }
+@(require_results) asuint_half4 :: proc "c" (v: half4) -> uint4 { return uint4{uint(v.x), uint(v.y), uint(v.z), uint(v.w)} }
@(require_results) asuint_float2 :: proc "c" (v: float2) -> uint2 { return uint2{uint(v.x), uint(v.y)} }
@(require_results) asuint_float3 :: proc "c" (v: float3) -> uint3 { return uint3{uint(v.x), uint(v.y), uint(v.z)} }
@(require_results) asuint_float4 :: proc "c" (v: float4) -> uint4 { return uint4{uint(v.x), uint(v.y), uint(v.z), uint(v.w)} }
diff --git a/core/math/linalg/hlsl/linalg_hlsl_math.odin b/core/math/linalg/hlsl/linalg_hlsl_math.odin
index 5b8004342..92c741f03 100644
--- a/core/math/linalg/hlsl/linalg_hlsl_math.odin
+++ b/core/math/linalg/hlsl/linalg_hlsl_math.odin
@@ -2,6 +2,42 @@ package math_linalg_hlsl
import "core:math"
+@(require_results) cos_half :: proc "c" (x: half) -> half { return math.cos(x) }
+@(require_results) sin_half :: proc "c" (x: half) -> half { return math.sin(x) }
+@(require_results) tan_half :: proc "c" (x: half) -> half { return math.tan(x) }
+@(require_results) acos_half :: proc "c" (x: half) -> half { return math.acos(x) }
+@(require_results) asin_half :: proc "c" (x: half) -> half { return math.asin(x) }
+@(require_results) atan_half :: proc "c" (x: half) -> half { return math.atan(x) }
+@(require_results) atan2_half :: proc "c" (y, x: half) -> half { return math.atan2(y, x) }
+@(require_results) cosh_half :: proc "c" (x: half) -> half { return math.cosh(x) }
+@(require_results) sinh_half :: proc "c" (x: half) -> half { return math.sinh(x) }
+@(require_results) tanh_half :: proc "c" (x: half) -> half { return math.tanh(x) }
+@(require_results) acosh_half :: proc "c" (x: half) -> half { return math.acosh(x) }
+@(require_results) asinh_half :: proc "c" (x: half) -> half { return math.asinh(x) }
+@(require_results) atanh_half :: proc "c" (x: half) -> half { return math.atanh(x) }
+@(require_results) sqrt_half :: proc "c" (x: half) -> half { return math.sqrt(x) }
+@(require_results) rsqrt_half :: proc "c" (x: half) -> half { return 1.0/math.sqrt(x) }
+@(require_results) rcp_half :: proc "c" (x: half) -> half { return 1.0/x }
+@(require_results) pow_half :: proc "c" (x, y: half) -> half { return math.pow(x, y) }
+@(require_results) exp_half :: proc "c" (x: half) -> half { return math.exp(x) }
+@(require_results) log_half :: proc "c" (x: half) -> half { return math.ln(x) }
+@(require_results) log2_half :: proc "c" (x: half) -> half { return math.log(x, 2) }
+@(require_results) log10_half :: proc "c" (x: half) -> half { return math.log(x, 10) }
+@(require_results) exp2_half :: proc "c" (x: half) -> half { return math.pow(half(2), x) }
+@(require_results) sign_half :: proc "c" (x: half) -> half { return math.sign(x) }
+@(require_results) floor_half :: proc "c" (x: half) -> half { return math.floor(x) }
+@(require_results) round_half :: proc "c" (x: half) -> half { return math.round(x) }
+@(require_results) ceil_half :: proc "c" (x: half) -> half { return math.ceil(x) }
+@(require_results) isnan_half :: proc "c" (x: half) -> bool { return math.classify(x) == .NaN}
+@(require_results) fmod_half :: proc "c" (x, y: half) -> half { return math.mod(x, y) }
+@(require_results)
+frac_half :: proc "c" (x: half) -> half {
+ if x >= 0 {
+ return x - math.trunc(x)
+ }
+ return math.trunc(-x) + x
+}
+
@(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) }
diff --git a/core/math/rand/rand.odin b/core/math/rand/rand.odin
index 8e270b7df..e8383ca9e 100644
--- a/core/math/rand/rand.odin
+++ b/core/math/rand/rand.odin
@@ -208,7 +208,7 @@ Inputs:
Returns:
- val: A random 31 bit value in the range `[0, n)`
-WARNING: Panics if n is less than 0
+WARNING: Panics if n is less than or equal to 0
Example:
import "core:math/rand"
@@ -249,7 +249,7 @@ Inputs:
Returns:
- val: A random 63 bit value in the range `[0, n)`
-WARNING: Panics if n is less than 0
+WARNING: Panics if n is less than or equal to 0
Example:
import "core:math/rand"
@@ -290,7 +290,7 @@ Inputs:
Returns:
- val: A random 127 bit value in the range `[0, n)`
-WARNING: Panics if n is less than 0
+WARNING: Panics if n is less than or equal to 0
Example:
import "core:math/rand"
@@ -331,7 +331,7 @@ Inputs:
Returns:
- val: A random integer value in the range `[0, n)`
-WARNING: Panics if n is less than 0
+WARNING: Panics if n is less than or equal to 0
Example:
import "core:math/rand"
diff --git a/core/mem/mem.odin b/core/mem/mem.odin
index 96ec1990a..8ce48d489 100644
--- a/core/mem/mem.odin
+++ b/core/mem/mem.odin
@@ -332,7 +332,7 @@ and returns an integer count of the `T` between them.
- `b`: A pointer to a type T
**Returns**
-- `b` - `a` in items of T as an `int`.
+- `a` - `b` in items of T as an `int`.
Example:
@@ -704,4 +704,4 @@ calc_padding_with_header :: proc "contextless" (ptr: uintptr, align: uintptr, he
}
}
return int(padding)
-} \ No newline at end of file
+}
diff --git a/core/odin/parser/parser.odin b/core/odin/parser/parser.odin
index 7ebe275ed..9ce484a10 100644
--- a/core/odin/parser/parser.odin
+++ b/core/odin/parser/parser.odin
@@ -3210,6 +3210,17 @@ parse_call_expr :: proc(p: ^Parser, operand: ^ast.Expr) -> ^ast.Expr {
return ce
}
+empty_selector_expr :: proc(tok: tokenizer.Token, operand: ^ast.Expr) -> ^ast.Selector_Expr {
+ field := ast.new(ast.Ident, tok.pos, end_pos(tok))
+ field.name = ""
+
+ sel := ast.new(ast.Selector_Expr, operand.pos, field)
+ sel.expr = operand
+ sel.op = tok
+ sel.field = field
+
+ return sel
+}
parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^ast.Expr) {
operand = value
@@ -3343,8 +3354,7 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a
case:
error(p, p.curr_tok.pos, "expected a selector")
- advance_token(p)
- operand = ast.new(ast.Bad_Expr, operand.pos, end_pos(tok))
+ operand = empty_selector_expr(tok, operand)
}
case .Arrow_Right:
@@ -3361,8 +3371,7 @@ parse_atom_expr :: proc(p: ^Parser, value: ^ast.Expr, lhs: bool) -> (operand: ^a
operand = sel
case:
error(p, p.curr_tok.pos, "expected a selector")
- advance_token(p)
- operand = ast.new(ast.Bad_Expr, operand.pos, end_pos(tok))
+ operand = empty_selector_expr(tok, operand)
}
case .Pointer:
diff --git a/core/os/os2/dir.odin b/core/os/os2/dir.odin
index 10b06a8ce..f63754273 100644
--- a/core/os/os2/dir.odin
+++ b/core/os/os2/dir.odin
@@ -6,6 +6,10 @@ import "core:strings"
read_dir :: read_directory
+/*
+ Reads the file `f` (assuming it is a directory) and returns the unsorted directory entries.
+ This returns up to `n` entries OR all of them if `n <= 0`.
+*/
@(require_results)
read_directory :: proc(f: ^File, n: int, allocator: runtime.Allocator) -> (files: []File_Info, err: Error) {
if f == nil {
@@ -47,11 +51,18 @@ read_directory :: proc(f: ^File, n: int, allocator: runtime.Allocator) -> (files
}
+/*
+ Reads the file `f` (assuming it is a directory) and returns all of the unsorted directory entries.
+*/
@(require_results)
read_all_directory :: proc(f: ^File, allocator: runtime.Allocator) -> (fi: []File_Info, err: Error) {
return read_directory(f, -1, allocator)
}
+/*
+ Reads the named directory by path (assuming it is a directory) and returns the unsorted directory entries.
+ This returns up to `n` entries OR all of them if `n <= 0`.
+*/
@(require_results)
read_directory_by_path :: proc(path: string, n: int, allocator: runtime.Allocator) -> (fi: []File_Info, err: Error) {
f := open(path) or_return
@@ -59,6 +70,9 @@ read_directory_by_path :: proc(path: string, n: int, allocator: runtime.Allocato
return read_directory(f, n, allocator)
}
+/*
+ Reads the named directory by path (assuming it is a directory) and returns all of the unsorted directory entries.
+*/
@(require_results)
read_all_directory_by_path :: proc(path: string, allocator: runtime.Allocator) -> (fi: []File_Info, err: Error) {
return read_directory_by_path(path, -1, allocator)
diff --git a/core/os/os2/dir_windows.odin b/core/os/os2/dir_windows.odin
index 6c754a677..a4dadca75 100644
--- a/core/os/os2/dir_windows.odin
+++ b/core/os/os2/dir_windows.odin
@@ -18,7 +18,7 @@ find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW, al
temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator })
path := concatenate({base_path, `\`, win32_wstring_to_utf8(cstring16(raw_data(d.cFileName[:])), temp_allocator) or_else ""}, allocator) or_return
- handle := win32.HANDLE(_open_internal(path, {.Read}, 0o666) or_else 0)
+ handle := win32.HANDLE(_open_internal(path, {.Read}, Permissions_Read_Write_All) or_else 0)
defer win32.CloseHandle(handle)
fi.fullpath = path
diff --git a/core/os/os2/errors.odin b/core/os/os2/errors.odin
index 1cf7d765c..077697c0d 100644
--- a/core/os/os2/errors.odin
+++ b/core/os/os2/errors.odin
@@ -3,6 +3,10 @@ package os2
import "core:io"
import "base:runtime"
+/*
+ General errors that are common within this package which cannot
+ be categorized by `io.Error` nor `runtime.Allocator_Error`.
+*/
General_Error :: enum u32 {
None,
@@ -33,8 +37,12 @@ General_Error :: enum u32 {
Unsupported,
}
+// A platform specific error
Platform_Error :: _Platform_Error
+/*
+ `Error` is a union of different classes of errors that could be returned from procedures in this package.
+*/
Error :: union #shared_nil {
General_Error,
io.Error,
@@ -46,6 +54,7 @@ Error :: union #shared_nil {
ERROR_NONE :: Error{}
+// Attempts to convert an `Error` into a platform specific error as an integer. `ok` is false if not possible
@(require_results)
is_platform_error :: proc(ferr: Error) -> (err: i32, ok: bool) {
v := ferr.(Platform_Error) or_else {}
@@ -53,6 +62,7 @@ is_platform_error :: proc(ferr: Error) -> (err: i32, ok: bool) {
}
+// Attempts to return the error `ferr` as a string without any allocation
@(require_results)
error_string :: proc(ferr: Error) -> string {
if ferr == nil {
@@ -112,6 +122,9 @@ error_string :: proc(ferr: Error) -> string {
return "unknown error"
}
+/*
+ `print_error` is a utility procedure which will print an error `ferr` to a specified file `f`.
+*/
print_error :: proc(f: ^File, ferr: Error, msg: string) {
temp_allocator := TEMP_ALLOCATOR_GUARD({})
err_str := error_string(ferr)
@@ -127,3 +140,14 @@ print_error :: proc(f: ^File, ferr: Error, msg: string) {
buf[length - 1] = '\n'
write(f, buf)
}
+
+
+
+// Attempts to convert an `Error` `ferr` into an `io.Error`
+@(private)
+error_to_io_error :: proc(ferr: Error) -> io.Error {
+ if ferr == nil {
+ return .None
+ }
+ return ferr.(io.Error) or_else .Unknown
+}
diff --git a/core/os/os2/file.odin b/core/os/os2/file.odin
index a9878a563..85ebfcece 100644
--- a/core/os/os2/file.odin
+++ b/core/os/os2/file.odin
@@ -56,6 +56,7 @@ File_Type :: enum {
Character_Device,
}
+// Represents the file flags for a file handle
File_Flags :: distinct bit_set[File_Flag; uint]
File_Flag :: enum {
Read,
@@ -90,17 +91,77 @@ O_SPARSE :: File_Flags{.Sparse}
*/
O_INHERITABLE :: File_Flags{.Inheritable}
+Permissions :: distinct bit_set[Permission_Flag; u32]
+Permission_Flag :: enum u32 {
+ Execute_Other = 0,
+ Write_Other = 1,
+ Read_Other = 2,
+
+ Execute_Group = 3,
+ Write_Group = 4,
+ Read_Group = 5,
+
+ Execute_User = 6,
+ Write_User = 7,
+ Read_User = 8,
+}
+
+Permissions_Execute_All :: Permissions{.Execute_User, .Execute_Group, .Execute_Other}
+Permissions_Write_All :: Permissions{.Write_User, .Write_Group, .Write_Other}
+Permissions_Read_All :: Permissions{.Read_User, .Read_Group, .Read_Other}
+
+Permissions_Read_Write_All :: Permissions_Read_All + Permissions_Write_All
+
+Permissions_All :: Permissions_Read_All + Permissions_Write_All + Permissions_Execute_All
+
+Permissions_Default_File :: Permissions_Read_All + Permissions_Write_All
+Permissions_Default_Directory :: Permissions_Read_All + Permissions_Write_All + Permissions_Execute_All
+Permissions_Default :: Permissions_Default_Directory
+
+perm :: proc{
+ perm_number,
+}
+
+/*
+ `perm_number` converts an integer value `perm` to the bit set `Permissions`
+*/
+@(require_results)
+perm_number :: proc "contextless" (perm: int) -> Permissions {
+ return transmute(Permissions)u32(perm & 0o777)
+}
+
+
+
+// `stdin` is an open file pointing to the standard input file stream
stdin: ^File = nil // OS-Specific
+
+// `stdout` is an open file pointing to the standard output file stream
stdout: ^File = nil // OS-Specific
+
+// `stderr` is an open file pointing to the standard error file stream
stderr: ^File = nil // OS-Specific
+/*
+ `create` creates or truncates a named file `name`.
+ If the file already exists, it is truncated.
+ If the file does not exist, it is created with the `Permissions_Default_File` permissions.
+ If successful, a `^File` is return which can be used for I/O.
+ And error is returned if any is encountered.
+*/
@(require_results)
create :: proc(name: string) -> (^File, Error) {
- return open(name, {.Read, .Write, .Create}, 0o777)
+ return open(name, {.Read, .Write, .Create, .Trunc}, Permissions_Default_File)
}
+/*
+ `open` is a generalized open call, which defaults to opening for reading.
+ If the file does not exist, and the `{.Create}` flag is passed, it is created with the permissions `perm`,
+ and please note that the containing directory must exist otherwise and an error will be returned.
+ If successful, a `^File` is return which can be used for I/O.
+ And error is returned if any is encountered.
+*/
@(require_results)
-open :: proc(name: string, flags := File_Flags{.Read}, perm := 0o777) -> (^File, Error) {
+open :: proc(name: string, flags := File_Flags{.Read}, perm := Permissions_Default) -> (^File, Error) {
return _open(name, flags, perm)
}
@@ -112,7 +173,10 @@ open :: proc(name: string, flags := File_Flags{.Read}, perm := 0o777) -> (^File,
// return _open_buffered(name, buffer_size, flags, perm)
// }
-
+/*
+ `new_file` returns a new `^File` with the given file descriptor `handle` and `name`.
+ The return value will only be `nil` IF the `handle` is not a valid file descriptor.
+*/
@(require_results)
new_file :: proc(handle: uintptr, name: string) -> ^File {
file, err := _new_file(handle, name, file_allocator())
@@ -122,16 +186,25 @@ new_file :: proc(handle: uintptr, name: string) -> ^File {
return file
}
+/*
+ `clone` returns a new `^File` based on the passed file `f` with the same underlying file descriptor.
+*/
@(require_results)
clone :: proc(f: ^File) -> (^File, Error) {
return _clone(f)
}
+/*
+ `fd` returns the file descriptor of the file `f` passed. If the file is not valid, an invalid handle will be returned.
+*/
@(require_results)
fd :: proc(f: ^File) -> uintptr {
return _fd(f)
}
+/*
+ `name` returns the name of the file. The lifetime of this string lasts as long as the file handle itself.
+*/
@(require_results)
name :: proc(f: ^File) -> string {
return _name(f)
@@ -150,6 +223,16 @@ close :: proc(f: ^File) -> Error {
return nil
}
+/*
+ seek sets the offsets for the next read or write on a file to a specified `offset`,
+ according to what `whence` is set.
+ `.Start` is relative to the origin of the file.
+ `.Current` is relative to the current offset.
+ `.End` is relative to the end.
+ It returns the new offset and an error, if any is encountered.
+ Prefer `read_at` or `write_at` if the offset does not want to be changed.
+
+*/
seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Error) {
if f != nil {
return io.seek(f.stream, offset, whence)
@@ -157,6 +240,11 @@ seek :: proc(f: ^File, offset: i64, whence: io.Seek_From) -> (ret: i64, err: Err
return 0, .Invalid_File
}
+/*
+ `read` reads up to len(p) bytes from the file `f`, and then stores them in `p`.
+ It returns the number of bytes read and an error, if any is encountered.
+ At the end of a file, it returns `0, io.EOF`.
+*/
read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
if f != nil {
return io.read(f.stream, p)
@@ -164,6 +252,12 @@ read :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
return 0, .Invalid_File
}
+/*
+ `read_at` reads up to len(p) bytes from the file `f` at the byte offset `offset`, and then stores them in `p`.
+ It returns the number of bytes read and an error, if any is encountered.
+ `read_at` always returns a non-nil error when `n < len(p)`.
+ At the end of a file, the error is `io.EOF`.
+*/
read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
if f != nil {
return io.read_at(f.stream, p, offset)
@@ -171,6 +265,11 @@ read_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
return 0, .Invalid_File
}
+/*
+ `write` writes `len(p)` bytes from `p` to the file `f`. It returns the number of bytes written to
+ and an error, if any is encountered.
+ `write` returns a non-nil error when `n != len(p)`.
+*/
write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
if f != nil {
return io.write(f.stream, p)
@@ -178,6 +277,11 @@ write :: proc(f: ^File, p: []byte) -> (n: int, err: Error) {
return 0, .Invalid_File
}
+/*
+ `write_at` writes `len(p)` bytes from `p` to the file `f` starting at byte offset `offset`.
+ It returns the number of bytes written to and an error, if any is encountered.
+ `write_at` returns a non-nil error when `n != len(p)`.
+*/
write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
if f != nil {
return io.write_at(f.stream, p, offset)
@@ -185,6 +289,9 @@ write_at :: proc(f: ^File, p: []byte, offset: i64) -> (n: int, err: Error) {
return 0, .Invalid_File
}
+/*
+ `file_size` returns the length of the file `f` in bytes and an error, if any is encountered.
+*/
file_size :: proc(f: ^File) -> (n: i64, err: Error) {
if f != nil {
return io.size(f.stream)
@@ -192,6 +299,9 @@ file_size :: proc(f: ^File) -> (n: i64, err: Error) {
return 0, .Invalid_File
}
+/*
+ `flush` flushes a file `f`
+*/
flush :: proc(f: ^File) -> Error {
if f != nil {
return io.flush(f.stream)
@@ -199,31 +309,54 @@ flush :: proc(f: ^File) -> Error {
return nil
}
+/*
+ `sync` commits the current contents of the file `f` to stable storage.
+ This usually means flushing the file system's in-memory copy to disk.
+*/
sync :: proc(f: ^File) -> Error {
return _sync(f)
}
+/*
+ `truncate` changes the size of the file `f` to `size` in bytes.
+ This can be used to shorten or lengthen a file.
+ It does not change the "offset" of the file.
+*/
truncate :: proc(f: ^File, size: i64) -> Error {
return _truncate(f, size)
}
+/*
+ `remove` removes a named file or (empty) directory.
+*/
remove :: proc(name: string) -> Error {
return _remove(name)
}
+/*
+ `rename` renames (moves) `old_path` to `new_path`.
+*/
rename :: proc(old_path, new_path: string) -> Error {
return _rename(old_path, new_path)
}
-
+/*
+ `link` creates a `new_name` as a hard link to the `old_name` file.
+*/
link :: proc(old_name, new_name: string) -> Error {
return _link(old_name, new_name)
}
+/*
+ `symlink` creates a `new_name` as a symbolic link to the `old_name` file.
+*/
symlink :: proc(old_name, new_name: string) -> Error {
return _symlink(old_name, new_name)
}
+/*
+ `read_link` returns the destinction of the named symbolic link `name`.
+*/
read_link :: proc(name: string, allocator: runtime.Allocator) -> (string, Error) {
return _read_link(name,allocator)
}
@@ -231,36 +364,65 @@ read_link :: proc(name: string, allocator: runtime.Allocator) -> (string, Error)
chdir :: change_directory
+/*
+ Changes the current working directory to the named directory.
+*/
change_directory :: proc(name: string) -> Error {
return _chdir(name)
}
chmod :: change_mode
-change_mode :: proc(name: string, mode: int) -> Error {
+/*
+ Changes the mode/permissions of the named file to `mode`.
+ If the file is a symbolic link, it changes the mode of the link's target.
+
+ On Windows, only `{.Write_User}` of `mode` is used, and controls whether or not
+ the file has a read-only attribute. Use `{.Read_User}` for a read-only file and
+ `{.Read_User, .Write_User}` for a readable & writable file.
+*/
+change_mode :: proc(name: string, mode: Permissions) -> Error {
return _chmod(name, mode)
}
chown :: change_owner
+/*
+ Changes the numeric `uid` and `gid` of a named file. If the file is a symbolic link,
+ it changes the `uid` and `gid` of the link's target.
+
+ On Windows, it always returns an error.
+*/
change_owner :: proc(name: string, uid, gid: int) -> Error {
return _chown(name, uid, gid)
}
fchdir :: fchange_directory
+/*
+ Changes the current working directory to the file, which must be a directory.
+*/
fchange_directory :: proc(f: ^File) -> Error {
return _fchdir(f)
}
fchmod :: fchange_mode
-fchange_mode :: proc(f: ^File, mode: int) -> Error {
+/*
+ Changes the current `mode` permissions of the file `f`.
+*/
+fchange_mode :: proc(f: ^File, mode: Permissions) -> Error {
return _fchmod(f, mode)
}
fchown :: fchange_owner
+/*
+ Changes the numeric `uid` and `gid` of the file `f`. If the file is a symbolic link,
+ it changes the `uid` and `gid` of the link's target.
+
+ On Windows, it always returns an error.
+*/
fchange_owner :: proc(f: ^File, uid, gid: int) -> Error {
return _fchown(f, uid, gid)
}
@@ -268,27 +430,45 @@ fchange_owner :: proc(f: ^File, uid, gid: int) -> Error {
lchown :: change_owner_do_not_follow_links
+/*
+ Changes the numeric `uid` and `gid` of the file `f`. If the file is a symbolic link,
+ it changes the `uid` and `gid` of the lin itself.
+
+ On Windows, it always returns an error.
+*/
change_owner_do_not_follow_links :: proc(name: string, uid, gid: int) -> Error {
return _lchown(name, uid, gid)
}
chtimes :: change_times
+/*
+ Changes the access `atime` and modification `mtime` times of a named file.
+*/
change_times :: proc(name: string, atime, mtime: time.Time) -> Error {
return _chtimes(name, atime, mtime)
}
fchtimes :: fchange_times
+/*
+ Changes the access `atime` and modification `mtime` times of the file `f`.
+*/
fchange_times :: proc(f: ^File, atime, mtime: time.Time) -> Error {
return _fchtimes(f, atime, mtime)
}
+/*
+ `exists` returns whether or not a named file exists.
+*/
@(require_results)
exists :: proc(path: string) -> bool {
return _exists(path)
}
+/*
+ `is_file` returns whether or not the type of a named file is a `File_Type.Regular` file.
+*/
@(require_results)
is_file :: proc(path: string) -> bool {
temp_allocator := TEMP_ALLOCATOR_GUARD({})
@@ -301,6 +481,9 @@ is_file :: proc(path: string) -> bool {
is_dir :: is_directory
+/*
+ Returns whether or not the type of a named file is a `File_Type.Directory` file.
+*/
@(require_results)
is_directory :: proc(path: string) -> bool {
temp_allocator := TEMP_ALLOCATOR_GUARD({})
@@ -311,7 +494,9 @@ is_directory :: proc(path: string) -> bool {
return fi.type == .Directory
}
-
+/*
+ `copy_file` copies a file from `src_path` to `dst_path` and returns an error if any was encountered.
+*/
copy_file :: proc(dst_path, src_path: string) -> Error {
when #defined(_copy_file_native) {
return _copy_file_native(dst_path, src_path)
@@ -331,7 +516,7 @@ _copy_file :: proc(dst_path, src_path: string) -> Error {
return .Invalid_File
}
- dst := open(dst_path, {.Read, .Write, .Create, .Trunc}, info.mode & 0o777) or_return
+ dst := open(dst_path, {.Read, .Write, .Create, .Trunc}, info.mode & Permissions_All) or_return
defer close(dst)
_, err := io.copy(to_writer(dst), to_reader(src))
diff --git a/core/os/os2/file_linux.odin b/core/os/os2/file_linux.odin
index 85f639c8b..b2350d9b5 100644
--- a/core/os/os2/file_linux.odin
+++ b/core/os/os2/file_linux.odin
@@ -65,7 +65,7 @@ _standard_stream_init :: proc "contextless" () {
stderr = new_std(&files[2], 2, "/proc/self/fd/2")
}
-_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) {
+_open :: proc(name: string, flags: File_Flags, perm: Permissions) -> (f: ^File, err: Error) {
temp_allocator := TEMP_ALLOCATOR_GUARD({})
name_cstr := clone_to_cstring(name, temp_allocator) or_return
@@ -88,7 +88,7 @@ _open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Err
if .Trunc in flags { sys_flags += {.TRUNC} }
if .Inheritable in flags { sys_flags -= {.CLOEXEC} }
- fd, errno := linux.open(name_cstr, sys_flags, transmute(linux.Mode)u32(perm))
+ fd, errno := linux.open(name_cstr, sys_flags, transmute(linux.Mode)transmute(u32)perm)
if errno != .NONE {
return nil, _get_platform_error(errno)
}
@@ -132,7 +132,7 @@ _clone :: proc(f: ^File) -> (clone: ^File, err: Error) {
@(require_results)
-_open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm := 0o777) -> (f: ^File, err: Error) {
+_open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm: Permissions) -> (f: ^File, err: Error) {
assert(buffer_size > 0)
f, err = _open(name, flags, perm)
if f != nil && err == nil {
@@ -369,15 +369,15 @@ _fchdir :: proc(f: ^File) -> Error {
return _get_platform_error(linux.fchdir(impl.fd))
}
-_chmod :: proc(name: string, mode: int) -> Error {
+_chmod :: proc(name: string, mode: Permissions) -> Error {
temp_allocator := TEMP_ALLOCATOR_GUARD({})
name_cstr := clone_to_cstring(name, temp_allocator) or_return
- return _get_platform_error(linux.chmod(name_cstr, transmute(linux.Mode)(u32(mode))))
+ return _get_platform_error(linux.chmod(name_cstr, transmute(linux.Mode)transmute(u32)mode))
}
-_fchmod :: proc(f: ^File, mode: int) -> Error {
+_fchmod :: proc(f: ^File, mode: Permissions) -> Error {
impl := (^File_Impl)(f.impl)
- return _get_platform_error(linux.fchmod(impl.fd, transmute(linux.Mode)(u32(mode))))
+ return _get_platform_error(linux.fchmod(impl.fd, transmute(linux.Mode)transmute(u32)mode))
}
// NOTE: will throw error without super user priviledges
diff --git a/core/os/os2/file_posix.odin b/core/os/os2/file_posix.odin
index a251a3ae7..fd409b9d4 100644
--- a/core/os/os2/file_posix.odin
+++ b/core/os/os2/file_posix.odin
@@ -46,7 +46,7 @@ init_std_files :: proc "contextless" () {
stderr = new_std(&files[2], posix.STDERR_FILENO, "/dev/stderr")
}
-_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) {
+_open :: proc(name: string, flags: File_Flags, perm: Permissions) -> (f: ^File, err: Error) {
if name == "" {
err = .Invalid_Path
return
@@ -72,7 +72,7 @@ _open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Err
temp_allocator := TEMP_ALLOCATOR_GUARD({})
cname := clone_to_cstring(name, temp_allocator) or_return
- fd := posix.open(cname, sys_flags, transmute(posix.mode_t)posix._mode_t(perm))
+ fd := posix.open(cname, sys_flags, transmute(posix.mode_t)posix._mode_t(transmute(u32)perm))
if fd < 0 {
err = _get_platform_error()
return
@@ -284,17 +284,17 @@ _fchdir :: proc(f: ^File) -> Error {
return nil
}
-_fchmod :: proc(f: ^File, mode: int) -> Error {
- if posix.fchmod(__fd(f), transmute(posix.mode_t)posix._mode_t(mode)) != .OK {
+_fchmod :: proc(f: ^File, mode: Permissions) -> Error {
+ if posix.fchmod(__fd(f), transmute(posix.mode_t)posix._mode_t(transmute(u32)mode)) != .OK {
return _get_platform_error()
}
return nil
}
-_chmod :: proc(name: string, mode: int) -> (err: Error) {
+_chmod :: proc(name: string, mode: Permissions) -> (err: Error) {
temp_allocator := TEMP_ALLOCATOR_GUARD({})
cname := clone_to_cstring(name, temp_allocator) or_return
- if posix.chmod(cname, transmute(posix.mode_t)posix._mode_t(mode)) != .OK {
+ if posix.chmod(cname, transmute(posix.mode_t)posix._mode_t(transmute(u32)mode)) != .OK {
return _get_platform_error()
}
return nil
diff --git a/core/os/os2/file_posix_other.odin b/core/os/os2/file_posix_other.odin
index d2946098b..8871a0062 100644
--- a/core/os/os2/file_posix_other.odin
+++ b/core/os/os2/file_posix_other.odin
@@ -8,7 +8,7 @@ import "core:sys/posix"
_posix_absolute_path :: proc(fd: posix.FD, name: string, allocator: runtime.Allocator) -> (path: cstring, err: Error) {
temp_allocator := TEMP_ALLOCATOR_GUARD({ allocator })
- cname := clone_to_cstring(name, temp_allocator)
+ cname := clone_to_cstring(name, temp_allocator) or_return
buf: [posix.PATH_MAX]byte
path = posix.realpath(cname, raw_data(buf[:]))
diff --git a/core/os/os2/file_stream.odin b/core/os/os2/file_stream.odin
index 84176928d..e1c29a792 100644
--- a/core/os/os2/file_stream.odin
+++ b/core/os/os2/file_stream.odin
@@ -2,6 +2,7 @@ package os2
import "core:io"
+// Converts a file `f` into an `io.Stream`
to_stream :: proc(f: ^File) -> (s: io.Stream) {
if f != nil {
assert(f.stream.procedure != nil)
@@ -10,14 +11,16 @@ to_stream :: proc(f: ^File) -> (s: io.Stream) {
return
}
+/*
+ This is an alias of `to_stream` which converts a file `f` to an `io.Stream`.
+ It can be useful to indicate what the stream is meant to be used for as a writer,
+ even if it has no logical difference.
+*/
to_writer :: to_stream
-to_reader :: to_stream
-
-@(private)
-error_to_io_error :: proc(ferr: Error) -> io.Error {
- if ferr == nil {
- return .None
- }
- return ferr.(io.Error) or_else .Unknown
-}
+/*
+ This is an alias of `to_stream` which converts a file `f` to an `io.Stream`.
+ It can be useful to indicate what the stream is meant to be used for as a reader,
+ even if it has no logical difference.
+*/
+to_reader :: to_stream
diff --git a/core/os/os2/file_util.odin b/core/os/os2/file_util.odin
index 5934f02f5..c2cf7c121 100644
--- a/core/os/os2/file_util.odin
+++ b/core/os/os2/file_util.odin
@@ -4,10 +4,18 @@ import "base:runtime"
import "core:strconv"
import "core:unicode/utf8"
+/*
+ `write_string` writes a string `s` to file `f`.
+ Returns the number of bytes written and an error, if any is encountered.
+*/
write_string :: proc(f: ^File, s: string) -> (n: int, err: Error) {
return write(f, transmute([]byte)s)
}
+/*
+ `write_strings` writes a variadic list of strings `strings` to file `f`.
+ Returns the number of bytes written and an error, if any is encountered.
+*/
write_strings :: proc(f: ^File, strings: ..string) -> (n: int, err: Error) {
for s in strings {
m: int
@@ -19,11 +27,18 @@ write_strings :: proc(f: ^File, strings: ..string) -> (n: int, err: Error) {
}
return
}
-
+/*
+ `write_byte` writes a byte `b` to file `f`.
+ Returns the number of bytes written and an error, if any is encountered.
+*/
write_byte :: proc(f: ^File, b: byte) -> (n: int, err: Error) {
return write(f, []byte{b})
}
+/*
+ `write_rune` writes a rune `r` as an UTF-8 encoded string to file `f`.
+ Returns the number of bytes written and an error, if any is encountered.
+*/
write_rune :: proc(f: ^File, r: rune) -> (n: int, err: Error) {
if r < utf8.RUNE_SELF {
return write_byte(f, byte(r))
@@ -34,6 +49,10 @@ write_rune :: proc(f: ^File, r: rune) -> (n: int, err: Error) {
return write(f, b[:n])
}
+/*
+ `write_encoded_rune` writes a rune `r` as an UTF-8 encoded string which with escaped control codes to file `f`.
+ Returns the number of bytes written and an error, if any is encountered.
+*/
write_encoded_rune :: proc(f: ^File, r: rune) -> (n: int, err: Error) {
wrap :: proc(m: int, merr: Error, n: ^int, err: ^Error) -> bool {
n^ += m
@@ -73,6 +92,31 @@ write_encoded_rune :: proc(f: ^File, r: rune) -> (n: int, err: Error) {
return
}
+/*
+ `write_ptr` is a utility procedure that writes the bytes points at `data` with length `len`.
+
+ It is equivalent to: `write(f, ([^]byte)(data)[:len])`
+*/
+write_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) {
+ return write(f, ([^]byte)(data)[:len])
+}
+
+/*
+ `read_ptr` is a utility procedure that reads the bytes points at `data` with length `len`.
+
+ It is equivalent to: `read(f, ([^]byte)(data)[:len])`
+*/
+read_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) {
+ return read(f, ([^]byte)(data)[:len])
+}
+
+
+
+/*
+ `read_at_least` reads from `f` into `buf` until it has read at least `min` bytes.
+ It returns the number of bytes copied and an error if fewer bytes were read.
+ The error is only an `io.EOF` if no bytes were read.
+*/
read_at_least :: proc(f: ^File, buf: []byte, min: int) -> (n: int, err: Error) {
if len(buf) < min {
return 0, .Short_Buffer
@@ -88,17 +132,17 @@ read_at_least :: proc(f: ^File, buf: []byte, min: int) -> (n: int, err: Error) {
return
}
+/*
+ `read_full` reads exactly `len(buf)` bytes from `f` into `buf`.
+ It returns the number of bytes copied and an error if fewer bytes were read.
+ The error is only an `io.EOF` if no bytes were read.
+
+ It is equivalent to `read_at_least(f, buf, len(buf))`.
+*/
read_full :: proc(f: ^File, buf: []byte) -> (n: int, err: Error) {
return read_at_least(f, buf, len(buf))
}
-write_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) {
- return write(f, ([^]byte)(data)[:len])
-}
-
-read_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) {
- return read(f, ([^]byte)(data)[:len])
-}
read_entire_file :: proc{
@@ -106,6 +150,10 @@ read_entire_file :: proc{
read_entire_file_from_file,
}
+/*
+ `read_entire_file_from_path` reads the entire named file `name` into memory allocated with `allocator`.
+ A slice of bytes and an error is returned, if any error is encountered.
+*/
@(require_results)
read_entire_file_from_path :: proc(name: string, allocator: runtime.Allocator, loc := #caller_location) -> (data: []byte, err: Error) {
f := open(name) or_return
@@ -113,6 +161,10 @@ read_entire_file_from_path :: proc(name: string, allocator: runtime.Allocator, l
return read_entire_file_from_file(f, allocator, loc)
}
+/*
+ `read_entire_file_from_file` reads the entire file `f` into memory allocated with `allocator`.
+ A slice of bytes and an error is returned, if any error is encountered.
+*/
@(require_results)
read_entire_file_from_file :: proc(f: ^File, allocator: runtime.Allocator, loc := #caller_location) -> (data: []byte, err: Error) {
size: int
@@ -160,8 +212,23 @@ read_entire_file_from_file :: proc(f: ^File, allocator: runtime.Allocator, loc :
}
}
+/*
+ `write_entire_file` writes the contents of `data` into named file `name`.
+ It defaults with the permssions `perm := Permissions_Read_All + {.Write_User}`, and `truncate`s by default.
+ An error is returned if any is encountered.
+*/
+write_entire_file :: proc{
+ write_entire_file_from_bytes,
+ write_entire_file_from_string,
+}
+
+/*
+ `write_entire_file_from_bytes` writes the contents of `data` into named file `name`.
+ It defaults with the permssions `perm := Permissions_Read_All + {.Write_User}`, and `truncate`s by default.
+ An error is returned if any is encountered.
+*/
@(require_results)
-write_entire_file :: proc(name: string, data: []byte, perm: int = 0o644, truncate := true) -> Error {
+write_entire_file_from_bytes :: proc(name: string, data: []byte, perm := Permissions_Read_All + {.Write_User}, truncate := true) -> Error {
flags := O_WRONLY|O_CREATE
if truncate {
flags |= O_TRUNC
@@ -174,3 +241,14 @@ write_entire_file :: proc(name: string, data: []byte, perm: int = 0o644, truncat
return err
}
+
+
+/*
+ `write_entire_file_from_string` writes the contents of `data` into named file `name`.
+ It defaults with the permssions `perm := Permissions_Read_All + {.Write_User}`, and `truncate`s by default.
+ An error is returned if any is encountered.
+*/
+@(require_results)
+write_entire_file_from_string :: proc(name: string, data: string, perm := Permissions_Read_All + {.Write_User}, truncate := true) -> Error {
+ return write_entire_file(name, transmute([]byte)data, perm, truncate)
+}
diff --git a/core/os/os2/file_wasi.odin b/core/os/os2/file_wasi.odin
index 1d417ffb1..ec464fc52 100644
--- a/core/os/os2/file_wasi.odin
+++ b/core/os/os2/file_wasi.odin
@@ -51,8 +51,8 @@ init_std_files :: proc "contextless" () {
}
@(init)
-init_preopens :: proc() {
- strip_prefixes :: proc(path: string) -> string {
+init_preopens :: proc "contextless" () {
+ strip_prefixes :: proc "contextless" (path: string) -> string {
path := path
loop: for len(path) > 0 {
switch {
@@ -69,6 +69,8 @@ init_preopens :: proc() {
return path
}
+ context = runtime.default_context()
+
n: int
n_loop: for fd := wasi.fd_t(3); ; fd += 1 {
_, err := wasi.fd_prestat_get(fd)
@@ -171,7 +173,7 @@ match_preopen :: proc(path: string) -> (wasi.fd_t, string, bool) {
return match.fd, relative, true
}
-_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) {
+_open :: proc(name: string, flags: File_Flags, perm: Permissions) -> (f: ^File, err: Error) {
dir_fd, relative, ok := match_preopen(name)
if !ok {
return nil, .Invalid_Path
@@ -373,11 +375,11 @@ _fchdir :: proc(f: ^File) -> Error {
return .Unsupported
}
-_fchmod :: proc(f: ^File, mode: int) -> Error {
+_fchmod :: proc(f: ^File, mode: Permissions) -> Error {
return .Unsupported
}
-_chmod :: proc(name: string, mode: int) -> Error {
+_chmod :: proc(name: string, mode: Permissions) -> Error {
return .Unsupported
}
diff --git a/core/os/os2/file_windows.odin b/core/os/os2/file_windows.odin
index b39e65fe2..be5aeb8ab 100644
--- a/core/os/os2/file_windows.odin
+++ b/core/os/os2/file_windows.odin
@@ -12,7 +12,6 @@ import win32 "core:sys/windows"
INVALID_HANDLE :: ~uintptr(0)
-S_IWRITE :: 0o200
_ERROR_BAD_NETPATH :: 53
MAX_RW :: 1<<30
@@ -81,7 +80,7 @@ _handle :: proc "contextless" (f: ^File) -> win32.HANDLE {
return win32.HANDLE(_fd(f))
}
-_open_internal :: proc(name: string, flags: File_Flags, perm: int) -> (handle: uintptr, err: Error) {
+_open_internal :: proc(name: string, flags: File_Flags, perm: Permissions) -> (handle: uintptr, err: Error) {
if len(name) == 0 {
err = .Not_Exist
return
@@ -122,7 +121,7 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: int) -> (handle: u
}
attrs: u32 = win32.FILE_ATTRIBUTE_NORMAL|win32.FILE_FLAG_BACKUP_SEMANTICS
- if perm & S_IWRITE == 0 {
+ if .Write_User not_in perm {
attrs = win32.FILE_ATTRIBUTE_READONLY
if create_mode == win32.CREATE_ALWAYS {
// NOTE(bill): Open has just asked to create a file in read-only mode.
@@ -150,7 +149,7 @@ _open_internal :: proc(name: string, flags: File_Flags, perm: int) -> (handle: u
}
-_open :: proc(name: string, flags: File_Flags, perm: int) -> (f: ^File, err: Error) {
+_open :: proc(name: string, flags: File_Flags, perm: Permissions) -> (f: ^File, err: Error) {
flags := flags if flags != nil else {.Read}
handle := _open_internal(name, flags, perm) or_return
return _new_file(handle, name, file_allocator())
@@ -193,7 +192,7 @@ _new_file :: proc(handle: uintptr, name: string, allocator: runtime.Allocator) -
@(require_results)
-_open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm := 0o777) -> (f: ^File, err: Error) {
+_open_buffered :: proc(name: string, buffer_size: uint, flags := File_Flags{.Read}, perm: Permissions) -> (f: ^File, err: Error) {
assert(buffer_size > 0)
flags := flags if flags != nil else {.Read}
handle := _open_internal(name, flags, perm) or_return
@@ -744,7 +743,7 @@ _fchdir :: proc(f: ^File) -> Error {
return nil
}
-_fchmod :: proc(f: ^File, mode: int) -> Error {
+_fchmod :: proc(f: ^File, mode: Permissions) -> Error {
if f == nil || f.impl == nil {
return nil
}
@@ -753,7 +752,7 @@ _fchmod :: proc(f: ^File, mode: int) -> Error {
return _get_platform_error()
}
attrs := d.dwFileAttributes
- if mode & S_IWRITE != 0 {
+ if .Write_User in mode {
attrs &~= win32.FILE_ATTRIBUTE_READONLY
} else {
attrs |= win32.FILE_ATTRIBUTE_READONLY
@@ -780,7 +779,7 @@ _chdir :: proc(name: string) -> Error {
return nil
}
-_chmod :: proc(name: string, mode: int) -> Error {
+_chmod :: proc(name: string, mode: Permissions) -> Error {
f := open(name, {.Write}) or_return
defer close(f)
return _fchmod(f, mode)
diff --git a/core/os/os2/heap.odin b/core/os/os2/heap.odin
index 8f9c7680a..b1db54dc7 100644
--- a/core/os/os2/heap.odin
+++ b/core/os/os2/heap.odin
@@ -2,6 +2,9 @@ package os2
import "base:runtime"
+/*
+ Returns the default `heap_allocator` for this specific platform.
+*/
@(require_results)
heap_allocator :: proc() -> runtime.Allocator {
return runtime.Allocator{
diff --git a/core/os/os2/path_wasi.odin b/core/os/os2/path_wasi.odin
index b8240e188..f26e16158 100644
--- a/core/os/os2/path_wasi.odin
+++ b/core/os/os2/path_wasi.odin
@@ -34,7 +34,7 @@ _mkdir_all :: proc(path: string, perm: int) -> Error {
return .Exist
}
- clean_path := clean_path(path, temp_allocator)
+ clean_path := clean_path(path, temp_allocator) or_return
return internal_mkdir_all(clean_path)
internal_mkdir_all :: proc(path: string) -> Error {
@@ -114,3 +114,7 @@ _get_executable_path :: proc(allocator: runtime.Allocator) -> (path: string, err
return concatenate({"/", arg}, allocator)
}
+
+_get_absolute_path :: proc(path: string, allocator: runtime.Allocator) -> (absolute_path: string, err: Error) {
+ return "", .Unsupported
+}
diff --git a/core/os/os2/process.odin b/core/os/os2/process.odin
index 635befc64..def561e28 100644
--- a/core/os/os2/process.odin
+++ b/core/os/os2/process.odin
@@ -35,7 +35,7 @@ delete_args :: proc "contextless" () {
Exit the current process.
*/
exit :: proc "contextless" (code: int) -> ! {
- _exit(code)
+ runtime.exit(code)
}
/*
diff --git a/core/os/os2/process_linux.odin b/core/os/os2/process_linux.odin
index 43ab78bdb..197693dc3 100644
--- a/core/os/os2/process_linux.odin
+++ b/core/os/os2/process_linux.odin
@@ -14,11 +14,6 @@ import "core:sys/linux"
PIDFD_UNASSIGNED :: ~uintptr(0)
@(private="package")
-_exit :: proc "contextless" (code: int) -> ! {
- linux.exit_group(i32(code))
-}
-
-@(private="package")
_get_uid :: proc() -> int {
return int(linux.getuid())
}
diff --git a/core/os/os2/process_posix.odin b/core/os/os2/process_posix.odin
index fcacdf654..a48e44900 100644
--- a/core/os/os2/process_posix.odin
+++ b/core/os/os2/process_posix.odin
@@ -10,10 +10,6 @@ import "core:strings"
import kq "core:sys/kqueue"
import "core:sys/posix"
-_exit :: proc "contextless" (code: int) -> ! {
- posix.exit(i32(code))
-}
-
_get_uid :: proc() -> int {
return int(posix.getuid())
}
diff --git a/core/os/os2/process_wasi.odin b/core/os/os2/process_wasi.odin
index 9f4d61649..52fdb1680 100644
--- a/core/os/os2/process_wasi.odin
+++ b/core/os/os2/process_wasi.odin
@@ -4,11 +4,7 @@ package os2
import "base:runtime"
import "core:time"
-import "core:sys/wasm/wasi"
-
-_exit :: proc "contextless" (code: int) -> ! {
- wasi.proc_exit(wasi.exitcode_t(code))
-}
+// import "core:sys/wasm/wasi"
_get_uid :: proc() -> int {
return 0
diff --git a/core/os/os2/process_windows.odin b/core/os/os2/process_windows.odin
index 990da6616..05ac9da93 100644
--- a/core/os/os2/process_windows.odin
+++ b/core/os/os2/process_windows.odin
@@ -8,11 +8,6 @@ import win32 "core:sys/windows"
import "core:time"
@(private="package")
-_exit :: proc "contextless" (code: int) -> ! {
- win32.ExitProcess(u32(code))
-}
-
-@(private="package")
_get_uid :: proc() -> int {
return -1
}
diff --git a/core/os/os2/stat.odin b/core/os/os2/stat.odin
index d6b524684..f87afc4c9 100644
--- a/core/os/os2/stat.odin
+++ b/core/os/os2/stat.odin
@@ -6,13 +6,16 @@ import "core:time"
Fstat_Callback :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error)
+/*
+ `File_Info` describes a file and is returned from `stat`, `fstat`, and `lstat`.
+*/
File_Info :: struct {
- fullpath: string,
- name: string,
+ fullpath: string, // fullpath of the file
+ name: string, // base name of the file
- inode: u128, // might be zero if cannot be determined
- size: i64 `fmt:"M"`,
- mode: int `fmt:"o"`,
+ inode: u128, // might be zero if cannot be determined
+ size: i64 `fmt:"M"`, // length in bytes for regular files; system-dependent for other file types
+ mode: Permissions, // file permission flags
type: File_Type,
creation_time: time.Time,
@@ -49,6 +52,10 @@ fstat :: proc(f: ^File, allocator: runtime.Allocator) -> (File_Info, Error) {
return {}, .Invalid_Callback
}
+/*
+ `stat` returns a `File_Info` describing the named file from the file system.
+ The resulting `File_Info` must be deleted with `file_info_delete`.
+*/
@(require_results)
stat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) {
return _stat(name, allocator)
@@ -56,12 +63,21 @@ stat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) {
lstat :: stat_do_not_follow_links
+/*
+ Returns a `File_Info` describing the named file from the file system.
+ If the file is a symbolic link, the `File_Info` returns describes the symbolic link,
+ rather than following the link.
+ The resulting `File_Info` must be deleted with `file_info_delete`.
+*/
@(require_results)
stat_do_not_follow_links :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) {
return _lstat(name, allocator)
}
+/*
+ Returns true if two `File_Info`s are equivalent.
+*/
@(require_results)
same_file :: proc(fi1, fi2: File_Info) -> bool {
return _same_file(fi1, fi2)
@@ -71,6 +87,10 @@ same_file :: proc(fi1, fi2: File_Info) -> bool {
last_write_time :: modification_time
last_write_time_by_name :: modification_time_by_path
+/*
+ Returns the modification time of the file `f`.
+ The resolution of the timestamp is system-dependent.
+*/
@(require_results)
modification_time :: proc(f: ^File) -> (time.Time, Error) {
temp_allocator := TEMP_ALLOCATOR_GUARD({})
@@ -78,6 +98,10 @@ modification_time :: proc(f: ^File) -> (time.Time, Error) {
return fi.modification_time, err
}
+/*
+ Returns the modification time of the named file `path`.
+ The resolution of the timestamp is system-dependent.
+*/
@(require_results)
modification_time_by_path :: proc(path: string) -> (time.Time, Error) {
temp_allocator := TEMP_ALLOCATOR_GUARD({})
diff --git a/core/os/os2/stat_linux.odin b/core/os/os2/stat_linux.odin
index 373765be5..6185252cf 100644
--- a/core/os/os2/stat_linux.odin
+++ b/core/os/os2/stat_linux.odin
@@ -26,7 +26,7 @@ _fstat_internal :: proc(fd: linux.Fd, allocator: runtime.Allocator) -> (fi: File
case linux.S_IFREG: type = .Regular
case linux.S_IFSOCK: type = .Socket
}
- mode := int(0o7777 & transmute(u32)s.mode)
+ mode := transmute(Permissions)(0o7777 & transmute(u32)s.mode)
// TODO: As of Linux 4.11, the new statx syscall can retrieve creation_time
fi = File_Info {
diff --git a/core/os/os2/stat_posix.odin b/core/os/os2/stat_posix.odin
index 6ffbdf1da..4ed96b389 100644
--- a/core/os/os2/stat_posix.odin
+++ b/core/os/os2/stat_posix.odin
@@ -14,7 +14,7 @@ internal_stat :: proc(stat: posix.stat_t, fullpath: string) -> (fi: File_Info) {
fi.inode = u128(stat.st_ino)
fi.size = i64(stat.st_size)
- fi.mode = int(transmute(posix._mode_t)(stat.st_mode - posix.S_IFMT))
+ fi.mode = transmute(Permissions)u32(transmute(posix._mode_t)(stat.st_mode - posix.S_IFMT))
fi.type = .Undetermined
switch {
diff --git a/core/os/os2/stat_windows.odin b/core/os/os2/stat_windows.odin
index 3dee42be6..20a708145 100644
--- a/core/os/os2/stat_windows.odin
+++ b/core/os/os2/stat_windows.odin
@@ -211,11 +211,11 @@ _file_type_from_create_file :: proc(wname: win32.wstring, create_file_attributes
return file_type(h)
}
-_file_type_mode_from_file_attributes :: proc(file_attributes: win32.DWORD, h: win32.HANDLE, ReparseTag: win32.DWORD) -> (type: File_Type, mode: int) {
+_file_type_mode_from_file_attributes :: proc(file_attributes: win32.DWORD, h: win32.HANDLE, ReparseTag: win32.DWORD) -> (type: File_Type, mode: Permissions) {
if file_attributes & win32.FILE_ATTRIBUTE_READONLY != 0 {
- mode |= 0o444
+ mode += Permissions_Write_All
} else {
- mode |= 0o666
+ mode += Permissions_Read_Write_All
}
is_sym := false
@@ -229,7 +229,7 @@ _file_type_mode_from_file_attributes :: proc(file_attributes: win32.DWORD, h: wi
type = .Symlink
} else if file_attributes & win32.FILE_ATTRIBUTE_DIRECTORY != 0 {
type = .Directory
- mode |= 0o111
+ mode += Permissions_Execute_All
} else if h != nil {
type = file_type(h)
}
diff --git a/core/os/os2/temp_file.odin b/core/os/os2/temp_file.odin
index e3e74bd11..f0bc3788e 100644
--- a/core/os/os2/temp_file.odin
+++ b/core/os/os2/temp_file.odin
@@ -7,7 +7,7 @@ MAX_ATTEMPTS :: 1<<13 // Should be enough for everyone, right?
// Creates a new temperatory file in the directory `dir`.
//
-// Opens the file for reading and writing, with 0o666 permissions, and returns the new `^File`.
+// Opens the file for reading and writing, with `Permissions_Read_Write_All` permissions, and returns the new `^File`.
// The filename is generated by taking a pattern, and adding a randomized string to the end.
// If the pattern includes an "*", the random string replaces the last "*".
// If `dir` is an empty string, `temp_directory()` will be used.
@@ -26,7 +26,7 @@ create_temp_file :: proc(dir, pattern: string) -> (f: ^File, err: Error) {
attempts := 0
for {
name := concatenate_strings_from_buffer(name_buf[:], prefix, random_string(rand_buf[:]), suffix)
- f, err = open(name, {.Read, .Write, .Create, .Excl}, 0o666)
+ f, err = open(name, {.Read, .Write, .Create, .Excl}, Permissions_Read_Write_All)
if err == .Exist {
close(f)
attempts += 1
@@ -80,6 +80,19 @@ make_directory_temp :: proc(dir, pattern: string, allocator: runtime.Allocator)
}
temp_dir :: temp_directory
+
+/*
+ Returns the default directory to use for temporary files.
+
+ On Unix systems, it typically returns $TMPDIR if non-empty, otherwlse `/tmp`.
+ On Windows, it uses `GetTempPathW`, returning the first non-empty value from one of the following:
+ * `%TMP%`
+ * `%TEMP%`
+ * `%USERPROFILE %`
+ * or the Windows directory
+ See https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppathw for more information.
+ On wasi, it returns `/tmp`.
+*/
@(require_results)
temp_directory :: proc(allocator: runtime.Allocator) -> (string, Error) {
return _temp_dir(allocator)
diff --git a/core/sys/darwin/Foundation/NSApplication.odin b/core/sys/darwin/Foundation/NSApplication.odin
index a5e9f2e24..6cb3df979 100644
--- a/core/sys/darwin/Foundation/NSApplication.odin
+++ b/core/sys/darwin/Foundation/NSApplication.odin
@@ -132,6 +132,11 @@ Application_finishLaunching :: proc "c" (self: ^Application) {
msgSend(nil, self, "finishLaunching")
}
+@(objc_type=Application, objc_name="stop")
+Application_stop :: proc "c" (self: ^Application, sender: ^Object) {
+ msgSend(nil, self, "stop:", sender)
+}
+
@(objc_type=Application, objc_name="terminate")
Application_terminate :: proc "c" (self: ^Application, sender: ^Object) {
msgSend(nil, self, "terminate:", sender)
@@ -156,6 +161,12 @@ Application_nextEventMatchingMask :: proc "c" (self: ^Application, mask: EventMa
Application_sendEvent :: proc "c" (self: ^Application, event: ^Event) {
msgSend(nil, self, "sendEvent:", event)
}
+
+@(objc_type=Application, objc_name="postEvent")
+Application_postEvent :: proc "c" (self: ^Application, event: ^Event, atStart: BOOL) {
+ msgSend(nil, self, "postEvent:atStart:", event, atStart)
+}
+
@(objc_type=Application, objc_name="updateWindows")
Application_updateWindows :: proc "c" (self: ^Application) {
msgSend(nil, self, "updateWindows")
@@ -175,6 +186,11 @@ RunningApplication_localizedName :: proc "c" (self: ^RunningApplication) -> ^Str
return msgSend(^String, self, "localizedName")
}
+@(objc_type=RunningApplication, objc_name="finishedLaunching")
+RunningApplication_finishedLaunching :: proc "c" (self: ^RunningApplication) -> BOOL {
+ return msgSend(BOOL, self, "isFinishedLaunching")
+}
+
ApplicationDelegateTemplate :: struct {
// Launching Applications
applicationWillFinishLaunching: proc(notification: ^Notification),
diff --git a/core/sys/darwin/Foundation/NSEvent.odin b/core/sys/darwin/Foundation/NSEvent.odin
index 548c5c172..3bd0c1879 100644
--- a/core/sys/darwin/Foundation/NSEvent.odin
+++ b/core/sys/darwin/Foundation/NSEvent.odin
@@ -250,6 +250,35 @@ kVK :: enum {
ISO_Section = 0x0A,
}
+/* class methods for creating events */
+
+@(objc_type=Event, objc_name="otherEventWithType", objc_is_class_method=true)
+Event_otherEventWithType :: proc "c" (
+ type: EventType,
+ location: Point,
+ flags: EventModifierFlags,
+ time: TimeInterval,
+ window_number: Integer,
+ ctx: id,
+ subtype: i16,
+ data1: Integer,
+ data2: Integer,
+) -> ^Event {
+ return msgSend(
+ ^Event,
+ Event,
+ "otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:",
+ type,
+ location,
+ flags,
+ time,
+ window_number,
+ ctx,
+ subtype,
+ data1,
+ data2,
+ )
+}
/* these messages are valid for all events */
diff --git a/core/sys/darwin/Foundation/NSWindow.odin b/core/sys/darwin/Foundation/NSWindow.odin
index e1b027a89..e5bc10074 100644
--- a/core/sys/darwin/Foundation/NSWindow.odin
+++ b/core/sys/darwin/Foundation/NSWindow.odin
@@ -56,6 +56,60 @@ BackingStoreType :: enum UInteger {
Buffered = 2,
}
+WindowCollectionBehaviorFlag :: enum UInteger {
+ CanJoinAllSpaces = 0,
+ MoveToActiveSpace = 1,
+ Managed = 2,
+ Transient = 3,
+ Stationary = 4,
+ ParticipatesInCycle = 5,
+ IgnoresCycle = 6,
+ FullScreenPrimary = 7,
+ FullScreenAuxiliary = 8,
+ FullScreenNone = 9,
+ FullScreenAllowsTiling = 11,
+ FullScreenDisallowsTiling = 12,
+ Primary = 16,
+ Auxiliary = 17,
+ CanJoinAllApplications = 18,
+}
+WindowCollectionBehavior :: distinct bit_set[WindowCollectionBehaviorFlag; UInteger]
+WindowCollectionBehaviorDefault :: WindowCollectionBehavior{}
+WindowCollectionBehaviorPrimary :: WindowCollectionBehavior{.Primary, .FullScreenAuxiliary}
+WindowCollectionBehaviorAuxiliary :: WindowCollectionBehavior{.Auxiliary, .FullScreenNone}
+WindowCollectionBehaviorCanJoinAllApplications :: WindowCollectionBehavior{.CanJoinAllApplications}
+WindowCollectionBehaviorCanJoinAllSpaces :: WindowCollectionBehavior{.CanJoinAllSpaces}
+WindowCollectionBehaviorMoveToActiveSpace :: WindowCollectionBehavior{.MoveToActiveSpace}
+WindowCollectionBehaviorStationary :: WindowCollectionBehavior{.Stationary}
+WindowCollectionBehaviorManaged :: WindowCollectionBehavior{.Managed}
+WindowCollectionBehaviorTransient :: WindowCollectionBehavior{.Transient}
+WindowCollectionBehaviorFullScreenPrimary :: WindowCollectionBehavior{.FullScreenPrimary}
+WindowCollectionBehaviorFullScreenAuxiliary :: WindowCollectionBehavior{.FullScreenAuxiliary}
+WindowCollectionBehaviorFullScreenNone :: WindowCollectionBehavior{.FullScreenNone}
+WindowCollectionBehaviorFullScreenAllowsTiling :: WindowCollectionBehavior{.FullScreenAllowsTiling}
+WindowCollectionBehaviorFullScreenDisallowsTiling :: WindowCollectionBehavior{.FullScreenDisallowsTiling}
+WindowCollectionBehaviorParticipatesInCycle :: WindowCollectionBehavior{.ParticipatesInCycle}
+WindowCollectionBehaviorIgnoresCycle :: WindowCollectionBehavior{.IgnoresCycle}
+
+WindowLevel :: enum Integer {
+ Normal = 0,
+ Floating = 3,
+ Submenu = 3,
+ TornOffMenu = 3,
+ ModalPanel = 8,
+ MainMenu = 24,
+ Status = 25,
+ PopUpMenu = 101,
+ ScreenSaver = 1000,
+}
+
+WindowTabbingMode :: enum Integer {
+ Automatic = 0,
+ Preferred = 1,
+ Disallowed = 2,
+}
+
+
WindowDelegateTemplate :: struct {
// Managing Sheets
windowWillPositionSheetUsingRect: proc(window: ^Window, sheet: ^Window, rect: Rect) -> Rect,
@@ -600,6 +654,10 @@ Responder :: struct {using _: Object}
@(objc_class="NSView")
View :: struct {using _: Responder}
+@(objc_type=View, objc_name="alloc", objc_is_class_method=true)
+View_alloc :: proc "c" () -> ^View {
+ return msgSend(^View, View, "alloc")
+}
@(objc_type=View, objc_name="initWithFrame")
View_initWithFrame :: proc "c" (self: ^View, frame: Rect) -> ^View {
@@ -670,6 +728,10 @@ Window_setFrame :: proc "c" (self: ^Window, frame: Rect, display: BOOL) {
Window_setFrameOrigin :: proc "c" (self: ^Window, origin: Point) {
msgSend(nil, self, "setFrameOrigin:", origin)
}
+@(objc_type=Window, objc_name="center")
+Window_center :: proc "c" (self: ^Window) {
+ msgSend(nil, self, "center")
+}
@(objc_type=Window, objc_name="opaque")
Window_opaque :: proc "c" (self: ^Window) -> BOOL {
return msgSend(BOOL, self, "opaque")
@@ -686,6 +748,14 @@ Window_backgroundColor :: proc "c" (self: ^Window) -> ^Color {
Window_setBackgroundColor :: proc "c" (self: ^Window, color: ^Color) {
msgSend(nil, self, "setBackgroundColor:", color)
}
+@(objc_type = Window, objc_name = "orderFront")
+Window_orderFront :: proc "c" (self: ^Window, sender: id) {
+ msgSend(nil, self, "orderFront:", sender)
+}
+@(objc_type = Window, objc_name = "orderOut")
+Window_orderOut :: proc "c" (self: ^Window, sender: id) {
+ msgSend(nil, self, "orderOut:", sender)
+}
@(objc_type=Window, objc_name="makeKeyAndOrderFront")
Window_makeKeyAndOrderFront :: proc "c" (self: ^Window, key: ^Object) {
msgSend(nil, self, "makeKeyAndOrderFront:", key)
@@ -722,6 +792,10 @@ Window_close :: proc "c" (self: ^Window) {
Window_setDelegate :: proc "c" (self: ^Window, delegate: ^WindowDelegate) {
msgSend(nil, self, "setDelegate:", delegate)
}
+@(objc_type = Window, objc_name = "delegate")
+Window_delegate :: proc "c" (self: ^Window) -> ^WindowDelegate {
+ return msgSend(^WindowDelegate, self, "delegate")
+}
@(objc_type=Window, objc_name="backingScaleFactor")
Window_backingScaleFactor :: proc "c" (self: ^Window) -> Float {
return msgSend(Float, self, "backingScaleFactor")
@@ -798,3 +872,35 @@ Window_performWindowDragWithEvent :: proc "c" (self: ^Window, event: ^Event) {
Window_setToolbar :: proc "c" (self: ^Window, toolbar: ^Toolbar) {
msgSend(nil, self, "setToolbar:", toolbar)
}
+@(objc_type = Window, objc_name = "setCollectionBehavior")
+Window_setCollectionBehavior :: proc "c" (self: ^Window, behavior: WindowCollectionBehavior) {
+ msgSend(nil, self, "setCollectionBehavior:", behavior)
+}
+@(objc_type = Window, objc_name = "collectionBehavior")
+Window_collectionBehavior :: proc "c" (self: ^Window) -> WindowCollectionBehavior {
+ return msgSend(WindowCollectionBehavior, self, "collectionBehavior")
+}
+@(objc_type = Window, objc_name = "setLevel")
+Window_setLevel :: proc "c" (self: ^Window, level: WindowLevel) {
+ msgSend(nil, self, "setLevel:", level)
+}
+@(objc_type = Window, objc_name = "setReleasedWhenClosed")
+Window_setReleasedWhenClosed :: proc "c" (self: ^Window, flag: BOOL) {
+ msgSend(nil, self, "setReleasedWhenClosed:", flag)
+}
+@(objc_type = Window, objc_name = "makeFirstResponder")
+Window_makeFirstResponder :: proc "c" (self: ^Window, responder: ^Responder) -> BOOL {
+ return msgSend(BOOL, self, "makeFirstResponder:", responder)
+}
+@(objc_type = Window, objc_name = "setRestorable")
+Window_setRestorable :: proc "c" (self: ^Window, flag: BOOL) {
+ msgSend(nil, self, "setRestorable:", flag)
+}
+@(objc_type = Window, objc_name = "setTabbingMode")
+Window_setTabbingMode :: proc "c" (self: ^Window, mode: WindowTabbingMode) {
+ msgSend(nil, self, "setTabbingMode:", mode)
+}
+@(objc_type = Window, objc_name = "toggleFullScreen")
+Window_toggleFullScreen :: proc "c" (self: ^Window, sender: id) {
+ msgSend(nil, self, "toggleFullScreen:", sender)
+}
diff --git a/core/testing/logging.odin b/core/testing/logging.odin
index 428e50afe..3138a745b 100644
--- a/core/testing/logging.odin
+++ b/core/testing/logging.odin
@@ -83,7 +83,31 @@ format_log_text :: proc(level: runtime.Logger_Level, text: string, options: runt
log.do_level_header(options, &buf, level)
log.do_time_header(options, &buf, at_time)
- log.do_location_header(options, &buf, location)
-
+ when GO_TO_ERROR {
+ do_go_to_error_friendly_location(options, &buf, location)
+ } else {
+ log.do_location_header(options, &buf, location)
+ }
return fmt.aprintf("%s%s", strings.to_string(buf), text, allocator = allocator)
}
+
+do_go_to_error_friendly_location :: proc(opts: log.Options, buf: ^strings.Builder, location := #caller_location) {
+ if log.Location_Header_Opts & opts == nil {
+ return
+ }
+ fmt.sbprint(buf, "\n")
+
+ file := location.file_path
+ fmt.sbprint(buf, file)
+
+ fmt.sbprint(buf, "(")
+ fmt.sbprint(buf, location.line)
+ fmt.sbprint(buf, ":")
+ fmt.sbprint(buf, location.column)
+ fmt.sbprint(buf, ")")
+
+ if .Procedure in opts {
+ fmt.sbprintf(buf, ":%s()", location.procedure)
+ }
+ fmt.sbprint(buf, " ")
+} \ No newline at end of file
diff --git a/core/testing/runner.odin b/core/testing/runner.odin
index 0897e4fed..9ce4f35cb 100644
--- a/core/testing/runner.odin
+++ b/core/testing/runner.odin
@@ -63,6 +63,9 @@ LOG_STATE_CHANGES : bool : #config(ODIN_TEST_LOG_STATE_CHANGES, false)
USING_SHORT_LOGS : bool : #config(ODIN_TEST_SHORT_LOGS, false)
// Output a report of the tests to the given path.
JSON_REPORT : string : #config(ODIN_TEST_JSON_REPORT, "")
+// Print the full file path for failed test cases on a new line
+// in a way that's friendly to regex capture for an editor's "go to error".
+GO_TO_ERROR : bool : #config(ODIN_TEST_GO_TO_ERROR, false)
get_log_level :: #force_inline proc() -> runtime.Logger_Level {
when LOG_LEVEL == "debug" { return .Debug } else
@@ -803,7 +806,7 @@ runner :: proc(internal_tests: []Internal_Test) -> bool {
}
} else {
if total_done_count != last_done_count {
- if !global_ansi_disabled {
+ if !(global_ansi_disabled || !FANCY_OUTPUT) {
fmt.wprintf(stdout, OSC_WINDOW_TITLE, total_done_count, total_test_count)
}
last_done_count = total_done_count
diff --git a/core/text/scanner/scanner.odin b/core/text/scanner/scanner.odin
index 649b4d2d7..9445df58c 100644
--- a/core/text/scanner/scanner.odin
+++ b/core/text/scanner/scanner.odin
@@ -341,8 +341,10 @@ scan_number :: proc(s: ^Scanner, ch: rune, seen_dot: bool) -> (rune, rune) {
case 'x':
ch = advance(s)
base, prefix = 16, 'x'
- case:
+ case 'o':
+ ch = advance(s)
base, prefix = 8, 'o'
+ case:
digsep = 1 // Leading zero
}
} else {
diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin
index 205eb2a3c..cda04278e 100644
--- a/examples/all/all_main.odin
+++ b/examples/all/all_main.odin
@@ -111,6 +111,7 @@ package all
@(require) import "core:prof/spall"
@(require) import "core:os"
+@(require) import "core:os/os2"
@(require) import "core:path/slashpath"
@(require) import "core:path/filepath"
diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp
index 530efb3c8..b2d28afc0 100644
--- a/src/check_builtin.cpp
+++ b/src/check_builtin.cpp
@@ -13,6 +13,7 @@ gb_global BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_simple_bool
nullptr, // BuiltinProc__type_simple_boolean_begin
is_type_boolean,
+ is_type_bit_field,
is_type_integer,
is_type_rune,
is_type_float,
@@ -24,6 +25,7 @@ gb_global BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_simple_bool
is_type_cstring16,
is_type_typeid,
is_type_any,
+
is_type_endian_platform,
is_type_endian_little,
is_type_endian_big,
@@ -34,8 +36,8 @@ gb_global BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_simple_bool
is_type_indexable,
is_type_sliceable,
is_type_comparable,
- is_type_simple_compare,
- is_type_nearly_simple_compare,
+ is_type_simple_compare, // easily compared using memcmp
+ is_type_nearly_simple_compare, // easily compared using memcmp (including floats)
is_type_dereferenceable,
is_type_valid_for_keys,
is_type_valid_for_matrix_elems,
@@ -47,14 +49,12 @@ gb_global BuiltinTypeIsProc *builtin_type_is_procs[BuiltinProc__type_simple_bool
is_type_enumerated_array,
is_type_slice,
is_type_dynamic_array,
-
is_type_map,
is_type_struct,
is_type_union,
is_type_enum,
is_type_proc,
is_type_bit_set,
- is_type_bit_field,
is_type_simd_vector,
is_type_matrix,
is_type_raw_union,
@@ -4768,6 +4768,42 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
break;
}
+ case BuiltinProc_constant_floor:
+ case BuiltinProc_constant_trunc:
+ case BuiltinProc_constant_ceil:
+ case BuiltinProc_constant_round:
+ {
+ Operand o = {};
+ check_expr(c, &o, ce->args[0]);
+
+ if (!is_type_integer_or_float(o.type) && (o.mode != Addressing_Constant)) {
+ error(ce->args[0], "Expected a constant number for '%.*s'", LIT(builtin_name));
+ return false;
+ }
+ operand->mode = Addressing_Constant;
+ operand->type = o.type;
+
+ ExactValue value = o.value;
+ if (value.kind == ExactValue_Integer) {
+ // do nothing
+ } else if (value.kind == ExactValue_Float) {
+ f64 f = value.value_float;
+ switch (id) {
+ case BuiltinProc_constant_floor: f = floor(f); break;
+ case BuiltinProc_constant_trunc: f = trunc(f); break;
+ case BuiltinProc_constant_ceil: f = ceil(f); break;
+ case BuiltinProc_constant_round: f = round(f); break;
+ default:
+ GB_PANIC("Unhandled built-in: %.*s", LIT(builtin_name));
+ break;
+ }
+ value = exact_value_float(f);
+ }
+
+ operand->value = value;
+ break;
+ }
+
case BuiltinProc_soa_struct: {
Operand x = {};
Operand y = {};
@@ -6552,17 +6588,18 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
case BuiltinProc_type_is_boolean:
+ case BuiltinProc_type_is_bit_field:
case BuiltinProc_type_is_integer:
case BuiltinProc_type_is_rune:
case BuiltinProc_type_is_float:
case BuiltinProc_type_is_complex:
case BuiltinProc_type_is_quaternion:
- case BuiltinProc_type_is_typeid:
- case BuiltinProc_type_is_any:
case BuiltinProc_type_is_string:
case BuiltinProc_type_is_string16:
case BuiltinProc_type_is_cstring:
case BuiltinProc_type_is_cstring16:
+ case BuiltinProc_type_is_typeid:
+ case BuiltinProc_type_is_any:
case BuiltinProc_type_is_endian_platform:
case BuiltinProc_type_is_endian_little:
case BuiltinProc_type_is_endian_big:
@@ -6573,8 +6610,8 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
case BuiltinProc_type_is_indexable:
case BuiltinProc_type_is_sliceable:
case BuiltinProc_type_is_comparable:
- case BuiltinProc_type_is_simple_compare:
- case BuiltinProc_type_is_nearly_simple_compare:
+ case BuiltinProc_type_is_simple_compare: // easily compared using memcmp
+ case BuiltinProc_type_is_nearly_simple_compare: // easily compared using memcmp (including floats)
case BuiltinProc_type_is_dereferenceable:
case BuiltinProc_type_is_valid_map_key:
case BuiltinProc_type_is_valid_matrix_elements:
@@ -6591,7 +6628,6 @@ gb_internal bool check_builtin_procedure(CheckerContext *c, Operand *operand, As
case BuiltinProc_type_is_enum:
case BuiltinProc_type_is_proc:
case BuiltinProc_type_is_bit_set:
- case BuiltinProc_type_is_bit_field:
case BuiltinProc_type_is_simd_vector:
case BuiltinProc_type_is_matrix:
case BuiltinProc_type_is_raw_union:
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index e22f12323..8ac277917 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -9200,6 +9200,52 @@ gb_internal ExprKind check_basic_directive_expr(CheckerContext *c, Operand *o, A
return kind;
}
+
+gb_internal void check_expr_as_value_for_ternary(CheckerContext *c, Operand *o, Ast *e, Type *type_hint) {
+ check_expr_base(c, o, e, type_hint);
+ check_not_tuple(c, o);
+ error_operand_no_value(o);
+
+ switch (o->mode) {
+ case Addressing_Type: {
+ ERROR_BLOCK();
+ gbString expr_str = expr_to_string(o->expr);
+ defer (gb_string_free(expr_str));
+
+ error(o->expr, "A type '%s' cannot be used as a runtime value", expr_str);
+
+ error_line("\tSuggestion: If a runtime 'typeid' is wanted, use 'typeid_of' to convert a type\n");
+
+ o->mode = Addressing_Invalid;
+
+ } break;
+
+ case Addressing_Builtin: {
+ ERROR_BLOCK();
+ gbString expr_str = expr_to_string(o->expr);
+ defer (gb_string_free(expr_str));
+
+ error(o->expr, "A built-in procedure '%s' cannot be used as a runtime value", expr_str);
+
+ error_line("\tNote: Built-in procedures are implemented by the compiler and might not be actually instantiated procedures\n");
+
+ o->mode = Addressing_Invalid;
+ } break;
+
+ case Addressing_ProcGroup: {
+ ERROR_BLOCK();
+ gbString expr_str = expr_to_string(o->expr);
+ defer (gb_string_free(expr_str));
+
+ error(o->expr, "Cannot use overloaded procedure '%s' as a runtime value", expr_str);
+
+ error_line("\tNote: Please specify which procedure in the procedure group to use, via cast or type inference\n");
+
+ o->mode = Addressing_Invalid;
+ } break;
+ }
+}
+
gb_internal ExprKind check_ternary_if_expr(CheckerContext *c, Operand *o, Ast *node, Type *type_hint) {
ExprKind kind = Expr_Expr;
Operand cond = {Addressing_Invalid};
@@ -9213,7 +9259,7 @@ gb_internal ExprKind check_ternary_if_expr(CheckerContext *c, Operand *o, Ast *n
Operand x = {Addressing_Invalid};
Operand y = {Addressing_Invalid};
- check_expr_or_type(c, &x, te->x, type_hint);
+ check_expr_as_value_for_ternary(c, &x, te->x, type_hint);
node->viral_state_flags |= te->x->viral_state_flags;
if (te->y != nullptr) {
@@ -9221,7 +9267,7 @@ gb_internal ExprKind check_ternary_if_expr(CheckerContext *c, Operand *o, Ast *n
if (type_hint == nullptr && is_type_typed(x.type)) {
th = x.type;
}
- check_expr_or_type(c, &y, te->y, th);
+ check_expr_as_value_for_ternary(c, &y, te->y, th);
node->viral_state_flags |= te->y->viral_state_flags;
} else {
error(node, "A ternary expression must have an else clause");
@@ -9248,6 +9294,20 @@ gb_internal ExprKind check_ternary_if_expr(CheckerContext *c, Operand *o, Ast *n
return kind;
}
+ if (x.mode == Addressing_Builtin && y.mode == Addressing_Builtin) {
+ if (type_hint == nullptr) {
+ error(node, "Built-in procedures cannot be used within a ternary expression since they have no well-defined signature");
+ return kind;
+ }
+ }
+
+ if (x.mode == Addressing_ProcGroup && y.mode == Addressing_ProcGroup) {
+ if (type_hint == nullptr) {
+ error(node, "Procedure groups cannot be used within a ternary expression since they have no well-defined signature that can be inferred without a context");
+ return kind;
+ }
+ }
+
// NOTE(bill, 2023-01-30): Allow for expression like this:
// x: union{f32} = f32(123) if cond else nil
if (type_hint && !is_type_any(type_hint)) {
diff --git a/src/check_type.cpp b/src/check_type.cpp
index f1a2e9e22..5accfbd9f 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -1633,6 +1633,8 @@ gb_internal bool is_expr_from_a_parameter(CheckerContext *ctx, Ast *expr) {
} else if (expr->kind == Ast_Ident) {
Operand x= {};
Entity *e = check_ident(ctx, &x, expr, nullptr, nullptr, true);
+ GB_ASSERT(e != nullptr);
+
if (e->flags & EntityFlag_Param) {
return true;
}
diff --git a/src/checker.cpp b/src/checker.cpp
index 8b3638c9d..1daacd9ce 100644
--- a/src/checker.cpp
+++ b/src/checker.cpp
@@ -923,6 +923,22 @@ gb_internal AstPackage *get_core_package(CheckerInfo *info, String name) {
return *found;
}
+
+gb_internal AstPackage *try_get_core_package(CheckerInfo *info, String name) {
+ if (name == "runtime") {
+ return get_runtime_package(info);
+ }
+
+ gbAllocator a = heap_allocator();
+ String path = get_fullpath_core_collection(a, name, nullptr);
+ defer (gb_free(a, path.text));
+ auto found = string_map_get(&info->packages, path);
+ if (found == nullptr) {
+ return nullptr;
+ }
+ return *found;
+}
+
gb_internal void add_package_dependency(CheckerContext *c, char const *package_name, char const *name, bool required=false) {
String n = make_string_c(name);
AstPackage *p = get_core_package(&c->checker->info, make_string_c(package_name));
diff --git a/src/checker_builtin_procs.hpp b/src/checker_builtin_procs.hpp
index 01502128a..663274cdc 100644
--- a/src/checker_builtin_procs.hpp
+++ b/src/checker_builtin_procs.hpp
@@ -49,6 +49,11 @@ enum BuiltinProcId {
BuiltinProc_constant_log2,
+ BuiltinProc_constant_floor,
+ BuiltinProc_constant_trunc,
+ BuiltinProc_constant_ceil,
+ BuiltinProc_constant_round,
+
BuiltinProc_transpose,
BuiltinProc_outer_product,
BuiltinProc_hadamard_product,
@@ -420,7 +425,11 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT("has_target_feature"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
- {STR_LIT("constant_log2"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+ {STR_LIT("constant_log2"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+ {STR_LIT("constant_floor"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+ {STR_LIT("constant_trunc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+ {STR_LIT("constant_ceil"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+ {STR_LIT("constant_round"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("transpose"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("outer_product"), 2, false, Expr_Expr, BuiltinProcPkg_intrinsics},
@@ -615,17 +624,18 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT(""), 0, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
{STR_LIT("type_is_boolean"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+ {STR_LIT("type_is_bit_field"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_is_integer"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_is_rune"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_is_float"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_is_complex"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_is_quaternion"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
- {STR_LIT("type_is_typeid"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
- {STR_LIT("type_is_any"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_is_string"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_is_string16"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
- {STR_LIT("type_is_cstring"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
- {STR_LIT("type_is_cstring16"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+ {STR_LIT("type_is_cstring"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+ {STR_LIT("type_is_cstring16"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+ {STR_LIT("type_is_typeid"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
+ {STR_LIT("type_is_any"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_is_endian_platform"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_is_endian_little"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
@@ -656,7 +666,6 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
{STR_LIT("type_is_enum"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_is_proc"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_is_bit_set"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
- {STR_LIT("type_is_bit_field"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_is_simd_vector"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_is_matrix"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
{STR_LIT("type_is_raw_union"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp
index 7742fb39d..d6bd7d72d 100644
--- a/src/llvm_backend.cpp
+++ b/src/llvm_backend.cpp
@@ -2553,6 +2553,8 @@ gb_internal WORKER_TASK_PROC(lb_generate_missing_procedures_to_check_worker_proc
}
gb_internal void lb_generate_missing_procedures(lbGenerator *gen, bool do_threading) {
+ isize retry_count = 0;
+retry:;
if (do_threading) {
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
@@ -2570,6 +2572,14 @@ gb_internal void lb_generate_missing_procedures(lbGenerator *gen, bool do_thread
for (auto const &entry : gen->modules) {
lbModule *m = entry.value;
+ if (m->missing_procedures_to_check.count != 0) {
+ if (retry_count > gen->modules.count) {
+ GB_ASSERT(m->missing_procedures_to_check.count == 0);
+ }
+
+ retry_count += 1;
+ goto retry;
+ }
GB_ASSERT(m->missing_procedures_to_check.count == 0);
GB_ASSERT(m->procedures_to_generate.count == 0);
}
@@ -2890,7 +2900,18 @@ gb_internal lbProcedure *lb_create_main_procedure(lbModule *m, lbProcedure *star
args[0] = lb_addr_load(p, all_tests_slice);
lbValue result = lb_emit_call(p, runner, args);
- lbValue exit_runner = lb_find_package_value(m, str_lit("os"), str_lit("exit"));
+ lbValue exit_runner = {};
+ {
+ AstPackage *pkg = get_runtime_package(m->info);
+
+ String name = str_lit("exit");
+ Entity *e = scope_lookup_current(pkg->scope, name);
+ if (e == nullptr) {
+ compiler_error("Could not find type declaration for '%.*s.%.*s'\n", LIT(pkg->name), LIT(name));
+ }
+ exit_runner = lb_find_value_from_entity(m, e);
+ }
+
auto exit_args = array_make<lbValue>(temporary_allocator(), 1);
exit_args[0] = lb_emit_select(p, result, lb_const_int(m, t_int, 0), lb_const_int(m, t_int, 1));
lb_emit_call(p, exit_runner, exit_args, ProcInlining_none);
diff --git a/src/llvm_backend_const.cpp b/src/llvm_backend_const.cpp
index a7117fe0b..c014adc05 100644
--- a/src/llvm_backend_const.cpp
+++ b/src/llvm_backend_const.cpp
@@ -691,11 +691,20 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
} else if (bt->Union.variants.count == 1) {
if (value.kind == ExactValue_Compound) {
ast_node(cl, CompoundLit, value.value_compound);
- if (cl->elems.count == 0 && cl->type == nullptr) {
- return lb_const_nil(m, original_type);
+ if (cl->elems.count == 0) {
+ if (cl->type == nullptr) {
+ return lb_const_nil(m, original_type);
+ }
+ if (are_types_identical(type_of_expr(cl->type), original_type)) {
+ return lb_const_nil(m, original_type);
+ }
}
}
+ if (value_type == t_untyped_nil) {
+ return lb_const_nil(m, original_type);
+ }
+
Type *t = bt->Union.variants[0];
lbValue cv = lb_const_value(m, t, value, cc);
GB_ASSERT(LLVMIsConstant(cv.value));
@@ -736,6 +745,8 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, lb
} else if (value.kind == ExactValue_Invalid) {
return lb_const_nil(m, original_type);
}
+ } else if (value_type == t_untyped_nil) {
+ return lb_const_nil(m, original_type);
}
GB_ASSERT_MSG(value_type != nullptr, "%s :: %s", type_to_string(original_type), exact_value_to_string(value));
diff --git a/src/main.cpp b/src/main.cpp
index 0af589339..83e7d688c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2296,9 +2296,10 @@ gb_internal void export_linked_libraries(LinkerData *gen) {
for (auto *e : gen->foreign_libraries) {
GB_ASSERT(e->kind == Entity_LibraryName);
+ ast_node(imp, ForeignImportDecl, e->LibraryName.decl);
- for (auto lib_path : e->LibraryName.paths) {
- lib_path = string_trim_whitespace(lib_path);
+ for (isize i = 0; i < e->LibraryName.paths.count; i++) {
+ String lib_path = string_trim_whitespace(e->LibraryName.paths[i]);
if (lib_path.len == 0) {
continue;
}
@@ -2319,16 +2320,15 @@ gb_internal void export_linked_libraries(LinkerData *gen) {
}
gb_fprintf(&f, "\t");
- ast_node(imp, ForeignImportDecl, e->LibraryName.decl);
- for (Ast* file_path : imp->filepaths) {
- GB_ASSERT(file_path->tav.mode == Addressing_Constant && file_path->tav.value.kind == ExactValue_String);
- String file_path_str = file_path->tav.value.value_string;
- if (string_starts_with(file_path_str, str_lit("system:"))) {
- gb_fprintf(&f, "system");
- } else {
- gb_fprintf(&f, "user");
- }
+ Ast *file_path = imp->filepaths[i];
+ GB_ASSERT(file_path->tav.mode == Addressing_Constant && file_path->tav.value.kind == ExactValue_String);
+ String file_path_str = file_path->tav.value.value_string;
+
+ if (string_starts_with(file_path_str, str_lit("system:"))) {
+ gb_fprintf(&f, "system");
+ } else {
+ gb_fprintf(&f, "user");
}
gb_fprintf(&f, "\n");
diff --git a/src/name_canonicalization.cpp b/src/name_canonicalization.cpp
index 8bacfabc6..c2acf83f5 100644
--- a/src/name_canonicalization.cpp
+++ b/src/name_canonicalization.cpp
@@ -417,7 +417,7 @@ gb_internal gbString string_canonical_entity_name(gbAllocator allocator, Entity
gb_internal void write_canonical_parent_prefix(TypeWriter *w, Entity *e) {
GB_ASSERT(e != nullptr);
- if (e->kind == Entity_Procedure || e->kind == Entity_TypeName) {
+ if (e->kind == Entity_Procedure || e->kind == Entity_TypeName || e->kind == Entity_Variable) {
if (e->kind == Entity_Procedure && (e->Procedure.is_export || e->Procedure.is_foreign)) {
// no prefix
return;
@@ -756,6 +756,14 @@ gb_internal void write_type_to_canonical_string(TypeWriter *w, Type *type) {
if (i > 0) {
type_writer_appendc(w, CANONICAL_FIELD_SEPARATOR);
}
+
+ if (f->flags & EntityFlags_IsSubtype) {
+ type_writer_appendc(w, "#subtype ");
+ }
+
+ if (f->flags & EntityFlag_Using) {
+ type_writer_appendc(w, "using ");
+ }
type_writer_append(w, f->token.string.text, f->token.string.len);
type_writer_appendc(w, CANONICAL_TYPE_SEPARATOR);
write_type_to_canonical_string(w, f->type);
diff --git a/src/parser.cpp b/src/parser.cpp
index 94c6083f7..152e55f8b 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -2739,7 +2739,7 @@ gb_internal Ast *parse_operand(AstFile *f, bool lhs) {
while (allow_token(f, Token_Comma)) {
Ast *dummy_name = parse_ident(f);
if (!err_once) {
- error(dummy_name, "'bit_field' fields do not support multiple names per field");
+ syntax_error(dummy_name, "'bit_field' fields do not support multiple names per field");
err_once = true;
}
}
@@ -3299,8 +3299,16 @@ gb_internal Ast *parse_atom_expr(AstFile *f, Ast *operand, bool lhs) {
open = expect_token(f, Token_OpenBracket);
if (f->curr_token.kind == Token_CloseBracket) {
- error(f->curr_token, "Expected an operand, got ]");
+ ERROR_BLOCK();
+ syntax_error(f->curr_token, "Expected an operand, got ]");
close = expect_token(f, Token_CloseBracket);
+
+ if (f->allow_type) {
+ gbString s = expr_to_string(operand);
+ error_line("\tSuggestion: If a type was wanted, did you mean '[]%s'?", s);
+ gb_string_free(s);
+ }
+
operand = ast_index_expr(f, operand, nullptr, open, close);
break;
}
@@ -6594,7 +6602,7 @@ gb_internal bool parse_file_tag(const String &lc, const Token &tok, AstFile *f)
} else if (lc == "no-instrumentation") {
f->flags |= AstFile_NoInstrumentation;
} else {
- error(tok, "Unknown tag '%.*s'", LIT(lc));
+ syntax_error(tok, "Unknown tag '%.*s'", LIT(lc));
}
return true;
diff --git a/src/types.cpp b/src/types.cpp
index bf668e5f6..a1311ba5d 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -1296,6 +1296,15 @@ gb_internal bool is_type_rune(Type *t) {
}
return false;
}
+gb_internal bool is_type_integer_or_float(Type *t) {
+ t = base_type(t);
+ if (t == nullptr) { return false; }
+ if (t->kind == Type_Basic) {
+ return (t->Basic.flags & (BasicFlag_Integer|BasicFlag_Float)) != 0;
+ }
+ return false;
+}
+
gb_internal bool is_type_numeric(Type *t) {
t = base_type(t);
if (t == nullptr) { return false; }
diff --git a/tests/core/runtime/test_core_runtime.odin b/tests/core/runtime/test_core_runtime.odin
index 881b5f41a..f3559954d 100644
--- a/tests/core/runtime/test_core_runtime.odin
+++ b/tests/core/runtime/test_core_runtime.odin
@@ -293,6 +293,65 @@ test_soa_array_allocator_resize_overlapping :: proc(t: ^testing.T) {
}
@(test)
+test_soa_array_inject_at_elem :: proc(t: ^testing.T) {
+
+ V :: struct {a: u8, b: f32}
+
+ array := make(#soa[dynamic]V, 0, 2)
+ defer delete(array)
+
+ append(&array, V{1, 1.5}, V{2, 2.5}, V{3, 3.5})
+
+ expect_inject(t, &array, 0, {0, 0.5}, {{0, 0.5}, {1, 1.5}, {2, 2.5}, {3, 3.5}})
+ expect_inject(t, &array, 2, {5, 5.5}, {{0, 0.5}, {1, 1.5}, {5, 5.5}, {2, 2.5}, {3, 3.5}})
+ expect_inject(t, &array, 5, {9, 9.5}, {{0, 0.5}, {1, 1.5}, {5, 5.5}, {2, 2.5}, {3, 3.5}, {9, 9.5}})
+
+ expect_inject :: proc(t: ^testing.T, arr: ^#soa[dynamic]V, index: int, arg: V, expected_slice: []V) {
+ ok, err := inject_at_soa(arr, index, arg)
+ testing.expectf(t, ok == true, "Injection of %v at index %d failed", arg, index)
+ testing.expectf(t, err == nil, "Injection allocation of %v at index %d failed: %v", arg, index, err)
+ equals := len(arr) == len(expected_slice)
+ for e, i in expected_slice {
+ if arr[i] != e {
+ equals = false
+ break
+ }
+ }
+ testing.expectf(t, equals, "After injection of %v at index %d, expected array to be\n&%v, got\n%v", arg, index, expected_slice, arr)
+ }
+}
+
+@(test)
+test_soa_array_inject_at_elems :: proc(t: ^testing.T) {
+
+ V :: struct {a: u8, b: f32}
+
+ array := make(#soa[dynamic]V, 0, 2)
+ defer delete(array)
+
+ append(&array, V{1, 1.5}, V{2, 2.5}, V{3, 3.5})
+
+ expect_inject(t, &array, 0, {{0, 0.5}}, {{0, 0.5}, {1, 1.5}, {2, 2.5}, {3, 3.5}})
+ expect_inject(t, &array, 2, {{5, 5.5}, {6, 6.5}}, {{0, 0.5}, {1, 1.5}, {5, 5.5}, {6, 6.5}, {2, 2.5}, {3, 3.5}})
+ expect_inject(t, &array, 6, {{9, 9.5}, {10, 10.5}}, {{0, 0.5}, {1, 1.5}, {5, 5.5}, {6, 6.5}, {2, 2.5}, {3, 3.5}, {9, 9.5}, {10, 10.5}})
+ expect_inject(t, &array, 6, {}, {{0, 0.5}, {1, 1.5}, {5, 5.5}, {6, 6.5}, {2, 2.5}, {3, 3.5}, {9, 9.5}, {10, 10.5}})
+
+ expect_inject :: proc(t: ^testing.T, arr: ^#soa[dynamic]V, index: int, args: []V, expected_slice: []V) {
+ ok, err := inject_at_soa(arr, index, ..args)
+ testing.expectf(t, ok == true, "Injection of %v at index %d failed", args, index)
+ testing.expectf(t, err == nil, "Injection allocation of %v at index %d failed: %v", args, index, err)
+ equals := len(arr) == len(expected_slice)
+ for e, i in expected_slice {
+ if arr[i] != e {
+ equals = false
+ break
+ }
+ }
+ testing.expectf(t, equals, "After injection of %v at index %d, expected array to be\n&%v, got\n%v", args, index, expected_slice, arr)
+ }
+}
+
+@(test)
test_memory_equal :: proc(t: ^testing.T) {
data: [256]u8
cmp: [256]u8
diff --git a/vendor/raylib/raylib.odin b/vendor/raylib/raylib.odin
index 7dae19f4b..37589f165 100644
--- a/vendor/raylib/raylib.odin
+++ b/vendor/raylib/raylib.odin
@@ -96,6 +96,7 @@ _ :: linalg
MAX_TEXTFORMAT_BUFFERS :: #config(RAYLIB_MAX_TEXTFORMAT_BUFFERS, 4)
MAX_TEXT_BUFFER_LENGTH :: #config(RAYLIB_MAX_TEXT_BUFFER_LENGTH, 1024)
+MAX_MATERIAL_MAPS :: #config(RAYLIB_MAX_MATERIAL_MAPS, 12)
#assert(size_of(rune) == size_of(c.int))