mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-09 04:51:37 -07:00
Compare commits
186 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a04d849e30 | |||
| 8c9505505a | |||
| eac74631ec | |||
| 85706d559d | |||
| 67ba05cb7c | |||
| 2f1aeaf757 | |||
| 14a17fb36f | |||
| 1a9ec776cb | |||
| da1edac56d | |||
| 44ec95a983 | |||
| 1502066303 | |||
| 35a826a0fd | |||
| ebb8ca7c26 | |||
| 763de44853 | |||
| 62cc752066 | |||
| 965b962b29 | |||
| 2f3c5336d9 | |||
| 3824937295 | |||
| fc8ddcef5c | |||
| 3165b7cf95 | |||
| 5eea23cf76 | |||
| 2aa783179e | |||
| 24e7356825 | |||
| 2fcba25e50 | |||
| 28bc274449 | |||
| 16786aac78 | |||
| 32b37f3429 | |||
| 5808793cae | |||
| 7e11f3cc4b | |||
| 714ab516c5 | |||
| 498f68c06b | |||
| 070b450768 | |||
| 74174eb4ae | |||
| b190404b21 | |||
| 081a5a52a6 | |||
| fb86c23dbd | |||
| cb6a4ebf60 | |||
| 1bf8328606 | |||
| 6a7f39453b | |||
| 515fd2a228 | |||
| dd3322ac1f | |||
| f16f1d932e | |||
| a3e7b2baa1 | |||
| fadf9b5309 | |||
| f6a087775e | |||
| d5f7e181a0 | |||
| 65f8722afc | |||
| c0479f1564 | |||
| fe0b5bf4e2 | |||
| f20105ddfe | |||
| 42ab882db4 | |||
| dcc9e61362 | |||
| 2554c72bb2 | |||
| 49872e40dc | |||
| 849fe01e70 | |||
| d269dbcd40 | |||
| 18e639f59b | |||
| 6ad262c2df | |||
| 10b97a1b39 | |||
| 56b4e0a3c3 | |||
| 27dbe84f79 | |||
| 0711d4e5fe | |||
| 1e46537959 | |||
| a5e1693774 | |||
| 63771bc6e8 | |||
| 8516e2e7e3 | |||
| b3c3e41706 | |||
| 59f3a009fa | |||
| 9bc5b84c4d | |||
| f9265c14bf | |||
| 9c1e1a63a2 | |||
| 4dc5839e3d | |||
| fdcb9deaff | |||
| fe6539fad9 | |||
| 0e06383620 | |||
| cfbc1a447b | |||
| 1b23dd2257 | |||
| b612edba5a | |||
| d39c05b183 | |||
| 3a3cb521ab | |||
| 5b97ff0b48 | |||
| 2b918ada4b | |||
| b5754b6ed9 | |||
| 07ee23f817 | |||
| ecdaac9921 | |||
| 5ff82fc113 | |||
| 28a816ef25 | |||
| 6bdb210ad8 | |||
| db08847f9a | |||
| 841c428273 | |||
| 6b830f42b6 | |||
| fb01dfe048 | |||
| c7a9c8274f | |||
| cafb6e5587 | |||
| e9ae6e20e8 | |||
| 2ca2dbcc92 | |||
| 0d4642825f | |||
| 8eda756714 | |||
| c85ac955f7 | |||
| 97922406fe | |||
| 76ccce2942 | |||
| 686dbb4421 | |||
| cd6898439e | |||
| 95620aaf2a | |||
| 1d293749c2 | |||
| 2d35a5c1af | |||
| d4ea02a877 | |||
| 2a325b3da0 | |||
| f0529535e0 | |||
| 3f59c45740 | |||
| 29ebe0c3c9 | |||
| 6c48670819 | |||
| 51dcbc80c3 | |||
| 9ecbadd457 | |||
| 79f32d7b71 | |||
| 7501cc2f17 | |||
| a390ef41f8 | |||
| bb9c2f7aad | |||
| 6aa80ee8e4 | |||
| 0741bc37cc | |||
| c6ed3fa4b5 | |||
| e277102947 | |||
| 6cf5371d7d | |||
| e15f714660 | |||
| 4f77151ebc | |||
| 9a46463078 | |||
| a0816bb581 | |||
| b33ca6651e | |||
| 315a08f33f | |||
| 50668fa7a6 | |||
| ee260986a9 | |||
| c9bc759624 | |||
| 80f175cdb0 | |||
| 8f03811842 | |||
| 3def94505e | |||
| e30f16b1f3 | |||
| 7df93ea504 | |||
| 6209b02bf9 | |||
| 75b7f2b9fe | |||
| f1521aa980 | |||
| fb0a3ab7c1 | |||
| 8eaafd5242 | |||
| 774951e8c0 | |||
| 5ec93677a0 | |||
| 7e4067c44c | |||
| f2f6c3c67d | |||
| 847b05013f | |||
| d308473075 | |||
| 4334dbe69a | |||
| 8f91e9307c | |||
| 32ec1162bf | |||
| 7cc265e14c | |||
| 6f3e450c50 | |||
| cb1080d56c | |||
| 80bd1eb615 | |||
| fb53402914 | |||
| 731853ce78 | |||
| f0260e9771 | |||
| af612bc7e9 | |||
| d76dd95c0b | |||
| 1cff72ad62 | |||
| 773cfac449 | |||
| b02f2953ac | |||
| 566a750899 | |||
| 1d1d684cbc | |||
| 7a14acaa01 | |||
| 057174497a | |||
| 8c9597b24b | |||
| 72862ce30d | |||
| d0f4cb1de4 | |||
| 17613185e7 | |||
| 00ff1fbca2 | |||
| f15bb0b424 | |||
| f818d0feb1 | |||
| 8ff6f95571 | |||
| 68e5f57e27 | |||
| 38e5e13b3f | |||
| defc1672c3 | |||
| 12f459b5fb | |||
| e6b8f7e77a | |||
| 236b08cb49 | |||
| e4f28de3de | |||
| 750ee4ecdb | |||
| 92e70b9a58 | |||
| 822da9d12d | |||
| 5d80e24224 |
@@ -17,13 +17,16 @@ jobs:
|
|||||||
run: ./odin report
|
run: ./odin report
|
||||||
timeout-minutes: 1
|
timeout-minutes: 1
|
||||||
- name: Odin check
|
- name: Odin check
|
||||||
run: ./odin check examples/demo/demo.odin -vet
|
run: ./odin check examples/demo -vet
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Odin run
|
- name: Odin run
|
||||||
run: ./odin run examples/demo/demo.odin
|
run: ./odin run examples/demo
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Odin run -debug
|
- name: Odin run -debug
|
||||||
run: ./odin run examples/demo/demo.odin -debug
|
run: ./odin run examples/demo -debug
|
||||||
|
timeout-minutes: 10
|
||||||
|
- name: Odin check examples/all
|
||||||
|
run: ./odin check examples/all -strict-style
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Core library tests
|
- name: Core library tests
|
||||||
run: |
|
run: |
|
||||||
@@ -54,13 +57,16 @@ jobs:
|
|||||||
run: ./odin report
|
run: ./odin report
|
||||||
timeout-minutes: 1
|
timeout-minutes: 1
|
||||||
- name: Odin check
|
- name: Odin check
|
||||||
run: ./odin check examples/demo/demo.odin -vet
|
run: ./odin check examples/demo -vet
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Odin run
|
- name: Odin run
|
||||||
run: ./odin run examples/demo/demo.odin
|
run: ./odin run examples/demo
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Odin run -debug
|
- name: Odin run -debug
|
||||||
run: ./odin run examples/demo/demo.odin -debug
|
run: ./odin run examples/demo -debug
|
||||||
|
timeout-minutes: 10
|
||||||
|
- name: Odin check examples/all
|
||||||
|
run: ./odin check examples/all -strict-style
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Core library tests
|
- name: Core library tests
|
||||||
run: |
|
run: |
|
||||||
@@ -91,19 +97,25 @@ jobs:
|
|||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
odin check examples/demo/demo.odin -vet
|
odin check examples/demo -vet
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Odin run
|
- name: Odin run
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
odin run examples/demo/demo.odin
|
odin run examples/demo
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Odin run -debug
|
- name: Odin run -debug
|
||||||
shell: cmd
|
shell: cmd
|
||||||
run: |
|
run: |
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
odin run examples/demo/demo.odin -debug
|
odin run examples/demo -debug
|
||||||
|
timeout-minutes: 10
|
||||||
|
- name: Odin check examples/all
|
||||||
|
shell: cmd
|
||||||
|
run: |
|
||||||
|
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvars64.bat
|
||||||
|
odin check examples/all -strict-style
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
- name: Core library tests
|
- name: Core library tests
|
||||||
shell: cmd
|
shell: cmd
|
||||||
|
|||||||
@@ -8,22 +8,34 @@ CC=clang
|
|||||||
OS=$(shell uname)
|
OS=$(shell uname)
|
||||||
|
|
||||||
ifeq ($(OS), Darwin)
|
ifeq ($(OS), Darwin)
|
||||||
|
|
||||||
ARCH=$(shell uname -m)
|
ARCH=$(shell uname -m)
|
||||||
LLVM_CONFIG=llvm-config
|
LLVM_CONFIG=
|
||||||
|
|
||||||
# LLVM Version Setting
|
# allow for arm only llvm's with version 13
|
||||||
LLVM_VERSION_PATTERN="^11\."
|
|
||||||
LLVM_VERSION="11"
|
|
||||||
ifeq ($(ARCH), arm64)
|
ifeq ($(ARCH), arm64)
|
||||||
LLVM_VERSION="13"
|
LLVM_VERSIONS = "13.%.%"
|
||||||
LLVM_VERSION_PATTERN="^13"
|
else
|
||||||
endif
|
# allow for x86 / amd64 all llvm versions begining from 11
|
||||||
|
LLVM_VERSIONS = "13.%.%" "12.0.1" "11.1.0"
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq ($(shell llvm-config --version | grep $(LLVM_VERSION_PATTERN)),)
|
LLVM_VERSION_PATTERN_SEPERATOR = )|(
|
||||||
|
LLVM_VERSION_PATTERNS_ESCAPED_DOT = $(subst .,\.,$(LLVM_VERSIONS))
|
||||||
|
LLVM_VERSION_PATTERNS_REPLACE_PERCENT = $(subst %,.*,$(LLVM_VERSION_PATTERNS_ESCAPED_DOT))
|
||||||
|
LLVM_VERSION_PATTERN_REMOVE_ELEMENTS = $(subst " ",$(LLVM_VERSION_PATTERN_SEPERATOR),$(LLVM_VERSION_PATTERNS_REPLACE_PERCENT))
|
||||||
|
LLMV_VERSION_PATTERN_REMOVE_SINGLE_STR = $(subst ",,$(LLVM_VERSION_PATTERN_REMOVE_ELEMENTS))
|
||||||
|
LLVM_VERSION_PATTERN = "^(($(LLMV_VERSION_PATTERN_REMOVE_SINGLE_STR)))"
|
||||||
|
|
||||||
|
ifneq ($(shell llvm-config --version | grep -E $(LLVM_VERSION_PATTERN)),)
|
||||||
LLVM_CONFIG=llvm-config
|
LLVM_CONFIG=llvm-config
|
||||||
else
|
else
|
||||||
$(error "Requirement: llvm-config must be version $(LLVM_VERSION)")
|
ifeq ($(ARCH), arm64)
|
||||||
endif
|
$(error "Requirement: llvm-config must be base version 13 for arm64")
|
||||||
|
else
|
||||||
|
$(error "Requirement: llvm-config must be base version greater than 11 for amd64/x86")
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
LDFLAGS:=$(LDFLAGS) -liconv
|
LDFLAGS:=$(LDFLAGS) -liconv
|
||||||
CFLAGS:=$(CFLAGS) $(shell $(LLVM_CONFIG) --cxxflags --ldflags)
|
CFLAGS:=$(CFLAGS) $(shell $(LLVM_CONFIG) --cxxflags --ldflags)
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ The official Odin Language specification.
|
|||||||
|
|
||||||
### Articles
|
### Articles
|
||||||
|
|
||||||
#### [The Odin Blog](https://odin-lang.org/blog)
|
#### [The Odin Blog](https://odin-lang.org/news/)
|
||||||
|
|
||||||
The official blog of the Odin programming language, featuring announcements, news, and in-depth articles by the Odin team and guests.
|
The official blog of the Odin programming language, featuring announcements, news, and in-depth articles by the Odin team and guests.
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
package builtin
|
package builtin
|
||||||
|
|
||||||
nil :: nil;
|
nil :: nil;
|
||||||
false :: 0!==0;
|
false :: 0!=0;
|
||||||
true :: 0==0;
|
true :: 0==0;
|
||||||
|
|
||||||
ODIN_OS :: ODIN_OS;
|
ODIN_OS :: ODIN_OS;
|
||||||
|
|||||||
+3
-1
@@ -3,6 +3,8 @@ package c
|
|||||||
import builtin "core:builtin"
|
import builtin "core:builtin"
|
||||||
|
|
||||||
char :: builtin.u8 // assuming -funsigned-char
|
char :: builtin.u8 // assuming -funsigned-char
|
||||||
|
|
||||||
|
schar :: builtin.i8
|
||||||
short :: builtin.i16
|
short :: builtin.i16
|
||||||
int :: builtin.i32
|
int :: builtin.i32
|
||||||
long :: builtin.i32 when (ODIN_OS == "windows" || size_of(builtin.rawptr) == 4) else builtin.i64
|
long :: builtin.i32 when (ODIN_OS == "windows" || size_of(builtin.rawptr) == 4) else builtin.i64
|
||||||
@@ -46,7 +48,7 @@ int_least64_t :: builtin.i64
|
|||||||
uint_least64_t :: builtin.u64
|
uint_least64_t :: builtin.u64
|
||||||
|
|
||||||
// Same on Windows, Linux, and FreeBSD
|
// Same on Windows, Linux, and FreeBSD
|
||||||
when ODIN_ARCH == "386" || ODIN_ARCH == "amd64" {
|
when ODIN_ARCH == "i386" || ODIN_ARCH == "amd64" {
|
||||||
int_fast8_t :: builtin.i8
|
int_fast8_t :: builtin.i8
|
||||||
uint_fast8_t :: builtin.u8
|
uint_fast8_t :: builtin.u8
|
||||||
int_fast16_t :: builtin.i32
|
int_fast16_t :: builtin.i32
|
||||||
|
|||||||
@@ -956,7 +956,7 @@ substitute_token :: proc(cpp: ^Preprocessor, tok: ^Token, args: ^Macro_Arg) -> ^
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if tok.lit == "__VA__OPT__" && tok.next.lit == "(" {
|
if tok.lit == "__VA_OPT__" && tok.next.lit == "(" {
|
||||||
opt_arg := read_macro_arg_one(cpp, &tok, tok.next.next, true)
|
opt_arg := read_macro_arg_one(cpp, &tok, tok.next.next, true)
|
||||||
if has_varargs(args) {
|
if has_varargs(args) {
|
||||||
for t := opt_arg.tok; t.kind != .EOF; t = t.next {
|
for t := opt_arg.tok; t.kind != .EOF; t = t.next {
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ foreign libc {
|
|||||||
putchar :: proc() -> int ---
|
putchar :: proc() -> int ---
|
||||||
puts :: proc(s: cstring) -> int ---
|
puts :: proc(s: cstring) -> int ---
|
||||||
ungetc :: proc(c: int, stream: ^FILE) -> int ---
|
ungetc :: proc(c: int, stream: ^FILE) -> int ---
|
||||||
fread :: proc(ptr: rawptr, size: size_t, stream: ^FILE) -> size_t ---
|
fread :: proc(ptr: rawptr, size: size_t, nmemb: size_t, stream: ^FILE) -> size_t ---
|
||||||
fwrite :: proc(ptr: rawptr, size: size_t, nmemb: size_t, stream: ^FILE) -> size_t ---
|
fwrite :: proc(ptr: rawptr, size: size_t, nmemb: size_t, stream: ^FILE) -> size_t ---
|
||||||
|
|
||||||
// 7.21.9 File positioning functions
|
// 7.21.9 File positioning functions
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package libc
|
|||||||
import "core:c"
|
import "core:c"
|
||||||
|
|
||||||
char :: c.char // assuming -funsigned-char
|
char :: c.char // assuming -funsigned-char
|
||||||
|
|
||||||
|
schar :: c.schar
|
||||||
short :: c.short
|
short :: c.short
|
||||||
int :: c.int
|
int :: c.int
|
||||||
long :: c.long
|
long :: c.long
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
List of contributors:
|
List of contributors:
|
||||||
Jeroen van Rijn: Initial implementation, optimization.
|
Jeroen van Rijn: Initial implementation, optimization.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// package compress is a collection of utilities to aid with other compression packages
|
||||||
package compress
|
package compress
|
||||||
|
|
||||||
import "core:io"
|
import "core:io"
|
||||||
|
|||||||
@@ -111,9 +111,9 @@ ZFAST_MASK :: ((1 << ZFAST_BITS) - 1)
|
|||||||
*/
|
*/
|
||||||
Huffman_Table :: struct {
|
Huffman_Table :: struct {
|
||||||
fast: [1 << ZFAST_BITS]u16,
|
fast: [1 << ZFAST_BITS]u16,
|
||||||
firstcode: [16]u16,
|
firstcode: [17]u16,
|
||||||
maxcode: [17]int,
|
maxcode: [17]int,
|
||||||
firstsymbol: [16]u16,
|
firstsymbol: [17]u16,
|
||||||
size: [288]u8,
|
size: [288]u8,
|
||||||
value: [288]u16,
|
value: [288]u16,
|
||||||
}
|
}
|
||||||
@@ -244,7 +244,7 @@ allocate_huffman_table :: proc(allocator := context.allocator) -> (z: ^Huffman_T
|
|||||||
@(optimization_mode="speed")
|
@(optimization_mode="speed")
|
||||||
build_huffman :: proc(z: ^Huffman_Table, code_lengths: []u8) -> (err: Error) {
|
build_huffman :: proc(z: ^Huffman_Table, code_lengths: []u8) -> (err: Error) {
|
||||||
sizes: [HUFFMAN_MAX_BITS+1]int
|
sizes: [HUFFMAN_MAX_BITS+1]int
|
||||||
next_code: [HUFFMAN_MAX_BITS]int
|
next_code: [HUFFMAN_MAX_BITS+1]int
|
||||||
|
|
||||||
k := int(0)
|
k := int(0)
|
||||||
|
|
||||||
@@ -256,14 +256,14 @@ build_huffman :: proc(z: ^Huffman_Table, code_lengths: []u8) -> (err: Error) {
|
|||||||
}
|
}
|
||||||
sizes[0] = 0
|
sizes[0] = 0
|
||||||
|
|
||||||
for i in 1..<(HUFFMAN_MAX_BITS+1) {
|
for i in 1 ..< HUFFMAN_MAX_BITS {
|
||||||
if sizes[i] > (1 << uint(i)) {
|
if sizes[i] > (1 << uint(i)) {
|
||||||
return E_Deflate.Huffman_Bad_Sizes
|
return E_Deflate.Huffman_Bad_Sizes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
code := int(0)
|
code := int(0)
|
||||||
|
|
||||||
for i in 1..<HUFFMAN_MAX_BITS {
|
for i in 1 ..= HUFFMAN_MAX_BITS {
|
||||||
next_code[i] = code
|
next_code[i] = code
|
||||||
z.firstcode[i] = u16(code)
|
z.firstcode[i] = u16(code)
|
||||||
z.firstsymbol[i] = u16(k)
|
z.firstsymbol[i] = u16(k)
|
||||||
@@ -538,19 +538,20 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
|
|||||||
final = compress.read_bits_lsb(z, 1)
|
final = compress.read_bits_lsb(z, 1)
|
||||||
type = compress.read_bits_lsb(z, 2)
|
type = compress.read_bits_lsb(z, 2)
|
||||||
|
|
||||||
// fmt.printf("Final: %v | Type: %v\n", final, type);
|
// fmt.printf("Final: %v | Type: %v\n", final, type)
|
||||||
|
|
||||||
switch type {
|
switch type {
|
||||||
case 0:
|
case 0:
|
||||||
|
// fmt.printf("Method 0: STORED\n")
|
||||||
// Uncompressed block
|
// Uncompressed block
|
||||||
|
|
||||||
// Discard bits until next byte boundary
|
// Discard bits until next byte boundary
|
||||||
compress.discard_to_next_byte_lsb(z)
|
compress.discard_to_next_byte_lsb(z)
|
||||||
|
|
||||||
uncompressed_len := i16(compress.read_bits_lsb(z, 16))
|
uncompressed_len := u16(compress.read_bits_lsb(z, 16))
|
||||||
length_check := i16(compress.read_bits_lsb(z, 16))
|
length_check := u16(compress.read_bits_lsb(z, 16))
|
||||||
|
|
||||||
// fmt.printf("LEN: %v, ~LEN: %v, NLEN: %v, ~NLEN: %v\n", uncompressed_len, ~uncompressed_len, length_check, ~length_check);
|
// fmt.printf("LEN: %v, ~LEN: %v, NLEN: %v, ~NLEN: %v\n", uncompressed_len, ~uncompressed_len, length_check, ~length_check)
|
||||||
|
|
||||||
|
|
||||||
if ~uncompressed_len != length_check {
|
if ~uncompressed_len != length_check {
|
||||||
@@ -567,10 +568,12 @@ inflate_raw :: proc(z: ^$C, expected_output_size := -1, allocator := context.all
|
|||||||
write_byte(z, u8(lit))
|
write_byte(z, u8(lit))
|
||||||
uncompressed_len -= 1
|
uncompressed_len -= 1
|
||||||
}
|
}
|
||||||
|
assert(uncompressed_len == 0)
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
return E_Deflate.BType_3
|
return E_Deflate.BType_3
|
||||||
case:
|
case:
|
||||||
// log.debugf("Err: %v | Final: %v | Type: %v\n", err, final, type);
|
// fmt.printf("Err: %v | Final: %v | Type: %v\n", err, final, type)
|
||||||
if type == 1 {
|
if type == 1 {
|
||||||
// Use fixed code lengths.
|
// Use fixed code lengths.
|
||||||
build_huffman(z_repeat, Z_FIXED_LENGTH[:]) or_return
|
build_huffman(z_repeat, Z_FIXED_LENGTH[:]) or_return
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ create :: proc(max_index: int, min_index := 0, allocator := context.allocator) -
|
|||||||
res = Bit_Array{
|
res = Bit_Array{
|
||||||
bias = min_index,
|
bias = min_index,
|
||||||
}
|
}
|
||||||
return res, resize_if_needed(&res, size_in_bits)
|
return res, resize_if_needed(&res, legs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -0,0 +1,183 @@
|
|||||||
|
package container_lru
|
||||||
|
|
||||||
|
import "core:intrinsics"
|
||||||
|
import "core:mem"
|
||||||
|
_ :: intrinsics
|
||||||
|
_ :: mem
|
||||||
|
|
||||||
|
Node :: struct($Key, $Value: typeid) where intrinsics.type_is_valid_map_key(Key) {
|
||||||
|
prev, next: ^Node(Key, Value),
|
||||||
|
key: Key,
|
||||||
|
value: Value,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache is an LRU cache. It automatically removes entries as new entries are
|
||||||
|
// added if the capacity is reached. Entries are removed based on how recently
|
||||||
|
// they were used where the oldest entries are removed first.
|
||||||
|
Cache :: struct($Key, $Value: typeid) where intrinsics.type_is_valid_map_key(Key) {
|
||||||
|
head: ^Node(Key, Value),
|
||||||
|
tail: ^Node(Key, Value),
|
||||||
|
|
||||||
|
entries: map[Key]^Node(Key, Value),
|
||||||
|
|
||||||
|
count: int,
|
||||||
|
capacity: int,
|
||||||
|
|
||||||
|
node_allocator: mem.Allocator,
|
||||||
|
|
||||||
|
on_remove: proc(key: Key, value: Value, user_data: rawptr),
|
||||||
|
on_remove_user_data: rawptr,
|
||||||
|
call_on_remove_on_destroy: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
// init initializes a Cache
|
||||||
|
init :: proc(c: ^$C/Cache($Key, $Value), capacity: int, entries_allocator := context.allocator, node_allocator := context.allocator) {
|
||||||
|
c.entries.allocator = entries_allocator
|
||||||
|
c.node_allocator = node_allocator
|
||||||
|
c.capacity = capacity
|
||||||
|
}
|
||||||
|
|
||||||
|
// destroy deinitializes a Cache
|
||||||
|
destroy :: proc(c: ^$C/Cache($Key, $Value)) {
|
||||||
|
for _, node in c.entries {
|
||||||
|
if c.call_on_remove_on_destroy && c.on_remove != nil {
|
||||||
|
c.on_remove(node.key, node.value, c.on_remove_user_data)
|
||||||
|
}
|
||||||
|
free(node, c.node_allocator)
|
||||||
|
}
|
||||||
|
clear(&c.entries)
|
||||||
|
delete(c.entries)
|
||||||
|
c.head = nil
|
||||||
|
c.tail = nil
|
||||||
|
c.count = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the given key value pair. This operation updates the recent usage of the item.
|
||||||
|
set :: proc(c: ^$C/Cache($Key, $Value), key: Key, value: Value) -> mem.Allocator_Error {
|
||||||
|
if e, ok := c.entries[key]; ok {
|
||||||
|
e.value = value
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
e := new(Node(Key, Value), c.node_allocator) or_return
|
||||||
|
e.key = key
|
||||||
|
e.value = value
|
||||||
|
|
||||||
|
_push_front_node(c, e)
|
||||||
|
if c.count > c.capacity {
|
||||||
|
_remove_node(c, c.tail)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.entries[key] = e
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// get a value from the cache from a given key. This operation updates the usage of the item.
|
||||||
|
get :: proc(c: ^$C/Cache($Key, $Value), key: Key) -> (value: Value, ok: bool) #optional_ok {
|
||||||
|
e: ^Node(Key, Value)
|
||||||
|
e, ok = c.entries[key]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_pop_node(c, e)
|
||||||
|
_push_front_node(c, e)
|
||||||
|
return e.value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// get_ptr gets the pointer to a value the cache from a given key. This operation updates the usage of the item.
|
||||||
|
get_ptr :: proc(c: ^$C/Cache($Key, $Value), key: Key) -> (value: ^Value, ok: bool) #optional_ok {
|
||||||
|
e: ^Node(Key, Value)
|
||||||
|
e, ok = c.entries[key]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_pop_node(c, e)
|
||||||
|
_push_front_node(c, e)
|
||||||
|
return &e.value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// peek gets the value from the cache from a given key without updating the recent usage.
|
||||||
|
peek :: proc(c: ^$C/Cache($Key, $Value), key: Key) -> (value: Value, ok: bool) #optional_ok {
|
||||||
|
e: ^Node(Key, Value)
|
||||||
|
e, ok = c.entries[key]
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return e.value, true
|
||||||
|
}
|
||||||
|
|
||||||
|
// exists checks for the existence of a value from a given key without updating the recent usage.
|
||||||
|
exists :: proc(c: ^$C/Cache($Key, $Value), key: Key) -> bool {
|
||||||
|
return key in c.entries
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove removes an item from the cache.
|
||||||
|
remove :: proc(c: ^$C/Cache($Key, $Value), key: Key) -> bool {
|
||||||
|
e, ok := c.entries[key]
|
||||||
|
if !ok {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_remove_node(c, e)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
_remove_node :: proc(c: ^$C/Cache($Key, $Value), node: ^Node(Key, Value)) {
|
||||||
|
if c.head == node {
|
||||||
|
c.head = node.next
|
||||||
|
}
|
||||||
|
if c.tail == node {
|
||||||
|
c.tail = node.prev
|
||||||
|
}
|
||||||
|
if node.prev != nil {
|
||||||
|
node.prev.next = node.next
|
||||||
|
}
|
||||||
|
if node.next != nil {
|
||||||
|
node.next.prev = node.prev
|
||||||
|
}
|
||||||
|
node.prev = nil
|
||||||
|
node.next = nil
|
||||||
|
|
||||||
|
c.count -= 1
|
||||||
|
|
||||||
|
delete_key(&c.entries, node.key)
|
||||||
|
|
||||||
|
if c.on_remove != nil {
|
||||||
|
c.on_remove(node.key, node.value, c.on_remove_user_data)
|
||||||
|
}
|
||||||
|
|
||||||
|
free(node, c.node_allocator)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
_push_front_node :: proc(c: ^$C/Cache($Key, $Value), e: ^Node(Key, Value)) {
|
||||||
|
if c.head != nil {
|
||||||
|
e.next = c.head
|
||||||
|
e.next.prev = e
|
||||||
|
}
|
||||||
|
c.head = e
|
||||||
|
if c.tail == nil {
|
||||||
|
c.tail = e
|
||||||
|
}
|
||||||
|
e.prev = nil
|
||||||
|
|
||||||
|
c.count += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
_pop_node :: proc(c: ^$C/Cache($Key, $Value), e: ^Node(Key, Value)) {
|
||||||
|
if e == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if e.prev != nil {
|
||||||
|
e.prev.next = e.next
|
||||||
|
}
|
||||||
|
|
||||||
|
if e.next != nil {
|
||||||
|
e.next.prev = e.prev
|
||||||
|
}
|
||||||
|
e.prev = nil
|
||||||
|
e.next = nil
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package container_queue
|
|||||||
|
|
||||||
import "core:builtin"
|
import "core:builtin"
|
||||||
import "core:runtime"
|
import "core:runtime"
|
||||||
|
_ :: runtime
|
||||||
|
|
||||||
// Dynamically resizable double-ended queue/ring-buffer
|
// Dynamically resizable double-ended queue/ring-buffer
|
||||||
Queue :: struct($T: typeid) {
|
Queue :: struct($T: typeid) {
|
||||||
@@ -86,7 +87,8 @@ push_back :: proc(q: ^$Q/Queue($T), elem: T) -> bool {
|
|||||||
if space(q^) == 0 {
|
if space(q^) == 0 {
|
||||||
_grow(q) or_return
|
_grow(q) or_return
|
||||||
}
|
}
|
||||||
q.data[q.len] = elem
|
idx := (q.offset+uint(q.len))%builtin.len(q.data)
|
||||||
|
q.data[idx] = elem
|
||||||
q.len += 1
|
q.len += 1
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -126,6 +128,7 @@ pop_back_safe :: proc(q: ^$Q/Queue($T)) -> (elem: T, ok: bool) {
|
|||||||
pop_front :: proc(q: ^$Q/Queue($T), loc := #caller_location) -> (elem: T) {
|
pop_front :: proc(q: ^$Q/Queue($T), loc := #caller_location) -> (elem: T) {
|
||||||
assert(condition=q.len > 0, loc=loc)
|
assert(condition=q.len > 0, loc=loc)
|
||||||
elem = q.data[q.offset]
|
elem = q.data[q.offset]
|
||||||
|
q.offset = (q.offset+1)%builtin.len(q.data)
|
||||||
q.len -= 1
|
q.len -= 1
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -133,6 +136,7 @@ pop_front :: proc(q: ^$Q/Queue($T), loc := #caller_location) -> (elem: T) {
|
|||||||
pop_front_safe :: proc(q: ^$Q/Queue($T)) -> (elem: T, ok: bool) {
|
pop_front_safe :: proc(q: ^$Q/Queue($T)) -> (elem: T, ok: bool) {
|
||||||
if q.len > 0 {
|
if q.len > 0 {
|
||||||
elem = q.data[q.offset]
|
elem = q.data[q.offset]
|
||||||
|
q.offset = (q.offset+1)%builtin.len(q.data)
|
||||||
q.len -= 1
|
q.len -= 1
|
||||||
ok = true
|
ok = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ fe_from_bytes :: #force_inline proc (out1: ^Tight_Field_Element, arg1: []byte, a
|
|||||||
|
|
||||||
assert(len(arg1) == 16)
|
assert(len(arg1) == 16)
|
||||||
|
|
||||||
when ODIN_ARCH == "386" || ODIN_ARCH == "amd64" {
|
when ODIN_ARCH == "i386" || ODIN_ARCH == "amd64" {
|
||||||
// While it may be unwise to do deserialization here on our
|
// While it may be unwise to do deserialization here on our
|
||||||
// own when fiat-crypto provides equivalent functionality,
|
// own when fiat-crypto provides equivalent functionality,
|
||||||
// doing it this way provides a little under 3x performance
|
// doing it this way provides a little under 3x performance
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ keccakf :: proc "contextless" (st: ^[25]u64) {
|
|||||||
t: u64 = ---
|
t: u64 = ---
|
||||||
bc: [5]u64 = ---
|
bc: [5]u64 = ---
|
||||||
|
|
||||||
when ODIN_ENDIAN != "little" {
|
when ODIN_ENDIAN != .Little {
|
||||||
v: uintptr = ---
|
v: uintptr = ---
|
||||||
for i = 0; i < 25; i += 1 {
|
for i = 0; i < 25; i += 1 {
|
||||||
v := uintptr(&st[i])
|
v := uintptr(&st[i])
|
||||||
@@ -98,7 +98,7 @@ keccakf :: proc "contextless" (st: ^[25]u64) {
|
|||||||
st[0] ~= keccakf_rndc[r]
|
st[0] ~= keccakf_rndc[r]
|
||||||
}
|
}
|
||||||
|
|
||||||
when ODIN_ENDIAN != "little" {
|
when ODIN_ENDIAN != .Little {
|
||||||
for i = 0; i < 25; i += 1 {
|
for i = 0; i < 25; i += 1 {
|
||||||
v = uintptr(&st[i])
|
v = uintptr(&st[i])
|
||||||
t = st[i]
|
t = st[i]
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ hash_bytes_224 :: proc "contextless" (data: []byte) -> [DIGEST_SIZE_224]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_224 will hash the given input and write the
|
// hash_bytes_to_buffer_224 will hash the given input and write the
|
||||||
@@ -123,7 +123,7 @@ hash_bytes_256 :: proc "contextless" (data: []byte) -> [DIGEST_SIZE_256]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||||
@@ -202,7 +202,7 @@ hash_bytes_384 :: proc "contextless" (data: []byte) -> [DIGEST_SIZE_384]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_384 will hash the given input and write the
|
// hash_bytes_to_buffer_384 will hash the given input and write the
|
||||||
@@ -281,7 +281,7 @@ hash_bytes_512 :: proc "contextless" (data: []byte) -> [DIGEST_SIZE_512]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_512 will hash the given input and write the
|
// hash_bytes_to_buffer_512 will hash the given input and write the
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer will hash the given input and write the
|
// hash_bytes_to_buffer will hash the given input and write the
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer will hash the given input and write the
|
// hash_bytes_to_buffer will hash the given input and write the
|
||||||
|
|||||||
@@ -346,7 +346,7 @@ _do_blocks :: proc (ctx: ^Context, dst, src: []byte, nr_blocks: int) {
|
|||||||
// Until dedicated assembly can be written leverage the fact that
|
// Until dedicated assembly can be written leverage the fact that
|
||||||
// the callers of this routine ensure that src/dst are valid.
|
// the callers of this routine ensure that src/dst are valid.
|
||||||
|
|
||||||
when ODIN_ARCH == "386" || ODIN_ARCH == "amd64" {
|
when ODIN_ARCH == "i386" || ODIN_ARCH == "amd64" {
|
||||||
// util.PUT_U32_LE/util.U32_LE are not required on little-endian
|
// util.PUT_U32_LE/util.U32_LE are not required on little-endian
|
||||||
// systems that also happen to not be strict about aligned
|
// systems that also happen to not be strict about aligned
|
||||||
// memory access.
|
// memory access.
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer will hash the given input and write the
|
// hash_bytes_to_buffer will hash the given input and write the
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_224 will hash the given input and write the
|
// hash_bytes_to_buffer_224 will hash the given input and write the
|
||||||
@@ -123,7 +123,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||||
@@ -202,7 +202,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_384 will hash the given input and write the
|
// hash_bytes_to_buffer_384 will hash the given input and write the
|
||||||
@@ -281,7 +281,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_512 will hash the given input and write the
|
// hash_bytes_to_buffer_512 will hash the given input and write the
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ hash_bytes_128_3 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_128_3 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_128_3 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_128_3(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_128_3(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_128_3 will hash the given input and write the
|
// hash_bytes_to_buffer_128_3 will hash the given input and write the
|
||||||
@@ -135,7 +135,7 @@ hash_bytes_128_4 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_128_4 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_128_4 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_128_4(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_128_4(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_128_4 will hash the given input and write the
|
// hash_bytes_to_buffer_128_4 will hash the given input and write the
|
||||||
@@ -220,7 +220,7 @@ hash_bytes_128_5 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_128_5 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_128_5 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_128_5(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_128_5(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_128_5 will hash the given input and write the
|
// hash_bytes_to_buffer_128_5 will hash the given input and write the
|
||||||
@@ -305,7 +305,7 @@ hash_bytes_160_3 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_160_3 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_160_3 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_160_3(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_160_3(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_160_3 will hash the given input and write the
|
// hash_bytes_to_buffer_160_3 will hash the given input and write the
|
||||||
@@ -390,7 +390,7 @@ hash_bytes_160_4 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_160_4 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_160_4 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_160_4(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_160_4(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_160_4 will hash the given input and write the
|
// hash_bytes_to_buffer_160_4 will hash the given input and write the
|
||||||
@@ -475,7 +475,7 @@ hash_bytes_160_5 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_160_5 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_160_5 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_160_5(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_160_5(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_160_5 will hash the given input and write the
|
// hash_bytes_to_buffer_160_5 will hash the given input and write the
|
||||||
@@ -560,7 +560,7 @@ hash_bytes_192_3 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_192_3 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_192_3 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_192_3(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_192_3(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_192_3 will hash the given input and write the
|
// hash_bytes_to_buffer_192_3 will hash the given input and write the
|
||||||
@@ -645,7 +645,7 @@ hash_bytes_192_4 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_192_4 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_192_4 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_192_4(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_192_4(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_192_4 will hash the given input and write the
|
// hash_bytes_to_buffer_192_4 will hash the given input and write the
|
||||||
@@ -730,7 +730,7 @@ hash_bytes_192_5 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_192_5 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_192_5 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_192_5(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_192_5(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_192_5 will hash the given input and write the
|
// hash_bytes_to_buffer_192_5 will hash the given input and write the
|
||||||
@@ -815,7 +815,7 @@ hash_bytes_224_3 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_224_3 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_224_3 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_224_3(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_224_3(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_224_3 will hash the given input and write the
|
// hash_bytes_to_buffer_224_3 will hash the given input and write the
|
||||||
@@ -900,7 +900,7 @@ hash_bytes_224_4 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_224_4 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_224_4 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_224_4(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_224_4(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_224_4 will hash the given input and write the
|
// hash_bytes_to_buffer_224_4 will hash the given input and write the
|
||||||
@@ -985,7 +985,7 @@ hash_bytes_224_5 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_224_5 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_224_5 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_224_5(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_224_5(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_224_5 will hash the given input and write the
|
// hash_bytes_to_buffer_224_5 will hash the given input and write the
|
||||||
@@ -1070,7 +1070,7 @@ hash_bytes_256_3 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_256_3 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_256_3 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_256_3(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_256_3(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_256_3 will hash the given input and write the
|
// hash_bytes_to_buffer_256_3 will hash the given input and write the
|
||||||
@@ -1155,7 +1155,7 @@ hash_bytes_256_4 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_256_4 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_256_4 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_256_4(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_256_4(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_256_4 will hash the given input and write the
|
// hash_bytes_to_buffer_256_4 will hash the given input and write the
|
||||||
@@ -1240,7 +1240,7 @@ hash_bytes_256_5 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_256_5 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_256_5 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_256_5(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_256_5(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_256_5 will hash the given input and write the
|
// hash_bytes_to_buffer_256_5 will hash the given input and write the
|
||||||
@@ -1332,7 +1332,7 @@ update :: proc(ctx: ^Haval_Context, data: []byte) {
|
|||||||
}
|
}
|
||||||
ctx.count[1] += str_len >> 29
|
ctx.count[1] += str_len >> 29
|
||||||
|
|
||||||
when ODIN_ENDIAN == "little" {
|
when ODIN_ENDIAN == .Little {
|
||||||
if rmd_len + str_len >= 128 {
|
if rmd_len + str_len >= 128 {
|
||||||
copy(util.slice_to_bytes(ctx.block[:])[rmd_len:], data[:fill_len])
|
copy(util.slice_to_bytes(ctx.block[:])[rmd_len:], data[:fill_len])
|
||||||
block(ctx, ctx.rounds)
|
block(ctx, ctx.rounds)
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_224 will hash the given input and write the
|
// hash_bytes_to_buffer_224 will hash the given input and write the
|
||||||
@@ -123,7 +123,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||||
@@ -202,7 +202,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_384 will hash the given input and write the
|
// hash_bytes_to_buffer_384 will hash the given input and write the
|
||||||
@@ -281,7 +281,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_512 will hash the given input and write the
|
// hash_bytes_to_buffer_512 will hash the given input and write the
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_224 will hash the given input and write the
|
// hash_bytes_to_buffer_224 will hash the given input and write the
|
||||||
@@ -131,7 +131,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||||
@@ -213,7 +213,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_384 will hash the given input and write the
|
// hash_bytes_to_buffer_384 will hash the given input and write the
|
||||||
@@ -295,7 +295,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_512 will hash the given input and write the
|
// hash_bytes_to_buffer_512 will hash the given input and write the
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer will hash the given input and write the
|
// hash_bytes_to_buffer will hash the given input and write the
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer will hash the given input and write the
|
// hash_bytes_to_buffer will hash the given input and write the
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer will hash the given input and write the
|
// hash_bytes_to_buffer will hash the given input and write the
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_128(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_128(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_128 will hash the given input and write the
|
// hash_bytes_to_buffer_128 will hash the given input and write the
|
||||||
@@ -121,7 +121,7 @@ hash_bytes_160 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_160 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_160 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_160(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_160(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_160 will hash the given input and write the
|
// hash_bytes_to_buffer_160 will hash the given input and write the
|
||||||
@@ -197,7 +197,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||||
@@ -273,7 +273,7 @@ hash_bytes_320 :: proc(data: []byte) -> [DIGEST_SIZE_320]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_320 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_320 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_320(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_320(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_320 will hash the given input and write the
|
// hash_bytes_to_buffer_320 will hash the given input and write the
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer will hash the given input and write the
|
// hash_bytes_to_buffer will hash the given input and write the
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_224 will hash the given input and write the
|
// hash_bytes_to_buffer_224 will hash the given input and write the
|
||||||
@@ -127,7 +127,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||||
@@ -206,7 +206,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_384 will hash the given input and write the
|
// hash_bytes_to_buffer_384 will hash the given input and write the
|
||||||
@@ -285,7 +285,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_512 will hash the given input and write the
|
// hash_bytes_to_buffer_512 will hash the given input and write the
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ hash_bytes_224 :: proc(data: []byte) -> [DIGEST_SIZE_224]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_224 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_224(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_224(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_224 will hash the given input and write the
|
// hash_bytes_to_buffer_224 will hash the given input and write the
|
||||||
@@ -126,7 +126,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||||
@@ -205,7 +205,7 @@ hash_bytes_384 :: proc(data: []byte) -> [DIGEST_SIZE_384]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_384 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_384(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_384(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_384 will hash the given input and write the
|
// hash_bytes_to_buffer_384 will hash the given input and write the
|
||||||
@@ -284,7 +284,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_512 will hash the given input and write the
|
// hash_bytes_to_buffer_512 will hash the given input and write the
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_128(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_128(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_128 will hash the given input and write the
|
// hash_bytes_to_buffer_128 will hash the given input and write the
|
||||||
@@ -128,7 +128,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer will hash the given input and write the
|
// hash_bytes_to_buffer will hash the given input and write the
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ hash_bytes_256 :: proc(data: []byte) -> [DIGEST_SIZE_256]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_256 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_256(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_256(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_256 will hash the given input and write the
|
// hash_bytes_to_buffer_256 will hash the given input and write the
|
||||||
@@ -122,7 +122,7 @@ hash_bytes_512 :: proc(data: []byte) -> [DIGEST_SIZE_512]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_512 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_512(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_512(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_512 will hash the given input and write the
|
// hash_bytes_to_buffer_512 will hash the given input and write the
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_128(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_128(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_128 will hash the given input and write the
|
// hash_bytes_to_buffer_128 will hash the given input and write the
|
||||||
@@ -124,7 +124,7 @@ hash_bytes_160 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_160 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_160 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_160(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_160(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_160 will hash the given input and write the
|
// hash_bytes_to_buffer_160 will hash the given input and write the
|
||||||
@@ -203,7 +203,7 @@ hash_bytes_192 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_192 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_192 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_192(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_192(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_192 will hash the given input and write the
|
// hash_bytes_to_buffer_192 will hash the given input and write the
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ hash_bytes_128 :: proc(data: []byte) -> [DIGEST_SIZE_128]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_128 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_128(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_128(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_128 will hash the given input and write the
|
// hash_bytes_to_buffer_128 will hash the given input and write the
|
||||||
@@ -124,7 +124,7 @@ hash_bytes_160 :: proc(data: []byte) -> [DIGEST_SIZE_160]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_160 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_160 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_160(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_160(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_160 will hash the given input and write the
|
// hash_bytes_to_buffer_160 will hash the given input and write the
|
||||||
@@ -203,7 +203,7 @@ hash_bytes_192 :: proc(data: []byte) -> [DIGEST_SIZE_192]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer_192 :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer_192 :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer_192(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer_192(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer_192 will hash the given input and write the
|
// hash_bytes_to_buffer_192 will hash the given input and write the
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ hash_bytes :: proc(data: []byte) -> [DIGEST_SIZE]byte {
|
|||||||
// computed hash to the second parameter.
|
// computed hash to the second parameter.
|
||||||
// It requires that the destination buffer is at least as big as the digest size
|
// It requires that the destination buffer is at least as big as the digest size
|
||||||
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
hash_string_to_buffer :: proc(data: string, hash: []byte) {
|
||||||
hash_bytes_to_buffer(transmute([]byte)(data), hash);
|
hash_bytes_to_buffer(transmute([]byte)(data), hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash_bytes_to_buffer will hash the given input and write the
|
// hash_bytes_to_buffer will hash the given input and write the
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
// Construction history, or BSP trees would make the format too large to serve its purpose.
|
// Construction history, or BSP trees would make the format too large to serve its purpose.
|
||||||
// The facilities of the formats to store meta data should make the format flexible enough
|
// The facilities of the formats to store meta data should make the format flexible enough
|
||||||
// for most uses. Adding HxA support should be something anyone can do in a days work.
|
// for most uses. Adding HxA support should be something anyone can do in a days work.
|
||||||
|
//
|
||||||
// Structure:
|
// Structure:
|
||||||
// ----------
|
// ----------
|
||||||
// HxA is designed to be extremely simple to parse, and is therefore based around conventions. It has
|
// HxA is designed to be extremely simple to parse, and is therefore based around conventions. It has
|
||||||
@@ -45,17 +45,17 @@
|
|||||||
// of a number of named layers. All layers in the stack have the same number of elements. Each layer
|
// of a number of named layers. All layers in the stack have the same number of elements. Each layer
|
||||||
// describes one property of the primitive. Each layer can have multiple channels and each layer can
|
// describes one property of the primitive. Each layer can have multiple channels and each layer can
|
||||||
// store data of a different type.
|
// store data of a different type.
|
||||||
|
//
|
||||||
// HaX stores 3 kinds of nodes
|
// HaX stores 3 kinds of nodes
|
||||||
// - Pixel data.
|
// - Pixel data.
|
||||||
// - Polygon geometry data.
|
// - Polygon geometry data.
|
||||||
// - Meta data only.
|
// - Meta data only.
|
||||||
|
//
|
||||||
// Pixel Nodes stores pixels in a layer stack. A layer may store things like Albedo, Roughness,
|
// Pixel Nodes stores pixels in a layer stack. A layer may store things like Albedo, Roughness,
|
||||||
// Reflectance, Light maps, Masks, Normal maps, and Displacement. Layers use the channels of the
|
// Reflectance, Light maps, Masks, Normal maps, and Displacement. Layers use the channels of the
|
||||||
// layers to store things like color. The length of the layer stack is determined by the type and
|
// layers to store things like color. The length of the layer stack is determined by the type and
|
||||||
// dimensions stored in the
|
// dimensions stored in the
|
||||||
|
//
|
||||||
// Geometry data is stored in 3 separate layer stacks for: vertex data, corner data and face data. The
|
// Geometry data is stored in 3 separate layer stacks for: vertex data, corner data and face data. The
|
||||||
// vertex data stores things like verities, blend shapes, weight maps, and vertex colors. The first
|
// vertex data stores things like verities, blend shapes, weight maps, and vertex colors. The first
|
||||||
// layer in a vertex stack has to be a 3 channel layer named "position" describing the base position
|
// layer in a vertex stack has to be a 3 channel layer named "position" describing the base position
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
// for things like UV, normals, and adjacency. The first layer in a corner stack has to be a 1 channel
|
// for things like UV, normals, and adjacency. The first layer in a corner stack has to be a 1 channel
|
||||||
// integer layer named "index" describing the vertices used to form polygons. The last value in each
|
// integer layer named "index" describing the vertices used to form polygons. The last value in each
|
||||||
// polygon has a negative - 1 index to indicate the end of the polygon.
|
// polygon has a negative - 1 index to indicate the end of the polygon.
|
||||||
|
//
|
||||||
// Example:
|
// Example:
|
||||||
// A quad and a tri with the vertex index:
|
// A quad and a tri with the vertex index:
|
||||||
// [0, 1, 2, 3] [1, 4, 2]
|
// [0, 1, 2, 3] [1, 4, 2]
|
||||||
@@ -72,7 +72,7 @@
|
|||||||
// The face stack stores values per face. the length of the face stack has to match the number of
|
// The face stack stores values per face. the length of the face stack has to match the number of
|
||||||
// negative values in the index layer in the corner stack. The face stack can be used to store things
|
// negative values in the index layer in the corner stack. The face stack can be used to store things
|
||||||
// like material index.
|
// like material index.
|
||||||
|
//
|
||||||
// Storage
|
// Storage
|
||||||
// -------
|
// -------
|
||||||
// All data is stored in little endian byte order with no padding. The layout mirrors the structs
|
// All data is stored in little endian byte order with no padding. The layout mirrors the structs
|
||||||
|
|||||||
@@ -285,8 +285,8 @@ marshal_to_writer :: proc(w: io.Writer, v: any) -> (err: Marshal_Error) {
|
|||||||
case runtime.Type_Info_Integer:
|
case runtime.Type_Info_Integer:
|
||||||
switch info.endianness {
|
switch info.endianness {
|
||||||
case .Platform: return false
|
case .Platform: return false
|
||||||
case .Little: return ODIN_ENDIAN != "little"
|
case .Little: return ODIN_ENDIAN != .Little
|
||||||
case .Big: return ODIN_ENDIAN != "big"
|
case .Big: return ODIN_ENDIAN != .Big
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|||||||
+1
-1
@@ -64,6 +64,7 @@ If not present, the width is whatever is necessary to represent the value.
|
|||||||
Precision is specified after the (optional) width followed by a period followed by a decimal number.
|
Precision is specified after the (optional) width followed by a period followed by a decimal number.
|
||||||
If no period is present, a default precision is used.
|
If no period is present, a default precision is used.
|
||||||
A period with no following number specifies a precision of 0.
|
A period with no following number specifies a precision of 0.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
%f default width, default precision
|
%f default width, default precision
|
||||||
%8f width 8, default precision
|
%8f width 8, default precision
|
||||||
@@ -84,7 +85,6 @@ Other flags:
|
|||||||
add leading 0z for dozenal (%#z)
|
add leading 0z for dozenal (%#z)
|
||||||
add leading 0x or 0X for hexadecimal (%#x or %#X)
|
add leading 0x or 0X for hexadecimal (%#x or %#X)
|
||||||
remove leading 0x for %p (%#p)
|
remove leading 0x for %p (%#p)
|
||||||
|
|
||||||
' ' (space) leave a space for elided sign in numbers (% d)
|
' ' (space) leave a space for elided sign in numbers (% d)
|
||||||
0 pad with leading zeros rather than spaces
|
0 pad with leading zeros rather than spaces
|
||||||
|
|
||||||
|
|||||||
+29
-8
@@ -11,6 +11,7 @@ import "core:time"
|
|||||||
import "core:unicode/utf8"
|
import "core:unicode/utf8"
|
||||||
import "core:intrinsics"
|
import "core:intrinsics"
|
||||||
|
|
||||||
|
// Internal data structure that stores the required information for formatted printing
|
||||||
Info :: struct {
|
Info :: struct {
|
||||||
minus: bool,
|
minus: bool,
|
||||||
plus: bool,
|
plus: bool,
|
||||||
@@ -46,9 +47,13 @@ Register_User_Formatter_Error :: enum {
|
|||||||
// it is prefixed with `_` rather than marked with a private attribute so that users can access it if necessary
|
// it is prefixed with `_` rather than marked with a private attribute so that users can access it if necessary
|
||||||
_user_formatters: ^map[typeid]User_Formatter
|
_user_formatters: ^map[typeid]User_Formatter
|
||||||
|
|
||||||
|
// set_user_formatters assigns m to a global value allowing the user have custom print formatting for specific
|
||||||
|
// types
|
||||||
set_user_formatters :: proc(m: ^map[typeid]User_Formatter) {
|
set_user_formatters :: proc(m: ^map[typeid]User_Formatter) {
|
||||||
_user_formatters = m
|
_user_formatters = m
|
||||||
}
|
}
|
||||||
|
// register_user_formatter assigns a formatter to a specific typeid. set_user_formatters must be called
|
||||||
|
// before any use of this procedure.
|
||||||
register_user_formatter :: proc(id: typeid, formatter: User_Formatter) -> Register_User_Formatter_Error {
|
register_user_formatter :: proc(id: typeid, formatter: User_Formatter) -> Register_User_Formatter_Error {
|
||||||
if _user_formatters == nil {
|
if _user_formatters == nil {
|
||||||
return .No_User_Formatter
|
return .No_User_Formatter
|
||||||
@@ -61,7 +66,7 @@ register_user_formatter :: proc(id: typeid, formatter: User_Formatter) -> Regist
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// aprint* procedures return a string that was allocated with the current context
|
// aprint procedure return a string that was allocated with the current context
|
||||||
// They must be freed accordingly
|
// They must be freed accordingly
|
||||||
aprint :: proc(args: ..any, sep := " ") -> string {
|
aprint :: proc(args: ..any, sep := " ") -> string {
|
||||||
str: strings.Builder
|
str: strings.Builder
|
||||||
@@ -69,12 +74,16 @@ aprint :: proc(args: ..any, sep := " ") -> string {
|
|||||||
sbprint(buf=&str, args=args, sep=sep)
|
sbprint(buf=&str, args=args, sep=sep)
|
||||||
return strings.to_string(str)
|
return strings.to_string(str)
|
||||||
}
|
}
|
||||||
|
// aprintln procedure return a string that was allocated with the current context
|
||||||
|
// They must be freed accordingly
|
||||||
aprintln :: proc(args: ..any, sep := " ") -> string {
|
aprintln :: proc(args: ..any, sep := " ") -> string {
|
||||||
str: strings.Builder
|
str: strings.Builder
|
||||||
strings.init_builder(&str)
|
strings.init_builder(&str)
|
||||||
sbprintln(buf=&str, args=args, sep=sep)
|
sbprintln(buf=&str, args=args, sep=sep)
|
||||||
return strings.to_string(str)
|
return strings.to_string(str)
|
||||||
}
|
}
|
||||||
|
// aprintf procedure return a string that was allocated with the current context
|
||||||
|
// They must be freed accordingly
|
||||||
aprintf :: proc(fmt: string, args: ..any) -> string {
|
aprintf :: proc(fmt: string, args: ..any) -> string {
|
||||||
str: strings.Builder
|
str: strings.Builder
|
||||||
strings.init_builder(&str)
|
strings.init_builder(&str)
|
||||||
@@ -83,19 +92,21 @@ aprintf :: proc(fmt: string, args: ..any) -> string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// tprint* procedures return a string that was allocated with the current context's temporary allocator
|
// tprint procedure return a string that was allocated with the current context's temporary allocator
|
||||||
tprint :: proc(args: ..any, sep := " ") -> string {
|
tprint :: proc(args: ..any, sep := " ") -> string {
|
||||||
str: strings.Builder
|
str: strings.Builder
|
||||||
strings.init_builder(&str, context.temp_allocator)
|
strings.init_builder(&str, context.temp_allocator)
|
||||||
sbprint(buf=&str, args=args, sep=sep)
|
sbprint(buf=&str, args=args, sep=sep)
|
||||||
return strings.to_string(str)
|
return strings.to_string(str)
|
||||||
}
|
}
|
||||||
|
// tprintln procedure return a string that was allocated with the current context's temporary allocator
|
||||||
tprintln :: proc(args: ..any, sep := " ") -> string {
|
tprintln :: proc(args: ..any, sep := " ") -> string {
|
||||||
str: strings.Builder
|
str: strings.Builder
|
||||||
strings.init_builder(&str, context.temp_allocator)
|
strings.init_builder(&str, context.temp_allocator)
|
||||||
sbprintln(buf=&str, args=args, sep=sep)
|
sbprintln(buf=&str, args=args, sep=sep)
|
||||||
return strings.to_string(str)
|
return strings.to_string(str)
|
||||||
}
|
}
|
||||||
|
// tprintf procedure return a string that was allocated with the current context's temporary allocator
|
||||||
tprintf :: proc(fmt: string, args: ..any) -> string {
|
tprintf :: proc(fmt: string, args: ..any) -> string {
|
||||||
str: strings.Builder
|
str: strings.Builder
|
||||||
strings.init_builder(&str, context.temp_allocator)
|
strings.init_builder(&str, context.temp_allocator)
|
||||||
@@ -104,21 +115,24 @@ tprintf :: proc(fmt: string, args: ..any) -> string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// bprint* procedures return a string using a buffer from an array
|
// bprint procedures return a string using a buffer from an array
|
||||||
bprint :: proc(buf: []byte, args: ..any, sep := " ") -> string {
|
bprint :: proc(buf: []byte, args: ..any, sep := " ") -> string {
|
||||||
sb := strings.builder_from_slice(buf[0:len(buf)])
|
sb := strings.builder_from_slice(buf[0:len(buf)])
|
||||||
return sbprint(buf=&sb, args=args, sep=sep)
|
return sbprint(buf=&sb, args=args, sep=sep)
|
||||||
}
|
}
|
||||||
|
// bprintln procedures return a string using a buffer from an array
|
||||||
bprintln :: proc(buf: []byte, args: ..any, sep := " ") -> string {
|
bprintln :: proc(buf: []byte, args: ..any, sep := " ") -> string {
|
||||||
sb := strings.builder_from_slice(buf[0:len(buf)])
|
sb := strings.builder_from_slice(buf[0:len(buf)])
|
||||||
return sbprintln(buf=&sb, args=args, sep=sep)
|
return sbprintln(buf=&sb, args=args, sep=sep)
|
||||||
}
|
}
|
||||||
|
// bprintf procedures return a string using a buffer from an array
|
||||||
bprintf :: proc(buf: []byte, fmt: string, args: ..any) -> string {
|
bprintf :: proc(buf: []byte, fmt: string, args: ..any) -> string {
|
||||||
sb := strings.builder_from_slice(buf[0:len(buf)])
|
sb := strings.builder_from_slice(buf[0:len(buf)])
|
||||||
return sbprintf(&sb, fmt, ..args)
|
return sbprintf(&sb, fmt, ..args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// formatted assert
|
||||||
assertf :: proc(condition: bool, fmt: string, args: ..any, loc := #caller_location) -> bool {
|
assertf :: proc(condition: bool, fmt: string, args: ..any, loc := #caller_location) -> bool {
|
||||||
if !condition {
|
if !condition {
|
||||||
p := context.assertion_failure_proc
|
p := context.assertion_failure_proc
|
||||||
@@ -131,6 +145,7 @@ assertf :: proc(condition: bool, fmt: string, args: ..any, loc := #caller_locati
|
|||||||
return condition
|
return condition
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// formatted panic
|
||||||
panicf :: proc(fmt: string, args: ..any, loc := #caller_location) -> ! {
|
panicf :: proc(fmt: string, args: ..any, loc := #caller_location) -> ! {
|
||||||
p := context.assertion_failure_proc
|
p := context.assertion_failure_proc
|
||||||
if p == nil {
|
if p == nil {
|
||||||
@@ -142,24 +157,26 @@ panicf :: proc(fmt: string, args: ..any, loc := #caller_location) -> ! {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// sbprint formats using the default print settings and writes to buf
|
||||||
|
|
||||||
sbprint :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
|
sbprint :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
|
||||||
wprint(w=strings.to_writer(buf), args=args, sep=sep)
|
wprint(w=strings.to_writer(buf), args=args, sep=sep)
|
||||||
return strings.to_string(buf^)
|
return strings.to_string(buf^)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sbprintln formats using the default print settings and writes to buf
|
||||||
sbprintln :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
|
sbprintln :: proc(buf: ^strings.Builder, args: ..any, sep := " ") -> string {
|
||||||
wprintln(w=strings.to_writer(buf), args=args, sep=sep)
|
wprintln(w=strings.to_writer(buf), args=args, sep=sep)
|
||||||
return strings.to_string(buf^)
|
return strings.to_string(buf^)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sbprintf formats according to the specififed format string and writes to buf
|
||||||
sbprintf :: proc(buf: ^strings.Builder, fmt: string, args: ..any) -> string {
|
sbprintf :: proc(buf: ^strings.Builder, fmt: string, args: ..any) -> string {
|
||||||
wprintf(w=strings.to_writer(buf), fmt=fmt, args=args)
|
wprintf(w=strings.to_writer(buf), fmt=fmt, args=args)
|
||||||
return strings.to_string(buf^)
|
return strings.to_string(buf^)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// wprint formats using the default print settings and writes to w
|
||||||
wprint :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
|
wprint :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
|
||||||
fi: Info
|
fi: Info
|
||||||
fi.writer = w
|
fi.writer = w
|
||||||
@@ -194,6 +211,7 @@ wprint :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
|
|||||||
return int(size1 - size0)
|
return int(size1 - size0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wprintln formats using the default print settings and writes to w
|
||||||
wprintln :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
|
wprintln :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
|
||||||
fi: Info
|
fi: Info
|
||||||
fi.writer = w
|
fi.writer = w
|
||||||
@@ -214,6 +232,7 @@ wprintln :: proc(w: io.Writer, args: ..any, sep := " ") -> int {
|
|||||||
return int(size1 - size0)
|
return int(size1 - size0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wprintf formats according to the specififed format string and writes to w
|
||||||
wprintf :: proc(w: io.Writer, fmt: string, args: ..any) -> int {
|
wprintf :: proc(w: io.Writer, fmt: string, args: ..any) -> int {
|
||||||
fi: Info
|
fi: Info
|
||||||
arg_index: int = 0
|
arg_index: int = 0
|
||||||
@@ -493,11 +512,13 @@ wprintf :: proc(w: io.Writer, fmt: string, args: ..any) -> int {
|
|||||||
return int(size1 - size0)
|
return int(size1 - size0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// wprint_type is a utility procedure to write a ^runtime.Type_Info value to w
|
||||||
wprint_type :: proc(w: io.Writer, info: ^runtime.Type_Info) -> (int, io.Error) {
|
wprint_type :: proc(w: io.Writer, info: ^runtime.Type_Info) -> (int, io.Error) {
|
||||||
n, err := reflect.write_type(w, info)
|
n, err := reflect.write_type(w, info)
|
||||||
io.flush(auto_cast w)
|
io.flush(auto_cast w)
|
||||||
return n, err
|
return n, err
|
||||||
}
|
}
|
||||||
|
// wprint_typeid is a utility procedure to write a typeid value to w
|
||||||
wprint_typeid :: proc(w: io.Writer, id: typeid) -> (int, io.Error) {
|
wprint_typeid :: proc(w: io.Writer, id: typeid) -> (int, io.Error) {
|
||||||
n, err := reflect.write_type(w, type_info_of(id))
|
n, err := reflect.write_type(w, type_info_of(id))
|
||||||
io.flush(auto_cast w)
|
io.flush(auto_cast w)
|
||||||
@@ -829,7 +850,7 @@ _pad :: proc(fi: ^Info, s: string) {
|
|||||||
|
|
||||||
fmt_float :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune) {
|
fmt_float :: proc(fi: ^Info, v: f64, bit_size: int, verb: rune) {
|
||||||
switch verb {
|
switch verb {
|
||||||
case 'f', 'F', 'v':
|
case 'f', 'F', 'g', 'G', 'v':
|
||||||
prec: int = 3
|
prec: int = 3
|
||||||
if fi.prec_set {
|
if fi.prec_set {
|
||||||
prec = fi.prec
|
prec = fi.prec
|
||||||
@@ -1092,8 +1113,8 @@ fmt_bit_set :: proc(fi: ^Info, v: any, name: string = "") {
|
|||||||
case runtime.Type_Info_Integer:
|
case runtime.Type_Info_Integer:
|
||||||
switch info.endianness {
|
switch info.endianness {
|
||||||
case .Platform: return false
|
case .Platform: return false
|
||||||
case .Little: return ODIN_ENDIAN != "little"
|
case .Little: return ODIN_ENDIAN != .Little
|
||||||
case .Big: return ODIN_ENDIAN != "big"
|
case .Big: return ODIN_ENDIAN != .Big
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -34,11 +34,16 @@ stderr := io.Writer{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// print* procedures return the number of bytes written
|
// print formats using the default print settings and writes to stdout
|
||||||
print :: proc(args: ..any, sep := " ") -> int { return wprint(w=stdout, args=args, sep=sep) }
|
print :: proc(args: ..any, sep := " ") -> int { return wprint(w=stdout, args=args, sep=sep) }
|
||||||
|
// println formats using the default print settings and writes to stdout
|
||||||
println :: proc(args: ..any, sep := " ") -> int { return wprintln(w=stdout, args=args, sep=sep) }
|
println :: proc(args: ..any, sep := " ") -> int { return wprintln(w=stdout, args=args, sep=sep) }
|
||||||
|
// printf formats according to the specififed format string and writes to stdout
|
||||||
printf :: proc(fmt: string, args: ..any) -> int { return wprintf(stdout, fmt, ..args) }
|
printf :: proc(fmt: string, args: ..any) -> int { return wprintf(stdout, fmt, ..args) }
|
||||||
|
|
||||||
|
// eprint formats using the default print settings and writes to stderr
|
||||||
eprint :: proc(args: ..any, sep := " ") -> int { return wprint(w=stderr, args=args, sep=sep) }
|
eprint :: proc(args: ..any, sep := " ") -> int { return wprint(w=stderr, args=args, sep=sep) }
|
||||||
|
// eprintln formats using the default print settings and writes to stderr
|
||||||
eprintln :: proc(args: ..any, sep := " ") -> int { return wprintln(w=stderr, args=args, sep=sep) }
|
eprintln :: proc(args: ..any, sep := " ") -> int { return wprintln(w=stderr, args=args, sep=sep) }
|
||||||
|
// eprintf formats according to the specififed format string and writes to stderr
|
||||||
eprintf :: proc(fmt: string, args: ..any) -> int { return wprintf(stderr, fmt, ..args) }
|
eprintf :: proc(fmt: string, args: ..any) -> int { return wprintf(stderr, fmt, ..args) }
|
||||||
|
|||||||
@@ -5,15 +5,18 @@ import "core:runtime"
|
|||||||
import "core:os"
|
import "core:os"
|
||||||
import "core:io"
|
import "core:io"
|
||||||
|
|
||||||
|
// fprint formats using the default print settings and writes to fd
|
||||||
fprint :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
|
fprint :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
|
||||||
w := io.to_writer(os.stream_from_handle(fd))
|
w := io.to_writer(os.stream_from_handle(fd))
|
||||||
return wprint(w=w, args=args, sep=sep)
|
return wprint(w=w, args=args, sep=sep)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fprintln formats using the default print settings and writes to fd
|
||||||
fprintln :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
|
fprintln :: proc(fd: os.Handle, args: ..any, sep := " ") -> int {
|
||||||
w := io.to_writer(os.stream_from_handle(fd))
|
w := io.to_writer(os.stream_from_handle(fd))
|
||||||
return wprintln(w=w, args=args, sep=sep)
|
return wprintln(w=w, args=args, sep=sep)
|
||||||
}
|
}
|
||||||
|
// fprintf formats according to the specififed format string and writes to fd
|
||||||
fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
|
fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
|
||||||
w := io.to_writer(os.stream_from_handle(fd))
|
w := io.to_writer(os.stream_from_handle(fd))
|
||||||
return wprintf(w, fmt, ..args)
|
return wprintf(w, fmt, ..args)
|
||||||
@@ -27,11 +30,16 @@ fprint_typeid :: proc(fd: os.Handle, id: typeid) -> (n: int, err: io.Error) {
|
|||||||
return wprint_typeid(w, id)
|
return wprint_typeid(w, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
// print* procedures return the number of bytes written
|
// print formats using the default print settings and writes to os.stdout
|
||||||
print :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stdout, args=args, sep=sep) }
|
print :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stdout, args=args, sep=sep) }
|
||||||
|
// println formats using the default print settings and writes to os.stdout
|
||||||
println :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stdout, args=args, sep=sep) }
|
println :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stdout, args=args, sep=sep) }
|
||||||
|
// printf formats according to the specififed format string and writes to os.stdout
|
||||||
printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args) }
|
printf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stdout, fmt, ..args) }
|
||||||
|
|
||||||
|
// eprint formats using the default print settings and writes to os.stderr
|
||||||
eprint :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stderr, args=args, sep=sep) }
|
eprint :: proc(args: ..any, sep := " ") -> int { return fprint(fd=os.stderr, args=args, sep=sep) }
|
||||||
|
// eprintln formats using the default print settings and writes to os.stderr
|
||||||
eprintln :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stderr, args=args, sep=sep) }
|
eprintln :: proc(args: ..any, sep := " ") -> int { return fprintln(fd=os.stderr, args=args, sep=sep) }
|
||||||
|
// eprintf formats according to the specififed format string and writes to os.stderr
|
||||||
eprintf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args) }
|
eprintf :: proc(fmt: string, args: ..any) -> int { return fprintf(os.stderr, fmt, ..args) }
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ XXH3_128_canonical_from_hash :: proc(hash: XXH128_hash_t) -> (canonical: XXH128_
|
|||||||
#assert(size_of(XXH128_canonical) == size_of(XXH128_hash_t))
|
#assert(size_of(XXH128_canonical) == size_of(XXH128_hash_t))
|
||||||
|
|
||||||
t := hash
|
t := hash
|
||||||
when ODIN_ENDIAN == "little" {
|
when ODIN_ENDIAN == .Little {
|
||||||
t.high = byte_swap(t.high)
|
t.high = byte_swap(t.high)
|
||||||
t.low = byte_swap(t.low)
|
t.low = byte_swap(t.low)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
Jeroen van Rijn: Initial implementation, optimization.
|
Jeroen van Rijn: Initial implementation, optimization.
|
||||||
Ginger Bill: Cosmetic changes.
|
Ginger Bill: Cosmetic changes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// package image implements a general 2D image library to be used with other image related packages
|
||||||
package image
|
package image
|
||||||
|
|
||||||
import "core:bytes"
|
import "core:bytes"
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ write_image_as_ppm :: proc(filename: string, image: ^image.Image) -> (success: b
|
|||||||
img := image
|
img := image
|
||||||
|
|
||||||
// PBM 16-bit images are big endian
|
// PBM 16-bit images are big endian
|
||||||
when ODIN_ENDIAN == "little" {
|
when ODIN_ENDIAN == .Little {
|
||||||
if img.depth == 16 {
|
if img.depth == 16 {
|
||||||
// The pixel components are in Big Endian. Let's byteswap back.
|
// The pixel components are in Big Endian. Let's byteswap back.
|
||||||
input := mem.slice_data_cast([]u16, img.pixels.buf[:])
|
input := mem.slice_data_cast([]u16, img.pixels.buf[:])
|
||||||
|
|||||||
@@ -6,6 +6,11 @@
|
|||||||
Jeroen van Rijn: Initial implementation.
|
Jeroen van Rijn: Initial implementation.
|
||||||
Ginger Bill: Cosmetic changes.
|
Ginger Bill: Cosmetic changes.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// package png implements a PNG image reader
|
||||||
|
//
|
||||||
|
// The PNG specification is at https://www.w3.org/TR/PNG/.
|
||||||
package png
|
package png
|
||||||
|
|
||||||
import "core:compress"
|
import "core:compress"
|
||||||
@@ -1611,7 +1616,7 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
when ODIN_ENDIAN == "little" {
|
when ODIN_ENDIAN == .Little {
|
||||||
if img.depth == 16 {
|
if img.depth == 16 {
|
||||||
// The pixel components are in Big Endian. Let's byteswap.
|
// The pixel components are in Big Endian. Let's byteswap.
|
||||||
input := mem.slice_data_cast([]u16be, img.pixels.buf[:])
|
input := mem.slice_data_cast([]u16be, img.pixels.buf[:])
|
||||||
|
|||||||
@@ -197,3 +197,8 @@ 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_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_hasher_proc :: proc($T: typeid) -> (hasher: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr) where type_is_comparable(T) ---
|
||||||
|
|
||||||
|
|
||||||
|
// Internal compiler use only
|
||||||
|
|
||||||
|
__entry_point :: proc() ---
|
||||||
+39
-2
@@ -1,9 +1,13 @@
|
|||||||
|
// package io provides basic interfaces for generic data stream primitives.
|
||||||
|
// The purpose of this package is wrap existing data structures and their
|
||||||
|
// operations into an abstracted stream interface.
|
||||||
package io
|
package io
|
||||||
|
|
||||||
import "core:intrinsics"
|
import "core:intrinsics"
|
||||||
import "core:runtime"
|
import "core:runtime"
|
||||||
import "core:unicode/utf8"
|
import "core:unicode/utf8"
|
||||||
|
|
||||||
|
// Seek whence values
|
||||||
Seek_From :: enum {
|
Seek_From :: enum {
|
||||||
Start = 0, // seek relative to the origin of the file
|
Start = 0, // seek relative to the origin of the file
|
||||||
Current = 1, // seek relative to the current offset
|
Current = 1, // seek relative to the current offset
|
||||||
@@ -139,6 +143,10 @@ destroy :: proc(s: Stream) -> Error {
|
|||||||
return .Empty
|
return .Empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// read reads up to len(p) bytes into s. It returns the number of bytes read and any error if occurred.
|
||||||
|
//
|
||||||
|
// When read encounters an .EOF or error after successfully reading n > 0 bytes, it returns the number of
|
||||||
|
// bytes read along with the error.
|
||||||
read :: proc(s: Reader, p: []byte, n_read: ^int = nil) -> (n: int, err: Error) {
|
read :: proc(s: Reader, p: []byte, n_read: ^int = nil) -> (n: int, err: Error) {
|
||||||
if s.stream_vtable != nil && s.impl_read != nil {
|
if s.stream_vtable != nil && s.impl_read != nil {
|
||||||
n, err = s->impl_read(p)
|
n, err = s->impl_read(p)
|
||||||
@@ -150,6 +158,7 @@ read :: proc(s: Reader, p: []byte, n_read: ^int = nil) -> (n: int, err: Error) {
|
|||||||
return 0, .Empty
|
return 0, .Empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write writes up to len(p) bytes into s. It returns the number of bytes written and any error if occurred.
|
||||||
write :: proc(s: Writer, p: []byte, n_written: ^int = nil) -> (n: int, err: Error) {
|
write :: proc(s: Writer, p: []byte, n_written: ^int = nil) -> (n: int, err: Error) {
|
||||||
if s.stream_vtable != nil && s.impl_write != nil {
|
if s.stream_vtable != nil && s.impl_write != nil {
|
||||||
n, err = s->impl_write(p)
|
n, err = s->impl_write(p)
|
||||||
@@ -161,6 +170,13 @@ write :: proc(s: Writer, p: []byte, n_written: ^int = nil) -> (n: int, err: Erro
|
|||||||
return 0, .Empty
|
return 0, .Empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// seek sets the offset of the next read or write to offset.
|
||||||
|
//
|
||||||
|
// .Start means seek relative to the origin of the file.
|
||||||
|
// .Current means seek relative to the current offset.
|
||||||
|
// .End means seek relative to the end.
|
||||||
|
//
|
||||||
|
// seek returns the new offset to the start of the file/stream, and any error if occurred.
|
||||||
seek :: proc(s: Seeker, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
|
seek :: proc(s: Seeker, offset: i64, whence: Seek_From) -> (n: i64, err: Error) {
|
||||||
if s.stream_vtable != nil && s.impl_seek != nil {
|
if s.stream_vtable != nil && s.impl_seek != nil {
|
||||||
return s->impl_seek(offset, whence)
|
return s->impl_seek(offset, whence)
|
||||||
@@ -168,6 +184,8 @@ seek :: proc(s: Seeker, offset: i64, whence: Seek_From) -> (n: i64, err: Error)
|
|||||||
return 0, .Empty
|
return 0, .Empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The behaviour of close after the first call is stream implementation defined.
|
||||||
|
// Different streams may document their own behaviour.
|
||||||
close :: proc(s: Closer) -> Error {
|
close :: proc(s: Closer) -> Error {
|
||||||
if s.stream_vtable != nil && s.impl_close != nil {
|
if s.stream_vtable != nil && s.impl_close != nil {
|
||||||
return s->impl_close()
|
return s->impl_close()
|
||||||
@@ -184,6 +202,7 @@ flush :: proc(s: Flusher) -> Error {
|
|||||||
return .None
|
return .None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// size returns the size of the stream. If the stream does not support querying its size, 0 will be returned.
|
||||||
size :: proc(s: Stream) -> i64 {
|
size :: proc(s: Stream) -> i64 {
|
||||||
if s.stream_vtable == nil {
|
if s.stream_vtable == nil {
|
||||||
return 0
|
return 0
|
||||||
@@ -214,7 +233,12 @@ size :: proc(s: Stream) -> i64 {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// read_at reads len(p) bytes into p starting with the provided offset in the underlying Reader_At stream r.
|
||||||
|
// It returns the number of bytes read and any error if occurred.
|
||||||
|
//
|
||||||
|
// When read_at returns n < len(p), it returns a non-nil Error explaining why.
|
||||||
|
//
|
||||||
|
// If n == len(p), err may be either nil or .EOF
|
||||||
read_at :: proc(r: Reader_At, p: []byte, offset: i64, n_read: ^int = nil) -> (n: int, err: Error) {
|
read_at :: proc(r: Reader_At, p: []byte, offset: i64, n_read: ^int = nil) -> (n: int, err: Error) {
|
||||||
defer if n_read != nil {
|
defer if n_read != nil {
|
||||||
n_read^ += n
|
n_read^ += n
|
||||||
@@ -245,6 +269,11 @@ read_at :: proc(r: Reader_At, p: []byte, offset: i64, n_read: ^int = nil) -> (n:
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write_at writes len(p) bytes into p starting with the provided offset in the underlying Writer_At stream w.
|
||||||
|
// It returns the number of bytes written and any error if occurred.
|
||||||
|
//
|
||||||
|
// If write_at is writing to a Writer_At which has a seek offset, then write_at should not affect the underlying
|
||||||
|
// seek offset.
|
||||||
write_at :: proc(w: Writer_At, p: []byte, offset: i64, n_written: ^int = nil) -> (n: int, err: Error) {
|
write_at :: proc(w: Writer_At, p: []byte, offset: i64, n_written: ^int = nil) -> (n: int, err: Error) {
|
||||||
defer if n_written != nil {
|
defer if n_written != nil {
|
||||||
n_written^ += n
|
n_written^ += n
|
||||||
@@ -294,6 +323,7 @@ read_from :: proc(w: Reader_From, r: Reader) -> (n: i64, err: Error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// read_byte reads and returns the next byte from r.
|
||||||
read_byte :: proc(r: Byte_Reader, n_read: ^int = nil) -> (b: byte, err: Error) {
|
read_byte :: proc(r: Byte_Reader, n_read: ^int = nil) -> (b: byte, err: Error) {
|
||||||
defer if err == nil && n_read != nil {
|
defer if err == nil && n_read != nil {
|
||||||
n_read^ += 1
|
n_read^ += 1
|
||||||
@@ -347,6 +377,7 @@ _write_byte :: proc(w: Byte_Writer, c: byte, n_written: ^int = nil) -> (err: Err
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// read_rune reads a single UTF-8 encoded Unicode codepoint and returns the rune and its size in bytes.
|
||||||
read_rune :: proc(br: Rune_Reader, n_read: ^int = nil) -> (ch: rune, size: int, err: Error) {
|
read_rune :: proc(br: Rune_Reader, n_read: ^int = nil) -> (ch: rune, size: int, err: Error) {
|
||||||
defer if err == nil && n_read != nil {
|
defer if err == nil && n_read != nil {
|
||||||
n_read^ += size
|
n_read^ += size
|
||||||
@@ -405,10 +436,12 @@ unread_rune :: proc(s: Rune_Scanner) -> Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// write_string writes the contents of the string s to w.
|
||||||
write_string :: proc(s: Writer, str: string, n_written: ^int = nil) -> (n: int, err: Error) {
|
write_string :: proc(s: Writer, str: string, n_written: ^int = nil) -> (n: int, err: Error) {
|
||||||
return write(s, transmute([]byte)str, n_written)
|
return write(s, transmute([]byte)str, n_written)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write_rune writes a UTF-8 encoded rune to w.
|
||||||
write_rune :: proc(s: Writer, r: rune, n_written: ^int = nil) -> (size: int, err: Error) {
|
write_rune :: proc(s: Writer, r: rune, n_written: ^int = nil) -> (size: int, err: Error) {
|
||||||
defer if err == nil && n_written != nil {
|
defer if err == nil && n_written != nil {
|
||||||
n_written^ += size
|
n_written^ += size
|
||||||
@@ -430,12 +463,16 @@ write_rune :: proc(s: Writer, r: rune, n_written: ^int = nil) -> (size: int, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// read_full expected exactly len(buf) bytes from r into buf.
|
||||||
read_full :: proc(r: Reader, buf: []byte) -> (n: int, err: Error) {
|
read_full :: proc(r: Reader, buf: []byte) -> (n: int, err: Error) {
|
||||||
return read_at_least(r, buf, len(buf))
|
return read_at_least(r, buf, len(buf))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// read_at_least reads from r into buf until it has read at least min bytes. It returns the number
|
||||||
|
// of bytes copied and an error if fewer bytes were read. `.EOF` is only returned if no bytes were read.
|
||||||
|
// `.Unexpected_EOF` is returned when an `.EOF ` is returned by the passed Reader after reading
|
||||||
|
// fewer than min bytes. If len(buf) is less than min, `.Short_Buffer` is returned.
|
||||||
read_at_least :: proc(r: Reader, buf: []byte, min: int) -> (n: int, err: Error) {
|
read_at_least :: proc(r: Reader, buf: []byte, min: int) -> (n: int, err: Error) {
|
||||||
if len(buf) < min {
|
if len(buf) < min {
|
||||||
return 0, .Short_Buffer
|
return 0, .Short_Buffer
|
||||||
|
|||||||
@@ -2,12 +2,10 @@
|
|||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
Made available under Odin's BSD-3 license.
|
Made available under Odin's BSD-3 license.
|
||||||
|
|
||||||
An arbitrary precision mathematics implementation in Odin.
|
|
||||||
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
|
|
||||||
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
|
|
||||||
|
|
||||||
This file collects public proc maps and their aliases.
|
This file collects public proc maps and their aliases.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package math_big
|
package math_big
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
Made available under Odin's BSD-3 license.
|
Made available under Odin's BSD-3 license.
|
||||||
|
|
||||||
An arbitrary precision mathematics implementation in Odin.
|
|
||||||
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
|
|
||||||
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package math_big
|
package math_big
|
||||||
|
|
||||||
import "core:intrinsics"
|
import "core:intrinsics"
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/*
|
||||||
|
A BigInt implementation in Odin.
|
||||||
|
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
|
||||||
|
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
|
||||||
|
*/
|
||||||
|
package math_big
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
Made available under Odin's BSD-3 license.
|
Made available under Odin's BSD-3 license.
|
||||||
|
|
||||||
An arbitrary precision mathematics implementation in Odin.
|
|
||||||
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
|
|
||||||
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package math_big
|
package math_big
|
||||||
|
|
||||||
import "core:intrinsics"
|
import "core:intrinsics"
|
||||||
|
|||||||
@@ -1,12 +1,7 @@
|
|||||||
//+ignore
|
|
||||||
/*
|
/*
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
Made available under Odin's BSD-3 license.
|
Made available under Odin's BSD-3 license.
|
||||||
|
|
||||||
A BigInt implementation in Odin.
|
|
||||||
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
|
|
||||||
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
|
|
||||||
|
|
||||||
========================== Low-level routines ==========================
|
========================== Low-level routines ==========================
|
||||||
|
|
||||||
IMPORTANT: `internal_*` procedures make certain assumptions about their input.
|
IMPORTANT: `internal_*` procedures make certain assumptions about their input.
|
||||||
@@ -29,6 +24,9 @@
|
|||||||
|
|
||||||
TODO: Handle +/- Infinity and NaN.
|
TODO: Handle +/- Infinity and NaN.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
//+ignore
|
||||||
package math_big
|
package math_big
|
||||||
|
|
||||||
import "core:mem"
|
import "core:mem"
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
This file contains logical operations like `and`, `or` and `xor`.
|
This file contains logical operations like `and`, `or` and `xor`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package math_big
|
package math_big
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
This file contains prime finding operations.
|
This file contains prime finding operations.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package math_big
|
package math_big
|
||||||
|
|
||||||
import rnd "core:math/rand"
|
import rnd "core:math/rand"
|
||||||
|
|||||||
@@ -15,6 +15,8 @@
|
|||||||
|
|
||||||
These aren't exported for the same reasons.
|
These aren't exported for the same reasons.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package math_big
|
package math_big
|
||||||
|
|
||||||
import "core:intrinsics"
|
import "core:intrinsics"
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
This file contains basic arithmetic operations like `add`, `sub`, `mul`, `div`, ...
|
This file contains basic arithmetic operations like `add`, `sub`, `mul`, `div`, ...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package math_big
|
package math_big
|
||||||
|
|
||||||
import "core:intrinsics"
|
import "core:intrinsics"
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
- Use Barrett reduction for non-powers-of-two.
|
- Use Barrett reduction for non-powers-of-two.
|
||||||
- Also look at extracting and splatting several digits at once.
|
- Also look at extracting and splatting several digits at once.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package math_big
|
package math_big
|
||||||
|
|
||||||
import "core:intrinsics"
|
import "core:intrinsics"
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
//+ignore
|
|
||||||
/*
|
/*
|
||||||
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
Copyright 2021 Jeroen van Rijn <nom@duclavier.com>.
|
||||||
Made available under Odin's BSD-3 license.
|
Made available under Odin's BSD-3 license.
|
||||||
@@ -7,6 +6,8 @@
|
|||||||
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
|
For the theoretical underpinnings, see Knuth's The Art of Computer Programming, Volume 2, section 4.3.
|
||||||
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
|
The code started out as an idiomatic source port of libTomMath, which is in the public domain, with thanks.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
//+ignore
|
||||||
package math_big
|
package math_big
|
||||||
|
|
||||||
import "core:time"
|
import "core:time"
|
||||||
|
|||||||
+16
-16
@@ -69,29 +69,29 @@ rotate_left :: proc(x: uint, k: int) -> uint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
from_be_u8 :: proc(i: u8) -> u8 { return i }
|
from_be_u8 :: proc(i: u8) -> u8 { return i }
|
||||||
from_be_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "big" { return i } else { return byte_swap(i) } }
|
from_be_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
|
||||||
from_be_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "big" { return i } else { return byte_swap(i) } }
|
from_be_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
|
||||||
from_be_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "big" { return i } else { return byte_swap(i) } }
|
from_be_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
|
||||||
from_be_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i } else { return byte_swap(i) } }
|
from_be_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
|
||||||
|
|
||||||
from_le_u8 :: proc(i: u8) -> u8 { return i }
|
from_le_u8 :: proc(i: u8) -> u8 { return i }
|
||||||
from_le_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "little" { return i } else { return byte_swap(i) } }
|
from_le_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
|
||||||
from_le_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "little" { return i } else { return byte_swap(i) } }
|
from_le_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
|
||||||
from_le_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "little" { return i } else { return byte_swap(i) } }
|
from_le_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
|
||||||
from_le_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i } else { return byte_swap(i) } }
|
from_le_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
|
||||||
|
|
||||||
to_be_u8 :: proc(i: u8) -> u8 { return i }
|
to_be_u8 :: proc(i: u8) -> u8 { return i }
|
||||||
to_be_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "big" { return i } else { return byte_swap(i) } }
|
to_be_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
|
||||||
to_be_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "big" { return i } else { return byte_swap(i) } }
|
to_be_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
|
||||||
to_be_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "big" { return i } else { return byte_swap(i) } }
|
to_be_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
|
||||||
to_be_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "big" { return i } else { return byte_swap(i) } }
|
to_be_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == .Big { return i } else { return byte_swap(i) } }
|
||||||
|
|
||||||
|
|
||||||
to_le_u8 :: proc(i: u8) -> u8 { return i }
|
to_le_u8 :: proc(i: u8) -> u8 { return i }
|
||||||
to_le_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == "little" { return i } else { return byte_swap(i) } }
|
to_le_u16 :: proc(i: u16) -> u16 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
|
||||||
to_le_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == "little" { return i } else { return byte_swap(i) } }
|
to_le_u32 :: proc(i: u32) -> u32 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
|
||||||
to_le_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == "little" { return i } else { return byte_swap(i) } }
|
to_le_u64 :: proc(i: u64) -> u64 { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
|
||||||
to_le_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == "little" { return i } else { return byte_swap(i) } }
|
to_le_uint :: proc(i: uint) -> uint { when ODIN_ENDIAN == .Little { return i } else { return byte_swap(i) } }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package linalg
|
package linalg
|
||||||
|
|
||||||
import "core:math"
|
import "core:math"
|
||||||
|
import "core:builtin"
|
||||||
import "core:intrinsics"
|
import "core:intrinsics"
|
||||||
|
|
||||||
// Generic
|
// Generic
|
||||||
@@ -60,14 +61,7 @@ quaternion256_dot :: proc(a, b: $T/quaternion256) -> (c: f64) {
|
|||||||
dot :: proc{scalar_dot, vector_dot, quaternion64_dot, quaternion128_dot, quaternion256_dot}
|
dot :: proc{scalar_dot, vector_dot, quaternion64_dot, quaternion128_dot, quaternion256_dot}
|
||||||
|
|
||||||
inner_product :: dot
|
inner_product :: dot
|
||||||
outer_product :: proc(a: $A/[$M]$E, b: $B/[$N]E) -> (out: [M][N]E) where IS_NUMERIC(E) #no_bounds_check {
|
outer_product :: builtin.outer_product
|
||||||
for i in 0..<M {
|
|
||||||
for j in 0..<N {
|
|
||||||
out[i][j] = a[i]*b[j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
quaternion_inverse :: proc(q: $Q) -> Q where IS_QUATERNION(Q) {
|
quaternion_inverse :: proc(q: $Q) -> Q where IS_QUATERNION(Q) {
|
||||||
return conj(q) * quaternion(1.0/dot(q, q), 0, 0, 0)
|
return conj(q) * quaternion(1.0/dot(q, q), 0, 0, 0)
|
||||||
@@ -163,65 +157,28 @@ identity :: proc($T: typeid/[$N][N]$E) -> (m: T) #no_bounds_check {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
trace :: proc(m: $T/[$N][N]$E) -> (tr: E) {
|
trace :: builtin.matrix_trace
|
||||||
for i in 0..<N {
|
transpose :: builtin.transpose
|
||||||
tr += m[i][i]
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
transpose :: proc(a: $T/[$N][$M]$E) -> (m: (T when N == M else [M][N]E)) #no_bounds_check {
|
matrix_mul :: proc(a, b: $M/matrix[$N, N]$E) -> (c: M)
|
||||||
for j in 0..<M {
|
|
||||||
for i in 0..<N {
|
|
||||||
m[j][i] = a[i][j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
matrix_mul :: proc(a, b: $M/[$N][N]$E) -> (c: M)
|
|
||||||
where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check {
|
where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check {
|
||||||
for i in 0..<N {
|
return a * b
|
||||||
for k in 0..<N {
|
|
||||||
for j in 0..<N {
|
|
||||||
c[k][i] += a[j][i] * b[k][j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
matrix_comp_mul :: proc(a, b: $M/[$J][$I]$E) -> (c: M)
|
matrix_comp_mul :: proc(a, b: $M/matrix[$I, $J]$E) -> (c: M)
|
||||||
where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check {
|
where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check {
|
||||||
for j in 0..<J {
|
return hadamard_product(a, b)
|
||||||
for i in 0..<I {
|
|
||||||
c[j][i] = a[j][i] * b[j][i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
matrix_mul_differ :: proc(a: $A/[$J][$I]$E, b: $B/[$K][J]E) -> (c: [K][I]E)
|
matrix_mul_differ :: proc(a: $A/matrix[$I, $J]$E, b: $B/matrix[J, $K]E) -> (c: matrix[I, K]E)
|
||||||
where !IS_ARRAY(E), IS_NUMERIC(E), I != K #no_bounds_check {
|
where !IS_ARRAY(E), IS_NUMERIC(E), I != K #no_bounds_check {
|
||||||
for k in 0..<K {
|
return a * b
|
||||||
for j in 0..<J {
|
|
||||||
for i in 0..<I {
|
|
||||||
c[k][i] += a[j][i] * b[k][j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
matrix_mul_vector :: proc(a: $A/[$I][$J]$E, b: $B/[I]E) -> (c: B)
|
matrix_mul_vector :: proc(a: $A/matrix[$I, $J]$E, b: $B/[J]E) -> (c: B)
|
||||||
where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check {
|
where !IS_ARRAY(E), IS_NUMERIC(E) #no_bounds_check {
|
||||||
for i in 0..<I {
|
return a * b
|
||||||
for j in 0..<J {
|
|
||||||
c[j] += a[i][j] * b[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
quaternion_mul_quaternion :: proc(q1, q2: $Q) -> Q where IS_QUATERNION(Q) {
|
quaternion_mul_quaternion :: proc(q1, q2: $Q) -> Q where IS_QUATERNION(Q) {
|
||||||
@@ -270,8 +227,8 @@ mul :: proc{
|
|||||||
vector_to_ptr :: proc(v: ^$V/[$N]$E) -> ^E where IS_NUMERIC(E), N > 0 #no_bounds_check {
|
vector_to_ptr :: proc(v: ^$V/[$N]$E) -> ^E where IS_NUMERIC(E), N > 0 #no_bounds_check {
|
||||||
return &v[0]
|
return &v[0]
|
||||||
}
|
}
|
||||||
matrix_to_ptr :: proc(m: ^$A/[$I][$J]$E) -> ^E where IS_NUMERIC(E), I > 0, J > 0 #no_bounds_check {
|
matrix_to_ptr :: proc(m: ^$A/matrix[$I, $J]$E) -> ^E where IS_NUMERIC(E), I > 0, J > 0 #no_bounds_check {
|
||||||
return &m[0][0]
|
return &m[0, 0]
|
||||||
}
|
}
|
||||||
|
|
||||||
to_ptr :: proc{vector_to_ptr, matrix_to_ptr}
|
to_ptr :: proc{vector_to_ptr, matrix_to_ptr}
|
||||||
@@ -330,10 +287,10 @@ array_cast :: proc(v: $A/[$N]$T, $Elem_Type: typeid) -> (w: [N]Elem_Type) #no_bo
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
matrix_cast :: proc(v: $A/[$M][$N]$T, $Elem_Type: typeid) -> (w: [M][N]Elem_Type) #no_bounds_check {
|
matrix_cast :: proc(v: $A/matrix[$M, $N]$T, $Elem_Type: typeid) -> (w: matrix[M, N]Elem_Type) #no_bounds_check {
|
||||||
for i in 0..<M {
|
for j in 0..<N {
|
||||||
for j in 0..<N {
|
for i in 0..<M {
|
||||||
w[i][j] = Elem_Type(v[i][j])
|
w[i, j] = Elem_Type(v[i, j])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -357,6 +314,6 @@ to_uint :: #force_inline proc(v: $A/[$N]$T) -> [N]uint { return array_cast(v, ui
|
|||||||
to_complex32 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex32 { return array_cast(v, complex32) }
|
to_complex32 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex32 { return array_cast(v, complex32) }
|
||||||
to_complex64 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex64 { return array_cast(v, complex64) }
|
to_complex64 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex64 { return array_cast(v, complex64) }
|
||||||
to_complex128 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex128 { return array_cast(v, complex128) }
|
to_complex128 :: #force_inline proc(v: $A/[$N]$T) -> [N]complex128 { return array_cast(v, complex128) }
|
||||||
to_quaternion64 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion64 { return array_cast(v, quaternion64) }
|
to_quaternion64 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion64 { return array_cast(v, quaternion64) }
|
||||||
to_quaternion128 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion128 { return array_cast(v, quaternion128) }
|
to_quaternion128 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion128 { return array_cast(v, quaternion128) }
|
||||||
to_quaternion256 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion256 { return array_cast(v, quaternion256) }
|
to_quaternion256 :: #force_inline proc(v: $A/[$N]$T) -> [N]quaternion256 { return array_cast(v, quaternion256) }
|
||||||
|
|||||||
@@ -473,6 +473,25 @@ floor_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {floor(x.x), floor(x.y), fl
|
|||||||
floor_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} }
|
floor_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
round :: proc{
|
||||||
|
round_f32,
|
||||||
|
round_f64,
|
||||||
|
round_vec2,
|
||||||
|
round_vec3,
|
||||||
|
round_vec4,
|
||||||
|
round_dvec2,
|
||||||
|
round_dvec3,
|
||||||
|
round_dvec4,
|
||||||
|
}
|
||||||
|
round_vec2 :: proc "c" (x: vec2) -> vec2 { return {round(x.x), round(x.y)} }
|
||||||
|
round_vec3 :: proc "c" (x: vec3) -> vec3 { return {round(x.x), round(x.y), round(x.z)} }
|
||||||
|
round_vec4 :: proc "c" (x: vec4) -> vec4 { return {round(x.x), round(x.y), round(x.z), round(x.w)} }
|
||||||
|
round_dvec2 :: proc "c" (x: dvec2) -> dvec2 { return {round(x.x), round(x.y)} }
|
||||||
|
round_dvec3 :: proc "c" (x: dvec3) -> dvec3 { return {round(x.x), round(x.y), round(x.z)} }
|
||||||
|
round_dvec4 :: proc "c" (x: dvec4) -> dvec4 { return {round(x.x), round(x.y), round(x.z), round(x.w)} }
|
||||||
|
|
||||||
|
|
||||||
ceil :: proc{
|
ceil :: proc{
|
||||||
ceil_f32,
|
ceil_f32,
|
||||||
ceil_f64,
|
ceil_f64,
|
||||||
@@ -693,23 +712,22 @@ saturate :: proc{
|
|||||||
saturate_uvec3,
|
saturate_uvec3,
|
||||||
saturate_uvec4,
|
saturate_uvec4,
|
||||||
}
|
}
|
||||||
saturate_i32 :: proc "c" (x, y, z: i32) -> i32 { return builtin.clamp(x, 0, 1) }
|
saturate_i32 :: proc "c" (v: i32) -> i32 { return builtin.clamp(v, 0, 1) }
|
||||||
saturate_u32 :: proc "c" (x, y, z: u32) -> u32 { return builtin.clamp(x, 0, 1) }
|
saturate_u32 :: proc "c" (v: u32) -> u32 { return builtin.clamp(v, 0, 1) }
|
||||||
saturate_f32 :: proc "c" (x, y, z: f32) -> f32 { return builtin.clamp(x, 0, 1) }
|
saturate_f32 :: proc "c" (v: f32) -> f32 { return builtin.clamp(v, 0, 1) }
|
||||||
saturate_f64 :: proc "c" (x, y, z: f64) -> f64 { return builtin.clamp(x, 0, 1) }
|
saturate_f64 :: proc "c" (v: f64) -> f64 { return builtin.clamp(v, 0, 1) }
|
||||||
saturate_vec2 :: proc "c" (x, y, z: vec2) -> vec2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} }
|
saturate_vec2 :: proc "c" (v: vec2) -> vec2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
|
||||||
saturate_vec3 :: proc "c" (x, y, z: vec3) -> vec3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} }
|
saturate_vec3 :: proc "c" (v: vec3) -> vec3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
|
||||||
saturate_vec4 :: proc "c" (x, y, z: vec4) -> vec4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} }
|
saturate_vec4 :: proc "c" (v: vec4) -> vec4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
|
||||||
saturate_dvec2 :: proc "c" (x, y, z: dvec2) -> dvec2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} }
|
saturate_dvec2 :: proc "c" (v: dvec2) -> dvec2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
|
||||||
saturate_dvec3 :: proc "c" (x, y, z: dvec3) -> dvec3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} }
|
saturate_dvec3 :: proc "c" (v: dvec3) -> dvec3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
|
||||||
saturate_dvec4 :: proc "c" (x, y, z: dvec4) -> dvec4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} }
|
saturate_dvec4 :: proc "c" (v: dvec4) -> dvec4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
|
||||||
saturate_ivec2 :: proc "c" (x, y, z: ivec2) -> ivec2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} }
|
saturate_ivec2 :: proc "c" (v: ivec2) -> ivec2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
|
||||||
saturate_ivec3 :: proc "c" (x, y, z: ivec3) -> ivec3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} }
|
saturate_ivec3 :: proc "c" (v: ivec3) -> ivec3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
|
||||||
saturate_ivec4 :: proc "c" (x, y, z: ivec4) -> ivec4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} }
|
saturate_ivec4 :: proc "c" (v: ivec4) -> ivec4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
|
||||||
saturate_uvec2 :: proc "c" (x, y, z: uvec2) -> uvec2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} }
|
saturate_uvec2 :: proc "c" (v: uvec2) -> uvec2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
|
||||||
saturate_uvec3 :: proc "c" (x, y, z: uvec3) -> uvec3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} }
|
saturate_uvec3 :: proc "c" (v: uvec3) -> uvec3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
|
||||||
saturate_uvec4 :: proc "c" (x, y, z: uvec4) -> uvec4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} }
|
saturate_uvec4 :: proc "c" (v: uvec4) -> uvec4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
|
||||||
|
|
||||||
|
|
||||||
mix :: proc{
|
mix :: proc{
|
||||||
mix_f32,
|
mix_f32,
|
||||||
@@ -1597,7 +1615,7 @@ quatNlerp :: proc "c" (a, b: quat, t: f32) -> (c: quat) {
|
|||||||
c.y = a.y + (b.y-a.y)*t
|
c.y = a.y + (b.y-a.y)*t
|
||||||
c.z = a.z + (b.z-a.z)*t
|
c.z = a.z + (b.z-a.z)*t
|
||||||
c.w = a.w + (b.w-a.w)*t
|
c.w = a.w + (b.w-a.w)*t
|
||||||
return c/builtin.abs(c)
|
return c/quat(builtin.abs(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
quatSlerp :: proc "c" (x, y: quat, t: f32) -> (q: quat) {
|
quatSlerp :: proc "c" (x, y: quat, t: f32) -> (q: quat) {
|
||||||
@@ -1699,7 +1717,7 @@ dquatNlerp :: proc "c" (a, b: dquat, t: f64) -> (c: dquat) {
|
|||||||
c.y = a.y + (b.y-a.y)*t
|
c.y = a.y + (b.y-a.y)*t
|
||||||
c.z = a.z + (b.z-a.z)*t
|
c.z = a.z + (b.z-a.z)*t
|
||||||
c.w = a.w + (b.w-a.w)*t
|
c.w = a.w + (b.w-a.w)*t
|
||||||
return c/builtin.abs(c)
|
return c/dquat(builtin.abs(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
dquatSlerp :: proc "c" (x, y: dquat, t: f64) -> (q: dquat) {
|
dquatSlerp :: proc "c" (x, y: dquat, t: f64) -> (q: dquat) {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ log_f32 :: proc "c" (x: f32) -> f32 { return math.ln(x) }
|
|||||||
exp2_f32 :: proc "c" (x: f32) -> f32 { return math.pow(f32(2), x) }
|
exp2_f32 :: proc "c" (x: f32) -> f32 { return math.pow(f32(2), x) }
|
||||||
sign_f32 :: proc "c" (x: f32) -> f32 { return math.sign(x) }
|
sign_f32 :: proc "c" (x: f32) -> f32 { return math.sign(x) }
|
||||||
floor_f32 :: proc "c" (x: f32) -> f32 { return math.floor(x) }
|
floor_f32 :: proc "c" (x: f32) -> f32 { return math.floor(x) }
|
||||||
|
round_f32 :: proc "c" (x: f32) -> f32 { return math.round(x) }
|
||||||
ceil_f32 :: proc "c" (x: f32) -> f32 { return math.ceil(x) }
|
ceil_f32 :: proc "c" (x: f32) -> f32 { return math.ceil(x) }
|
||||||
mod_f32 :: proc "c" (x, y: f32) -> f32 { return math.mod(x, y) }
|
mod_f32 :: proc "c" (x, y: f32) -> f32 { return math.mod(x, y) }
|
||||||
fract_f32 :: proc "c" (x: f32) -> f32 {
|
fract_f32 :: proc "c" (x: f32) -> f32 {
|
||||||
@@ -53,6 +54,7 @@ log_f64 :: proc "c" (x: f64) -> f64 { return math.ln(x) }
|
|||||||
exp2_f64 :: proc "c" (x: f64) -> f64 { return math.pow(f64(2), x) }
|
exp2_f64 :: proc "c" (x: f64) -> f64 { return math.pow(f64(2), x) }
|
||||||
sign_f64 :: proc "c" (x: f64) -> f64 { return math.sign(x) }
|
sign_f64 :: proc "c" (x: f64) -> f64 { return math.sign(x) }
|
||||||
floor_f64 :: proc "c" (x: f64) -> f64 { return math.floor(x) }
|
floor_f64 :: proc "c" (x: f64) -> f64 { return math.floor(x) }
|
||||||
|
round_f64 :: proc "c" (x: f64) -> f64 { return math.round(x) }
|
||||||
ceil_f64 :: proc "c" (x: f64) -> f64 { return math.ceil(x) }
|
ceil_f64 :: proc "c" (x: f64) -> f64 { return math.ceil(x) }
|
||||||
mod_f64 :: proc "c" (x, y: f64) -> f64 { return math.mod(x, y) }
|
mod_f64 :: proc "c" (x, y: f64) -> f64 { return math.mod(x, y) }
|
||||||
fract_f64 :: proc "c" (x: f64) -> f64 {
|
fract_f64 :: proc "c" (x: f64) -> f64 {
|
||||||
|
|||||||
@@ -551,6 +551,23 @@ floor_double2 :: proc "c" (x: double2) -> double2 { return {floor(x.x), floor(x.
|
|||||||
floor_double3 :: proc "c" (x: double3) -> double3 { return {floor(x.x), floor(x.y), floor(x.z)} }
|
floor_double3 :: proc "c" (x: double3) -> double3 { return {floor(x.x), floor(x.y), floor(x.z)} }
|
||||||
floor_double4 :: proc "c" (x: double4) -> double4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} }
|
floor_double4 :: proc "c" (x: double4) -> double4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} }
|
||||||
|
|
||||||
|
round :: proc{
|
||||||
|
round_float,
|
||||||
|
round_double,
|
||||||
|
round_float2,
|
||||||
|
round_float3,
|
||||||
|
round_float4,
|
||||||
|
round_double2,
|
||||||
|
round_double3,
|
||||||
|
round_double4,
|
||||||
|
}
|
||||||
|
round_float2 :: proc "c" (x: float2) -> float2 { return {round(x.x), round(x.y)} }
|
||||||
|
round_float3 :: proc "c" (x: float3) -> float3 { return {round(x.x), round(x.y), round(x.z)} }
|
||||||
|
round_float4 :: proc "c" (x: float4) -> float4 { return {round(x.x), round(x.y), round(x.z), round(x.w)} }
|
||||||
|
round_double2 :: proc "c" (x: double2) -> double2 { return {round(x.x), round(x.y)} }
|
||||||
|
round_double3 :: proc "c" (x: double3) -> double3 { return {round(x.x), round(x.y), round(x.z)} }
|
||||||
|
round_double4 :: proc "c" (x: double4) -> double4 { return {round(x.x), round(x.y), round(x.z), round(x.w)} }
|
||||||
|
|
||||||
|
|
||||||
ceil :: proc{
|
ceil :: proc{
|
||||||
ceil_float,
|
ceil_float,
|
||||||
@@ -570,6 +587,69 @@ ceil_double3 :: proc "c" (x: double3) -> double3 { return {ceil(x.x), ceil(x.y),
|
|||||||
ceil_double4 :: proc "c" (x: double4) -> double4 { return {ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w)} }
|
ceil_double4 :: proc "c" (x: double4) -> double4 { return {ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w)} }
|
||||||
|
|
||||||
|
|
||||||
|
isfinite_float :: proc "c" (x: float) -> bool { return !isinf_float(x) }
|
||||||
|
isfinite_float2 :: proc "c" (x: float2) -> bool2 { return {isfinite_float(x.x), isfinite_float(x.y)} }
|
||||||
|
isfinite_float3 :: proc "c" (x: float3) -> bool3 { return {isfinite_float(x.x), isfinite_float(x.y), isfinite_float(x.z)} }
|
||||||
|
isfinite_float4 :: proc "c" (x: float4) -> bool4 { return {isfinite_float(x.x), isfinite_float(x.y), isfinite_float(x.z), isfinite_float(x.w)} }
|
||||||
|
isfinite_double :: proc "c" (x: double) -> bool { return !isinf_double(x) }
|
||||||
|
isfinite_double2 :: proc "c" (x: double2) -> bool2 { return {isfinite_double(x.x), isfinite_double(x.y)} }
|
||||||
|
isfinite_double3 :: proc "c" (x: double3) -> bool3 { return {isfinite_double(x.x), isfinite_double(x.y), isfinite_double(x.z)} }
|
||||||
|
isfinite_double4 :: proc "c" (x: double4) -> bool4 { return {isfinite_double(x.x), isfinite_double(x.y), isfinite_double(x.z), isfinite_double(x.w)} }
|
||||||
|
|
||||||
|
// isfinite is the opposite of isinf and returns true if the number is neither positive-infinite or negative-infinite
|
||||||
|
isfinite :: proc{
|
||||||
|
isfinite_float,
|
||||||
|
isfinite_float2,
|
||||||
|
isfinite_float3,
|
||||||
|
isfinite_float4,
|
||||||
|
isfinite_double,
|
||||||
|
isfinite_double2,
|
||||||
|
isfinite_double3,
|
||||||
|
isfinite_double4,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
isinf_float :: proc "c" (x: float) -> bool { return x * 0.5 == x }
|
||||||
|
isinf_float2 :: proc "c" (x: float2) -> bool2 { return {isinf_float(x.x), isinf_float(x.y)} }
|
||||||
|
isinf_float3 :: proc "c" (x: float3) -> bool3 { return {isinf_float(x.x), isinf_float(x.y), isinf_float(x.z)} }
|
||||||
|
isinf_float4 :: proc "c" (x: float4) -> bool4 { return {isinf_float(x.x), isinf_float(x.y), isinf_float(x.z), isinf_float(x.w)} }
|
||||||
|
isinf_double :: proc "c" (x: double) -> bool { return x * 0.5 == x }
|
||||||
|
isinf_double2 :: proc "c" (x: double2) -> bool2 { return {isinf_double(x.x), isinf_double(x.y)} }
|
||||||
|
isinf_double3 :: proc "c" (x: double3) -> bool3 { return {isinf_double(x.x), isinf_double(x.y), isinf_double(x.z)} }
|
||||||
|
isinf_double4 :: proc "c" (x: double4) -> bool4 { return {isinf_double(x.x), isinf_double(x.y), isinf_double(x.z), isinf_double(x.w)} }
|
||||||
|
|
||||||
|
// isinf is the opposite of isfinite and returns true if the number is either positive-infinite or negative-infinite
|
||||||
|
isinf :: proc{
|
||||||
|
isinf_float,
|
||||||
|
isinf_float2,
|
||||||
|
isinf_float3,
|
||||||
|
isinf_float4,
|
||||||
|
isinf_double,
|
||||||
|
isinf_double2,
|
||||||
|
isinf_double3,
|
||||||
|
isinf_double4,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
isnan_float2 :: proc "c" (x: float2) -> bool2 { return {isnan_float(x.x), isnan_float(x.y)} }
|
||||||
|
isnan_float3 :: proc "c" (x: float3) -> bool3 { return {isnan_float(x.x), isnan_float(x.y), isnan_float(x.z)} }
|
||||||
|
isnan_float4 :: proc "c" (x: float4) -> bool4 { return {isnan_float(x.x), isnan_float(x.y), isnan_float(x.z), isnan_float(x.w)} }
|
||||||
|
isnan_double2 :: proc "c" (x: double2) -> bool2 { return {isnan_double(x.x), isnan_double(x.y)} }
|
||||||
|
isnan_double3 :: proc "c" (x: double3) -> bool3 { return {isnan_double(x.x), isnan_double(x.y), isnan_double(x.z)} }
|
||||||
|
isnan_double4 :: proc "c" (x: double4) -> bool4 { return {isnan_double(x.x), isnan_double(x.y), isnan_double(x.z), isnan_double(x.w)} }
|
||||||
|
|
||||||
|
// isnan returns true if the input value is the special case of Not-A-Number
|
||||||
|
isnan :: proc{
|
||||||
|
isnan_float,
|
||||||
|
isnan_float2,
|
||||||
|
isnan_float3,
|
||||||
|
isnan_float4,
|
||||||
|
isnan_double,
|
||||||
|
isnan_double2,
|
||||||
|
isnan_double3,
|
||||||
|
isnan_double4,
|
||||||
|
}
|
||||||
|
|
||||||
fmod :: proc{
|
fmod :: proc{
|
||||||
fmod_float,
|
fmod_float,
|
||||||
fmod_double,
|
fmod_double,
|
||||||
@@ -772,22 +852,22 @@ saturate :: proc{
|
|||||||
saturate_uint3,
|
saturate_uint3,
|
||||||
saturate_uint4,
|
saturate_uint4,
|
||||||
}
|
}
|
||||||
saturate_int :: proc "c" (x, y, z: int) -> int { return builtin.clamp(x, 0, 1) }
|
saturate_int :: proc "c" (v: int) -> int { return builtin.clamp(v, 0, 1) }
|
||||||
saturate_uint :: proc "c" (x, y, z: uint) -> uint { return builtin.clamp(x, 0, 1) }
|
saturate_uint :: proc "c" (v: uint) -> uint { return builtin.clamp(v, 0, 1) }
|
||||||
saturate_float :: proc "c" (x, y, z: float) -> float { return builtin.clamp(x, 0, 1) }
|
saturate_float :: proc "c" (v: float) -> float { return builtin.clamp(v, 0, 1) }
|
||||||
saturate_double :: proc "c" (x, y, z: double) -> double { return builtin.clamp(x, 0, 1) }
|
saturate_double :: proc "c" (v: double) -> double { return builtin.clamp(v, 0, 1) }
|
||||||
saturate_float2 :: proc "c" (x, y, z: float2) -> float2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} }
|
saturate_float2 :: proc "c" (v: float2) -> float2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
|
||||||
saturate_float3 :: proc "c" (x, y, z: float3) -> float3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} }
|
saturate_float3 :: proc "c" (v: float3) -> float3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
|
||||||
saturate_float4 :: proc "c" (x, y, z: float4) -> float4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} }
|
saturate_float4 :: proc "c" (v: float4) -> float4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
|
||||||
saturate_double2 :: proc "c" (x, y, z: double2) -> double2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} }
|
saturate_double2 :: proc "c" (v: double2) -> double2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
|
||||||
saturate_double3 :: proc "c" (x, y, z: double3) -> double3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} }
|
saturate_double3 :: proc "c" (v: double3) -> double3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
|
||||||
saturate_double4 :: proc "c" (x, y, z: double4) -> double4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} }
|
saturate_double4 :: proc "c" (v: double4) -> double4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
|
||||||
saturate_int2 :: proc "c" (x, y, z: int2) -> int2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} }
|
saturate_int2 :: proc "c" (v: int2) -> int2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
|
||||||
saturate_int3 :: proc "c" (x, y, z: int3) -> int3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} }
|
saturate_int3 :: proc "c" (v: int3) -> int3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
|
||||||
saturate_int4 :: proc "c" (x, y, z: int4) -> int4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} }
|
saturate_int4 :: proc "c" (v: int4) -> int4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
|
||||||
saturate_uint2 :: proc "c" (x, y, z: uint2) -> uint2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1)} }
|
saturate_uint2 :: proc "c" (v: uint2) -> uint2 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1)} }
|
||||||
saturate_uint3 :: proc "c" (x, y, z: uint3) -> uint3 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1)} }
|
saturate_uint3 :: proc "c" (v: uint3) -> uint3 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1)} }
|
||||||
saturate_uint4 :: proc "c" (x, y, z: uint4) -> uint4 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.y, 0, 1), builtin.clamp(x.z, 0, 1), builtin.clamp(x.w, 0, 1)} }
|
saturate_uint4 :: proc "c" (v: uint4) -> uint4 { return {builtin.clamp(v.x, 0, 1), builtin.clamp(v.y, 0, 1), builtin.clamp(v.z, 0, 1), builtin.clamp(v.w, 0, 1)} }
|
||||||
|
|
||||||
|
|
||||||
lerp :: proc{
|
lerp :: proc{
|
||||||
|
|||||||
@@ -26,7 +26,9 @@ log10_float :: proc "c" (x: float) -> float { return math.log(x, 10) }
|
|||||||
exp2_float :: proc "c" (x: float) -> float { return math.pow(float(2), x) }
|
exp2_float :: proc "c" (x: float) -> float { return math.pow(float(2), x) }
|
||||||
sign_float :: proc "c" (x: float) -> float { return math.sign(x) }
|
sign_float :: proc "c" (x: float) -> float { return math.sign(x) }
|
||||||
floor_float :: proc "c" (x: float) -> float { return math.floor(x) }
|
floor_float :: proc "c" (x: float) -> float { return math.floor(x) }
|
||||||
|
round_float :: proc "c" (x: float) -> float { return math.round(x) }
|
||||||
ceil_float :: proc "c" (x: float) -> float { return math.ceil(x) }
|
ceil_float :: proc "c" (x: float) -> float { return math.ceil(x) }
|
||||||
|
isnan_float :: proc "c" (x: float) -> bool { return math.classify(x) == .NaN}
|
||||||
fmod_float :: proc "c" (x, y: float) -> float { return math.mod(x, y) }
|
fmod_float :: proc "c" (x, y: float) -> float { return math.mod(x, y) }
|
||||||
frac_float :: proc "c" (x: float) -> float {
|
frac_float :: proc "c" (x: float) -> float {
|
||||||
if x >= 0 {
|
if x >= 0 {
|
||||||
@@ -35,6 +37,7 @@ frac_float :: proc "c" (x: float) -> float {
|
|||||||
return math.trunc(-x) + x
|
return math.trunc(-x) + x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
cos_double :: proc "c" (x: double) -> double { return math.cos(x) }
|
cos_double :: proc "c" (x: double) -> double { return math.cos(x) }
|
||||||
sin_double :: proc "c" (x: double) -> double { return math.sin(x) }
|
sin_double :: proc "c" (x: double) -> double { return math.sin(x) }
|
||||||
tan_double :: proc "c" (x: double) -> double { return math.tan(x) }
|
tan_double :: proc "c" (x: double) -> double { return math.tan(x) }
|
||||||
@@ -59,7 +62,9 @@ log10_double :: proc "c" (x: double) -> double { return math.log(x, 10)
|
|||||||
exp2_double :: proc "c" (x: double) -> double { return math.pow(double(2), x) }
|
exp2_double :: proc "c" (x: double) -> double { return math.pow(double(2), x) }
|
||||||
sign_double :: proc "c" (x: double) -> double { return math.sign(x) }
|
sign_double :: proc "c" (x: double) -> double { return math.sign(x) }
|
||||||
floor_double :: proc "c" (x: double) -> double { return math.floor(x) }
|
floor_double :: proc "c" (x: double) -> double { return math.floor(x) }
|
||||||
|
round_double :: proc "c" (x: double) -> double { return math.round(x) }
|
||||||
ceil_double :: proc "c" (x: double) -> double { return math.ceil(x) }
|
ceil_double :: proc "c" (x: double) -> double { return math.ceil(x) }
|
||||||
|
isnan_double :: proc "c" (x: double) -> bool { return math.classify(x) == .NaN}
|
||||||
fmod_double :: proc "c" (x, y: double) -> double { return math.mod(x, y) }
|
fmod_double :: proc "c" (x, y: double) -> double { return math.mod(x, y) }
|
||||||
frac_double :: proc "c" (x: double) -> double {
|
frac_double :: proc "c" (x: double) -> double {
|
||||||
if x >= 0 {
|
if x >= 0 {
|
||||||
|
|||||||
+520
-543
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,10 @@
|
|||||||
package linalg
|
package linalg
|
||||||
|
|
||||||
|
/*
|
||||||
|
These procedures are to allow for swizzling with non-compile (runtime) known components
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
Scalar_Components :: enum u8 {
|
Scalar_Components :: enum u8 {
|
||||||
x = 0,
|
x = 0,
|
||||||
r = 0,
|
r = 0,
|
||||||
|
|||||||
@@ -0,0 +1,214 @@
|
|||||||
|
package rand
|
||||||
|
|
||||||
|
import "core:math"
|
||||||
|
|
||||||
|
// exp_float64 returns a exponential distribution in the range (0, max(f64)],
|
||||||
|
// with an exponential distribution who rate parameter is 1 (lambda) and whose mean
|
||||||
|
// is 1 (1/lambda).
|
||||||
|
//
|
||||||
|
// To produce a distribution with a differetn rate parameter, divide the result by
|
||||||
|
// the desired rate parameter
|
||||||
|
//
|
||||||
|
// "The Ziggurat Method for Generating Random Variables"
|
||||||
|
// Authors: George Marsaglia, Wai Wan Tsang
|
||||||
|
// Submitted: 2000-04-15. Published: 2000-10-02.
|
||||||
|
// https://www.jstatsoft.org/index.php/jss/article/view/v005i08/ziggurat.pdf [pdf]
|
||||||
|
// https://www.jstatsoft.org/article/view/v005i08 [web page]
|
||||||
|
//
|
||||||
|
exp_float64 :: proc(r: ^Rand = nil) -> f64 {
|
||||||
|
re :: 7.69711747013104972
|
||||||
|
|
||||||
|
@(static)
|
||||||
|
ke := [256]u32{
|
||||||
|
0xe290a139, 0x0, 0x9beadebc, 0xc377ac71, 0xd4ddb990,
|
||||||
|
0xde893fb8, 0xe4a8e87c, 0xe8dff16a, 0xebf2deab, 0xee49a6e8,
|
||||||
|
0xf0204efd, 0xf19bdb8e, 0xf2d458bb, 0xf3da104b, 0xf4b86d78,
|
||||||
|
0xf577ad8a, 0xf61de83d, 0xf6afb784, 0xf730a573, 0xf7a37651,
|
||||||
|
0xf80a5bb6, 0xf867189d, 0xf8bb1b4f, 0xf9079062, 0xf94d70ca,
|
||||||
|
0xf98d8c7d, 0xf9c8928a, 0xf9ff175b, 0xfa319996, 0xfa6085f8,
|
||||||
|
0xfa8c3a62, 0xfab5084e, 0xfadb36c8, 0xfaff0410, 0xfb20a6ea,
|
||||||
|
0xfb404fb4, 0xfb5e2951, 0xfb7a59e9, 0xfb95038c, 0xfbae44ba,
|
||||||
|
0xfbc638d8, 0xfbdcf892, 0xfbf29a30, 0xfc0731df, 0xfc1ad1ed,
|
||||||
|
0xfc2d8b02, 0xfc3f6c4d, 0xfc5083ac, 0xfc60ddd1, 0xfc708662,
|
||||||
|
0xfc7f8810, 0xfc8decb4, 0xfc9bbd62, 0xfca9027c, 0xfcb5c3c3,
|
||||||
|
0xfcc20864, 0xfccdd70a, 0xfcd935e3, 0xfce42ab0, 0xfceebace,
|
||||||
|
0xfcf8eb3b, 0xfd02c0a0, 0xfd0c3f59, 0xfd156b7b, 0xfd1e48d6,
|
||||||
|
0xfd26daff, 0xfd2f2552, 0xfd372af7, 0xfd3eeee5, 0xfd4673e7,
|
||||||
|
0xfd4dbc9e, 0xfd54cb85, 0xfd5ba2f2, 0xfd62451b, 0xfd68b415,
|
||||||
|
0xfd6ef1da, 0xfd750047, 0xfd7ae120, 0xfd809612, 0xfd8620b4,
|
||||||
|
0xfd8b8285, 0xfd90bcf5, 0xfd95d15e, 0xfd9ac10b, 0xfd9f8d36,
|
||||||
|
0xfda43708, 0xfda8bf9e, 0xfdad2806, 0xfdb17141, 0xfdb59c46,
|
||||||
|
0xfdb9a9fd, 0xfdbd9b46, 0xfdc170f6, 0xfdc52bd8, 0xfdc8ccac,
|
||||||
|
0xfdcc542d, 0xfdcfc30b, 0xfdd319ef, 0xfdd6597a, 0xfdd98245,
|
||||||
|
0xfddc94e5, 0xfddf91e6, 0xfde279ce, 0xfde54d1f, 0xfde80c52,
|
||||||
|
0xfdeab7de, 0xfded5034, 0xfdefd5be, 0xfdf248e3, 0xfdf4aa06,
|
||||||
|
0xfdf6f984, 0xfdf937b6, 0xfdfb64f4, 0xfdfd818d, 0xfdff8dd0,
|
||||||
|
0xfe018a08, 0xfe03767a, 0xfe05536c, 0xfe07211c, 0xfe08dfc9,
|
||||||
|
0xfe0a8fab, 0xfe0c30fb, 0xfe0dc3ec, 0xfe0f48b1, 0xfe10bf76,
|
||||||
|
0xfe122869, 0xfe1383b4, 0xfe14d17c, 0xfe1611e7, 0xfe174516,
|
||||||
|
0xfe186b2a, 0xfe19843e, 0xfe1a9070, 0xfe1b8fd6, 0xfe1c8289,
|
||||||
|
0xfe1d689b, 0xfe1e4220, 0xfe1f0f26, 0xfe1fcfbc, 0xfe2083ed,
|
||||||
|
0xfe212bc3, 0xfe21c745, 0xfe225678, 0xfe22d95f, 0xfe234ffb,
|
||||||
|
0xfe23ba4a, 0xfe241849, 0xfe2469f2, 0xfe24af3c, 0xfe24e81e,
|
||||||
|
0xfe25148b, 0xfe253474, 0xfe2547c7, 0xfe254e70, 0xfe25485a,
|
||||||
|
0xfe25356a, 0xfe251586, 0xfe24e88f, 0xfe24ae64, 0xfe2466e1,
|
||||||
|
0xfe2411df, 0xfe23af34, 0xfe233eb4, 0xfe22c02c, 0xfe22336b,
|
||||||
|
0xfe219838, 0xfe20ee58, 0xfe20358c, 0xfe1f6d92, 0xfe1e9621,
|
||||||
|
0xfe1daef0, 0xfe1cb7ac, 0xfe1bb002, 0xfe1a9798, 0xfe196e0d,
|
||||||
|
0xfe1832fd, 0xfe16e5fe, 0xfe15869d, 0xfe141464, 0xfe128ed3,
|
||||||
|
0xfe10f565, 0xfe0f478c, 0xfe0d84b1, 0xfe0bac36, 0xfe09bd73,
|
||||||
|
0xfe07b7b5, 0xfe059a40, 0xfe03644c, 0xfe011504, 0xfdfeab88,
|
||||||
|
0xfdfc26e9, 0xfdf98629, 0xfdf6c83b, 0xfdf3ec01, 0xfdf0f04a,
|
||||||
|
0xfdedd3d1, 0xfdea953d, 0xfde7331e, 0xfde3abe9, 0xfddffdfb,
|
||||||
|
0xfddc2791, 0xfdd826cd, 0xfdd3f9a8, 0xfdcf9dfc, 0xfdcb1176,
|
||||||
|
0xfdc65198, 0xfdc15bb3, 0xfdbc2ce2, 0xfdb6c206, 0xfdb117be,
|
||||||
|
0xfdab2a63, 0xfda4f5fd, 0xfd9e7640, 0xfd97a67a, 0xfd908192,
|
||||||
|
0xfd8901f2, 0xfd812182, 0xfd78d98e, 0xfd7022bb, 0xfd66f4ed,
|
||||||
|
0xfd5d4732, 0xfd530f9c, 0xfd48432b, 0xfd3cd59a, 0xfd30b936,
|
||||||
|
0xfd23dea4, 0xfd16349e, 0xfd07a7a3, 0xfcf8219b, 0xfce7895b,
|
||||||
|
0xfcd5c220, 0xfcc2aadb, 0xfcae1d5e, 0xfc97ed4e, 0xfc7fe6d4,
|
||||||
|
0xfc65ccf3, 0xfc495762, 0xfc2a2fc8, 0xfc07ee19, 0xfbe213c1,
|
||||||
|
0xfbb8051a, 0xfb890078, 0xfb5411a5, 0xfb180005, 0xfad33482,
|
||||||
|
0xfa839276, 0xfa263b32, 0xf9b72d1c, 0xf930a1a2, 0xf889f023,
|
||||||
|
0xf7b577d2, 0xf69c650c, 0xf51530f0, 0xf2cb0e3c, 0xeeefb15d,
|
||||||
|
0xe6da6ecf,
|
||||||
|
}
|
||||||
|
@(static)
|
||||||
|
we := [256]f32{
|
||||||
|
2.0249555e-09, 1.486674e-11, 2.4409617e-11, 3.1968806e-11,
|
||||||
|
3.844677e-11, 4.4228204e-11, 4.9516443e-11, 5.443359e-11,
|
||||||
|
5.905944e-11, 6.344942e-11, 6.7643814e-11, 7.1672945e-11,
|
||||||
|
7.556032e-11, 7.932458e-11, 8.298079e-11, 8.654132e-11,
|
||||||
|
9.0016515e-11, 9.3415074e-11, 9.674443e-11, 1.0001099e-10,
|
||||||
|
1.03220314e-10, 1.06377254e-10, 1.09486115e-10, 1.1255068e-10,
|
||||||
|
1.1557435e-10, 1.1856015e-10, 1.2151083e-10, 1.2442886e-10,
|
||||||
|
1.2731648e-10, 1.3017575e-10, 1.3300853e-10, 1.3581657e-10,
|
||||||
|
1.3860142e-10, 1.4136457e-10, 1.4410738e-10, 1.4683108e-10,
|
||||||
|
1.4953687e-10, 1.5222583e-10, 1.54899e-10, 1.5755733e-10,
|
||||||
|
1.6020171e-10, 1.6283301e-10, 1.6545203e-10, 1.6805951e-10,
|
||||||
|
1.7065617e-10, 1.732427e-10, 1.7581973e-10, 1.7838787e-10,
|
||||||
|
1.8094774e-10, 1.8349985e-10, 1.8604476e-10, 1.8858298e-10,
|
||||||
|
1.9111498e-10, 1.9364126e-10, 1.9616223e-10, 1.9867835e-10,
|
||||||
|
2.0119004e-10, 2.0369768e-10, 2.0620168e-10, 2.087024e-10,
|
||||||
|
2.1120022e-10, 2.136955e-10, 2.1618855e-10, 2.1867974e-10,
|
||||||
|
2.2116936e-10, 2.2365775e-10, 2.261452e-10, 2.2863202e-10,
|
||||||
|
2.311185e-10, 2.3360494e-10, 2.360916e-10, 2.3857874e-10,
|
||||||
|
2.4106667e-10, 2.4355562e-10, 2.4604588e-10, 2.485377e-10,
|
||||||
|
2.5103128e-10, 2.5352695e-10, 2.560249e-10, 2.585254e-10,
|
||||||
|
2.6102867e-10, 2.6353494e-10, 2.6604446e-10, 2.6855745e-10,
|
||||||
|
2.7107416e-10, 2.7359479e-10, 2.761196e-10, 2.7864877e-10,
|
||||||
|
2.8118255e-10, 2.8372119e-10, 2.8626485e-10, 2.888138e-10,
|
||||||
|
2.9136826e-10, 2.939284e-10, 2.9649452e-10, 2.9906677e-10,
|
||||||
|
3.016454e-10, 3.0423064e-10, 3.0682268e-10, 3.0942177e-10,
|
||||||
|
3.1202813e-10, 3.1464195e-10, 3.1726352e-10, 3.19893e-10,
|
||||||
|
3.2253064e-10, 3.251767e-10, 3.2783135e-10, 3.3049485e-10,
|
||||||
|
3.3316744e-10, 3.3584938e-10, 3.3854083e-10, 3.4124212e-10,
|
||||||
|
3.4395342e-10, 3.46675e-10, 3.4940711e-10, 3.5215003e-10,
|
||||||
|
3.5490397e-10, 3.5766917e-10, 3.6044595e-10, 3.6323455e-10,
|
||||||
|
3.660352e-10, 3.6884823e-10, 3.7167386e-10, 3.745124e-10,
|
||||||
|
3.773641e-10, 3.802293e-10, 3.8310827e-10, 3.860013e-10,
|
||||||
|
3.8890866e-10, 3.918307e-10, 3.9476775e-10, 3.9772008e-10,
|
||||||
|
4.0068804e-10, 4.0367196e-10, 4.0667217e-10, 4.09689e-10,
|
||||||
|
4.1272286e-10, 4.1577405e-10, 4.1884296e-10, 4.2192994e-10,
|
||||||
|
4.250354e-10, 4.281597e-10, 4.313033e-10, 4.3446652e-10,
|
||||||
|
4.3764986e-10, 4.408537e-10, 4.4407847e-10, 4.4732465e-10,
|
||||||
|
4.5059267e-10, 4.5388301e-10, 4.571962e-10, 4.6053267e-10,
|
||||||
|
4.6389292e-10, 4.6727755e-10, 4.70687e-10, 4.741219e-10,
|
||||||
|
4.7758275e-10, 4.810702e-10, 4.845848e-10, 4.8812715e-10,
|
||||||
|
4.9169796e-10, 4.9529775e-10, 4.989273e-10, 5.0258725e-10,
|
||||||
|
5.0627835e-10, 5.100013e-10, 5.1375687e-10, 5.1754584e-10,
|
||||||
|
5.21369e-10, 5.2522725e-10, 5.2912136e-10, 5.330522e-10,
|
||||||
|
5.370208e-10, 5.4102806e-10, 5.45075e-10, 5.491625e-10,
|
||||||
|
5.532918e-10, 5.5746385e-10, 5.616799e-10, 5.6594107e-10,
|
||||||
|
5.7024857e-10, 5.746037e-10, 5.7900773e-10, 5.834621e-10,
|
||||||
|
5.8796823e-10, 5.925276e-10, 5.971417e-10, 6.018122e-10,
|
||||||
|
6.065408e-10, 6.113292e-10, 6.1617933e-10, 6.2109295e-10,
|
||||||
|
6.260722e-10, 6.3111916e-10, 6.3623595e-10, 6.4142497e-10,
|
||||||
|
6.4668854e-10, 6.5202926e-10, 6.5744976e-10, 6.6295286e-10,
|
||||||
|
6.6854156e-10, 6.742188e-10, 6.79988e-10, 6.858526e-10,
|
||||||
|
6.9181616e-10, 6.978826e-10, 7.04056e-10, 7.103407e-10,
|
||||||
|
7.167412e-10, 7.2326256e-10, 7.2990985e-10, 7.366886e-10,
|
||||||
|
7.4360473e-10, 7.5066453e-10, 7.5787476e-10, 7.6524265e-10,
|
||||||
|
7.7277595e-10, 7.80483e-10, 7.883728e-10, 7.9645507e-10,
|
||||||
|
8.047402e-10, 8.1323964e-10, 8.219657e-10, 8.309319e-10,
|
||||||
|
8.401528e-10, 8.496445e-10, 8.594247e-10, 8.6951274e-10,
|
||||||
|
8.799301e-10, 8.9070046e-10, 9.018503e-10, 9.134092e-10,
|
||||||
|
9.254101e-10, 9.378904e-10, 9.508923e-10, 9.644638e-10,
|
||||||
|
9.786603e-10, 9.935448e-10, 1.0091913e-09, 1.025686e-09,
|
||||||
|
1.0431306e-09, 1.0616465e-09, 1.08138e-09, 1.1025096e-09,
|
||||||
|
1.1252564e-09, 1.1498986e-09, 1.1767932e-09, 1.206409e-09,
|
||||||
|
1.2393786e-09, 1.276585e-09, 1.3193139e-09, 1.3695435e-09,
|
||||||
|
1.4305498e-09, 1.508365e-09, 1.6160854e-09, 1.7921248e-09,
|
||||||
|
}
|
||||||
|
@(static)
|
||||||
|
fe := [256]f32{
|
||||||
|
1, 0.9381437, 0.90046996, 0.87170434, 0.8477855, 0.8269933,
|
||||||
|
0.8084217, 0.7915276, 0.77595687, 0.7614634, 0.7478686,
|
||||||
|
0.7350381, 0.72286767, 0.71127474, 0.70019263, 0.6895665,
|
||||||
|
0.67935055, 0.6695063, 0.66000086, 0.65080583, 0.6418967,
|
||||||
|
0.63325197, 0.6248527, 0.6166822, 0.60872537, 0.60096896,
|
||||||
|
0.5934009, 0.58601034, 0.5787874, 0.57172304, 0.5648092,
|
||||||
|
0.5580383, 0.5514034, 0.5448982, 0.5385169, 0.53225386,
|
||||||
|
0.5261042, 0.52006316, 0.5141264, 0.50828975, 0.5025495,
|
||||||
|
0.496902, 0.49134386, 0.485872, 0.48048335, 0.4751752,
|
||||||
|
0.46994483, 0.46478975, 0.45970762, 0.45469615, 0.44975325,
|
||||||
|
0.44487688, 0.44006512, 0.43531612, 0.43062815, 0.42599955,
|
||||||
|
0.42142874, 0.4169142, 0.41245446, 0.40804818, 0.403694,
|
||||||
|
0.3993907, 0.39513698, 0.39093173, 0.38677382, 0.38266218,
|
||||||
|
0.37859577, 0.37457356, 0.37059465, 0.3666581, 0.362763,
|
||||||
|
0.35890847, 0.35509375, 0.351318, 0.3475805, 0.34388044,
|
||||||
|
0.34021714, 0.3365899, 0.33299807, 0.32944095, 0.32591796,
|
||||||
|
0.3224285, 0.3189719, 0.31554767, 0.31215525, 0.30879408,
|
||||||
|
0.3054636, 0.3021634, 0.29889292, 0.2956517, 0.29243928,
|
||||||
|
0.28925523, 0.28609908, 0.28297043, 0.27986884, 0.27679393,
|
||||||
|
0.2737453, 0.2707226, 0.2677254, 0.26475343, 0.26180625,
|
||||||
|
0.25888354, 0.25598502, 0.2531103, 0.25025907, 0.24743107,
|
||||||
|
0.24462597, 0.24184346, 0.23908329, 0.23634516, 0.23362878,
|
||||||
|
0.23093392, 0.2282603, 0.22560766, 0.22297576, 0.22036438,
|
||||||
|
0.21777324, 0.21520215, 0.21265087, 0.21011916, 0.20760682,
|
||||||
|
0.20511365, 0.20263945, 0.20018397, 0.19774707, 0.19532852,
|
||||||
|
0.19292815, 0.19054577, 0.1881812, 0.18583426, 0.18350479,
|
||||||
|
0.1811926, 0.17889754, 0.17661946, 0.17435817, 0.17211354,
|
||||||
|
0.1698854, 0.16767362, 0.16547804, 0.16329853, 0.16113494,
|
||||||
|
0.15898713, 0.15685499, 0.15473837, 0.15263714, 0.15055119,
|
||||||
|
0.14848037, 0.14642459, 0.14438373, 0.14235765, 0.14034624,
|
||||||
|
0.13834943, 0.13636707, 0.13439907, 0.13244532, 0.13050574,
|
||||||
|
0.1285802, 0.12666863, 0.12477092, 0.12288698, 0.12101672,
|
||||||
|
0.119160056, 0.1173169, 0.115487166, 0.11367077, 0.11186763,
|
||||||
|
0.11007768, 0.10830083, 0.10653701, 0.10478614, 0.10304816,
|
||||||
|
0.101323, 0.09961058, 0.09791085, 0.09622374, 0.09454919,
|
||||||
|
0.09288713, 0.091237515, 0.08960028, 0.087975375, 0.08636274,
|
||||||
|
0.08476233, 0.083174095, 0.081597984, 0.08003395, 0.07848195,
|
||||||
|
0.076941945, 0.07541389, 0.07389775, 0.072393484, 0.07090106,
|
||||||
|
0.069420435, 0.06795159, 0.066494495, 0.06504912, 0.063615434,
|
||||||
|
0.062193416, 0.060783047, 0.059384305, 0.057997175,
|
||||||
|
0.05662164, 0.05525769, 0.053905312, 0.052564494, 0.051235236,
|
||||||
|
0.049917534, 0.048611384, 0.047316793, 0.046033762, 0.0447623,
|
||||||
|
0.043502413, 0.042254124, 0.041017443, 0.039792392,
|
||||||
|
0.038578995, 0.037377283, 0.036187284, 0.035009038,
|
||||||
|
0.033842582, 0.032687962, 0.031545233, 0.030414443, 0.02929566,
|
||||||
|
0.02818895, 0.027094385, 0.026012046, 0.024942026, 0.023884421,
|
||||||
|
0.022839336, 0.021806888, 0.020787204, 0.019780423, 0.0187867,
|
||||||
|
0.0178062, 0.016839107, 0.015885621, 0.014945968, 0.014020392,
|
||||||
|
0.013109165, 0.012212592, 0.011331013, 0.01046481, 0.009614414,
|
||||||
|
0.008780315, 0.007963077, 0.0071633533, 0.006381906,
|
||||||
|
0.0056196423, 0.0048776558, 0.004157295, 0.0034602648,
|
||||||
|
0.0027887989, 0.0021459677, 0.0015362998, 0.0009672693,
|
||||||
|
0.00045413437,
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
j := uint32(r)
|
||||||
|
i := j & 0xFF
|
||||||
|
x := f64(j) * f64(we[i])
|
||||||
|
if j < ke[i] {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
return re - math.ln(float64(r))
|
||||||
|
}
|
||||||
|
if fe[i]+f32(float64(r))*(fe[i-1]-fe[i]) < f32(math.exp(-x)) {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,12 @@ package rand
|
|||||||
|
|
||||||
import "core:math"
|
import "core:math"
|
||||||
|
|
||||||
|
|
||||||
|
// norm_float64 returns a normally distributed f64 in the range -max(f64) through +max(f64) inclusive,
|
||||||
|
// with a standard normal distribution with a mean of 0 and standard deviation of 1.
|
||||||
|
//
|
||||||
|
// sample = norm_float64() * std_dev + mean
|
||||||
|
//
|
||||||
//
|
//
|
||||||
// Normal distribution
|
// Normal distribution
|
||||||
//
|
//
|
||||||
@@ -11,12 +17,6 @@ import "core:math"
|
|||||||
// https://www.jstatsoft.org/index.php/jss/article/view/v005i08/ziggurat.pdf [pdf]
|
// https://www.jstatsoft.org/index.php/jss/article/view/v005i08/ziggurat.pdf [pdf]
|
||||||
// https://www.jstatsoft.org/article/view/v005i08 [web page]
|
// https://www.jstatsoft.org/article/view/v005i08 [web page]
|
||||||
//
|
//
|
||||||
|
|
||||||
// norm_float64 returns a normally distributed f64 in the range -max(f64) through +max(f64) inclusive,
|
|
||||||
// with a standard normal distribution with a mean of 0 and standard deviation of 1.
|
|
||||||
//
|
|
||||||
// sample = norm_float64() * std_dev + mean
|
|
||||||
//
|
|
||||||
norm_float64 :: proc(r: ^Rand = nil) -> f64 {
|
norm_float64 :: proc(r: ^Rand = nil) -> f64 {
|
||||||
rn :: 3.442619855899
|
rn :: 3.442619855899
|
||||||
|
|
||||||
@@ -49,7 +49,6 @@ norm_float64 :: proc(r: ^Rand = nil) -> f64 {
|
|||||||
0x7da61a1e, 0x7d72a0fb, 0x7d30e097, 0x7cd9b4ab, 0x7c600f1a,
|
0x7da61a1e, 0x7d72a0fb, 0x7d30e097, 0x7cd9b4ab, 0x7c600f1a,
|
||||||
0x7ba90bdc, 0x7a722176, 0x77d664e5,
|
0x7ba90bdc, 0x7a722176, 0x77d664e5,
|
||||||
}
|
}
|
||||||
|
|
||||||
@(static)
|
@(static)
|
||||||
wn := [128]f32{
|
wn := [128]f32{
|
||||||
1.7290405e-09, 1.2680929e-10, 1.6897518e-10, 1.9862688e-10,
|
1.7290405e-09, 1.2680929e-10, 1.6897518e-10, 1.9862688e-10,
|
||||||
@@ -85,7 +84,6 @@ norm_float64 :: proc(r: ^Rand = nil) -> f64 {
|
|||||||
1.2601323e-09, 1.2857697e-09, 1.3146202e-09, 1.347784e-09,
|
1.2601323e-09, 1.2857697e-09, 1.3146202e-09, 1.347784e-09,
|
||||||
1.3870636e-09, 1.4357403e-09, 1.5008659e-09, 1.6030948e-09,
|
1.3870636e-09, 1.4357403e-09, 1.5008659e-09, 1.6030948e-09,
|
||||||
}
|
}
|
||||||
|
|
||||||
@(static)
|
@(static)
|
||||||
fn := [128]f32{
|
fn := [128]f32{
|
||||||
1.00000000, 0.9635997, 0.9362827, 0.9130436, 0.89228165,
|
1.00000000, 0.9635997, 0.9362827, 0.9130436, 0.89228165,
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ int31_max :: proc(n: i32, r: ^Rand = nil) -> i32 {
|
|||||||
if n&(n-1) == 0 {
|
if n&(n-1) == 0 {
|
||||||
return int31(r) & (n-1)
|
return int31(r) & (n-1)
|
||||||
}
|
}
|
||||||
max := i32((1<<31) - 1 - (1<<31)&u32(n))
|
max := i32((1<<31) - 1 - (1<<31)%u32(n))
|
||||||
v := int31(r)
|
v := int31(r)
|
||||||
for v > max {
|
for v > max {
|
||||||
v = int31(r)
|
v = int31(r)
|
||||||
@@ -85,7 +85,7 @@ int63_max :: proc(n: i64, r: ^Rand = nil) -> i64 {
|
|||||||
if n&(n-1) == 0 {
|
if n&(n-1) == 0 {
|
||||||
return int63(r) & (n-1)
|
return int63(r) & (n-1)
|
||||||
}
|
}
|
||||||
max := i64((1<<63) - 1 - (1<<63)&u64(n))
|
max := i64((1<<63) - 1 - (1<<63)%u64(n))
|
||||||
v := int63(r)
|
v := int63(r)
|
||||||
for v > max {
|
for v > max {
|
||||||
v = int63(r)
|
v = int63(r)
|
||||||
@@ -100,7 +100,7 @@ int127_max :: proc(n: i128, r: ^Rand = nil) -> i128 {
|
|||||||
if n&(n-1) == 0 {
|
if n&(n-1) == 0 {
|
||||||
return int127(r) & (n-1)
|
return int127(r) & (n-1)
|
||||||
}
|
}
|
||||||
max := i128((1<<63) - 1 - (1<<63)&u128(n))
|
max := i128((1<<127) - 1 - (1<<127)%u128(n))
|
||||||
v := int127(r)
|
v := int127(r)
|
||||||
for v > max {
|
for v > max {
|
||||||
v = int127(r)
|
v = int127(r)
|
||||||
@@ -142,8 +142,8 @@ read :: proc(p: []byte, r: ^Rand = nil) -> (n: int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// perm returns a slice of n ints in a pseudo-random permutation of integers in the range [0, n)
|
// perm returns a slice of n ints in a pseudo-random permutation of integers in the range [0, n)
|
||||||
perm :: proc(n: int, r: ^Rand = nil) -> []int {
|
perm :: proc(n: int, r: ^Rand = nil, allocator := context.allocator) -> []int {
|
||||||
m := make([]int, n)
|
m := make([]int, n, allocator)
|
||||||
for i := 0; i < n; i += 1 {
|
for i := 0; i < n; i += 1 {
|
||||||
j := int_max(i+1, r)
|
j := int_max(i+1, r)
|
||||||
m[i] = m[j]
|
m[i] = m[j]
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ String :: distinct Array(byte)
|
|||||||
|
|
||||||
Version_Type_Major :: 0
|
Version_Type_Major :: 0
|
||||||
Version_Type_Minor :: 2
|
Version_Type_Minor :: 2
|
||||||
Version_Type_Patch :: 1
|
Version_Type_Patch :: 4
|
||||||
|
|
||||||
Version_Type :: struct {
|
Version_Type :: struct {
|
||||||
major, minor, patch: u8,
|
major, minor, patch: u8,
|
||||||
@@ -77,9 +77,15 @@ Pkg :: struct {
|
|||||||
flags: Pkg_Flags,
|
flags: Pkg_Flags,
|
||||||
docs: String,
|
docs: String,
|
||||||
files: Array(File_Index),
|
files: Array(File_Index),
|
||||||
entities: Array(Entity_Index),
|
entries: Array(Scope_Entry),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Scope_Entry :: struct {
|
||||||
|
name: String,
|
||||||
|
entity: Entity_Index,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Entity_Kind :: enum u32le {
|
Entity_Kind :: enum u32le {
|
||||||
Invalid = 0,
|
Invalid = 0,
|
||||||
Constant = 1,
|
Constant = 1,
|
||||||
@@ -89,6 +95,7 @@ Entity_Kind :: enum u32le {
|
|||||||
Proc_Group = 5,
|
Proc_Group = 5,
|
||||||
Import_Name = 6,
|
Import_Name = 6,
|
||||||
Library_Name = 7,
|
Library_Name = 7,
|
||||||
|
Builtin = 8,
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity_Flag :: enum u32le {
|
Entity_Flag :: enum u32le {
|
||||||
@@ -105,8 +112,13 @@ Entity_Flag :: enum u32le {
|
|||||||
|
|
||||||
Type_Alias = 20,
|
Type_Alias = 20,
|
||||||
|
|
||||||
|
Builtin_Pkg_Builtin = 30,
|
||||||
|
Builtin_Pkg_Intrinsics = 31,
|
||||||
|
|
||||||
Var_Thread_Local = 40,
|
Var_Thread_Local = 40,
|
||||||
Var_Static = 41,
|
Var_Static = 41,
|
||||||
|
|
||||||
|
Private = 50,
|
||||||
}
|
}
|
||||||
|
|
||||||
Entity_Flags :: distinct bit_set[Entity_Flag; u64le]
|
Entity_Flags :: distinct bit_set[Entity_Flag; u64le]
|
||||||
@@ -122,6 +134,10 @@ Entity :: struct {
|
|||||||
_: u32le, // reserved for init
|
_: u32le, // reserved for init
|
||||||
comment: String,
|
comment: String,
|
||||||
docs: String,
|
docs: String,
|
||||||
|
// May be used by (Struct fields and procedure fields):
|
||||||
|
// .Variable
|
||||||
|
// .Constant
|
||||||
|
field_group_index: i32le,
|
||||||
|
|
||||||
// May used by:
|
// May used by:
|
||||||
// .Variable
|
// .Variable
|
||||||
@@ -242,6 +258,8 @@ Type :: struct {
|
|||||||
polymorphic_params: Type_Index,
|
polymorphic_params: Type_Index,
|
||||||
// Used By: .Struct, .Union
|
// Used By: .Struct, .Union
|
||||||
where_clauses: Array(String),
|
where_clauses: Array(String),
|
||||||
|
// Used By: .Struct
|
||||||
|
tags: Array(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
Type_Flags_Basic :: distinct bit_set[Type_Flag_Basic; u32le]
|
Type_Flags_Basic :: distinct bit_set[Type_Flag_Basic; u32le]
|
||||||
|
|||||||
+24
-1
@@ -296,6 +296,8 @@ foreign libc {
|
|||||||
@(link_name="readdir_r$INODE64") _unix_readdir_r :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int ---
|
@(link_name="readdir_r$INODE64") _unix_readdir_r :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int ---
|
||||||
@(link_name="fcntl") _unix_fcntl :: proc(fd: Handle, cmd: c.int, buf: ^byte) -> c.int ---
|
@(link_name="fcntl") _unix_fcntl :: proc(fd: Handle, cmd: c.int, buf: ^byte) -> c.int ---
|
||||||
|
|
||||||
|
@(link_name="fchmod") _unix_fchmod :: proc(fildes: Handle, mode: u16) -> c.int ---
|
||||||
|
|
||||||
@(link_name="malloc") _unix_malloc :: proc(size: int) -> rawptr ---
|
@(link_name="malloc") _unix_malloc :: proc(size: int) -> rawptr ---
|
||||||
@(link_name="calloc") _unix_calloc :: proc(num, size: int) -> rawptr ---
|
@(link_name="calloc") _unix_calloc :: proc(num, size: int) -> rawptr ---
|
||||||
@(link_name="free") _unix_free :: proc(ptr: rawptr) ---
|
@(link_name="free") _unix_free :: proc(ptr: rawptr) ---
|
||||||
@@ -305,6 +307,8 @@ foreign libc {
|
|||||||
@(link_name="chdir") _unix_chdir :: proc(buf: cstring) -> c.int ---
|
@(link_name="chdir") _unix_chdir :: proc(buf: cstring) -> c.int ---
|
||||||
@(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr ---
|
@(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr ---
|
||||||
|
|
||||||
|
@(link_name="strerror") _darwin_string_error :: proc(num : c.int) -> cstring ---
|
||||||
|
|
||||||
@(link_name="exit") _unix_exit :: proc(status: c.int) -> ! ---
|
@(link_name="exit") _unix_exit :: proc(status: c.int) -> ! ---
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,16 +323,35 @@ get_last_error :: proc() -> int {
|
|||||||
return __error()^
|
return __error()^
|
||||||
}
|
}
|
||||||
|
|
||||||
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {
|
get_last_error_string :: proc() -> string {
|
||||||
|
return cast(string)_darwin_string_error(cast(c.int)get_last_error())
|
||||||
|
}
|
||||||
|
|
||||||
|
open :: proc(path: string, flags: int = O_RDWR, mode: int = 0) -> (Handle, Errno) {
|
||||||
cstr := strings.clone_to_cstring(path)
|
cstr := strings.clone_to_cstring(path)
|
||||||
handle := _unix_open(cstr, i32(flags), u16(mode))
|
handle := _unix_open(cstr, i32(flags), u16(mode))
|
||||||
delete(cstr)
|
delete(cstr)
|
||||||
if handle == -1 {
|
if handle == -1 {
|
||||||
return INVALID_HANDLE, 1
|
return INVALID_HANDLE, 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
when ODIN_OS == "darwin" && ODIN_ARCH == "arm64" {
|
||||||
|
if mode != 0 {
|
||||||
|
err := fchmod(handle, cast(u16)mode)
|
||||||
|
if err != 0 {
|
||||||
|
_unix_close(handle)
|
||||||
|
return INVALID_HANDLE, 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return handle, 0
|
return handle, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fchmod :: proc(fildes: Handle, mode: u16) -> Errno {
|
||||||
|
return cast(Errno)_unix_fchmod(fildes, mode)
|
||||||
|
}
|
||||||
|
|
||||||
close :: proc(fd: Handle) {
|
close :: proc(fd: Handle) {
|
||||||
_unix_close(fd)
|
_unix_close(fd)
|
||||||
}
|
}
|
||||||
|
|||||||
+233
-48
@@ -266,33 +266,142 @@ X_OK :: 1 // Test for execute permission
|
|||||||
W_OK :: 2 // Test for write permission
|
W_OK :: 2 // Test for write permission
|
||||||
R_OK :: 4 // Test for read permission
|
R_OK :: 4 // Test for read permission
|
||||||
|
|
||||||
|
AT_FDCWD :: -100
|
||||||
|
AT_REMOVEDIR :: uintptr(0x200)
|
||||||
|
AT_SYMLINK_NOFOLLOW :: uintptr(0x100)
|
||||||
|
|
||||||
|
_unix_open :: proc(path: cstring, flags: int, mode: int = 0o000) -> Handle {
|
||||||
|
when ODIN_ARCH != "arm64" {
|
||||||
|
res := int(intrinsics.syscall(unix.SYS_open, uintptr(rawptr(path)), uintptr(flags), uintptr(mode)))
|
||||||
|
} else { // NOTE: arm64 does not have open
|
||||||
|
res := int(intrinsics.syscall(unix.SYS_openat, uintptr(AT_FDCWD), uintptr(rawptr(path), uintptr(flags), uintptr(mode))))
|
||||||
|
}
|
||||||
|
return -1 if res < 0 else Handle(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
_unix_close :: proc(fd: Handle) -> int {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_close, uintptr(fd)))
|
||||||
|
}
|
||||||
|
|
||||||
|
_unix_read :: proc(fd: Handle, buf: rawptr, size: uint) -> int {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_read, uintptr(fd), uintptr(buf), uintptr(size)))
|
||||||
|
}
|
||||||
|
|
||||||
|
_unix_write :: proc(fd: Handle, buf: rawptr, size: uint) -> int {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_write, uintptr(fd), uintptr(buf), uintptr(size)))
|
||||||
|
}
|
||||||
|
|
||||||
|
_unix_seek :: proc(fd: Handle, offset: i64, whence: int) -> i64 {
|
||||||
|
when ODIN_ARCH == "amd64" || ODIN_ARCH == "arm64" {
|
||||||
|
return i64(intrinsics.syscall(unix.SYS_lseek, uintptr(fd), uintptr(offset), uintptr(whence)))
|
||||||
|
} else {
|
||||||
|
low := uintptr(offset & 0xFFFFFFFF)
|
||||||
|
high := uintptr(offset >> 32)
|
||||||
|
result: i64
|
||||||
|
res := i64(intrinsics.syscall(unix.SYS__llseek, uintptr(fd), high, low, &result, uintptr(whence)))
|
||||||
|
return -1 if res < 0 else result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_unix_stat :: proc(path: cstring, stat: ^OS_Stat) -> int {
|
||||||
|
when ODIN_ARCH == "amd64" {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_stat, uintptr(rawptr(path)), uintptr(stat)))
|
||||||
|
} else when ODIN_ARCH != "arm64" {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_stat64, uintptr(rawptr(path)), uintptr(stat)))
|
||||||
|
} else { // NOTE: arm64 does not have stat
|
||||||
|
return int(intrinsics.syscall(unix.SYS_fstatat, uintptr(AT_FDCWD), uintptr(rawptr(path)), uintptr(stat), 0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_unix_fstat :: proc(fd: Handle, stat: ^OS_Stat) -> int {
|
||||||
|
when ODIN_ARCH == "amd64" || ODIN_ARCH == "arm64" {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_fstat, uintptr(fd), uintptr(stat)))
|
||||||
|
} else {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_fstat64, uintptr(fd), uintptr(stat)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_unix_lstat :: proc(path: cstring, stat: ^OS_Stat) -> int {
|
||||||
|
when ODIN_ARCH == "amd64" {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_lstat, uintptr(rawptr(path)), uintptr(stat)))
|
||||||
|
} else when ODIN_ARCH != "arm64" {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_lstat64, uintptr(rawptr(path)), uintptr(stat)))
|
||||||
|
} else { // NOTE: arm64 does not have any lstat
|
||||||
|
return int(intrinsics.syscall(unix.SYS_fstatat, uintptr(AT_FDCWD), uintptr(rawptr(path)), uintptr(stat), AT_SYMLINK_NOFOLLOW))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_unix_readlink :: proc(path: cstring, buf: rawptr, bufsiz: uint) -> int {
|
||||||
|
when ODIN_ARCH != "arm64" {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_readlink, uintptr(rawptr(path)), uintptr(buf), uintptr(bufsiz)))
|
||||||
|
} else { // NOTE: arm64 does not have readlink
|
||||||
|
return int(intrinsics.syscall(unix.SYS_readlinkat, uintptr(AT_FDCWD), uintptr(rawptr(path)), uintptr(buf), uintptr(bufsiz)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_unix_access :: proc(path: cstring, mask: int) -> int {
|
||||||
|
when ODIN_ARCH != "arm64" {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_access, uintptr(rawptr(path)), uintptr(mask)))
|
||||||
|
} else { // NOTE: arm64 does not have access
|
||||||
|
return int(intrinsics.syscall(unix.SYS_faccessat, uintptr(AT_FDCWD), uintptr(rawptr(path)), uintptr(mask)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_unix_getcwd :: proc(buf: rawptr, size: uint) -> int {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_getcwd, uintptr(buf), uintptr(size)))
|
||||||
|
}
|
||||||
|
|
||||||
|
_unix_chdir :: proc(path: cstring) -> int {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_chdir, uintptr(rawptr(path))))
|
||||||
|
}
|
||||||
|
|
||||||
|
_unix_rename :: proc(old, new: cstring) -> int {
|
||||||
|
when ODIN_ARCH != "arm64" {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_rename, uintptr(rawptr(old)), uintptr(rawptr(new))))
|
||||||
|
} else { // NOTE: arm64 does not have rename
|
||||||
|
return int(intrinsics.syscall(unix.SYS_renameat, uintptr(AT_FDCWD), uintptr(rawptr(old)), uintptr(rawptr(new))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_unix_unlink :: proc(path: cstring) -> int {
|
||||||
|
when ODIN_ARCH != "arm64" {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_unlink, uintptr(rawptr(path))))
|
||||||
|
} else { // NOTE: arm64 does not have unlink
|
||||||
|
return int(intrinsics.syscall(unix.SYS_unlinkat, uintptr(AT_FDCWD), uintptr(rawptr(path), 0)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_unix_rmdir :: proc(path: cstring) -> int {
|
||||||
|
when ODIN_ARCH != "arm64" {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_rmdir, uintptr(rawptr(path))))
|
||||||
|
} else { // NOTE: arm64 does not have rmdir
|
||||||
|
return int(intrinsics.syscall(unix.SYS_unlinkat, uintptr(AT_FDCWD), uintptr(rawptr(path)), AT_REMOVEDIR))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_unix_mkdir :: proc(path: cstring, mode: u32) -> int {
|
||||||
|
when ODIN_ARCH != "arm64" {
|
||||||
|
return int(intrinsics.syscall(unix.SYS_mkdir, uintptr(rawptr(path)), uintptr(mode)))
|
||||||
|
} else { // NOTE: arm64 does not have mkdir
|
||||||
|
return int(intrinsics.syscall(unix.SYS_mkdirat, uintptr(AT_FDCWD), uintptr(rawptr(path)), uintptr(mode)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreign libc {
|
foreign libc {
|
||||||
@(link_name="__errno_location") __errno_location :: proc() -> ^int ---
|
@(link_name="__errno_location") __errno_location :: proc() -> ^int ---
|
||||||
|
|
||||||
@(link_name="open") _unix_open :: proc(path: cstring, flags: c.int, mode: c.int) -> Handle ---
|
|
||||||
@(link_name="close") _unix_close :: proc(fd: Handle) -> c.int ---
|
|
||||||
@(link_name="read") _unix_read :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
|
|
||||||
@(link_name="write") _unix_write :: proc(fd: Handle, buf: rawptr, size: c.size_t) -> c.ssize_t ---
|
|
||||||
@(link_name="lseek64") _unix_seek :: proc(fd: Handle, offset: i64, whence: c.int) -> i64 ---
|
|
||||||
@(link_name="gettid") _unix_gettid :: proc() -> u64 ---
|
|
||||||
@(link_name="getpagesize") _unix_getpagesize :: proc() -> c.int ---
|
@(link_name="getpagesize") _unix_getpagesize :: proc() -> c.int ---
|
||||||
@(link_name="stat64") _unix_stat :: proc(path: cstring, stat: ^OS_Stat) -> c.int ---
|
|
||||||
@(link_name="lstat") _unix_lstat :: proc(path: cstring, stat: ^OS_Stat) -> c.int ---
|
|
||||||
@(link_name="fstat") _unix_fstat :: proc(fd: Handle, stat: ^OS_Stat) -> c.int ---
|
|
||||||
@(link_name="fdopendir") _unix_fdopendir :: proc(fd: Handle) -> Dir ---
|
@(link_name="fdopendir") _unix_fdopendir :: proc(fd: Handle) -> Dir ---
|
||||||
@(link_name="closedir") _unix_closedir :: proc(dirp: Dir) -> c.int ---
|
@(link_name="closedir") _unix_closedir :: proc(dirp: Dir) -> c.int ---
|
||||||
@(link_name="rewinddir") _unix_rewinddir :: proc(dirp: Dir) ---
|
@(link_name="rewinddir") _unix_rewinddir :: proc(dirp: Dir) ---
|
||||||
@(link_name="readdir_r") _unix_readdir_r :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int ---
|
@(link_name="readdir_r") _unix_readdir_r :: proc(dirp: Dir, entry: ^Dirent, result: ^^Dirent) -> c.int ---
|
||||||
@(link_name="readlink") _unix_readlink :: proc(path: cstring, buf: ^byte, bufsiz: c.size_t) -> c.ssize_t ---
|
|
||||||
@(link_name="access") _unix_access :: proc(path: cstring, mask: c.int) -> c.int ---
|
|
||||||
|
|
||||||
@(link_name="malloc") _unix_malloc :: proc(size: c.size_t) -> rawptr ---
|
@(link_name="malloc") _unix_malloc :: proc(size: c.size_t) -> rawptr ---
|
||||||
@(link_name="calloc") _unix_calloc :: proc(num, size: c.size_t) -> rawptr ---
|
@(link_name="calloc") _unix_calloc :: proc(num, size: c.size_t) -> rawptr ---
|
||||||
@(link_name="free") _unix_free :: proc(ptr: rawptr) ---
|
@(link_name="free") _unix_free :: proc(ptr: rawptr) ---
|
||||||
@(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: c.size_t) -> rawptr ---
|
@(link_name="realloc") _unix_realloc :: proc(ptr: rawptr, size: c.size_t) -> rawptr ---
|
||||||
|
|
||||||
@(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring ---
|
@(link_name="getenv") _unix_getenv :: proc(cstring) -> cstring ---
|
||||||
@(link_name="getcwd") _unix_getcwd :: proc(buf: cstring, len: c.size_t) -> cstring ---
|
|
||||||
@(link_name="chdir") _unix_chdir :: proc(buf: cstring) -> c.int ---
|
|
||||||
@(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr ---
|
@(link_name="realpath") _unix_realpath :: proc(path: cstring, resolved_path: rawptr) -> rawptr ---
|
||||||
|
|
||||||
@(link_name="exit") _unix_exit :: proc(status: c.int) -> ! ---
|
@(link_name="exit") _unix_exit :: proc(status: c.int) -> ! ---
|
||||||
@@ -308,51 +417,57 @@ is_path_separator :: proc(r: rune) -> bool {
|
|||||||
return r == '/'
|
return r == '/'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// determine errno from syscall return value
|
||||||
|
@private
|
||||||
|
_get_errno :: proc(res: int) -> Errno {
|
||||||
|
if res < 0 && res > -4096 {
|
||||||
|
return Errno(-res)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// get errno from libc
|
||||||
get_last_error :: proc() -> int {
|
get_last_error :: proc() -> int {
|
||||||
return __errno_location()^
|
return __errno_location()^
|
||||||
}
|
}
|
||||||
|
|
||||||
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {
|
open :: proc(path: string, flags: int = O_RDONLY, mode: int = 0) -> (Handle, Errno) {
|
||||||
cstr := strings.clone_to_cstring(path)
|
cstr := strings.clone_to_cstring(path)
|
||||||
handle := _unix_open(cstr, c.int(flags), c.int(mode))
|
handle := _unix_open(cstr, flags, mode)
|
||||||
delete(cstr)
|
defer delete(cstr)
|
||||||
if handle == -1 {
|
if handle < 0 {
|
||||||
return INVALID_HANDLE, Errno(get_last_error())
|
return INVALID_HANDLE, _get_errno(int(handle))
|
||||||
}
|
}
|
||||||
return handle, ERROR_NONE
|
return handle, ERROR_NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
close :: proc(fd: Handle) -> Errno {
|
close :: proc(fd: Handle) -> Errno {
|
||||||
result := _unix_close(fd)
|
return _get_errno(_unix_close(fd))
|
||||||
if result == -1 {
|
|
||||||
return Errno(get_last_error())
|
|
||||||
}
|
|
||||||
return ERROR_NONE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
read :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
||||||
bytes_read := _unix_read(fd, &data[0], c.size_t(len(data)))
|
bytes_read := _unix_read(fd, &data[0], c.size_t(len(data)))
|
||||||
if bytes_read == -1 {
|
if bytes_read < 0 {
|
||||||
return -1, Errno(get_last_error())
|
return -1, _get_errno(bytes_read)
|
||||||
}
|
}
|
||||||
return int(bytes_read), ERROR_NONE
|
return bytes_read, ERROR_NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
write :: proc(fd: Handle, data: []byte) -> (int, Errno) {
|
||||||
if len(data) == 0 {
|
if len(data) == 0 {
|
||||||
return 0, ERROR_NONE
|
return 0, ERROR_NONE
|
||||||
}
|
}
|
||||||
bytes_written := _unix_write(fd, &data[0], c.size_t(len(data)))
|
bytes_written := _unix_write(fd, &data[0], uint(len(data)))
|
||||||
if bytes_written == -1 {
|
if bytes_written < 0 {
|
||||||
return -1, Errno(get_last_error())
|
return -1, _get_errno(bytes_written)
|
||||||
}
|
}
|
||||||
return int(bytes_written), ERROR_NONE
|
return int(bytes_written), ERROR_NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Errno) {
|
||||||
res := _unix_seek(fd, offset, c.int(whence))
|
res := _unix_seek(fd, offset, whence)
|
||||||
if res == -1 {
|
if res < 0 {
|
||||||
return -1, Errno(get_last_error())
|
return -1, _get_errno(int(res))
|
||||||
}
|
}
|
||||||
return res, ERROR_NONE
|
return res, ERROR_NONE
|
||||||
}
|
}
|
||||||
@@ -365,6 +480,75 @@ file_size :: proc(fd: Handle) -> (i64, Errno) {
|
|||||||
return max(s.size, 0), ERROR_NONE
|
return max(s.size, 0), ERROR_NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rename :: proc(old_path, new_path: string) -> Errno {
|
||||||
|
old_path_cstr := strings.clone_to_cstring(old_path, context.temp_allocator)
|
||||||
|
new_path_cstr := strings.clone_to_cstring(new_path, context.temp_allocator)
|
||||||
|
return _get_errno(_unix_rename(old_path_cstr, new_path_cstr))
|
||||||
|
}
|
||||||
|
|
||||||
|
remove :: proc(path: string) -> Errno {
|
||||||
|
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||||
|
return _get_errno(_unix_unlink(path_cstr))
|
||||||
|
}
|
||||||
|
|
||||||
|
make_directory :: proc(path: string, mode: u32 = 0o775) -> Errno {
|
||||||
|
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||||
|
return _get_errno(_unix_mkdir(path_cstr, mode))
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_directory :: proc(path: string) -> Errno {
|
||||||
|
path_cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||||
|
return _get_errno(_unix_rmdir(path_cstr))
|
||||||
|
}
|
||||||
|
|
||||||
|
is_file_handle :: proc(fd: Handle) -> bool {
|
||||||
|
s, err := _fstat(fd)
|
||||||
|
if err != ERROR_NONE {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return S_ISREG(s.mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
is_file_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||||
|
s: OS_Stat
|
||||||
|
err: Errno
|
||||||
|
if follow_links {
|
||||||
|
s, err = _stat(path)
|
||||||
|
} else {
|
||||||
|
s, err = _lstat(path)
|
||||||
|
}
|
||||||
|
if err != ERROR_NONE {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return S_ISREG(s.mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
is_dir_handle :: proc(fd: Handle) -> bool {
|
||||||
|
s, err := _fstat(fd)
|
||||||
|
if err != ERROR_NONE {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return S_ISDIR(s.mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
is_dir_path :: proc(path: string, follow_links: bool = true) -> bool {
|
||||||
|
s: OS_Stat
|
||||||
|
err: Errno
|
||||||
|
if follow_links {
|
||||||
|
s, err = _stat(path)
|
||||||
|
} else {
|
||||||
|
s, err = _lstat(path)
|
||||||
|
}
|
||||||
|
if err != ERROR_NONE {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return S_ISDIR(s.mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
is_file :: proc {is_file_path, is_file_handle}
|
||||||
|
is_dir :: proc {is_dir_path, is_dir_handle}
|
||||||
|
|
||||||
|
|
||||||
// NOTE(bill): Uses startup to initialize it
|
// NOTE(bill): Uses startup to initialize it
|
||||||
|
|
||||||
@@ -401,8 +585,8 @@ _stat :: proc(path: string) -> (OS_Stat, Errno) {
|
|||||||
|
|
||||||
s: OS_Stat
|
s: OS_Stat
|
||||||
result := _unix_stat(cstr, &s)
|
result := _unix_stat(cstr, &s)
|
||||||
if result == -1 {
|
if result < 0 {
|
||||||
return s, Errno(get_last_error())
|
return s, _get_errno(result)
|
||||||
}
|
}
|
||||||
return s, ERROR_NONE
|
return s, ERROR_NONE
|
||||||
}
|
}
|
||||||
@@ -414,8 +598,8 @@ _lstat :: proc(path: string) -> (OS_Stat, Errno) {
|
|||||||
|
|
||||||
s: OS_Stat
|
s: OS_Stat
|
||||||
result := _unix_lstat(cstr, &s)
|
result := _unix_lstat(cstr, &s)
|
||||||
if result == -1 {
|
if result < 0 {
|
||||||
return s, Errno(get_last_error())
|
return s, _get_errno(result)
|
||||||
}
|
}
|
||||||
return s, ERROR_NONE
|
return s, ERROR_NONE
|
||||||
}
|
}
|
||||||
@@ -424,8 +608,8 @@ _lstat :: proc(path: string) -> (OS_Stat, Errno) {
|
|||||||
_fstat :: proc(fd: Handle) -> (OS_Stat, Errno) {
|
_fstat :: proc(fd: Handle) -> (OS_Stat, Errno) {
|
||||||
s: OS_Stat
|
s: OS_Stat
|
||||||
result := _unix_fstat(fd, &s)
|
result := _unix_fstat(fd, &s)
|
||||||
if result == -1 {
|
if result < 0 {
|
||||||
return s, Errno(get_last_error())
|
return s, _get_errno(result)
|
||||||
}
|
}
|
||||||
return s, ERROR_NONE
|
return s, ERROR_NONE
|
||||||
}
|
}
|
||||||
@@ -482,9 +666,9 @@ _readlink :: proc(path: string) -> (string, Errno) {
|
|||||||
buf := make([]byte, bufsz)
|
buf := make([]byte, bufsz)
|
||||||
for {
|
for {
|
||||||
rc := _unix_readlink(path_cstr, &(buf[0]), bufsz)
|
rc := _unix_readlink(path_cstr, &(buf[0]), bufsz)
|
||||||
if rc == -1 {
|
if rc < 0 {
|
||||||
delete(buf)
|
delete(buf)
|
||||||
return "", Errno(get_last_error())
|
return "", _get_errno(rc)
|
||||||
} else if rc == int(bufsz) {
|
} else if rc == int(bufsz) {
|
||||||
// NOTE(laleksic, 2021-01-21): Any cleaner way to resize the slice?
|
// NOTE(laleksic, 2021-01-21): Any cleaner way to resize the slice?
|
||||||
bufsz *= 2
|
bufsz *= 2
|
||||||
@@ -530,9 +714,9 @@ absolute_path_from_relative :: proc(rel: string) -> (path: string, err: Errno) {
|
|||||||
access :: proc(path: string, mask: int) -> (bool, Errno) {
|
access :: proc(path: string, mask: int) -> (bool, Errno) {
|
||||||
cstr := strings.clone_to_cstring(path)
|
cstr := strings.clone_to_cstring(path)
|
||||||
defer delete(cstr)
|
defer delete(cstr)
|
||||||
result := _unix_access(cstr, c.int(mask))
|
result := _unix_access(cstr, mask)
|
||||||
if result == -1 {
|
if result < 0 {
|
||||||
return false, Errno(get_last_error())
|
return false, _get_errno(result)
|
||||||
}
|
}
|
||||||
return true, ERROR_NONE
|
return true, ERROR_NONE
|
||||||
}
|
}
|
||||||
@@ -567,11 +751,12 @@ get_current_directory :: proc() -> string {
|
|||||||
page_size := get_page_size()
|
page_size := get_page_size()
|
||||||
buf := make([dynamic]u8, page_size)
|
buf := make([dynamic]u8, page_size)
|
||||||
for {
|
for {
|
||||||
#no_bounds_check cwd := _unix_getcwd(cstring(&buf[0]), c.size_t(len(buf)))
|
#no_bounds_check res := _unix_getcwd(&buf[0], uint(len(buf)))
|
||||||
if cwd != nil {
|
|
||||||
return string(cwd)
|
if res >= 0 {
|
||||||
|
return strings.string_from_nul_terminated_ptr(&buf[0], len(buf))
|
||||||
}
|
}
|
||||||
if Errno(get_last_error()) != ERANGE {
|
if _get_errno(res) != ERANGE {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
resize(&buf, len(buf)+page_size)
|
resize(&buf, len(buf)+page_size)
|
||||||
@@ -582,8 +767,8 @@ get_current_directory :: proc() -> string {
|
|||||||
set_current_directory :: proc(path: string) -> (err: Errno) {
|
set_current_directory :: proc(path: string) -> (err: Errno) {
|
||||||
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
cstr := strings.clone_to_cstring(path, context.temp_allocator)
|
||||||
res := _unix_chdir(cstr)
|
res := _unix_chdir(cstr)
|
||||||
if res == -1 {
|
if res < 0 {
|
||||||
return Errno(get_last_error())
|
return _get_errno(res)
|
||||||
}
|
}
|
||||||
return ERROR_NONE
|
return ERROR_NONE
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package path
|
||||||
|
|
||||||
|
#panic(
|
||||||
|
`core:path/slashpath - for paths separated by forward slashes, e.g. paths in URLs, this does not deal with OS-specific paths
|
||||||
|
core:path/filepath - uses either forward slashes or backslashes depending on the operating system, deals with Windows/NT paths with volume letters or backslashes (on the related platforms)`)
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package path
|
package slashpath
|
||||||
|
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
import "core:unicode/utf8"
|
import "core:unicode/utf8"
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
// The path package is only to be used for paths separated by forward slashes,
|
// The slashpath package is only to be used for paths separated by forward slashes,
|
||||||
// e.g. paths in URLs
|
// e.g. paths in URLs
|
||||||
//
|
//
|
||||||
// This package does not deal with Windows/NT paths with volume letters or backslashes
|
// This package does not deal with Windows/NT paths with volume letters or backslashes
|
||||||
// To manipulate operating system specific paths, use the path/filepath package
|
// To manipulate operating system specific paths, use the path/filepath package
|
||||||
package path
|
package slashpath
|
||||||
|
|
||||||
import "core:strings"
|
import "core:strings"
|
||||||
|
|
||||||
@@ -386,6 +386,29 @@ Raw_Cstring :: struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Defined internally by the compiler
|
||||||
|
Odin_Build_Mode_Type :: enum int {
|
||||||
|
Executable,
|
||||||
|
Dynamic,
|
||||||
|
Object,
|
||||||
|
Assembly,
|
||||||
|
LLVM_IR,
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
Odin_Build_Mode_Type :: type_of(ODIN_BUILD_MODE)
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Defined internally by the compiler
|
||||||
|
Odin_Endian_Type :: enum int {
|
||||||
|
Unknown,
|
||||||
|
Little,
|
||||||
|
Big,
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
Odin_Endian_Type :: type_of(ODIN_ENDIAN)
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
// Init Startup Procedures //
|
// Init Startup Procedures //
|
||||||
/////////////////////////////
|
/////////////////////////////
|
||||||
|
|||||||
@@ -614,6 +614,10 @@ raw_data :: proc{raw_array_data, raw_slice_data, raw_dynamic_array_data, raw_str
|
|||||||
@(disabled=ODIN_DISABLE_ASSERT)
|
@(disabled=ODIN_DISABLE_ASSERT)
|
||||||
assert :: proc(condition: bool, message := "", loc := #caller_location) {
|
assert :: proc(condition: bool, message := "", loc := #caller_location) {
|
||||||
if !condition {
|
if !condition {
|
||||||
|
// NOTE(bill): This is wrapped in a procedure call
|
||||||
|
// to improve performance to make the CPU not
|
||||||
|
// execute speculatively, making it about an order of
|
||||||
|
// magnitude faster
|
||||||
proc(message: string, loc: Source_Code_Location) {
|
proc(message: string, loc: Source_Code_Location) {
|
||||||
p := context.assertion_failure_proc
|
p := context.assertion_failure_proc
|
||||||
if p == nil {
|
if p == nil {
|
||||||
|
|||||||
@@ -146,14 +146,14 @@ matrix2x2_inverse_transpose :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y:
|
|||||||
d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0]
|
d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0]
|
||||||
when intrinsics.type_is_integer(T) {
|
when intrinsics.type_is_integer(T) {
|
||||||
y[0, 0] = +x[1, 1] / d
|
y[0, 0] = +x[1, 1] / d
|
||||||
y[1, 0] = -x[1, 0] / d
|
y[1, 0] = -x[0, 1] / d
|
||||||
y[0, 1] = -x[0, 1] / d
|
y[0, 1] = -x[1, 0] / d
|
||||||
y[1, 1] = +x[0, 0] / d
|
y[1, 1] = +x[0, 0] / d
|
||||||
} else {
|
} else {
|
||||||
id := 1 / d
|
id := 1 / d
|
||||||
y[0, 0] = +x[1, 1] * id
|
y[0, 0] = +x[1, 1] * id
|
||||||
y[1, 0] = -x[1, 0] * id
|
y[1, 0] = -x[0, 1] * id
|
||||||
y[0, 1] = -x[0, 1] * id
|
y[0, 1] = -x[1, 0] * id
|
||||||
y[1, 1] = +x[0, 0] * id
|
y[1, 1] = +x[0, 0] * id
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@@ -214,16 +214,16 @@ matrix1x1_inverse :: proc "contextless" (x: $M/matrix[1, 1]$T) -> (y: M) {
|
|||||||
matrix2x2_inverse :: proc "contextless" (x: $M/matrix[2, 2]$T) -> (y: M) {
|
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]
|
d := x[0, 0]*x[1, 1] - x[0, 1]*x[1, 0]
|
||||||
when intrinsics.type_is_integer(T) {
|
when intrinsics.type_is_integer(T) {
|
||||||
y[0, 0] = x[1, 1] / d
|
y[0, 0] = +x[1, 1] / d
|
||||||
y[0, 1] = x[1, 0] / d
|
y[0, 1] = -x[0, 1] / d
|
||||||
y[1, 0] = x[0, 1] / d
|
y[1, 0] = -x[1, 0] / d
|
||||||
y[1, 1] = x[0, 0] / d
|
y[1, 1] = +x[0, 0] / d
|
||||||
} else {
|
} else {
|
||||||
id := 1 / d
|
id := 1 / d
|
||||||
y[0, 0] = x[1, 1] * id
|
y[0, 0] = +x[1, 1] * id
|
||||||
y[0, 1] = x[1, 0] * id
|
y[0, 1] = -x[0, 1] * id
|
||||||
y[1, 0] = x[0, 1] * id
|
y[1, 0] = -x[1, 0] * id
|
||||||
y[1, 1] = x[0, 0] * id
|
y[1, 1] = +x[0, 0] * id
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
//+private
|
||||||
|
//+build linux, darwin, freebsd
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import "core:intrinsics"
|
||||||
|
|
||||||
|
when ODIN_BUILD_MODE == .Dynamic {
|
||||||
|
@(link_name="_odin_entry_point", linkage="strong", require/*, link_section=".init"*/)
|
||||||
|
_odin_entry_point :: proc "c" () {
|
||||||
|
context = default_context()
|
||||||
|
#force_no_inline _startup_runtime()
|
||||||
|
intrinsics.__entry_point()
|
||||||
|
}
|
||||||
|
@(link_name="_odin_exit_point", linkage="strong", require/*, link_section=".fini"*/)
|
||||||
|
_odin_exit_point :: proc "c" () {
|
||||||
|
context = default_context()
|
||||||
|
#force_no_inline _cleanup_runtime()
|
||||||
|
}
|
||||||
|
@(link_name="main", linkage="strong", require)
|
||||||
|
main :: proc "c" (argc: i32, argv: [^]cstring) -> i32 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
} else when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
|
||||||
|
@(link_name="main", linkage="strong", require)
|
||||||
|
main :: proc "c" (argc: i32, argv: [^]cstring) -> i32 {
|
||||||
|
args__ = argv[:argc]
|
||||||
|
context = default_context()
|
||||||
|
#force_no_inline _startup_runtime()
|
||||||
|
intrinsics.__entry_point()
|
||||||
|
#force_no_inline _cleanup_runtime()
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
//+private
|
||||||
|
//+build wasm32, wasm64
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import "core:intrinsics"
|
||||||
|
|
||||||
|
when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
|
||||||
|
@(link_name="_start", linkage="strong", require, export)
|
||||||
|
_start :: proc "c" () {
|
||||||
|
context = default_context()
|
||||||
|
#force_no_inline _startup_runtime()
|
||||||
|
intrinsics.__entry_point()
|
||||||
|
}
|
||||||
|
@(link_name="_end", linkage="strong", require, export)
|
||||||
|
_end :: proc "c" () {
|
||||||
|
context = default_context()
|
||||||
|
#force_no_inline _cleanup_runtime()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
//+private
|
||||||
|
//+build windows
|
||||||
|
package runtime
|
||||||
|
|
||||||
|
import "core:intrinsics"
|
||||||
|
|
||||||
|
when ODIN_BUILD_MODE == .Dynamic {
|
||||||
|
@(link_name="DllMain", linkage="strong", require)
|
||||||
|
DllMain :: proc "stdcall" (hinstDLL: rawptr, fdwReason: u32, lpReserved: rawptr) -> b32 {
|
||||||
|
context = default_context()
|
||||||
|
switch fdwReason {
|
||||||
|
case 1: // DLL_PROCESS_ATTACH
|
||||||
|
#force_no_inline _startup_runtime()
|
||||||
|
intrinsics.__entry_point()
|
||||||
|
case 0: // DLL_PROCESS_DETACH
|
||||||
|
#force_no_inline _cleanup_runtime()
|
||||||
|
case 2: // DLL_THREAD_ATTACH
|
||||||
|
break
|
||||||
|
case 3: // DLL_THREAD_DETACH
|
||||||
|
break
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
} else when !ODIN_TEST && !ODIN_NO_ENTRY_POINT {
|
||||||
|
when ODIN_ARCH == "i386" || ODIN_NO_CRT {
|
||||||
|
@(link_name="mainCRTStartup", linkage="strong", require)
|
||||||
|
mainCRTStartup :: proc "stdcall" () -> i32 {
|
||||||
|
context = default_context()
|
||||||
|
#force_no_inline _startup_runtime()
|
||||||
|
intrinsics.__entry_point()
|
||||||
|
#force_no_inline _cleanup_runtime()
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
@(link_name="main", linkage="strong", require)
|
||||||
|
main :: proc "c" (argc: i32, argv: [^]cstring) -> i32 {
|
||||||
|
args__ = argv[:argc]
|
||||||
|
context = default_context()
|
||||||
|
#force_no_inline _startup_runtime()
|
||||||
|
intrinsics.__entry_point()
|
||||||
|
#force_no_inline _cleanup_runtime()
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,7 @@ IS_WASM :: ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64"
|
|||||||
@(private)
|
@(private)
|
||||||
RUNTIME_LINKAGE :: "strong" when (
|
RUNTIME_LINKAGE :: "strong" when (
|
||||||
(ODIN_USE_SEPARATE_MODULES ||
|
(ODIN_USE_SEPARATE_MODULES ||
|
||||||
ODIN_BUILD_MODE == "dynamic" ||
|
ODIN_BUILD_MODE == .Dynamic ||
|
||||||
!ODIN_NO_CRT) &&
|
!ODIN_NO_CRT) &&
|
||||||
!IS_WASM) else "internal"
|
!IS_WASM) else "internal"
|
||||||
RUNTIME_REQUIRE :: true
|
RUNTIME_REQUIRE :: true
|
||||||
|
|||||||
+15
-5
@@ -143,11 +143,21 @@ print_int :: proc "contextless" (x: int) { print_i64(i64(x)) }
|
|||||||
|
|
||||||
print_caller_location :: proc "contextless" (using loc: Source_Code_Location) {
|
print_caller_location :: proc "contextless" (using loc: Source_Code_Location) {
|
||||||
print_string(file_path)
|
print_string(file_path)
|
||||||
print_byte('(')
|
when ODIN_ERROR_POS_STYLE == .Default {
|
||||||
print_u64(u64(line))
|
print_byte('(')
|
||||||
print_byte(':')
|
print_u64(u64(line))
|
||||||
print_u64(u64(column))
|
print_byte(':')
|
||||||
print_byte(')')
|
print_u64(u64(column))
|
||||||
|
print_byte(')')
|
||||||
|
} else when ODIN_ERROR_POS_STYLE == .Unix {
|
||||||
|
print_byte(':')
|
||||||
|
print_u64(u64(line))
|
||||||
|
print_byte(':')
|
||||||
|
print_u64(u64(column))
|
||||||
|
print_byte(':')
|
||||||
|
} else {
|
||||||
|
#panic("unhandled ODIN_ERROR_POS_STYLE")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
print_typeid :: proc "contextless" (id: typeid) {
|
print_typeid :: proc "contextless" (id: typeid) {
|
||||||
if id == nil {
|
if id == nil {
|
||||||
|
|||||||
@@ -22,4 +22,4 @@ windows_trap_type_assertion :: proc "contextless" () -> ! {
|
|||||||
when ODIN_NO_CRT {
|
when ODIN_NO_CRT {
|
||||||
@(require)
|
@(require)
|
||||||
foreign import crt_lib "procs_windows_amd64.asm"
|
foreign import crt_lib "procs_windows_amd64.asm"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ udivmod128 :: proc "c" (a, b: u128, rem: ^u128) -> u128 {
|
|||||||
q, r: [2]u64
|
q, r: [2]u64
|
||||||
sr: u32 = 0
|
sr: u32 = 0
|
||||||
|
|
||||||
low :: 1 when ODIN_ENDIAN == "big" else 0
|
low :: 1 when ODIN_ENDIAN == .Big else 0
|
||||||
high :: 1 - low
|
high :: 1 - low
|
||||||
U64_BITS :: 8*size_of(u64)
|
U64_BITS :: 8*size_of(u64)
|
||||||
U128_BITS :: 8*size_of(u128)
|
U128_BITS :: 8*size_of(u128)
|
||||||
|
|||||||
@@ -304,6 +304,23 @@ filter :: proc(s: $S/[]$U, f: proc(U) -> bool, allocator := context.allocator) -
|
|||||||
return r[:]
|
return r[:]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scanner :: proc (s: $S/[]$U, initializer: $V, f: proc(V, U)->V, allocator := context.allocator) -> []V {
|
||||||
|
if len(s) == 0 { return {} }
|
||||||
|
|
||||||
|
res := make([]V, len(s), allocator)
|
||||||
|
p := as_ptr(s)
|
||||||
|
q := as_ptr(res)
|
||||||
|
r := initializer
|
||||||
|
|
||||||
|
for l := len(s); l > 0; l -= 1 {
|
||||||
|
r = f(r, p[0])
|
||||||
|
q[0] = r
|
||||||
|
p = p[1:]
|
||||||
|
q = q[1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
min :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok {
|
min :: proc(s: $S/[]$T) -> (res: T, ok: bool) where intrinsics.type_is_ordered(T) #optional_ok {
|
||||||
|
|||||||
+31
-488
@@ -1,10 +1,5 @@
|
|||||||
package slice
|
package slice
|
||||||
|
|
||||||
import "core:intrinsics"
|
|
||||||
_ :: intrinsics
|
|
||||||
|
|
||||||
ORD :: intrinsics.type_is_ordered
|
|
||||||
|
|
||||||
Ordering :: enum {
|
Ordering :: enum {
|
||||||
Less = -1,
|
Less = -1,
|
||||||
Equal = 0,
|
Equal = 0,
|
||||||
@@ -38,7 +33,7 @@ cmp_proc :: proc($E: typeid) -> (proc(E, E) -> Ordering) where ORD(E) {
|
|||||||
sort :: proc(data: $T/[]$E) where ORD(E) {
|
sort :: proc(data: $T/[]$E) where ORD(E) {
|
||||||
when size_of(E) != 0 {
|
when size_of(E) != 0 {
|
||||||
if n := len(data); n > 1 {
|
if n := len(data); n > 1 {
|
||||||
_quick_sort(data, 0, n, _max_depth(n))
|
_quick_sort_general(data, 0, n, _max_depth(n), struct{}{}, .Ordered)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,7 +43,7 @@ sort :: proc(data: $T/[]$E) where ORD(E) {
|
|||||||
sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
|
sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
|
||||||
when size_of(E) != 0 {
|
when size_of(E) != 0 {
|
||||||
if n := len(data); n > 1 {
|
if n := len(data); n > 1 {
|
||||||
_quick_sort_less(data, 0, n, _max_depth(n), less)
|
_quick_sort_general(data, 0, n, _max_depth(n), less, .Less)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -56,7 +51,33 @@ sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
|
|||||||
sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
|
sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
|
||||||
when size_of(E) != 0 {
|
when size_of(E) != 0 {
|
||||||
if n := len(data); n > 1 {
|
if n := len(data); n > 1 {
|
||||||
_quick_sort_cmp(data, 0, n, _max_depth(n), cmp)
|
_quick_sort_general(data, 0, n, _max_depth(n), cmp, .Cmp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stable_sort sorts a slice
|
||||||
|
stable_sort :: proc(data: $T/[]$E) where ORD(E) {
|
||||||
|
when size_of(E) != 0 {
|
||||||
|
if n := len(data); n > 1 {
|
||||||
|
_stable_sort_general(data, struct{}{}, .Ordered)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// stable_sort_by sorts a slice with a given procedure to test whether two values are ordered "i < j"
|
||||||
|
stable_sort_by :: proc(data: $T/[]$E, less: proc(i, j: E) -> bool) {
|
||||||
|
when size_of(E) != 0 {
|
||||||
|
if n := len(data); n > 1 {
|
||||||
|
_stable_sort_general(data, less, .Less)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stable_sort_by_cmp :: proc(data: $T/[]$E, cmp: proc(i, j: E) -> Ordering) {
|
||||||
|
when size_of(E) != 0 {
|
||||||
|
if n := len(data); n > 1 {
|
||||||
|
_stable_sort_general(data, cmp, .Cmp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,6 +100,7 @@ is_sorted_by :: proc(array: $T/[]$E, less: proc(i, j: E) -> bool) -> bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_sorted_by_cmp :: is_sorted_cmp
|
||||||
is_sorted_cmp :: proc(array: $T/[]$E, cmp: proc(i, j: E) -> Ordering) -> bool {
|
is_sorted_cmp :: proc(array: $T/[]$E, cmp: proc(i, j: E) -> Ordering) -> bool {
|
||||||
for i := len(array)-1; i > 0; i -= 1 {
|
for i := len(array)-1; i > 0; i -= 1 {
|
||||||
if cmp(array[i], array[i-1]) == .Equal {
|
if cmp(array[i], array[i-1]) == .Equal {
|
||||||
@@ -140,489 +162,10 @@ is_sorted_by_key :: proc(array: $T/[]$E, key: proc(E) -> $K) -> bool where ORD(K
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
_max_depth :: proc(n: int) -> int { // 2*ceil(log2(n+1))
|
_max_depth :: proc(n: int) -> (depth: int) { // 2*ceil(log2(n+1))
|
||||||
depth: int
|
|
||||||
for i := n; i > 0; i >>= 1 {
|
for i := n; i > 0; i >>= 1 {
|
||||||
depth += 1
|
depth += 1
|
||||||
}
|
}
|
||||||
return depth * 2
|
return depth * 2
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private)
|
|
||||||
_quick_sort :: proc(data: $T/[]$E, a, b, max_depth: int) where ORD(E) #no_bounds_check {
|
|
||||||
median3 :: proc(data: T, m1, m0, m2: int) #no_bounds_check {
|
|
||||||
if data[m1] < data[m0] {
|
|
||||||
swap(data, m1, m0)
|
|
||||||
}
|
|
||||||
if data[m2] < data[m1] {
|
|
||||||
swap(data, m2, m1)
|
|
||||||
if data[m1] < data[m0] {
|
|
||||||
swap(data, m1, m0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
do_pivot :: proc(data: T, lo, hi: int) -> (midlo, midhi: int) #no_bounds_check {
|
|
||||||
m := int(uint(lo+hi)>>1)
|
|
||||||
if hi-lo > 40 {
|
|
||||||
s := (hi-lo)/8
|
|
||||||
median3(data, lo, lo+s, lo+s*2)
|
|
||||||
median3(data, m, m-s, m+s)
|
|
||||||
median3(data, hi-1, hi-1-s, hi-1-s*2)
|
|
||||||
}
|
|
||||||
median3(data, lo, m, hi-1)
|
|
||||||
|
|
||||||
|
|
||||||
pivot := lo
|
|
||||||
a, c := lo+1, hi-1
|
|
||||||
|
|
||||||
for ; a < c && data[a] < data[pivot]; a += 1 {
|
|
||||||
}
|
|
||||||
b := a
|
|
||||||
|
|
||||||
for {
|
|
||||||
for ; b < c && !(data[pivot] < data[b]); b += 1 { // data[b] <= pivot
|
|
||||||
}
|
|
||||||
for ; b < c && data[pivot] < data[c-1]; c -=1 { // data[c-1] > pivot
|
|
||||||
}
|
|
||||||
if b >= c {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
swap(data, b, c-1)
|
|
||||||
b += 1
|
|
||||||
c -= 1
|
|
||||||
}
|
|
||||||
|
|
||||||
protect := hi-c < 5
|
|
||||||
if !protect && hi-c < (hi-lo)/4 {
|
|
||||||
dups := 0
|
|
||||||
if !(data[pivot] < data[hi-1]) {
|
|
||||||
swap(data, c, hi-1)
|
|
||||||
c += 1
|
|
||||||
dups += 1
|
|
||||||
}
|
|
||||||
if !(data[b-1] < data[pivot]) {
|
|
||||||
b -= 1
|
|
||||||
dups += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if !(data[m] < data[pivot]) {
|
|
||||||
swap(data, m, b-1)
|
|
||||||
b -= 1
|
|
||||||
dups += 1
|
|
||||||
}
|
|
||||||
protect = dups > 1
|
|
||||||
}
|
|
||||||
if protect {
|
|
||||||
for {
|
|
||||||
for ; a < b && !(data[b-1] < data[pivot]); b -= 1 {
|
|
||||||
}
|
|
||||||
for ; a < b && data[a] < data[pivot]; a += 1 {
|
|
||||||
}
|
|
||||||
if a >= b {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
swap(data, a, b-1)
|
|
||||||
a += 1
|
|
||||||
b -= 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
swap(data, pivot, b-1)
|
|
||||||
return b-1, c
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
a, b, max_depth := a, b, max_depth
|
|
||||||
|
|
||||||
if b-a > 12 { // only use shell sort for lengths <= 12
|
|
||||||
if max_depth == 0 {
|
|
||||||
_heap_sort(data, a, b)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
max_depth -= 1
|
|
||||||
mlo, mhi := do_pivot(data, a, b)
|
|
||||||
if mlo-a < b-mhi {
|
|
||||||
_quick_sort(data, a, mlo, max_depth)
|
|
||||||
a = mhi
|
|
||||||
} else {
|
|
||||||
_quick_sort(data, mhi, b, max_depth)
|
|
||||||
b = mlo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if b-a > 1 {
|
|
||||||
// Shell short with gap 6
|
|
||||||
for i in a+6..<b {
|
|
||||||
if data[i] < data[i-6] {
|
|
||||||
swap(data, i, i-6)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_insertion_sort(data, a, b)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
_insertion_sort :: proc(data: $T/[]$E, a, b: int) where ORD(E) #no_bounds_check {
|
|
||||||
for i in a+1..<b {
|
|
||||||
for j := i; j > a && data[j] < data[j-1]; j -= 1 {
|
|
||||||
swap(data, j, j-1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
_heap_sort :: proc(data: $T/[]$E, a, b: int) where ORD(E) #no_bounds_check {
|
|
||||||
sift_down :: proc(data: T, lo, hi, first: int) #no_bounds_check {
|
|
||||||
root := lo
|
|
||||||
for {
|
|
||||||
child := 2*root + 1
|
|
||||||
if child >= hi {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if child+1 < hi && data[first+child] < data[first+child+1] {
|
|
||||||
child += 1
|
|
||||||
}
|
|
||||||
if !(data[first+root] < data[first+child]) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
swap(data, first+root, first+child)
|
|
||||||
root = child
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
first, lo, hi := a, 0, b-a
|
|
||||||
|
|
||||||
for i := (hi-1)/2; i >= 0; i -= 1 {
|
|
||||||
sift_down(data, i, hi, first)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := hi-1; i >= 0; i -= 1 {
|
|
||||||
swap(data, first, first+i)
|
|
||||||
sift_down(data, lo, i, first)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
_quick_sort_less :: proc(data: $T/[]$E, a, b, max_depth: int, less: proc(i, j: E) -> bool) #no_bounds_check {
|
|
||||||
median3 :: proc(data: T, m1, m0, m2: int, less: proc(i, j: E) -> bool) #no_bounds_check {
|
|
||||||
if less(data[m1], data[m0]) {
|
|
||||||
swap(data, m1, m0)
|
|
||||||
}
|
|
||||||
if less(data[m2], data[m1]) {
|
|
||||||
swap(data, m2, m1)
|
|
||||||
if less(data[m1], data[m0]) {
|
|
||||||
swap(data, m1, m0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
do_pivot :: proc(data: T, lo, hi: int, less: proc(i, j: E) -> bool) -> (midlo, midhi: int) #no_bounds_check {
|
|
||||||
m := int(uint(lo+hi)>>1)
|
|
||||||
if hi-lo > 40 {
|
|
||||||
s := (hi-lo)/8
|
|
||||||
median3(data, lo, lo+s, lo+s*2, less)
|
|
||||||
median3(data, m, m-s, m+s, less)
|
|
||||||
median3(data, hi-1, hi-1-s, hi-1-s*2, less)
|
|
||||||
}
|
|
||||||
median3(data, lo, m, hi-1, less)
|
|
||||||
|
|
||||||
pivot := lo
|
|
||||||
a, c := lo+1, hi-1
|
|
||||||
|
|
||||||
for ; a < c && less(data[a], data[pivot]); a += 1 {
|
|
||||||
}
|
|
||||||
b := a
|
|
||||||
|
|
||||||
for {
|
|
||||||
for ; b < c && !less(data[pivot], data[b]); b += 1 { // data[b] <= pivot
|
|
||||||
}
|
|
||||||
for ; b < c && less(data[pivot], data[c-1]); c -=1 { // data[c-1] > pivot
|
|
||||||
}
|
|
||||||
if b >= c {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
swap(data, b, c-1)
|
|
||||||
b += 1
|
|
||||||
c -= 1
|
|
||||||
}
|
|
||||||
|
|
||||||
protect := hi-c < 5
|
|
||||||
if !protect && hi-c < (hi-lo)/4 {
|
|
||||||
dups := 0
|
|
||||||
if !less(data[pivot], data[hi-1]) {
|
|
||||||
swap(data, c, hi-1)
|
|
||||||
c += 1
|
|
||||||
dups += 1
|
|
||||||
}
|
|
||||||
if !less(data[b-1], data[pivot]) {
|
|
||||||
b -= 1
|
|
||||||
dups += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if !less(data[m], data[pivot]) {
|
|
||||||
swap(data, m, b-1)
|
|
||||||
b -= 1
|
|
||||||
dups += 1
|
|
||||||
}
|
|
||||||
protect = dups > 1
|
|
||||||
}
|
|
||||||
if protect {
|
|
||||||
for {
|
|
||||||
for ; a < b && !less(data[b-1], data[pivot]); b -= 1 {
|
|
||||||
}
|
|
||||||
for ; a < b && less(data[a], data[pivot]); a += 1 {
|
|
||||||
}
|
|
||||||
if a >= b {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
swap(data, a, b-1)
|
|
||||||
a += 1
|
|
||||||
b -= 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
swap(data, pivot, b-1)
|
|
||||||
return b-1, c
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
a, b, max_depth := a, b, max_depth
|
|
||||||
|
|
||||||
if b-a > 12 { // only use shell sort for lengths <= 12
|
|
||||||
if max_depth == 0 {
|
|
||||||
_heap_sort_less(data, a, b, less)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
max_depth -= 1
|
|
||||||
mlo, mhi := do_pivot(data, a, b, less)
|
|
||||||
if mlo-a < b-mhi {
|
|
||||||
_quick_sort_less(data, a, mlo, max_depth, less)
|
|
||||||
a = mhi
|
|
||||||
} else {
|
|
||||||
_quick_sort_less(data, mhi, b, max_depth, less)
|
|
||||||
b = mlo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if b-a > 1 {
|
|
||||||
// Shell short with gap 6
|
|
||||||
for i in a+6..<b {
|
|
||||||
if less(data[i], data[i-6]) {
|
|
||||||
swap(data, i, i-6)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_insertion_sort_less(data, a, b, less)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
_insertion_sort_less :: proc(data: $T/[]$E, a, b: int, less: proc(i, j: E) -> bool) #no_bounds_check {
|
|
||||||
for i in a+1..<b {
|
|
||||||
for j := i; j > a && less(data[j], data[j-1]); j -= 1 {
|
|
||||||
swap(data, j, j-1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
_heap_sort_less :: proc(data: $T/[]$E, a, b: int, less: proc(i, j: E) -> bool) #no_bounds_check {
|
|
||||||
sift_down :: proc(data: T, lo, hi, first: int, less: proc(i, j: E) -> bool) #no_bounds_check {
|
|
||||||
root := lo
|
|
||||||
for {
|
|
||||||
child := 2*root + 1
|
|
||||||
if child >= hi {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if child+1 < hi && less(data[first+child], data[first+child+1]) {
|
|
||||||
child += 1
|
|
||||||
}
|
|
||||||
if !less(data[first+root], data[first+child]) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
swap(data, first+root, first+child)
|
|
||||||
root = child
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
first, lo, hi := a, 0, b-a
|
|
||||||
|
|
||||||
for i := (hi-1)/2; i >= 0; i -= 1 {
|
|
||||||
sift_down(data, i, hi, first, less)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := hi-1; i >= 0; i -= 1 {
|
|
||||||
swap(data, first, first+i)
|
|
||||||
sift_down(data, lo, i, first, less)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
_quick_sort_cmp :: proc(data: $T/[]$E, a, b, max_depth: int, cmp: proc(i, j: E) -> Ordering) #no_bounds_check {
|
|
||||||
median3 :: proc(data: T, m1, m0, m2: int, cmp: proc(i, j: E) -> Ordering) #no_bounds_check {
|
|
||||||
if cmp(data[m1], data[m0]) == .Less {
|
|
||||||
swap(data, m1, m0)
|
|
||||||
}
|
|
||||||
if cmp(data[m2], data[m1]) == .Less {
|
|
||||||
swap(data, m2, m1)
|
|
||||||
if cmp(data[m1], data[m0]) == .Less {
|
|
||||||
swap(data, m1, m0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
do_pivot :: proc(data: T, lo, hi: int, cmp: proc(i, j: E) -> Ordering) -> (midlo, midhi: int) #no_bounds_check {
|
|
||||||
m := int(uint(lo+hi)>>1)
|
|
||||||
if hi-lo > 40 {
|
|
||||||
s := (hi-lo)/8
|
|
||||||
median3(data, lo, lo+s, lo+s*2, cmp)
|
|
||||||
median3(data, m, m-s, m+s, cmp)
|
|
||||||
median3(data, hi-1, hi-1-s, hi-1-s*2, cmp)
|
|
||||||
}
|
|
||||||
median3(data, lo, m, hi-1, cmp)
|
|
||||||
|
|
||||||
pivot := lo
|
|
||||||
a, c := lo+1, hi-1
|
|
||||||
|
|
||||||
for ; a < c && cmp(data[a], data[pivot]) == .Less; a += 1 {
|
|
||||||
}
|
|
||||||
b := a
|
|
||||||
|
|
||||||
for {
|
|
||||||
for ; b < c && cmp(data[pivot], data[b]) >= .Equal; b += 1 { // data[b] <= pivot
|
|
||||||
}
|
|
||||||
for ; b < c && cmp(data[pivot], data[c-1]) == .Less; c -=1 { // data[c-1] > pivot
|
|
||||||
}
|
|
||||||
if b >= c {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
swap(data, b, c-1)
|
|
||||||
b += 1
|
|
||||||
c -= 1
|
|
||||||
}
|
|
||||||
|
|
||||||
protect := hi-c < 5
|
|
||||||
if !protect && hi-c < (hi-lo)/4 {
|
|
||||||
dups := 0
|
|
||||||
if cmp(data[pivot], data[hi-1]) != .Less {
|
|
||||||
swap(data, c, hi-1)
|
|
||||||
c += 1
|
|
||||||
dups += 1
|
|
||||||
}
|
|
||||||
if cmp(data[b-1], data[pivot]) != .Less {
|
|
||||||
b -= 1
|
|
||||||
dups += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if cmp(data[m], data[pivot]) != .Less {
|
|
||||||
swap(data, m, b-1)
|
|
||||||
b -= 1
|
|
||||||
dups += 1
|
|
||||||
}
|
|
||||||
protect = dups > 1
|
|
||||||
}
|
|
||||||
if protect {
|
|
||||||
for {
|
|
||||||
for ; a < b && cmp(data[b-1], data[pivot]) >= .Equal; b -= 1 {
|
|
||||||
}
|
|
||||||
for ; a < b && cmp(data[a], data[pivot]) == .Less; a += 1 {
|
|
||||||
}
|
|
||||||
if a >= b {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
swap(data, a, b-1)
|
|
||||||
a += 1
|
|
||||||
b -= 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
swap(data, pivot, b-1)
|
|
||||||
return b-1, c
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
a, b, max_depth := a, b, max_depth
|
|
||||||
|
|
||||||
if b-a > 12 { // only use shell sort for lengths <= 12
|
|
||||||
if max_depth == 0 {
|
|
||||||
_heap_sort_cmp(data, a, b, cmp)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
max_depth -= 1
|
|
||||||
mlo, mhi := do_pivot(data, a, b, cmp)
|
|
||||||
if mlo-a < b-mhi {
|
|
||||||
_quick_sort_cmp(data, a, mlo, max_depth, cmp)
|
|
||||||
a = mhi
|
|
||||||
} else {
|
|
||||||
_quick_sort_cmp(data, mhi, b, max_depth, cmp)
|
|
||||||
b = mlo
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if b-a > 1 {
|
|
||||||
// Shell short with gap 6
|
|
||||||
for i in a+6..<b {
|
|
||||||
if cmp(data[i], data[i-6]) == .Less {
|
|
||||||
swap(data, i, i-6)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_insertion_sort_cmp(data, a, b, cmp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
_insertion_sort_cmp :: proc(data: $T/[]$E, a, b: int, cmp: proc(i, j: E) -> Ordering) #no_bounds_check {
|
|
||||||
for i in a+1..<b {
|
|
||||||
for j := i; j > a && cmp(data[j], data[j-1]) == .Less; j -= 1 {
|
|
||||||
swap(data, j, j-1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@(private)
|
|
||||||
_heap_sort_cmp :: proc(data: $T/[]$E, a, b: int, cmp: proc(i, j: E) -> Ordering) #no_bounds_check {
|
|
||||||
sift_down :: proc(data: T, lo, hi, first: int, cmp: proc(i, j: E) -> Ordering) #no_bounds_check {
|
|
||||||
root := lo
|
|
||||||
for {
|
|
||||||
child := 2*root + 1
|
|
||||||
if child >= hi {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if child+1 < hi && cmp(data[first+child], data[first+child+1]) == .Less {
|
|
||||||
child += 1
|
|
||||||
}
|
|
||||||
if cmp(data[first+root], data[first+child]) >= .Equal {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
swap(data, first+root, first+child)
|
|
||||||
root = child
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
first, lo, hi := a, 0, b-a
|
|
||||||
|
|
||||||
for i := (hi-1)/2; i >= 0; i -= 1 {
|
|
||||||
sift_down(data, i, hi, first, cmp)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := hi-1; i >= 0; i -= 1 {
|
|
||||||
swap(data, first, first+i)
|
|
||||||
sift_down(data, lo, i, first, cmp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,200 @@
|
|||||||
|
//+private
|
||||||
|
package slice
|
||||||
|
|
||||||
|
import "core:intrinsics"
|
||||||
|
_ :: intrinsics
|
||||||
|
|
||||||
|
ORD :: intrinsics.type_is_ordered
|
||||||
|
|
||||||
|
Sort_Kind :: enum {
|
||||||
|
Ordered,
|
||||||
|
Less,
|
||||||
|
Cmp,
|
||||||
|
}
|
||||||
|
|
||||||
|
_quick_sort_general :: proc(data: $T/[]$E, a, b, max_depth: int, call: $P, $KIND: Sort_Kind) where (ORD(E) && KIND == .Ordered) || (KIND != .Ordered) #no_bounds_check {
|
||||||
|
less :: #force_inline proc(a, b: E, call: P) -> bool {
|
||||||
|
when KIND == .Ordered {
|
||||||
|
return a < b
|
||||||
|
} else when KIND == .Less {
|
||||||
|
return call(a, b)
|
||||||
|
} else when KIND == .Cmp {
|
||||||
|
return call(a, b) == .Less
|
||||||
|
} else {
|
||||||
|
#panic("unhandled Sort_Kind")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
insertion_sort :: proc(data: $T/[]$E, a, b: int, call: P) #no_bounds_check {
|
||||||
|
for i in a+1..<b {
|
||||||
|
for j := i; j > a && less(data[j], data[j-1], call); j -= 1 {
|
||||||
|
swap(data, j, j-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
heap_sort :: proc(data: $T/[]$E, a, b: int, call: P) #no_bounds_check {
|
||||||
|
sift_down :: proc(data: T, lo, hi, first: int, call: P) #no_bounds_check {
|
||||||
|
root := lo
|
||||||
|
for {
|
||||||
|
child := 2*root + 1
|
||||||
|
if child >= hi {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if child+1 < hi && less(data[first+child], data[first+child+1], call) {
|
||||||
|
child += 1
|
||||||
|
}
|
||||||
|
if !less(data[first+root], data[first+child], call) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
swap(data, first+root, first+child)
|
||||||
|
root = child
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
first, lo, hi := a, 0, b-a
|
||||||
|
|
||||||
|
for i := (hi-1)/2; i >= 0; i -= 1 {
|
||||||
|
sift_down(data, i, hi, first, call)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := hi-1; i >= 0; i -= 1 {
|
||||||
|
swap(data, first, first+i)
|
||||||
|
sift_down(data, lo, i, first, call)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
median3 :: proc(data: T, m1, m0, m2: int, call: P) #no_bounds_check {
|
||||||
|
if less(data[m1], data[m0], call) {
|
||||||
|
swap(data, m1, m0)
|
||||||
|
}
|
||||||
|
if less(data[m2], data[m1], call) {
|
||||||
|
swap(data, m2, m1)
|
||||||
|
if less(data[m1], data[m0], call) {
|
||||||
|
swap(data, m1, m0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do_pivot :: proc(data: T, lo, hi: int, call: P) -> (midlo, midhi: int) #no_bounds_check {
|
||||||
|
m := int(uint(lo+hi)>>1)
|
||||||
|
if hi-lo > 40 {
|
||||||
|
s := (hi-lo)/8
|
||||||
|
median3(data, lo, lo+s, lo+s*2, call)
|
||||||
|
median3(data, m, m-s, m+s, call)
|
||||||
|
median3(data, hi-1, hi-1-s, hi-1-s*2, call)
|
||||||
|
}
|
||||||
|
median3(data, lo, m, hi-1, call)
|
||||||
|
|
||||||
|
pivot := lo
|
||||||
|
a, c := lo+1, hi-1
|
||||||
|
|
||||||
|
|
||||||
|
for ; a < c && less(data[a], data[pivot], call); a += 1 {
|
||||||
|
}
|
||||||
|
b := a
|
||||||
|
|
||||||
|
for {
|
||||||
|
for ; b < c && !less(data[pivot], data[b], call); b += 1 { // data[b] <= pivot
|
||||||
|
}
|
||||||
|
for ; b < c && less(data[pivot], data[c-1], call); c -=1 { // data[c-1] > pivot
|
||||||
|
}
|
||||||
|
if b >= c {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
swap(data, b, c-1)
|
||||||
|
b += 1
|
||||||
|
c -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
protect := hi-c < 5
|
||||||
|
if !protect && hi-c < (hi-lo)/4 {
|
||||||
|
dups := 0
|
||||||
|
if !less(data[pivot], data[hi-1], call) {
|
||||||
|
swap(data, c, hi-1)
|
||||||
|
c += 1
|
||||||
|
dups += 1
|
||||||
|
}
|
||||||
|
if !less(data[b-1], data[pivot], call) {
|
||||||
|
b -= 1
|
||||||
|
dups += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if !less(data[m], data[pivot], call) {
|
||||||
|
swap(data, m, b-1)
|
||||||
|
b -= 1
|
||||||
|
dups += 1
|
||||||
|
}
|
||||||
|
protect = dups > 1
|
||||||
|
}
|
||||||
|
if protect {
|
||||||
|
for {
|
||||||
|
for ; a < b && !less(data[b-1], data[pivot], call); b -= 1 {
|
||||||
|
}
|
||||||
|
for ; a < b && less(data[a], data[pivot], call); a += 1 {
|
||||||
|
}
|
||||||
|
if a >= b {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
swap(data, a, b-1)
|
||||||
|
a += 1
|
||||||
|
b -= 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
swap(data, pivot, b-1)
|
||||||
|
return b-1, c
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
a, b, max_depth := a, b, max_depth
|
||||||
|
|
||||||
|
if b-a > 12 { // only use shell sort for lengths <= 12
|
||||||
|
if max_depth == 0 {
|
||||||
|
heap_sort(data, a, b, call)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
max_depth -= 1
|
||||||
|
mlo, mhi := do_pivot(data, a, b, call)
|
||||||
|
if mlo-a < b-mhi {
|
||||||
|
_quick_sort_general(data, a, mlo, max_depth, call, KIND)
|
||||||
|
a = mhi
|
||||||
|
} else {
|
||||||
|
_quick_sort_general(data, mhi, b, max_depth, call, KIND)
|
||||||
|
b = mlo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if b-a > 1 {
|
||||||
|
// Shell short with gap 6
|
||||||
|
for i in a+6..<b {
|
||||||
|
if less(data[i], data[i-6], call) {
|
||||||
|
swap(data, i, i-6)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
insertion_sort(data, a, b, call)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// merge sort
|
||||||
|
_stable_sort_general :: proc(data: $T/[]$E, call: $P, $KIND: Sort_Kind) where (ORD(E) && KIND == .Ordered) || (KIND != .Ordered) #no_bounds_check {
|
||||||
|
less :: #force_inline proc(a, b: E, call: P) -> bool {
|
||||||
|
when KIND == .Ordered {
|
||||||
|
return a < b
|
||||||
|
} else when KIND == .Less {
|
||||||
|
return call(a, b)
|
||||||
|
} else when KIND == .Cmp {
|
||||||
|
return call(a, b) == .Less
|
||||||
|
} else {
|
||||||
|
#panic("unhandled Sort_Kind")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
n := len(data)
|
||||||
|
for i in 1..<n {
|
||||||
|
for j := i; j > 0 && less(data[j], data[j-1], call); j -= 1 {
|
||||||
|
swap(data, j, j-1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,9 @@ import "core:intrinsics"
|
|||||||
import "core:runtime"
|
import "core:runtime"
|
||||||
import "core:slice"
|
import "core:slice"
|
||||||
|
|
||||||
|
_ :: runtime
|
||||||
|
_ :: slice
|
||||||
|
|
||||||
map_entries_by_key :: proc(m: ^$M/map[$K]$V, loc := #caller_location) where intrinsics.type_is_ordered(K) {
|
map_entries_by_key :: proc(m: ^$M/map[$K]$V, loc := #caller_location) where intrinsics.type_is_ordered(K) {
|
||||||
Entry :: struct {
|
Entry :: struct {
|
||||||
hash: uintptr,
|
hash: uintptr,
|
||||||
|
|||||||
@@ -353,6 +353,76 @@ split_after_n_iterator :: proc(s: ^string, sep: string, n: int) -> (string, bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
_trim_cr :: proc(s: string) -> string {
|
||||||
|
n := len(s)
|
||||||
|
if n > 0 {
|
||||||
|
if s[n-1] == '\r' {
|
||||||
|
return s[:n-1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
split_lines :: proc(s: string, allocator := context.allocator) -> []string {
|
||||||
|
sep :: "\n"
|
||||||
|
lines := _split(s, sep, 0, -1, allocator)
|
||||||
|
for line in &lines {
|
||||||
|
line = _trim_cr(line)
|
||||||
|
}
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
split_lines_n :: proc(s: string, n: int, allocator := context.allocator) -> []string {
|
||||||
|
sep :: "\n"
|
||||||
|
lines := _split(s, sep, 0, n, allocator)
|
||||||
|
for line in &lines {
|
||||||
|
line = _trim_cr(line)
|
||||||
|
}
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
split_lines_after :: proc(s: string, allocator := context.allocator) -> []string {
|
||||||
|
sep :: "\n"
|
||||||
|
lines := _split(s, sep, len(sep), -1, allocator)
|
||||||
|
for line in &lines {
|
||||||
|
line = _trim_cr(line)
|
||||||
|
}
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
split_lines_after_n :: proc(s: string, n: int, allocator := context.allocator) -> []string {
|
||||||
|
sep :: "\n"
|
||||||
|
lines := _split(s, sep, len(sep), n, allocator)
|
||||||
|
for line in &lines {
|
||||||
|
line = _trim_cr(line)
|
||||||
|
}
|
||||||
|
return lines
|
||||||
|
}
|
||||||
|
|
||||||
|
split_lines_iterator :: proc(s: ^string) -> (line: string, ok: bool) {
|
||||||
|
sep :: "\n"
|
||||||
|
line = _split_iterator(s, sep, 0, -1) or_return
|
||||||
|
return _trim_cr(line), true
|
||||||
|
}
|
||||||
|
|
||||||
|
split_lines_n_iterator :: proc(s: ^string, n: int) -> (line: string, ok: bool) {
|
||||||
|
sep :: "\n"
|
||||||
|
line = _split_iterator(s, sep, 0, n) or_return
|
||||||
|
return _trim_cr(line), true
|
||||||
|
}
|
||||||
|
|
||||||
|
split_lines_after_iterator :: proc(s: ^string) -> (line: string, ok: bool) {
|
||||||
|
sep :: "\n"
|
||||||
|
line = _split_iterator(s, sep, len(sep), -1) or_return
|
||||||
|
return _trim_cr(line), true
|
||||||
|
}
|
||||||
|
|
||||||
|
split_lines_after_n_iterator :: proc(s: ^string, n: int) -> (line: string, ok: bool) {
|
||||||
|
sep :: "\n"
|
||||||
|
line = _split_iterator(s, sep, len(sep), n) or_return
|
||||||
|
return _trim_cr(line), true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+36
-37
@@ -1,44 +1,43 @@
|
|||||||
package sync
|
package sync
|
||||||
|
|
||||||
|
|
||||||
// A barrier enabling multiple threads to synchronize the beginning of some computation
|
|
||||||
/*
|
/*
|
||||||
* Example:
|
A barrier enabling multiple threads to synchronize the beginning of some computation
|
||||||
*
|
Example:
|
||||||
* package example
|
|
||||||
*
|
package example
|
||||||
* import "core:fmt"
|
|
||||||
* import "core:sync"
|
import "core:fmt"
|
||||||
* import "core:thread"
|
import "core:sync"
|
||||||
*
|
import "core:thread"
|
||||||
* barrier := &sync.Barrier{};
|
|
||||||
*
|
barrier := &sync.Barrier{};
|
||||||
* main :: proc() {
|
|
||||||
* fmt.println("Start");
|
main :: proc() {
|
||||||
*
|
fmt.println("Start");
|
||||||
* THREAD_COUNT :: 4;
|
|
||||||
* threads: [THREAD_COUNT]^thread.Thread;
|
THREAD_COUNT :: 4;
|
||||||
*
|
threads: [THREAD_COUNT]^thread.Thread;
|
||||||
* sync.barrier_init(barrier, THREAD_COUNT);
|
|
||||||
* defer sync.barrier_destroy(barrier);
|
sync.barrier_init(barrier, THREAD_COUNT);
|
||||||
*
|
defer sync.barrier_destroy(barrier);
|
||||||
*
|
|
||||||
* for _, i in threads {
|
|
||||||
* threads[i] = thread.create_and_start(proc(t: ^thread.Thread) {
|
for _, i in threads {
|
||||||
* // Same messages will be printed together but without any interleaving
|
threads[i] = thread.create_and_start(proc(t: ^thread.Thread) {
|
||||||
* fmt.println("Getting ready!");
|
// Same messages will be printed together but without any interleaving
|
||||||
* sync.barrier_wait(barrier);
|
fmt.println("Getting ready!");
|
||||||
* fmt.println("Off their marks they go!");
|
sync.barrier_wait(barrier);
|
||||||
* });
|
fmt.println("Off their marks they go!");
|
||||||
* }
|
});
|
||||||
*
|
}
|
||||||
* for t in threads {
|
|
||||||
* thread.destroy(t); // join and free thread
|
for t in threads {
|
||||||
* }
|
thread.destroy(t); // join and free thread
|
||||||
* fmt.println("Finished");
|
}
|
||||||
* }
|
fmt.println("Finished");
|
||||||
*
|
}
|
||||||
*/
|
*/
|
||||||
Barrier :: struct {
|
Barrier :: struct {
|
||||||
mutex: Blocking_Mutex,
|
mutex: Blocking_Mutex,
|
||||||
cond: Condition,
|
cond: Condition,
|
||||||
|
|||||||
@@ -67,44 +67,41 @@ wait_group_wait_with_timeout :: proc(wg: ^Wait_Group, duration: time.Duration) -
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
// A barrier enabling multiple threads to synchronize the beginning of some computation
|
|
||||||
/*
|
/*
|
||||||
* Example:
|
A barrier enabling multiple threads to synchronize the beginning of some computation
|
||||||
*
|
|
||||||
* package example
|
Example:
|
||||||
*
|
package example
|
||||||
* import "core:fmt"
|
|
||||||
* import "core:sync"
|
import "core:fmt"
|
||||||
* import "core:thread"
|
import "core:sync"
|
||||||
*
|
import "core:thread"
|
||||||
* barrier := &sync.Barrier{}
|
|
||||||
*
|
barrier := &sync.Barrier{}
|
||||||
* main :: proc() {
|
|
||||||
* fmt.println("Start")
|
main :: proc() {
|
||||||
*
|
fmt.println("Start")
|
||||||
* THREAD_COUNT :: 4
|
|
||||||
* threads: [THREAD_COUNT]^thread.Thread
|
THREAD_COUNT :: 4
|
||||||
*
|
threads: [THREAD_COUNT]^thread.Thread
|
||||||
* sync.barrier_init(barrier, THREAD_COUNT)
|
|
||||||
* defer sync.barrier_destroy(barrier)
|
sync.barrier_init(barrier, THREAD_COUNT)
|
||||||
*
|
|
||||||
*
|
for _, i in threads {
|
||||||
* for _, i in threads {
|
threads[i] = thread.create_and_start(proc(t: ^thread.Thread) {
|
||||||
* threads[i] = thread.create_and_start(proc(t: ^thread.Thread) {
|
// Same messages will be printed together but without any interleaving
|
||||||
* // Same messages will be printed together but without any interleaving
|
fmt.println("Getting ready!")
|
||||||
* fmt.println("Getting ready!")
|
sync.barrier_wait(barrier)
|
||||||
* sync.barrier_wait(barrier)
|
fmt.println("Off their marks they go!")
|
||||||
* fmt.println("Off their marks they go!")
|
})
|
||||||
* })
|
}
|
||||||
* }
|
|
||||||
*
|
for t in threads {
|
||||||
* for t in threads {
|
thread.destroy(t) // join and free thread
|
||||||
* thread.destroy(t) // join and free thread
|
}
|
||||||
* }
|
fmt.println("Finished")
|
||||||
* fmt.println("Finished")
|
}
|
||||||
* }
|
*/
|
||||||
*
|
|
||||||
*/
|
|
||||||
Barrier :: struct {
|
Barrier :: struct {
|
||||||
mutex: Mutex,
|
mutex: Mutex,
|
||||||
cond: Cond,
|
cond: Cond,
|
||||||
|
|||||||
@@ -29,12 +29,12 @@ mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
|||||||
return _mutex_try_lock(m)
|
return _mutex_try_lock(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example:
|
/*
|
||||||
//
|
Example:
|
||||||
// if mutex_guard(&m) {
|
if mutex_guard(&m) {
|
||||||
// ...
|
...
|
||||||
// }
|
}
|
||||||
//
|
*/
|
||||||
@(deferred_in=mutex_unlock)
|
@(deferred_in=mutex_unlock)
|
||||||
mutex_guard :: proc(m: ^Mutex) -> bool {
|
mutex_guard :: proc(m: ^Mutex) -> bool {
|
||||||
mutex_lock(m)
|
mutex_lock(m)
|
||||||
@@ -80,25 +80,24 @@ rw_mutex_shared_unlock :: proc(rw: ^RW_Mutex) {
|
|||||||
rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool {
|
rw_mutex_try_shared_lock :: proc(rw: ^RW_Mutex) -> bool {
|
||||||
return _rw_mutex_try_shared_lock(rw)
|
return _rw_mutex_try_shared_lock(rw)
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
// Example:
|
Example:
|
||||||
//
|
if rw_mutex_guard(&m) {
|
||||||
// if rw_mutex_guard(&m) {
|
...
|
||||||
// ...
|
}
|
||||||
// }
|
*/
|
||||||
//
|
|
||||||
@(deferred_in=rw_mutex_unlock)
|
@(deferred_in=rw_mutex_unlock)
|
||||||
rw_mutex_guard :: proc(m: ^RW_Mutex) -> bool {
|
rw_mutex_guard :: proc(m: ^RW_Mutex) -> bool {
|
||||||
rw_mutex_lock(m)
|
rw_mutex_lock(m)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example:
|
/*
|
||||||
//
|
Example:
|
||||||
// if rw_mutex_shared_guard(&m) {
|
if rw_mutex_shared_guard(&m) {
|
||||||
// ...
|
...
|
||||||
// }
|
}
|
||||||
//
|
*/
|
||||||
@(deferred_in=rw_mutex_shared_unlock)
|
@(deferred_in=rw_mutex_shared_unlock)
|
||||||
rw_mutex_shared_guard :: proc(m: ^RW_Mutex) -> bool {
|
rw_mutex_shared_guard :: proc(m: ^RW_Mutex) -> bool {
|
||||||
rw_mutex_shared_lock(m)
|
rw_mutex_shared_lock(m)
|
||||||
@@ -127,13 +126,12 @@ recursive_mutex_try_lock :: proc(m: ^Recursive_Mutex) -> bool {
|
|||||||
return _recursive_mutex_try_lock(m)
|
return _recursive_mutex_try_lock(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// Example:
|
Example:
|
||||||
//
|
if recursive_mutex_guard(&m) {
|
||||||
// if recursive_mutex_guard(&m) {
|
...
|
||||||
// ...
|
}
|
||||||
// }
|
*/
|
||||||
//
|
|
||||||
@(deferred_in=recursive_mutex_unlock)
|
@(deferred_in=recursive_mutex_unlock)
|
||||||
recursive_mutex_guard :: proc(m: ^Recursive_Mutex) -> bool {
|
recursive_mutex_guard :: proc(m: ^Recursive_Mutex) -> bool {
|
||||||
recursive_mutex_lock(m)
|
recursive_mutex_lock(m)
|
||||||
|
|||||||
@@ -82,13 +82,12 @@ atomic_mutex_try_lock :: proc(m: ^Atomic_Mutex) -> bool {
|
|||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// Example:
|
Example:
|
||||||
//
|
if atomic_mutex_guard(&m) {
|
||||||
// if atomic_mutex_guard(&m) {
|
...
|
||||||
// ...
|
}
|
||||||
// }
|
*/
|
||||||
//
|
|
||||||
@(deferred_in=atomic_mutex_unlock)
|
@(deferred_in=atomic_mutex_unlock)
|
||||||
atomic_mutex_guard :: proc(m: ^Atomic_Mutex) -> bool {
|
atomic_mutex_guard :: proc(m: ^Atomic_Mutex) -> bool {
|
||||||
atomic_mutex_lock(m)
|
atomic_mutex_lock(m)
|
||||||
@@ -193,25 +192,24 @@ atomic_rw_mutex_try_shared_lock :: proc(rw: ^Atomic_RW_Mutex) -> bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// Example:
|
Example:
|
||||||
//
|
if atomic_rw_mutex_guard(&m) {
|
||||||
// if atomic_rw_mutex_guard(&m) {
|
...
|
||||||
// ...
|
}
|
||||||
// }
|
*/
|
||||||
//
|
|
||||||
@(deferred_in=atomic_rw_mutex_unlock)
|
@(deferred_in=atomic_rw_mutex_unlock)
|
||||||
atomic_rw_mutex_guard :: proc(m: ^Atomic_RW_Mutex) -> bool {
|
atomic_rw_mutex_guard :: proc(m: ^Atomic_RW_Mutex) -> bool {
|
||||||
atomic_rw_mutex_lock(m)
|
atomic_rw_mutex_lock(m)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example:
|
/*
|
||||||
//
|
Example:
|
||||||
// if atomic_rw_mutex_shared_guard(&m) {
|
if atomic_rw_mutex_shared_guard(&m) {
|
||||||
// ...
|
...
|
||||||
// }
|
}
|
||||||
//
|
*/
|
||||||
@(deferred_in=atomic_rw_mutex_shared_unlock)
|
@(deferred_in=atomic_rw_mutex_shared_unlock)
|
||||||
atomic_rw_mutex_shared_guard :: proc(m: ^Atomic_RW_Mutex) -> bool {
|
atomic_rw_mutex_shared_guard :: proc(m: ^Atomic_RW_Mutex) -> bool {
|
||||||
atomic_rw_mutex_shared_lock(m)
|
atomic_rw_mutex_shared_lock(m)
|
||||||
@@ -270,13 +268,12 @@ atomic_recursive_mutex_try_lock :: proc(m: ^Atomic_Recursive_Mutex) -> bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
// Example:
|
Example:
|
||||||
//
|
if atomic_recursive_mutex_guard(&m) {
|
||||||
// if atomic_recursive_mutex_guard(&m) {
|
...
|
||||||
// ...
|
}
|
||||||
// }
|
*/
|
||||||
//
|
|
||||||
@(deferred_in=atomic_recursive_mutex_unlock)
|
@(deferred_in=atomic_recursive_mutex_unlock)
|
||||||
atomic_recursive_mutex_guard :: proc(m: ^Atomic_Recursive_Mutex) -> bool {
|
atomic_recursive_mutex_guard :: proc(m: ^Atomic_Recursive_Mutex) -> bool {
|
||||||
atomic_recursive_mutex_lock(m)
|
atomic_recursive_mutex_lock(m)
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user