misc changes

mostly added kt1l from watl exercise
This commit is contained in:
2025-08-07 10:53:35 -04:00
parent 3769413a50
commit 73bfdb63ea
12 changed files with 128 additions and 40 deletions

View File

@@ -4,6 +4,6 @@ djb8_hash_32 :: #force_inline proc "contextless" ( hash : ^u32, bytes : []byte )
for value in bytes do (hash^) = (( (hash^) << 8) + (hash^) ) + u32(value)
}
djb8_hash :: #force_inline proc "contextless" ( hash : ^u64, bytes : []byte ) {
hash64_djb8 :: #force_inline proc "contextless" ( hash : ^u64, bytes : []byte ) {
for value in bytes do (hash^) = (( (hash^) << 8) + (hash^) ) + u64(value)
}

View File

@@ -1,48 +1,72 @@
package grime
when (false) {
// Key Table 1-Layer Linear (KT1L)
KT1L_Slot :: struct($Type: typeid) {
key: u64,
value: Type,
KT1L_Use_TypeErased :: true
KT1L_Slot :: struct($KeyType, $ValueType: typeid) {
key: KeyType,
value: ValueType,
}
KT1L_Meta :: struct {
slot_size: uintptr,
kt_value_offset: uintptr,
type_width: uintptr,
type_name: string,
type: typeid,
}
kt1l_populate_slice_a2_Slice_Byte :: proc(kt: ^[]byte, backing: Allocator = context.allocator, values: []byte, num_values: int, m: KT1L_Meta) {
kt1l_64_populate_slice_a2_Slice_Byte :: proc(kt: ^[]byte, backing: Allocator, values: []byte, num_values: int, m: KT1L_Meta) {
assert(kt != nil)
if num_values == 0 { return }
table_size_bytes := num_values * int(m.slot_size)
err : AllocatorError
kt^, err = alloc_bytes(table_size_bytes, allocator = backing)
alloc_error: AllocatorError
kt^, alloc_error = alloc_bytes(table_size_bytes, allocator = backing)
assert(alloc_error == .None)
slice_assert(kt ^)
kt_raw : Raw_Slice = transmute(Raw_Slice) kt^
for cursor in 0 ..< cast(uintptr) num_values {
slot_offset := cursor * m.slot_size
slot_cursor := uintptr(kt_raw.data) + slot_offset
slot_key := cast(^u64) slot_cursor
slot_value := transmute([]byte) Raw_Slice { cast([^]byte) (slot_cursor + m.kt_value_offset), int(m.type_width)}
a2_offset := cursor * m.type_width * 2
a2_cursor := uintptr(& values[a2_offset])
a2_key := (transmute(^[]byte) a2_cursor) ^
a2_value := transmute([]byte) Raw_Slice { rawptr(a2_cursor + m.type_width), int(m.type_width) }
copy(slot_value, a2_value)
slot_key^ = 0; hash64_djb8(slot_key, a2_key)
kt_raw : SliceByte = transmute(SliceByte) kt^
for id in 0 ..< cast(uintptr) num_values {
slot_offset := id * m.slot_size // slot id
slot_cursor := kt_raw.data[slot_offset:] // slots[id] type: KT1L_<Type>
slot_key := cast(^u64) slot_cursor // slots[id].key type: U64
slot_value := slice(slot_cursor[m.kt_value_offset:], m.type_width) // slots[id].value type: <Type>
a2_offset := id * m.type_width * 2 // a2 entry id
a2_cursor := cursor(values)[a2_offset:] // a2_entries[id] type: A2_<Type>
a2_key := (transmute(^[]byte) a2_cursor) ^ // a2_entries[id].key type: <Type>
a2_value := slice(a2_cursor[m.type_width:], m.type_width) // a2_entries[id].value type: <Type>
copy(slot_value, a2_value) // slots[id].value = a2_entries[id].value
slot_key^ = 0; hash64_djb8(slot_key, a2_key) // slots[id].key = hash64_djb8(a2_entries[id].key)
}
kt_raw.len = num_values
}
kt1l_populate_slice_a2 :: proc($Type: typeid, kt: ^[]KT1L_Slot(Type), backing: AllocatorInfo, values: [][2]Type) {
assert(kt != nil)
values_bytes := transmute([]byte) Raw_Slice{data = raw_data(values), len = len(values) * size_of([2]Type)}
kt1l_populate_slice_a2_Slice_Byte(transmute(^[]byte) kt, backing, values_bytes, len(values), {
slot_size = size_of(KT1L_Slot(Type)),
kt_value_offset = offset_of(KT1L_Slot(Type), KT1L_Slot(Type).value),
type_width = size_of(Type),
type_name = #type_string(Type),
})
when KT1L_Use_TypeErased
{
kt1l_64_populate_slice_a2 :: proc(kt: ^[]KT1L_Slot(u64, $Type), values: [][2]Type, backing:= context.allocator) {
assert(kt != nil)
values_bytes := slice(transmute([^]u8) raw_data(values), len(values) * size_of([2]Type))
kt1l_64_populate_slice_a2_Slice_Byte(transmute(^[]byte) kt, backing, values_bytes, len(values), {
slot_size = size_of(KT1L_Slot(Type)),
kt_value_offset = offset_of(KT1L_Slot(Type), value),
type_width = size_of(Type),
type = Type,
})
}
}
else
{
kt1l_64_populate_slice_a2 :: proc(kt: ^[]KT1L_Slot(u64, $Type), values: [][2]Type, backing:= context.allocator) {
assert(kt != nil)
if len(values) == 0 { retrurn }
kt, alloc_error = make_slice([]KT1L_Slot(u64, Type), len(values), allocator = backing)
assert(alloc_error == .None)
slice_assert(kt)
for id in 0 ..< len(values) {
slot := & kt[id]
hash64_djb8(& slot.key, values[id][0])
slot.value = values[id][1]
}
}
}
// TODO(Ed): Move ot package mappings
kt1l_populate_slice_a2 :: proc {
kt1l_64_populate_slice_a2,
}

View File

@@ -2,17 +2,17 @@ package grime
import "base:runtime"
reload_array :: proc( self : ^[dynamic]$Type, allocator : Allocator ) {
reload_array :: proc(self: ^[dynamic]$Type, allocator: Allocator) {
raw := transmute( ^runtime.Raw_Dynamic_Array) self
raw.allocator = allocator
}
reload_queue :: proc( self : ^Queue($Type), allocator : Allocator ) {
reload_queue :: proc(self: ^Queue($Type), allocator: Allocator) {
raw_array := transmute( ^runtime.Raw_Dynamic_Array) self.data
raw_array.allocator = allocator
}
reload_map :: proc( self : ^map [$KeyType] $EntryType, allocator : Allocator ) {
reload_map :: proc(self: ^map [$KeyType] $EntryType, allocator: Allocator) {
raw := transmute( ^runtime.Raw_Map) self
raw.allocator = allocator
}

View File

@@ -99,3 +99,5 @@ swap :: #force_inline proc "contextless" ( a, b : ^ $Type ) -> ( ^ Type, ^ Type
to_bytes :: #force_inline proc "contextless" ( typed_block : ^$Type ) -> []byte {
return slice_ptr( transmute(^byte) typed_block, size_of(Type) )
}
ptr_cursor :: #force_inline proc "contextless" (ptr: ^$Type) -> [^]Type { return transmute([^]Type) ptr }

View File

@@ -6,10 +6,12 @@ import "base:builtin"
copy :: builtin.copy
import "base:intrinsics"
mem_zero :: intrinsics.mem_zero
ptr_sub :: intrinsics.ptr_sub
type_has_field :: intrinsics.type_has_field
type_elem_type :: intrinsics.type_elem_type
mem_zero :: intrinsics.mem_zero
mem_copy_non_overlapping :: intrinsics.mem_copy_non_overlapping
mem_copy :: intrinsics.mem_copy
ptr_sub :: intrinsics.ptr_sub
type_has_field :: intrinsics.type_has_field
type_elem_type :: intrinsics.type_elem_type
import "base:runtime"
Byte :: runtime.Byte
@@ -144,6 +146,12 @@ array_append_at :: proc {
array_append_at_value,
}
cursor :: proc {
ptr_cursor,
slice_cursor,
string_cursor,
}
is_power_of_two :: proc {
is_power_of_two_u32,
is_power_of_two_uintptr,

36
code/grime/slice.odin Normal file
View File

@@ -0,0 +1,36 @@
package grime
SliceByte :: struct {
data: [^]byte,
len: int
}
SliceRaw :: struct ($Type: typeid) {
data: [^]Type,
len: int,
}
slice :: #force_inline proc "contextless" (s: [^] $Type, num: $Some_Integer) -> [ ]Type { return transmute([]Type) SliceRaw(Type) { s, cast(int) num } }
slice_cursor :: #force_inline proc "contextless" (s: []$Type) -> [^]Type { return transmute([^]Type) raw_data(s) }
slice_assert :: #force_inline proc (s: $SliceType / []$Type) {
assert(len(s) > 0)
assert(s != nil)
}
slice_end :: #force_inline proc "contextless" (s : $SliceType / []$Type) -> ^Type { return & cursor(s)[len(s)] }
@(require_results) slice_to_bytes :: proc "contextless" (s: []$Type) -> []byte { return ([^]byte)(raw_data(s))[:len(s) * size_of(Type)] }
@(require_results) slice_raw :: proc "contextless" (s: []$Type) -> SliceRaw(Type) { return transmute(SliceRaw(Type)) s }
slice_zero :: proc "contextless" (data: $SliceType / []$Type) { memory_zero(raw_data(data), size_of(Type) * len(data)) }
slice_copy :: proc "contextless" (dst, src: $SliceType / []$Type) -> int {
n := max(0, min(len(dst), len(src)))
if n > 0 {
mem_copy(raw_data(dst), raw_data(src), n * size_of(Type))
}
return n
}
slice_copy_non_overlapping :: proc "contextless" (dst, src: $SliceType / []$Type) -> int {
n := max(0, min(len(dst), len(src)))
if n > 0 {
mem_copy_non_overlapping(raw_data(dst), raw_data(src), n * size_of(Type))
}
return n
}

10
code/grime/strings.odin Normal file
View File

@@ -0,0 +1,10 @@
package grime
Raw_String :: struct {
data: [^]byte,
len: int,
}
string_cursor :: proc(s: string) -> [^]u8 { return slice_cursor(transmute([]byte) s) }
string_copy :: proc(dst, src: string) { slice_copy (transmute([]byte) dst, transmute([]byte) src) }
string_end :: proc(s: string) -> ^u8 { return slice_end (transmute([]byte) s) }
string_assert :: proc(s: string) { slice_assert(transmute([]byte) s) }