Browse Source

Merge branch 'odin-lang:master' into master

marcs feh 1 year ago
parent
commit
fc113315f6
100 changed files with 1289 additions and 276 deletions
  1. 3 0
      .github/workflows/nightly.yml
  2. 0 0
      base/builtin/builtin.odin
  3. 6 0
      base/intrinsics/intrinsics.odin
  4. 1 1
      base/runtime/core.odin
  5. 5 37
      base/runtime/core_builtin.odin
  6. 2 1
      base/runtime/core_builtin_soa.odin
  7. 1 1
      base/runtime/default_allocators_arena.odin
  8. 12 0
      base/runtime/default_allocators_general.odin
  9. 0 8
      base/runtime/default_allocators_nil.odin
  10. 0 0
      base/runtime/default_temporary_allocator.odin
  11. 3 2
      base/runtime/docs.odin
  12. 0 0
      base/runtime/dynamic_array_internal.odin
  13. 1 1
      base/runtime/dynamic_map_internal.odin
  14. 1 1
      base/runtime/entry_unix.odin
  15. 0 0
      base/runtime/entry_unix_no_crt_amd64.asm
  16. 0 0
      base/runtime/entry_unix_no_crt_darwin_arm64.asm
  17. 0 0
      base/runtime/entry_unix_no_crt_i386.asm
  18. 1 1
      base/runtime/entry_wasm.odin
  19. 1 1
      base/runtime/entry_windows.odin
  20. 0 0
      base/runtime/error_checks.odin
  21. 110 0
      base/runtime/heap_allocator.odin
  22. 15 0
      base/runtime/heap_allocator_other.odin
  23. 38 0
      base/runtime/heap_allocator_unix.odin
  24. 39 0
      base/runtime/heap_allocator_windows.odin
  25. 4 78
      base/runtime/internal.odin
  26. 7 0
      base/runtime/os_specific.odin
  27. 22 0
      base/runtime/os_specific_bsd.odin
  28. 26 0
      base/runtime/os_specific_darwin.odin
  29. 2 1
      base/runtime/os_specific_freestanding.odin
  30. 2 1
      base/runtime/os_specific_js.odin
  31. 24 0
      base/runtime/os_specific_linux.odin
  32. 2 1
      base/runtime/os_specific_wasi.odin
  33. 51 0
      base/runtime/os_specific_windows.odin
  34. 6 6
      base/runtime/print.odin
  35. 0 0
      base/runtime/procs.odin
  36. 1 1
      base/runtime/procs_darwin.odin
  37. 0 0
      base/runtime/procs_js.odin
  38. 0 0
      base/runtime/procs_wasm.odin
  39. 0 0
      base/runtime/procs_windows_amd64.asm
  40. 0 0
      base/runtime/procs_windows_amd64.odin
  41. 0 0
      base/runtime/procs_windows_i386.odin
  42. 1 1
      base/runtime/udivmod128.odin
  43. 1 1
      core/bufio/scanner.odin
  44. 1 1
      core/c/c.odin
  45. 1 1
      core/c/libc/complex.odin
  46. 1 1
      core/c/libc/math.odin
  47. 1 1
      core/c/libc/stdarg.odin
  48. 1 1
      core/c/libc/stdatomic.odin
  49. 1 1
      core/c/libc/string.odin
  50. 1 1
      core/compress/common.odin
  51. 1 1
      core/compress/shoco/shoco.odin
  52. 1 1
      core/container/bit_array/bit_array.odin
  53. 1 1
      core/container/intrusive/list/intrusive_list.odin
  54. 2 2
      core/container/lru/lru_cache.odin
  55. 1 1
      core/container/priority_queue/priority_queue.odin
  56. 2 2
      core/container/queue/queue.odin
  57. 2 2
      core/container/small_array/small_array.odin
  58. 2 2
      core/container/topological_sort/topological_sort.odin
  59. 2 2
      core/dynlib/lib.odin
  60. 1 1
      core/dynlib/lib_windows.odin
  61. 1 1
      core/encoding/endian/endian.odin
  62. 1 1
      core/encoding/json/marshal.odin
  63. 1 1
      core/encoding/json/unmarshal.odin
  64. 2 2
      core/encoding/xml/xml_reader.odin
  65. 4 18
      core/fmt/fmt.odin
  66. 1 1
      core/fmt/fmt_os.odin
  67. 1 1
      core/hash/crc32.odin
  68. 1 1
      core/hash/hash.odin
  69. 2 2
      core/hash/xxhash/common.odin
  70. 1 1
      core/hash/xxhash/streaming.odin
  71. 1 1
      core/hash/xxhash/xxhash_3.odin
  72. 1 1
      core/hash/xxhash/xxhash_32.odin
  73. 1 1
      core/hash/xxhash/xxhash_64.odin
  74. 1 1
      core/image/common.odin
  75. 1 1
      core/image/netpbm/netpbm.odin
  76. 1 1
      core/image/png/helpers.odin
  77. 2 2
      core/image/png/png.odin
  78. 1 1
      core/io/io.odin
  79. 1 0
      core/log/file_console_logger.odin
  80. 1 1
      core/log/log.odin
  81. 1 1
      core/log/log_allocator.odin
  82. 1 1
      core/math/big/common.odin
  83. 1 1
      core/math/big/helpers.odin
  84. 2 2
      core/math/big/internal.odin
  85. 1 1
      core/math/big/private.odin
  86. 1 1
      core/math/big/public.odin
  87. 1 1
      core/math/big/radix.odin
  88. 2 2
      core/math/big/rat.odin
  89. 1 1
      core/math/big/tune.odin
  90. 1 1
      core/math/bits/bits.odin
  91. 1 1
      core/math/cmplx/cmplx.odin
  92. 1 1
      core/math/cmplx/cmplx_invtrig.odin
  93. 1 1
      core/math/ease/ease.odin
  94. 1 1
      core/math/fixed/fixed.odin
  95. 1 1
      core/math/linalg/extended.odin
  96. 274 5
      core/math/linalg/general.odin
  97. 276 24
      core/math/linalg/glsl/linalg_glsl.odin
  98. 277 16
      core/math/linalg/hlsl/linalg_hlsl.odin
  99. 7 7
      core/math/linalg/specific.odin
  100. 2 2
      core/math/math.odin

+ 3 - 0
.github/workflows/nightly.yml

@@ -29,6 +29,7 @@ jobs:
           cp LICENSE dist
           cp LLVM-C.dll dist
           cp -r shared dist
+          cp -r base dist
           cp -r core dist
           cp -r vendor dist
           cp -r bin dist
@@ -56,6 +57,7 @@ jobs:
           cp LICENSE dist
           cp libLLVM* dist
           cp -r shared dist
+          cp -r base dist
           cp -r core dist
           cp -r vendor dist
           cp -r examples dist
@@ -85,6 +87,7 @@ jobs:
           cp odin dist
           cp LICENSE dist
           cp -r shared dist
+          cp -r base dist
           cp -r core dist
           cp -r vendor dist
           cp -r examples dist

+ 0 - 0
core/builtin/builtin.odin → base/builtin/builtin.odin


+ 6 - 0
core/intrinsics/intrinsics.odin → base/intrinsics/intrinsics.odin

@@ -5,6 +5,12 @@ package intrinsics
 // Package-Related
 is_package_imported :: proc(package_name: string) -> bool ---
 
+// Matrix Related Procedures
+transpose        :: proc(m: $T/matrix[$R, $C]$E)    -> matrix[C, R]E ---
+outer_product    :: proc(a: $A/[$X]$E, b: $B/[$Y]E) -> matrix[X, Y]E ---
+hadamard_product :: proc(a, b: $T/matrix[$R, $C]$E) -> T ---
+matrix_flatten   :: proc(m: $T/matrix[$R, $C]$E)    -> [R*C]E ---
+
 // Types
 soa_struct :: proc($N: int, $T: typeid) -> type/#soa[N]T
 

+ 1 - 1
core/runtime/core.odin → base/runtime/core.odin

@@ -21,7 +21,7 @@
 //+no-instrumentation
 package runtime
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 // NOTE(bill): This must match the compiler's
 Calling_Convention :: enum u8 {

+ 5 - 37
core/runtime/core_builtin.odin → base/runtime/core_builtin.odin

@@ -1,6 +1,6 @@
 package runtime
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 @builtin
 Maybe :: union($T: typeid) {T}
@@ -122,7 +122,7 @@ pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #no_bou
 // `pop_safe` trys to remove and return the end value of dynamic array `array` and reduces the length of `array` by 1.
 // If the operation is not possible, it will return false.
 @builtin
-pop_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check {
+pop_safe :: proc "contextless" (array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check {
 	if len(array) == 0 {
 		return
 	}
@@ -148,7 +148,7 @@ pop_front :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: E) #
 // `pop_front_safe` trys to return and remove the first value of dynamic array `array` and reduces the length of `array` by 1.
 // If the operation is not possible, it will return false.
 @builtin
-pop_front_safe :: proc(array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check {
+pop_front_safe :: proc "contextless" (array: ^$T/[dynamic]$E) -> (res: E, ok: bool) #no_bounds_check {
 	if len(array) == 0 {
 		return
 	}
@@ -312,6 +312,7 @@ make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, alloca
 @(builtin, require_results)
 make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_allocator_error {
 	make_dynamic_array_error_loc(loc, len, cap)
+	array.allocator = allocator // initialize allocator before just in case it fails to allocate any memory
 	data := mem_alloc_bytes(size_of(E)*cap, align_of(E), allocator, loc) or_return
 	s := Raw_Dynamic_Array{raw_data(data), len, cap, allocator}
 	if data == nil && size_of(E) != 0 {
@@ -825,40 +826,7 @@ map_insert :: proc(m: ^$T/map[$K]$V, key: K, value: V, loc := #caller_location)
 
 
 @builtin
-incl_elem :: proc(s: ^$S/bit_set[$E; $U], elem: E) {
-	s^ |= {elem}
-}
-@builtin
-incl_elems :: proc(s: ^$S/bit_set[$E; $U], elems: ..E) {
-	for elem in elems {
-		s^ |= {elem}
-	}
-}
-@builtin
-incl_bit_set :: proc(s: ^$S/bit_set[$E; $U], other: S) {
-	s^ |= other
-}
-@builtin
-excl_elem :: proc(s: ^$S/bit_set[$E; $U], elem: E) {
-	s^ &~= {elem}
-}
-@builtin
-excl_elems :: proc(s: ^$S/bit_set[$E; $U], elems: ..E) {
-	for elem in elems {
-		s^ &~= {elem}
-	}
-}
-@builtin
-excl_bit_set :: proc(s: ^$S/bit_set[$E; $U], other: S) {
-	s^ &~= other
-}
-
-@builtin incl :: proc{incl_elem, incl_elems, incl_bit_set}
-@builtin excl :: proc{excl_elem, excl_elems, excl_bit_set}
-
-
-@builtin
-card :: proc(s: $S/bit_set[$E; $U]) -> int {
+card :: proc "contextless" (s: $S/bit_set[$E; $U]) -> int {
 	when size_of(S) == 1 {
 		return int(intrinsics.count_ones(transmute(u8)s))
 	} else when size_of(S) == 2 {

+ 2 - 1
core/runtime/core_builtin_soa.odin → base/runtime/core_builtin_soa.odin

@@ -1,6 +1,6 @@
 package runtime
 
-import "core:intrinsics"
+import "base:intrinsics"
 _ :: intrinsics
 
 /*
@@ -86,6 +86,7 @@ make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, alloc
 		return
 	}
 
+	array.allocator = allocator
 	footer := raw_soa_footer(&array)
 	if size_of(E) == 0 {
 		footer.len = length

+ 1 - 1
core/runtime/default_allocators_arena.odin → base/runtime/default_allocators_arena.odin

@@ -1,6 +1,6 @@
 package runtime
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE :: uint(DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE)
 

+ 12 - 0
base/runtime/default_allocators_general.odin

@@ -0,0 +1,12 @@
+package runtime
+
+when ODIN_DEFAULT_TO_NIL_ALLOCATOR {
+	default_allocator_proc :: nil_allocator_proc
+	default_allocator :: nil_allocator
+} else when ODIN_DEFAULT_TO_PANIC_ALLOCATOR {
+	default_allocator_proc :: panic_allocator_proc
+	default_allocator :: panic_allocator
+} else {
+	default_allocator :: heap_allocator
+	default_allocator_proc :: heap_allocator_proc
+}

+ 0 - 8
core/runtime/default_allocators_nil.odin → base/runtime/default_allocators_nil.odin

@@ -31,14 +31,6 @@ nil_allocator :: proc() -> Allocator {
 }
 
 
-
-when ODIN_OS == .Freestanding {
-	default_allocator_proc :: nil_allocator_proc
-	default_allocator :: nil_allocator
-}
-
-
-
 panic_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
                              size, alignment: int,
                              old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {

+ 0 - 0
core/runtime/default_temporary_allocator.odin → base/runtime/default_temporary_allocator.odin


+ 3 - 2
core/runtime/docs.odin → base/runtime/docs.odin

@@ -44,7 +44,7 @@ memcpy
 memove
 
 
-## Procedures required by the LLVM backend
+## Procedures required by the LLVM backend if u128/i128 is used
 umodti3
 udivti3
 modti3
@@ -59,11 +59,12 @@ truncdfhf2
 gnu_h2f_ieee
 gnu_f2h_ieee
 extendhfsf2
+
+## Procedures required by the LLVM backend if f16 is used
 __ashlti3 // wasm specific
 __multi3  // wasm specific
 
 
-
 ## Required an entry point is defined (i.e. 'main')
 
 args__

+ 0 - 0
core/runtime/dynamic_array_internal.odin → base/runtime/dynamic_array_internal.odin


+ 1 - 1
core/runtime/dynamic_map_internal.odin → base/runtime/dynamic_map_internal.odin

@@ -1,6 +1,6 @@
 package runtime
 
-import "core:intrinsics"
+import "base:intrinsics"
 _ :: intrinsics
 
 // High performance, cache-friendly, open-addressed Robin Hood hashing hash map

+ 1 - 1
core/runtime/entry_unix.odin → base/runtime/entry_unix.odin

@@ -3,7 +3,7 @@
 //+no-instrumentation
 package runtime
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 when ODIN_BUILD_MODE == .Dynamic {
 	@(link_name="_odin_entry_point", linkage="strong", require/*, link_section=".init"*/)

+ 0 - 0
core/runtime/entry_unix_no_crt_amd64.asm → base/runtime/entry_unix_no_crt_amd64.asm


+ 0 - 0
core/runtime/entry_unix_no_crt_darwin_arm64.asm → base/runtime/entry_unix_no_crt_darwin_arm64.asm


+ 0 - 0
core/runtime/entry_unix_no_crt_i386.asm → base/runtime/entry_unix_no_crt_i386.asm


+ 1 - 1
core/runtime/entry_wasm.odin → base/runtime/entry_wasm.odin

@@ -3,7 +3,7 @@
 //+no-instrumentation
 package runtime
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
 	@(link_name="_start", linkage="strong", require, export)

+ 1 - 1
core/runtime/entry_windows.odin → base/runtime/entry_windows.odin

@@ -3,7 +3,7 @@
 //+no-instrumentation
 package runtime
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 when ODIN_BUILD_MODE == .Dynamic {
 	@(link_name="DllMain", linkage="strong", require)

+ 0 - 0
core/runtime/error_checks.odin → base/runtime/error_checks.odin


+ 110 - 0
base/runtime/heap_allocator.odin

@@ -0,0 +1,110 @@
+package runtime
+
+import "base:intrinsics"
+
+heap_allocator :: proc() -> Allocator {
+	return Allocator{
+		procedure = heap_allocator_proc,
+		data = nil,
+	}
+}
+
+heap_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
+                            size, alignment: int,
+                            old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, 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.
+	//
+
+	aligned_alloc :: proc(size, alignment: int, old_ptr: rawptr = nil, zero_memory := true) -> ([]byte, Allocator_Error) {
+		a := max(alignment, align_of(rawptr))
+		space := size + a - 1
+
+		allocated_mem: rawptr
+		if old_ptr != nil {
+			original_old_ptr := ([^]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(([^]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)
+		([^]rawptr)(aligned_mem)[-1] = allocated_mem
+
+		return byte_slice(aligned_mem, size), nil
+	}
+
+	aligned_free :: proc(p: rawptr) {
+		if p != nil {
+			heap_free(([^]rawptr)(p)[-1])
+		}
+	}
+
+	aligned_resize :: proc(p: rawptr, old_size: int, new_size: int, new_alignment: int, zero_memory := true) -> (new_memory: []byte, err: 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 := raw_data(new_memory[old_size:])
+			intrinsics.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 := (^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_alloc :: proc(size: int, zero_memory := true) -> rawptr {
+	return _heap_alloc(size, zero_memory)
+}
+
+heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
+	return _heap_resize(ptr, new_size)
+}
+
+heap_free :: proc(ptr: rawptr) {
+	_heap_free(ptr)
+}

+ 15 - 0
base/runtime/heap_allocator_other.odin

@@ -0,0 +1,15 @@
+//+build js, wasi, freestanding, essence
+//+private
+package runtime
+
+_heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
+	unimplemented("base:runtime 'heap_alloc' procedure is not supported on this platform")
+}
+
+_heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
+	unimplemented("base:runtime 'heap_resize' procedure is not supported on this platform")
+}
+
+_heap_free :: proc(ptr: rawptr) {
+	unimplemented("base:runtime 'heap_free' procedure is not supported on this platform")
+}

+ 38 - 0
base/runtime/heap_allocator_unix.odin

@@ -0,0 +1,38 @@
+//+build linux, darwin, freebsd, openbsd
+//+private
+package runtime
+
+when ODIN_OS == .Darwin {
+	foreign import libc "system:System.framework"
+} else {
+	foreign import libc "system:c"
+}
+
+@(default_calling_convention="c")
+foreign libc {
+	@(link_name="malloc")   _unix_malloc   :: proc(size: int) -> rawptr ---
+	@(link_name="calloc")   _unix_calloc   :: proc(num, size: int) -> rawptr ---
+	@(link_name="free")     _unix_free     :: proc(ptr: rawptr) ---
+	@(link_name="realloc")  _unix_realloc  :: proc(ptr: rawptr, size: int) -> rawptr ---
+}
+
+_heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
+	if size <= 0 {
+		return nil
+	}
+	if zero_memory {
+		return _unix_calloc(1, size)
+	} else {
+		return _unix_malloc(size)
+	}
+}
+
+_heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
+	// NOTE: _unix_realloc doesn't guarantee new memory will be zeroed on
+	// POSIX platforms. Ensure your caller takes this into account.
+	return _unix_realloc(ptr, new_size)
+}
+
+_heap_free :: proc(ptr: rawptr) {
+	_unix_free(ptr)
+}

+ 39 - 0
base/runtime/heap_allocator_windows.odin

@@ -0,0 +1,39 @@
+package runtime
+
+foreign import kernel32 "system:Kernel32.lib"
+
+@(private="file")
+@(default_calling_convention="system")
+foreign kernel32 {
+	// NOTE(bill): The types are not using the standard names (e.g. DWORD and LPVOID) to just minimizing the dependency
+
+	// default_allocator
+	GetProcessHeap :: proc() -> rawptr ---
+	HeapAlloc      :: proc(hHeap: rawptr, dwFlags: u32, dwBytes: uint) -> rawptr ---
+	HeapReAlloc    :: proc(hHeap: rawptr, dwFlags: u32, lpMem: rawptr, dwBytes: uint) -> rawptr ---
+	HeapFree       :: proc(hHeap: rawptr, dwFlags: u32, lpMem: rawptr) -> b32 ---
+}
+
+_heap_alloc :: proc(size: int, zero_memory := true) -> rawptr {
+	HEAP_ZERO_MEMORY :: 0x00000008
+	return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY if zero_memory else 0, uint(size))
+}
+_heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
+	if new_size == 0 {
+		_heap_free(ptr)
+		return nil
+	}
+	if ptr == nil {
+		return _heap_alloc(new_size)
+	}
+
+	HEAP_ZERO_MEMORY :: 0x00000008
+	return HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptr, uint(new_size))
+}
+_heap_free :: proc(ptr: rawptr) {
+	if ptr == nil {
+		return
+	}
+	HeapFree(GetProcessHeap(), 0, ptr)
+}
+

+ 4 - 78
core/runtime/internal.odin → base/runtime/internal.odin

@@ -1,6 +1,6 @@
 package runtime
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 @(private="file")
 IS_WASM :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32
@@ -11,7 +11,7 @@ RUNTIME_LINKAGE :: "strong" when (
 	ODIN_BUILD_MODE == .Dynamic ||
 	!ODIN_NO_CRT) &&
 	!IS_WASM) else "internal"
-RUNTIME_REQUIRE :: !ODIN_TILDE
+RUNTIME_REQUIRE :: false // !ODIN_TILDE
 
 @(private)
 __float16 :: f16 when __ODIN_LLVM_F16_SUPPORTED else u16
@@ -22,51 +22,7 @@ byte_slice :: #force_inline proc "contextless" (data: rawptr, len: int) -> []byt
 	return ([^]byte)(data)[:max(len, 0)]
 }
 
-bswap_16 :: proc "contextless" (x: u16) -> u16 {
-	return x>>8 | x<<8
-}
-
-bswap_32 :: proc "contextless" (x: u32) -> u32 {
-	return x>>24 | (x>>8)&0xff00 | (x<<8)&0xff0000 | x<<24
-}
-
-bswap_64 :: proc "contextless" (x: u64) -> u64 {
-	z := x
-	z = (z & 0x00000000ffffffff) << 32 | (z & 0xffffffff00000000) >> 32
-	z = (z & 0x0000ffff0000ffff) << 16 | (z & 0xffff0000ffff0000) >> 16
-	z = (z & 0x00ff00ff00ff00ff) << 8  | (z & 0xff00ff00ff00ff00) >> 8
-	return z
-}
-
-bswap_128 :: proc "contextless" (x: u128) -> u128 {
-	z := transmute([4]u32)x
-	z[0], z[3] = bswap_32(z[3]), bswap_32(z[0])
-	z[1], z[2] = bswap_32(z[2]), bswap_32(z[1])
-	return transmute(u128)z
-}
-
-bswap_f16 :: proc "contextless" (f: f16) -> f16 {
-	x := transmute(u16)f
-	z := bswap_16(x)
-	return transmute(f16)z
-
-}
-
-bswap_f32 :: proc "contextless" (f: f32) -> f32 {
-	x := transmute(u32)f
-	z := bswap_32(x)
-	return transmute(f32)z
-
-}
-
-bswap_f64 :: proc "contextless" (f: f64) -> f64 {
-	x := transmute(u64)f
-	z := bswap_64(x)
-	return transmute(f64)z
-}
-
-
-is_power_of_two_int :: #force_inline proc(x: int) -> bool {
+is_power_of_two_int :: #force_inline proc "contextless" (x: int) -> bool {
 	if x <= 0 {
 		return false
 	}
@@ -84,7 +40,7 @@ align_forward_int :: #force_inline proc(ptr, align: int) -> int {
 	return p
 }
 
-is_power_of_two_uintptr :: #force_inline proc(x: uintptr) -> bool {
+is_power_of_two_uintptr :: #force_inline proc "contextless" (x: uintptr) -> bool {
 	if x <= 0 {
 		return false
 	}
@@ -608,36 +564,6 @@ string_decode_last_rune :: proc "contextless" (s: string) -> (rune, int) {
 	return r, size
 }
 
-
-abs_f16 :: #force_inline proc "contextless" (x: f16) -> f16 {
-	return -x if x < 0 else x
-}
-abs_f32 :: #force_inline proc "contextless" (x: f32) -> f32 {
-	return -x if x < 0 else x
-}
-abs_f64 :: #force_inline proc "contextless" (x: f64) -> f64 {
-	return -x if x < 0 else x
-}
-
-min_f16 :: #force_inline proc "contextless" (a, b: f16) -> f16 {
-	return a if a < b else b
-}
-min_f32 :: #force_inline proc "contextless" (a, b: f32) -> f32 {
-	return a if a < b else b
-}
-min_f64 :: #force_inline proc "contextless" (a, b: f64) -> f64 {
-	return a if a < b else b
-}
-max_f16 :: #force_inline proc "contextless" (a, b: f16) -> f16 {
-	return a if a > b else b
-}
-max_f32 :: #force_inline proc "contextless" (a, b: f32) -> f32 {
-	return a if a > b else b
-}
-max_f64 :: #force_inline proc "contextless" (a, b: f64) -> f64 {
-	return a if a > b else b
-}
-
 abs_complex32 :: #force_inline proc "contextless" (x: complex32) -> f16 {
 	p, q := abs(real(x)), abs(imag(x))
 	if p < q {

+ 7 - 0
base/runtime/os_specific.odin

@@ -0,0 +1,7 @@
+package runtime
+
+_OS_Errno :: distinct int
+
+stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
+	return _stderr_write(data)
+}

+ 22 - 0
base/runtime/os_specific_bsd.odin

@@ -0,0 +1,22 @@
+//+build freebsd, openbsd
+//+private
+package runtime
+
+foreign import libc "system:c"
+
+@(default_calling_convention="c")
+foreign libc {
+	@(link_name="write")
+	_unix_write :: proc(fd: i32, buf: rawptr, size: int) -> int ---
+
+	__error :: proc() -> ^i32 ---
+}
+
+_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
+	ret := _unix_write(2, raw_data(data), len(data))
+	if ret < len(data) {
+		err := __error()
+		return int(ret), _OS_Errno(err^ if err != nil else 0)
+	}
+	return int(ret), 0
+}

+ 26 - 0
base/runtime/os_specific_darwin.odin

@@ -0,0 +1,26 @@
+//+build darwin
+//+private
+package runtime
+
+foreign import libc "system:System.framework"
+
+@(default_calling_convention="c")
+foreign libc {
+	@(link_name="__stderrp")
+	_stderr: rawptr
+
+	@(link_name="fwrite")
+	_fwrite :: proc(ptr: rawptr, size: uint, nmemb: uint, stream: rawptr) -> uint ---
+
+	@(link_name="__error")
+	_get_errno :: proc() -> ^i32 ---
+}
+
+_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
+	ret := _fwrite(raw_data(data), 1, len(data), _stderr)
+	if ret < len(data) {
+		err := _get_errno()
+		return int(ret), _OS_Errno(err^ if err != nil else 0)
+	}
+	return int(ret), 0
+}

+ 2 - 1
core/runtime/os_specific_freestanding.odin → base/runtime/os_specific_freestanding.odin

@@ -1,7 +1,8 @@
 //+build freestanding
+//+private
 package runtime
 
 // TODO(bill): reimplement `os.write`
-_os_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
+_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
 	return 0, -1
 }

+ 2 - 1
core/runtime/os_specific_js.odin → base/runtime/os_specific_js.odin

@@ -1,9 +1,10 @@
 //+build js
+//+private
 package runtime
 
 foreign import "odin_env"
 
-_os_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
+_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
 	foreign odin_env {
 		write :: proc "contextless" (fd: u32, p: []byte) ---
 	}

+ 24 - 0
base/runtime/os_specific_linux.odin

@@ -0,0 +1,24 @@
+//+private
+package runtime
+
+import "base:intrinsics"
+
+_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
+	when ODIN_ARCH == .amd64 {
+		SYS_write :: uintptr(1)
+	} else when ODIN_ARCH == .arm64 {
+		SYS_write :: uintptr(64)
+	} else when ODIN_ARCH == .i386 {
+		SYS_write :: uintptr(4)
+	} else when ODIN_ARCH == .arm32 {
+		SYS_write :: uintptr(4)
+	}
+
+	stderr :: 2
+
+	ret := int(intrinsics.syscall(SYS_write, uintptr(stderr), uintptr(raw_data(data)), uintptr(len(data))))
+	if ret < 0 && ret > -4096 {
+		return 0, _OS_Errno(-ret)
+	}
+	return ret, 0
+}

+ 2 - 1
core/runtime/os_specific_wasi.odin → base/runtime/os_specific_wasi.odin

@@ -1,9 +1,10 @@
 //+build wasi
+//+private
 package runtime
 
 import "core:sys/wasm/wasi"
 
-_os_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
+_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
 	data := (wasi.ciovec_t)(data)
 	n, err := wasi.fd_write(1, {data})
 	return int(n), _OS_Errno(err)

+ 51 - 0
base/runtime/os_specific_windows.odin

@@ -0,0 +1,51 @@
+//+build windows
+//+private
+package runtime
+
+foreign import kernel32 "system:Kernel32.lib"
+
+@(private="file")
+@(default_calling_convention="system")
+foreign kernel32 {
+	// NOTE(bill): The types are not using the standard names (e.g. DWORD and LPVOID) to just minimizing the dependency
+
+	// stderr_write
+	GetStdHandle         :: proc(which: u32) -> rawptr ---
+	SetHandleInformation :: proc(hObject: rawptr, dwMask: u32, dwFlags: u32) -> b32 ---
+	WriteFile            :: proc(hFile: rawptr, lpBuffer: rawptr, nNumberOfBytesToWrite: u32, lpNumberOfBytesWritten: ^u32, lpOverlapped: rawptr) -> b32 ---
+	GetLastError         :: proc() -> u32 ---
+}
+
+_stderr_write :: proc "contextless" (data: []byte) -> (n: int, err: _OS_Errno) #no_bounds_check {
+	if len(data) == 0 {
+		return 0, 0
+	}
+
+	STD_ERROR_HANDLE :: ~u32(0) -12 + 1
+	HANDLE_FLAG_INHERIT :: 0x00000001
+	MAX_RW :: 1<<30
+
+	h := GetStdHandle(STD_ERROR_HANDLE)
+	when size_of(uintptr) == 8 {
+		SetHandleInformation(h, HANDLE_FLAG_INHERIT, 0)
+	}
+
+	single_write_length: u32
+	total_write: i64
+	length := i64(len(data))
+
+	for total_write < length {
+		remaining := length - total_write
+		to_write := u32(min(i32(remaining), MAX_RW))
+
+		e := WriteFile(h, &data[total_write], to_write, &single_write_length, nil)
+		if single_write_length <= 0 || !e {
+			err = _OS_Errno(GetLastError())
+			n = int(total_write)
+			return
+		}
+		total_write += i64(single_write_length)
+	}
+	n = int(total_write)
+	return
+}

+ 6 - 6
core/runtime/print.odin → base/runtime/print.odin

@@ -123,13 +123,13 @@ encode_rune :: proc "contextless" (c: rune) -> ([4]u8, int) {
 }
 
 print_string :: proc "contextless" (str: string) -> (n: int) {
-	n, _ = os_write(transmute([]byte)str)
+	n, _ = stderr_write(transmute([]byte)str)
 	return
 }
 
 print_strings :: proc "contextless" (args: ..string) -> (n: int) {
 	for str in args {
-		m, err := os_write(transmute([]byte)str)
+		m, err := stderr_write(transmute([]byte)str)
 		n += m
 		if err != 0 {
 			break
@@ -139,7 +139,7 @@ print_strings :: proc "contextless" (args: ..string) -> (n: int) {
 }
 
 print_byte :: proc "contextless" (b: byte) -> (n: int) {
-	n, _ = os_write([]byte{b})
+	n, _ = stderr_write([]byte{b})
 	return
 }
 
@@ -178,7 +178,7 @@ print_rune :: proc "contextless" (r: rune) -> int #no_bounds_check {
 	}
 
 	b, n := encode_rune(r)
-	m, _ := os_write(b[:n])
+	m, _ := stderr_write(b[:n])
 	return m
 }
 
@@ -194,7 +194,7 @@ print_u64 :: proc "contextless" (x: u64) #no_bounds_check {
 	}
 	i -= 1; a[i] = _INTEGER_DIGITS_VAR[u % b]
 
-	os_write(a[i:])
+	stderr_write(a[i:])
 }
 
 
@@ -216,7 +216,7 @@ print_i64 :: proc "contextless" (x: i64) #no_bounds_check {
 		i -= 1; a[i] = '-'
 	}
 
-	os_write(a[i:])
+	stderr_write(a[i:])
 }
 
 print_uint    :: proc "contextless" (x: uint)    { print_u64(u64(x)) }

+ 0 - 0
core/runtime/procs.odin → base/runtime/procs.odin


+ 1 - 1
core/runtime/procs_darwin.odin → base/runtime/procs_darwin.odin

@@ -3,7 +3,7 @@ package runtime
 
 foreign import "system:Foundation.framework"
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 objc_id :: ^intrinsics.objc_object
 objc_Class :: ^intrinsics.objc_class

+ 0 - 0
core/runtime/procs_js.odin → base/runtime/procs_js.odin


+ 0 - 0
core/runtime/procs_wasm.odin → base/runtime/procs_wasm.odin


+ 0 - 0
core/runtime/procs_windows_amd64.asm → base/runtime/procs_windows_amd64.asm


+ 0 - 0
core/runtime/procs_windows_amd64.odin → base/runtime/procs_windows_amd64.odin


+ 0 - 0
core/runtime/procs_windows_i386.odin → base/runtime/procs_windows_i386.odin


+ 1 - 1
core/runtime/udivmod128.odin → base/runtime/udivmod128.odin

@@ -1,6 +1,6 @@
 package runtime
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
 	_ctz :: intrinsics.count_trailing_zeros

+ 1 - 1
core/bufio/scanner.odin

@@ -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 - 1
core/c/c.odin

@@ -1,6 +1,6 @@
 package c
 
-import builtin "core:builtin"
+import builtin "base:builtin"
 
 char           :: builtin.u8  // assuming -funsigned-char
 

+ 1 - 1
core/c/libc/complex.odin

@@ -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

+ 1 - 1
core/c/libc/math.odin

@@ -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"

+ 1 - 1
core/c/libc/stdarg.odin

@@ -2,7 +2,7 @@ package libc
 
 // 7.16 Variable arguments
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 @(private="file")
 @(default_calling_convention="none")

+ 1 - 1
core/c/libc/stdatomic.odin

@@ -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 - 1
core/c/libc/string.odin

@@ -1,6 +1,6 @@
 package libc
 
-import "core:runtime"
+import "base:runtime"
 
 // 7.24 String handling
 

+ 1 - 1
core/compress/common.odin

@@ -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.

+ 1 - 1
core/compress/shoco/shoco.odin

@@ -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 - 1
core/container/bit_array/bit_array.odin

@@ -1,6 +1,6 @@
 package dynamic_bit_array
 
-import "core:intrinsics"
+import "base:intrinsics"
 import "core:mem"
 
 /*

+ 1 - 1
core/container/intrusive/list/intrusive_list.odin

@@ -1,6 +1,6 @@
 package container_intrusive_list
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 // An intrusive doubly-linked list
 //

+ 2 - 2
core/container/lru/lru_cache.odin

@@ -1,7 +1,7 @@
 package container_lru
 
-import "core:runtime"
-import "core:intrinsics"
+import "base:runtime"
+import "base:intrinsics"
 _ :: runtime
 _ :: intrinsics
 

+ 1 - 1
core/container/priority_queue/priority_queue.odin

@@ -1,6 +1,6 @@
 package container_priority_queue
 
-import "core:builtin"
+import "base:builtin"
 
 Priority_Queue :: struct($T: typeid) {
 	queue: [dynamic]T,

+ 2 - 2
core/container/queue/queue.odin

@@ -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

+ 2 - 2
core/container/small_array/small_array.odin

@@ -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 {

+ 2 - 2
core/container/topological_sort/topological_sort.odin

@@ -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
 

+ 2 - 2
core/dynlib/lib.odin

@@ -1,8 +1,8 @@
 package dynlib
 
-import "core:intrinsics"
+import "base:intrinsics"
 import "core:reflect"
-import "core:runtime"
+import "base:runtime"
 _ :: intrinsics
 _ :: reflect
 _ :: runtime

+ 1 - 1
core/dynlib/lib_windows.odin

@@ -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 - 1
core/encoding/endian/endian.odin

@@ -1,6 +1,6 @@
 package encoding_endian
 
-import "core:intrinsics"
+import "base:intrinsics"
 import "core:math/bits"
 
 Byte_Order :: enum u8 {

+ 1 - 1
core/encoding/json/marshal.odin

@@ -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"

+ 1 - 1
core/encoding/json/unmarshal.odin

@@ -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,

+ 2 - 2
core/encoding/xml/xml_reader.odin

@@ -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
core/fmt/fmt.odin

@@ -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

+ 1 - 1
core/fmt/fmt_os.odin

@@ -2,7 +2,7 @@
 //+build !js
 package fmt
 
-import "core:runtime"
+import "base:runtime"
 import "core:os"
 import "core:io"
 import "core:bufio"

+ 1 - 1
core/hash/crc32.odin

@@ -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
core/hash/hash.odin

@@ -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 {

+ 2 - 2
core/hash/xxhash/common.odin

@@ -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

+ 1 - 1
core/hash/xxhash/streaming.odin

@@ -10,7 +10,7 @@
 package xxhash
 
 import "core:mem"
-import "core:intrinsics"
+import "base:intrinsics"
 
 /*
 	===   XXH3 128-bit streaming   ===

+ 1 - 1
core/hash/xxhash/xxhash_3.odin

@@ -9,7 +9,7 @@
 */
 package xxhash
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 /*
 *************************************************************************

+ 1 - 1
core/hash/xxhash/xxhash_32.odin

@@ -9,7 +9,7 @@
 */
 package xxhash
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 /*
 	32-bit hash functions

+ 1 - 1
core/hash/xxhash/xxhash_64.odin

@@ -9,7 +9,7 @@
 */
 package xxhash
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 /*
 	64-bit hash functions

+ 1 - 1
core/image/common.odin

@@ -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.

+ 1 - 1
core/image/netpbm/netpbm.odin

@@ -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

+ 1 - 1
core/image/png/helpers.odin

@@ -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.

+ 2 - 2
core/image/png/png.odin

@@ -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 - 1
core/io/io.odin

@@ -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 - 0
core/log/file_console_logger.odin

@@ -1,3 +1,4 @@
+//+build !freestanding
 package log
 
 import "core:fmt"

+ 1 - 1
core/log/log.odin

@@ -1,6 +1,6 @@
 package log
 
-import "core:runtime"
+import "base:runtime"
 import "core:fmt"
 
 

+ 1 - 1
core/log/log_allocator.odin

@@ -1,6 +1,6 @@
 package log
 
-import "core:runtime"
+import "base:runtime"
 import "core:fmt"
 
 Log_Allocator_Format :: enum {

+ 1 - 1
core/math/big/common.odin

@@ -6,7 +6,7 @@
 
 package math_big
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 /*
 	TODO: Make the tunables runtime adjustable where practical.

+ 1 - 1
core/math/big/helpers.odin

@@ -6,7 +6,7 @@
 
 package math_big
 
-import "core:intrinsics"
+import "base:intrinsics"
 import rnd "core:math/rand"
 
 /*

+ 2 - 2
core/math/big/internal.odin

@@ -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.

+ 1 - 1
core/math/big/private.odin

@@ -19,7 +19,7 @@
 
 package math_big
 
-import "core:intrinsics"
+import "base:intrinsics"
 import "core:mem"
 
 /*

+ 1 - 1
core/math/big/public.odin

@@ -12,7 +12,7 @@
 
 package math_big
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 /*
 	===========================

+ 1 - 1
core/math/big/radix.odin

@@ -16,7 +16,7 @@
 
 package math_big
 
-import "core:intrinsics"
+import "base:intrinsics"
 import "core:mem"
 import "core:os"
 

+ 2 - 2
core/math/big/rat.odin

@@ -1,7 +1,7 @@
 package math_big
 
-import "core:builtin"
-import "core:intrinsics"
+import "base:builtin"
+import "base:intrinsics"
 import "core:math"
 
 Rat :: struct {

+ 1 - 1
core/math/big/tune.odin

@@ -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 - 1
core/math/bits/bits.odin

@@ -1,6 +1,6 @@
 package math_bits
 
-import "core:intrinsics"
+import "base:intrinsics"
 
 U8_MIN  :: 0
 U16_MIN :: 0

+ 1 - 1
core/math/cmplx/cmplx.odin

@@ -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 - 1
core/math/cmplx/cmplx_invtrig.odin

@@ -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 - 1
core/math/ease/ease.odin

@@ -2,7 +2,7 @@
 package ease
 
 import "core:math"
-import "core:intrinsics"
+import "base:intrinsics"
 import "core:time"
 
 @(private) PI_2 :: math.PI / 2

+ 1 - 1
core/math/fixed/fixed.odin

@@ -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 - 1
core/math/linalg/extended.odin

@@ -1,6 +1,6 @@
 package linalg
 
-import "core:builtin"
+import "base:builtin"
 import "core:math"
 
 @(require_results)

+ 274 - 5
core/math/linalg/general.odin

@@ -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
+}

+ 276 - 24
core/math/linalg/glsl/linalg_glsl.odin

@@ -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,
-}
-
-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
+	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
+}
+

+ 277 - 16
core/math/linalg/hlsl/linalg_hlsl.odin

@@ -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 :: 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
 }
 
-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
+@(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,

+ 7 - 7
core/math/linalg/specific.odin

@@ -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
core/math/math.odin

@@ -1,7 +1,7 @@
 package math
 
-import "core:intrinsics"
-import "core:builtin"
+import "base:intrinsics"
+import "base:builtin"
 _ :: intrinsics
 
 Float_Class :: enum {

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