mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-02 20:58:15 +00:00
Merge branch 'odin-lang:master' into master
This commit is contained in:
@@ -4,7 +4,7 @@ import "core:bytes"
|
||||
import "core:io"
|
||||
import "core:mem"
|
||||
import "core:unicode/utf8"
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
|
||||
// Extra errors returns by scanning procedures
|
||||
Scanner_Extra_Error :: enum i32 {
|
||||
|
||||
@@ -1,128 +0,0 @@
|
||||
// This is purely for documentation
|
||||
package builtin
|
||||
|
||||
nil :: nil
|
||||
false :: 0!=0
|
||||
true :: 0==0
|
||||
|
||||
ODIN_OS :: ODIN_OS
|
||||
ODIN_ARCH :: ODIN_ARCH
|
||||
ODIN_ENDIAN :: ODIN_ENDIAN
|
||||
ODIN_VENDOR :: ODIN_VENDOR
|
||||
ODIN_VERSION :: ODIN_VERSION
|
||||
ODIN_ROOT :: ODIN_ROOT
|
||||
ODIN_DEBUG :: ODIN_DEBUG
|
||||
|
||||
byte :: u8 // alias
|
||||
|
||||
bool :: bool
|
||||
b8 :: b8
|
||||
b16 :: b16
|
||||
b32 :: b32
|
||||
b64 :: b64
|
||||
|
||||
i8 :: i8
|
||||
u8 :: u8
|
||||
i16 :: i16
|
||||
u16 :: u16
|
||||
i32 :: i32
|
||||
u32 :: u32
|
||||
i64 :: i64
|
||||
u64 :: u64
|
||||
|
||||
i128 :: i128
|
||||
u128 :: u128
|
||||
|
||||
rune :: rune
|
||||
|
||||
f16 :: f16
|
||||
f32 :: f32
|
||||
f64 :: f64
|
||||
|
||||
complex32 :: complex32
|
||||
complex64 :: complex64
|
||||
complex128 :: complex128
|
||||
|
||||
quaternion64 :: quaternion64
|
||||
quaternion128 :: quaternion128
|
||||
quaternion256 :: quaternion256
|
||||
|
||||
int :: int
|
||||
uint :: uint
|
||||
uintptr :: uintptr
|
||||
|
||||
rawptr :: rawptr
|
||||
string :: string
|
||||
cstring :: cstring
|
||||
any :: any
|
||||
|
||||
typeid :: typeid
|
||||
|
||||
// Endian Specific Types
|
||||
i16le :: i16le
|
||||
u16le :: u16le
|
||||
i32le :: i32le
|
||||
u32le :: u32le
|
||||
i64le :: i64le
|
||||
u64le :: u64le
|
||||
i128le :: i128le
|
||||
u128le :: u128le
|
||||
|
||||
i16be :: i16be
|
||||
u16be :: u16be
|
||||
i32be :: i32be
|
||||
u32be :: u32be
|
||||
i64be :: i64be
|
||||
u64be :: u64be
|
||||
i128be :: i128be
|
||||
u128be :: u128be
|
||||
|
||||
|
||||
f16le :: f16le
|
||||
f32le :: f32le
|
||||
f64le :: f64le
|
||||
|
||||
f16be :: f16be
|
||||
f32be :: f32be
|
||||
f64be :: f64be
|
||||
|
||||
|
||||
|
||||
// Procedures
|
||||
len :: proc(array: Array_Type) -> int ---
|
||||
cap :: proc(array: Array_Type) -> int ---
|
||||
|
||||
size_of :: proc($T: typeid) -> int ---
|
||||
align_of :: proc($T: typeid) -> int ---
|
||||
|
||||
// e.g. offset_of(t.f), where t is an instance of the type T
|
||||
offset_of_selector :: proc(selector: $T) -> uintptr ---
|
||||
// e.g. offset_of(T, f), where T can be the type instead of a variable
|
||||
offset_of_member :: proc($T: typeid, member: $M) -> uintptr ---
|
||||
offset_of :: proc{offset_of_selector, offset_of_member}
|
||||
// e.g. offset_of(T, "f"), where T can be the type instead of a variable
|
||||
offset_of_by_string :: proc($T: typeid, member: string) -> uintptr ---
|
||||
|
||||
type_of :: proc(x: expr) -> type ---
|
||||
type_info_of :: proc($T: typeid) -> ^runtime.Type_Info ---
|
||||
typeid_of :: proc($T: typeid) -> typeid ---
|
||||
|
||||
swizzle :: proc(x: [N]T, indices: ..int) -> [len(indices)]T ---
|
||||
|
||||
complex :: proc(real, imag: Float) -> Complex_Type ---
|
||||
quaternion :: proc(imag, jmag, kmag, real: Float) -> Quaternion_Type --- // fields must be named
|
||||
real :: proc(value: Complex_Or_Quaternion) -> Float ---
|
||||
imag :: proc(value: Complex_Or_Quaternion) -> Float ---
|
||||
jmag :: proc(value: Quaternion) -> Float ---
|
||||
kmag :: proc(value: Quaternion) -> Float ---
|
||||
conj :: proc(value: Complex_Or_Quaternion) -> Complex_Or_Quaternion ---
|
||||
|
||||
expand_values :: proc(value: Struct_Or_Array) -> (A, B, C, ...) ---
|
||||
|
||||
min :: proc(values: ..T) -> T ---
|
||||
max :: proc(values: ..T) -> T ---
|
||||
abs :: proc(value: T) -> T ---
|
||||
clamp :: proc(value, minimum, maximum: T) -> T ---
|
||||
|
||||
soa_zip :: proc(slices: ...) -> #soa[]Struct ---
|
||||
soa_unzip :: proc(value: $S/#soa[]$E) -> (slices: ...) ---
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package c
|
||||
|
||||
import builtin "core:builtin"
|
||||
import builtin "base:builtin"
|
||||
|
||||
char :: builtin.u8 // assuming -funsigned-char
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ foreign libc {
|
||||
crealf :: proc(z: complex_float) -> float ---
|
||||
}
|
||||
|
||||
import builtin "core:builtin"
|
||||
import builtin "base:builtin"
|
||||
|
||||
complex_float :: distinct builtin.complex64
|
||||
complex_double :: distinct builtin.complex128
|
||||
|
||||
@@ -2,7 +2,7 @@ package libc
|
||||
|
||||
// 7.12 Mathematics
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
|
||||
when ODIN_OS == .Windows {
|
||||
foreign import libc "system:libucrt.lib"
|
||||
|
||||
@@ -2,7 +2,7 @@ package libc
|
||||
|
||||
// 7.16 Variable arguments
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
|
||||
@(private="file")
|
||||
@(default_calling_convention="none")
|
||||
|
||||
@@ -2,7 +2,7 @@ package libc
|
||||
|
||||
// 7.17 Atomics
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
|
||||
ATOMIC_BOOL_LOCK_FREE :: true
|
||||
ATOMIC_CHAR_LOCK_FREE :: true
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package libc
|
||||
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
// 7.24 String handling
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ package compress
|
||||
|
||||
import "core:io"
|
||||
import "core:bytes"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
/*
|
||||
These settings bound how much compression algorithms will allocate for their output buffer.
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// package shoco is an implementation of the shoco short string compressor
|
||||
package shoco
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
import "core:compress"
|
||||
|
||||
Shoco_Pack :: struct {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package dynamic_bit_array
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
import "core:mem"
|
||||
|
||||
/*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package container_intrusive_list
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
|
||||
// An intrusive doubly-linked list
|
||||
//
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package container_lru
|
||||
|
||||
import "core:runtime"
|
||||
import "core:intrinsics"
|
||||
import "base:runtime"
|
||||
import "base:intrinsics"
|
||||
_ :: runtime
|
||||
_ :: intrinsics
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package container_priority_queue
|
||||
|
||||
import "core:builtin"
|
||||
import "base:builtin"
|
||||
|
||||
Priority_Queue :: struct($T: typeid) {
|
||||
queue: [dynamic]T,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package container_queue
|
||||
|
||||
import "core:builtin"
|
||||
import "core:runtime"
|
||||
import "base:builtin"
|
||||
import "base:runtime"
|
||||
_ :: runtime
|
||||
|
||||
// Dynamically resizable double-ended queue/ring-buffer
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package container_small_array
|
||||
|
||||
import "core:builtin"
|
||||
import "core:runtime"
|
||||
import "base:builtin"
|
||||
import "base:runtime"
|
||||
_ :: runtime
|
||||
|
||||
Small_Array :: struct($N: int, $T: typeid) where N >= 0 {
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
// map type is being used to accelerate lookups.
|
||||
package container_topological_sort
|
||||
|
||||
import "core:intrinsics"
|
||||
import "core:runtime"
|
||||
import "base:intrinsics"
|
||||
import "base:runtime"
|
||||
_ :: intrinsics
|
||||
_ :: runtime
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package dynlib
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
import "core:reflect"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
_ :: intrinsics
|
||||
_ :: reflect
|
||||
_ :: runtime
|
||||
|
||||
@@ -4,7 +4,7 @@ package dynlib
|
||||
|
||||
import win32 "core:sys/windows"
|
||||
import "core:strings"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
import "core:reflect"
|
||||
|
||||
_load_library :: proc(path: string, global_symbols := false) -> (Library, bool) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package encoding_endian
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
import "core:math/bits"
|
||||
|
||||
Byte_Order :: enum u8 {
|
||||
|
||||
@@ -2,7 +2,7 @@ package json
|
||||
|
||||
import "core:mem"
|
||||
import "core:math/bits"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
import "core:strconv"
|
||||
import "core:strings"
|
||||
import "core:reflect"
|
||||
|
||||
@@ -5,7 +5,7 @@ import "core:math"
|
||||
import "core:reflect"
|
||||
import "core:strconv"
|
||||
import "core:strings"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
Unmarshal_Data_Error :: enum {
|
||||
Invalid_Data,
|
||||
|
||||
@@ -29,11 +29,11 @@ package xml
|
||||
|
||||
import "core:bytes"
|
||||
import "core:encoding/entity"
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
import "core:mem"
|
||||
import "core:os"
|
||||
import "core:strings"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
likely :: intrinsics.expect
|
||||
|
||||
|
||||
+4
-18
@@ -1,15 +1,15 @@
|
||||
package fmt
|
||||
|
||||
import "base:intrinsics"
|
||||
import "base:runtime"
|
||||
import "core:math/bits"
|
||||
import "core:mem"
|
||||
import "core:io"
|
||||
import "core:reflect"
|
||||
import "core:runtime"
|
||||
import "core:strconv"
|
||||
import "core:strings"
|
||||
import "core:time"
|
||||
import "core:unicode/utf8"
|
||||
import "core:intrinsics"
|
||||
|
||||
// Internal data structure that stores the required information for formatted printing
|
||||
Info :: struct {
|
||||
@@ -954,24 +954,10 @@ _fmt_int :: proc(fi: ^Info, u: u64, base: int, is_signed: bool, bit_size: int, d
|
||||
start := 0
|
||||
|
||||
flags: strconv.Int_Flags
|
||||
if fi.hash && !fi.zero { flags |= {.Prefix} }
|
||||
if fi.plus { flags |= {.Plus} }
|
||||
if fi.hash { flags |= {.Prefix} }
|
||||
if fi.plus { flags |= {.Plus} }
|
||||
s := strconv.append_bits(buf[start:], u, base, is_signed, bit_size, digits, flags)
|
||||
|
||||
if fi.hash && fi.zero && fi.indent == 0 {
|
||||
c: byte = 0
|
||||
switch base {
|
||||
case 2: c = 'b'
|
||||
case 8: c = 'o'
|
||||
case 12: c = 'z'
|
||||
case 16: c = 'x'
|
||||
}
|
||||
if c != 0 {
|
||||
io.write_byte(fi.writer, '0', &fi.n)
|
||||
io.write_byte(fi.writer, c, &fi.n)
|
||||
}
|
||||
}
|
||||
|
||||
prev_zero := fi.zero
|
||||
defer fi.zero = prev_zero
|
||||
fi.zero = false
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//+build !js
|
||||
package fmt
|
||||
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
import "core:os"
|
||||
import "core:io"
|
||||
import "core:bufio"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package hash
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
|
||||
@(optimization_mode="speed")
|
||||
crc32 :: proc(data: []byte, seed := u32(0)) -> u32 #no_bounds_check {
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
package hash
|
||||
|
||||
import "core:mem"
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
|
||||
@(optimization_mode="speed")
|
||||
adler32 :: proc(data: []byte, seed := u32(1)) -> u32 #no_bounds_check {
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
*/
|
||||
package xxhash
|
||||
|
||||
import "core:intrinsics"
|
||||
import "core:runtime"
|
||||
import "base:intrinsics"
|
||||
import "base:runtime"
|
||||
|
||||
mem_copy :: runtime.mem_copy
|
||||
byte_swap :: intrinsics.byte_swap
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
package xxhash
|
||||
|
||||
import "core:mem"
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
|
||||
/*
|
||||
=== XXH3 128-bit streaming ===
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
package xxhash
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
|
||||
/*
|
||||
*************************************************************************
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
package xxhash
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
|
||||
/*
|
||||
32-bit hash functions
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
*/
|
||||
package xxhash
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
|
||||
/*
|
||||
64-bit hash functions
|
||||
|
||||
@@ -13,7 +13,7 @@ package image
|
||||
import "core:bytes"
|
||||
import "core:mem"
|
||||
import "core:compress"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
/*
|
||||
67_108_864 pixels max by default.
|
||||
|
||||
@@ -8,7 +8,7 @@ import "core:mem"
|
||||
import "core:strconv"
|
||||
import "core:strings"
|
||||
import "core:unicode"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
Image :: image.Image
|
||||
Format :: image.Netpbm_Format
|
||||
|
||||
@@ -16,7 +16,7 @@ import coretime "core:time"
|
||||
import "core:strings"
|
||||
import "core:bytes"
|
||||
import "core:mem"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
/*
|
||||
Cleanup of image-specific data.
|
||||
|
||||
@@ -22,8 +22,8 @@ import "core:hash"
|
||||
import "core:bytes"
|
||||
import "core:io"
|
||||
import "core:mem"
|
||||
import "core:intrinsics"
|
||||
import "core:runtime"
|
||||
import "base:intrinsics"
|
||||
import "base:runtime"
|
||||
|
||||
// Limit chunk sizes.
|
||||
// By default: IDAT = 8k x 8k x 16-bits + 8k filter bytes.
|
||||
|
||||
@@ -1,316 +0,0 @@
|
||||
// This is purely for documentation
|
||||
//+build ignore
|
||||
package intrinsics
|
||||
|
||||
// Package-Related
|
||||
is_package_imported :: proc(package_name: string) -> bool ---
|
||||
|
||||
// Types
|
||||
soa_struct :: proc($N: int, $T: typeid) -> type/#soa[N]T
|
||||
|
||||
// Volatile
|
||||
volatile_load :: proc(dst: ^$T) -> T ---
|
||||
volatile_store :: proc(dst: ^$T, val: T) ---
|
||||
|
||||
non_temporal_load :: proc(dst: ^$T) -> T ---
|
||||
non_temporal_store :: proc(dst: ^$T, val: T) ---
|
||||
|
||||
// Trapping
|
||||
debug_trap :: proc() ---
|
||||
trap :: proc() -> ! ---
|
||||
|
||||
// Instructions
|
||||
|
||||
alloca :: proc(size, align: int) -> [^]u8 ---
|
||||
cpu_relax :: proc() ---
|
||||
read_cycle_counter :: proc() -> i64 ---
|
||||
|
||||
count_ones :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
|
||||
count_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
|
||||
count_trailing_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
|
||||
count_leading_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
|
||||
reverse_bits :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
|
||||
byte_swap :: proc(x: $T) -> T where type_is_integer(T) || type_is_float(T) ---
|
||||
|
||||
overflow_add :: proc(lhs, rhs: $T) -> (T, bool) #optional_ok ---
|
||||
overflow_sub :: proc(lhs, rhs: $T) -> (T, bool) #optional_ok ---
|
||||
overflow_mul :: proc(lhs, rhs: $T) -> (T, bool) #optional_ok ---
|
||||
|
||||
sqrt :: proc(x: $T) -> T where type_is_float(T) || (type_is_simd_vector(T) && type_is_float(type_elem_type(T))) ---
|
||||
|
||||
fused_mul_add :: proc(a, b, c: $T) -> T where type_is_float(T) || (type_is_simd_vector(T) && type_is_float(type_elem_type(T))) ---
|
||||
|
||||
mem_copy :: proc(dst, src: rawptr, len: int) ---
|
||||
mem_copy_non_overlapping :: proc(dst, src: rawptr, len: int) ---
|
||||
mem_zero :: proc(ptr: rawptr, len: int) ---
|
||||
mem_zero_volatile :: proc(ptr: rawptr, len: int) ---
|
||||
|
||||
// prefer [^]T operations if possible
|
||||
ptr_offset :: proc(ptr: ^$T, offset: int) -> ^T ---
|
||||
ptr_sub :: proc(a, b: ^$T) -> int ---
|
||||
|
||||
unaligned_load :: proc(src: ^$T) -> T ---
|
||||
unaligned_store :: proc(dst: ^$T, val: T) -> T ---
|
||||
|
||||
fixed_point_mul :: proc(lhs, rhs: $T, #const scale: uint) -> T where type_is_integer(T) ---
|
||||
fixed_point_div :: proc(lhs, rhs: $T, #const scale: uint) -> T where type_is_integer(T) ---
|
||||
fixed_point_mul_sat :: proc(lhs, rhs: $T, #const scale: uint) -> T where type_is_integer(T) ---
|
||||
fixed_point_div_sat :: proc(lhs, rhs: $T, #const scale: uint) -> T where type_is_integer(T) ---
|
||||
|
||||
prefetch_read_instruction :: proc(address: rawptr, #const locality: i32 /* 0..=3 */) ---
|
||||
prefetch_read_data :: proc(address: rawptr, #const locality: i32 /* 0..=3 */) ---
|
||||
prefetch_write_instruction :: proc(address: rawptr, #const locality: i32 /* 0..=3 */) ---
|
||||
prefetch_write_data :: proc(address: rawptr, #const locality: i32 /* 0..=3 */) ---
|
||||
|
||||
// Compiler Hints
|
||||
expect :: proc(val, expected_val: T) -> T ---
|
||||
|
||||
// Linux and Darwin Only
|
||||
syscall :: proc(id: uintptr, args: ..uintptr) -> uintptr ---
|
||||
|
||||
|
||||
// Atomics
|
||||
Atomic_Memory_Order :: enum {
|
||||
Relaxed = 0, // Unordered
|
||||
Consume = 1, // Monotonic
|
||||
Acquire = 2,
|
||||
Release = 3,
|
||||
Acq_Rel = 4,
|
||||
Seq_Cst = 5,
|
||||
}
|
||||
|
||||
atomic_type_is_lock_free :: proc($T: typeid) -> bool ---
|
||||
|
||||
atomic_thread_fence :: proc(order: Atomic_Memory_Order) ---
|
||||
atomic_signal_fence :: proc(order: Atomic_Memory_Order) ---
|
||||
|
||||
atomic_store :: proc(dst: ^$T, val: T) ---
|
||||
atomic_store_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) ---
|
||||
|
||||
atomic_load :: proc(dst: ^$T) -> T ---
|
||||
atomic_load_explicit :: proc(dst: ^$T, order: Atomic_Memory_Order) -> T ---
|
||||
|
||||
// fetch then operator
|
||||
atomic_add :: proc(dst: ^$T, val: T) -> T ---
|
||||
atomic_add_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
|
||||
atomic_sub :: proc(dst: ^$T, val: T) -> T ---
|
||||
atomic_sub_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
|
||||
atomic_and :: proc(dst: ^$T, val: T) -> T ---
|
||||
atomic_and_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
|
||||
atomic_nand :: proc(dst: ^$T, val: T) -> T ---
|
||||
atomic_nand_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
|
||||
atomic_or :: proc(dst: ^$T, val: T) -> T ---
|
||||
atomic_or_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
|
||||
atomic_xor :: proc(dst: ^$T, val: T) -> T ---
|
||||
atomic_xor_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
|
||||
atomic_exchange :: proc(dst: ^$T, val: T) -> T ---
|
||||
atomic_exchange_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
|
||||
|
||||
atomic_compare_exchange_strong :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
|
||||
atomic_compare_exchange_strong_explicit :: proc(dst: ^$T, old, new: T, success, failure: Atomic_Memory_Order) -> (T, bool) #optional_ok ---
|
||||
atomic_compare_exchange_weak :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
|
||||
atomic_compare_exchange_weak_explicit :: proc(dst: ^$T, old, new: T, success, failure: Atomic_Memory_Order) -> (T, bool) #optional_ok ---
|
||||
|
||||
|
||||
// Constant type tests
|
||||
|
||||
type_base_type :: proc($T: typeid) -> type ---
|
||||
type_core_type :: proc($T: typeid) -> type ---
|
||||
type_elem_type :: proc($T: typeid) -> type ---
|
||||
|
||||
type_is_boolean :: proc($T: typeid) -> bool ---
|
||||
type_is_integer :: proc($T: typeid) -> bool ---
|
||||
type_is_rune :: proc($T: typeid) -> bool ---
|
||||
type_is_float :: proc($T: typeid) -> bool ---
|
||||
type_is_complex :: proc($T: typeid) -> bool ---
|
||||
type_is_quaternion :: proc($T: typeid) -> bool ---
|
||||
type_is_string :: proc($T: typeid) -> bool ---
|
||||
type_is_typeid :: proc($T: typeid) -> bool ---
|
||||
type_is_any :: proc($T: typeid) -> bool ---
|
||||
|
||||
type_is_endian_platform :: proc($T: typeid) -> bool ---
|
||||
type_is_endian_little :: proc($T: typeid) -> bool ---
|
||||
type_is_endian_big :: proc($T: typeid) -> bool ---
|
||||
type_is_unsigned :: proc($T: typeid) -> bool ---
|
||||
type_is_numeric :: proc($T: typeid) -> bool ---
|
||||
type_is_ordered :: proc($T: typeid) -> bool ---
|
||||
type_is_ordered_numeric :: proc($T: typeid) -> bool ---
|
||||
type_is_indexable :: proc($T: typeid) -> bool ---
|
||||
type_is_sliceable :: proc($T: typeid) -> bool ---
|
||||
type_is_comparable :: proc($T: typeid) -> bool ---
|
||||
type_is_simple_compare :: proc($T: typeid) -> bool --- // easily compared using memcmp (== and !=)
|
||||
type_is_dereferenceable :: proc($T: typeid) -> bool ---
|
||||
type_is_valid_map_key :: proc($T: typeid) -> bool ---
|
||||
type_is_valid_matrix_elements :: proc($T: typeid) -> bool ---
|
||||
|
||||
type_is_named :: proc($T: typeid) -> bool ---
|
||||
type_is_pointer :: proc($T: typeid) -> bool ---
|
||||
type_is_multi_pointer :: proc($T: typeid) -> bool ---
|
||||
type_is_array :: proc($T: typeid) -> bool ---
|
||||
type_is_enumerated_array :: proc($T: typeid) -> bool ---
|
||||
type_is_slice :: proc($T: typeid) -> bool ---
|
||||
type_is_dynamic_array :: proc($T: typeid) -> bool ---
|
||||
type_is_map :: proc($T: typeid) -> bool ---
|
||||
type_is_struct :: proc($T: typeid) -> bool ---
|
||||
type_is_union :: proc($T: typeid) -> bool ---
|
||||
type_is_enum :: proc($T: typeid) -> bool ---
|
||||
type_is_proc :: proc($T: typeid) -> bool ---
|
||||
type_is_bit_set :: proc($T: typeid) -> bool ---
|
||||
type_is_simd_vector :: proc($T: typeid) -> bool ---
|
||||
type_is_matrix :: proc($T: typeid) -> bool ---
|
||||
|
||||
type_has_nil :: proc($T: typeid) -> bool ---
|
||||
|
||||
type_is_specialization_of :: proc($T, $S: typeid) -> bool ---
|
||||
|
||||
type_is_variant_of :: proc($U, $V: typeid) -> bool where type_is_union(U) ---
|
||||
type_union_tag_type :: proc($T: typeid) -> typeid where type_is_union(T) ---
|
||||
type_union_tag_offset :: proc($T: typeid) -> uintptr where type_is_union(T) ---
|
||||
type_union_base_tag_value :: proc($T: typeid) -> int where type_is_union(U) ---
|
||||
type_union_variant_count :: proc($T: typeid) -> int where type_is_union(T) ---
|
||||
type_variant_type_of :: proc($T: typeid, $index: int) -> typeid where type_is_union(T) ---
|
||||
type_variant_index_of :: proc($U, $V: typeid) -> int where type_is_union(U) ---
|
||||
|
||||
type_has_field :: proc($T: typeid, $name: string) -> bool ---
|
||||
type_field_type :: proc($T: typeid, $name: string) -> typeid ---
|
||||
|
||||
type_proc_parameter_count :: proc($T: typeid) -> int where type_is_proc(T) ---
|
||||
type_proc_return_count :: proc($T: typeid) -> int where type_is_proc(T) ---
|
||||
|
||||
type_proc_parameter_type :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) ---
|
||||
type_proc_return_type :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) ---
|
||||
|
||||
type_struct_field_count :: proc($T: typeid) -> int where type_is_struct(T) ---
|
||||
|
||||
type_polymorphic_record_parameter_count :: proc($T: typeid) -> typeid ---
|
||||
type_polymorphic_record_parameter_value :: proc($T: typeid, index: int) -> $V ---
|
||||
|
||||
type_is_specialized_polymorphic_record :: proc($T: typeid) -> bool ---
|
||||
type_is_unspecialized_polymorphic_record :: proc($T: typeid) -> bool ---
|
||||
|
||||
type_is_subtype_of :: proc($T, $U: typeid) -> bool ---
|
||||
|
||||
type_field_index_of :: proc($T: typeid, $name: string) -> uintptr ---
|
||||
|
||||
type_equal_proc :: proc($T: typeid) -> (equal: proc "contextless" (rawptr, rawptr) -> bool) where type_is_comparable(T) ---
|
||||
type_hasher_proc :: proc($T: typeid) -> (hasher: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr) where type_is_comparable(T) ---
|
||||
|
||||
type_map_info :: proc($T: typeid/map[$K]$V) -> ^runtime.Map_Info ---
|
||||
type_map_cell_info :: proc($T: typeid) -> ^runtime.Map_Cell_Info ---
|
||||
|
||||
type_convert_variants_to_pointers :: proc($T: typeid) -> typeid where type_is_union(T) ---
|
||||
type_merge :: proc($U, $V: typeid) -> typeid where type_is_union(U), type_is_union(V) ---
|
||||
|
||||
constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
|
||||
|
||||
// SIMD related
|
||||
simd_add :: proc(a, b: #simd[N]T) -> #simd[N]T ---
|
||||
simd_sub :: proc(a, b: #simd[N]T) -> #simd[N]T ---
|
||||
simd_mul :: proc(a, b: #simd[N]T) -> #simd[N]T ---
|
||||
simd_div :: proc(a, b: #simd[N]T) -> #simd[N]T where type_is_float(T) ---
|
||||
|
||||
// Keeps Odin's Behaviour
|
||||
// (x << y) if y <= mask else 0
|
||||
simd_shl :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
|
||||
simd_shr :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
|
||||
|
||||
// Similar to C's Behaviour
|
||||
// x << (y & mask)
|
||||
simd_shl_masked :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
|
||||
simd_shr_masked :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
|
||||
|
||||
simd_add_sat :: proc(a, b: #simd[N]T) -> #simd[N]T ---
|
||||
simd_sub_sat :: proc(a, b: #simd[N]T) -> #simd[N]T ---
|
||||
|
||||
simd_bit_and :: proc(a, b: #simd[N]T) -> #simd[N]T ---
|
||||
simd_bit_or :: proc(a, b: #simd[N]T) -> #simd[N]T ---
|
||||
simd_bit_xor :: proc(a, b: #simd[N]T) -> #simd[N]T ---
|
||||
simd_bit_and_not :: proc(a, b: #simd[N]T) -> #simd[N]T ---
|
||||
|
||||
simd_neg :: proc(a: #simd[N]T) -> #simd[N]T ---
|
||||
|
||||
simd_abs :: proc(a: #simd[N]T) -> #simd[N]T ---
|
||||
|
||||
simd_min :: proc(a, b: #simd[N]T) -> #simd[N]T ---
|
||||
simd_max :: proc(a, b: #simd[N]T) -> #simd[N]T ---
|
||||
simd_clamp :: proc(v, min, max: #simd[N]T) -> #simd[N]T ---
|
||||
|
||||
// Return an unsigned integer of the same size as the input type
|
||||
// NOT A BOOLEAN
|
||||
// element-wise:
|
||||
// false => 0x00...00
|
||||
// true => 0xff...ff
|
||||
simd_lanes_eq :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
|
||||
simd_lanes_ne :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
|
||||
simd_lanes_lt :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
|
||||
simd_lanes_le :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
|
||||
simd_lanes_gt :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
|
||||
simd_lanes_ge :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
|
||||
|
||||
simd_extract :: proc(a: #simd[N]T, idx: uint) -> T ---
|
||||
simd_replace :: proc(a: #simd[N]T, idx: uint, elem: T) -> #simd[N]T ---
|
||||
|
||||
simd_reduce_add_ordered :: proc(a: #simd[N]T) -> T ---
|
||||
simd_reduce_mul_ordered :: proc(a: #simd[N]T) -> T ---
|
||||
simd_reduce_min :: proc(a: #simd[N]T) -> T ---
|
||||
simd_reduce_max :: proc(a: #simd[N]T) -> T ---
|
||||
simd_reduce_and :: proc(a: #simd[N]T) -> T ---
|
||||
simd_reduce_or :: proc(a: #simd[N]T) -> T ---
|
||||
simd_reduce_xor :: proc(a: #simd[N]T) -> T ---
|
||||
|
||||
simd_shuffle :: proc(a, b: #simd[N]T, indices: ..int) -> #simd[len(indices)]T ---
|
||||
simd_select :: proc(cond: #simd[N]boolean_or_integer, true, false: #simd[N]T) -> #simd[N]T ---
|
||||
|
||||
// Lane-wise operations
|
||||
simd_ceil :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
|
||||
simd_floor :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
|
||||
simd_trunc :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
|
||||
// rounding to the nearest integral value; if two values are equally near, rounds to the even one
|
||||
simd_nearest :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
|
||||
|
||||
simd_to_bits :: proc(v: #simd[N]T) -> #simd[N]Integer where size_of(T) == size_of(Integer), type_is_unsigned(Integer) ---
|
||||
|
||||
// equivalent a swizzle with descending indices, e.g. reserve(a, 3, 2, 1, 0)
|
||||
simd_reverse :: proc(a: #simd[N]T) -> #simd[N]T ---
|
||||
|
||||
simd_rotate_left :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T ---
|
||||
simd_rotate_right :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T ---
|
||||
|
||||
|
||||
// WASM targets only
|
||||
wasm_memory_grow :: proc(index, delta: uintptr) -> int ---
|
||||
wasm_memory_size :: proc(index: uintptr) -> int ---
|
||||
|
||||
// `timeout_ns` is maximum number of nanoseconds the calling thread will be blocked for
|
||||
// A negative value will be blocked forever
|
||||
// Return value:
|
||||
// 0 - indicates that the thread blocked and then was woken up
|
||||
// 1 - the loaded value from `ptr` did not match `expected`, the thread did not block
|
||||
// 2 - the thread blocked, but the timeout
|
||||
wasm_memory_atomic_wait32 :: proc(ptr: ^u32, expected: u32, timeout_ns: i64) -> u32 ---
|
||||
wasm_memory_atomic_notify32 :: proc(ptr: ^u32, waiters: u32) -> (waiters_woken_up: u32) ---
|
||||
|
||||
// x86 Targets (i386, amd64)
|
||||
x86_cpuid :: proc(ax, cx: u32) -> (eax, ebx, ecx, edx: u32) ---
|
||||
x86_xgetbv :: proc(cx: u32) -> (eax, edx: u32) ---
|
||||
|
||||
|
||||
// Darwin targets only
|
||||
objc_object :: struct{}
|
||||
objc_selector :: struct{}
|
||||
objc_class :: struct{}
|
||||
objc_id :: ^objc_object
|
||||
objc_SEL :: ^objc_selector
|
||||
objc_Class :: ^objc_class
|
||||
|
||||
objc_find_selector :: proc($name: string) -> objc_SEL ---
|
||||
objc_register_selector :: proc($name: string) -> objc_SEL ---
|
||||
objc_find_class :: proc($name: string) -> objc_Class ---
|
||||
objc_register_class :: proc($name: string) -> objc_Class ---
|
||||
|
||||
|
||||
valgrind_client_request :: proc(default: uintptr, request: uintptr, a0, a1, a2, a3, a4: uintptr) -> uintptr ---
|
||||
|
||||
// Internal compiler use only
|
||||
|
||||
__entry_point :: proc() ---
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
// operations into an abstracted stream interface.
|
||||
package io
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
import "core:unicode/utf8"
|
||||
|
||||
// Seek whence values
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
//+build !freestanding
|
||||
package log
|
||||
|
||||
import "core:fmt"
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package log
|
||||
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
import "core:fmt"
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package log
|
||||
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
import "core:fmt"
|
||||
|
||||
Log_Allocator_Format :: enum {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
package math_big
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
|
||||
/*
|
||||
TODO: Make the tunables runtime adjustable where practical.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
package math_big
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
import rnd "core:math/rand"
|
||||
|
||||
/*
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
package math_big
|
||||
|
||||
import "core:mem"
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
import rnd "core:math/rand"
|
||||
import "core:builtin"
|
||||
import "base:builtin"
|
||||
|
||||
/*
|
||||
Low-level addition, unsigned. Handbook of Applied Cryptography, algorithm 14.7.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
package math_big
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
import "core:mem"
|
||||
|
||||
/*
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
package math_big
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
|
||||
/*
|
||||
===========================
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package math_big
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
import "core:mem"
|
||||
import "core:os"
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package math_big
|
||||
|
||||
import "core:builtin"
|
||||
import "core:intrinsics"
|
||||
import "base:builtin"
|
||||
import "base:intrinsics"
|
||||
import "core:math"
|
||||
|
||||
Rat :: struct {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
package math_big
|
||||
|
||||
import "core:time"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
print_value :: proc(name: string, value: i64) {
|
||||
runtime.print_string("\t")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package math_bits
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
|
||||
U8_MIN :: 0
|
||||
U16_MIN :: 0
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package math_cmplx
|
||||
|
||||
import "core:builtin"
|
||||
import "base:builtin"
|
||||
import "core:math"
|
||||
|
||||
// The original C code, the long comment, and the constants
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package math_cmplx
|
||||
|
||||
import "core:builtin"
|
||||
import "base:builtin"
|
||||
import "core:math"
|
||||
|
||||
// The original C code, the long comment, and the constants
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package ease
|
||||
|
||||
import "core:math"
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
import "core:time"
|
||||
|
||||
@(private) PI_2 :: math.PI / 2
|
||||
|
||||
@@ -2,7 +2,7 @@ package math_fixed
|
||||
|
||||
import "core:math"
|
||||
import "core:strconv"
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
_, _, _ :: intrinsics, strconv, math
|
||||
|
||||
Fixed :: struct($Backing: typeid, $Fraction_Width: uint)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package linalg
|
||||
|
||||
import "core:builtin"
|
||||
import "base:builtin"
|
||||
import "core:math"
|
||||
|
||||
@(require_results)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package linalg
|
||||
|
||||
import "core:math"
|
||||
import "core:builtin"
|
||||
import "core:intrinsics"
|
||||
import "base:builtin"
|
||||
import "base:intrinsics"
|
||||
|
||||
// Generic
|
||||
|
||||
@@ -66,7 +66,7 @@ quaternion256_dot :: proc "contextless" (a, b: $T/quaternion256) -> (c: f64) {
|
||||
dot :: proc{scalar_dot, vector_dot, quaternion64_dot, quaternion128_dot, quaternion256_dot}
|
||||
|
||||
inner_product :: dot
|
||||
outer_product :: builtin.outer_product
|
||||
outer_product :: intrinsics.outer_product
|
||||
|
||||
@(require_results)
|
||||
quaternion_inverse :: proc "contextless" (q: $Q) -> Q where IS_QUATERNION(Q) {
|
||||
@@ -179,8 +179,7 @@ identity :: proc "contextless" ($T: typeid/[$N][N]$E) -> (m: T) #no_bounds_check
|
||||
return m
|
||||
}
|
||||
|
||||
trace :: builtin.matrix_trace
|
||||
transpose :: builtin.transpose
|
||||
transpose :: intrinsics.transpose
|
||||
|
||||
@(require_results)
|
||||
matrix_mul :: proc "contextless" (a, b: $M/matrix[$N, N]$E) -> (c: M)
|
||||
@@ -355,3 +354,273 @@ matrix_cast :: proc "contextless" (v: $A/matrix[$M, $N]$T, $Elem_Type: typeid) -
|
||||
@(require_results) to_quaternion64 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion64 { return array_cast(v, quaternion64) }
|
||||
@(require_results) to_quaternion128 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion128 { return array_cast(v, quaternion128) }
|
||||
@(require_results) to_quaternion256 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion256 { return array_cast(v, quaternion256) }
|
||||
|
||||
|
||||
hadamard_product :: intrinsics.hadamard_product
|
||||
matrix_flatten :: intrinsics.matrix_flatten
|
||||
|
||||
|
||||
determinant :: proc{
|
||||
matrix1x1_determinant,
|
||||
matrix2x2_determinant,
|
||||
matrix3x3_determinant,
|
||||
matrix4x4_determinant,
|
||||
}
|
||||
|
||||
adjugate :: proc{
|
||||
matrix1x1_adjugate,
|
||||
matrix2x2_adjugate,
|
||||
matrix3x3_adjugate,
|
||||
matrix4x4_adjugate,
|
||||
}
|
||||
|
||||
inverse_transpose :: proc{
|
||||
matrix1x1_inverse_transpose,
|
||||
matrix2x2_inverse_transpose,
|
||||
matrix3x3_inverse_transpose,
|
||||
matrix4x4_inverse_transpose,
|
||||
}
|
||||
|
||||
|
||||
inverse :: proc{
|
||||
matrix1x1_inverse,
|
||||
matrix2x2_inverse,
|
||||
matrix3x3_inverse,
|
||||
matrix4x4_inverse,
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
hermitian_adjoint :: proc "contextless" (m: $M/matrix[$N, N]$T) -> M where intrinsics.type_is_complex(T), N >= 1 {
|
||||
return conj(transpose(m))
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
trace :: proc "contextless" (m: $M/matrix[$N, N]$T) -> (trace: T) {
|
||||
for i in 0..<N {
|
||||
trace += m[i, i]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix_minor :: proc "contextless" (m: $M/matrix[$N, N]$T, #any_int row, column: int) -> (minor: T) where N > 1 {
|
||||
K :: int(N-1)
|
||||
cut_down: matrix[K, K]T
|
||||
for col_idx in 0..<K {
|
||||
j := col_idx + int(col_idx >= column)
|
||||
for row_idx in 0..<K {
|
||||
i := row_idx + int(row_idx >= row)
|
||||
cut_down[row_idx, col_idx] = m[i, j]
|
||||
}
|
||||
}
|
||||
return determinant(cut_down)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@(require_results)
|
||||
matrix1x1_determinant :: proc "contextless" (m: $M/matrix[1, 1]$T) -> (det: T) {
|
||||
return m[0, 0]
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix2x2_determinant :: proc "contextless" (m: $M/matrix[2, 2]$T) -> (det: T) {
|
||||
return m[0, 0]*m[1, 1] - m[0, 1]*m[1, 0]
|
||||
}
|
||||
@(require_results)
|
||||
matrix3x3_determinant :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (det: T) {
|
||||
a := +m[0, 0] * (m[1, 1] * m[2, 2] - m[1, 2] * m[2, 1])
|
||||
b := -m[0, 1] * (m[1, 0] * m[2, 2] - m[1, 2] * m[2, 0])
|
||||
c := +m[0, 2] * (m[1, 0] * m[2, 1] - m[1, 1] * m[2, 0])
|
||||
return a + b + c
|
||||
}
|
||||
@(require_results)
|
||||
matrix4x4_determinant :: proc "contextless" (m: $M/matrix[4, 4]$T) -> (det: T) {
|
||||
a := adjugate(m)
|
||||
#no_bounds_check for i in 0..<4 {
|
||||
det += m[0, i] * a[0, i]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@(require_results)
|
||||
matrix1x1_adjugate :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
|
||||
y = x
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix2x2_adjugate :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
y[0, 0] = +x[1, 1]
|
||||
y[0, 1] = -x[1, 0]
|
||||
y[1, 0] = -x[0, 1]
|
||||
y[1, 1] = +x[0, 0]
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix3x3_adjugate :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
|
||||
y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2])
|
||||
y[0, 1] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2])
|
||||
y[0, 2] = +(m[1, 0] * m[2, 1] - m[2, 0] * m[1, 1])
|
||||
y[1, 0] = -(m[0, 1] * m[2, 2] - m[2, 1] * m[0, 2])
|
||||
y[1, 1] = +(m[0, 0] * m[2, 2] - m[2, 0] * m[0, 2])
|
||||
y[1, 2] = -(m[0, 0] * m[2, 1] - m[2, 0] * m[0, 1])
|
||||
y[2, 0] = +(m[0, 1] * m[1, 2] - m[1, 1] * m[0, 2])
|
||||
y[2, 1] = -(m[0, 0] * m[1, 2] - m[1, 0] * m[0, 2])
|
||||
y[2, 2] = +(m[0, 0] * m[1, 1] - m[1, 0] * m[0, 1])
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
matrix4x4_adjugate :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
sign: T = 1 if (i + j) % 2 == 0 else -1
|
||||
y[i, j] = sign * matrix_minor(x, i, j)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix1x1_inverse_transpose :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
|
||||
y[0, 0] = 1/x[0, 0]
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix2x2_inverse_transpose :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0]
|
||||
when intrinsics.type_is_integer(T) {
|
||||
y[0, 0] = +x[1, 1] / d
|
||||
y[1, 0] = -x[0, 1] / d
|
||||
y[0, 1] = -x[1, 0] / d
|
||||
y[1, 1] = +x[0, 0] / d
|
||||
} else {
|
||||
id := 1 / d
|
||||
y[0, 0] = +x[1, 1] * id
|
||||
y[1, 0] = -x[0, 1] * id
|
||||
y[0, 1] = -x[1, 0] * id
|
||||
y[1, 1] = +x[0, 0] * id
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix3x3_inverse_transpose :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
d := determinant(x)
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[i, j] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[i, j] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix4x4_inverse_transpose :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
d: T
|
||||
for i in 0..<4 {
|
||||
d += x[0, i] * a[0, i]
|
||||
}
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[i, j] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[i, j] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix1x1_inverse :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
|
||||
y[0, 0] = 1/x[0, 0]
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix2x2_inverse :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0]
|
||||
when intrinsics.type_is_integer(T) {
|
||||
y[0, 0] = +x[1, 1] / d
|
||||
y[0, 1] = -x[0, 1] / d
|
||||
y[1, 0] = -x[1, 0] / d
|
||||
y[1, 1] = +x[0, 0] / d
|
||||
} else {
|
||||
id := 1 / d
|
||||
y[0, 0] = +x[1, 1] * id
|
||||
y[0, 1] = -x[0, 1] * id
|
||||
y[1, 0] = -x[1, 0] * id
|
||||
y[1, 1] = +x[0, 0] * id
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix3x3_inverse :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
d := determinant(x)
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[j, i] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[j, i] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix4x4_inverse :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
d: T
|
||||
for i in 0..<4 {
|
||||
d += x[0, i] * a[0, i]
|
||||
}
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[j, i] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[j, i] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
// core:math/linalg/glsl implements a GLSL-like mathematics library plus numerous other utility procedures
|
||||
package math_linalg_glsl
|
||||
|
||||
import "core:builtin"
|
||||
import "base:builtin"
|
||||
import "base:intrinsics"
|
||||
|
||||
TAU :: 6.28318530717958647692528676655900576
|
||||
PI :: 3.14159265358979323846264338327950288
|
||||
@@ -1838,30 +1839,281 @@ dquatMulDvec3 :: proc "c" (q: dquat, v: dvec3) -> dvec3 {
|
||||
|
||||
|
||||
|
||||
@(require_results) inverse_mat2 :: proc "c" (m: mat2) -> mat2 { return builtin.inverse(m) }
|
||||
@(require_results) inverse_mat3 :: proc "c" (m: mat3) -> mat3 { return builtin.inverse(m) }
|
||||
@(require_results) inverse_mat4 :: proc "c" (m: mat4) -> mat4 { return builtin.inverse(m) }
|
||||
@(require_results) inverse_dmat2 :: proc "c" (m: dmat2) -> dmat2 { return builtin.inverse(m) }
|
||||
@(require_results) inverse_dmat3 :: proc "c" (m: dmat3) -> dmat3 { return builtin.inverse(m) }
|
||||
@(require_results) inverse_dmat4 :: proc "c" (m: dmat4) -> dmat4 { return builtin.inverse(m) }
|
||||
@(require_results) inverse_mat2 :: proc "c" (m: mat2) -> mat2 { return inverse_matrix2x2(m) }
|
||||
@(require_results) inverse_mat3 :: proc "c" (m: mat3) -> mat3 { return inverse_matrix3x3(m) }
|
||||
@(require_results) inverse_mat4 :: proc "c" (m: mat4) -> mat4 { return inverse_matrix4x4(m) }
|
||||
@(require_results) inverse_dmat2 :: proc "c" (m: dmat2) -> dmat2 { return inverse_matrix2x2(m) }
|
||||
@(require_results) inverse_dmat3 :: proc "c" (m: dmat3) -> dmat3 { return inverse_matrix3x3(m) }
|
||||
@(require_results) inverse_dmat4 :: proc "c" (m: dmat4) -> dmat4 { return inverse_matrix4x4(m) }
|
||||
@(require_results) inverse_quat :: proc "c" (q: quat) -> quat { return 1/q }
|
||||
@(require_results) inverse_dquat :: proc "c" (q: dquat) -> dquat { return 1/q }
|
||||
|
||||
|
||||
transpose :: intrinsics.transpose
|
||||
|
||||
|
||||
determinant :: proc{
|
||||
determinant_matrix1x1,
|
||||
determinant_matrix2x2,
|
||||
determinant_matrix3x3,
|
||||
determinant_matrix4x4,
|
||||
}
|
||||
|
||||
adjugate :: proc{
|
||||
adjugate_matrix1x1,
|
||||
adjugate_matrix2x2,
|
||||
adjugate_matrix3x3,
|
||||
adjugate_matrix4x4,
|
||||
}
|
||||
|
||||
inverse_transpose :: proc{
|
||||
inverse_transpose_matrix1x1,
|
||||
inverse_transpose_matrix2x2,
|
||||
inverse_transpose_matrix3x3,
|
||||
inverse_transpose_matrix4x4,
|
||||
}
|
||||
|
||||
|
||||
inverse :: proc{
|
||||
inverse_mat2,
|
||||
inverse_mat3,
|
||||
inverse_mat4,
|
||||
inverse_dmat2,
|
||||
inverse_dmat3,
|
||||
inverse_dmat4,
|
||||
inverse_quat,
|
||||
inverse_dquat,
|
||||
inverse_matrix1x1,
|
||||
inverse_matrix2x2,
|
||||
inverse_matrix3x3,
|
||||
inverse_matrix4x4,
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
hermitian_adjoint :: proc "contextless" (m: $M/matrix[$N, N]$T) -> M where intrinsics.type_is_complex(T), N >= 1 {
|
||||
return conj(transpose(m))
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
trace :: proc "contextless" (m: $M/matrix[$N, N]$T) -> (trace: T) {
|
||||
for i in 0..<N {
|
||||
trace += m[i, i]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix_minor :: proc "contextless" (m: $M/matrix[$N, N]$T, #any_int row, column: int) -> (minor: T) where N > 1 {
|
||||
K :: int(N-1)
|
||||
cut_down: matrix[K, K]T
|
||||
for col_idx in 0..<K {
|
||||
j := col_idx + int(col_idx >= column)
|
||||
for row_idx in 0..<K {
|
||||
i := row_idx + int(row_idx >= row)
|
||||
cut_down[row_idx, col_idx] = m[i, j]
|
||||
}
|
||||
}
|
||||
return determinant(cut_down)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@(require_results)
|
||||
determinant_matrix1x1 :: proc "contextless" (m: $M/matrix[1, 1]$T) -> (det: T) {
|
||||
return m[0, 0]
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
determinant_matrix2x2 :: proc "contextless" (m: $M/matrix[2, 2]$T) -> (det: T) {
|
||||
return m[0, 0]*m[1, 1] - m[0, 1]*m[1, 0]
|
||||
}
|
||||
@(require_results)
|
||||
determinant_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (det: T) {
|
||||
a := +m[0, 0] * (m[1, 1] * m[2, 2] - m[1, 2] * m[2, 1])
|
||||
b := -m[0, 1] * (m[1, 0] * m[2, 2] - m[1, 2] * m[2, 0])
|
||||
c := +m[0, 2] * (m[1, 0] * m[2, 1] - m[1, 1] * m[2, 0])
|
||||
return a + b + c
|
||||
}
|
||||
@(require_results)
|
||||
determinant_matrix4x4 :: proc "contextless" (m: $M/matrix[4, 4]$T) -> (det: T) {
|
||||
a := adjugate(m)
|
||||
#no_bounds_check for i in 0..<4 {
|
||||
det += m[0, i] * a[0, i]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix1x1 :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
|
||||
y = x
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
y[0, 0] = +x[1, 1]
|
||||
y[0, 1] = -x[1, 0]
|
||||
y[1, 0] = -x[0, 1]
|
||||
y[1, 1] = +x[0, 0]
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
|
||||
y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2])
|
||||
y[0, 1] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2])
|
||||
y[0, 2] = +(m[1, 0] * m[2, 1] - m[2, 0] * m[1, 1])
|
||||
y[1, 0] = -(m[0, 1] * m[2, 2] - m[2, 1] * m[0, 2])
|
||||
y[1, 1] = +(m[0, 0] * m[2, 2] - m[2, 0] * m[0, 2])
|
||||
y[1, 2] = -(m[0, 0] * m[2, 1] - m[2, 0] * m[0, 1])
|
||||
y[2, 0] = +(m[0, 1] * m[1, 2] - m[1, 1] * m[0, 2])
|
||||
y[2, 1] = -(m[0, 0] * m[1, 2] - m[1, 0] * m[0, 2])
|
||||
y[2, 2] = +(m[0, 0] * m[1, 1] - m[1, 0] * m[0, 1])
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
sign: T = 1 if (i + j) % 2 == 0 else -1
|
||||
y[i, j] = sign * matrix_minor(x, i, j)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
inverse_transpose_matrix1x1 :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
|
||||
y[0, 0] = 1/x[0, 0]
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
inverse_transpose_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0]
|
||||
when intrinsics.type_is_integer(T) {
|
||||
y[0, 0] = +x[1, 1] / d
|
||||
y[1, 0] = -x[0, 1] / d
|
||||
y[0, 1] = -x[1, 0] / d
|
||||
y[1, 1] = +x[0, 0] / d
|
||||
} else {
|
||||
id := 1 / d
|
||||
y[0, 0] = +x[1, 1] * id
|
||||
y[1, 0] = -x[0, 1] * id
|
||||
y[0, 1] = -x[1, 0] * id
|
||||
y[1, 1] = +x[0, 0] * id
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
inverse_transpose_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
d := determinant(x)
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[i, j] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[i, j] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
inverse_transpose_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
d: T
|
||||
for i in 0..<4 {
|
||||
d += x[0, i] * a[0, i]
|
||||
}
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[i, j] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[i, j] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
inverse_matrix1x1 :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
|
||||
y[0, 0] = 1/x[0, 0]
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
inverse_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0]
|
||||
when intrinsics.type_is_integer(T) {
|
||||
y[0, 0] = +x[1, 1] / d
|
||||
y[0, 1] = -x[0, 1] / d
|
||||
y[1, 0] = -x[1, 0] / d
|
||||
y[1, 1] = +x[0, 0] / d
|
||||
} else {
|
||||
id := 1 / d
|
||||
y[0, 0] = +x[1, 1] * id
|
||||
y[0, 1] = -x[0, 1] * id
|
||||
y[1, 0] = -x[1, 0] * id
|
||||
y[1, 1] = +x[0, 0] * id
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
inverse_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
d := determinant(x)
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[j, i] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[j, i] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
inverse_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
d: T
|
||||
for i in 0..<4 {
|
||||
d += x[0, i] * a[0, i]
|
||||
}
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[j, i] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[j, i] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
transpose :: builtin.transpose
|
||||
inverse_transpose :: builtin.inverse_transpose
|
||||
adjugate :: builtin.adjugate
|
||||
hermitian_adjoint :: builtin.hermitian_adjoint
|
||||
minor :: builtin.matrix_minor
|
||||
determinant :: builtin.determinant
|
||||
trace :: builtin.matrix_trace
|
||||
@@ -1,7 +1,8 @@
|
||||
// core:math/linalg/hlsl implements a HLSL-like mathematics library plus numerous other utility procedures
|
||||
package math_linalg_hlsl
|
||||
|
||||
import "core:builtin"
|
||||
import "base:builtin"
|
||||
import "base:intrinsics"
|
||||
|
||||
TAU :: 6.28318530717958647692528676655900576
|
||||
PI :: 3.14159265358979323846264338327950288
|
||||
@@ -1471,14 +1472,14 @@ not :: proc{
|
||||
|
||||
|
||||
|
||||
@(require_results) inverse_float1x1 :: proc "c" (m: float1x1) -> float1x1 { return builtin.inverse(m) }
|
||||
@(require_results) inverse_float2x2 :: proc "c" (m: float2x2) -> float2x2 { return builtin.inverse(m) }
|
||||
@(require_results) inverse_float3x3 :: proc "c" (m: float3x3) -> float3x3 { return builtin.inverse(m) }
|
||||
@(require_results) inverse_float4x4 :: proc "c" (m: float4x4) -> float4x4 { return builtin.inverse(m) }
|
||||
@(require_results) inverse_double1x1 :: proc "c" (m: double1x1) -> double1x1 { return builtin.inverse(m) }
|
||||
@(require_results) inverse_double2x2 :: proc "c" (m: double2x2) -> double2x2 { return builtin.inverse(m) }
|
||||
@(require_results) inverse_double3x3 :: proc "c" (m: double3x3) -> double3x3 { return builtin.inverse(m) }
|
||||
@(require_results) inverse_double4x4 :: proc "c" (m: double4x4) -> double4x4 { return builtin.inverse(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) }
|
||||
@(require_results) inverse_float4x4 :: proc "c" (m: float4x4) -> float4x4 { return inverse_matrix4x4(m) }
|
||||
@(require_results) inverse_double1x1 :: proc "c" (m: double1x1) -> double1x1 { return inverse_matrix1x1(m) }
|
||||
@(require_results) inverse_double2x2 :: proc "c" (m: double2x2) -> double2x2 { return inverse_matrix2x2(m) }
|
||||
@(require_results) inverse_double3x3 :: proc "c" (m: double3x3) -> double3x3 { return inverse_matrix3x3(m) }
|
||||
@(require_results) inverse_double4x4 :: proc "c" (m: double4x4) -> double4x4 { return inverse_matrix4x4(m) }
|
||||
|
||||
inverse :: proc{
|
||||
inverse_float1x1,
|
||||
@@ -1489,15 +1490,275 @@ inverse :: proc{
|
||||
inverse_double2x2,
|
||||
inverse_double3x3,
|
||||
inverse_double4x4,
|
||||
|
||||
inverse_matrix1x1,
|
||||
inverse_matrix2x2,
|
||||
inverse_matrix3x3,
|
||||
inverse_matrix4x4,
|
||||
}
|
||||
|
||||
transpose :: builtin.transpose
|
||||
inverse_transpose :: builtin.inverse_transpose
|
||||
adjugate :: builtin.adjugate
|
||||
hermitian_adjoint :: builtin.hermitian_adjoint
|
||||
minor :: builtin.matrix_minor
|
||||
determinant :: builtin.determinant
|
||||
trace :: builtin.matrix_trace
|
||||
transpose :: intrinsics.transpose
|
||||
|
||||
|
||||
determinant :: proc{
|
||||
determinant_matrix1x1,
|
||||
determinant_matrix2x2,
|
||||
determinant_matrix3x3,
|
||||
determinant_matrix4x4,
|
||||
}
|
||||
|
||||
adjugate :: proc{
|
||||
adjugate_matrix1x1,
|
||||
adjugate_matrix2x2,
|
||||
adjugate_matrix3x3,
|
||||
adjugate_matrix4x4,
|
||||
}
|
||||
|
||||
inverse_transpose :: proc{
|
||||
inverse_transpose_matrix1x1,
|
||||
inverse_transpose_matrix2x2,
|
||||
inverse_transpose_matrix3x3,
|
||||
inverse_transpose_matrix4x4,
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
hermitian_adjoint :: proc "contextless" (m: $M/matrix[$N, N]$T) -> M where intrinsics.type_is_complex(T), N >= 1 {
|
||||
return conj(transpose(m))
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
trace :: proc "contextless" (m: $M/matrix[$N, N]$T) -> (trace: T) {
|
||||
for i in 0..<N {
|
||||
trace += m[i, i]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
matrix_minor :: proc "contextless" (m: $M/matrix[$N, N]$T, #any_int row, column: int) -> (minor: T) where N > 1 {
|
||||
K :: int(N-1)
|
||||
cut_down: matrix[K, K]T
|
||||
for col_idx in 0..<K {
|
||||
j := col_idx + int(col_idx >= column)
|
||||
for row_idx in 0..<K {
|
||||
i := row_idx + int(row_idx >= row)
|
||||
cut_down[row_idx, col_idx] = m[i, j]
|
||||
}
|
||||
}
|
||||
return determinant(cut_down)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@(require_results)
|
||||
determinant_matrix1x1 :: proc "contextless" (m: $M/matrix[1, 1]$T) -> (det: T) {
|
||||
return m[0, 0]
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
determinant_matrix2x2 :: proc "contextless" (m: $M/matrix[2, 2]$T) -> (det: T) {
|
||||
return m[0, 0]*m[1, 1] - m[0, 1]*m[1, 0]
|
||||
}
|
||||
@(require_results)
|
||||
determinant_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (det: T) {
|
||||
a := +m[0, 0] * (m[1, 1] * m[2, 2] - m[1, 2] * m[2, 1])
|
||||
b := -m[0, 1] * (m[1, 0] * m[2, 2] - m[1, 2] * m[2, 0])
|
||||
c := +m[0, 2] * (m[1, 0] * m[2, 1] - m[1, 1] * m[2, 0])
|
||||
return a + b + c
|
||||
}
|
||||
@(require_results)
|
||||
determinant_matrix4x4 :: proc "contextless" (m: $M/matrix[4, 4]$T) -> (det: T) {
|
||||
a := adjugate(m)
|
||||
#no_bounds_check for i in 0..<4 {
|
||||
det += m[0, i] * a[0, i]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix1x1 :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
|
||||
y = x
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
y[0, 0] = +x[1, 1]
|
||||
y[0, 1] = -x[1, 0]
|
||||
y[1, 0] = -x[0, 1]
|
||||
y[1, 1] = +x[0, 0]
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix3x3 :: proc "contextless" (m: $M/matrix[3, 3]$T) -> (y: M) {
|
||||
y[0, 0] = +(m[1, 1] * m[2, 2] - m[2, 1] * m[1, 2])
|
||||
y[0, 1] = -(m[1, 0] * m[2, 2] - m[2, 0] * m[1, 2])
|
||||
y[0, 2] = +(m[1, 0] * m[2, 1] - m[2, 0] * m[1, 1])
|
||||
y[1, 0] = -(m[0, 1] * m[2, 2] - m[2, 1] * m[0, 2])
|
||||
y[1, 1] = +(m[0, 0] * m[2, 2] - m[2, 0] * m[0, 2])
|
||||
y[1, 2] = -(m[0, 0] * m[2, 1] - m[2, 0] * m[0, 1])
|
||||
y[2, 0] = +(m[0, 1] * m[1, 2] - m[1, 1] * m[0, 2])
|
||||
y[2, 1] = -(m[0, 0] * m[1, 2] - m[1, 0] * m[0, 2])
|
||||
y[2, 2] = +(m[0, 0] * m[1, 1] - m[1, 0] * m[0, 1])
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
adjugate_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
sign: T = 1 if (i + j) % 2 == 0 else -1
|
||||
y[i, j] = sign * matrix_minor(x, i, j)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
inverse_transpose_matrix1x1 :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
|
||||
y[0, 0] = 1/x[0, 0]
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
inverse_transpose_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0]
|
||||
when intrinsics.type_is_integer(T) {
|
||||
y[0, 0] = +x[1, 1] / d
|
||||
y[1, 0] = -x[0, 1] / d
|
||||
y[0, 1] = -x[1, 0] / d
|
||||
y[1, 1] = +x[0, 0] / d
|
||||
} else {
|
||||
id := 1 / d
|
||||
y[0, 0] = +x[1, 1] * id
|
||||
y[1, 0] = -x[0, 1] * id
|
||||
y[0, 1] = -x[1, 0] * id
|
||||
y[1, 1] = +x[0, 0] * id
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
inverse_transpose_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
d := determinant(x)
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[i, j] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[i, j] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
inverse_transpose_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
d: T
|
||||
for i in 0..<4 {
|
||||
d += x[0, i] * a[0, i]
|
||||
}
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[i, j] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[i, j] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
inverse_matrix1x1 :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
|
||||
y[0, 0] = 1/x[0, 0]
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
inverse_matrix2x2 :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
||||
d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0]
|
||||
when intrinsics.type_is_integer(T) {
|
||||
y[0, 0] = +x[1, 1] / d
|
||||
y[0, 1] = -x[0, 1] / d
|
||||
y[1, 0] = -x[1, 0] / d
|
||||
y[1, 1] = +x[0, 0] / d
|
||||
} else {
|
||||
id := 1 / d
|
||||
y[0, 0] = +x[1, 1] * id
|
||||
y[0, 1] = -x[0, 1] * id
|
||||
y[1, 0] = -x[1, 0] * id
|
||||
y[1, 1] = +x[0, 0] * id
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
inverse_matrix3x3 :: proc "contextless" (x: $M/matrix[3, 3]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
d := determinant(x)
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[j, i] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<3 {
|
||||
for j in 0..<3 {
|
||||
y[i, j] = a[j, i] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@(require_results)
|
||||
inverse_matrix4x4 :: proc "contextless" (x: $M/matrix[4, 4]$T) -> (y: M) #no_bounds_check {
|
||||
a := adjugate(x)
|
||||
d: T
|
||||
for i in 0..<4 {
|
||||
d += x[0, i] * a[0, i]
|
||||
}
|
||||
when intrinsics.type_is_integer(T) {
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[j, i] / d
|
||||
}
|
||||
}
|
||||
} else {
|
||||
id := 1/d
|
||||
for i in 0..<4 {
|
||||
for j in 0..<4 {
|
||||
y[i, j] = a[j, i] * id
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
asfloat :: proc{
|
||||
asfloat_float,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package linalg
|
||||
|
||||
import "core:builtin"
|
||||
import "base:builtin"
|
||||
import "core:math"
|
||||
|
||||
F16_EPSILON :: 1e-3
|
||||
@@ -1447,16 +1447,16 @@ matrix3_adjoint :: proc{
|
||||
|
||||
|
||||
@(require_results)
|
||||
matrix3_inverse_transpose_f16 :: proc "contextless" (m: Matrix3f16) -> (inverse_transpose: Matrix3f16) {
|
||||
return builtin.inverse_transpose(m)
|
||||
matrix3_inverse_transpose_f16 :: proc "contextless" (m: Matrix3f16) -> (p: Matrix3f16) {
|
||||
return inverse_transpose(m)
|
||||
}
|
||||
@(require_results)
|
||||
matrix3_inverse_transpose_f32 :: proc "contextless" (m: Matrix3f32) -> (inverse_transpose: Matrix3f32) {
|
||||
return builtin.inverse_transpose(m)
|
||||
matrix3_inverse_transpose_f32 :: proc "contextless" (m: Matrix3f32) -> (p: Matrix3f32) {
|
||||
return inverse_transpose(m)
|
||||
}
|
||||
@(require_results)
|
||||
matrix3_inverse_transpose_f64 :: proc "contextless" (m: Matrix3f64) -> (inverse_transpose: Matrix3f64) {
|
||||
return builtin.inverse_transpose(m)
|
||||
matrix3_inverse_transpose_f64 :: proc "contextless" (m: Matrix3f64) -> (p: Matrix3f64) {
|
||||
return inverse_transpose(m)
|
||||
}
|
||||
matrix3_inverse_transpose :: proc{
|
||||
matrix3_inverse_transpose_f16,
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package math
|
||||
|
||||
import "core:intrinsics"
|
||||
import "core:builtin"
|
||||
import "base:intrinsics"
|
||||
import "base:builtin"
|
||||
_ :: intrinsics
|
||||
|
||||
Float_Class :: enum {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//+build !js
|
||||
package math
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
|
||||
@(default_calling_convention="none", private="file")
|
||||
foreign _ {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//+build js
|
||||
package math
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
|
||||
foreign import "odin_env"
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ Package core:math/rand implements various random number generators
|
||||
*/
|
||||
package rand
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
import "core:math"
|
||||
import "core:mem"
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package mem
|
||||
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
// NOTE(bill, 2019-12-31): These are defined in `package runtime` as they are used in the `context`. This is to prevent an import definition cycle.
|
||||
Allocator_Mode :: runtime.Allocator_Mode
|
||||
|
||||
+2
-134
@@ -1,8 +1,7 @@
|
||||
package mem
|
||||
|
||||
import "core:intrinsics"
|
||||
import "core:runtime"
|
||||
import "core:sync"
|
||||
import "base:intrinsics"
|
||||
import "base:runtime"
|
||||
|
||||
nil_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||
size, alignment: int,
|
||||
@@ -861,134 +860,3 @@ panic_allocator :: proc() -> Allocator {
|
||||
data = nil,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Tracking_Allocator_Entry :: struct {
|
||||
memory: rawptr,
|
||||
size: int,
|
||||
alignment: int,
|
||||
mode: Allocator_Mode,
|
||||
err: Allocator_Error,
|
||||
location: runtime.Source_Code_Location,
|
||||
}
|
||||
Tracking_Allocator_Bad_Free_Entry :: struct {
|
||||
memory: rawptr,
|
||||
location: runtime.Source_Code_Location,
|
||||
}
|
||||
Tracking_Allocator :: struct {
|
||||
backing: Allocator,
|
||||
allocation_map: map[rawptr]Tracking_Allocator_Entry,
|
||||
bad_free_array: [dynamic]Tracking_Allocator_Bad_Free_Entry,
|
||||
mutex: sync.Mutex,
|
||||
clear_on_free_all: bool,
|
||||
}
|
||||
|
||||
tracking_allocator_init :: proc(t: ^Tracking_Allocator, backing_allocator: Allocator, internals_allocator := context.allocator) {
|
||||
t.backing = backing_allocator
|
||||
t.allocation_map.allocator = internals_allocator
|
||||
t.bad_free_array.allocator = internals_allocator
|
||||
|
||||
if .Free_All in query_features(t.backing) {
|
||||
t.clear_on_free_all = true
|
||||
}
|
||||
}
|
||||
|
||||
tracking_allocator_destroy :: proc(t: ^Tracking_Allocator) {
|
||||
delete(t.allocation_map)
|
||||
delete(t.bad_free_array)
|
||||
}
|
||||
|
||||
|
||||
tracking_allocator_clear :: proc(t: ^Tracking_Allocator) {
|
||||
sync.mutex_lock(&t.mutex)
|
||||
clear(&t.allocation_map)
|
||||
clear(&t.bad_free_array)
|
||||
sync.mutex_unlock(&t.mutex)
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
tracking_allocator :: proc(data: ^Tracking_Allocator) -> Allocator {
|
||||
return Allocator{
|
||||
data = data,
|
||||
procedure = tracking_allocator_proc,
|
||||
}
|
||||
}
|
||||
|
||||
tracking_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||
size, alignment: int,
|
||||
old_memory: rawptr, old_size: int, loc := #caller_location) -> (result: []byte, err: Allocator_Error) {
|
||||
data := (^Tracking_Allocator)(allocator_data)
|
||||
|
||||
sync.mutex_guard(&data.mutex)
|
||||
|
||||
if mode == .Query_Info {
|
||||
info := (^Allocator_Query_Info)(old_memory)
|
||||
if info != nil && info.pointer != nil {
|
||||
if entry, ok := data.allocation_map[info.pointer]; ok {
|
||||
info.size = entry.size
|
||||
info.alignment = entry.alignment
|
||||
}
|
||||
info.pointer = nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if mode == .Free && old_memory != nil && old_memory not_in data.allocation_map {
|
||||
append(&data.bad_free_array, Tracking_Allocator_Bad_Free_Entry{
|
||||
memory = old_memory,
|
||||
location = loc,
|
||||
})
|
||||
} else {
|
||||
result = data.backing.procedure(data.backing.data, mode, size, alignment, old_memory, old_size, loc) or_return
|
||||
}
|
||||
result_ptr := raw_data(result)
|
||||
|
||||
if data.allocation_map.allocator.procedure == nil {
|
||||
data.allocation_map.allocator = context.allocator
|
||||
}
|
||||
|
||||
switch mode {
|
||||
case .Alloc, .Alloc_Non_Zeroed:
|
||||
data.allocation_map[result_ptr] = Tracking_Allocator_Entry{
|
||||
memory = result_ptr,
|
||||
size = size,
|
||||
mode = mode,
|
||||
alignment = alignment,
|
||||
err = err,
|
||||
location = loc,
|
||||
}
|
||||
case .Free:
|
||||
delete_key(&data.allocation_map, old_memory)
|
||||
case .Free_All:
|
||||
if data.clear_on_free_all {
|
||||
clear_map(&data.allocation_map)
|
||||
}
|
||||
case .Resize, .Resize_Non_Zeroed:
|
||||
if old_memory != result_ptr {
|
||||
delete_key(&data.allocation_map, old_memory)
|
||||
}
|
||||
data.allocation_map[result_ptr] = Tracking_Allocator_Entry{
|
||||
memory = result_ptr,
|
||||
size = size,
|
||||
mode = mode,
|
||||
alignment = alignment,
|
||||
err = err,
|
||||
location = loc,
|
||||
}
|
||||
|
||||
case .Query_Features:
|
||||
set := (^Allocator_Mode_Set)(old_memory)
|
||||
if set != nil {
|
||||
set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Query_Features, .Query_Info}
|
||||
}
|
||||
return nil, nil
|
||||
|
||||
case .Query_Info:
|
||||
unreachable()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package mem
|
||||
|
||||
import "core:runtime"
|
||||
import "core:intrinsics"
|
||||
import "base:runtime"
|
||||
import "base:intrinsics"
|
||||
|
||||
Byte :: runtime.Byte
|
||||
Kilobyte :: runtime.Kilobyte
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package mem
|
||||
|
||||
import "core:builtin"
|
||||
import "core:runtime"
|
||||
import "base:builtin"
|
||||
import "base:runtime"
|
||||
|
||||
Raw_Any :: runtime.Raw_Any
|
||||
Raw_String :: runtime.Raw_String
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
//+build !freestanding
|
||||
package mem
|
||||
|
||||
import "base:runtime"
|
||||
import "core:sync"
|
||||
|
||||
Tracking_Allocator_Entry :: struct {
|
||||
memory: rawptr,
|
||||
size: int,
|
||||
alignment: int,
|
||||
mode: Allocator_Mode,
|
||||
err: Allocator_Error,
|
||||
location: runtime.Source_Code_Location,
|
||||
}
|
||||
Tracking_Allocator_Bad_Free_Entry :: struct {
|
||||
memory: rawptr,
|
||||
location: runtime.Source_Code_Location,
|
||||
}
|
||||
Tracking_Allocator :: struct {
|
||||
backing: Allocator,
|
||||
allocation_map: map[rawptr]Tracking_Allocator_Entry,
|
||||
bad_free_array: [dynamic]Tracking_Allocator_Bad_Free_Entry,
|
||||
mutex: sync.Mutex,
|
||||
clear_on_free_all: bool,
|
||||
}
|
||||
|
||||
tracking_allocator_init :: proc(t: ^Tracking_Allocator, backing_allocator: Allocator, internals_allocator := context.allocator) {
|
||||
t.backing = backing_allocator
|
||||
t.allocation_map.allocator = internals_allocator
|
||||
t.bad_free_array.allocator = internals_allocator
|
||||
|
||||
if .Free_All in query_features(t.backing) {
|
||||
t.clear_on_free_all = true
|
||||
}
|
||||
}
|
||||
|
||||
tracking_allocator_destroy :: proc(t: ^Tracking_Allocator) {
|
||||
delete(t.allocation_map)
|
||||
delete(t.bad_free_array)
|
||||
}
|
||||
|
||||
|
||||
tracking_allocator_clear :: proc(t: ^Tracking_Allocator) {
|
||||
sync.mutex_lock(&t.mutex)
|
||||
clear(&t.allocation_map)
|
||||
clear(&t.bad_free_array)
|
||||
sync.mutex_unlock(&t.mutex)
|
||||
}
|
||||
|
||||
|
||||
@(require_results)
|
||||
tracking_allocator :: proc(data: ^Tracking_Allocator) -> Allocator {
|
||||
return Allocator{
|
||||
data = data,
|
||||
procedure = tracking_allocator_proc,
|
||||
}
|
||||
}
|
||||
|
||||
tracking_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||
size, alignment: int,
|
||||
old_memory: rawptr, old_size: int, loc := #caller_location) -> (result: []byte, err: Allocator_Error) {
|
||||
data := (^Tracking_Allocator)(allocator_data)
|
||||
|
||||
sync.mutex_guard(&data.mutex)
|
||||
|
||||
if mode == .Query_Info {
|
||||
info := (^Allocator_Query_Info)(old_memory)
|
||||
if info != nil && info.pointer != nil {
|
||||
if entry, ok := data.allocation_map[info.pointer]; ok {
|
||||
info.size = entry.size
|
||||
info.alignment = entry.alignment
|
||||
}
|
||||
info.pointer = nil
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if mode == .Free && old_memory != nil && old_memory not_in data.allocation_map {
|
||||
append(&data.bad_free_array, Tracking_Allocator_Bad_Free_Entry{
|
||||
memory = old_memory,
|
||||
location = loc,
|
||||
})
|
||||
} else {
|
||||
result = data.backing.procedure(data.backing.data, mode, size, alignment, old_memory, old_size, loc) or_return
|
||||
}
|
||||
result_ptr := raw_data(result)
|
||||
|
||||
if data.allocation_map.allocator.procedure == nil {
|
||||
data.allocation_map.allocator = context.allocator
|
||||
}
|
||||
|
||||
switch mode {
|
||||
case .Alloc, .Alloc_Non_Zeroed:
|
||||
data.allocation_map[result_ptr] = Tracking_Allocator_Entry{
|
||||
memory = result_ptr,
|
||||
size = size,
|
||||
mode = mode,
|
||||
alignment = alignment,
|
||||
err = err,
|
||||
location = loc,
|
||||
}
|
||||
case .Free:
|
||||
delete_key(&data.allocation_map, old_memory)
|
||||
case .Free_All:
|
||||
if data.clear_on_free_all {
|
||||
clear_map(&data.allocation_map)
|
||||
}
|
||||
case .Resize, .Resize_Non_Zeroed:
|
||||
if old_memory != result_ptr {
|
||||
delete_key(&data.allocation_map, old_memory)
|
||||
}
|
||||
data.allocation_map[result_ptr] = Tracking_Allocator_Entry{
|
||||
memory = result_ptr,
|
||||
size = size,
|
||||
mode = mode,
|
||||
alignment = alignment,
|
||||
err = err,
|
||||
location = loc,
|
||||
}
|
||||
|
||||
case .Query_Features:
|
||||
set := (^Allocator_Mode_Set)(old_memory)
|
||||
if set != nil {
|
||||
set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Free_All, .Resize, .Query_Features, .Query_Info}
|
||||
}
|
||||
return nil, nil
|
||||
|
||||
case .Query_Info:
|
||||
unreachable()
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package mem_virtual
|
||||
|
||||
import "core:mem"
|
||||
import "core:intrinsics"
|
||||
import "core:runtime"
|
||||
import "base:intrinsics"
|
||||
import "base:runtime"
|
||||
_ :: runtime
|
||||
|
||||
DEFAULT_PAGE_SIZE := uint(4096)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//+private
|
||||
package mem_virtual
|
||||
|
||||
foreign import libc "System.framework"
|
||||
foreign import libc "system:System.framework"
|
||||
import "core:c"
|
||||
|
||||
PROT_NONE :: 0x0 /* [MC2] no permissions */
|
||||
|
||||
@@ -21,7 +21,7 @@ package net
|
||||
Jeroen van Rijn: Cross platform unification, code style, documentation
|
||||
*/
|
||||
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
/*
|
||||
TUNEABLES - See also top of `dns.odin` for DNS configuration.
|
||||
|
||||
@@ -768,6 +768,7 @@ Struct_Type :: struct {
|
||||
tok_pos: tokenizer.Pos,
|
||||
poly_params: ^Field_List,
|
||||
align: ^Expr,
|
||||
field_align: ^Expr,
|
||||
where_token: tokenizer.Token,
|
||||
where_clauses: []^Expr,
|
||||
is_packed: bool,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package odin_ast
|
||||
|
||||
import "core:intrinsics"
|
||||
import "base:intrinsics"
|
||||
import "core:mem"
|
||||
import "core:fmt"
|
||||
import "core:reflect"
|
||||
@@ -314,6 +314,7 @@ clone_node :: proc(node: ^Node) -> ^Node {
|
||||
case ^Struct_Type:
|
||||
r.poly_params = auto_cast clone(r.poly_params)
|
||||
r.align = clone(r.align)
|
||||
r.field_align = clone(r.field_align)
|
||||
r.fields = auto_cast clone(r.fields)
|
||||
case ^Union_Type:
|
||||
r.poly_params = auto_cast clone(r.poly_params)
|
||||
|
||||
@@ -2547,6 +2547,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
|
||||
poly_params: ^ast.Field_List
|
||||
align: ^ast.Expr
|
||||
field_align: ^ast.Expr
|
||||
is_packed: bool
|
||||
is_raw_union: bool
|
||||
is_no_copy: bool
|
||||
@@ -2578,6 +2579,11 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
error(p, tag.pos, "duplicate struct tag '#%s'", tag.text)
|
||||
}
|
||||
align = parse_expr(p, true)
|
||||
case "field_align":
|
||||
if field_align != nil {
|
||||
error(p, tag.pos, "duplicate struct tag '#%s'", tag.text)
|
||||
}
|
||||
field_align = parse_expr(p, true)
|
||||
case "raw_union":
|
||||
if is_raw_union {
|
||||
error(p, tag.pos, "duplicate struct tag '#%s'", tag.text)
|
||||
@@ -2620,6 +2626,7 @@ parse_operand :: proc(p: ^Parser, lhs: bool) -> ^ast.Expr {
|
||||
st := ast.new(ast.Struct_Type, tok.pos, end_pos(close))
|
||||
st.poly_params = poly_params
|
||||
st.align = align
|
||||
st.field_align = field_align
|
||||
st.is_packed = is_packed
|
||||
st.is_raw_union = is_raw_union
|
||||
st.is_no_copy = is_no_copy
|
||||
|
||||
@@ -2,7 +2,7 @@ package os
|
||||
|
||||
import "core:strings"
|
||||
import "core:mem"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Errno) {
|
||||
dirp: Dir
|
||||
|
||||
@@ -2,7 +2,7 @@ package os
|
||||
|
||||
import win32 "core:sys/windows"
|
||||
import "core:strings"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
read_dir :: proc(fd: Handle, n: int, allocator := context.allocator) -> (fi: []File_Info, err: Errno) {
|
||||
find_data_to_file_info :: proc(base_path: string, d: ^win32.WIN32_FIND_DATAW) -> (fi: File_Info) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package os
|
||||
|
||||
import win32 "core:sys/windows"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
// lookup_env gets the value of the environment variable named by the key
|
||||
// If the variable is found in the environment the value (which can be empty) is returned and the boolean is true
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package os
|
||||
|
||||
import win32 "core:sys/windows"
|
||||
import "core:intrinsics"
|
||||
import "core:runtime"
|
||||
import "base:intrinsics"
|
||||
import "base:runtime"
|
||||
import "core:unicode/utf16"
|
||||
|
||||
is_path_separator :: proc(c: byte) -> bool {
|
||||
@@ -349,7 +349,7 @@ exists :: proc(path: string) -> bool {
|
||||
wpath := win32.utf8_to_wstring(path, context.temp_allocator)
|
||||
attribs := win32.GetFileAttributesW(wpath)
|
||||
|
||||
return i32(attribs) != win32.INVALID_FILE_ATTRIBUTES
|
||||
return attribs != win32.INVALID_FILE_ATTRIBUTES
|
||||
}
|
||||
|
||||
is_file :: proc(path: string) -> bool {
|
||||
@@ -357,7 +357,7 @@ is_file :: proc(path: string) -> bool {
|
||||
wpath := win32.utf8_to_wstring(path, context.temp_allocator)
|
||||
attribs := win32.GetFileAttributesW(wpath)
|
||||
|
||||
if i32(attribs) != win32.INVALID_FILE_ATTRIBUTES {
|
||||
if attribs != win32.INVALID_FILE_ATTRIBUTES {
|
||||
return attribs & win32.FILE_ATTRIBUTE_DIRECTORY == 0
|
||||
}
|
||||
return false
|
||||
@@ -368,7 +368,7 @@ is_dir :: proc(path: string) -> bool {
|
||||
wpath := win32.utf8_to_wstring(path, context.temp_allocator)
|
||||
attribs := win32.GetFileAttributesW(wpath)
|
||||
|
||||
if i32(attribs) != win32.INVALID_FILE_ATTRIBUTES {
|
||||
if attribs != win32.INVALID_FILE_ATTRIBUTES {
|
||||
return attribs & win32.FILE_ATTRIBUTE_DIRECTORY != 0
|
||||
}
|
||||
return false
|
||||
|
||||
+6
-92
@@ -1,5 +1,6 @@
|
||||
package os
|
||||
|
||||
import "base:runtime"
|
||||
import "core:mem"
|
||||
import "core:strconv"
|
||||
import "core:unicode/utf8"
|
||||
@@ -168,99 +169,12 @@ read_ptr :: proc(fd: Handle, data: rawptr, len: int) -> (int, Errno) {
|
||||
return read(fd, s)
|
||||
}
|
||||
|
||||
heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
|
||||
size, alignment: int,
|
||||
old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, mem.Allocator_Error) {
|
||||
//
|
||||
// NOTE(tetra, 2020-01-14): The heap doesn't respect alignment.
|
||||
// Instead, we overallocate by `alignment + size_of(rawptr) - 1`, and insert
|
||||
// padding. We also store the original pointer returned by heap_alloc right before
|
||||
// the pointer we return to the user.
|
||||
//
|
||||
heap_allocator_proc :: runtime.heap_allocator_proc
|
||||
heap_allocator :: runtime.heap_allocator
|
||||
|
||||
aligned_alloc :: proc(size, alignment: int, old_ptr: rawptr = nil, zero_memory := true) -> ([]byte, mem.Allocator_Error) {
|
||||
a := max(alignment, align_of(rawptr))
|
||||
space := size + a - 1
|
||||
|
||||
allocated_mem: rawptr
|
||||
if old_ptr != nil {
|
||||
original_old_ptr := mem.ptr_offset((^rawptr)(old_ptr), -1)^
|
||||
allocated_mem = heap_resize(original_old_ptr, space+size_of(rawptr))
|
||||
} else {
|
||||
allocated_mem = heap_alloc(space+size_of(rawptr), zero_memory)
|
||||
}
|
||||
aligned_mem := rawptr(mem.ptr_offset((^u8)(allocated_mem), size_of(rawptr)))
|
||||
|
||||
ptr := uintptr(aligned_mem)
|
||||
aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a)
|
||||
diff := int(aligned_ptr - ptr)
|
||||
if (size + diff) > space || allocated_mem == nil {
|
||||
return nil, .Out_Of_Memory
|
||||
}
|
||||
|
||||
aligned_mem = rawptr(aligned_ptr)
|
||||
mem.ptr_offset((^rawptr)(aligned_mem), -1)^ = allocated_mem
|
||||
|
||||
return mem.byte_slice(aligned_mem, size), nil
|
||||
}
|
||||
|
||||
aligned_free :: proc(p: rawptr) {
|
||||
if p != nil {
|
||||
heap_free(mem.ptr_offset((^rawptr)(p), -1)^)
|
||||
}
|
||||
}
|
||||
|
||||
aligned_resize :: proc(p: rawptr, old_size: int, new_size: int, new_alignment: int, zero_memory := true) -> (new_memory: []byte, err: mem.Allocator_Error) {
|
||||
if p == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
new_memory = aligned_alloc(new_size, new_alignment, p, zero_memory) or_return
|
||||
|
||||
// NOTE: heap_resize does not zero the new memory, so we do it
|
||||
if zero_memory && new_size > old_size {
|
||||
new_region := mem.raw_data(new_memory[old_size:])
|
||||
mem.zero(new_region, new_size - old_size)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
switch mode {
|
||||
case .Alloc, .Alloc_Non_Zeroed:
|
||||
return aligned_alloc(size, alignment, nil, mode == .Alloc)
|
||||
|
||||
case .Free:
|
||||
aligned_free(old_memory)
|
||||
|
||||
case .Free_All:
|
||||
return nil, .Mode_Not_Implemented
|
||||
|
||||
case .Resize, .Resize_Non_Zeroed:
|
||||
if old_memory == nil {
|
||||
return aligned_alloc(size, alignment, nil, mode == .Resize)
|
||||
}
|
||||
return aligned_resize(old_memory, old_size, size, alignment, mode == .Resize)
|
||||
|
||||
case .Query_Features:
|
||||
set := (^mem.Allocator_Mode_Set)(old_memory)
|
||||
if set != nil {
|
||||
set^ = {.Alloc, .Alloc_Non_Zeroed, .Free, .Resize, .Resize_Non_Zeroed, .Query_Features}
|
||||
}
|
||||
return nil, nil
|
||||
|
||||
case .Query_Info:
|
||||
return nil, .Mode_Not_Implemented
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
heap_allocator :: proc() -> mem.Allocator {
|
||||
return mem.Allocator{
|
||||
procedure = heap_allocator_proc,
|
||||
data = nil,
|
||||
}
|
||||
}
|
||||
heap_alloc :: runtime.heap_alloc
|
||||
heap_resize :: runtime.heap_resize
|
||||
heap_free :: runtime.heap_free
|
||||
|
||||
processor_core_count :: proc() -> int {
|
||||
return _processor_core_count()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package os2
|
||||
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
// get_env retrieves the value of the environment variable named by the key
|
||||
// It returns the value, which will be empty if the variable is not present
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//+private
|
||||
package os2
|
||||
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
_lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) {
|
||||
//TODO
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package os2
|
||||
|
||||
import win32 "core:sys/windows"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
_lookup_env :: proc(key: string, allocator: runtime.Allocator) -> (value: string, found: bool) {
|
||||
if key == "" {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package os2
|
||||
|
||||
import "core:io"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
General_Error :: enum u32 {
|
||||
None,
|
||||
|
||||
+22
-16
@@ -2,7 +2,7 @@ package os2
|
||||
|
||||
import "core:io"
|
||||
import "core:time"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
File :: struct {
|
||||
impl: _File,
|
||||
@@ -156,41 +156,46 @@ read_link :: proc(name: string, allocator: runtime.Allocator) -> (string, Error)
|
||||
}
|
||||
|
||||
|
||||
chdir :: proc(name: string) -> Error {
|
||||
chdir :: change_directory
|
||||
change_directory :: proc(name: string) -> Error {
|
||||
return _chdir(name)
|
||||
}
|
||||
|
||||
chmod :: proc(name: string, mode: File_Mode) -> Error {
|
||||
chmod :: change_mode
|
||||
change_mode :: proc(name: string, mode: File_Mode) -> Error {
|
||||
return _chmod(name, mode)
|
||||
}
|
||||
|
||||
chown :: proc(name: string, uid, gid: int) -> Error {
|
||||
chown :: change_owner
|
||||
change_owner :: proc(name: string, uid, gid: int) -> Error {
|
||||
return _chown(name, uid, gid)
|
||||
}
|
||||
|
||||
fchdir :: proc(f: ^File) -> Error {
|
||||
fchdir :: fchange_directory
|
||||
fchange_directory :: proc(f: ^File) -> Error {
|
||||
return _fchdir(f)
|
||||
}
|
||||
|
||||
fchmod :: proc(f: ^File, mode: File_Mode) -> Error {
|
||||
fchmod :: fchange_mode
|
||||
fchange_mode :: proc(f: ^File, mode: File_Mode) -> Error {
|
||||
return _fchmod(f, mode)
|
||||
}
|
||||
|
||||
fchown :: proc(f: ^File, uid, gid: int) -> Error {
|
||||
fchown :: fchange_owner
|
||||
fchange_owner :: proc(f: ^File, uid, gid: int) -> Error {
|
||||
return _fchown(f, uid, gid)
|
||||
}
|
||||
|
||||
|
||||
|
||||
lchown :: proc(name: string, uid, gid: int) -> Error {
|
||||
lchown :: change_owner_do_not_follow_links
|
||||
change_owner_do_not_follow_links :: proc(name: string, uid, gid: int) -> Error {
|
||||
return _lchown(name, uid, gid)
|
||||
}
|
||||
|
||||
|
||||
chtimes :: proc(name: string, atime, mtime: time.Time) -> Error {
|
||||
chtimes :: change_times
|
||||
change_times :: proc(name: string, atime, mtime: time.Time) -> Error {
|
||||
return _chtimes(name, atime, mtime)
|
||||
}
|
||||
fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error {
|
||||
fchtimes :: fchange_times
|
||||
fchange_times :: proc(f: ^File, atime, mtime: time.Time) -> Error {
|
||||
return _fchtimes(f, atime, mtime)
|
||||
}
|
||||
|
||||
@@ -202,7 +207,8 @@ is_file :: proc(path: string) -> bool {
|
||||
return _is_file(path)
|
||||
}
|
||||
|
||||
is_dir :: proc(path: string) -> bool {
|
||||
is_dir :: is_directory
|
||||
is_directory :: proc(path: string) -> bool {
|
||||
return _is_dir(path)
|
||||
}
|
||||
|
||||
@@ -213,7 +219,7 @@ copy_file :: proc(dst_path, src_path: string) -> Error {
|
||||
|
||||
info := fstat(src, _file_allocator()) or_return
|
||||
defer file_info_delete(info, _file_allocator())
|
||||
if info.is_dir {
|
||||
if info.is_directory {
|
||||
return .Invalid_File
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ package os2
|
||||
import "core:io"
|
||||
import "core:time"
|
||||
import "core:strings"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
import "core:sys/unix"
|
||||
|
||||
INVALID_HANDLE :: -1
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package os2
|
||||
|
||||
import "core:mem"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
import "core:strconv"
|
||||
import "core:unicode/utf8"
|
||||
|
||||
@@ -74,14 +74,21 @@ read_ptr :: proc(f: ^File, data: rawptr, len: int) -> (n: int, err: Error) {
|
||||
}
|
||||
|
||||
|
||||
read_entire_file :: proc{
|
||||
read_entire_file_from_path,
|
||||
read_entire_file_from_file,
|
||||
}
|
||||
|
||||
read_entire_file :: proc(name: string, allocator: runtime.Allocator) -> (data: []byte, err: Error) {
|
||||
read_entire_file_from_path :: proc(name: string, allocator: runtime.Allocator) -> (data: []byte, err: Error) {
|
||||
f, ferr := open(name)
|
||||
if ferr != nil {
|
||||
return nil, ferr
|
||||
}
|
||||
defer close(f)
|
||||
return read_entire_file_from_file(f, allocator)
|
||||
}
|
||||
|
||||
read_entire_file_from_file :: proc(f: ^File, allocator: runtime.Allocator) -> (data: []byte, err: Error) {
|
||||
size: int
|
||||
if size64, err := file_size(f); err == nil {
|
||||
if i64(int(size64)) != size64 {
|
||||
|
||||
@@ -4,7 +4,7 @@ package os2
|
||||
import "core:io"
|
||||
import "core:mem"
|
||||
import "core:sync"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
import "core:strings"
|
||||
import "core:time"
|
||||
import "core:unicode/utf16"
|
||||
@@ -454,7 +454,7 @@ _remove :: proc(name: string) -> Error {
|
||||
|
||||
if err != err1 {
|
||||
a := win32.GetFileAttributesW(p)
|
||||
if a == ~u32(0) {
|
||||
if a == win32.INVALID_FILE_ATTRIBUTES {
|
||||
err = _get_platform_error()
|
||||
} else {
|
||||
if a & win32.FILE_ATTRIBUTE_DIRECTORY != 0 {
|
||||
@@ -704,13 +704,13 @@ _fchtimes :: proc(f: ^File, atime, mtime: time.Time) -> Error {
|
||||
_exists :: proc(path: string) -> bool {
|
||||
wpath := _fix_long_path(path)
|
||||
attribs := win32.GetFileAttributesW(wpath)
|
||||
return i32(attribs) != win32.INVALID_FILE_ATTRIBUTES
|
||||
return attribs != win32.INVALID_FILE_ATTRIBUTES
|
||||
}
|
||||
|
||||
_is_file :: proc(path: string) -> bool {
|
||||
wpath := _fix_long_path(path)
|
||||
attribs := win32.GetFileAttributesW(wpath)
|
||||
if i32(attribs) != win32.INVALID_FILE_ATTRIBUTES {
|
||||
if attribs != win32.INVALID_FILE_ATTRIBUTES {
|
||||
return attribs & win32.FILE_ATTRIBUTE_DIRECTORY == 0
|
||||
}
|
||||
return false
|
||||
@@ -719,7 +719,7 @@ _is_file :: proc(path: string) -> bool {
|
||||
_is_dir :: proc(path: string) -> bool {
|
||||
wpath := _fix_long_path(path)
|
||||
attribs := win32.GetFileAttributesW(wpath)
|
||||
if i32(attribs) != win32.INVALID_FILE_ATTRIBUTES {
|
||||
if attribs != win32.INVALID_FILE_ATTRIBUTES {
|
||||
return attribs & win32.FILE_ATTRIBUTE_DIRECTORY != 0
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package os2
|
||||
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
heap_allocator :: proc() -> runtime.Allocator {
|
||||
return runtime.Allocator{
|
||||
|
||||
@@ -200,7 +200,7 @@ _heap_allocator_proc :: proc(allocator_data: rawptr, mode: mem.Allocator_Mode,
|
||||
case .Free_All:
|
||||
return nil, .Mode_Not_Implemented
|
||||
|
||||
case .Resize:
|
||||
case .Resize, .Resize_Non_Zeroed:
|
||||
if old_memory == nil {
|
||||
return aligned_alloc(size, alignment)
|
||||
}
|
||||
|
||||
+10
-6
@@ -1,6 +1,6 @@
|
||||
package os2
|
||||
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
Path_Separator :: _Path_Separator // OS-Specific
|
||||
Path_List_Separator :: _Path_List_Separator // OS-Specific
|
||||
@@ -9,11 +9,13 @@ is_path_separator :: proc(c: byte) -> bool {
|
||||
return _is_path_separator(c)
|
||||
}
|
||||
|
||||
mkdir :: proc(name: string, perm: File_Mode) -> Error {
|
||||
mkdir :: make_directory
|
||||
make_directory :: proc(name: string, perm: File_Mode) -> Error {
|
||||
return _mkdir(name, perm)
|
||||
}
|
||||
|
||||
mkdir_all :: proc(path: string, perm: File_Mode) -> Error {
|
||||
mkdir_all :: make_directory_all
|
||||
make_directory_all :: proc(path: string, perm: File_Mode) -> Error {
|
||||
return _mkdir_all(path, perm)
|
||||
}
|
||||
|
||||
@@ -22,10 +24,12 @@ remove_all :: proc(path: string) -> Error {
|
||||
}
|
||||
|
||||
|
||||
|
||||
getwd :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) {
|
||||
getwd :: get_working_directory
|
||||
get_working_directory :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) {
|
||||
return _getwd(allocator)
|
||||
}
|
||||
setwd :: proc(dir: string) -> (err: Error) {
|
||||
|
||||
setwd :: set_working_directory
|
||||
set_working_directory :: proc(dir: string) -> (err: Error) {
|
||||
return _setwd(dir)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ package os2
|
||||
|
||||
import "core:strings"
|
||||
import "core:strconv"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
import "core:sys/unix"
|
||||
|
||||
_Path_Separator :: '/'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package os2
|
||||
|
||||
import win32 "core:sys/windows"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
import "core:strings"
|
||||
|
||||
_Path_Separator :: '\\'
|
||||
@@ -33,7 +33,7 @@ _mkdir_all :: proc(path: string, perm: File_Mode) -> Error {
|
||||
|
||||
dir, err := stat(path, _temp_allocator())
|
||||
if err == nil {
|
||||
if dir.is_dir {
|
||||
if dir.is_directory {
|
||||
return nil
|
||||
}
|
||||
return .Exist
|
||||
@@ -60,7 +60,7 @@ _mkdir_all :: proc(path: string, perm: File_Mode) -> Error {
|
||||
err = mkdir(path, perm)
|
||||
if err != nil {
|
||||
dir1, err1 := lstat(path, _temp_allocator())
|
||||
if err1 == nil && dir1.is_dir {
|
||||
if err1 == nil && dir1.is_directory {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
|
||||
@@ -2,7 +2,7 @@ package os2
|
||||
|
||||
import "core:sync"
|
||||
import "core:time"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
args: []string
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
package os2
|
||||
|
||||
import "core:time"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
File_Info :: struct {
|
||||
fullpath: string,
|
||||
name: string,
|
||||
size: i64,
|
||||
mode: File_Mode,
|
||||
is_dir: bool,
|
||||
fullpath: string,
|
||||
name: string,
|
||||
size: i64,
|
||||
mode: File_Mode,
|
||||
is_directory: bool,
|
||||
creation_time: time.Time,
|
||||
modification_time: time.Time,
|
||||
access_time: time.Time,
|
||||
@@ -33,7 +33,8 @@ stat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) {
|
||||
return _stat(name, allocator)
|
||||
}
|
||||
|
||||
lstat :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) {
|
||||
lstat :: stat_do_not_follow_links
|
||||
stat_do_not_follow_links :: proc(name: string, allocator: runtime.Allocator) -> (File_Info, Error) {
|
||||
return _lstat(name, allocator)
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
package os2
|
||||
|
||||
import "core:time"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
import "core:strings"
|
||||
import "core:sys/unix"
|
||||
import "core:path/filepath"
|
||||
@@ -101,7 +101,7 @@ _fstat_internal :: proc(fd: int, allocator: runtime.Allocator) -> (File_Info, Er
|
||||
name = "",
|
||||
size = s.size,
|
||||
mode = 0,
|
||||
is_dir = S_ISDIR(s.mode),
|
||||
is_directory = S_ISDIR(s.mode),
|
||||
modification_time = time.Time {s.modified.seconds},
|
||||
access_time = time.Time {s.last_access.seconds},
|
||||
creation_time = time.Time{0}, // regular stat does not provide this
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//+private
|
||||
package os2
|
||||
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
import "core:time"
|
||||
import "core:strings"
|
||||
import win32 "core:sys/windows"
|
||||
@@ -228,7 +228,7 @@ _file_info_from_win32_file_attribute_data :: proc(d: ^win32.WIN32_FILE_ATTRIBUTE
|
||||
fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow)
|
||||
|
||||
fi.mode |= _file_mode_from_file_attributes(d.dwFileAttributes, nil, 0)
|
||||
fi.is_dir = fi.mode & File_Mode_Dir != 0
|
||||
fi.is_directory = fi.mode & File_Mode_Dir != 0
|
||||
|
||||
fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime))
|
||||
fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime))
|
||||
@@ -245,7 +245,7 @@ _file_info_from_win32_find_data :: proc(d: ^win32.WIN32_FIND_DATAW, name: string
|
||||
fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow)
|
||||
|
||||
fi.mode |= _file_mode_from_file_attributes(d.dwFileAttributes, nil, 0)
|
||||
fi.is_dir = fi.mode & File_Mode_Dir != 0
|
||||
fi.is_directory = fi.mode & File_Mode_Dir != 0
|
||||
|
||||
fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime))
|
||||
fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime))
|
||||
@@ -282,7 +282,7 @@ _file_info_from_get_file_information_by_handle :: proc(path: string, h: win32.HA
|
||||
fi.size = i64(d.nFileSizeHigh)<<32 + i64(d.nFileSizeLow)
|
||||
|
||||
fi.mode |= _file_mode_from_file_attributes(ti.FileAttributes, h, ti.ReparseTag)
|
||||
fi.is_dir = fi.mode & File_Mode_Dir != 0
|
||||
fi.is_directory = fi.mode & File_Mode_Dir != 0
|
||||
|
||||
fi.creation_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftCreationTime))
|
||||
fi.modification_time = time.unix(0, win32.FILETIME_as_unix_nanoseconds(d.ftLastWriteTime))
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
package os2
|
||||
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
create_temp :: proc(dir, pattern: string) -> (^File, Error) {
|
||||
create_temp_file :: proc(dir, pattern: string) -> (^File, Error) {
|
||||
return _create_temp(dir, pattern)
|
||||
}
|
||||
|
||||
mkdir_temp :: proc(dir, pattern: string, allocator: runtime.Allocator) -> (string, Error) {
|
||||
mkdir_temp :: make_directory_temp
|
||||
make_directory_temp :: proc(dir, pattern: string, allocator: runtime.Allocator) -> (string, Error) {
|
||||
return _mkdir_temp(dir, pattern, allocator)
|
||||
}
|
||||
|
||||
temp_dir :: proc(allocator: runtime.Allocator) -> (string, Error) {
|
||||
temp_dir :: temp_directory
|
||||
temp_directory :: proc(allocator: runtime.Allocator) -> (string, Error) {
|
||||
return _temp_dir(allocator)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//+private
|
||||
package os2
|
||||
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
|
||||
_create_temp :: proc(dir, pattern: string) -> (^File, Error) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//+private
|
||||
package os2
|
||||
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
import win32 "core:sys/windows"
|
||||
|
||||
_create_temp :: proc(dir, pattern: string) -> (^File, Error) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package os2
|
||||
|
||||
import "core:strings"
|
||||
import "core:runtime"
|
||||
import "base:runtime"
|
||||
|
||||
user_cache_dir :: proc(allocator: runtime.Allocator) -> (dir: string, err: Error) {
|
||||
#partial switch ODIN_OS {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user