From 84540d7aa2f69df6d9c62b53846751a11239dd76 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 15:57:27 +0000 Subject: [PATCH 01/29] Add `smoothstep` --- core/math/linalg/glsl/linalg_glsl.odin | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/core/math/linalg/glsl/linalg_glsl.odin b/core/math/linalg/glsl/linalg_glsl.odin index 9cce68149..6cec4b32d 100644 --- a/core/math/linalg/glsl/linalg_glsl.odin +++ b/core/math/linalg/glsl/linalg_glsl.odin @@ -769,6 +769,31 @@ step_dvec2 :: proc "c" (edge, x: dvec2) -> dvec2 { return {step(edge.x, x.x), st step_dvec3 :: proc "c" (edge, x: dvec3) -> dvec3 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z)} } step_dvec4 :: proc "c" (edge, x: dvec4) -> dvec4 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z), step(edge.w, x.w)} } +smoothstep :: proc{ + smoothstep_f32, + smoothstep_f64, + smoothstep_vec2, + smoothstep_vec3, + smoothstep_vec4, + smoothstep_dvec2, + smoothstep_dvec3, + smoothstep_dvec4, +} +smoothstep_f32 :: proc "c" (edge0, edge1, x: f32) -> f32 { + y := clamp(((x-edge0) / (edge1 - edge0)), 0, 1) + return y * y * (3 - 2*y) +} +smoothstep_f64 :: proc "c" (edge0, edge1, x: f64) -> f64 { + y := clamp(((x-edge0) / (edge1 - edge0)), 0, 1) + return y * y * (3 - 2*y) +} +smoothstep_vec2 :: proc "c" (edge0, edge1, x: vec2) -> vec2 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y)} } +smoothstep_vec3 :: proc "c" (edge0, edge1, x: vec3) -> vec3 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y), smoothstep(edge0.z, edge1.z, x.z)} } +smoothstep_vec4 :: proc "c" (edge0, edge1, x: vec4) -> vec4 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y), smoothstep(edge0.z, edge1.z, x.z), smoothstep(edge0.w, edge1.w, x.w)} } +smoothstep_dvec2 :: proc "c" (edge0, edge1, x: dvec2) -> dvec2 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y)} } +smoothstep_dvec3 :: proc "c" (edge0, edge1, x: dvec3) -> dvec3 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y), smoothstep(edge0.z, edge1.z, x.z)} } +smoothstep_dvec4 :: proc "c" (edge0, edge1, x: dvec4) -> dvec4 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y), smoothstep(edge0.z, edge1.z, x.z), smoothstep(edge0.w, edge1.w, x.w)} } + abs :: proc{ abs_i32, From d551144841f7dfd61e22e9dbed2b1b35d8736ffb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 16:09:19 +0000 Subject: [PATCH 02/29] Add inverse for dmatN types --- core/math/linalg/glsl/linalg_glsl.odin | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/core/math/linalg/glsl/linalg_glsl.odin b/core/math/linalg/glsl/linalg_glsl.odin index 6cec4b32d..3b4976452 100644 --- a/core/math/linalg/glsl/linalg_glsl.odin +++ b/core/math/linalg/glsl/linalg_glsl.odin @@ -1790,16 +1790,24 @@ dquatMulDvec3 :: proc "c" (q: dquat, v: dvec3) -> dvec3 { -inverse_mat2 :: proc "c" (m: mat2) -> mat2 { return builtin.inverse(m) } -inverse_mat3 :: proc "c" (m: mat3) -> mat3 { return builtin.inverse(m) } -inverse_mat4 :: proc "c" (m: mat4) -> mat4 { return builtin.inverse(m) } -inverse_quat :: proc "c" (q: quat) -> quat { return 1/q } +inverse_mat2 :: proc "c" (m: mat2) -> mat2 { return builtin.inverse(m) } +inverse_mat3 :: proc "c" (m: mat3) -> mat3 { return builtin.inverse(m) } +inverse_mat4 :: proc "c" (m: mat4) -> mat4 { return builtin.inverse(m) } +inverse_dmat2 :: proc "c" (m: dmat2) -> dmat2 { return builtin.inverse(m) } +inverse_dmat3 :: proc "c" (m: dmat3) -> dmat3 { return builtin.inverse(m) } +inverse_dmat4 :: proc "c" (m: dmat4) -> dmat4 { return builtin.inverse(m) } +inverse_quat :: proc "c" (q: quat) -> quat { return 1/q } +inverse_dquat :: proc "c" (q: dquat) -> dquat { return 1/q } inverse :: proc{ inverse_mat2, inverse_mat3, inverse_mat4, + inverse_dmat2, + inverse_dmat3, + inverse_dmat4, inverse_quat, + inverse_dquat, } transpose :: builtin.transpose From bc2bf1caeba5cca828318d1547e214f785e2d71a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 16:29:41 +0000 Subject: [PATCH 03/29] Add `#load_hash(, )` --- src/check_builtin.cpp | 145 ++++++++++++++++++++++++++++++++++++++++++ src/check_expr.cpp | 2 + 2 files changed, 147 insertions(+) diff --git a/src/check_builtin.cpp b/src/check_builtin.cpp index e405343b9..d910314fb 100644 --- a/src/check_builtin.cpp +++ b/src/check_builtin.cpp @@ -318,6 +318,151 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32 operand->mode = Addressing_Constant; operand->value = exact_value_string(result); + } else if (name == "load_hash") { + if (ce->args.count != 2) { + if (ce->args.count == 0) { + error(ce->close, "'#load_hash' expects 2 argument, got 0"); + } else { + error(ce->args[0], "'#load_hash' expects 2 argument, got %td", ce->args.count); + } + return false; + } + + Ast *arg0 = ce->args[0]; + Ast *arg1 = ce->args[1]; + Operand o = {}; + check_expr(c, &o, arg0); + if (o.mode != Addressing_Constant) { + error(arg0, "'#load_hash' expected a constant string argument"); + return false; + } + + if (!is_type_string(o.type)) { + gbString str = type_to_string(o.type); + error(arg0, "'#load_hash' expected a constant string, got %s", str); + gb_string_free(str); + return false; + } + + Operand o_hash = {}; + check_expr(c, &o_hash, arg1); + if (o_hash.mode != Addressing_Constant) { + error(arg1, "'#load_hash' expected a constant string argument"); + return false; + } + + if (!is_type_string(o_hash.type)) { + gbString str = type_to_string(o.type); + error(arg1, "'#load_hash' expected a constant string, got %s", str); + gb_string_free(str); + return false; + } + + + gbAllocator a = heap_allocator(); + + GB_ASSERT(o.value.kind == ExactValue_String); + GB_ASSERT(o_hash.value.kind == ExactValue_String); + + String base_dir = dir_from_path(get_file_path_string(bd->token.pos.file_id)); + String original_string = o.value.value_string; + String hash_kind = o_hash.value.value_string; + + String supported_hashes[] = { + str_lit("adler32"), + str_lit("crc32"), + str_lit("crc64"), + str_lit("fnv32"), + str_lit("fnv64"), + str_lit("fnv32a"), + str_lit("fnv64a"), + str_lit("murmur32"), + str_lit("murmur64"), + }; + + bool hash_found = false; + for (isize i = 0; i < gb_count_of(supported_hashes); i++) { + if (supported_hashes[i] == hash_kind) { + hash_found = true; + break; + } + } + if (!hash_found) { + ERROR_BLOCK(); + error(ce->proc, "Invalid hash kind passed to `#load_hash`, got: %.*s", LIT(hash_kind)); + error_line("\tAvailable hash kinds:\n"); + for (isize i = 0; i < gb_count_of(supported_hashes); i++) { + error_line("\t%.*s\n", LIT(supported_hashes[i])); + } + return false; + } + + + BlockingMutex *ignore_mutex = nullptr; + String path = {}; + bool ok = determine_path_from_string(ignore_mutex, call, base_dir, original_string, &path); + gb_unused(ok); + + char *c_str = alloc_cstring(a, path); + defer (gb_free(a, c_str)); + + + gbFile f = {}; + gbFileError file_err = gb_file_open(&f, c_str); + defer (gb_file_close(&f)); + + switch (file_err) { + default: + case gbFileError_Invalid: + error(ce->proc, "Failed to `#load_hash` file: %s; invalid file or cannot be found", c_str); + return false; + case gbFileError_NotExists: + error(ce->proc, "Failed to `#load_hash` file: %s; file cannot be found", c_str); + return false; + case gbFileError_Permission: + error(ce->proc, "Failed to `#load_hash` file: %s; file permissions problem", c_str); + return false; + case gbFileError_None: + // Okay + break; + } + + // TODO(bill): make these procedures fast :P + + u64 hash_value = 0; + String result = {}; + isize file_size = cast(isize)gb_file_size(&f); + if (file_size > 0) { + u8 *data = cast(u8 *)gb_alloc(a, file_size); + gb_file_read_at(&f, data, file_size, 0); + if (hash_kind == "adler32") { + hash_value = gb_adler32(data, file_size); + } else if (hash_kind == "crc32") { + hash_value = gb_crc32(data, file_size); + } else if (hash_kind == "crc64") { + hash_value = gb_crc64(data, file_size); + } else if (hash_kind == "fnv32") { + hash_value = gb_fnv32(data, file_size); + } else if (hash_kind == "fnv64") { + hash_value = gb_fnv64(data, file_size); + } else if (hash_kind == "fnv32a") { + hash_value = gb_fnv32a(data, file_size); + } else if (hash_kind == "fnv64a") { + hash_value = gb_fnv64a(data, file_size); + } else if (hash_kind == "murmur32") { + hash_value = gb_murmur32(data, file_size); + } else if (hash_kind == "murmur64") { + hash_value = gb_murmur64(data, file_size); + } else { + compiler_error("unhandled hash kind: %.*s", LIT(hash_kind)); + } + gb_free(a, data); + } + + operand->type = t_untyped_integer; + operand->mode = Addressing_Constant; + operand->value = exact_value_u64(hash_value); + } else if (name == "load_or") { if (ce->args.count != 2) { if (ce->args.count == 0) { diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 2139cd777..6c85ae43a 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -6108,6 +6108,7 @@ ExprKind check_call_expr(CheckerContext *c, Operand *operand, Ast *call, Ast *pr name == "defined" || name == "config" || name == "load" || + name == "load_hash" || name == "load_or" ) { operand->mode = Addressing_Builtin; @@ -6943,6 +6944,7 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type name == "defined" || name == "config" || name == "load" || + name == "load_hash" || name == "load_or" ) { error(node, "'#%.*s' must be used as a call", LIT(name)); From 68046d0c088d7acd90c8e0024b587d9e64ac06d2 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 16:50:59 +0000 Subject: [PATCH 04/29] Allow casting between matrix types of different element types --- src/check_expr.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 6c85ae43a..2ad3cc4a6 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -659,8 +659,8 @@ i64 check_distance_between_types(CheckerContext *c, Operand *operand, Type *type } if (is_type_matrix(dst)) { - Type *elem = base_array_type(dst); - i64 distance = check_distance_between_types(c, operand, elem); + Type *dst_elem = base_array_type(dst); + i64 distance = check_distance_between_types(c, operand, dst_elem); if (distance >= 0) { return distance + 7; } @@ -2467,7 +2467,9 @@ bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) { if (is_type_matrix(src) && is_type_matrix(dst)) { GB_ASSERT(src->kind == Type_Matrix); GB_ASSERT(dst->kind == Type_Matrix); - if (!are_types_identical(src->Matrix.elem, dst->Matrix.elem)) { + Operand op = *operand; + op.type = src->Matrix.elem; + if (!check_is_castable_to(c, &op, dst->Matrix.elem)) { return false; } @@ -2477,11 +2479,7 @@ bool check_is_castable_to(CheckerContext *c, Operand *operand, Type *y) { return src_count == dst_count; } - if (dst->Matrix.row_count != dst->Matrix.column_count) { - return false; - } - - return true; + return is_matrix_square(dst) && is_matrix_square(src); } From d8e34bd9b77c1e92e07f0e2bb9d9ff81fda28daa Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 17:08:59 +0000 Subject: [PATCH 05/29] Add `core:math/linalg/hlsl` --- core/math/linalg/hlsl/linalg_hlsl.odin | 1772 +++++++++++++++++++ core/math/linalg/hlsl/linalg_hlsl_math.odin | 69 + 2 files changed, 1841 insertions(+) create mode 100644 core/math/linalg/hlsl/linalg_hlsl.odin create mode 100644 core/math/linalg/hlsl/linalg_hlsl_math.odin diff --git a/core/math/linalg/hlsl/linalg_hlsl.odin b/core/math/linalg/hlsl/linalg_hlsl.odin new file mode 100644 index 000000000..0eb8413a9 --- /dev/null +++ b/core/math/linalg/hlsl/linalg_hlsl.odin @@ -0,0 +1,1772 @@ +// core:math/linalg/hlsl implements a HLSL-like mathematics library plus numerous other utility procedures +package math_linalg_hlsl + +import "core:builtin" + +TAU :: 6.28318530717958647692528676655900576 +PI :: 3.14159265358979323846264338327950288 +E :: 2.71828182845904523536 +τ :: TAU +π :: PI +e :: E + +SQRT_TWO :: 1.41421356237309504880168872420969808 +SQRT_THREE :: 1.73205080756887729352744634150587236 +SQRT_FIVE :: 2.23606797749978969640917366873127623 + +LN2 :: 0.693147180559945309417232121458176568 +LN10 :: 2.30258509299404568401799145468436421 + +FLOAT_EPSILON :: 1e-7 +DOUBLE_EPSILON :: 1e-15 + +// Aliases (not distinct) of types +float :: f32 +double :: f64 +int :: builtin.i32 +uint :: builtin.u32 + +// Odin matrices are stored internally as Column-Major, which matches the internal layout of HLSL by default +float1x1 :: distinct matrix[1, 1]float +float2x2 :: distinct matrix[2, 2]float +float3x3 :: distinct matrix[3, 3]float +float4x4 :: distinct matrix[4, 4]float + +float1x2 :: distinct matrix[1, 2]float +float1x3 :: distinct matrix[1, 3]float +float1x4 :: distinct matrix[1, 4]float +float2x1 :: distinct matrix[2, 1]float +float2x3 :: distinct matrix[2, 3]float +float2x4 :: distinct matrix[2, 4]float +float3x1 :: distinct matrix[3, 1]float +float3x2 :: distinct matrix[3, 2]float +float3x4 :: distinct matrix[3, 4]float +float4x1 :: distinct matrix[4, 1]float +float4x2 :: distinct matrix[4, 2]float +float4x3 :: distinct matrix[4, 3]float + +float2 :: distinct [2]float +float3 :: distinct [3]float +float4 :: distinct [4]float + +int2 :: distinct [2]int +int3 :: distinct [3]int +int4 :: distinct [4]int + +uint2 :: distinct [2]uint +uint3 :: distinct [3]uint +uint4 :: distinct [4]uint + +bool2 :: distinct [2]bool +bool3 :: distinct [3]bool +bool4 :: distinct [4]bool + +// Double Precision (double) Floating Point Types + +double1x1 :: distinct matrix[1, 1]double +double2x2 :: distinct matrix[2, 2]double +double3x3 :: distinct matrix[3, 3]double +double4x4 :: distinct matrix[4, 4]double + +double1x2 :: distinct matrix[1, 2]double +double1x3 :: distinct matrix[1, 3]double +double1x4 :: distinct matrix[1, 4]double +double2x1 :: distinct matrix[2, 1]double +double2x3 :: distinct matrix[2, 3]double +double2x4 :: distinct matrix[2, 4]double +double3x1 :: distinct matrix[3, 1]double +double3x2 :: distinct matrix[3, 2]double +double3x4 :: distinct matrix[3, 4]double +double4x1 :: distinct matrix[4, 1]double +double4x2 :: distinct matrix[4, 2]double +double4x3 :: distinct matrix[4, 3]double + +double2 :: distinct [2]double +double3 :: distinct [3]double +double4 :: distinct [4]double + + +int1x1 :: distinct matrix[1, 1]int +int2x2 :: distinct matrix[2, 2]int +int3x3 :: distinct matrix[3, 3]int +int4x4 :: distinct matrix[4, 4]int + +int1x2 :: distinct matrix[1, 2]int +int1x3 :: distinct matrix[1, 3]int +int1x4 :: distinct matrix[1, 4]int +int2x1 :: distinct matrix[2, 1]int +int2x3 :: distinct matrix[2, 3]int +int2x4 :: distinct matrix[2, 4]int +int3x1 :: distinct matrix[3, 1]int +int3x2 :: distinct matrix[3, 2]int +int3x4 :: distinct matrix[3, 4]int +int4x1 :: distinct matrix[4, 1]int +int4x2 :: distinct matrix[4, 2]int +int4x3 :: distinct matrix[4, 3]int + +cos :: proc{ + cos_float, + cos_double, + cos_float2, + cos_float3, + cos_float4, + cos_double2, + cos_double3, + cos_double4, +} +cos_float2 :: proc "c" (x: float2) -> float2 { return {cos(x.x), cos(x.y)} } +cos_float3 :: proc "c" (x: float3) -> float3 { return {cos(x.x), cos(x.y), cos(x.z)} } +cos_float4 :: proc "c" (x: float4) -> float4 { return {cos(x.x), cos(x.y), cos(x.z), cos(x.w)} } +cos_double2 :: proc "c" (x: double2) -> double2 { return {cos(x.x), cos(x.y)} } +cos_double3 :: proc "c" (x: double3) -> double3 { return {cos(x.x), cos(x.y), cos(x.z)} } +cos_double4 :: proc "c" (x: double4) -> double4 { return {cos(x.x), cos(x.y), cos(x.z), cos(x.w)} } + +sin :: proc{ + sin_float, + sin_double, + sin_float2, + sin_float3, + sin_float4, + sin_double2, + sin_double3, + sin_double4, +} +sin_float2 :: proc "c" (x: float2) -> float2 { return {sin(x.x), sin(x.y)} } +sin_float3 :: proc "c" (x: float3) -> float3 { return {sin(x.x), sin(x.y), sin(x.z)} } +sin_float4 :: proc "c" (x: float4) -> float4 { return {sin(x.x), sin(x.y), sin(x.z), sin(x.w)} } +sin_double2 :: proc "c" (x: double2) -> double2 { return {sin(x.x), sin(x.y)} } +sin_double3 :: proc "c" (x: double3) -> double3 { return {sin(x.x), sin(x.y), sin(x.z)} } +sin_double4 :: proc "c" (x: double4) -> double4 { return {sin(x.x), sin(x.y), sin(x.z), sin(x.w)} } + +tan :: proc{ + tan_float, + tan_double, + tan_float2, + tan_float3, + tan_float4, + tan_double2, + tan_double3, + tan_double4, +} +tan_float2 :: proc "c" (x: float2) -> float2 { return {tan(x.x), tan(x.y)} } +tan_float3 :: proc "c" (x: float3) -> float3 { return {tan(x.x), tan(x.y), tan(x.z)} } +tan_float4 :: proc "c" (x: float4) -> float4 { return {tan(x.x), tan(x.y), tan(x.z), tan(x.w)} } +tan_double2 :: proc "c" (x: double2) -> double2 { return {tan(x.x), tan(x.y)} } +tan_double3 :: proc "c" (x: double3) -> double3 { return {tan(x.x), tan(x.y), tan(x.z)} } +tan_double4 :: proc "c" (x: double4) -> double4 { return {tan(x.x), tan(x.y), tan(x.z), tan(x.w)} } + +acos :: proc{ + acos_float, + acos_double, + acos_float2, + acos_float3, + acos_float4, + acos_double2, + acos_double3, + acos_double4, +} +acos_float2 :: proc "c" (x: float2) -> float2 { return {acos(x.x), acos(x.y)} } +acos_float3 :: proc "c" (x: float3) -> float3 { return {acos(x.x), acos(x.y), acos(x.z)} } +acos_float4 :: proc "c" (x: float4) -> float4 { return {acos(x.x), acos(x.y), acos(x.z), acos(x.w)} } +acos_double2 :: proc "c" (x: double2) -> double2 { return {acos(x.x), acos(x.y)} } +acos_double3 :: proc "c" (x: double3) -> double3 { return {acos(x.x), acos(x.y), acos(x.z)} } +acos_double4 :: proc "c" (x: double4) -> double4 { return {acos(x.x), acos(x.y), acos(x.z), acos(x.w)} } + +asin :: proc{ + asin_float, + asin_double, + asin_float2, + asin_float3, + asin_float4, + asin_double2, + asin_double3, + asin_double4, +} +asin_float2 :: proc "c" (x: float2) -> float2 { return {asin(x.x), asin(x.y)} } +asin_float3 :: proc "c" (x: float3) -> float3 { return {asin(x.x), asin(x.y), asin(x.z)} } +asin_float4 :: proc "c" (x: float4) -> float4 { return {asin(x.x), asin(x.y), asin(x.z), asin(x.w)} } +asin_double2 :: proc "c" (x: double2) -> double2 { return {asin(x.x), asin(x.y)} } +asin_double3 :: proc "c" (x: double3) -> double3 { return {asin(x.x), asin(x.y), asin(x.z)} } +asin_double4 :: proc "c" (x: double4) -> double4 { return {asin(x.x), asin(x.y), asin(x.z), asin(x.w)} } + +atan :: proc{ + atan_float, + atan_double, + atan_float2, + atan_float3, + atan_float4, + atan_double2, + atan_double3, + atan_double4, + atan2_float, + atan2_double, + atan2_float2, + atan2_float3, + atan2_float4, + atan2_double2, + atan2_double3, + atan2_double4, +} +atan_float2 :: proc "c" (x: float2) -> float2 { return {atan(x.x), atan(x.y)} } +atan_float3 :: proc "c" (x: float3) -> float3 { return {atan(x.x), atan(x.y), atan(x.z)} } +atan_float4 :: proc "c" (x: float4) -> float4 { return {atan(x.x), atan(x.y), atan(x.z), atan(x.w)} } +atan_double2 :: proc "c" (x: double2) -> double2 { return {atan(x.x), atan(x.y)} } +atan_double3 :: proc "c" (x: double3) -> double3 { return {atan(x.x), atan(x.y), atan(x.z)} } +atan_double4 :: proc "c" (x: double4) -> double4 { return {atan(x.x), atan(x.y), atan(x.z), atan(x.w)} } + +atan2 :: proc{ + atan2_float, + atan2_double, + atan2_float2, + atan2_float3, + atan2_float4, + atan2_double2, + atan2_double3, + atan2_double4, +} +atan2_float2 :: proc "c" (y, x: float2) -> float2 { return {atan2(y.x, x.x), atan2(y.y, x.y)} } +atan2_float3 :: proc "c" (y, x: float3) -> float3 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z)} } +atan2_float4 :: proc "c" (y, x: float4) -> float4 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z), atan2(y.w, x.w)} } +atan2_double2 :: proc "c" (y, x: double2) -> double2 { return {atan2(y.x, x.x), atan2(y.y, x.y)} } +atan2_double3 :: proc "c" (y, x: double3) -> double3 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z)} } +atan2_double4 :: proc "c" (y, x: double4) -> double4 { return {atan2(y.x, x.x), atan2(y.y, x.y), atan2(y.z, x.z), atan2(y.w, x.w)} } + + + +cosh :: proc{ + cosh_float, + cosh_double, + cosh_float2, + cosh_float3, + cosh_float4, + cosh_double2, + cosh_double3, + cosh_double4, +} +cosh_float2 :: proc "c" (x: float2) -> float2 { return {cosh(x.x), cosh(x.y)} } +cosh_float3 :: proc "c" (x: float3) -> float3 { return {cosh(x.x), cosh(x.y), cosh(x.z)} } +cosh_float4 :: proc "c" (x: float4) -> float4 { return {cosh(x.x), cosh(x.y), cosh(x.z), cosh(x.w)} } +cosh_double2 :: proc "c" (x: double2) -> double2 { return {cosh(x.x), cosh(x.y)} } +cosh_double3 :: proc "c" (x: double3) -> double3 { return {cosh(x.x), cosh(x.y), cosh(x.z)} } +cosh_double4 :: proc "c" (x: double4) -> double4 { return {cosh(x.x), cosh(x.y), cosh(x.z), cosh(x.w)} } + + +sinh :: proc{ + sinh_float, + sinh_double, + sinh_float2, + sinh_float3, + sinh_float4, + sinh_double2, + sinh_double3, + sinh_double4, +} +sinh_float2 :: proc "c" (x: float2) -> float2 { return {sinh(x.x), sinh(x.y)} } +sinh_float3 :: proc "c" (x: float3) -> float3 { return {sinh(x.x), sinh(x.y), sinh(x.z)} } +sinh_float4 :: proc "c" (x: float4) -> float4 { return {sinh(x.x), sinh(x.y), sinh(x.z), sinh(x.w)} } +sinh_double2 :: proc "c" (x: double2) -> double2 { return {sinh(x.x), sinh(x.y)} } +sinh_double3 :: proc "c" (x: double3) -> double3 { return {sinh(x.x), sinh(x.y), sinh(x.z)} } +sinh_double4 :: proc "c" (x: double4) -> double4 { return {sinh(x.x), sinh(x.y), sinh(x.z), sinh(x.w)} } + +tanh :: proc{ + tanh_float, + tanh_double, + tanh_float2, + tanh_float3, + tanh_float4, + tanh_double2, + tanh_double3, + tanh_double4, +} +tanh_float2 :: proc "c" (x: float2) -> float2 { return {tanh(x.x), tanh(x.y)} } +tanh_float3 :: proc "c" (x: float3) -> float3 { return {tanh(x.x), tanh(x.y), tanh(x.z)} } +tanh_float4 :: proc "c" (x: float4) -> float4 { return {tanh(x.x), tanh(x.y), tanh(x.z), tanh(x.w)} } +tanh_double2 :: proc "c" (x: double2) -> double2 { return {tanh(x.x), tanh(x.y)} } +tanh_double3 :: proc "c" (x: double3) -> double3 { return {tanh(x.x), tanh(x.y), tanh(x.z)} } +tanh_double4 :: proc "c" (x: double4) -> double4 { return {tanh(x.x), tanh(x.y), tanh(x.z), tanh(x.w)} } + +acosh :: proc{ + acosh_float, + acosh_double, + acosh_float2, + acosh_float3, + acosh_float4, + acosh_double2, + acosh_double3, + acosh_double4, +} +acosh_float2 :: proc "c" (x: float2) -> float2 { return {acosh(x.x), acosh(x.y)} } +acosh_float3 :: proc "c" (x: float3) -> float3 { return {acosh(x.x), acosh(x.y), acosh(x.z)} } +acosh_float4 :: proc "c" (x: float4) -> float4 { return {acosh(x.x), acosh(x.y), acosh(x.z), acosh(x.w)} } +acosh_double2 :: proc "c" (x: double2) -> double2 { return {acosh(x.x), acosh(x.y)} } +acosh_double3 :: proc "c" (x: double3) -> double3 { return {acosh(x.x), acosh(x.y), acosh(x.z)} } +acosh_double4 :: proc "c" (x: double4) -> double4 { return {acosh(x.x), acosh(x.y), acosh(x.z), acosh(x.w)} } + +asinh :: proc{ + asinh_float, + asinh_double, + asinh_float2, + asinh_float3, + asinh_float4, + asinh_double2, + asinh_double3, + asinh_double4, +} +asinh_float2 :: proc "c" (x: float2) -> float2 { return {asinh(x.x), asinh(x.y)} } +asinh_float3 :: proc "c" (x: float3) -> float3 { return {asinh(x.x), asinh(x.y), asinh(x.z)} } +asinh_float4 :: proc "c" (x: float4) -> float4 { return {asinh(x.x), asinh(x.y), asinh(x.z), asinh(x.w)} } +asinh_double2 :: proc "c" (x: double2) -> double2 { return {asinh(x.x), asinh(x.y)} } +asinh_double3 :: proc "c" (x: double3) -> double3 { return {asinh(x.x), asinh(x.y), asinh(x.z)} } +asinh_double4 :: proc "c" (x: double4) -> double4 { return {asinh(x.x), asinh(x.y), asinh(x.z), asinh(x.w)} } + +atanh :: proc{ + atanh_float, + atanh_double, + atanh_float2, + atanh_float3, + atanh_float4, + atanh_double2, + atanh_double3, + atanh_double4, +} +atanh_float2 :: proc "c" (x: float2) -> float2 { return {atanh(x.x), atanh(x.y)} } +atanh_float3 :: proc "c" (x: float3) -> float3 { return {atanh(x.x), atanh(x.y), atanh(x.z)} } +atanh_float4 :: proc "c" (x: float4) -> float4 { return {atanh(x.x), atanh(x.y), atanh(x.z), atanh(x.w)} } +atanh_double2 :: proc "c" (x: double2) -> double2 { return {atanh(x.x), atanh(x.y)} } +atanh_double3 :: proc "c" (x: double3) -> double3 { return {atanh(x.x), atanh(x.y), atanh(x.z)} } +atanh_double4 :: proc "c" (x: double4) -> double4 { return {atanh(x.x), atanh(x.y), atanh(x.z), atanh(x.w)} } + +sqrt :: proc{ + sqrt_float, + sqrt_double, + sqrt_float2, + sqrt_float3, + sqrt_float4, + sqrt_double2, + sqrt_double3, + sqrt_double4, +} +sqrt_float2 :: proc "c" (x: float2) -> float2 { return {sqrt(x.x), sqrt(x.y)} } +sqrt_float3 :: proc "c" (x: float3) -> float3 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z)} } +sqrt_float4 :: proc "c" (x: float4) -> float4 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z), sqrt(x.w)} } +sqrt_double2 :: proc "c" (x: double2) -> double2 { return {sqrt(x.x), sqrt(x.y)} } +sqrt_double3 :: proc "c" (x: double3) -> double3 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z)} } +sqrt_double4 :: proc "c" (x: double4) -> double4 { return {sqrt(x.x), sqrt(x.y), sqrt(x.z), sqrt(x.w)} } + +rsqrt :: proc{ + rsqrt_float, + rsqrt_double, + rsqrt_float2, + rsqrt_float3, + rsqrt_float4, + rsqrt_double2, + rsqrt_double3, + rsqrt_double4, +} +rsqrt_float2 :: proc "c" (x: float2) -> float2 { return {rsqrt(x.x), rsqrt(x.y)} } +rsqrt_float3 :: proc "c" (x: float3) -> float3 { return {rsqrt(x.x), rsqrt(x.y), rsqrt(x.z)} } +rsqrt_float4 :: proc "c" (x: float4) -> float4 { return {rsqrt(x.x), rsqrt(x.y), rsqrt(x.z), rsqrt(x.w)} } +rsqrt_double2 :: proc "c" (x: double2) -> double2 { return {rsqrt(x.x), rsqrt(x.y)} } +rsqrt_double3 :: proc "c" (x: double3) -> double3 { return {rsqrt(x.x), rsqrt(x.y), rsqrt(x.z)} } +rsqrt_double4 :: proc "c" (x: double4) -> double4 { return {rsqrt(x.x), rsqrt(x.y), rsqrt(x.z), rsqrt(x.w)} } + +rcp :: proc{ + rcp_float, + rcp_double, + rcp_float2, + rcp_float3, + rcp_float4, + rcp_double2, + rcp_double3, + rcp_double4, +} +rcp_float2 :: proc "c" (x: float2) -> float2 { return {rcp(x.x), rcp(x.y)} } +rcp_float3 :: proc "c" (x: float3) -> float3 { return {rcp(x.x), rcp(x.y), rcp(x.z)} } +rcp_float4 :: proc "c" (x: float4) -> float4 { return {rcp(x.x), rcp(x.y), rcp(x.z), rcp(x.w)} } +rcp_double2 :: proc "c" (x: double2) -> double2 { return {rcp(x.x), rcp(x.y)} } +rcp_double3 :: proc "c" (x: double3) -> double3 { return {rcp(x.x), rcp(x.y), rcp(x.z)} } +rcp_double4 :: proc "c" (x: double4) -> double4 { return {rcp(x.x), rcp(x.y), rcp(x.z), rcp(x.w)} } + + +pow :: proc{ + pow_float, + pow_double, + pow_float2, + pow_float3, + pow_float4, + pow_double2, + pow_double3, + pow_double4, +} +pow_float2 :: proc "c" (x, y: float2) -> float2 { return {pow(x.x, y.x), pow(x.y, y.y)} } +pow_float3 :: proc "c" (x, y: float3) -> float3 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z)} } +pow_float4 :: proc "c" (x, y: float4) -> float4 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z), pow(x.w, y.w)} } +pow_double2 :: proc "c" (x, y: double2) -> double2 { return {pow(x.x, y.x), pow(x.y, y.y)} } +pow_double3 :: proc "c" (x, y: double3) -> double3 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z)} } +pow_double4 :: proc "c" (x, y: double4) -> double4 { return {pow(x.x, y.x), pow(x.y, y.y), pow(x.z, y.z), pow(x.w, y.w)} } + + + +exp :: proc{ + exp_float, + exp_double, + exp_float2, + exp_float3, + exp_float4, + exp_double2, + exp_double3, + exp_double4, +} +exp_float2 :: proc "c" (x: float2) -> float2 { return {exp(x.x), exp(x.y)} } +exp_float3 :: proc "c" (x: float3) -> float3 { return {exp(x.x), exp(x.y), exp(x.z)} } +exp_float4 :: proc "c" (x: float4) -> float4 { return {exp(x.x), exp(x.y), exp(x.z), exp(x.w)} } +exp_double2 :: proc "c" (x: double2) -> double2 { return {exp(x.x), exp(x.y)} } +exp_double3 :: proc "c" (x: double3) -> double3 { return {exp(x.x), exp(x.y), exp(x.z)} } +exp_double4 :: proc "c" (x: double4) -> double4 { return {exp(x.x), exp(x.y), exp(x.z), exp(x.w)} } + + + +log :: proc{ + log_float, + log_double, + log_float2, + log_float3, + log_float4, + log_double2, + log_double3, + log_double4, +} +log_float2 :: proc "c" (x: float2) -> float2 { return {log(x.x), log(x.y)} } +log_float3 :: proc "c" (x: float3) -> float3 { return {log(x.x), log(x.y), log(x.z)} } +log_float4 :: proc "c" (x: float4) -> float4 { return {log(x.x), log(x.y), log(x.z), log(x.w)} } +log_double2 :: proc "c" (x: double2) -> double2 { return {log(x.x), log(x.y)} } +log_double3 :: proc "c" (x: double3) -> double3 { return {log(x.x), log(x.y), log(x.z)} } +log_double4 :: proc "c" (x: double4) -> double4 { return {log(x.x), log(x.y), log(x.z), log(x.w)} } + + +log2 :: proc{ + log2_float, + log2_double, + log2_float2, + log2_float3, + log2_float4, + log2_double2, + log2_double3, + log2_double4, +} +log2_float2 :: proc "c" (x: float2) -> float2 { return {log2(x.x), log2(x.y)} } +log2_float3 :: proc "c" (x: float3) -> float3 { return {log2(x.x), log2(x.y), log2(x.z)} } +log2_float4 :: proc "c" (x: float4) -> float4 { return {log2(x.x), log2(x.y), log2(x.z), log2(x.w)} } +log2_double2 :: proc "c" (x: double2) -> double2 { return {log2(x.x), log2(x.y)} } +log2_double3 :: proc "c" (x: double3) -> double3 { return {log2(x.x), log2(x.y), log2(x.z)} } +log2_double4 :: proc "c" (x: double4) -> double4 { return {log2(x.x), log2(x.y), log2(x.z), log2(x.w)} } + + + +log10 :: proc{ + log10_float, + log10_double, + log10_float2, + log10_float3, + log10_float4, + log10_double2, + log10_double3, + log10_double4, +} +log10_float2 :: proc "c" (x: float2) -> float2 { return {log10(x.x), log10(x.y)} } +log10_float3 :: proc "c" (x: float3) -> float3 { return {log10(x.x), log10(x.y), log10(x.z)} } +log10_float4 :: proc "c" (x: float4) -> float4 { return {log10(x.x), log10(x.y), log10(x.z), log10(x.w)} } +log10_double2 :: proc "c" (x: double2) -> double2 { return {log10(x.x), log10(x.y)} } +log10_double3 :: proc "c" (x: double3) -> double3 { return {log10(x.x), log10(x.y), log10(x.z)} } +log10_double4 :: proc "c" (x: double4) -> double4 { return {log10(x.x), log10(x.y), log10(x.z), log10(x.w)} } + + + + +exp2 :: proc{ + exp2_float, + exp2_double, + exp2_float2, + exp2_float3, + exp2_float4, + exp2_double2, + exp2_double3, + exp2_double4, +} +exp2_float2 :: proc "c" (x: float2) -> float2 { return {exp2(x.x), exp2(x.y)} } +exp2_float3 :: proc "c" (x: float3) -> float3 { return {exp2(x.x), exp2(x.y), exp2(x.z)} } +exp2_float4 :: proc "c" (x: float4) -> float4 { return {exp2(x.x), exp2(x.y), exp2(x.z), exp2(x.w)} } +exp2_double2 :: proc "c" (x: double2) -> double2 { return {exp2(x.x), exp2(x.y)} } +exp2_double3 :: proc "c" (x: double3) -> double3 { return {exp2(x.x), exp2(x.y), exp2(x.z)} } +exp2_double4 :: proc "c" (x: double4) -> double4 { return {exp2(x.x), exp2(x.y), exp2(x.z), exp2(x.w)} } + + +sign :: proc{ + sign_int, + sign_uint, + sign_float, + sign_double, + sign_float2, + sign_float3, + sign_float4, + sign_double2, + sign_double3, + sign_double4, + sign_int2, + sign_int3, + sign_int4, + sign_uint2, + sign_uint3, + sign_uint4, +} +sign_int :: proc "c" (x: int) -> int { return -1 if x < 0 else +1 if x > 0 else 0 } +sign_uint :: proc "c" (x: uint) -> uint { return +1 if x > 0 else 0 } +sign_float2 :: proc "c" (x: float2) -> float2 { return {sign(x.x), sign(x.y)} } +sign_float3 :: proc "c" (x: float3) -> float3 { return {sign(x.x), sign(x.y), sign(x.z)} } +sign_float4 :: proc "c" (x: float4) -> float4 { return {sign(x.x), sign(x.y), sign(x.z), sign(x.w)} } +sign_double2 :: proc "c" (x: double2) -> double2 { return {sign(x.x), sign(x.y)} } +sign_double3 :: proc "c" (x: double3) -> double3 { return {sign(x.x), sign(x.y), sign(x.z)} } +sign_double4 :: proc "c" (x: double4) -> double4 { return {sign(x.x), sign(x.y), sign(x.z), sign(x.w)} } +sign_int2 :: proc "c" (x: int2) -> int2 { return {sign(x.x), sign(x.y)} } +sign_int3 :: proc "c" (x: int3) -> int3 { return {sign(x.x), sign(x.y), sign(x.z)} } +sign_int4 :: proc "c" (x: int4) -> int4 { return {sign(x.x), sign(x.y), sign(x.z), sign(x.w)} } +sign_uint2 :: proc "c" (x: uint2) -> uint2 { return {sign(x.x), sign(x.y)} } +sign_uint3 :: proc "c" (x: uint3) -> uint3 { return {sign(x.x), sign(x.y), sign(x.z)} } +sign_uint4 :: proc "c" (x: uint4) -> uint4 { return {sign(x.x), sign(x.y), sign(x.z), sign(x.w)} } + +floor :: proc{ + floor_float, + floor_double, + floor_float2, + floor_float3, + floor_float4, + floor_double2, + floor_double3, + floor_double4, +} +floor_float2 :: proc "c" (x: float2) -> float2 { return {floor(x.x), floor(x.y)} } +floor_float3 :: proc "c" (x: float3) -> float3 { return {floor(x.x), floor(x.y), floor(x.z)} } +floor_float4 :: proc "c" (x: float4) -> float4 { return {floor(x.x), floor(x.y), floor(x.z), floor(x.w)} } +floor_double2 :: proc "c" (x: double2) -> double2 { return {floor(x.x), floor(x.y)} } +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)} } + + +ceil :: proc{ + ceil_float, + ceil_double, + ceil_float2, + ceil_float3, + ceil_float4, + ceil_double2, + ceil_double3, + ceil_double4, +} +ceil_float2 :: proc "c" (x: float2) -> float2 { return {ceil(x.x), ceil(x.y)} } +ceil_float3 :: proc "c" (x: float3) -> float3 { return {ceil(x.x), ceil(x.y), ceil(x.z)} } +ceil_float4 :: proc "c" (x: float4) -> float4 { return {ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w)} } +ceil_double2 :: proc "c" (x: double2) -> double2 { return {ceil(x.x), ceil(x.y)} } +ceil_double3 :: proc "c" (x: double3) -> double3 { return {ceil(x.x), ceil(x.y), ceil(x.z)} } +ceil_double4 :: proc "c" (x: double4) -> double4 { return {ceil(x.x), ceil(x.y), ceil(x.z), ceil(x.w)} } + + +fmod :: proc{ + fmod_float, + fmod_double, + fmod_float2, + fmod_float3, + fmod_float4, + fmod_double2, + fmod_double3, + fmod_double4, +} +fmod_float2 :: proc "c" (x, y: float2) -> float2 { return {fmod(x.x, y.x), fmod(x.y, y.y)} } +fmod_float3 :: proc "c" (x, y: float3) -> float3 { return {fmod(x.x, y.x), fmod(x.y, y.y), fmod(x.z, y.z)} } +fmod_float4 :: proc "c" (x, y: float4) -> float4 { return {fmod(x.x, y.x), fmod(x.y, y.y), fmod(x.z, y.z), fmod(x.w, y.w)} } +fmod_double2 :: proc "c" (x, y: double2) -> double2 { return {fmod(x.x, y.x), fmod(x.y, y.y)} } +fmod_double3 :: proc "c" (x, y: double3) -> double3 { return {fmod(x.x, y.x), fmod(x.y, y.y), fmod(x.z, y.z)} } +fmod_double4 :: proc "c" (x, y: double4) -> double4 { return {fmod(x.x, y.x), fmod(x.y, y.y), fmod(x.z, y.z), fmod(x.w, y.w)} } + + +frac :: proc{ + frac_float, + frac_double, + frac_float2, + frac_float3, + frac_float4, + frac_double2, + frac_double3, + frac_double4, +} +frac_float2 :: proc "c" (x: float2) -> float2 { return {frac(x.x), frac(x.y)} } +frac_float3 :: proc "c" (x: float3) -> float3 { return {frac(x.x), frac(x.y), frac(x.z)} } +frac_float4 :: proc "c" (x: float4) -> float4 { return {frac(x.x), frac(x.y), frac(x.z), frac(x.w)} } +frac_double2 :: proc "c" (x: double2) -> double2 { return {frac(x.x), frac(x.y)} } +frac_double3 :: proc "c" (x: double3) -> double3 { return {frac(x.x), frac(x.y), frac(x.z)} } +frac_double4 :: proc "c" (x: double4) -> double4 { return {frac(x.x), frac(x.y), frac(x.z), frac(x.w)} } + + + +radians :: proc{ + radians_float, + radians_double, + radians_float2, + radians_float3, + radians_float4, + radians_double2, + radians_double3, + radians_double4, +} +radians_float :: proc "c" (degrees: float) -> float { return degrees * TAU / 360.0 } +radians_double :: proc "c" (degrees: double) -> double { return degrees * TAU / 360.0 } +radians_float2 :: proc "c" (degrees: float2) -> float2 { return degrees * TAU / 360.0 } +radians_float3 :: proc "c" (degrees: float3) -> float3 { return degrees * TAU / 360.0 } +radians_float4 :: proc "c" (degrees: float4) -> float4 { return degrees * TAU / 360.0 } +radians_double2 :: proc "c" (degrees: double2) -> double2 { return degrees * TAU / 360.0 } +radians_double3 :: proc "c" (degrees: double3) -> double3 { return degrees * TAU / 360.0 } +radians_double4 :: proc "c" (degrees: double4) -> double4 { return degrees * TAU / 360.0 } + + +degrees :: proc{ + degrees_float, + degrees_double, + degrees_float2, + degrees_float3, + degrees_float4, + degrees_double2, + degrees_double3, + degrees_double4, +} +degrees_float :: proc "c" (radians: float) -> float { return radians * 360.0 / TAU } +degrees_double :: proc "c" (radians: double) -> double { return radians * 360.0 / TAU } +degrees_float2 :: proc "c" (radians: float2) -> float2 { return radians * 360.0 / TAU } +degrees_float3 :: proc "c" (radians: float3) -> float3 { return radians * 360.0 / TAU } +degrees_float4 :: proc "c" (radians: float4) -> float4 { return radians * 360.0 / TAU } +degrees_double2 :: proc "c" (radians: double2) -> double2 { return radians * 360.0 / TAU } +degrees_double3 :: proc "c" (radians: double3) -> double3 { return radians * 360.0 / TAU } +degrees_double4 :: proc "c" (radians: double4) -> double4 { return radians * 360.0 / TAU } + +min :: proc{ + min_int, + min_uint, + min_float, + min_double, + min_float2, + min_float3, + min_float4, + min_double2, + min_double3, + min_double4, + min_int2, + min_int3, + min_int4, + min_uint2, + min_uint3, + min_uint4, +} +min_int :: proc "c" (x, y: int) -> int { return builtin.min(x, y) } +min_uint :: proc "c" (x, y: uint) -> uint { return builtin.min(x, y) } +min_float :: proc "c" (x, y: float) -> float { return builtin.min(x, y) } +min_double :: proc "c" (x, y: double) -> double { return builtin.min(x, y) } +min_float2 :: proc "c" (x, y: float2) -> float2 { return {min(x.x, y.x), min(x.y, y.y)} } +min_float3 :: proc "c" (x, y: float3) -> float3 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z)} } +min_float4 :: proc "c" (x, y: float4) -> float4 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z), min(x.w, y.w)} } +min_double2 :: proc "c" (x, y: double2) -> double2 { return {min(x.x, y.x), min(x.y, y.y)} } +min_double3 :: proc "c" (x, y: double3) -> double3 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z)} } +min_double4 :: proc "c" (x, y: double4) -> double4 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z), min(x.w, y.w)} } +min_int2 :: proc "c" (x, y: int2) -> int2 { return {min(x.x, y.x), min(x.y, y.y)} } +min_int3 :: proc "c" (x, y: int3) -> int3 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z)} } +min_int4 :: proc "c" (x, y: int4) -> int4 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z), min(x.w, y.w)} } +min_uint2 :: proc "c" (x, y: uint2) -> uint2 { return {min(x.x, y.x), min(x.y, y.y)} } +min_uint3 :: proc "c" (x, y: uint3) -> uint3 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z)} } +min_uint4 :: proc "c" (x, y: uint4) -> uint4 { return {min(x.x, y.x), min(x.y, y.y), min(x.z, y.z), min(x.w, y.w)} } + + +max :: proc{ + max_int, + max_uint, + max_float, + max_double, + max_float2, + max_float3, + max_float4, + max_double2, + max_double3, + max_double4, + max_int2, + max_int3, + max_int4, + max_uint2, + max_uint3, + max_uint4, +} +max_int :: proc "c" (x, y: int) -> int { return builtin.max(x, y) } +max_uint :: proc "c" (x, y: uint) -> uint { return builtin.max(x, y) } +max_float :: proc "c" (x, y: float) -> float { return builtin.max(x, y) } +max_double :: proc "c" (x, y: double) -> double { return builtin.max(x, y) } +max_float2 :: proc "c" (x, y: float2) -> float2 { return {max(x.x, y.x), max(x.y, y.y)} } +max_float3 :: proc "c" (x, y: float3) -> float3 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z)} } +max_float4 :: proc "c" (x, y: float4) -> float4 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z), max(x.w, y.w)} } +max_double2 :: proc "c" (x, y: double2) -> double2 { return {max(x.x, y.x), max(x.y, y.y)} } +max_double3 :: proc "c" (x, y: double3) -> double3 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z)} } +max_double4 :: proc "c" (x, y: double4) -> double4 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z), max(x.w, y.w)} } +max_int2 :: proc "c" (x, y: int2) -> int2 { return {max(x.x, y.x), max(x.y, y.y)} } +max_int3 :: proc "c" (x, y: int3) -> int3 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z)} } +max_int4 :: proc "c" (x, y: int4) -> int4 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z), max(x.w, y.w)} } +max_uint2 :: proc "c" (x, y: uint2) -> uint2 { return {max(x.x, y.x), max(x.y, y.y)} } +max_uint3 :: proc "c" (x, y: uint3) -> uint3 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z)} } +max_uint4 :: proc "c" (x, y: uint4) -> uint4 { return {max(x.x, y.x), max(x.y, y.y), max(x.z, y.z), max(x.w, y.w)} } + + + +clamp :: proc{ + clamp_int, + clamp_uint, + clamp_float, + clamp_double, + clamp_float2, + clamp_float3, + clamp_float4, + clamp_double2, + clamp_double3, + clamp_double4, + clamp_int2, + clamp_int3, + clamp_int4, + clamp_uint2, + clamp_uint3, + clamp_uint4, +} +clamp_int :: proc "c" (x, y, z: int) -> int { return builtin.clamp(x, y, z) } +clamp_uint :: proc "c" (x, y, z: uint) -> uint { return builtin.clamp(x, y, z) } +clamp_float :: proc "c" (x, y, z: float) -> float { return builtin.clamp(x, y, z) } +clamp_double :: proc "c" (x, y, z: double) -> double { return builtin.clamp(x, y, z) } +clamp_float2 :: proc "c" (x, y, z: float2) -> float2 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y)} } +clamp_float3 :: proc "c" (x, y, z: float3) -> float3 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z)} } +clamp_float4 :: proc "c" (x, y, z: float4) -> float4 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z), clamp(x.w, y.w, z.w)} } +clamp_double2 :: proc "c" (x, y, z: double2) -> double2 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y)} } +clamp_double3 :: proc "c" (x, y, z: double3) -> double3 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z)} } +clamp_double4 :: proc "c" (x, y, z: double4) -> double4 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z), clamp(x.w, y.w, z.w)} } +clamp_int2 :: proc "c" (x, y, z: int2) -> int2 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y)} } +clamp_int3 :: proc "c" (x, y, z: int3) -> int3 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z)} } +clamp_int4 :: proc "c" (x, y, z: int4) -> int4 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z), clamp(x.w, y.w, z.w)} } +clamp_uint2 :: proc "c" (x, y, z: uint2) -> uint2 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y)} } +clamp_uint3 :: proc "c" (x, y, z: uint3) -> uint3 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z)} } +clamp_uint4 :: proc "c" (x, y, z: uint4) -> uint4 { return {clamp(x.x, y.x, z.x), clamp(x.y, y.y, z.y), clamp(x.z, y.z, z.z), clamp(x.w, y.w, z.w)} } + +saturate :: proc{ + saturate_int, + saturate_uint, + saturate_float, + saturate_double, + saturate_float2, + saturate_float3, + saturate_float4, + saturate_double2, + saturate_double3, + saturate_double4, + saturate_int2, + saturate_int3, + saturate_int4, + saturate_uint2, + saturate_uint3, + saturate_uint4, +} +saturate_int :: proc "c" (x, y, z: int) -> int { return builtin.clamp(x, 0, 1) } +saturate_uint :: proc "c" (x, y, z: uint) -> uint { return builtin.clamp(x, 0, 1) } +saturate_float :: proc "c" (x, y, z: float) -> float { return builtin.clamp(x, 0, 1) } +saturate_double :: proc "c" (x, y, z: double) -> double { return builtin.clamp(x, 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_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_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_double2 :: proc "c" (x, y, z: double2) -> double2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.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_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_int2 :: proc "c" (x, y, z: int2) -> int2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.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_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_uint2 :: proc "c" (x, y, z: uint2) -> uint2 { return {builtin.clamp(x.x, 0, 1), builtin.clamp(x.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_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)} } + + +lerp :: proc{ + lerp_float, + lerp_double, + lerp_float2, + lerp_float3, + lerp_float4, + lerp_double2, + lerp_double3, + lerp_double4, +} +lerp_float :: proc "c" (x, y, t: float) -> float { return x*(1-t) + y*t } +lerp_double :: proc "c" (x, y, t: double) -> double { return x*(1-t) + y*t } +lerp_float2 :: proc "c" (x, y, t: float2) -> float2 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y)} } +lerp_float3 :: proc "c" (x, y, t: float3) -> float3 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y), lerp(x.z, y.z, t.z)} } +lerp_float4 :: proc "c" (x, y, t: float4) -> float4 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, y.y), lerp(x.z, y.z, t.z), lerp(x.w, y.w, t.w)} } +lerp_double2 :: proc "c" (x, y, t: double2) -> double2 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y)} } +lerp_double3 :: proc "c" (x, y, t: double3) -> double3 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, t.y), lerp(x.z, y.z, t.z)} } +lerp_double4 :: proc "c" (x, y, t: double4) -> double4 { return {lerp(x.x, y.x, t.x), lerp(x.y, y.y, y.y), lerp(x.z, y.z, t.z), lerp(x.w, y.w, t.w)} } + + +step :: proc{ + step_float, + step_double, + step_float2, + step_float3, + step_float4, + step_double2, + step_double3, + step_double4, +} +step_float :: proc "c" (edge, x: float) -> float { return 0 if x < edge else 1 } +step_double :: proc "c" (edge, x: double) -> double { return 0 if x < edge else 1 } +step_float2 :: proc "c" (edge, x: float2) -> float2 { return {step(edge.x, x.x), step(edge.y, x.y)} } +step_float3 :: proc "c" (edge, x: float3) -> float3 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z)} } +step_float4 :: proc "c" (edge, x: float4) -> float4 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z), step(edge.w, x.w)} } +step_double2 :: proc "c" (edge, x: double2) -> double2 { return {step(edge.x, x.x), step(edge.y, x.y)} } +step_double3 :: proc "c" (edge, x: double3) -> double3 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z)} } +step_double4 :: proc "c" (edge, x: double4) -> double4 { return {step(edge.x, x.x), step(edge.y, x.y), step(edge.z, x.z), step(edge.w, x.w)} } + +smoothstep :: proc{ + smoothstep_float, + smoothstep_double, + smoothstep_float2, + smoothstep_float3, + smoothstep_float4, + smoothstep_double2, + smoothstep_double3, + smoothstep_double4, +} +smoothstep_float :: proc "c" (edge0, edge1, x: float) -> float { + y := clamp(((x-edge0) / (edge1 - edge0)), 0, 1) + return y * y * (3 - 2*y) +} +smoothstep_double :: proc "c" (edge0, edge1, x: double) -> double { + y := clamp(((x-edge0) / (edge1 - edge0)), 0, 1) + return y * y * (3 - 2*y) +} +smoothstep_float2 :: proc "c" (edge0, edge1, x: float2) -> float2 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y)} } +smoothstep_float3 :: proc "c" (edge0, edge1, x: float3) -> float3 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y), smoothstep(edge0.z, edge1.z, x.z)} } +smoothstep_float4 :: proc "c" (edge0, edge1, x: float4) -> float4 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y), smoothstep(edge0.z, edge1.z, x.z), smoothstep(edge0.w, edge1.w, x.w)} } +smoothstep_double2 :: proc "c" (edge0, edge1, x: double2) -> double2 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y)} } +smoothstep_double3 :: proc "c" (edge0, edge1, x: double3) -> double3 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y), smoothstep(edge0.z, edge1.z, x.z)} } +smoothstep_double4 :: proc "c" (edge0, edge1, x: double4) -> double4 { return {smoothstep(edge0.x, edge1.x, x.x), smoothstep(edge0.y, edge1.y, x.y), smoothstep(edge0.z, edge1.z, x.z), smoothstep(edge0.w, edge1.w, x.w)} } + + +abs :: proc{ + abs_int, + abs_uint, + abs_float, + abs_double, + abs_float2, + abs_float3, + abs_float4, + abs_double2, + abs_double3, + abs_double4, + abs_int2, + abs_int3, + abs_int4, + abs_uint2, + abs_uint3, + abs_uint4, +} +abs_int :: proc "c" (x: int) -> int { return builtin.abs(x) } +abs_uint :: proc "c" (x: uint) -> uint { return x } +abs_float :: proc "c" (x: float) -> float { return builtin.abs(x) } +abs_double :: proc "c" (x: double) -> double { return builtin.abs(x) } +abs_float2 :: proc "c" (x: float2) -> float2 { return {abs(x.x), abs(x.y)} } +abs_float3 :: proc "c" (x: float3) -> float3 { return {abs(x.x), abs(x.y), abs(x.z)} } +abs_float4 :: proc "c" (x: float4) -> float4 { return {abs(x.x), abs(x.y), abs(x.z), abs(x.w)} } +abs_double2 :: proc "c" (x: double2) -> double2 { return {abs(x.x), abs(x.y)} } +abs_double3 :: proc "c" (x: double3) -> double3 { return {abs(x.x), abs(x.y), abs(x.z)} } +abs_double4 :: proc "c" (x: double4) -> double4 { return {abs(x.x), abs(x.y), abs(x.z), abs(x.w)} } +abs_int2 :: proc "c" (x: int2) -> int2 { return {abs(x.x), abs(x.y)} } +abs_int3 :: proc "c" (x: int3) -> int3 { return {abs(x.x), abs(x.y), abs(x.z)} } +abs_int4 :: proc "c" (x: int4) -> int4 { return {abs(x.x), abs(x.y), abs(x.z), abs(x.w)} } +abs_uint2 :: proc "c" (x: uint2) -> uint2 { return x } +abs_uint3 :: proc "c" (x: uint3) -> uint3 { return x } +abs_uint4 :: proc "c" (x: uint4) -> uint4 { return x } + +dot :: proc{ + dot_int, + dot_uint, + dot_float, + dot_double, + dot_float2, + dot_float3, + dot_float4, + dot_double2, + dot_double3, + dot_double4, + dot_int2, + dot_int3, + dot_int4, + dot_uint2, + dot_uint3, + dot_uint4, +} +dot_int :: proc "c" (a, b: int) -> int { return a*b } +dot_uint :: proc "c" (a, b: uint) -> uint { return a*b } +dot_float :: proc "c" (a, b: float) -> float { return a*b } +dot_double :: proc "c" (a, b: double) -> double { return a*b } +dot_float2 :: proc "c" (a, b: float2) -> float { return a.x*b.x + a.y*b.y } +dot_float3 :: proc "c" (a, b: float3) -> float { return a.x*b.x + a.y*b.y + a.z*b.z } +dot_float4 :: proc "c" (a, b: float4) -> float { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } +dot_double2 :: proc "c" (a, b: double2) -> double { return a.x*b.x + a.y*b.y } +dot_double3 :: proc "c" (a, b: double3) -> double { return a.x*b.x + a.y*b.y + a.z*b.z } +dot_double4 :: proc "c" (a, b: double4) -> double { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } +dot_int2 :: proc "c" (a, b: int2) -> int { return a.x*b.x + a.y*b.y } +dot_int3 :: proc "c" (a, b: int3) -> int { return a.x*b.x + a.y*b.y + a.z*b.z } +dot_int4 :: proc "c" (a, b: int4) -> int { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } +dot_uint2 :: proc "c" (a, b: uint2) -> uint { return a.x*b.x + a.y*b.y } +dot_uint3 :: proc "c" (a, b: uint3) -> uint { return a.x*b.x + a.y*b.y + a.z*b.z } +dot_uint4 :: proc "c" (a, b: uint4) -> uint { return a.x*b.x + a.y*b.y + a.z*b.z + a.w*b.w } + +length :: proc{ + length_float, + length_double, + length_float2, + length_float3, + length_float4, + length_double2, + length_double3, + length_double4, +} +length_float :: proc "c" (x: float) -> float { return builtin.abs(x) } +length_double :: proc "c" (x: double) -> double { return builtin.abs(x) } +length_float2 :: proc "c" (x: float2) -> float { return sqrt(x.x*x.x + x.y*x.y) } +length_float3 :: proc "c" (x: float3) -> float { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z) } +length_float4 :: proc "c" (x: float4) -> float { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z + x.w*x.w) } +length_double2 :: proc "c" (x: double2) -> double { return sqrt(x.x*x.x + x.y*x.y) } +length_double3 :: proc "c" (x: double3) -> double { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z) } +length_double4 :: proc "c" (x: double4) -> double { return sqrt(x.x*x.x + x.y*x.y + x.z*x.z + x.w*x.w) } + + +distance :: proc{ + distance_float, + distance_double, + distance_float2, + distance_float3, + distance_float4, + distance_double2, + distance_double3, + distance_double4, +} +distance_float :: proc "c" (x, y: float) -> float { return length(y-x) } +distance_double :: proc "c" (x, y: double) -> double { return length(y-x) } +distance_float2 :: proc "c" (x, y: float2) -> float { return length(y-x) } +distance_float3 :: proc "c" (x, y: float3) -> float { return length(y-x) } +distance_float4 :: proc "c" (x, y: float4) -> float { return length(y-x) } +distance_double2 :: proc "c" (x, y: double2) -> double { return length(y-x) } +distance_double3 :: proc "c" (x, y: double3) -> double { return length(y-x) } +distance_double4 :: proc "c" (x, y: double4) -> double { return length(y-x) } + + +cross :: proc{ + cross_float3, + cross_double3, + cross_int3, +} + +cross_float3 :: proc "c" (a, b: float3) -> (c: float3) { + c.x = a.y*b.z - b.y*a.z + c.y = a.z*b.x - b.z*a.x + c.z = a.x*b.y - b.x*a.y + return +} +cross_double3 :: proc "c" (a, b: double3) -> (c: double3) { + c.x = a.y*b.z - b.y*a.z + c.y = a.z*b.x - b.z*a.x + c.z = a.x*b.y - b.x*a.y + return +} +cross_int3 :: proc "c" (a, b: int3) -> (c: int3) { + c.x = a.y*b.z - b.y*a.z + c.y = a.z*b.x - b.z*a.x + c.z = a.x*b.y - b.x*a.y + return +} + +normalize :: proc{ + normalize_float, + normalize_double, + normalize_float2, + normalize_float3, + normalize_float4, + normalize_double2, + normalize_double3, + normalize_double4, +} +normalize_float :: proc "c" (x: float) -> float { return 1.0 } +normalize_double :: proc "c" (x: double) -> double { return 1.0 } +normalize_float2 :: proc "c" (x: float2) -> float2 { return x / length(x) } +normalize_float3 :: proc "c" (x: float3) -> float3 { return x / length(x) } +normalize_float4 :: proc "c" (x: float4) -> float4 { return x / length(x) } +normalize_double2 :: proc "c" (x: double2) -> double2 { return x / length(x) } +normalize_double3 :: proc "c" (x: double3) -> double3 { return x / length(x) } +normalize_double4 :: proc "c" (x: double4) -> double4 { return x / length(x) } + + +faceforward :: proc{ + faceforward_float, + faceforward_double, + faceforward_float2, + faceforward_float3, + faceforward_float4, + faceforward_double2, + faceforward_double3, + faceforward_double4, +} +faceforward_float :: proc "c" (N, I, Nref: float) -> float { return N if dot(I, Nref) < 0 else -N } +faceforward_double :: proc "c" (N, I, Nref: double) -> double { return N if dot(I, Nref) < 0 else -N } +faceforward_float2 :: proc "c" (N, I, Nref: float2) -> float2 { return N if dot(I, Nref) < 0 else -N } +faceforward_float3 :: proc "c" (N, I, Nref: float3) -> float3 { return N if dot(I, Nref) < 0 else -N } +faceforward_float4 :: proc "c" (N, I, Nref: float4) -> float4 { return N if dot(I, Nref) < 0 else -N } +faceforward_double2 :: proc "c" (N, I, Nref: double2) -> double2 { return N if dot(I, Nref) < 0 else -N } +faceforward_double3 :: proc "c" (N, I, Nref: double3) -> double3 { return N if dot(I, Nref) < 0 else -N } +faceforward_double4 :: proc "c" (N, I, Nref: double4) -> double4 { return N if dot(I, Nref) < 0 else -N } + + +reflect :: proc{ + reflect_float, + reflect_double, + reflect_float2, + reflect_float3, + reflect_float4, + reflect_double2, + reflect_double3, + reflect_double4, +} +reflect_float :: proc "c" (I, N: float) -> float { return I - 2*N*dot(N, I) } +reflect_double :: proc "c" (I, N: double) -> double { return I - 2*N*dot(N, I) } +reflect_float2 :: proc "c" (I, N: float2) -> float2 { return I - 2*N*dot(N, I) } +reflect_float3 :: proc "c" (I, N: float3) -> float3 { return I - 2*N*dot(N, I) } +reflect_float4 :: proc "c" (I, N: float4) -> float4 { return I - 2*N*dot(N, I) } +reflect_double2 :: proc "c" (I, N: double2) -> double2 { return I - 2*N*dot(N, I) } +reflect_double3 :: proc "c" (I, N: double3) -> double3 { return I - 2*N*dot(N, I) } +reflect_double4 :: proc "c" (I, N: double4) -> double4 { return I - 2*N*dot(N, I) } + + + + +refract :: proc{ + refract_float, + refract_double, + refract_float2, + refract_float3, + refract_float4, + refract_double2, + refract_double3, + refract_double4, +} +refract_float :: proc "c" (i, n, eta: float) -> float { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * float(int(cost2 > 0)) +} +refract_double :: proc "c" (i, n, eta: double) -> double { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * double(int(cost2 > 0)) +} +refract_float2 :: proc "c" (i, n, eta: float2) -> float2 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * float2{float(int(cost2.x > 0)), float(int(cost2.y > 0))} +} +refract_float3 :: proc "c" (i, n, eta: float3) -> float3 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * float3{float(int(cost2.x > 0)), float(int(cost2.y > 0)), float(int(cost2.z > 0))} +} +refract_float4 :: proc "c" (i, n, eta: float4) -> float4 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * float4{float(int(cost2.x > 0)), float(int(cost2.y > 0)), float(int(cost2.z > 0)), float(int(cost2.w > 0))} +} +refract_double2 :: proc "c" (i, n, eta: double2) -> double2 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * double2{double(int(cost2.x > 0)), double(int(cost2.y > 0))} +} +refract_double3 :: proc "c" (i, n, eta: double3) -> double3 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * double3{double(int(cost2.x > 0)), double(int(cost2.y > 0)), double(int(cost2.z > 0))} +} +refract_double4 :: proc "c" (i, n, eta: double4) -> double4 { + cosi := dot(-i, n) + cost2 := 1 - eta*eta*(1 - cosi*cosi) + t := eta*i + ((eta*cosi - sqrt(abs(cost2))) * n) + return t * double4{double(int(cost2.x > 0)), double(int(cost2.y > 0)), double(int(cost2.z > 0)), double(int(cost2.w > 0))} +} + +scalarTripleProduct :: proc{ + scalarTripleProduct_float3, + scalarTripleProduct_double3, + scalarTripleProduct_int3, +} +scalarTripleProduct_float3 :: proc "c" (a, b, c: float3) -> float { return dot(a, cross(b, c)) } +scalarTripleProduct_double3 :: proc "c" (a, b, c: double3) -> double { return dot(a, cross(b, c)) } +scalarTripleProduct_int3 :: proc "c" (a, b, c: int3) -> int { return dot(a, cross(b, c)) } + +vectorTripleProduct :: proc { + vectorTripleProduct_float3, + vectorTripleProduct_double3, + vectorTripleProduct_int3, +} +vectorTripleProduct_float3 :: proc "c" (a, b, c: float3) -> float3 { return cross(a, cross(b, c)) } +vectorTripleProduct_double3 :: proc "c" (a, b, c: double3) -> double3 { return cross(a, cross(b, c)) } +vectorTripleProduct_int3 :: proc "c" (a, b, c: int3) -> int3 { return cross(a, cross(b, c)) } + + +// Vector Relational Procedures + +lessThan :: proc{ + lessThan_float, + lessThan_double, + lessThan_int, + lessThan_uint, + lessThan_float2, + lessThan_double2, + lessThan_int2, + lessThan_uint2, + lessThan_float3, + lessThan_double3, + lessThan_int3, + lessThan_uint3, + lessThan_float4, + lessThan_double4, + lessThan_int4, + lessThan_uint4, +} +lessThan_float :: proc "c" (a, b: float) -> bool { return a < b } +lessThan_double :: proc "c" (a, b: double) -> bool { return a < b } +lessThan_int :: proc "c" (a, b: int) -> bool { return a < b } +lessThan_uint :: proc "c" (a, b: uint) -> bool { return a < b } +lessThan_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x < b.x, a.y < b.y} } +lessThan_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x < b.x, a.y < b.y} } +lessThan_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x < b.x, a.y < b.y} } +lessThan_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x < b.x, a.y < b.y} } +lessThan_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x < b.x, a.y < b.y, a.z < b.z} } +lessThan_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x < b.x, a.y < b.y, a.z < b.z} } +lessThan_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x < b.x, a.y < b.y, a.z < b.z} } +lessThan_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x < b.x, a.y < b.y, a.z < b.z} } +lessThan_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} } +lessThan_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} } +lessThan_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} } +lessThan_uint4 :: proc "c" (a, b: uint4) -> bool4 { return {a.x < b.x, a.y < b.y, a.z < b.z, a.w < b.w} } + + +lessThanEqual :: proc{ + lessThanEqual_float, + lessThanEqual_double, + lessThanEqual_int, + lessThanEqual_uint, + lessThanEqual_float2, + lessThanEqual_double2, + lessThanEqual_int2, + lessThanEqual_uint2, + lessThanEqual_float3, + lessThanEqual_double3, + lessThanEqual_int3, + lessThanEqual_uint3, + lessThanEqual_float4, + lessThanEqual_double4, + lessThanEqual_int4, + lessThanEqual_uint4, +} +lessThanEqual_float :: proc "c" (a, b: float) -> bool { return a <= b } +lessThanEqual_double :: proc "c" (a, b: double) -> bool { return a <= b } +lessThanEqual_int :: proc "c" (a, b: int) -> bool { return a <= b } +lessThanEqual_uint :: proc "c" (a, b: uint) -> bool { return a <= b } +lessThanEqual_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x <= b.x, a.y <= b.y} } +lessThanEqual_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x <= b.x, a.y <= b.y} } +lessThanEqual_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x <= b.x, a.y <= b.y} } +lessThanEqual_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x <= b.x, a.y <= b.y} } +lessThanEqual_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} } +lessThanEqual_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} } +lessThanEqual_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} } +lessThanEqual_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z} } +lessThanEqual_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} } +lessThanEqual_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} } +lessThanEqual_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} } +lessThanEqual_uint4 :: proc "c" (a, b: uint4) -> bool4 { return {a.x <= b.x, a.y <= b.y, a.z <= b.z, a.w <= b.w} } + + +greaterThan :: proc{ + greaterThan_float, + greaterThan_double, + greaterThan_int, + greaterThan_uint, + greaterThan_float2, + greaterThan_double2, + greaterThan_int2, + greaterThan_uint2, + greaterThan_float3, + greaterThan_double3, + greaterThan_int3, + greaterThan_uint3, + greaterThan_float4, + greaterThan_double4, + greaterThan_int4, + greaterThan_uint4, +} +greaterThan_float :: proc "c" (a, b: float) -> bool { return a > b } +greaterThan_double :: proc "c" (a, b: double) -> bool { return a > b } +greaterThan_int :: proc "c" (a, b: int) -> bool { return a > b } +greaterThan_uint :: proc "c" (a, b: uint) -> bool { return a > b } +greaterThan_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x > b.x, a.y > b.y} } +greaterThan_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x > b.x, a.y > b.y} } +greaterThan_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x > b.x, a.y > b.y} } +greaterThan_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x > b.x, a.y > b.y} } +greaterThan_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x > b.x, a.y > b.y, a.z > b.z} } +greaterThan_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x > b.x, a.y > b.y, a.z > b.z} } +greaterThan_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x > b.x, a.y > b.y, a.z > b.z} } +greaterThan_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x > b.x, a.y > b.y, a.z > b.z} } +greaterThan_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} } +greaterThan_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} } +greaterThan_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} } +greaterThan_uint4 :: proc "c" (a, b: uint4) -> bool4 { return {a.x > b.x, a.y > b.y, a.z > b.z, a.w > b.w} } + + +greaterThanEqual :: proc{ + greaterThanEqual_float, + greaterThanEqual_double, + greaterThanEqual_int, + greaterThanEqual_uint, + greaterThanEqual_float2, + greaterThanEqual_double2, + greaterThanEqual_int2, + greaterThanEqual_uint2, + greaterThanEqual_float3, + greaterThanEqual_double3, + greaterThanEqual_int3, + greaterThanEqual_uint3, + greaterThanEqual_float4, + greaterThanEqual_double4, + greaterThanEqual_int4, + greaterThanEqual_uint4, +} +greaterThanEqual_float :: proc "c" (a, b: float) -> bool { return a >= b } +greaterThanEqual_double :: proc "c" (a, b: double) -> bool { return a >= b } +greaterThanEqual_int :: proc "c" (a, b: int) -> bool { return a >= b } +greaterThanEqual_uint :: proc "c" (a, b: uint) -> bool { return a >= b } +greaterThanEqual_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x >= b.x, a.y >= b.y} } +greaterThanEqual_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x >= b.x, a.y >= b.y} } +greaterThanEqual_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x >= b.x, a.y >= b.y} } +greaterThanEqual_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x >= b.x, a.y >= b.y} } +greaterThanEqual_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} } +greaterThanEqual_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} } +greaterThanEqual_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} } +greaterThanEqual_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z} } +greaterThanEqual_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} } +greaterThanEqual_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} } +greaterThanEqual_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} } +greaterThanEqual_uint4 :: proc "c" (a, b: uint4) -> bool4 { return {a.x >= b.x, a.y >= b.y, a.z >= b.z, a.w >= b.w} } + + +equal :: proc{ + equal_float, + equal_double, + equal_int, + equal_uint, + equal_float2, + equal_double2, + equal_int2, + equal_uint2, + equal_float3, + equal_double3, + equal_int3, + equal_uint3, + equal_float4, + equal_double4, + equal_int4, + equal_uint4, +} +equal_float :: proc "c" (a, b: float) -> bool { return a == b } +equal_double :: proc "c" (a, b: double) -> bool { return a == b } +equal_int :: proc "c" (a, b: int) -> bool { return a == b } +equal_uint :: proc "c" (a, b: uint) -> bool { return a == b } +equal_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x == b.x, a.y == b.y} } +equal_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x == b.x, a.y == b.y} } +equal_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x == b.x, a.y == b.y} } +equal_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x == b.x, a.y == b.y} } +equal_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x == b.x, a.y == b.y, a.z == b.z} } +equal_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x == b.x, a.y == b.y, a.z == b.z} } +equal_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x == b.x, a.y == b.y, a.z == b.z} } +equal_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x == b.x, a.y == b.y, a.z == b.z} } +equal_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} } +equal_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} } +equal_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} } +equal_uint4 :: proc "c" (a, b: uint4) -> bool4 { return {a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w} } + +notEqual :: proc{ + notEqual_float, + notEqual_double, + notEqual_int, + notEqual_uint, + notEqual_float2, + notEqual_double2, + notEqual_int2, + notEqual_uint2, + notEqual_float3, + notEqual_double3, + notEqual_int3, + notEqual_uint3, + notEqual_float4, + notEqual_double4, + notEqual_int4, + notEqual_uint4, +} +notEqual_float :: proc "c" (a, b: float) -> bool { return a != b } +notEqual_double :: proc "c" (a, b: double) -> bool { return a != b } +notEqual_int :: proc "c" (a, b: int) -> bool { return a != b } +notEqual_uint :: proc "c" (a, b: uint) -> bool { return a != b } +notEqual_float2 :: proc "c" (a, b: float2) -> bool2 { return {a.x != b.x, a.y != b.y} } +notEqual_double2 :: proc "c" (a, b: double2) -> bool2 { return {a.x != b.x, a.y != b.y} } +notEqual_int2 :: proc "c" (a, b: int2) -> bool2 { return {a.x != b.x, a.y != b.y} } +notEqual_uint2 :: proc "c" (a, b: uint2) -> bool2 { return {a.x != b.x, a.y != b.y} } +notEqual_float3 :: proc "c" (a, b: float3) -> bool3 { return {a.x != b.x, a.y != b.y, a.z != b.z} } +notEqual_double3 :: proc "c" (a, b: double3) -> bool3 { return {a.x != b.x, a.y != b.y, a.z != b.z} } +notEqual_int3 :: proc "c" (a, b: int3) -> bool3 { return {a.x != b.x, a.y != b.y, a.z != b.z} } +notEqual_uint3 :: proc "c" (a, b: uint3) -> bool3 { return {a.x != b.x, a.y != b.y, a.z != b.z} } +notEqual_float4 :: proc "c" (a, b: float4) -> bool4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} } +notEqual_double4 :: proc "c" (a, b: double4) -> bool4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} } +notEqual_int4 :: proc "c" (a, b: int4) -> bool4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} } +notEqual_uint4 :: proc "c" (a, b: uint4) -> bool4 { return {a.x != b.x, a.y != b.y, a.z != b.z, a.w != b.w} } + + +any :: proc{ + any_bool, + any_bool2, + any_bool3, + any_bool4, +} +any_bool :: proc "c" (v: bool) -> bool { return v } +any_bool2 :: proc "c" (v: bool2) -> bool { return v.x || v.y } +any_bool3 :: proc "c" (v: bool3) -> bool { return v.x || v.y || v.z } +any_bool4 :: proc "c" (v: bool4) -> bool { return v.x || v.y || v.z || v.w } + +all :: proc{ + all_bool, + all_bool2, + all_bool3, + all_bool4, +} +all_bool :: proc "c" (v: bool) -> bool { return v } +all_bool2 :: proc "c" (v: bool2) -> bool { return v.x && v.y } +all_bool3 :: proc "c" (v: bool3) -> bool { return v.x && v.y && v.z } +all_bool4 :: proc "c" (v: bool4) -> bool { return v.x && v.y && v.z && v.w } + +not :: proc{ + not_bool, + not_bool2, + not_bool3, + not_bool4, +} +not_bool :: proc "c" (v: bool) -> bool { return !v } +not_bool2 :: proc "c" (v: bool2) -> bool2 { return {!v.x, !v.y} } +not_bool3 :: proc "c" (v: bool3) -> bool3 { return {!v.x, !v.y, !v.z} } +not_bool4 :: proc "c" (v: bool4) -> bool4 { return {!v.x, !v.y, !v.z, !v.w} } + + + + +inverse_float1x1 :: proc "c" (m: float1x1) -> float1x1 { return builtin.inverse(m) } +inverse_float2x2 :: proc "c" (m: float2x2) -> float2x2 { return builtin.inverse(m) } +inverse_float3x3 :: proc "c" (m: float3x3) -> float3x3 { return builtin.inverse(m) } +inverse_float4x4 :: proc "c" (m: float4x4) -> float4x4 { return builtin.inverse(m) } +inverse_double1x1 :: proc "c" (m: double1x1) -> double1x1 { return builtin.inverse(m) } +inverse_double2x2 :: proc "c" (m: double2x2) -> double2x2 { return builtin.inverse(m) } +inverse_double3x3 :: proc "c" (m: double3x3) -> double3x3 { return builtin.inverse(m) } +inverse_double4x4 :: proc "c" (m: double4x4) -> double4x4 { return builtin.inverse(m) } + +inverse :: proc{ + inverse_float1x1, + inverse_float2x2, + inverse_float3x3, + inverse_float4x4, + inverse_double1x1, + inverse_double2x2, + inverse_double3x3, + inverse_double4x4, +} + +transpose :: builtin.transpose +inverse_transpose :: builtin.inverse_transpose +adjugate :: builtin.adjugate +hermitian_adjoint :: builtin.hermitian_adjoint +minor :: builtin.matrix_minor +determinant :: builtin.determinant +trace :: builtin.matrix_trace + +asfloat :: proc{ + asfloat_float, + asfloat_double, + asfloat_int, + asfloat_uint, + asfloat_float1x1, + asfloat_float2x2, + asfloat_float3x3, + asfloat_float4x4, + asfloat_float1x2, + asfloat_float1x3, + asfloat_float1x4, + asfloat_float2x1, + asfloat_float2x3, + asfloat_float2x4, + asfloat_float3x1, + asfloat_float3x2, + asfloat_float3x4, + asfloat_float4x1, + asfloat_float4x2, + asfloat_float4x3, + asfloat_float2, + asfloat_float3, + asfloat_float4, + asfloat_int2, + asfloat_int3, + asfloat_int4, + asfloat_uint2, + asfloat_uint3, + asfloat_uint4, + asfloat_bool2, + asfloat_bool3, + asfloat_bool4, + asfloat_double1x1, + asfloat_double2x2, + asfloat_double3x3, + asfloat_double4x4, + asfloat_double1x2, + asfloat_double1x3, + asfloat_double1x4, + asfloat_double2x1, + asfloat_double2x3, + asfloat_double2x4, + asfloat_double3x1, + asfloat_double3x2, + asfloat_double3x4, + asfloat_double4x1, + asfloat_double4x2, + asfloat_double4x3, + asfloat_double2, + asfloat_double3, + asfloat_double4, +} +asfloat_float :: proc "c" (v: float) -> float { return float(v) } +asfloat_double :: proc "c" (v: double) -> float { return float(v) } +asfloat_int :: proc "c" (v: int) -> float { return float(v) } +asfloat_uint :: proc "c" (v: uint) -> float { return float(v) } +asfloat_float1x1 :: proc "c" (v: float1x1) -> float1x1 { return float1x1(v) } +asfloat_float2x2 :: proc "c" (v: float2x2) -> float2x2 { return float2x2(v) } +asfloat_float3x3 :: proc "c" (v: float3x3) -> float3x3 { return float3x3(v) } +asfloat_float4x4 :: proc "c" (v: float4x4) -> float4x4 { return float4x4(v) } +asfloat_float1x2 :: proc "c" (v: float1x2) -> float1x2 { return float1x2(v) } +asfloat_float1x3 :: proc "c" (v: float1x3) -> float1x3 { return float1x3(v) } +asfloat_float1x4 :: proc "c" (v: float1x4) -> float1x4 { return float1x4(v) } +asfloat_float2x1 :: proc "c" (v: float2x1) -> float2x1 { return float2x1(v) } +asfloat_float2x3 :: proc "c" (v: float2x3) -> float2x3 { return float2x3(v) } +asfloat_float2x4 :: proc "c" (v: float2x4) -> float2x4 { return float2x4(v) } +asfloat_float3x1 :: proc "c" (v: float3x1) -> float3x1 { return float3x1(v) } +asfloat_float3x2 :: proc "c" (v: float3x2) -> float3x2 { return float3x2(v) } +asfloat_float3x4 :: proc "c" (v: float3x4) -> float3x4 { return float3x4(v) } +asfloat_float4x1 :: proc "c" (v: float4x1) -> float4x1 { return float4x1(v) } +asfloat_float4x2 :: proc "c" (v: float4x2) -> float4x2 { return float4x2(v) } +asfloat_float4x3 :: proc "c" (v: float4x3) -> float4x3 { return float4x3(v) } +asfloat_float2 :: proc "c" (v: float2) -> float2 { return float2(v) } +asfloat_float3 :: proc "c" (v: float3) -> float3 { return float3(v) } +asfloat_float4 :: proc "c" (v: float4) -> float4 { return float4(v) } +asfloat_int2 :: proc "c" (v: int2) -> float2 { return float2{float(v.x), float(v.y)} } +asfloat_int3 :: proc "c" (v: int3) -> float3 { return float3{float(v.x), float(v.y), float(v.z)} } +asfloat_int4 :: proc "c" (v: int4) -> float4 { return float4{float(v.x), float(v.y), float(v.z), float(v.w)} } +asfloat_uint2 :: proc "c" (v: uint2) -> float2 { return float2{float(v.x), float(v.y)} } +asfloat_uint3 :: proc "c" (v: uint3) -> float3 { return float3{float(v.x), float(v.y), float(v.z)} } +asfloat_uint4 :: proc "c" (v: uint4) -> float4 { return float4{float(v.x), float(v.y), float(v.z), float(v.w)} } +asfloat_bool2 :: proc "c" (v: bool2) -> float2 { return float2{float(int(v.x)), float(int(v.y))} } +asfloat_bool3 :: proc "c" (v: bool3) -> float3 { return float3{float(int(v.x)), float(int(v.y)), float(int(v.z))} } +asfloat_bool4 :: proc "c" (v: bool4) -> float4 { return float4{float(int(v.x)), float(int(v.y)), float(int(v.z)), float(int(v.w))} } +asfloat_double1x1 :: proc "c" (v: double1x1) -> float1x1 { return float1x1(v) } +asfloat_double2x2 :: proc "c" (v: double2x2) -> float2x2 { return float2x2(v) } +asfloat_double3x3 :: proc "c" (v: double3x3) -> float3x3 { return float3x3(v) } +asfloat_double4x4 :: proc "c" (v: double4x4) -> float4x4 { return float4x4(v) } +asfloat_double1x2 :: proc "c" (v: double1x2) -> float1x2 { return float1x2(v) } +asfloat_double1x3 :: proc "c" (v: double1x3) -> float1x3 { return float1x3(v) } +asfloat_double1x4 :: proc "c" (v: double1x4) -> float1x4 { return float1x4(v) } +asfloat_double2x1 :: proc "c" (v: double2x1) -> float2x1 { return float2x1(v) } +asfloat_double2x3 :: proc "c" (v: double2x3) -> float2x3 { return float2x3(v) } +asfloat_double2x4 :: proc "c" (v: double2x4) -> float2x4 { return float2x4(v) } +asfloat_double3x1 :: proc "c" (v: double3x1) -> float3x1 { return float3x1(v) } +asfloat_double3x2 :: proc "c" (v: double3x2) -> float3x2 { return float3x2(v) } +asfloat_double3x4 :: proc "c" (v: double3x4) -> float3x4 { return float3x4(v) } +asfloat_double4x1 :: proc "c" (v: double4x1) -> float4x1 { return float4x1(v) } +asfloat_double4x2 :: proc "c" (v: double4x2) -> float4x2 { return float4x2(v) } +asfloat_double4x3 :: proc "c" (v: double4x3) -> float4x3 { return float4x3(v) } +asfloat_double2 :: proc "c" (v: double2) -> float2 { return float2{float(v.x), float(v.y)} } +asfloat_double3 :: proc "c" (v: double3) -> float3 { return float3{float(v.x), float(v.y), float(v.z)} } +asfloat_double4 :: proc "c" (v: double4) -> float4 { return float4{float(v.x), float(v.y), float(v.z), float(v.w)} } + +asdouble :: proc{ + asdouble_float, + asdouble_double, + asdouble_int, + asdouble_uint, + asdouble_float1x1, + asdouble_float2x2, + asdouble_float3x3, + asdouble_float4x4, + asdouble_float1x2, + asdouble_float1x3, + asdouble_float1x4, + asdouble_float2x1, + asdouble_float2x3, + asdouble_float2x4, + asdouble_float3x1, + asdouble_float3x2, + asdouble_float3x4, + asdouble_float4x1, + asdouble_float4x2, + asdouble_float4x3, + asdouble_float2, + asdouble_float3, + asdouble_float4, + asdouble_int2, + asdouble_int3, + asdouble_int4, + asdouble_uint2, + asdouble_uint3, + asdouble_uint4, + asdouble_bool2, + asdouble_bool3, + asdouble_bool4, + asdouble_double1x1, + asdouble_double2x2, + asdouble_double3x3, + asdouble_double4x4, + asdouble_double1x2, + asdouble_double1x3, + asdouble_double1x4, + asdouble_double2x1, + asdouble_double2x3, + asdouble_double2x4, + asdouble_double3x1, + asdouble_double3x2, + asdouble_double3x4, + asdouble_double4x1, + asdouble_double4x2, + asdouble_double4x3, + asdouble_double2, + asdouble_double3, + asdouble_double4, +} +asdouble_float :: proc "c" (v: float) -> double { return double(v) } +asdouble_double :: proc "c" (v: double) -> double { return double(v) } +asdouble_int :: proc "c" (v: int) -> double { return double(v) } +asdouble_uint :: proc "c" (v: uint) -> double { return double(v) } +asdouble_float1x1 :: proc "c" (v: float1x1) -> double1x1 { return double1x1(v) } +asdouble_float2x2 :: proc "c" (v: float2x2) -> double2x2 { return double2x2(v) } +asdouble_float3x3 :: proc "c" (v: float3x3) -> double3x3 { return double3x3(v) } +asdouble_float4x4 :: proc "c" (v: float4x4) -> double4x4 { return double4x4(v) } +asdouble_float1x2 :: proc "c" (v: float1x2) -> double1x2 { return double1x2(v) } +asdouble_float1x3 :: proc "c" (v: float1x3) -> double1x3 { return double1x3(v) } +asdouble_float1x4 :: proc "c" (v: float1x4) -> double1x4 { return double1x4(v) } +asdouble_float2x1 :: proc "c" (v: float2x1) -> double2x1 { return double2x1(v) } +asdouble_float2x3 :: proc "c" (v: float2x3) -> double2x3 { return double2x3(v) } +asdouble_float2x4 :: proc "c" (v: float2x4) -> double2x4 { return double2x4(v) } +asdouble_float3x1 :: proc "c" (v: float3x1) -> double3x1 { return double3x1(v) } +asdouble_float3x2 :: proc "c" (v: float3x2) -> double3x2 { return double3x2(v) } +asdouble_float3x4 :: proc "c" (v: float3x4) -> double3x4 { return double3x4(v) } +asdouble_float4x1 :: proc "c" (v: float4x1) -> double4x1 { return double4x1(v) } +asdouble_float4x2 :: proc "c" (v: float4x2) -> double4x2 { return double4x2(v) } +asdouble_float4x3 :: proc "c" (v: float4x3) -> double4x3 { return double4x3(v) } +asdouble_float2 :: proc "c" (v: float2) -> double2 { return double2{double(v.x), double(v.y)} } +asdouble_float3 :: proc "c" (v: float3) -> double3 { return double3{double(v.x), double(v.y), double(v.z)} } +asdouble_float4 :: proc "c" (v: float4) -> double4 { return double4{double(v.x), double(v.y), double(v.z), double(v.w)} } +asdouble_int2 :: proc "c" (v: int2) -> double2 { return double2{double(v.x), double(v.y)} } +asdouble_int3 :: proc "c" (v: int3) -> double3 { return double3{double(v.x), double(v.y), double(v.z)} } +asdouble_int4 :: proc "c" (v: int4) -> double4 { return double4{double(v.x), double(v.y), double(v.z), double(v.w)} } +asdouble_uint2 :: proc "c" (v: uint2) -> double2 { return double2{double(v.x), double(v.y)} } +asdouble_uint3 :: proc "c" (v: uint3) -> double3 { return double3{double(v.x), double(v.y), double(v.z)} } +asdouble_uint4 :: proc "c" (v: uint4) -> double4 { return double4{double(v.x), double(v.y), double(v.z), double(v.w)} } +asdouble_bool2 :: proc "c" (v: bool2) -> double2 { return double2{double(int(v.x)), double(int(v.y))} } +asdouble_bool3 :: proc "c" (v: bool3) -> double3 { return double3{double(int(v.x)), double(int(v.y)), double(int(v.z))} } +asdouble_bool4 :: proc "c" (v: bool4) -> double4 { return double4{double(int(v.x)), double(int(v.y)), double(int(v.z)), double(int(v.w))} } +asdouble_double1x1 :: proc "c" (v: double1x1) -> double1x1 { return double1x1(v) } +asdouble_double2x2 :: proc "c" (v: double2x2) -> double2x2 { return double2x2(v) } +asdouble_double3x3 :: proc "c" (v: double3x3) -> double3x3 { return double3x3(v) } +asdouble_double4x4 :: proc "c" (v: double4x4) -> double4x4 { return double4x4(v) } +asdouble_double1x2 :: proc "c" (v: double1x2) -> double1x2 { return double1x2(v) } +asdouble_double1x3 :: proc "c" (v: double1x3) -> double1x3 { return double1x3(v) } +asdouble_double1x4 :: proc "c" (v: double1x4) -> double1x4 { return double1x4(v) } +asdouble_double2x1 :: proc "c" (v: double2x1) -> double2x1 { return double2x1(v) } +asdouble_double2x3 :: proc "c" (v: double2x3) -> double2x3 { return double2x3(v) } +asdouble_double2x4 :: proc "c" (v: double2x4) -> double2x4 { return double2x4(v) } +asdouble_double3x1 :: proc "c" (v: double3x1) -> double3x1 { return double3x1(v) } +asdouble_double3x2 :: proc "c" (v: double3x2) -> double3x2 { return double3x2(v) } +asdouble_double3x4 :: proc "c" (v: double3x4) -> double3x4 { return double3x4(v) } +asdouble_double4x1 :: proc "c" (v: double4x1) -> double4x1 { return double4x1(v) } +asdouble_double4x2 :: proc "c" (v: double4x2) -> double4x2 { return double4x2(v) } +asdouble_double4x3 :: proc "c" (v: double4x3) -> double4x3 { return double4x3(v) } +asdouble_double2 :: proc "c" (v: double2) -> double2 { return double2{double(v.x), double(v.y)} } +asdouble_double3 :: proc "c" (v: double3) -> double3 { return double3{double(v.x), double(v.y), double(v.z)} } +asdouble_double4 :: proc "c" (v: double4) -> double4 { return double4{double(v.x), double(v.y), double(v.z), double(v.w)} } + +asint :: proc{ + asint_float, + asint_double, + asint_int, + asint_uint, + asint_float1x1, + asint_float2x2, + asint_float3x3, + asint_float4x4, + asint_float1x2, + asint_float1x3, + asint_float1x4, + asint_float2x1, + asint_float2x3, + asint_float2x4, + asint_float3x1, + asint_float3x2, + asint_float3x4, + asint_float4x1, + asint_float4x2, + asint_float4x3, + asint_float2, + asint_float3, + asint_float4, + asint_int2, + asint_int3, + asint_int4, + asint_uint2, + asint_uint3, + asint_uint4, + asint_bool2, + asint_bool3, + asint_bool4, + asint_double1x1, + asint_double2x2, + asint_double3x3, + asint_double4x4, + asint_double1x2, + asint_double1x3, + asint_double1x4, + asint_double2x1, + asint_double2x3, + asint_double2x4, + asint_double3x1, + asint_double3x2, + asint_double3x4, + asint_double4x1, + asint_double4x2, + asint_double4x3, + asint_double2, + asint_double3, + asint_double4, +} +asint_float :: proc "c" (v: float) -> int { return int(v) } +asint_double :: proc "c" (v: double) -> int { return int(v) } +asint_int :: proc "c" (v: int) -> int { return int(v) } +asint_uint :: proc "c" (v: uint) -> int { return int(v) } +asint_float1x1 :: proc "c" (v: float1x1) -> int1x1 { return int1x1(v) } +asint_float2x2 :: proc "c" (v: float2x2) -> int2x2 { return int2x2(v) } +asint_float3x3 :: proc "c" (v: float3x3) -> int3x3 { return int3x3(v) } +asint_float4x4 :: proc "c" (v: float4x4) -> int4x4 { return int4x4(v) } +asint_float1x2 :: proc "c" (v: float1x2) -> int1x2 { return int1x2(v) } +asint_float1x3 :: proc "c" (v: float1x3) -> int1x3 { return int1x3(v) } +asint_float1x4 :: proc "c" (v: float1x4) -> int1x4 { return int1x4(v) } +asint_float2x1 :: proc "c" (v: float2x1) -> int2x1 { return int2x1(v) } +asint_float2x3 :: proc "c" (v: float2x3) -> int2x3 { return int2x3(v) } +asint_float2x4 :: proc "c" (v: float2x4) -> int2x4 { return int2x4(v) } +asint_float3x1 :: proc "c" (v: float3x1) -> int3x1 { return int3x1(v) } +asint_float3x2 :: proc "c" (v: float3x2) -> int3x2 { return int3x2(v) } +asint_float3x4 :: proc "c" (v: float3x4) -> int3x4 { return int3x4(v) } +asint_float4x1 :: proc "c" (v: float4x1) -> int4x1 { return int4x1(v) } +asint_float4x2 :: proc "c" (v: float4x2) -> int4x2 { return int4x2(v) } +asint_float4x3 :: proc "c" (v: float4x3) -> int4x3 { return int4x3(v) } +asint_float2 :: proc "c" (v: float2) -> int2 { return int2{int(v.x), int(v.y)} } +asint_float3 :: proc "c" (v: float3) -> int3 { return int3{int(v.x), int(v.y), int(v.z)} } +asint_float4 :: proc "c" (v: float4) -> int4 { return int4{int(v.x), int(v.y), int(v.z), int(v.w)} } +asint_int2 :: proc "c" (v: int2) -> int2 { return int2{int(v.x), int(v.y)} } +asint_int3 :: proc "c" (v: int3) -> int3 { return int3{int(v.x), int(v.y), int(v.z)} } +asint_int4 :: proc "c" (v: int4) -> int4 { return int4{int(v.x), int(v.y), int(v.z), int(v.w)} } +asint_uint2 :: proc "c" (v: uint2) -> int2 { return int2{int(v.x), int(v.y)} } +asint_uint3 :: proc "c" (v: uint3) -> int3 { return int3{int(v.x), int(v.y), int(v.z)} } +asint_uint4 :: proc "c" (v: uint4) -> int4 { return int4{int(v.x), int(v.y), int(v.z), int(v.w)} } +asint_bool2 :: proc "c" (v: bool2) -> int2 { return int2{int(int(v.x)), int(int(v.y))} } +asint_bool3 :: proc "c" (v: bool3) -> int3 { return int3{int(int(v.x)), int(int(v.y)), int(int(v.z))} } +asint_bool4 :: proc "c" (v: bool4) -> int4 { return int4{int(int(v.x)), int(int(v.y)), int(int(v.z)), int(int(v.w))} } +asint_double1x1 :: proc "c" (v: double1x1) -> int1x1 { return int1x1(v) } +asint_double2x2 :: proc "c" (v: double2x2) -> int2x2 { return int2x2(v) } +asint_double3x3 :: proc "c" (v: double3x3) -> int3x3 { return int3x3(v) } +asint_double4x4 :: proc "c" (v: double4x4) -> int4x4 { return int4x4(v) } +asint_double1x2 :: proc "c" (v: double1x2) -> int1x2 { return int1x2(v) } +asint_double1x3 :: proc "c" (v: double1x3) -> int1x3 { return int1x3(v) } +asint_double1x4 :: proc "c" (v: double1x4) -> int1x4 { return int1x4(v) } +asint_double2x1 :: proc "c" (v: double2x1) -> int2x1 { return int2x1(v) } +asint_double2x3 :: proc "c" (v: double2x3) -> int2x3 { return int2x3(v) } +asint_double2x4 :: proc "c" (v: double2x4) -> int2x4 { return int2x4(v) } +asint_double3x1 :: proc "c" (v: double3x1) -> int3x1 { return int3x1(v) } +asint_double3x2 :: proc "c" (v: double3x2) -> int3x2 { return int3x2(v) } +asint_double3x4 :: proc "c" (v: double3x4) -> int3x4 { return int3x4(v) } +asint_double4x1 :: proc "c" (v: double4x1) -> int4x1 { return int4x1(v) } +asint_double4x2 :: proc "c" (v: double4x2) -> int4x2 { return int4x2(v) } +asint_double4x3 :: proc "c" (v: double4x3) -> int4x3 { return int4x3(v) } +asint_double2 :: proc "c" (v: double2) -> int2 { return int2{int(v.x), int(v.y)} } +asint_double3 :: proc "c" (v: double3) -> int3 { return int3{int(v.x), int(v.y), int(v.z)} } +asint_double4 :: proc "c" (v: double4) -> int4 { return int4{int(v.x), int(v.y), int(v.z), int(v.w)} } + + +asuint :: proc{ + asuint_float, + asuint_double, + asuint_int, + asuint_uint, + asuint_float2, + asuint_float3, + asuint_float4, + asuint_int2, + asuint_int3, + asuint_int4, + asuint_uint2, + asuint_uint3, + asuint_uint4, + asuint_bool2, + asuint_bool3, + asuint_bool4, + asuint_double2, + asuint_double3, + asuint_double4, +} +asuint_float :: proc "c" (v: float) -> uint { return uint(v) } +asuint_double :: proc "c" (v: double) -> uint { return uint(v) } +asuint_int :: proc "c" (v: int) -> uint { return uint(v) } +asuint_uint :: proc "c" (v: uint) -> uint { return uint(v) } +asuint_float2 :: proc "c" (v: float2) -> uint2 { return uint2{uint(v.x), uint(v.y)} } +asuint_float3 :: proc "c" (v: float3) -> uint3 { return uint3{uint(v.x), uint(v.y), uint(v.z)} } +asuint_float4 :: proc "c" (v: float4) -> uint4 { return uint4{uint(v.x), uint(v.y), uint(v.z), uint(v.w)} } +asuint_int2 :: proc "c" (v: int2) -> uint2 { return uint2{uint(v.x), uint(v.y)} } +asuint_int3 :: proc "c" (v: int3) -> uint3 { return uint3{uint(v.x), uint(v.y), uint(v.z)} } +asuint_int4 :: proc "c" (v: int4) -> uint4 { return uint4{uint(v.x), uint(v.y), uint(v.z), uint(v.w)} } +asuint_uint2 :: proc "c" (v: uint2) -> uint2 { return uint2{uint(v.x), uint(v.y)} } +asuint_uint3 :: proc "c" (v: uint3) -> uint3 { return uint3{uint(v.x), uint(v.y), uint(v.z)} } +asuint_uint4 :: proc "c" (v: uint4) -> uint4 { return uint4{uint(v.x), uint(v.y), uint(v.z), uint(v.w)} } +asuint_bool2 :: proc "c" (v: bool2) -> uint2 { return uint2{uint(uint(v.x)), uint(uint(v.y))} } +asuint_bool3 :: proc "c" (v: bool3) -> uint3 { return uint3{uint(uint(v.x)), uint(uint(v.y)), uint(uint(v.z))} } +asuint_bool4 :: proc "c" (v: bool4) -> uint4 { return uint4{uint(uint(v.x)), uint(uint(v.y)), uint(uint(v.z)), uint(uint(v.w))} } +asuint_double2 :: proc "c" (v: double2) -> uint2 { return uint2{uint(v.x), uint(v.y)} } +asuint_double3 :: proc "c" (v: double3) -> uint3 { return uint3{uint(v.x), uint(v.y), uint(v.z)} } +asuint_double4 :: proc "c" (v: double4) -> uint4 { return uint4{uint(v.x), uint(v.y), uint(v.z), uint(v.w)} } + + +// TODO(bill): All of the `mul` procedures diff --git a/core/math/linalg/hlsl/linalg_hlsl_math.odin b/core/math/linalg/hlsl/linalg_hlsl_math.odin new file mode 100644 index 000000000..d884c3d31 --- /dev/null +++ b/core/math/linalg/hlsl/linalg_hlsl_math.odin @@ -0,0 +1,69 @@ +package math_linalg_hlsl + +import "core:math" + +cos_float :: proc "c" (x: float) -> float { return math.cos(x) } +sin_float :: proc "c" (x: float) -> float { return math.sin(x) } +tan_float :: proc "c" (x: float) -> float { return math.tan(x) } +acos_float :: proc "c" (x: float) -> float { return math.acos(x) } +asin_float :: proc "c" (x: float) -> float { return math.asin(x) } +atan_float :: proc "c" (x: float) -> float { return math.atan(x) } +atan2_float :: proc "c" (y, x: float) -> float { return math.atan2(y, x) } +cosh_float :: proc "c" (x: float) -> float { return math.cosh(x) } +sinh_float :: proc "c" (x: float) -> float { return math.sinh(x) } +tanh_float :: proc "c" (x: float) -> float { return math.tanh(x) } +acosh_float :: proc "c" (x: float) -> float { return math.acosh(x) } +asinh_float :: proc "c" (x: float) -> float { return math.asinh(x) } +atanh_float :: proc "c" (x: float) -> float { return math.atanh(x) } +sqrt_float :: proc "c" (x: float) -> float { return math.sqrt(x) } +rsqrt_float :: proc "c" (x: float) -> float { return 1.0/math.sqrt(x) } +rcp_float :: proc "c" (x: float) -> float { return 1.0/x } +pow_float :: proc "c" (x, y: float) -> float { return math.pow(x, y) } +exp_float :: proc "c" (x: float) -> float { return math.exp(x) } +log_float :: proc "c" (x: float) -> float { return math.ln(x) } +log2_float :: proc "c" (x: float) -> float { return math.log(x, 2) } +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) } +sign_float :: proc "c" (x: float) -> float { return math.sign(x) } +floor_float :: proc "c" (x: float) -> float { return math.floor(x) } +ceil_float :: proc "c" (x: float) -> float { return math.ceil(x) } +fmod_float :: proc "c" (x, y: float) -> float { return math.mod(x, y) } +frac_float :: proc "c" (x: float) -> float { + if x >= 0 { + return x - math.trunc(x) + } + return math.trunc(-x) + x +} + +cos_double :: proc "c" (x: double) -> double { return math.cos(x) } +sin_double :: proc "c" (x: double) -> double { return math.sin(x) } +tan_double :: proc "c" (x: double) -> double { return math.tan(x) } +acos_double :: proc "c" (x: double) -> double { return math.acos(x) } +asin_double :: proc "c" (x: double) -> double { return math.asin(x) } +atan_double :: proc "c" (x: double) -> double { return math.atan(x) } +atan2_double :: proc "c" (y, x: double) -> double { return math.atan2(y, x) } +cosh_double :: proc "c" (x: double) -> double { return math.cosh(x) } +sinh_double :: proc "c" (x: double) -> double { return math.sinh(x) } +tanh_double :: proc "c" (x: double) -> double { return math.tanh(x) } +acosh_double :: proc "c" (x: double) -> double { return math.acosh(x) } +asinh_double :: proc "c" (x: double) -> double { return math.asinh(x) } +atanh_double :: proc "c" (x: double) -> double { return math.atanh(x) } +sqrt_double :: proc "c" (x: double) -> double { return math.sqrt(x) } +rsqrt_double :: proc "c" (x: double) -> double { return 1.0/math.sqrt(x) } +rcp_double :: proc "c" (x: double) -> double { return 1.0/x } +pow_double :: proc "c" (x, y: double) -> double { return math.pow(x, y) } +exp_double :: proc "c" (x: double) -> double { return math.exp(x) } +log_double :: proc "c" (x: double) -> double { return math.ln(x) } +log2_double :: proc "c" (x: double) -> double { return math.log(x, 2) } +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) } +sign_double :: proc "c" (x: double) -> double { return math.sign(x) } +floor_double :: proc "c" (x: double) -> double { return math.floor(x) } +ceil_double :: proc "c" (x: double) -> double { return math.ceil(x) } +fmod_double :: proc "c" (x, y: double) -> double { return math.mod(x, y) } +frac_double :: proc "c" (x: double) -> double { + if x >= 0 { + return x - math.trunc(x) + } + return math.trunc(-x) + x +} From adcfca966e2ce725cd968f8702a553fcee741a56 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 17:24:28 +0000 Subject: [PATCH 06/29] Use `Rtl*Memory` procedures with `-no-crt` on Windows --- core/runtime/procs.odin | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/core/runtime/procs.odin b/core/runtime/procs.odin index c69e5b00a..a403c2265 100644 --- a/core/runtime/procs.odin +++ b/core/runtime/procs.odin @@ -1,6 +1,6 @@ package runtime -when ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" || ODIN_NO_CRT { +when ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" || (ODIN_NO_CRT && ODIN_OS != "windows") { @(link_name="memset", linkage="strong", require) memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { if ptr != nil && len != 0 { @@ -36,6 +36,34 @@ when ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" || ODIN_NO_CRT { } return dst + } +} else when ODIN_NO_CRT && ODIN_OS == "windows" { + foreign import Kernel32 "system:Kernel32.lib" + + @(private="file") + @(default_calling_convention="std") + foreign Kernel32 { + RtlMoveMemory :: proc(dst, src: rawptr, length: int) --- + RtlFillMemory :: proc(dst: rawptr, length: int, fill: i32) --- + } + + @(link_name="memset", linkage="strong", require) + memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { + RtlFillMemory(ptr, len, val) + return ptr + } + + @(link_name="memmove", linkage="strong", require) + memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr { + RtlMoveMemory(dst, src, len) + return dst + + } + @(link_name="memcpy", linkage="strong", require) + memcpy :: proc "c" (dst, src: rawptr, len: int) -> rawptr { + RtlMoveMemory(dst, src, len) + return dst + } } else { memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { From ae25eaf10c9f8d0b29c7e5d9cbd2f6519c8126fd Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 17:25:37 +0000 Subject: [PATCH 07/29] Correct foreign import library usage --- core/runtime/procs.odin | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/runtime/procs.odin b/core/runtime/procs.odin index a403c2265..d588a2c2f 100644 --- a/core/runtime/procs.odin +++ b/core/runtime/procs.odin @@ -38,11 +38,11 @@ when ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" || (ODIN_NO_CRT && ODIN_OS ! } } else when ODIN_NO_CRT && ODIN_OS == "windows" { - foreign import Kernel32 "system:Kernel32.lib" + foreign import lib "system:NtDll.lib" @(private="file") @(default_calling_convention="std") - foreign Kernel32 { + foreign lib { RtlMoveMemory :: proc(dst, src: rawptr, length: int) --- RtlFillMemory :: proc(dst: rawptr, length: int, fill: i32) --- } From a22120fe947fc0a950f3b2ef04753b573a989885 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 17:38:58 +0000 Subject: [PATCH 08/29] Reorganize code --- core/runtime/procs.odin | 55 +++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/core/runtime/procs.odin b/core/runtime/procs.odin index d588a2c2f..fe37c7e7d 100644 --- a/core/runtime/procs.odin +++ b/core/runtime/procs.odin @@ -1,6 +1,31 @@ package runtime -when ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" || (ODIN_NO_CRT && ODIN_OS != "windows") { +when ODIN_NO_CRT && ODIN_OS == "windows" { + foreign import lib "system:NtDll.lib" + + @(private="file") + @(default_calling_convention="std") + foreign lib { + RtlMoveMemory :: proc(dst, src: rawptr, length: int) --- + RtlFillMemory :: proc(dst: rawptr, length: int, fill: i32) --- + } + + @(link_name="memset", linkage="strong", require) + memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { + RtlFillMemory(ptr, len, val) + return ptr + } + @(link_name="memmove", linkage="strong", require) + memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr { + RtlMoveMemory(dst, src, len) + return dst + } + @(link_name="memcpy", linkage="strong", require) + memcpy :: proc "c" (dst, src: rawptr, len: int) -> rawptr { + RtlMoveMemory(dst, src, len) + return dst + } +} else when ODIN_NO_CRT || (ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64") { @(link_name="memset", linkage="strong", require) memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { if ptr != nil && len != 0 { @@ -36,34 +61,6 @@ when ODIN_ARCH == "wasm32" || ODIN_ARCH == "wasm64" || (ODIN_NO_CRT && ODIN_OS ! } return dst - } -} else when ODIN_NO_CRT && ODIN_OS == "windows" { - foreign import lib "system:NtDll.lib" - - @(private="file") - @(default_calling_convention="std") - foreign lib { - RtlMoveMemory :: proc(dst, src: rawptr, length: int) --- - RtlFillMemory :: proc(dst: rawptr, length: int, fill: i32) --- - } - - @(link_name="memset", linkage="strong", require) - memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { - RtlFillMemory(ptr, len, val) - return ptr - } - - @(link_name="memmove", linkage="strong", require) - memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr { - RtlMoveMemory(dst, src, len) - return dst - - } - @(link_name="memcpy", linkage="strong", require) - memcpy :: proc "c" (dst, src: rawptr, len: int) -> rawptr { - RtlMoveMemory(dst, src, len) - return dst - } } else { memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { From 23c74bc67bc02c543f34275a836d2e05a4b7e59d Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 19:30:46 +0000 Subject: [PATCH 09/29] Update `all_main.odin` to include `core:math/linalg/hlsl` --- examples/all/all_main.odin | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/all/all_main.odin b/examples/all/all_main.odin index 92026fe2c..a88cc273e 100644 --- a/examples/all/all_main.odin +++ b/examples/all/all_main.odin @@ -30,6 +30,7 @@ import bits "core:math/bits" import fixed "core:math/fixed" import linalg "core:math/linalg" import glm "core:math/linalg/glsl" +import hlm "core:math/linalg/hlsl" import rand "core:math/rand" import mem "core:mem" import ast "core:odin/ast" @@ -86,6 +87,7 @@ _ :: bits _ :: fixed _ :: linalg _ :: glm +_ :: hlm _ :: rand _ :: mem _ :: ast From adb5928767b641132dd34ce44616877f635e71bb Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 4 Nov 2021 20:21:51 +0000 Subject: [PATCH 10/29] Change to `RUNTIME_LINKAGE` definition --- core/runtime/internal.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index 5ab91e627..775245cc8 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -3,7 +3,7 @@ package runtime import "core:intrinsics" @(private) -RUNTIME_LINKAGE :: "strong" when (ODIN_USE_SEPARATE_MODULES || ODIN_BUILD_MODE == "dynamic") else "internal" +RUNTIME_LINKAGE :: "strong" when (ODIN_USE_SEPARATE_MODULES || ODIN_BUILD_MODE == "dynamic" || !ODIN_NO_CRT) else "internal" @(private) byte_slice :: #force_inline proc "contextless" (data: rawptr, len: int) -> []byte #no_bounds_check { From 3d0cd6f0dc939bdc34884b24a40fc583632d6d7a Mon Sep 17 00:00:00 2001 From: Henry Dooley Date: Thu, 4 Nov 2021 18:52:25 -0700 Subject: [PATCH 11/29] don't try to use __cpuid() on arm64 --- src/bug_report.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/bug_report.cpp b/src/bug_report.cpp index 5249cc3a4..27e7fcf9a 100644 --- a/src/bug_report.cpp +++ b/src/bug_report.cpp @@ -146,10 +146,17 @@ void report_windows_product_type(DWORD ProductType) { #endif void odin_cpuid(int leaf, int result[]) { - #if defined(GB_COMPILER_MSVC) - __cpuid(result, leaf); - #else - __get_cpuid(leaf, (unsigned int*)&result[0], (unsigned int*)&result[1], (unsigned int*)&result[2], (unsigned int*)&result[3]); + #if defined(GB_CPU_ARM) + return; + + #elif defined(GB_CPU_X86) + + #if defined(GB_COMPILER_MSVC) + __cpuid(result, leaf); + #else + __get_cpuid(leaf, (unsigned int*)&result[0], (unsigned int*)&result[1], (unsigned int*)&result[2], (unsigned int*)&result[3]); + #endif + #endif } From a022f18015596d02c15e76eef582cd39c4c02fe6 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 12:11:33 +0000 Subject: [PATCH 12/29] Reorganize code --- src/checker.cpp | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/checker.cpp b/src/checker.cpp index 1a92b1c06..125893d11 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -5207,6 +5207,17 @@ void check_sort_init_procedures(Checker *c) { gb_sort_array(c->info.init_procedures.data, c->info.init_procedures.count, init_procedures_cmp); } +void add_type_info_for_type_definitions(Checker *c) { + for_array(i, c->info.definitions) { + Entity *e = c->info.definitions[i]; + if (e->kind == Entity_TypeName && e->type != nullptr) { + i64 align = type_align_of(e->type); + if (align > 0 && ptr_set_exists(&c->info.minimum_dependency_set, e)) { + add_type_info_type(&c->builtin_ctx, e->type); + } + } + } +} void check_parsed_files(Checker *c) { TIME_SECTION("map full filepaths to scope"); @@ -5286,7 +5297,7 @@ void check_parsed_files(Checker *c) { } - TIME_SECTION("add type information"); + TIME_SECTION("add basic type information"); // Add "Basic" type information for (isize i = 0; i < Basic_COUNT; i++) { Type *t = &basic_types[i]; @@ -5331,16 +5342,7 @@ void check_parsed_files(Checker *c) { check_unchecked_bodies(c); TIME_SECTION("add type info for type definitions"); - for_array(i, c->info.definitions) { - Entity *e = c->info.definitions[i]; - if (e->kind == Entity_TypeName && e->type != nullptr) { - i64 align = type_align_of(e->type); - if (align > 0 && ptr_set_exists(&c->info.minimum_dependency_set, e)) { - add_type_info_type(&c->builtin_ctx, e->type); - } - } - } - + add_type_info_for_type_definitions(c); check_merge_queues_into_arrays(c); TIME_SECTION("check entry point"); From 0010e882a771fc834ea7902786f4b26e8860915c Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 12:11:50 +0000 Subject: [PATCH 13/29] Make PtrSet match Map --- src/ptr_set.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/ptr_set.cpp b/src/ptr_set.cpp index 96372fa86..9a9f6d252 100644 --- a/src/ptr_set.cpp +++ b/src/ptr_set.cpp @@ -17,7 +17,7 @@ struct PtrSetEntry { template struct PtrSet { - Array hashes; + Slice hashes; Array> entries; }; @@ -36,7 +36,7 @@ template void ptr_set_init(PtrSet *s, gbAllocator a, isize capacity) { capacity = next_pow2_isize(gb_max(16, capacity)); - array_init(&s->hashes, a, capacity); + slice_init(&s->hashes, a, capacity); array_init(&s->entries, a, 0, capacity); for (isize i = 0; i < capacity; i++) { s->hashes.data[i] = PTR_SET_SENTINEL; @@ -45,7 +45,7 @@ void ptr_set_init(PtrSet *s, gbAllocator a, isize capacity) { template void ptr_set_destroy(PtrSet *s) { - array_free(&s->hashes); + slice_free(&s->hashes, s->entries.allocator); array_free(&s->entries); } @@ -93,12 +93,14 @@ template void ptr_set_rehash(PtrSet *s, isize new_count) { isize i, j; PtrSet ns = {}; - ptr_set_init(&ns, s->hashes.allocator); - array_resize(&ns.hashes, new_count); - array_reserve(&ns.entries, s->entries.count); + new_count = next_pow2_isize(new_count); + ns.hashes = s->hashes; + ns.entries.allocator = s->entries.allocator; + slice_resize(&ns.hashes, s->entries.allocator, new_count); for (i = 0; i < new_count; i++) { ns.hashes.data[i] = PTR_SET_SENTINEL; } + array_reserve(&ns.entries, ARRAY_GROW_FORMULA(s->entries.count)); for (i = 0; i < s->entries.count; i++) { PtrSetEntry *e = &s->entries.data[i]; PtrSetFindResult fr; @@ -117,7 +119,7 @@ void ptr_set_rehash(PtrSet *s, isize new_count) { ptr_set_grow(&ns); } } - ptr_set_destroy(s); + array_free(&s->entries); *s = ns; } @@ -208,6 +210,8 @@ void ptr_set_remove(PtrSet *s, T ptr) { template gb_inline void ptr_set_clear(PtrSet *s) { - array_clear(&s->hashes); array_clear(&s->entries); + for (isize i = 0; i < s->hashes.count; i++) { + s->hashes.data[i] = PTR_SET_SENTINEL; + } } From 439fc86740a3a170b1ea5d2ce4816dcba03b21ad Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 12:42:19 +0000 Subject: [PATCH 14/29] Improve performance of the compiler hash table types and unify behaviour --- src/map.cpp | 100 +++++++++++++++++++++++-------------------- src/ptr_set.cpp | 71 ++++++++++++++++++++----------- src/string_map.cpp | 104 ++++++++++++++++++++++++--------------------- 3 files changed, 155 insertions(+), 120 deletions(-) diff --git a/src/map.cpp b/src/map.cpp index 3a34764bf..86def4f1b 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -7,12 +7,17 @@ #ifndef MAP_UTIL_STUFF #define MAP_UTIL_STUFF // NOTE(bill): This util stuff is the same for every `Map` + +typedef isize MapIndex; + struct MapFindResult { - isize hash_index; - isize entry_prev; - isize entry_index; + MapIndex hash_index; + MapIndex entry_prev; + MapIndex entry_index; }; +enum : MapIndex { MAP_SENTINEL = ~(MapIndex)0 }; + struct HashKey { u64 key; @@ -73,6 +78,7 @@ template void map_remove (Map *h, HashKey const &key); template void map_clear (Map *h); template void map_grow (Map *h); template void map_rehash (Map *h, isize new_count); +template void map_reserve (Map *h, isize cap); #if MAP_ENABLE_MULTI_MAP // Mutlivalued map procedure @@ -92,7 +98,7 @@ gb_inline void map_init(Map *h, gbAllocator a, isize capacity) { slice_init(&h->hashes, a, capacity); array_init(&h->entries, a, 0, capacity); for (isize i = 0; i < capacity; i++) { - h->hashes.data[i] = -1; + h->hashes.data[i] = MAP_SENTINEL; } } @@ -106,20 +112,20 @@ template gb_internal isize map__add_entry(Map *h, HashKey const &key) { MapEntry e = {}; e.key = key; - e.next = -1; + e.next = MAP_SENTINEL; array_add(&h->entries, e); return h->entries.count-1; } template gb_internal MapFindResult map__find(Map *h, HashKey const &key) { - MapFindResult fr = {-1, -1, -1}; + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; if (h->hashes.count == 0) { return fr; } fr.hash_index = key.key & (h->hashes.count-1); fr.entry_index = h->hashes.data[fr.hash_index]; - while (fr.entry_index >= 0) { + while (fr.entry_index != MAP_SENTINEL) { if (hash_key_equal(h->entries.data[fr.entry_index].key, key)) { return fr; } @@ -131,13 +137,13 @@ gb_internal MapFindResult map__find(Map *h, HashKey const &key) { template gb_internal MapFindResult map__find_from_entry(Map *h, MapEntry *e) { - MapFindResult fr = {-1, -1, -1}; + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; if (h->hashes.count == 0) { return fr; } fr.hash_index = e->key.key & (h->hashes.count-1); fr.entry_index = h->hashes.data[fr.hash_index]; - while (fr.entry_index >= 0) { + while (fr.entry_index != MAP_SENTINEL) { if (&h->entries.data[fr.entry_index] == e) { return fr; } @@ -159,44 +165,44 @@ gb_inline void map_grow(Map *h) { } template -void map_rehash(Map *h, isize new_count) { - isize i, j; - Map nh = {}; - new_count = next_pow2_isize(new_count); - nh.hashes = h->hashes; - nh.entries.allocator = h->entries.allocator; - slice_resize(&nh.hashes, h->entries.allocator, new_count); - for (i = 0; i < new_count; i++) { - nh.hashes.data[i] = -1; +void map_reset_entries(Map *h) { + isize i; + for (i = 0; i < h->hashes.count; i++) { + h->hashes.data[i] = MAP_SENTINEL; } - array_reserve(&nh.entries, ARRAY_GROW_FORMULA(h->entries.count)); for (i = 0; i < h->entries.count; i++) { - MapEntry *e = &h->entries.data[i]; MapFindResult fr; - if (nh.hashes.count == 0) { - map_grow(&nh); - } - fr = map__find(&nh, e->key); - j = map__add_entry(&nh, e->key); - if (fr.entry_prev < 0) { - nh.hashes.data[fr.hash_index] = j; + MapEntry *e = &h->entries.data[i]; + e->next = MAP_SENTINEL; + fr = map__find_from_entry(h, e); + if (fr.entry_prev == MAP_SENTINEL) { + h->hashes[fr.hash_index] = i; } else { - nh.entries.data[fr.entry_prev].next = j; - } - nh.entries.data[j].next = fr.entry_index; - nh.entries.data[j].value = e->value; - if (map__full(&nh)) { - map_grow(&nh); + h->entries[fr.entry_prev].next = i; } } - array_free(&h->entries); - *h = nh; +} + +template +void map_reserve(Map *h, isize cap) { + array_reserve(&h->entries, cap); + if (h->entries.count*2 < h->hashes.count) { + return; + } + slice_resize(&h->hashes, h->entries.allocator, cap*2); + map_reset_entries(h); +} + + +template +void map_rehash(Map *h, isize new_count) { + map_reserve(h, new_count); } template T *map_get(Map *h, HashKey const &key) { isize index = map__find(h, key).entry_index; - if (index >= 0) { + if (index != MAP_SENTINEL) { return &h->entries.data[index].value; } return nullptr; @@ -205,7 +211,7 @@ T *map_get(Map *h, HashKey const &key) { template T &map_must_get(Map *h, HashKey const &key) { isize index = map__find(h, key).entry_index; - GB_ASSERT(index >= 0); + GB_ASSERT(index != MAP_SENTINEL); return h->entries.data[index].value; } @@ -217,11 +223,11 @@ void map_set(Map *h, HashKey const &key, T const &value) { map_grow(h); } fr = map__find(h, key); - if (fr.entry_index >= 0) { + if (fr.entry_index != MAP_SENTINEL) { index = fr.entry_index; } else { index = map__add_entry(h, key); - if (fr.entry_prev >= 0) { + if (fr.entry_prev != MAP_SENTINEL) { h->entries.data[fr.entry_prev].next = index; } else { h->hashes.data[fr.hash_index] = index; @@ -238,7 +244,7 @@ void map_set(Map *h, HashKey const &key, T const &value) { template void map__erase(Map *h, MapFindResult const &fr) { MapFindResult last; - if (fr.entry_prev < 0) { + if (fr.entry_prev == MAP_SENTINEL) { h->hashes.data[fr.hash_index] = h->entries.data[fr.entry_index].next; } else { h->entries.data[fr.entry_prev].next = h->entries.data[fr.entry_index].next; @@ -251,7 +257,7 @@ void map__erase(Map *h, MapFindResult const &fr) { array_pop(&h->entries); last = map__find(h, h->entries.data[fr.entry_index].key); - if (last.entry_prev >= 0) { + if (last.entry_prev != MAP_SENTINEL) { h->entries.data[last.entry_prev].next = fr.entry_index; } else { h->hashes.data[last.hash_index] = fr.entry_index; @@ -261,7 +267,7 @@ void map__erase(Map *h, MapFindResult const &fr) { template void map_remove(Map *h, HashKey const &key) { MapFindResult fr = map__find(h, key); - if (fr.entry_index >= 0) { + if (fr.entry_index != MAP_SENTINEL) { map__erase(h, fr); } } @@ -270,7 +276,7 @@ template gb_inline void map_clear(Map *h) { array_clear(&h->entries); for (isize i = 0; i < h->hashes.count; i++) { - h->hashes.data[i] = -1; + h->hashes.data[i] = MAP_SENTINEL; } } @@ -279,7 +285,7 @@ gb_inline void map_clear(Map *h) { template MapEntry *multi_map_find_first(Map *h, HashKey const &key) { isize i = map__find(h, key).entry_index; - if (i < 0) { + if (i == MAP_SENTINEL) { return nullptr; } return &h->entries.data[i]; @@ -288,7 +294,7 @@ MapEntry *multi_map_find_first(Map *h, HashKey const &key) { template MapEntry *multi_map_find_next(Map *h, MapEntry *e) { isize i = e->next; - while (i >= 0) { + while (i != MAP_SENTINEL) { if (hash_key_equal(h->entries.data[i].key, e->key)) { return &h->entries.data[i]; } @@ -328,7 +334,7 @@ void multi_map_insert(Map *h, HashKey const &key, T const &value) { // Make fr = map__find(h, key); i = map__add_entry(h, key); - if (fr.entry_prev < 0) { + if (fr.entry_prev == MAP_SENTINEL) { h->hashes.data[fr.hash_index] = i; } else { h->entries.data[fr.entry_prev].next = i; @@ -344,7 +350,7 @@ void multi_map_insert(Map *h, HashKey const &key, T const &value) { template void multi_map_remove(Map *h, HashKey const &key, MapEntry *e) { MapFindResult fr = map__find_from_entry(h, e); - if (fr.entry_index >= 0) { + if (fr.entry_index != MAP_SENTINEL) { map__erase(h, fr); } } diff --git a/src/ptr_set.cpp b/src/ptr_set.cpp index 9a9f6d252..a17ab7e1c 100644 --- a/src/ptr_set.cpp +++ b/src/ptr_set.cpp @@ -30,6 +30,7 @@ template void ptr_set_remove (PtrSet *s, T ptr); template void ptr_set_clear (PtrSet *s); template void ptr_set_grow (PtrSet *s); template void ptr_set_rehash (PtrSet *s, isize new_count); +template void ptr_set_reserve(PtrSet *h, isize cap); template @@ -78,6 +79,25 @@ gb_internal PtrSetFindResult ptr_set__find(PtrSet *s, T ptr) { return fr; } +template +gb_internal PtrSetFindResult ptr_set__find_from_entry(PtrSet *s, PtrSetEntry *e) { + PtrSetFindResult fr = {PTR_SET_SENTINEL, PTR_SET_SENTINEL, PTR_SET_SENTINEL}; + if (s->hashes.count != 0) { + u64 hash = 0xcbf29ce484222325ull ^ cast(u64)cast(uintptr)e->ptr; + u64 n = cast(u64)s->hashes.count; + fr.hash_index = cast(PtrSetIndex)(hash & (n-1)); + fr.entry_index = s->hashes.data[fr.hash_index]; + while (fr.entry_index != PTR_SET_SENTINEL) { + if (&s->entries.data[fr.entry_index] == e) { + return fr; + } + fr.entry_prev = fr.entry_index; + fr.entry_index = s->entries.data[fr.entry_index].next; + } + } + return fr; +} + template gb_internal bool ptr_set__full(PtrSet *s) { return 0.75f * s->hashes.count <= s->entries.count; @@ -90,37 +110,38 @@ gb_inline void ptr_set_grow(PtrSet *s) { } template -void ptr_set_rehash(PtrSet *s, isize new_count) { - isize i, j; - PtrSet ns = {}; - new_count = next_pow2_isize(new_count); - ns.hashes = s->hashes; - ns.entries.allocator = s->entries.allocator; - slice_resize(&ns.hashes, s->entries.allocator, new_count); - for (i = 0; i < new_count; i++) { - ns.hashes.data[i] = PTR_SET_SENTINEL; +void ptr_set_reset_entries(PtrSet *s) { + PtrSetIndex i; + for (i = 0; i < cast(PtrSetIndex)s->hashes.count; i++) { + s->hashes.data[i] = PTR_SET_SENTINEL; } - array_reserve(&ns.entries, ARRAY_GROW_FORMULA(s->entries.count)); - for (i = 0; i < s->entries.count; i++) { - PtrSetEntry *e = &s->entries.data[i]; + for (i = 0; i < cast(PtrSetIndex)s->entries.count; i++) { PtrSetFindResult fr; - if (ns.hashes.count == 0) { - ptr_set_grow(&ns); - } - fr = ptr_set__find(&ns, e->ptr); - j = ptr_set__add_entry(&ns, e->ptr); + PtrSetEntry *e = &s->entries.data[i]; + e->next = PTR_SET_SENTINEL; + fr = ptr_set__find_from_entry(s, e); if (fr.entry_prev == PTR_SET_SENTINEL) { - ns.hashes.data[fr.hash_index] = cast(PtrSetIndex)j; + s->hashes[fr.hash_index] = i; } else { - ns.entries.data[fr.entry_prev].next = cast(PtrSetIndex)j; - } - ns.entries.data[j].next = fr.entry_index; - if (ptr_set__full(&ns)) { - ptr_set_grow(&ns); + s->entries[fr.entry_prev].next = i; } } - array_free(&s->entries); - *s = ns; +} + +template +void ptr_set_reserve(PtrSet *s, isize cap) { + array_reserve(&s->entries, cap); + if (s->entries.count*2 < s->hashes.count) { + return; + } + slice_resize(&s->hashes, s->entries.allocator, cap*2); + ptr_set_reset_entries(s); +} + + +template +void ptr_set_rehash(PtrSet *s, isize new_count) { + ptr_set_reserve(s, new_count); } template diff --git a/src/string_map.cpp b/src/string_map.cpp index c8715b60b..2d0da8c66 100644 --- a/src/string_map.cpp +++ b/src/string_map.cpp @@ -1,10 +1,16 @@ // NOTE(bill): This util stuff is the same for every `Map` + +typedef isize StringMapIndex; + struct StringMapFindResult { - isize hash_index; - isize entry_prev; - isize entry_index; + StringMapIndex hash_index; + StringMapIndex entry_prev; + StringMapIndex entry_index; }; +enum : StringMapIndex { STRING_MAP_SENTINEL = ~(StringMapIndex)0 }; + + struct StringHashKey { u64 hash; String string; @@ -65,6 +71,7 @@ template void string_map_remove (StringMap *h, StringH template void string_map_clear (StringMap *h); template void string_map_grow (StringMap *h); template void string_map_rehash (StringMap *h, isize new_count); +template void string_map_reserve (StringMap *h, isize cap); template gb_inline void string_map_init(StringMap *h, gbAllocator a, isize capacity) { @@ -72,7 +79,7 @@ gb_inline void string_map_init(StringMap *h, gbAllocator a, isize capacity) { slice_init(&h->hashes, a, capacity); array_init(&h->entries, a, 0, capacity); for (isize i = 0; i < capacity; i++) { - h->hashes.data[i] = -1; + h->hashes.data[i] = STRING_MAP_SENTINEL; } } @@ -86,18 +93,18 @@ template gb_internal isize string_map__add_entry(StringMap *h, StringHashKey const &key) { StringMapEntry e = {}; e.key = key; - e.next = -1; + e.next = STRING_MAP_SENTINEL; array_add(&h->entries, e); return h->entries.count-1; } template gb_internal StringMapFindResult string_map__find(StringMap *h, StringHashKey const &key) { - StringMapFindResult fr = {-1, -1, -1}; + StringMapFindResult fr = {STRING_MAP_SENTINEL, STRING_MAP_SENTINEL, STRING_MAP_SENTINEL}; if (h->hashes.count != 0) { fr.hash_index = key.hash & (h->hashes.count-1); fr.entry_index = h->hashes.data[fr.hash_index]; - while (fr.entry_index >= 0) { + while (fr.entry_index != STRING_MAP_SENTINEL) { if (string_hash_key_equal(h->entries.data[fr.entry_index].key, key)) { return fr; } @@ -110,11 +117,11 @@ gb_internal StringMapFindResult string_map__find(StringMap *h, StringHashKey template gb_internal StringMapFindResult string_map__find_from_entry(StringMap *h, StringMapEntry *e) { - StringMapFindResult fr = {-1, -1, -1}; + StringMapFindResult fr = {STRING_MAP_SENTINEL, STRING_MAP_SENTINEL, STRING_MAP_SENTINEL}; if (h->hashes.count != 0) { fr.hash_index = e->key.hash & (h->hashes.count-1); fr.entry_index = h->hashes.data[fr.hash_index]; - while (fr.entry_index >= 0) { + while (fr.entry_index != STRING_MAP_SENTINEL) { if (&h->entries.data[fr.entry_index] == e) { return fr; } @@ -136,45 +143,46 @@ gb_inline void string_map_grow(StringMap *h) { string_map_rehash(h, new_count); } + +template +void string_map_reset_entries(StringMap *h) { + isize i; + for (i = 0; i < h->hashes.count; i++) { + h->hashes.data[i] = STRING_MAP_SENTINEL; + } + for (i = 0; i < h->entries.count; i++) { + StringMapFindResult fr; + StringMapEntry *e = &h->entries.data[i]; + e->next = STRING_MAP_SENTINEL; + fr = string_map__find_from_entry(h, e); + if (fr.entry_prev == STRING_MAP_SENTINEL) { + h->hashes[fr.hash_index] = i; + } else { + h->entries[fr.entry_prev].next = i; + } + } +} + +template +void string_map_reserve(StringMap *h, isize cap) { + array_reserve(&h->entries, cap); + if (h->entries.count*2 < h->hashes.count) { + return; + } + slice_resize(&h->hashes, h->entries.allocator, cap*2); + string_map_reset_entries(h); +} + + template void string_map_rehash(StringMap *h, isize new_count) { - isize i, j; - StringMap nh = {}; - new_count = next_pow2_isize(new_count); - nh.hashes = h->hashes; - nh.entries.allocator = h->entries.allocator; - slice_resize(&nh.hashes, h->entries.allocator, new_count); - for (i = 0; i < new_count; i++) { - nh.hashes.data[i] = -1; - } - array_reserve(&nh.entries, ARRAY_GROW_FORMULA(h->entries.count)); - for (i = 0; i < h->entries.count; i++) { - StringMapEntry *e = &h->entries.data[i]; - StringMapFindResult fr; - if (nh.hashes.count == 0) { - string_map_grow(&nh); - } - fr = string_map__find(&nh, e->key); - j = string_map__add_entry(&nh, e->key); - if (fr.entry_prev < 0) { - nh.hashes.data[fr.hash_index] = j; - } else { - nh.entries.data[fr.entry_prev].next = j; - } - nh.entries.data[j].next = fr.entry_index; - nh.entries.data[j].value = e->value; - if (string_map__full(&nh)) { - string_map_grow(&nh); - } - } - array_free(&h->entries); - *h = nh; + string_map_reserve(h, new_count); } template T *string_map_get(StringMap *h, StringHashKey const &key) { isize index = string_map__find(h, key).entry_index; - if (index >= 0) { + if (index != STRING_MAP_SENTINEL) { return &h->entries.data[index].value; } return nullptr; @@ -193,7 +201,7 @@ gb_inline T *string_map_get(StringMap *h, char const *key) { template T &string_map_must_get(StringMap *h, StringHashKey const &key) { isize index = string_map__find(h, key).entry_index; - GB_ASSERT(index >= 0); + GB_ASSERT(index != STRING_MAP_SENTINEL); return h->entries.data[index].value; } @@ -215,11 +223,11 @@ void string_map_set(StringMap *h, StringHashKey const &key, T const &value) { string_map_grow(h); } fr = string_map__find(h, key); - if (fr.entry_index >= 0) { + if (fr.entry_index != STRING_MAP_SENTINEL) { index = fr.entry_index; } else { index = string_map__add_entry(h, key); - if (fr.entry_prev >= 0) { + if (fr.entry_prev != STRING_MAP_SENTINEL) { h->entries.data[fr.entry_prev].next = index; } else { h->hashes.data[fr.hash_index] = index; @@ -246,7 +254,7 @@ gb_inline void string_map_set(StringMap *h, char const *key, T const &value) template void string_map__erase(StringMap *h, StringMapFindResult const &fr) { StringMapFindResult last; - if (fr.entry_prev < 0) { + if (fr.entry_prev == STRING_MAP_SENTINEL) { h->hashes.data[fr.hash_index] = h->entries.data[fr.entry_index].next; } else { h->entries.data[fr.entry_prev].next = h->entries.data[fr.entry_index].next; @@ -257,7 +265,7 @@ void string_map__erase(StringMap *h, StringMapFindResult const &fr) { } h->entries.data[fr.entry_index] = h->entries.data[h->entries.count-1]; last = string_map__find(h, h->entries.data[fr.entry_index].key); - if (last.entry_prev >= 0) { + if (last.entry_prev != STRING_MAP_SENTINEL) { h->entries.data[last.entry_prev].next = fr.entry_index; } else { h->hashes.data[last.hash_index] = fr.entry_index; @@ -267,7 +275,7 @@ void string_map__erase(StringMap *h, StringMapFindResult const &fr) { template void string_map_remove(StringMap *h, StringHashKey const &key) { StringMapFindResult fr = string_map__find(h, key); - if (fr.entry_index >= 0) { + if (fr.entry_index != STRING_MAP_SENTINEL) { string_map__erase(h, fr); } } @@ -276,7 +284,7 @@ template gb_inline void string_map_clear(StringMap *h) { array_clear(&h->entries); for (isize i = 0; i < h->hashes.count; i++) { - h->hashes.data[i] = -1; + h->hashes.data[i] = STRING_MAP_SENTINEL; } } From e963fc4d6a2b8fc63f46bb57b2c727999ce39e29 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 12:51:28 +0000 Subject: [PATCH 15/29] Change map index types to `u32` from `isize` --- src/map.cpp | 27 +++++++++++++-------------- src/ptr_set.cpp | 9 ++++----- src/string_map.cpp | 29 ++++++++++++++--------------- 3 files changed, 31 insertions(+), 34 deletions(-) diff --git a/src/map.cpp b/src/map.cpp index 86def4f1b..cc91e51d4 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -8,7 +8,7 @@ #define MAP_UTIL_STUFF // NOTE(bill): This util stuff is the same for every `Map` -typedef isize MapIndex; +typedef u32 MapIndex; struct MapFindResult { MapIndex hash_index; @@ -58,13 +58,13 @@ gb_inline bool operator!=(HashKey a, HashKey b) { return !hash_key_equal(a, b); template struct MapEntry { HashKey key; - isize next; + MapIndex next; T value; }; template struct Map { - Slice hashes; + Slice hashes; Array > entries; }; @@ -109,12 +109,12 @@ gb_inline void map_destroy(Map *h) { } template -gb_internal isize map__add_entry(Map *h, HashKey const &key) { +gb_internal MapIndex map__add_entry(Map *h, HashKey const &key) { MapEntry e = {}; e.key = key; e.next = MAP_SENTINEL; array_add(&h->entries, e); - return h->entries.count-1; + return cast(MapIndex)(h->entries.count-1); } template @@ -123,7 +123,7 @@ gb_internal MapFindResult map__find(Map *h, HashKey const &key) { if (h->hashes.count == 0) { return fr; } - fr.hash_index = key.key & (h->hashes.count-1); + fr.hash_index = cast(MapIndex)(key.key & (h->hashes.count-1)); fr.entry_index = h->hashes.data[fr.hash_index]; while (fr.entry_index != MAP_SENTINEL) { if (hash_key_equal(h->entries.data[fr.entry_index].key, key)) { @@ -141,7 +141,7 @@ gb_internal MapFindResult map__find_from_entry(Map *h, MapEntry *e) { if (h->hashes.count == 0) { return fr; } - fr.hash_index = e->key.key & (h->hashes.count-1); + fr.hash_index = cast(MapIndex)(e->key.key & (h->hashes.count-1)); fr.entry_index = h->hashes.data[fr.hash_index]; while (fr.entry_index != MAP_SENTINEL) { if (&h->entries.data[fr.entry_index] == e) { @@ -166,19 +166,18 @@ gb_inline void map_grow(Map *h) { template void map_reset_entries(Map *h) { - isize i; - for (i = 0; i < h->hashes.count; i++) { + for (isize i = 0; i < h->hashes.count; i++) { h->hashes.data[i] = MAP_SENTINEL; } - for (i = 0; i < h->entries.count; i++) { + for (isize i = 0; i < h->entries.count; i++) { MapFindResult fr; MapEntry *e = &h->entries.data[i]; e->next = MAP_SENTINEL; fr = map__find_from_entry(h, e); if (fr.entry_prev == MAP_SENTINEL) { - h->hashes[fr.hash_index] = i; + h->hashes[fr.hash_index] = cast(MapIndex)i; } else { - h->entries[fr.entry_prev].next = i; + h->entries[fr.entry_prev].next = cast(MapIndex)i; } } } @@ -217,7 +216,7 @@ T &map_must_get(Map *h, HashKey const &key) { template void map_set(Map *h, HashKey const &key, T const &value) { - isize index; + MapIndex index; MapFindResult fr; if (h->hashes.count == 0) { map_grow(h); @@ -327,7 +326,7 @@ void multi_map_get_all(Map *h, HashKey const &key, T *items) { template void multi_map_insert(Map *h, HashKey const &key, T const &value) { MapFindResult fr; - isize i; + MapIndex i; if (h->hashes.count == 0) { map_grow(h); } diff --git a/src/ptr_set.cpp b/src/ptr_set.cpp index a17ab7e1c..0ca1921e8 100644 --- a/src/ptr_set.cpp +++ b/src/ptr_set.cpp @@ -111,19 +111,18 @@ gb_inline void ptr_set_grow(PtrSet *s) { template void ptr_set_reset_entries(PtrSet *s) { - PtrSetIndex i; - for (i = 0; i < cast(PtrSetIndex)s->hashes.count; i++) { + for (isize i = 0; i < s->hashes.count; i++) { s->hashes.data[i] = PTR_SET_SENTINEL; } - for (i = 0; i < cast(PtrSetIndex)s->entries.count; i++) { + for (isize i = 0; i < s->entries.count; i++) { PtrSetFindResult fr; PtrSetEntry *e = &s->entries.data[i]; e->next = PTR_SET_SENTINEL; fr = ptr_set__find_from_entry(s, e); if (fr.entry_prev == PTR_SET_SENTINEL) { - s->hashes[fr.hash_index] = i; + s->hashes[fr.hash_index] = cast(PtrSetIndex)i; } else { - s->entries[fr.entry_prev].next = i; + s->entries[fr.entry_prev].next = cast(PtrSetIndex)i; } } } diff --git a/src/string_map.cpp b/src/string_map.cpp index 2d0da8c66..448af624d 100644 --- a/src/string_map.cpp +++ b/src/string_map.cpp @@ -1,6 +1,6 @@ // NOTE(bill): This util stuff is the same for every `Map` -typedef isize StringMapIndex; +typedef u32 StringMapIndex; struct StringMapFindResult { StringMapIndex hash_index; @@ -40,14 +40,14 @@ bool operator!=(StringHashKey const &a, StringHashKey const &b) { return !string template struct StringMapEntry { - StringHashKey key; - isize next; - T value; + StringHashKey key; + StringMapIndex next; + T value; }; template struct StringMap { - Slice hashes; + Slice hashes; Array > entries; }; @@ -90,19 +90,19 @@ gb_inline void string_map_destroy(StringMap *h) { } template -gb_internal isize string_map__add_entry(StringMap *h, StringHashKey const &key) { +gb_internal StringMapIndex string_map__add_entry(StringMap *h, StringHashKey const &key) { StringMapEntry e = {}; e.key = key; e.next = STRING_MAP_SENTINEL; array_add(&h->entries, e); - return h->entries.count-1; + return cast(StringMapIndex)(h->entries.count-1); } template gb_internal StringMapFindResult string_map__find(StringMap *h, StringHashKey const &key) { StringMapFindResult fr = {STRING_MAP_SENTINEL, STRING_MAP_SENTINEL, STRING_MAP_SENTINEL}; if (h->hashes.count != 0) { - fr.hash_index = key.hash & (h->hashes.count-1); + fr.hash_index = cast(StringMapIndex)(key.hash & (h->hashes.count-1)); fr.entry_index = h->hashes.data[fr.hash_index]; while (fr.entry_index != STRING_MAP_SENTINEL) { if (string_hash_key_equal(h->entries.data[fr.entry_index].key, key)) { @@ -119,7 +119,7 @@ template gb_internal StringMapFindResult string_map__find_from_entry(StringMap *h, StringMapEntry *e) { StringMapFindResult fr = {STRING_MAP_SENTINEL, STRING_MAP_SENTINEL, STRING_MAP_SENTINEL}; if (h->hashes.count != 0) { - fr.hash_index = e->key.hash & (h->hashes.count-1); + fr.hash_index = cast(StringMapIndex)(e->key.hash & (h->hashes.count-1)); fr.entry_index = h->hashes.data[fr.hash_index]; while (fr.entry_index != STRING_MAP_SENTINEL) { if (&h->entries.data[fr.entry_index] == e) { @@ -146,19 +146,18 @@ gb_inline void string_map_grow(StringMap *h) { template void string_map_reset_entries(StringMap *h) { - isize i; - for (i = 0; i < h->hashes.count; i++) { + for (isize i = 0; i < h->hashes.count; i++) { h->hashes.data[i] = STRING_MAP_SENTINEL; } - for (i = 0; i < h->entries.count; i++) { + for (isize i = 0; i < h->entries.count; i++) { StringMapFindResult fr; StringMapEntry *e = &h->entries.data[i]; e->next = STRING_MAP_SENTINEL; fr = string_map__find_from_entry(h, e); if (fr.entry_prev == STRING_MAP_SENTINEL) { - h->hashes[fr.hash_index] = i; + h->hashes[fr.hash_index] = cast(StringMapIndex)i; } else { - h->entries[fr.entry_prev].next = i; + h->entries[fr.entry_prev].next = cast(StringMapIndex)i; } } } @@ -217,7 +216,7 @@ gb_inline T &string_map_must_get(StringMap *h, char const *key) { template void string_map_set(StringMap *h, StringHashKey const &key, T const &value) { - isize index; + StringMapIndex index; StringMapFindResult fr; if (h->hashes.count == 0) { string_map_grow(h); From e95204908a12d4386ba9bda6de1fed7c73f66d29 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 16:34:37 +0000 Subject: [PATCH 16/29] Add `PtrMap`, begin working change `Map` to `PtrMap` where possible --- src/checker.cpp | 15 +-- src/checker.hpp | 2 +- src/common.cpp | 1 + src/ptr_map.cpp | 318 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 326 insertions(+), 10 deletions(-) create mode 100644 src/ptr_map.cpp diff --git a/src/checker.cpp b/src/checker.cpp index 125893d11..643673afe 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1135,8 +1135,7 @@ isize type_info_index(CheckerInfo *info, Type *type, bool error_on_failure) { mutex_lock(&info->type_info_mutex); isize entry_index = -1; - HashKey key = hash_type(type); - isize *found_entry_index = map_get(&info->type_info_map, key); + isize *found_entry_index = map_get(&info->type_info_map, type); if (found_entry_index) { entry_index = *found_entry_index; } @@ -1145,11 +1144,10 @@ isize type_info_index(CheckerInfo *info, Type *type, bool error_on_failure) { // TODO(bill): This is O(n) and can be very slow for_array(i, info->type_info_map.entries){ auto *e = &info->type_info_map.entries[i]; - Type *prev_type = cast(Type *)cast(uintptr)e->key.key; - if (are_types_identical(prev_type, type)) { + if (are_types_identical(e->key, type)) { entry_index = e->value; // NOTE(bill): Add it to the search map - map_set(&info->type_info_map, key, entry_index); + map_set(&info->type_info_map, type, entry_index); break; } } @@ -1484,7 +1482,7 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) { add_type_info_dependency(c->decl, t); - auto found = map_get(&c->info->type_info_map, hash_type(t)); + auto found = map_get(&c->info->type_info_map, t); if (found != nullptr) { // Types have already been added return; @@ -1494,8 +1492,7 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) { isize ti_index = -1; for_array(i, c->info->type_info_map.entries) { auto *e = &c->info->type_info_map.entries[i]; - Type *prev_type = cast(Type *)cast(uintptr)e->key.key; - if (are_types_identical(t, prev_type)) { + if (are_types_identical(t, e->key)) { // Duplicate entry ti_index = e->value; prev = true; @@ -1508,7 +1505,7 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) { ti_index = c->info->type_info_types.count; array_add(&c->info->type_info_types, t); } - map_set(&c->checker->info.type_info_map, hash_type(t), ti_index); + map_set(&c->checker->info.type_info_map, t, ti_index); if (prev) { // NOTE(bill): If a previous one exists already, no need to continue diff --git a/src/checker.hpp b/src/checker.hpp index c65d766ba..e7f152eb2 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -321,7 +321,7 @@ struct CheckerInfo { BlockingMutex type_info_mutex; // NOT recursive Array type_info_types; - Map type_info_map; // Key: Type * + PtrMap type_info_map; BlockingMutex foreign_mutex; // NOT recursive StringMap foreigns; diff --git a/src/common.cpp b/src/common.cpp index 7af7026b9..5d7c87b6d 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -277,6 +277,7 @@ gb_global bool global_module_path_set = false; #include "string_map.cpp" #include "map.cpp" +#include "ptr_map.cpp" #include "ptr_set.cpp" #include "string_set.cpp" #include "priority_queue.cpp" diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp new file mode 100644 index 000000000..af3cf86f9 --- /dev/null +++ b/src/ptr_map.cpp @@ -0,0 +1,318 @@ +#define PTR_MAP_ENABLE_MULTI_MAP 1 + + +template +struct PtrMapEntry { + static_assert(sizeof(K) == sizeof(void *), "Key size must be pointer size"); + + u32 hash; + MapIndex next; + K key; + V value; +}; + +template +struct PtrMap { + Slice hashes; + Array > entries; +}; + + +template +u32 ptr_map_hash_key(K key) { + return gb_fnv32a(&key, gb_size_of(key)); +} + +template void map_init (PtrMap *h, gbAllocator a, isize capacity = 16); +template void map_destroy (PtrMap *h); +template V * map_get (PtrMap *h, K key); +template void map_set (PtrMap *h, K key, V const &value); +template void map_remove (PtrMap *h, K key); +template void map_clear (PtrMap *h); +template void map_grow (PtrMap *h); +template void map_rehash (PtrMap *h, isize new_count); +template void map_reserve (PtrMap *h, isize cap); + +#if PTR_MAP_ENABLE_MULTI_MAP +// Mutlivalued map procedure +template PtrMapEntry * multi_map_find_first(PtrMap *h, K key); +template PtrMapEntry * multi_map_find_next (PtrMap *h, PtrMapEntry *e); + +template isize multi_map_count (PtrMap *h, K key); +template void multi_map_get_all (PtrMap *h, K key, V *items); +template void multi_map_insert (PtrMap *h, K key, V const &value); +template void multi_map_remove (PtrMap *h, K key, PtrMapEntry *e); +template void multi_map_remove_all(PtrMap *h, K key); +#endif + +template +gb_inline void map_init(PtrMap *h, gbAllocator a, isize capacity) { + capacity = next_pow2_isize(capacity); + slice_init(&h->hashes, a, capacity); + array_init(&h->entries, a, 0, capacity); + for (isize i = 0; i < capacity; i++) { + h->hashes.data[i] = MAP_SENTINEL; + } +} + +template +gb_inline void map_destroy(PtrMap *h) { + slice_free(&h->hashes, h->entries.allocator); + array_free(&h->entries); +} + +template +gb_internal MapIndex map__add_entry(PtrMap *h, K key) { + PtrMapEntry e = {}; + e.hash = ptr_map_hash_key(key); + e.key = key; + e.next = MAP_SENTINEL; + array_add(&h->entries, e); + return cast(MapIndex)(h->entries.count-1); +} + +template +gb_internal MapFindResult map__find(PtrMap *h, K key) { + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; + if (h->hashes.count == 0) { + return fr; + } + u32 hash = ptr_map_hash_key(key); + fr.hash_index = cast(MapIndex)(hash & (h->hashes.count-1)); + fr.entry_index = h->hashes.data[fr.hash_index]; + while (fr.entry_index != MAP_SENTINEL) { + if (h->entries.data[fr.entry_index].key == key) { + return fr; + } + fr.entry_prev = fr.entry_index; + fr.entry_index = h->entries.data[fr.entry_index].next; + } + return fr; +} + +template +gb_internal MapFindResult map__find_from_entry(PtrMap *h, PtrMapEntry *e) { + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; + if (h->hashes.count == 0) { + return fr; + } + fr.hash_index = cast(MapIndex)(e->hash & (h->hashes.count-1)); + fr.entry_index = h->hashes.data[fr.hash_index]; + while (fr.entry_index != MAP_SENTINEL) { + if (&h->entries.data[fr.entry_index] == e) { + return fr; + } + fr.entry_prev = fr.entry_index; + fr.entry_index = h->entries.data[fr.entry_index].next; + } + return fr; +} + +template +gb_internal b32 map__full(PtrMap *h) { + return 0.75f * h->hashes.count <= h->entries.count; +} + +template +gb_inline void map_grow(PtrMap *h) { + isize new_count = gb_max(h->hashes.count<<1, 16); + map_rehash(h, new_count); +} + +template +void map_reset_entries(PtrMap *h) { + for (isize i = 0; i < h->hashes.count; i++) { + h->hashes.data[i] = MAP_SENTINEL; + } + for (isize i = 0; i < h->entries.count; i++) { + MapFindResult fr; + PtrMapEntry *e = &h->entries.data[i]; + e->next = MAP_SENTINEL; + fr = map__find_from_entry(h, e); + if (fr.entry_prev == MAP_SENTINEL) { + h->hashes[fr.hash_index] = cast(MapIndex)i; + } else { + h->entries[fr.entry_prev].next = cast(MapIndex)i; + } + } +} + +template +void map_reserve(PtrMap *h, isize cap) { + array_reserve(&h->entries, cap); + if (h->entries.count*2 < h->hashes.count) { + return; + } + slice_resize(&h->hashes, h->entries.allocator, cap*2); + map_reset_entries(h); +} + + +template +void map_rehash(PtrMap *h, isize new_count) { + map_reserve(h, new_count); +} + +template +V *map_get(PtrMap *h, K key) { + isize index = map__find(h, key).entry_index; + if (index != MAP_SENTINEL) { + return &h->entries.data[index].value; + } + return nullptr; +} + +template +V &map_must_get(PtrMap *h, K key) { + isize index = map__find(h, key).entry_index; + GB_ASSERT(index != MAP_SENTINEL); + return h->entries.data[index].value; +} + +template +void map_set(PtrMap *h, K key, V const &value) { + MapIndex index; + MapFindResult fr; + if (h->hashes.count == 0) { + map_grow(h); + } + fr = map__find(h, key); + if (fr.entry_index != MAP_SENTINEL) { + index = fr.entry_index; + } else { + index = map__add_entry(h, key); + if (fr.entry_prev != MAP_SENTINEL) { + h->entries.data[fr.entry_prev].next = index; + } else { + h->hashes.data[fr.hash_index] = index; + } + } + h->entries.data[index].value = value; + + if (map__full(h)) { + map_grow(h); + } +} + + +template +void map__erase(PtrMap *h, MapFindResult const &fr) { + MapFindResult last; + if (fr.entry_prev == MAP_SENTINEL) { + h->hashes.data[fr.hash_index] = h->entries.data[fr.entry_index].next; + } else { + h->entries.data[fr.entry_prev].next = h->entries.data[fr.entry_index].next; + } + if (fr.entry_index == h->entries.count-1) { + array_pop(&h->entries); + return; + } + h->entries.data[fr.entry_index] = h->entries.data[h->entries.count-1]; + array_pop(&h->entries); + + last = map__find(h, h->entries.data[fr.entry_index].key); + if (last.entry_prev != MAP_SENTINEL) { + h->entries.data[last.entry_prev].next = fr.entry_index; + } else { + h->hashes.data[last.hash_index] = fr.entry_index; + } +} + +template +void map_remove(PtrMap *h, HashKey const &key) { + MapFindResult fr = map__find(h, key); + if (fr.entry_index != MAP_SENTINEL) { + map__erase(h, fr); + } +} + +template +gb_inline void map_clear(PtrMap *h) { + array_clear(&h->entries); + for (isize i = 0; i < h->hashes.count; i++) { + h->hashes.data[i] = MAP_SENTINEL; + } +} + + +#if PTR_MAP_ENABLE_MULTI_MAP +template +PtrMapEntry *multi_map_find_first(PtrMap *h, HashKey const &key) { + isize i = map__find(h, key).entry_index; + if (i == MAP_SENTINEL) { + return nullptr; + } + return &h->entries.data[i]; +} + +template +PtrMapEntry *multi_map_find_next(PtrMap *h, PtrMapEntry *e) { + isize i = e->next; + while (i != MAP_SENTINEL) { + if (hash_key_equal(h->entries.data[i].key, e->key)) { + return &h->entries.data[i]; + } + i = h->entries.data[i].next; + } + return nullptr; +} + +template +isize multi_map_count(PtrMap *h, HashKey const &key) { + isize count = 0; + PtrMapEntry *e = multi_map_find_first(h, key); + while (e != nullptr) { + count++; + e = multi_map_find_next(h, e); + } + return count; +} + +template +void multi_map_get_all(PtrMap *h, K key, V *items) { + isize i = 0; + PtrMapEntry *e = multi_map_find_first(h, key); + while (e != nullptr) { + items[i++] = e->value; + e = multi_map_find_next(h, e); + } +} + +template +void multi_map_insert(PtrMap *h, K key, V const &value) { + MapFindResult fr; + MapIndex i; + if (h->hashes.count == 0) { + map_grow(h); + } + // Make + fr = map__find(h, key); + i = map__add_entry(h, key); + if (fr.entry_prev == MAP_SENTINEL) { + h->hashes.data[fr.hash_index] = i; + } else { + h->entries.data[fr.entry_prev].next = i; + } + h->entries.data[i].next = fr.entry_index; + h->entries.data[i].value = value; + // Grow if needed + if (map__full(h)) { + map_grow(h); + } +} + +template +void multi_map_remove(PtrMap *h, HashKey const &key, PtrMapEntry *e) { + MapFindResult fr = map__find_from_entry(h, e); + if (fr.entry_index != MAP_SENTINEL) { + map__erase(h, fr); + } +} + +template +void multi_map_remove_all(PtrMap *h, HashKey const &key) { + while (map_get(h, key) != nullptr) { + map_remove(h, key); + } +} +#endif From 6be104e5215668aad05c68cb26e1dd9fe898fc11 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 16:43:53 +0000 Subject: [PATCH 17/29] Make llvm backend code use `PtrMap`; remove dead code --- src/llvm_backend.cpp | 15 ++++------ src/llvm_backend.hpp | 26 ++++++++--------- src/llvm_backend_debug.cpp | 4 +-- src/llvm_backend_expr.cpp | 6 ++-- src/llvm_backend_general.cpp | 56 ++++++++++++++++-------------------- src/llvm_backend_opt.cpp | 2 +- src/llvm_backend_proc.cpp | 2 +- src/llvm_backend_stmt.cpp | 10 +++---- src/llvm_backend_utility.cpp | 6 ++-- 9 files changed, 58 insertions(+), 69 deletions(-) diff --git a/src/llvm_backend.cpp b/src/llvm_backend.cpp index 928efbb54..dbe780284 100644 --- a/src/llvm_backend.cpp +++ b/src/llvm_backend.cpp @@ -123,8 +123,7 @@ lbValue lb_get_equal_proc_for_type(lbModule *m, Type *type) { Type *pt = alloc_type_pointer(type); LLVMTypeRef ptr_type = lb_type(m, pt); - auto key = hash_type(type); - lbProcedure **found = map_get(&m->equal_procs, key); + lbProcedure **found = map_get(&m->equal_procs, type); lbProcedure *compare_proc = nullptr; if (found) { compare_proc = *found; @@ -140,7 +139,7 @@ lbValue lb_get_equal_proc_for_type(lbModule *m, Type *type) { String proc_name = make_string_c(str); lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_equal_proc); - map_set(&m->equal_procs, key, p); + map_set(&m->equal_procs, type, p); lb_begin_procedure_body(p); LLVMValueRef x = LLVMGetParam(p->value, 0); @@ -279,8 +278,7 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) { Type *pt = alloc_type_pointer(type); - auto key = hash_type(type); - lbProcedure **found = map_get(&m->hasher_procs, key); + lbProcedure **found = map_get(&m->hasher_procs, type); if (found) { GB_ASSERT(*found != nullptr); return {(*found)->value, (*found)->type}; @@ -294,7 +292,7 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) { String proc_name = make_string_c(str); lbProcedure *p = lb_create_dummy_procedure(m, proc_name, t_hasher_proc); - map_set(&m->hasher_procs, key, p); + map_set(&m->hasher_procs, type, p); lb_begin_procedure_body(p); defer (lb_end_procedure_body(p)); @@ -433,7 +431,7 @@ lbValue lb_get_hasher_proc_for_type(lbModule *m, Type *type) { lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, Ast *expr, lbProcedure *parent) { - lbProcedure **found = map_get(&m->gen->anonymous_proc_lits, hash_pointer(expr)); + lbProcedure **found = map_get(&m->gen->anonymous_proc_lits, expr); if (found) { return lb_find_procedure_value_from_entity(m, (*found)->entity); } @@ -473,8 +471,7 @@ lbValue lb_generate_anonymous_proc_lit(lbModule *m, String const &prefix_name, A string_map_set(&m->members, name, value); } - map_set(&m->anonymous_proc_lits, hash_pointer(expr), p); - map_set(&m->gen->anonymous_proc_lits, hash_pointer(expr), p); + map_set(&m->gen->anonymous_proc_lits, expr, p); return value; } diff --git a/src/llvm_backend.hpp b/src/llvm_backend.hpp index 16c9f752e..7a93b7088 100644 --- a/src/llvm_backend.hpp +++ b/src/llvm_backend.hpp @@ -114,25 +114,23 @@ struct lbModule { CheckerInfo *info; AstPackage *pkg; // associated - Map types; // Key: Type * - Map struct_field_remapping; // Key: LLVMTypeRef or Type * - Map llvm_types; // Key: LLVMTypeRef + PtrMap types; + PtrMap struct_field_remapping; // Key: LLVMTypeRef or Type * i32 internal_type_level; - Map values; // Key: Entity * - Map soa_values; // Key: Entity * + PtrMap values; + PtrMap soa_values; StringMap members; StringMap procedures; - Map procedure_values; // Key: LLVMValueRef + PtrMap procedure_values; Array missing_procedures_to_check; StringMap const_strings; - Map anonymous_proc_lits; // Key: Ast * - Map function_type_map; // Key: Type * + PtrMap function_type_map; - Map equal_procs; // Key: Type * - Map hasher_procs; // Key: Type * + PtrMap equal_procs; + PtrMap hasher_procs; u32 nested_type_name_guid; @@ -143,7 +141,7 @@ struct lbModule { LLVMDIBuilderRef debug_builder; LLVMMetadataRef debug_compile_unit; - Map debug_values; // Key: Pointer + PtrMap debug_values; Array debug_incomplete_types; }; @@ -155,11 +153,11 @@ struct lbGenerator { Array output_temp_paths; String output_base; String output_name; - Map modules; // Key: AstPackage * - Map modules_through_ctx; // Key: LLVMContextRef * + PtrMap modules; + PtrMap modules_through_ctx; lbModule default_module; - Map anonymous_proc_lits; // Key: Ast * + PtrMap anonymous_proc_lits; std::atomic global_array_index; std::atomic global_generated_index; diff --git a/src/llvm_backend_debug.cpp b/src/llvm_backend_debug.cpp index 4a73c03f2..f39034d04 100644 --- a/src/llvm_backend_debug.cpp +++ b/src/llvm_backend_debug.cpp @@ -2,7 +2,7 @@ LLVMMetadataRef lb_get_llvm_metadata(lbModule *m, void *key) { if (key == nullptr) { return nullptr; } - auto found = map_get(&m->debug_values, hash_pointer(key)); + auto found = map_get(&m->debug_values, key); if (found) { return *found; } @@ -10,7 +10,7 @@ LLVMMetadataRef lb_get_llvm_metadata(lbModule *m, void *key) { } void lb_set_llvm_metadata(lbModule *m, void *key, LLVMMetadataRef value) { if (key != nullptr) { - map_set(&m->debug_values, hash_pointer(key), value); + map_set(&m->debug_values, key, value); } } diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp index 8fd39fdb9..006d396ed 100644 --- a/src/llvm_backend_expr.cpp +++ b/src/llvm_backend_expr.cpp @@ -3142,7 +3142,7 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) { } lbAddr lb_get_soa_variable_addr(lbProcedure *p, Entity *e) { - return map_must_get(&p->module->soa_values, hash_entity(e)); + return map_must_get(&p->module->soa_values, e); } lbValue lb_get_using_variable(lbProcedure *p, Entity *e) { GB_ASSERT(e->kind == Entity_Variable && e->flags & EntityFlag_Using); @@ -3150,7 +3150,7 @@ lbValue lb_get_using_variable(lbProcedure *p, Entity *e) { Entity *parent = e->using_parent; Selection sel = lookup_field(parent->type, name, false); GB_ASSERT(sel.entity != nullptr); - lbValue *pv = map_get(&p->module->values, hash_entity(parent)); + lbValue *pv = map_get(&p->module->values, parent); lbValue v = {}; @@ -3190,7 +3190,7 @@ lbAddr lb_build_addr_from_entity(lbProcedure *p, Entity *e, Ast *expr) { lbValue v = {}; - lbValue *found = map_get(&p->module->values, hash_entity(e)); + lbValue *found = map_get(&p->module->values, e); if (found) { v = *found; } else if (e->kind == Entity_Variable && e->flags & EntityFlag_Using) { diff --git a/src/llvm_backend_general.cpp b/src/llvm_backend_general.cpp index 5c664f0e0..68bba2206 100644 --- a/src/llvm_backend_general.cpp +++ b/src/llvm_backend_general.cpp @@ -57,14 +57,12 @@ void lb_init_module(lbModule *m, Checker *c) { gbAllocator a = heap_allocator(); map_init(&m->types, a); map_init(&m->struct_field_remapping, a); - map_init(&m->llvm_types, a); map_init(&m->values, a); map_init(&m->soa_values, a); string_map_init(&m->members, a); map_init(&m->procedure_values, a); string_map_init(&m->procedures, a); string_map_init(&m->const_strings, a); - map_init(&m->anonymous_proc_lits, a); map_init(&m->function_type_map, a); map_init(&m->equal_procs, a); map_init(&m->hasher_procs, a); @@ -133,20 +131,20 @@ bool lb_init_generator(lbGenerator *gen, Checker *c) { auto m = gb_alloc_item(permanent_allocator(), lbModule); m->pkg = pkg; m->gen = gen; - map_set(&gen->modules, hash_pointer(pkg), m); + map_set(&gen->modules, pkg, m); lb_init_module(m, c); } } gen->default_module.gen = gen; - map_set(&gen->modules, hash_pointer(nullptr), &gen->default_module); + map_set(&gen->modules, cast(AstPackage *)nullptr, &gen->default_module); lb_init_module(&gen->default_module, c); for_array(i, gen->modules.entries) { lbModule *m = gen->modules.entries[i].value; LLVMContextRef ctx = LLVMGetModuleContext(m->mod); - map_set(&gen->modules_through_ctx, hash_pointer(ctx), m); + map_set(&gen->modules_through_ctx, ctx, m); } return true; @@ -251,7 +249,7 @@ bool lb_is_instr_terminating(LLVMValueRef instr) { lbModule *lb_pkg_module(lbGenerator *gen, AstPackage *pkg) { - auto *found = map_get(&gen->modules, hash_pointer(pkg)); + auto *found = map_get(&gen->modules, pkg); if (found) { return *found; } @@ -1590,7 +1588,7 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { return lb_type_internal(m, base); } - LLVMTypeRef *found = map_get(&m->types, hash_type(base)); + LLVMTypeRef *found = map_get(&m->types, base); if (found) { LLVMTypeKind kind = LLVMGetTypeKind(*found); if (kind == LLVMStructTypeKind) { @@ -1600,7 +1598,7 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { return llvm_type; } llvm_type = LLVMStructCreateNamed(ctx, name); - map_set(&m->types, hash_type(type), llvm_type); + map_set(&m->types, type, llvm_type); lb_clone_struct_type(llvm_type, *found); return llvm_type; } @@ -1616,7 +1614,7 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { return llvm_type; } llvm_type = LLVMStructCreateNamed(ctx, name); - map_set(&m->types, hash_type(type), llvm_type); + map_set(&m->types, type, llvm_type); lb_clone_struct_type(llvm_type, lb_type(m, base)); return llvm_type; } @@ -1697,7 +1695,7 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { for_array(i, entries_field_remapping) { entries_field_remapping[i] = cast(i32)i; } - map_set(&m->struct_field_remapping, hash_pointer(fields[1]), entries_field_remapping); + map_set(&m->struct_field_remapping, cast(void *)fields[1], entries_field_remapping); } return LLVMStructTypeInContext(ctx, fields, field_count, false); @@ -1721,8 +1719,8 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { field_remapping[0] = 0; LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields, gb_count_of(fields), false); - map_set(&m->struct_field_remapping, hash_pointer(struct_type), field_remapping); - map_set(&m->struct_field_remapping, hash_pointer(type), field_remapping); + map_set(&m->struct_field_remapping, cast(void *)struct_type, field_remapping); + map_set(&m->struct_field_remapping, cast(void *)type, field_remapping); return struct_type; } @@ -1768,8 +1766,8 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { } LLVMTypeRef struct_type = LLVMStructTypeInContext(ctx, fields.data, cast(unsigned)fields.count, type->Struct.is_packed); - map_set(&m->struct_field_remapping, hash_pointer(struct_type), field_remapping); - map_set(&m->struct_field_remapping, hash_pointer(type), field_remapping); + map_set(&m->struct_field_remapping, cast(void *)struct_type, field_remapping); + map_set(&m->struct_field_remapping, cast(void *)type, field_remapping); #if 0 GB_ASSERT_MSG(lb_sizeof(struct_type) == full_type_size, "(%lld) %s vs (%lld) %s", @@ -1930,7 +1928,7 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { LLVMGetTypeContext(ft->ret.type), ft->ctx, LLVMGetGlobalContext()); } - map_set(&m->function_type_map, hash_type(type), ft); + map_set(&m->function_type_map, type, ft); LLVMTypeRef new_abi_fn_ptr_type = lb_function_type_to_llvm_ptr(ft, type->Proc.c_vararg); LLVMTypeRef new_abi_fn_type = LLVMGetElementType(new_abi_fn_ptr_type); @@ -1991,7 +1989,7 @@ LLVMTypeRef lb_type_internal(lbModule *m, Type *type) { LLVMTypeRef lb_type(lbModule *m, Type *type) { type = default_type(type); - LLVMTypeRef *found = map_get(&m->types, hash_type(type)); + LLVMTypeRef *found = map_get(&m->types, type); if (found) { return *found; } @@ -2002,21 +2000,18 @@ LLVMTypeRef lb_type(lbModule *m, Type *type) { llvm_type = lb_type_internal(m, type); m->internal_type_level -= 1; if (m->internal_type_level == 0) { - map_set(&m->types, hash_type(type), llvm_type); - if (is_type_named(type)) { - map_set(&m->llvm_types, hash_pointer(llvm_type), type); - } + map_set(&m->types, type, llvm_type); } return llvm_type; } lbFunctionType *lb_get_function_type(lbModule *m, lbProcedure *p, Type *pt) { lbFunctionType **ft_found = nullptr; - ft_found = map_get(&m->function_type_map, hash_type(pt)); + ft_found = map_get(&m->function_type_map, pt); if (!ft_found) { LLVMTypeRef llvm_proc_type = lb_type(p->module, pt); gb_unused(llvm_proc_type); - ft_found = map_get(&m->function_type_map, hash_type(pt)); + ft_found = map_get(&m->function_type_map, pt); } GB_ASSERT(ft_found != nullptr); @@ -2027,12 +2022,11 @@ void lb_ensure_abi_function_type(lbModule *m, lbProcedure *p) { if (p->abi_function_type != nullptr) { return; } - auto hash = hash_type(p->type); - lbFunctionType **ft_found = map_get(&m->function_type_map, hash); + lbFunctionType **ft_found = map_get(&m->function_type_map, p->type); if (ft_found == nullptr) { LLVMTypeRef llvm_proc_type = lb_type(p->module, p->type); gb_unused(llvm_proc_type); - ft_found = map_get(&m->function_type_map, hash); + ft_found = map_get(&m->function_type_map, p->type); } GB_ASSERT(ft_found != nullptr); p->abi_function_type = *ft_found; @@ -2041,7 +2035,7 @@ void lb_ensure_abi_function_type(lbModule *m, lbProcedure *p) { void lb_add_entity(lbModule *m, Entity *e, lbValue val) { if (e != nullptr) { - map_set(&m->values, hash_entity(e), val); + map_set(&m->values, e, val); } } void lb_add_member(lbModule *m, String const &name, lbValue val) { @@ -2054,7 +2048,7 @@ void lb_add_member(lbModule *m, StringHashKey const &key, lbValue val) { } void lb_add_procedure_value(lbModule *m, lbProcedure *p) { if (p->entity != nullptr) { - map_set(&m->procedure_values, hash_pointer(p->value), p->entity); + map_set(&m->procedure_values, p->value, p->entity); } string_map_set(&m->procedures, p->name, p); } @@ -2368,7 +2362,7 @@ lbValue lb_find_or_add_entity_string_byte_slice(lbModule *m, String const &str) lbValue lb_find_ident(lbProcedure *p, lbModule *m, Entity *e, Ast *expr) { - auto *found = map_get(&m->values, hash_entity(e)); + auto *found = map_get(&m->values, e); if (found) { auto v = *found; // NOTE(bill): This is because pointers are already pointers in LLVM @@ -2417,7 +2411,7 @@ lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) { e = strip_entity_wrapping(e); GB_ASSERT(e != nullptr); - auto *found = map_get(&m->values, hash_entity(e)); + auto *found = map_get(&m->values, e); if (found) { return *found; } @@ -2437,7 +2431,7 @@ lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e) { if (!ignore_body) { array_add(&m->missing_procedures_to_check, missing_proc); } - found = map_get(&m->values, hash_entity(e)); + found = map_get(&m->values, e); if (found) { return *found; } @@ -2501,7 +2495,7 @@ lbValue lb_find_value_from_entity(lbModule *m, Entity *e) { return lb_find_procedure_value_from_entity(m, e); } - auto *found = map_get(&m->values, hash_entity(e)); + auto *found = map_get(&m->values, e); if (found) { return *found; } diff --git a/src/llvm_backend_opt.cpp b/src/llvm_backend_opt.cpp index 2648863e2..13ce13aa5 100644 --- a/src/llvm_backend_opt.cpp +++ b/src/llvm_backend_opt.cpp @@ -387,7 +387,7 @@ void lb_run_remove_unused_function_pass(lbModule *m) { continue; } - Entity **found = map_get(&m->procedure_values, hash_pointer(curr_func)); + Entity **found = map_get(&m->procedure_values, curr_func); if (found && *found) { Entity *e = *found; bool is_required = (e->flags & EntityFlag_Require) == EntityFlag_Require; diff --git a/src/llvm_backend_proc.cpp b/src/llvm_backend_proc.cpp index ee5b94cec..c7b0374cd 100644 --- a/src/llvm_backend_proc.cpp +++ b/src/llvm_backend_proc.cpp @@ -948,7 +948,7 @@ lbValue lb_emit_call(lbProcedure *p, lbValue value, Array const &args, } - Entity **found = map_get(&p->module->procedure_values, hash_pointer(value.value)); + Entity **found = map_get(&p->module->procedure_values, value.value); if (found != nullptr) { Entity *e = *found; if (e != nullptr && entity_has_deferred_procedure(e)) { diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 82ad199bb..4f57dbfa6 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -670,7 +670,7 @@ void lb_build_range_stmt_struct_soa(lbProcedure *p, AstRangeStmt *rs, Scope *sco Entity *e = entity_of_node(rs->vals[0]); if (e != nullptr) { lbAddr soa_val = lb_addr_soa_variable(array.addr, lb_addr_load(p, index), nullptr); - map_set(&p->module->soa_values, hash_entity(e), soa_val); + map_set(&p->module->soa_values, e, soa_val); } } if (val_types[1]) { @@ -1525,7 +1525,7 @@ void lb_build_return_stmt(lbProcedure *p, Slice const &return_results) { } else if (return_count == 1) { Entity *e = tuple->variables[0]; if (res_count == 0) { - lbValue found = map_must_get(&p->module->values, hash_entity(e)); + lbValue found = map_must_get(&p->module->values, e); res = lb_emit_load(p, found); } else { res = lb_build_expr(p, return_results[0]); @@ -1534,7 +1534,7 @@ void lb_build_return_stmt(lbProcedure *p, Slice const &return_results) { if (p->type->Proc.has_named_results) { // NOTE(bill): store the named values before returning if (e->token.string != "") { - lbValue found = map_must_get(&p->module->values, hash_entity(e)); + lbValue found = map_must_get(&p->module->values, e); lb_emit_store(p, found, lb_emit_conv(p, res, e->type)); } } @@ -1558,7 +1558,7 @@ void lb_build_return_stmt(lbProcedure *p, Slice const &return_results) { } else { for (isize res_index = 0; res_index < return_count; res_index++) { Entity *e = tuple->variables[res_index]; - lbValue found = map_must_get(&p->module->values, hash_entity(e)); + lbValue found = map_must_get(&p->module->values, e); lbValue res = lb_emit_load(p, found); array_add(&results, res); } @@ -1580,7 +1580,7 @@ void lb_build_return_stmt(lbProcedure *p, Slice const &return_results) { if (e->token.string == "") { continue; } - named_results[i] = map_must_get(&p->module->values, hash_entity(e)); + named_results[i] = map_must_get(&p->module->values, e); values[i] = lb_emit_conv(p, results[i], e->type); } diff --git a/src/llvm_backend_utility.cpp b/src/llvm_backend_utility.cpp index ab50b8c1e..2ff54342a 100644 --- a/src/llvm_backend_utility.cpp +++ b/src/llvm_backend_utility.cpp @@ -401,7 +401,7 @@ lbValue lb_emit_or_return(lbProcedure *p, Ast *arg, TypeAndValue const &tv) { GB_ASSERT(end_entity->token.string.len != 0); // NOTE(bill): store the named values before returning - lbValue found = map_must_get(&p->module->values, hash_entity(end_entity)); + lbValue found = map_must_get(&p->module->values, end_entity); lb_emit_store(p, found, rhs); lb_build_return_stmt(p, {}); @@ -811,9 +811,9 @@ lbValue lb_address_from_load(lbProcedure *p, lbValue value) { lbStructFieldRemapping lb_get_struct_remapping(lbModule *m, Type *t) { t = base_type(t); LLVMTypeRef struct_type = lb_type(m, t); - auto *field_remapping = map_get(&m->struct_field_remapping, hash_pointer(struct_type)); + auto *field_remapping = map_get(&m->struct_field_remapping, cast(void *)struct_type); if (field_remapping == nullptr) { - field_remapping = map_get(&m->struct_field_remapping, hash_pointer(t)); + field_remapping = map_get(&m->struct_field_remapping, cast(void *)t); } GB_ASSERT(field_remapping != nullptr); return *field_remapping; From 924faa58b43b5e727436cd50bded45b9c43ac3a4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 16:45:27 +0000 Subject: [PATCH 18/29] Correct `map_remove(PtrMap)` --- src/checker.cpp | 18 +++++++++--------- src/checker.hpp | 2 +- src/ptr_map.cpp | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/checker.cpp b/src/checker.cpp index 643673afe..044342760 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -1086,7 +1086,7 @@ Scope *scope_of_node(Ast *node) { } ExprInfo *check_get_expr_info(CheckerContext *c, Ast *expr) { if (c->untyped != nullptr) { - ExprInfo **found = map_get(c->untyped, hash_pointer(expr)); + ExprInfo **found = map_get(c->untyped, expr); if (found) { return *found; } @@ -1094,7 +1094,7 @@ ExprInfo *check_get_expr_info(CheckerContext *c, Ast *expr) { } else { mutex_lock(&c->info->global_untyped_mutex); defer (mutex_unlock(&c->info->global_untyped_mutex)); - ExprInfo **found = map_get(&c->info->global_untyped, hash_pointer(expr)); + ExprInfo **found = map_get(&c->info->global_untyped, expr); if (found) { return *found; } @@ -1104,23 +1104,23 @@ ExprInfo *check_get_expr_info(CheckerContext *c, Ast *expr) { void check_set_expr_info(CheckerContext *c, Ast *expr, AddressingMode mode, Type *type, ExactValue value) { if (c->untyped != nullptr) { - map_set(c->untyped, hash_pointer(expr), make_expr_info(mode, type, value, false)); + map_set(c->untyped, expr, make_expr_info(mode, type, value, false)); } else { mutex_lock(&c->info->global_untyped_mutex); - map_set(&c->info->global_untyped, hash_pointer(expr), make_expr_info(mode, type, value, false)); + map_set(&c->info->global_untyped, expr, make_expr_info(mode, type, value, false)); mutex_unlock(&c->info->global_untyped_mutex); } } void check_remove_expr_info(CheckerContext *c, Ast *e) { if (c->untyped != nullptr) { - map_remove(c->untyped, hash_pointer(e)); - GB_ASSERT(map_get(c->untyped, hash_pointer(e)) == nullptr); + map_remove(c->untyped, e); + GB_ASSERT(map_get(c->untyped, e) == nullptr); } else { auto *untyped = &c->info->global_untyped; mutex_lock(&c->info->global_untyped_mutex); - map_remove(untyped, hash_pointer(e)); - GB_ASSERT(map_get(untyped, hash_pointer(e)) == nullptr); + map_remove(untyped, e); + GB_ASSERT(map_get(untyped, e) == nullptr); mutex_unlock(&c->info->global_untyped_mutex); } } @@ -4952,7 +4952,7 @@ void add_untyped_expressions(CheckerInfo *cinfo, UntypedExprInfoMap *untyped) { return; } for_array(i, untyped->entries) { - Ast *expr = cast(Ast *)cast(uintptr)untyped->entries[i].key.key; + Ast *expr = untyped->entries[i].key; ExprInfo *info = untyped->entries[i].value; if (expr != nullptr && info != nullptr) { mpmc_enqueue(&cinfo->checker->global_untyped_queue, UntypedExprInfo{expr, info}); diff --git a/src/checker.hpp b/src/checker.hpp index e7f152eb2..700cd7e54 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -264,7 +264,7 @@ struct UntypedExprInfo { ExprInfo *info; }; -typedef Map UntypedExprInfoMap; // Key: Ast * +typedef PtrMap UntypedExprInfoMap; typedef MPMCQueue ProcBodyQueue; // CheckerInfo stores all the symbol information for a type-checked program diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp index af3cf86f9..153b40b7e 100644 --- a/src/ptr_map.cpp +++ b/src/ptr_map.cpp @@ -219,7 +219,7 @@ void map__erase(PtrMap *h, MapFindResult const &fr) { } template -void map_remove(PtrMap *h, HashKey const &key) { +void map_remove(PtrMap *h, K key) { MapFindResult fr = map__find(h, key); if (fr.entry_index != MAP_SENTINEL) { map__erase(h, fr); From c38d6dc9592cff3bfd21c45076cd82df2d763eb2 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 16:46:09 +0000 Subject: [PATCH 19/29] Remove HashKey usage for `PtrMap` calls --- src/ptr_map.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp index 153b40b7e..4659fcf9b 100644 --- a/src/ptr_map.cpp +++ b/src/ptr_map.cpp @@ -237,7 +237,7 @@ gb_inline void map_clear(PtrMap *h) { #if PTR_MAP_ENABLE_MULTI_MAP template -PtrMapEntry *multi_map_find_first(PtrMap *h, HashKey const &key) { +PtrMapEntry *multi_map_find_first(PtrMap *h, K key) { isize i = map__find(h, key).entry_index; if (i == MAP_SENTINEL) { return nullptr; @@ -258,7 +258,7 @@ PtrMapEntry *multi_map_find_next(PtrMap *h, PtrMapEntry *e) { } template -isize multi_map_count(PtrMap *h, HashKey const &key) { +isize multi_map_count(PtrMap *h, K key) { isize count = 0; PtrMapEntry *e = multi_map_find_first(h, key); while (e != nullptr) { @@ -302,7 +302,7 @@ void multi_map_insert(PtrMap *h, K key, V const &value) { } template -void multi_map_remove(PtrMap *h, HashKey const &key, PtrMapEntry *e) { +void multi_map_remove(PtrMap *h, K key, PtrMapEntry *e) { MapFindResult fr = map__find_from_entry(h, e); if (fr.entry_index != MAP_SENTINEL) { map__erase(h, fr); @@ -310,7 +310,7 @@ void multi_map_remove(PtrMap *h, HashKey const &key, PtrMapEntry *e) } template -void multi_map_remove_all(PtrMap *h, HashKey const &key) { +void multi_map_remove_all(PtrMap *h, K key) { while (map_get(h, key) != nullptr) { map_remove(h, key); } From 6646348e1a0086d9a2341d0866f787ffc2608c8f Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 17:03:02 +0000 Subject: [PATCH 20/29] Increase usage of `PtrMap` --- src/build_settings.cpp | 2 +- src/check_expr.cpp | 4 ++-- src/check_type.cpp | 6 +++--- src/checker.cpp | 40 ++++++++++++++++------------------- src/checker.hpp | 4 ++-- src/docs_writer.cpp | 44 +++++++++++++++------------------------ src/llvm_backend_stmt.cpp | 2 +- src/main.cpp | 2 +- src/ptr_map.cpp | 8 +++++-- 9 files changed, 51 insertions(+), 61 deletions(-) diff --git a/src/build_settings.cpp b/src/build_settings.cpp index fa8922f61..182975d7b 100644 --- a/src/build_settings.cpp +++ b/src/build_settings.cpp @@ -244,7 +244,7 @@ struct BuildContext { gbAffinity affinity; isize thread_count; - Map defined_values; // Key: + PtrMap defined_values; }; diff --git a/src/check_expr.cpp b/src/check_expr.cpp index 2ad3cc4a6..7a0273805 100644 --- a/src/check_expr.cpp +++ b/src/check_expr.cpp @@ -314,7 +314,7 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, Entity *base_ return false; } - auto *found_gen_procs = map_get(&info->gen_procs, hash_pointer(base_entity->identifier)); + auto *found_gen_procs = map_get(&info->gen_procs, base_entity->identifier.load()); if (found_gen_procs) { auto procs = *found_gen_procs; for_array(i, procs) { @@ -423,7 +423,7 @@ bool find_or_generate_polymorphic_procedure(CheckerContext *old_c, Entity *base_ } else { auto array = array_make(heap_allocator()); array_add(&array, entity); - map_set(&info->gen_procs, hash_pointer(base_entity->identifier), array); + map_set(&info->gen_procs, base_entity->identifier.load(), array); } if (poly_proc_data) { diff --git a/src/check_type.cpp b/src/check_type.cpp index 05d5c674a..398967af8 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -228,7 +228,7 @@ Entity *find_polymorphic_record_entity(CheckerContext *ctx, Type *original_type, mutex_lock(&ctx->info->gen_types_mutex); defer (mutex_unlock(&ctx->info->gen_types_mutex)); - auto *found_gen_types = map_get(&ctx->info->gen_types, hash_pointer(original_type)); + auto *found_gen_types = map_get(&ctx->info->gen_types, original_type); if (found_gen_types != nullptr) { // GB_ASSERT_MSG(ordered_operands.count >= param_count, "%td >= %td", ordered_operands.count, param_count); @@ -311,13 +311,13 @@ void add_polymorphic_record_entity(CheckerContext *ctx, Ast *node, Type *named_t named_type->Named.type_name = e; mutex_lock(&ctx->info->gen_types_mutex); - auto *found_gen_types = map_get(&ctx->info->gen_types, hash_pointer(original_type)); + auto *found_gen_types = map_get(&ctx->info->gen_types, original_type); if (found_gen_types) { array_add(found_gen_types, e); } else { auto array = array_make(heap_allocator()); array_add(&array, e); - map_set(&ctx->info->gen_types, hash_pointer(original_type), array); + map_set(&ctx->info->gen_types, original_type, array); } mutex_unlock(&ctx->info->gen_types_mutex); } diff --git a/src/checker.cpp b/src/checker.cpp index 044342760..16e699ee3 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -810,7 +810,7 @@ void init_universal(void) { bool defined_values_double_declaration = false; for_array(i, bc->defined_values.entries) { - char const *name = cast(char const *)cast(uintptr)bc->defined_values.entries[i].key.key; + char const *name = bc->defined_values.entries[i].key; ExactValue value = bc->defined_values.entries[i].value; GB_ASSERT(value.kind != ExactValue_Invalid); @@ -2199,7 +2199,7 @@ void add_entity_dependency_from_procedure_parameters(Map *M, } Array generate_entity_dependency_graph(CheckerInfo *info, gbAllocator allocator) { - Map M = {}; // Key: Entity * + PtrMap M = {}; map_init(&M, allocator, info->entities.count); defer (map_destroy(&M)); for_array(i, info->entities) { @@ -2207,7 +2207,7 @@ Array generate_entity_dependency_graph(CheckerInfo *info, gbA if (is_entity_a_dependency(e)) { EntityGraphNode *n = gb_alloc_item(allocator, EntityGraphNode); n->entity = e; - map_set(&M, hash_pointer(e), n); + map_set(&M, e, n); } } @@ -2227,9 +2227,7 @@ Array generate_entity_dependency_graph(CheckerInfo *info, gbA } GB_ASSERT(dep != nullptr); if (is_entity_a_dependency(dep)) { - EntityGraphNode **m_ = map_get(&M, hash_pointer(dep)); - GB_ASSERT(m_ != nullptr); - EntityGraphNode *m = *m_; + EntityGraphNode *m = map_must_get(&M, dep); entity_graph_node_set_add(&n->succ, m); entity_graph_node_set_add(&m->pred, n); } @@ -2244,7 +2242,7 @@ Array generate_entity_dependency_graph(CheckerInfo *info, gbA for_array(i, M.entries) { auto *entry = &M.entries[i]; - auto *e = cast(Entity *)cast(uintptr)entry->key.key; + auto *e = entry->key; EntityGraphNode *n = entry->value; if (e->kind == Entity_Procedure) { @@ -3728,7 +3726,7 @@ String path_to_entity_name(String name, String fullpath, bool strip_extension=tr #if 1 -void add_import_dependency_node(Checker *c, Ast *decl, Map *M) { +void add_import_dependency_node(Checker *c, Ast *decl, PtrMap *M) { AstPackage *parent_pkg = decl->file->pkg; switch (decl->kind) { @@ -3752,11 +3750,11 @@ void add_import_dependency_node(Checker *c, Ast *decl, Map *M ImportGraphNode *m = nullptr; ImportGraphNode *n = nullptr; - found_node = map_get(M, hash_pointer(pkg)); + found_node = map_get(M, pkg); GB_ASSERT(found_node != nullptr); m = *found_node; - found_node = map_get(M, hash_pointer(parent_pkg)); + found_node = map_get(M, parent_pkg); GB_ASSERT(found_node != nullptr); n = *found_node; @@ -3794,14 +3792,14 @@ void add_import_dependency_node(Checker *c, Ast *decl, Map *M } Array generate_import_dependency_graph(Checker *c) { - Map M = {}; // Key: AstPackage * + PtrMap M = {}; map_init(&M, heap_allocator(), 2*c->parser->packages.count); defer (map_destroy(&M)); for_array(i, c->parser->packages) { AstPackage *pkg = c->parser->packages[i]; ImportGraphNode *n = import_graph_node_create(heap_allocator(), pkg); - map_set(&M, hash_pointer(pkg), n); + map_set(&M, pkg, n); } // Calculate edges for graph M @@ -4507,9 +4505,9 @@ void check_import_entities(Checker *c) { } -Array find_entity_path(Entity *start, Entity *end, Map *visited = nullptr); +Array find_entity_path(Entity *start, Entity *end, PtrSet *visited = nullptr); -bool find_entity_path_tuple(Type *tuple, Entity *end, Map *visited, Array *path_) { +bool find_entity_path_tuple(Type *tuple, Entity *end, PtrSet *visited, Array *path_) { GB_ASSERT(path_ != nullptr); if (tuple == nullptr) { return false; @@ -4541,26 +4539,24 @@ bool find_entity_path_tuple(Type *tuple, Entity *end, Map *visited, Ar return false; } -Array find_entity_path(Entity *start, Entity *end, Map *visited) { - Map visited_ = {}; +Array find_entity_path(Entity *start, Entity *end, PtrSet *visited) { + PtrSet visited_ = {}; bool made_visited = false; if (visited == nullptr) { made_visited = true; - map_init(&visited_, heap_allocator()); + ptr_set_init(&visited_, heap_allocator()); visited = &visited_; } defer (if (made_visited) { - map_destroy(&visited_); + ptr_set_destroy(&visited_); }); Array empty_path = {}; - HashKey key = hash_pointer(start); - - if (map_get(visited, key) != nullptr) { + if (ptr_set_exists(visited, start)) { return empty_path; } - map_set(visited, key, start); + ptr_set_add(visited, start); DeclInfo *decl = start->decl_info; if (decl) { diff --git a/src/checker.hpp b/src/checker.hpp index 700cd7e54..ab8fce3d8 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -316,8 +316,8 @@ struct CheckerInfo { RecursiveMutex gen_procs_mutex; RecursiveMutex gen_types_mutex; - Map > gen_procs; // Key: Ast * | Identifier -> Entity - Map > gen_types; // Key: Type * + PtrMap > gen_procs; // Key: Ast * | Identifier -> Entity + PtrMap > gen_types; BlockingMutex type_info_mutex; // NOT recursive Array type_info_types; diff --git a/src/docs_writer.cpp b/src/docs_writer.cpp index 1603ca22c..e7254e16b 100644 --- a/src/docs_writer.cpp +++ b/src/docs_writer.cpp @@ -26,12 +26,10 @@ struct OdinDocWriter { StringMap string_cache; - Map file_cache; // Key: AstFile * - Map pkg_cache; // Key: AstPackage * - Map entity_cache; // Key: Entity * - Map entity_id_cache; // Key: OdinDocEntityIndex - Map type_cache; // Key: Type * - Map type_id_cache; // Key: OdinDocTypeIndex + PtrMap file_cache; + PtrMap pkg_cache; + PtrMap entity_cache; + PtrMap type_cache; OdinDocWriterItemTracker files; OdinDocWriterItemTracker pkgs; @@ -61,9 +59,7 @@ void odin_doc_writer_prepare(OdinDocWriter *w) { map_init(&w->file_cache, a); map_init(&w->pkg_cache, a); map_init(&w->entity_cache, a); - map_init(&w->entity_id_cache, a); map_init(&w->type_cache, a); - map_init(&w->type_id_cache, a); odin_doc_writer_item_tracker_init(&w->files, 1); odin_doc_writer_item_tracker_init(&w->pkgs, 1); @@ -81,9 +77,7 @@ void odin_doc_writer_destroy(OdinDocWriter *w) { map_destroy(&w->file_cache); map_destroy(&w->pkg_cache); map_destroy(&w->entity_cache); - map_destroy(&w->entity_id_cache); map_destroy(&w->type_cache); - map_destroy(&w->type_id_cache); } @@ -115,9 +109,7 @@ void odin_doc_writer_start_writing(OdinDocWriter *w) { map_clear(&w->file_cache); map_clear(&w->pkg_cache); map_clear(&w->entity_cache); - map_clear(&w->entity_id_cache); map_clear(&w->type_cache); - map_clear(&w->type_id_cache); isize total_size = odin_doc_writer_calc_total_size(w); total_size = align_formula_isize(total_size, 8); @@ -267,7 +259,7 @@ OdinDocPosition odin_doc_token_pos_cast(OdinDocWriter *w, TokenPos const &pos) { if (pos.file_id != 0) { AstFile *file = get_ast_file_from_id(pos.file_id); if (file != nullptr) { - OdinDocFileIndex *file_index_found = map_get(&w->file_cache, hash_pointer(file)); + OdinDocFileIndex *file_index_found = map_get(&w->file_cache, file); GB_ASSERT(file_index_found != nullptr); file_index = *file_index_found; } @@ -483,16 +475,16 @@ OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) { if (type == nullptr) { return 0; } - OdinDocTypeIndex *found = map_get(&w->type_cache, hash_pointer(type)); + OdinDocTypeIndex *found = map_get(&w->type_cache, type); if (found) { return *found; } for_array(i, w->type_cache.entries) { // NOTE(bill): THIS IS SLOW - Type *other = cast(Type *)cast(uintptr)w->type_cache.entries[i].key.key; + Type *other = w->type_cache.entries[i].key; if (are_types_identical(type, other)) { OdinDocTypeIndex index = w->type_cache.entries[i].value; - map_set(&w->type_cache, hash_pointer(type), index); + map_set(&w->type_cache, type, index); return index; } } @@ -502,8 +494,7 @@ OdinDocTypeIndex odin_doc_type(OdinDocWriter *w, Type *type) { OdinDocType doc_type = {}; OdinDocTypeIndex type_index = 0; type_index = odin_doc_write_item(w, &w->types, &doc_type, &dst); - map_set(&w->type_cache, hash_pointer(type), type_index); - map_set(&w->type_id_cache, hash_integer(type_index), type); + map_set(&w->type_cache, type, type_index); switch (type->kind) { case Type_Basic: @@ -776,12 +767,12 @@ OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e) { return 0; } - OdinDocEntityIndex *prev_index = map_get(&w->entity_cache, hash_pointer(e)); + OdinDocEntityIndex *prev_index = map_get(&w->entity_cache, e); if (prev_index) { return *prev_index; } - if (e->pkg != nullptr && map_get(&w->pkg_cache, hash_pointer(e->pkg)) == nullptr) { + if (e->pkg != nullptr && map_get(&w->pkg_cache, e->pkg) == nullptr) { return 0; } @@ -789,8 +780,7 @@ OdinDocEntityIndex odin_doc_add_entity(OdinDocWriter *w, Entity *e) { OdinDocEntity* dst = nullptr; OdinDocEntityIndex doc_entity_index = odin_doc_write_item(w, &w->entities, &doc_entity, &dst); - map_set(&w->entity_cache, hash_pointer(e), doc_entity_index); - map_set(&w->entity_id_cache, hash_integer(doc_entity_index), e); + map_set(&w->entity_cache, e, doc_entity_index); Ast *type_expr = nullptr; @@ -901,7 +891,7 @@ void odin_doc_update_entities(OdinDocWriter *w) { defer (array_free(&entities)); for_array(i, w->entity_cache.entries) { - Entity *e = cast(Entity *)cast(uintptr)w->entity_cache.entries[i].key.key; + Entity *e = w->entity_cache.entries[i].key; entities[i] = e; } for_array(i, entities) { @@ -912,7 +902,7 @@ void odin_doc_update_entities(OdinDocWriter *w) { } for_array(i, w->entity_cache.entries) { - Entity *e = cast(Entity *)cast(uintptr)w->entity_cache.entries[i].key.key; + Entity *e = w->entity_cache.entries[i].key; OdinDocEntityIndex entity_index = w->entity_cache.entries[i].value; OdinDocTypeIndex type_index = odin_doc_type(w, e->type); @@ -955,7 +945,7 @@ OdinDocArray odin_doc_add_pkg_entities(OdinDocWriter *w, Ast if (pkg->scope == nullptr) { return {}; } - if (map_get(&w->pkg_cache, hash_pointer(pkg)) == nullptr) { + if (map_get(&w->pkg_cache, pkg) == nullptr) { return {}; } @@ -1056,7 +1046,7 @@ void odin_doc_write_docs(OdinDocWriter *w) { OdinDocPkg *dst = nullptr; OdinDocPkgIndex pkg_index = odin_doc_write_item(w, &w->pkgs, &doc_pkg, &dst); - map_set(&w->pkg_cache, hash_pointer(pkg), pkg_index); + map_set(&w->pkg_cache, pkg, pkg_index); auto file_indices = array_make(heap_allocator(), 0, pkg->files.count); defer (array_free(&file_indices)); @@ -1067,7 +1057,7 @@ void odin_doc_write_docs(OdinDocWriter *w) { doc_file.pkg = pkg_index; doc_file.name = odin_doc_write_string(w, file->fullpath); OdinDocFileIndex file_index = odin_doc_write_item(w, &w->files, &doc_file); - map_set(&w->file_cache, hash_pointer(file), file_index); + map_set(&w->file_cache, file, file_index); array_add(&file_indices, file_index); } diff --git a/src/llvm_backend_stmt.cpp b/src/llvm_backend_stmt.cpp index 4f57dbfa6..9d3d2c949 100644 --- a/src/llvm_backend_stmt.cpp +++ b/src/llvm_backend_stmt.cpp @@ -83,7 +83,7 @@ void lb_build_constant_value_decl(lbProcedure *p, AstValueDecl *vd) { DeclInfo *decl = decl_info_of_entity(e); ast_node(pl, ProcLit, decl->proc_lit); if (pl->body != nullptr) { - auto *found = map_get(&info->gen_procs, hash_pointer(ident)); + auto *found = map_get(&info->gen_procs, ident); if (found) { auto procs = *found; for_array(i, procs) { diff --git a/src/main.cpp b/src/main.cpp index e79e7203d..3fed50c80 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1109,7 +1109,7 @@ bool parse_build_flags(Array args) { break; } - HashKey key = hash_pointer(string_intern(name)); + char const *key = string_intern(name); if (map_get(&build_context.defined_values, key) != nullptr) { gb_printf_err("Defined constant '%.*s' already exists\n", LIT(name)); diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp index 4659fcf9b..2387a2a20 100644 --- a/src/ptr_map.cpp +++ b/src/ptr_map.cpp @@ -18,8 +18,12 @@ struct PtrMap { }; -template -u32 ptr_map_hash_key(K key) { +u32 ptr_map_hash_key(void const *key) { + // TODO(bill): Improve ptr_map_hash_key + return gb_fnv32a(&key, gb_size_of(key)); +} +u32 ptr_map_hash_key(uintptr key) { + // TODO(bill): Improve ptr_map_hash_key return gb_fnv32a(&key, gb_size_of(key)); } From 541beb615b745b45f2cc82813014a3e04f1a3231 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 17:13:07 +0000 Subject: [PATCH 21/29] Move more things to `PtrMap` --- src/check_stmt.cpp | 9 ++++----- src/common.cpp | 8 ++++---- src/exact_value.cpp | 33 ++++++++++++++------------------- src/ptr_map.cpp | 2 +- 4 files changed, 23 insertions(+), 29 deletions(-) diff --git a/src/check_stmt.cpp b/src/check_stmt.cpp index 103ffa071..24ad0eec1 100644 --- a/src/check_stmt.cpp +++ b/src/check_stmt.cpp @@ -699,7 +699,7 @@ struct TypeAndToken { }; -void add_constant_switch_case(CheckerContext *ctx, Map *seen, Operand operand, bool use_expr = true) { +void add_constant_switch_case(CheckerContext *ctx, PtrMap *seen, Operand operand, bool use_expr = true) { if (operand.mode != Addressing_Constant) { return; } @@ -707,7 +707,7 @@ void add_constant_switch_case(CheckerContext *ctx, Map *seen, Oper return; } - HashKey key = hash_exact_value(operand.value); + uintptr key = hash_exact_value(operand.value); TypeAndToken *found = map_get(seen, key); if (found != nullptr) { isize count = multi_map_count(seen, key); @@ -964,7 +964,7 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { } } - Map seen = {}; // NOTE(bill): Multimap, Key: ExactValue + PtrMap seen = {}; // NOTE(bill): Multimap, Key: ExactValue map_init(&seen, heap_allocator()); defer (map_destroy(&seen)); @@ -1133,8 +1133,7 @@ void check_switch_stmt(CheckerContext *ctx, Ast *node, u32 mod_flags) { continue; } ExactValue v = f->Constant.value; - HashKey key = hash_exact_value(v); - auto found = map_get(&seen, key); + auto found = map_get(&seen, hash_exact_value(v)); if (!found) { array_add(&unhandled, f); } diff --git a/src/common.cpp b/src/common.cpp index 5d7c87b6d..f7a0653ac 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -290,13 +290,13 @@ struct StringIntern { char str[1]; }; -Map string_intern_map = {}; // Key: u64 +PtrMap string_intern_map = {}; // Key: u64 gb_global Arena string_intern_arena = {}; char const *string_intern(char const *text, isize len) { u64 hash = gb_fnv64a(text, len); - u64 key = hash ? hash : 1; - StringIntern **found = map_get(&string_intern_map, hash_integer(key)); + uintptr key = cast(uintptr)(hash ? hash : 1); + StringIntern **found = map_get(&string_intern_map, key); if (found) { for (StringIntern *it = *found; it != nullptr; it = it->next) { if (it->len == len && gb_strncmp(it->str, (char *)text, len) == 0) { @@ -310,7 +310,7 @@ char const *string_intern(char const *text, isize len) { new_intern->next = found ? *found : nullptr; gb_memmove(new_intern->str, text, len); new_intern->str[len] = 0; - map_set(&string_intern_map, hash_integer(key), new_intern); + map_set(&string_intern_map, key, new_intern); return new_intern->str; } diff --git a/src/exact_value.cpp b/src/exact_value.cpp index 363c6d863..fd90278e5 100644 --- a/src/exact_value.cpp +++ b/src/exact_value.cpp @@ -63,44 +63,39 @@ struct ExactValue { gb_global ExactValue const empty_exact_value = {}; -HashKey hash_exact_value(ExactValue v) { +uintptr hash_exact_value(ExactValue v) { mutex_lock(&hash_exact_value_mutex); defer (mutex_unlock(&hash_exact_value_mutex)); - HashKey empty = {}; switch (v.kind) { case ExactValue_Invalid: - return empty; + return 0; case ExactValue_Bool: - return hash_integer(u64(v.value_bool)); + return gb_fnv32a(&v.value_bool, gb_size_of(v.value_bool)); case ExactValue_String: - { - char const *str = string_intern(v.value_string); - return hash_pointer(str); - } + return ptr_map_hash_key(string_intern(v.value_string)); case ExactValue_Integer: { - HashKey key = hashing_proc(v.value_integer.dp, gb_size_of(*v.value_integer.dp) * v.value_integer.used); + u32 key = gb_fnv32a(v.value_integer.dp, gb_size_of(*v.value_integer.dp) * v.value_integer.used); u8 last = (u8)v.value_integer.sign; - key.key = (key.key ^ last) * 0x100000001b3ll; - return key; + return (key ^ last) * 0x01000193; } case ExactValue_Float: - return hash_f64(v.value_float); + return gb_fnv32a(&v.value_float, gb_size_of(v.value_float)); case ExactValue_Pointer: - return hash_integer(v.value_pointer); + return ptr_map_hash_key(v.value_pointer); case ExactValue_Complex: - return hashing_proc(v.value_complex, gb_size_of(Complex128)); + return gb_fnv32a(v.value_complex, gb_size_of(Complex128)); case ExactValue_Quaternion: - return hashing_proc(v.value_quaternion, gb_size_of(Quaternion256)); + return gb_fnv32a(v.value_quaternion, gb_size_of(Quaternion256)); case ExactValue_Compound: - return hash_pointer(v.value_compound); + return ptr_map_hash_key(v.value_compound); case ExactValue_Procedure: - return hash_pointer(v.value_procedure); + return ptr_map_hash_key(v.value_procedure); case ExactValue_Typeid: - return hash_pointer(v.value_typeid); + return ptr_map_hash_key(v.value_typeid); } - return hashing_proc(&v, gb_size_of(ExactValue)); + return gb_fnv32a(&v, gb_size_of(ExactValue)); } diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp index 2387a2a20..0a61d300f 100644 --- a/src/ptr_map.cpp +++ b/src/ptr_map.cpp @@ -253,7 +253,7 @@ template PtrMapEntry *multi_map_find_next(PtrMap *h, PtrMapEntry *e) { isize i = e->next; while (i != MAP_SENTINEL) { - if (hash_key_equal(h->entries.data[i].key, e->key)) { + if (h->entries.data[i].key == e->key) { return &h->entries.data[i]; } i = h->entries.data[i].next; From 86e26c9a4401469ea3f3d05aa2371551ad43e3a4 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 17:13:26 +0000 Subject: [PATCH 22/29] Remove dead code --- src/checker.cpp | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/checker.cpp b/src/checker.cpp index 16e699ee3..5d8d6dcdc 100644 --- a/src/checker.cpp +++ b/src/checker.cpp @@ -2179,25 +2179,6 @@ bool is_entity_a_dependency(Entity *e) { return false; } -void add_entity_dependency_from_procedure_parameters(Map *M, EntityGraphNode *n, Type *tuple) { - if (tuple == nullptr) { - return; - } - GB_ASSERT(tuple->kind == Type_Tuple); - TypeTuple *t = &tuple->Tuple; - for_array(i, t->variables) { - Entity *v = t->variables[i]; - EntityGraphNode **found = map_get(M, hash_pointer(v)); - if (found == nullptr) { - continue; - } - EntityGraphNode *m = *found; - entity_graph_node_set_add(&n->succ, m); - entity_graph_node_set_add(&m->pred, n); - } - -} - Array generate_entity_dependency_graph(CheckerInfo *info, gbAllocator allocator) { PtrMap M = {}; map_init(&M, allocator, info->entities.count); From 0af69f8cda4e4bed8cfc732fd53bd93be55916f3 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 17:16:37 +0000 Subject: [PATCH 23/29] Remove `map.cpp` code --- src/checker.hpp | 7 - src/map.cpp | 363 ------------------------------------------------ src/ptr_map.cpp | 9 ++ 3 files changed, 9 insertions(+), 370 deletions(-) delete mode 100644 src/map.cpp diff --git a/src/checker.hpp b/src/checker.hpp index ab8fce3d8..6511dad32 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -406,13 +406,6 @@ gb_global AstPackage *intrinsics_pkg = nullptr; gb_global AstPackage *config_pkg = nullptr; -HashKey hash_node (Ast *node) { return hash_pointer(node); } -HashKey hash_ast_file (AstFile *file) { return hash_pointer(file); } -HashKey hash_entity (Entity *e) { return hash_pointer(e); } -HashKey hash_type (Type *t) { return hash_pointer(t); } -HashKey hash_decl_info(DeclInfo *decl) { return hash_pointer(decl); } - - // CheckerInfo API TypeAndValue type_and_value_of_expr (Ast *expr); Type * type_of_expr (Ast *expr); diff --git a/src/map.cpp b/src/map.cpp deleted file mode 100644 index cc91e51d4..000000000 --- a/src/map.cpp +++ /dev/null @@ -1,363 +0,0 @@ -// A `Map` is an unordered hash table which can allow for a key to point to multiple values -// with the use of the `multi_*` procedures. -// TODO(bill): I should probably allow the `multi_map_*` stuff to be #ifdefed out - -#define MAP_ENABLE_MULTI_MAP 1 - -#ifndef MAP_UTIL_STUFF -#define MAP_UTIL_STUFF -// NOTE(bill): This util stuff is the same for every `Map` - -typedef u32 MapIndex; - -struct MapFindResult { - MapIndex hash_index; - MapIndex entry_prev; - MapIndex entry_index; -}; - -enum : MapIndex { MAP_SENTINEL = ~(MapIndex)0 }; - - -struct HashKey { - u64 key; -}; -GB_STATIC_ASSERT(gb_size_of(u64) >= gb_size_of(void *)); - -gb_inline HashKey hashing_proc(void const *data, isize len) { - HashKey h = {}; - h.key = fnv64a(data, len); - return h; -} - -gb_inline HashKey hash_pointer(void const *ptr) { - HashKey h = {}; - h.key = cast(u64)cast(uintptr)ptr; - return h; -} - -gb_inline HashKey hash_integer(u64 u) { - HashKey h = {}; - h.key = u; - return h; -} -gb_inline HashKey hash_f64(f64 f) { - HashKey h = {}; - h.key = bit_cast(f); - return h; -} - -gb_inline bool hash_key_equal(HashKey a, HashKey b) { - return a.key == b.key; -} -gb_inline bool operator==(HashKey a, HashKey b) { return hash_key_equal(a, b); } -gb_inline bool operator!=(HashKey a, HashKey b) { return !hash_key_equal(a, b); } - -#endif - -template -struct MapEntry { - HashKey key; - MapIndex next; - T value; -}; - -template -struct Map { - Slice hashes; - Array > entries; -}; - - -template void map_init (Map *h, gbAllocator a, isize capacity = 16); -template void map_destroy (Map *h); -template T * map_get (Map *h, HashKey const &key); -template T & map_must_get (Map *h, HashKey const &key); -template void map_set (Map *h, HashKey const &key, T const &value); -template void map_remove (Map *h, HashKey const &key); -template void map_clear (Map *h); -template void map_grow (Map *h); -template void map_rehash (Map *h, isize new_count); -template void map_reserve (Map *h, isize cap); - -#if MAP_ENABLE_MULTI_MAP -// Mutlivalued map procedure -template MapEntry * multi_map_find_first(Map *h, HashKey const &key); -template MapEntry * multi_map_find_next (Map *h, MapEntry *e); - -template isize multi_map_count (Map *h, HashKey const &key); -template void multi_map_get_all (Map *h, HashKey const &key, T *items); -template void multi_map_insert (Map *h, HashKey const &key, T const &value); -template void multi_map_remove (Map *h, HashKey const &key, MapEntry *e); -template void multi_map_remove_all(Map *h, HashKey const &key); -#endif - -template -gb_inline void map_init(Map *h, gbAllocator a, isize capacity) { - capacity = next_pow2_isize(capacity); - slice_init(&h->hashes, a, capacity); - array_init(&h->entries, a, 0, capacity); - for (isize i = 0; i < capacity; i++) { - h->hashes.data[i] = MAP_SENTINEL; - } -} - -template -gb_inline void map_destroy(Map *h) { - slice_free(&h->hashes, h->entries.allocator); - array_free(&h->entries); -} - -template -gb_internal MapIndex map__add_entry(Map *h, HashKey const &key) { - MapEntry e = {}; - e.key = key; - e.next = MAP_SENTINEL; - array_add(&h->entries, e); - return cast(MapIndex)(h->entries.count-1); -} - -template -gb_internal MapFindResult map__find(Map *h, HashKey const &key) { - MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; - if (h->hashes.count == 0) { - return fr; - } - fr.hash_index = cast(MapIndex)(key.key & (h->hashes.count-1)); - fr.entry_index = h->hashes.data[fr.hash_index]; - while (fr.entry_index != MAP_SENTINEL) { - if (hash_key_equal(h->entries.data[fr.entry_index].key, key)) { - return fr; - } - fr.entry_prev = fr.entry_index; - fr.entry_index = h->entries.data[fr.entry_index].next; - } - return fr; -} - -template -gb_internal MapFindResult map__find_from_entry(Map *h, MapEntry *e) { - MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; - if (h->hashes.count == 0) { - return fr; - } - fr.hash_index = cast(MapIndex)(e->key.key & (h->hashes.count-1)); - fr.entry_index = h->hashes.data[fr.hash_index]; - while (fr.entry_index != MAP_SENTINEL) { - if (&h->entries.data[fr.entry_index] == e) { - return fr; - } - fr.entry_prev = fr.entry_index; - fr.entry_index = h->entries.data[fr.entry_index].next; - } - return fr; -} - -template -gb_internal b32 map__full(Map *h) { - return 0.75f * h->hashes.count <= h->entries.count; -} - -template -gb_inline void map_grow(Map *h) { - isize new_count = gb_max(h->hashes.count<<1, 16); - map_rehash(h, new_count); -} - -template -void map_reset_entries(Map *h) { - for (isize i = 0; i < h->hashes.count; i++) { - h->hashes.data[i] = MAP_SENTINEL; - } - for (isize i = 0; i < h->entries.count; i++) { - MapFindResult fr; - MapEntry *e = &h->entries.data[i]; - e->next = MAP_SENTINEL; - fr = map__find_from_entry(h, e); - if (fr.entry_prev == MAP_SENTINEL) { - h->hashes[fr.hash_index] = cast(MapIndex)i; - } else { - h->entries[fr.entry_prev].next = cast(MapIndex)i; - } - } -} - -template -void map_reserve(Map *h, isize cap) { - array_reserve(&h->entries, cap); - if (h->entries.count*2 < h->hashes.count) { - return; - } - slice_resize(&h->hashes, h->entries.allocator, cap*2); - map_reset_entries(h); -} - - -template -void map_rehash(Map *h, isize new_count) { - map_reserve(h, new_count); -} - -template -T *map_get(Map *h, HashKey const &key) { - isize index = map__find(h, key).entry_index; - if (index != MAP_SENTINEL) { - return &h->entries.data[index].value; - } - return nullptr; -} - -template -T &map_must_get(Map *h, HashKey const &key) { - isize index = map__find(h, key).entry_index; - GB_ASSERT(index != MAP_SENTINEL); - return h->entries.data[index].value; -} - -template -void map_set(Map *h, HashKey const &key, T const &value) { - MapIndex index; - MapFindResult fr; - if (h->hashes.count == 0) { - map_grow(h); - } - fr = map__find(h, key); - if (fr.entry_index != MAP_SENTINEL) { - index = fr.entry_index; - } else { - index = map__add_entry(h, key); - if (fr.entry_prev != MAP_SENTINEL) { - h->entries.data[fr.entry_prev].next = index; - } else { - h->hashes.data[fr.hash_index] = index; - } - } - h->entries.data[index].value = value; - - if (map__full(h)) { - map_grow(h); - } -} - - -template -void map__erase(Map *h, MapFindResult const &fr) { - MapFindResult last; - if (fr.entry_prev == MAP_SENTINEL) { - h->hashes.data[fr.hash_index] = h->entries.data[fr.entry_index].next; - } else { - h->entries.data[fr.entry_prev].next = h->entries.data[fr.entry_index].next; - } - if (fr.entry_index == h->entries.count-1) { - array_pop(&h->entries); - return; - } - h->entries.data[fr.entry_index] = h->entries.data[h->entries.count-1]; - array_pop(&h->entries); - - last = map__find(h, h->entries.data[fr.entry_index].key); - if (last.entry_prev != MAP_SENTINEL) { - h->entries.data[last.entry_prev].next = fr.entry_index; - } else { - h->hashes.data[last.hash_index] = fr.entry_index; - } -} - -template -void map_remove(Map *h, HashKey const &key) { - MapFindResult fr = map__find(h, key); - if (fr.entry_index != MAP_SENTINEL) { - map__erase(h, fr); - } -} - -template -gb_inline void map_clear(Map *h) { - array_clear(&h->entries); - for (isize i = 0; i < h->hashes.count; i++) { - h->hashes.data[i] = MAP_SENTINEL; - } -} - - -#if MAP_ENABLE_MULTI_MAP -template -MapEntry *multi_map_find_first(Map *h, HashKey const &key) { - isize i = map__find(h, key).entry_index; - if (i == MAP_SENTINEL) { - return nullptr; - } - return &h->entries.data[i]; -} - -template -MapEntry *multi_map_find_next(Map *h, MapEntry *e) { - isize i = e->next; - while (i != MAP_SENTINEL) { - if (hash_key_equal(h->entries.data[i].key, e->key)) { - return &h->entries.data[i]; - } - i = h->entries.data[i].next; - } - return nullptr; -} - -template -isize multi_map_count(Map *h, HashKey const &key) { - isize count = 0; - MapEntry *e = multi_map_find_first(h, key); - while (e != nullptr) { - count++; - e = multi_map_find_next(h, e); - } - return count; -} - -template -void multi_map_get_all(Map *h, HashKey const &key, T *items) { - isize i = 0; - MapEntry *e = multi_map_find_first(h, key); - while (e != nullptr) { - items[i++] = e->value; - e = multi_map_find_next(h, e); - } -} - -template -void multi_map_insert(Map *h, HashKey const &key, T const &value) { - MapFindResult fr; - MapIndex i; - if (h->hashes.count == 0) { - map_grow(h); - } - // Make - fr = map__find(h, key); - i = map__add_entry(h, key); - if (fr.entry_prev == MAP_SENTINEL) { - h->hashes.data[fr.hash_index] = i; - } else { - h->entries.data[fr.entry_prev].next = i; - } - h->entries.data[i].next = fr.entry_index; - h->entries.data[i].value = value; - // Grow if needed - if (map__full(h)) { - map_grow(h); - } -} - -template -void multi_map_remove(Map *h, HashKey const &key, MapEntry *e) { - MapFindResult fr = map__find_from_entry(h, e); - if (fr.entry_index != MAP_SENTINEL) { - map__erase(h, fr); - } -} - -template -void multi_map_remove_all(Map *h, HashKey const &key) { - while (map_get(h, key) != nullptr) { - map_remove(h, key); - } -} -#endif diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp index 0a61d300f..19443d8a1 100644 --- a/src/ptr_map.cpp +++ b/src/ptr_map.cpp @@ -1,5 +1,14 @@ #define PTR_MAP_ENABLE_MULTI_MAP 1 +typedef u32 MapIndex; + +struct MapFindResult { + MapIndex hash_index; + MapIndex entry_prev; + MapIndex entry_index; +}; + +enum : MapIndex { MAP_SENTINEL = ~(MapIndex)0 }; template struct PtrMapEntry { From 26e3daf5adc6c59f7bf7c621abc4640ba7a8bda0 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 17:24:19 +0000 Subject: [PATCH 24/29] Unify `MapFindResult` types --- src/common.cpp | 3 +- src/ptr_map.cpp | 4 +- src/ptr_set.cpp | 85 +++++++++++++++++++------------------------ src/string_map.cpp | 91 +++++++++++++++++++--------------------------- src/string_set.cpp | 64 +++++++++++++++----------------- 5 files changed, 107 insertions(+), 140 deletions(-) diff --git a/src/common.cpp b/src/common.cpp index f7a0653ac..cca478421 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -275,10 +275,9 @@ gb_global String global_module_path = {0}; gb_global bool global_module_path_set = false; -#include "string_map.cpp" -#include "map.cpp" #include "ptr_map.cpp" #include "ptr_set.cpp" +#include "string_map.cpp" #include "string_set.cpp" #include "priority_queue.cpp" #include "thread_pool.cpp" diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp index 19443d8a1..7937e6968 100644 --- a/src/ptr_map.cpp +++ b/src/ptr_map.cpp @@ -29,11 +29,11 @@ struct PtrMap { u32 ptr_map_hash_key(void const *key) { // TODO(bill): Improve ptr_map_hash_key - return gb_fnv32a(&key, gb_size_of(key)); + return fnv32a(&key, gb_size_of(key)); } u32 ptr_map_hash_key(uintptr key) { // TODO(bill): Improve ptr_map_hash_key - return gb_fnv32a(&key, gb_size_of(key)); + return fnv32a(&key, gb_size_of(key)); } template void map_init (PtrMap *h, gbAllocator a, isize capacity = 16); diff --git a/src/ptr_set.cpp b/src/ptr_set.cpp index 0ca1921e8..4ab3d3259 100644 --- a/src/ptr_set.cpp +++ b/src/ptr_set.cpp @@ -1,23 +1,12 @@ -typedef u32 PtrSetIndex; - -struct PtrSetFindResult { - PtrSetIndex hash_index; - PtrSetIndex entry_prev; - PtrSetIndex entry_index; -}; - -enum : PtrSetIndex { PTR_SET_SENTINEL = ~(PtrSetIndex)0 }; - - template struct PtrSetEntry { - T ptr; - PtrSetIndex next; + T ptr; + MapIndex next; }; template struct PtrSet { - Slice hashes; + Slice hashes; Array> entries; }; @@ -40,7 +29,7 @@ void ptr_set_init(PtrSet *s, gbAllocator a, isize capacity) { slice_init(&s->hashes, a, capacity); array_init(&s->entries, a, 0, capacity); for (isize i = 0; i < capacity; i++) { - s->hashes.data[i] = PTR_SET_SENTINEL; + s->hashes.data[i] = MAP_SENTINEL; } } @@ -51,24 +40,24 @@ void ptr_set_destroy(PtrSet *s) { } template -gb_internal PtrSetIndex ptr_set__add_entry(PtrSet *s, T ptr) { +gb_internal MapIndex ptr_set__add_entry(PtrSet *s, T ptr) { PtrSetEntry e = {}; e.ptr = ptr; - e.next = PTR_SET_SENTINEL; + e.next = MAP_SENTINEL; array_add(&s->entries, e); - return cast(PtrSetIndex)(s->entries.count-1); + return cast(MapIndex)(s->entries.count-1); } template -gb_internal PtrSetFindResult ptr_set__find(PtrSet *s, T ptr) { - PtrSetFindResult fr = {PTR_SET_SENTINEL, PTR_SET_SENTINEL, PTR_SET_SENTINEL}; +gb_internal MapFindResult ptr_set__find(PtrSet *s, T ptr) { + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; if (s->hashes.count != 0) { u64 hash = 0xcbf29ce484222325ull ^ cast(u64)cast(uintptr)ptr; u64 n = cast(u64)s->hashes.count; - fr.hash_index = cast(PtrSetIndex)(hash & (n-1)); + fr.hash_index = cast(MapIndex)(hash & (n-1)); fr.entry_index = s->hashes.data[fr.hash_index]; - while (fr.entry_index != PTR_SET_SENTINEL) { + while (fr.entry_index != MAP_SENTINEL) { if (s->entries.data[fr.entry_index].ptr == ptr) { return fr; } @@ -80,14 +69,14 @@ gb_internal PtrSetFindResult ptr_set__find(PtrSet *s, T ptr) { } template -gb_internal PtrSetFindResult ptr_set__find_from_entry(PtrSet *s, PtrSetEntry *e) { - PtrSetFindResult fr = {PTR_SET_SENTINEL, PTR_SET_SENTINEL, PTR_SET_SENTINEL}; +gb_internal MapFindResult ptr_set__find_from_entry(PtrSet *s, PtrSetEntry *e) { + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; if (s->hashes.count != 0) { u64 hash = 0xcbf29ce484222325ull ^ cast(u64)cast(uintptr)e->ptr; u64 n = cast(u64)s->hashes.count; - fr.hash_index = cast(PtrSetIndex)(hash & (n-1)); + fr.hash_index = cast(MapIndex)(hash & (n-1)); fr.entry_index = s->hashes.data[fr.hash_index]; - while (fr.entry_index != PTR_SET_SENTINEL) { + while (fr.entry_index != MAP_SENTINEL) { if (&s->entries.data[fr.entry_index] == e) { return fr; } @@ -112,17 +101,17 @@ gb_inline void ptr_set_grow(PtrSet *s) { template void ptr_set_reset_entries(PtrSet *s) { for (isize i = 0; i < s->hashes.count; i++) { - s->hashes.data[i] = PTR_SET_SENTINEL; + s->hashes.data[i] = MAP_SENTINEL; } for (isize i = 0; i < s->entries.count; i++) { - PtrSetFindResult fr; + MapFindResult fr; PtrSetEntry *e = &s->entries.data[i]; - e->next = PTR_SET_SENTINEL; + e->next = MAP_SENTINEL; fr = ptr_set__find_from_entry(s, e); - if (fr.entry_prev == PTR_SET_SENTINEL) { - s->hashes[fr.hash_index] = cast(PtrSetIndex)i; + if (fr.entry_prev == MAP_SENTINEL) { + s->hashes[fr.hash_index] = cast(MapIndex)i; } else { - s->entries[fr.entry_prev].next = cast(PtrSetIndex)i; + s->entries[fr.entry_prev].next = cast(MapIndex)i; } } } @@ -146,21 +135,21 @@ void ptr_set_rehash(PtrSet *s, isize new_count) { template gb_inline bool ptr_set_exists(PtrSet *s, T ptr) { isize index = ptr_set__find(s, ptr).entry_index; - return index != PTR_SET_SENTINEL; + return index != MAP_SENTINEL; } // Returns true if it already exists template T ptr_set_add(PtrSet *s, T ptr) { - PtrSetIndex index; - PtrSetFindResult fr; + MapIndex index; + MapFindResult fr; if (s->hashes.count == 0) { ptr_set_grow(s); } fr = ptr_set__find(s, ptr); - if (fr.entry_index == PTR_SET_SENTINEL) { + if (fr.entry_index == MAP_SENTINEL) { index = ptr_set__add_entry(s, ptr); - if (fr.entry_prev != PTR_SET_SENTINEL) { + if (fr.entry_prev != MAP_SENTINEL) { s->entries.data[fr.entry_prev].next = index; } else { s->hashes.data[fr.hash_index] = index; @@ -175,17 +164,17 @@ T ptr_set_add(PtrSet *s, T ptr) { template bool ptr_set_update(PtrSet *s, T ptr) { // returns true if it previously existsed bool exists = false; - PtrSetIndex index; - PtrSetFindResult fr; + MapIndex index; + MapFindResult fr; if (s->hashes.count == 0) { ptr_set_grow(s); } fr = ptr_set__find(s, ptr); - if (fr.entry_index != PTR_SET_SENTINEL) { + if (fr.entry_index != MAP_SENTINEL) { exists = true; } else { index = ptr_set__add_entry(s, ptr); - if (fr.entry_prev != PTR_SET_SENTINEL) { + if (fr.entry_prev != MAP_SENTINEL) { s->entries.data[fr.entry_prev].next = index; } else { s->hashes.data[fr.hash_index] = index; @@ -200,9 +189,9 @@ bool ptr_set_update(PtrSet *s, T ptr) { // returns true if it previously exis template -void ptr_set__erase(PtrSet *s, PtrSetFindResult fr) { - PtrSetFindResult last; - if (fr.entry_prev == PTR_SET_SENTINEL) { +void ptr_set__erase(PtrSet *s, MapFindResult fr) { + MapFindResult last; + if (fr.entry_prev == MAP_SENTINEL) { s->hashes.data[fr.hash_index] = s->entries.data[fr.entry_index].next; } else { s->entries.data[fr.entry_prev].next = s->entries.data[fr.entry_index].next; @@ -213,7 +202,7 @@ void ptr_set__erase(PtrSet *s, PtrSetFindResult fr) { } s->entries.data[fr.entry_index] = s->entries.data[s->entries.count-1]; last = ptr_set__find(s, s->entries.data[fr.entry_index].ptr); - if (last.entry_prev != PTR_SET_SENTINEL) { + if (last.entry_prev != MAP_SENTINEL) { s->entries.data[last.entry_prev].next = fr.entry_index; } else { s->hashes.data[last.hash_index] = fr.entry_index; @@ -222,8 +211,8 @@ void ptr_set__erase(PtrSet *s, PtrSetFindResult fr) { template void ptr_set_remove(PtrSet *s, T ptr) { - PtrSetFindResult fr = ptr_set__find(s, ptr); - if (fr.entry_index != PTR_SET_SENTINEL) { + MapFindResult fr = ptr_set__find(s, ptr); + if (fr.entry_index != MAP_SENTINEL) { ptr_set__erase(s, fr); } } @@ -232,6 +221,6 @@ template gb_inline void ptr_set_clear(PtrSet *s) { array_clear(&s->entries); for (isize i = 0; i < s->hashes.count; i++) { - s->hashes.data[i] = PTR_SET_SENTINEL; + s->hashes.data[i] = MAP_SENTINEL; } } diff --git a/src/string_map.cpp b/src/string_map.cpp index 448af624d..218a45482 100644 --- a/src/string_map.cpp +++ b/src/string_map.cpp @@ -1,28 +1,11 @@ -// NOTE(bill): This util stuff is the same for every `Map` - -typedef u32 StringMapIndex; - -struct StringMapFindResult { - StringMapIndex hash_index; - StringMapIndex entry_prev; - StringMapIndex entry_index; -}; - -enum : StringMapIndex { STRING_MAP_SENTINEL = ~(StringMapIndex)0 }; - - struct StringHashKey { - u64 hash; + u32 hash; String string; }; -u64 string_hashing_proc(void const *data, isize len) { - return fnv64a(data, len); -} - gb_inline StringHashKey string_hash_string(String const &s) { StringHashKey hash_key = {}; - hash_key.hash = string_hashing_proc(s.text, s.len); + hash_key.hash = fnv32a(s.text, s.len); hash_key.string = s; return hash_key; } @@ -40,14 +23,14 @@ bool operator!=(StringHashKey const &a, StringHashKey const &b) { return !string template struct StringMapEntry { - StringHashKey key; - StringMapIndex next; - T value; + StringHashKey key; + MapIndex next; + T value; }; template struct StringMap { - Slice hashes; + Slice hashes; Array > entries; }; @@ -79,7 +62,7 @@ gb_inline void string_map_init(StringMap *h, gbAllocator a, isize capacity) { slice_init(&h->hashes, a, capacity); array_init(&h->entries, a, 0, capacity); for (isize i = 0; i < capacity; i++) { - h->hashes.data[i] = STRING_MAP_SENTINEL; + h->hashes.data[i] = MAP_SENTINEL; } } @@ -90,21 +73,21 @@ gb_inline void string_map_destroy(StringMap *h) { } template -gb_internal StringMapIndex string_map__add_entry(StringMap *h, StringHashKey const &key) { +gb_internal MapIndex string_map__add_entry(StringMap *h, StringHashKey const &key) { StringMapEntry e = {}; e.key = key; - e.next = STRING_MAP_SENTINEL; + e.next = MAP_SENTINEL; array_add(&h->entries, e); - return cast(StringMapIndex)(h->entries.count-1); + return cast(MapIndex)(h->entries.count-1); } template -gb_internal StringMapFindResult string_map__find(StringMap *h, StringHashKey const &key) { - StringMapFindResult fr = {STRING_MAP_SENTINEL, STRING_MAP_SENTINEL, STRING_MAP_SENTINEL}; +gb_internal MapFindResult string_map__find(StringMap *h, StringHashKey const &key) { + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; if (h->hashes.count != 0) { - fr.hash_index = cast(StringMapIndex)(key.hash & (h->hashes.count-1)); + fr.hash_index = cast(MapIndex)(key.hash & (h->hashes.count-1)); fr.entry_index = h->hashes.data[fr.hash_index]; - while (fr.entry_index != STRING_MAP_SENTINEL) { + while (fr.entry_index != MAP_SENTINEL) { if (string_hash_key_equal(h->entries.data[fr.entry_index].key, key)) { return fr; } @@ -116,12 +99,12 @@ gb_internal StringMapFindResult string_map__find(StringMap *h, StringHashKey } template -gb_internal StringMapFindResult string_map__find_from_entry(StringMap *h, StringMapEntry *e) { - StringMapFindResult fr = {STRING_MAP_SENTINEL, STRING_MAP_SENTINEL, STRING_MAP_SENTINEL}; +gb_internal MapFindResult string_map__find_from_entry(StringMap *h, StringMapEntry *e) { + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; if (h->hashes.count != 0) { - fr.hash_index = cast(StringMapIndex)(e->key.hash & (h->hashes.count-1)); + fr.hash_index = cast(MapIndex)(e->key.hash & (h->hashes.count-1)); fr.entry_index = h->hashes.data[fr.hash_index]; - while (fr.entry_index != STRING_MAP_SENTINEL) { + while (fr.entry_index != MAP_SENTINEL) { if (&h->entries.data[fr.entry_index] == e) { return fr; } @@ -147,17 +130,17 @@ gb_inline void string_map_grow(StringMap *h) { template void string_map_reset_entries(StringMap *h) { for (isize i = 0; i < h->hashes.count; i++) { - h->hashes.data[i] = STRING_MAP_SENTINEL; + h->hashes.data[i] = MAP_SENTINEL; } for (isize i = 0; i < h->entries.count; i++) { - StringMapFindResult fr; + MapFindResult fr; StringMapEntry *e = &h->entries.data[i]; - e->next = STRING_MAP_SENTINEL; + e->next = MAP_SENTINEL; fr = string_map__find_from_entry(h, e); - if (fr.entry_prev == STRING_MAP_SENTINEL) { - h->hashes[fr.hash_index] = cast(StringMapIndex)i; + if (fr.entry_prev == MAP_SENTINEL) { + h->hashes[fr.hash_index] = cast(MapIndex)i; } else { - h->entries[fr.entry_prev].next = cast(StringMapIndex)i; + h->entries[fr.entry_prev].next = cast(MapIndex)i; } } } @@ -181,7 +164,7 @@ void string_map_rehash(StringMap *h, isize new_count) { template T *string_map_get(StringMap *h, StringHashKey const &key) { isize index = string_map__find(h, key).entry_index; - if (index != STRING_MAP_SENTINEL) { + if (index != MAP_SENTINEL) { return &h->entries.data[index].value; } return nullptr; @@ -200,7 +183,7 @@ gb_inline T *string_map_get(StringMap *h, char const *key) { template T &string_map_must_get(StringMap *h, StringHashKey const &key) { isize index = string_map__find(h, key).entry_index; - GB_ASSERT(index != STRING_MAP_SENTINEL); + GB_ASSERT(index != MAP_SENTINEL); return h->entries.data[index].value; } @@ -216,17 +199,17 @@ gb_inline T &string_map_must_get(StringMap *h, char const *key) { template void string_map_set(StringMap *h, StringHashKey const &key, T const &value) { - StringMapIndex index; - StringMapFindResult fr; + MapIndex index; + MapFindResult fr; if (h->hashes.count == 0) { string_map_grow(h); } fr = string_map__find(h, key); - if (fr.entry_index != STRING_MAP_SENTINEL) { + if (fr.entry_index != MAP_SENTINEL) { index = fr.entry_index; } else { index = string_map__add_entry(h, key); - if (fr.entry_prev != STRING_MAP_SENTINEL) { + if (fr.entry_prev != MAP_SENTINEL) { h->entries.data[fr.entry_prev].next = index; } else { h->hashes.data[fr.hash_index] = index; @@ -251,9 +234,9 @@ gb_inline void string_map_set(StringMap *h, char const *key, T const &value) template -void string_map__erase(StringMap *h, StringMapFindResult const &fr) { - StringMapFindResult last; - if (fr.entry_prev == STRING_MAP_SENTINEL) { +void string_map__erase(StringMap *h, MapFindResult const &fr) { + MapFindResult last; + if (fr.entry_prev == MAP_SENTINEL) { h->hashes.data[fr.hash_index] = h->entries.data[fr.entry_index].next; } else { h->entries.data[fr.entry_prev].next = h->entries.data[fr.entry_index].next; @@ -264,7 +247,7 @@ void string_map__erase(StringMap *h, StringMapFindResult const &fr) { } h->entries.data[fr.entry_index] = h->entries.data[h->entries.count-1]; last = string_map__find(h, h->entries.data[fr.entry_index].key); - if (last.entry_prev != STRING_MAP_SENTINEL) { + if (last.entry_prev != MAP_SENTINEL) { h->entries.data[last.entry_prev].next = fr.entry_index; } else { h->hashes.data[last.hash_index] = fr.entry_index; @@ -273,8 +256,8 @@ void string_map__erase(StringMap *h, StringMapFindResult const &fr) { template void string_map_remove(StringMap *h, StringHashKey const &key) { - StringMapFindResult fr = string_map__find(h, key); - if (fr.entry_index != STRING_MAP_SENTINEL) { + MapFindResult fr = string_map__find(h, key); + if (fr.entry_index != MAP_SENTINEL) { string_map__erase(h, fr); } } @@ -283,7 +266,7 @@ template gb_inline void string_map_clear(StringMap *h) { array_clear(&h->entries); for (isize i = 0; i < h->hashes.count; i++) { - h->hashes.data[i] = STRING_MAP_SENTINEL; + h->hashes.data[i] = MAP_SENTINEL; } } diff --git a/src/string_set.cpp b/src/string_set.cpp index 671b2c9ff..1f2ea96a4 100644 --- a/src/string_set.cpp +++ b/src/string_set.cpp @@ -1,17 +1,11 @@ -struct StringSetFindResult { - isize hash_index; - isize entry_prev; - isize entry_index; -}; - struct StringSetEntry { - u64 hash; - isize next; - String value; + u32 hash; + MapIndex next; + String value; }; struct StringSet { - Array hashes; + Array hashes; Array entries; }; @@ -36,22 +30,22 @@ gb_inline void string_set_destroy(StringSet *s) { array_free(&s->hashes); } -gb_internal isize string_set__add_entry(StringSet *s, StringHashKey const &key) { +gb_internal MapIndex string_set__add_entry(StringSet *s, StringHashKey const &key) { StringSetEntry e = {}; e.hash = key.hash; - e.next = -1; + e.next = MAP_SENTINEL; e.value = key.string; array_add(&s->entries, e); - return s->entries.count-1; + return cast(MapIndex)(s->entries.count-1); } -gb_internal StringSetFindResult string_set__find(StringSet *s, StringHashKey const &key) { - StringSetFindResult fr = {-1, -1, -1}; +gb_internal MapFindResult string_set__find(StringSet *s, StringHashKey const &key) { + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; if (s->hashes.count > 0) { // fr.hash_index = u128_to_i64(key.key % u128_from_i64(s->hashes.count)); - fr.hash_index = key.hash % s->hashes.count; + fr.hash_index = cast(MapIndex)(((u64)key.hash) % s->hashes.count); fr.entry_index = s->hashes[fr.hash_index]; - while (fr.entry_index >= 0) { + while (fr.entry_index != MAP_SENTINEL) { auto const &entry = s->entries[fr.entry_index]; if (entry.hash == key.hash && entry.value == key.string) { return fr; @@ -79,21 +73,21 @@ void string_set_rehash(StringSet *s, isize new_count) { array_resize(&ns.hashes, new_count); array_reserve(&ns.entries, s->entries.count); for (i = 0; i < new_count; i++) { - ns.hashes[i] = -1; + ns.hashes[i] = MAP_SENTINEL; } for (i = 0; i < s->entries.count; i++) { StringSetEntry *e = &s->entries[i]; - StringSetFindResult fr; + MapFindResult fr; if (ns.hashes.count == 0) { string_set_grow(&ns); } StringHashKey key = {e->hash, e->value}; fr = string_set__find(&ns, key); j = string_set__add_entry(&ns, key); - if (fr.entry_prev < 0) { - ns.hashes[fr.hash_index] = j; + if (fr.entry_prev == MAP_SENTINEL) { + ns.hashes[fr.hash_index] = cast(MapIndex)j; } else { - ns.entries[fr.entry_prev].next = j; + ns.entries[fr.entry_prev].next = cast(MapIndex)j; } ns.entries[j].next = fr.entry_index; ns.entries[j].value = e->value; @@ -108,22 +102,22 @@ void string_set_rehash(StringSet *s, isize new_count) { gb_inline bool string_set_exists(StringSet *s, String const &str) { StringHashKey key = string_hash_string(str); isize index = string_set__find(s, key).entry_index; - return index >= 0; + return index != MAP_SENTINEL; } void string_set_add(StringSet *s, String const &str) { - isize index; - StringSetFindResult fr; + MapIndex index; + MapFindResult fr; StringHashKey key = string_hash_string(str); if (s->hashes.count == 0) { string_set_grow(s); } fr = string_set__find(s, key); - if (fr.entry_index >= 0) { + if (fr.entry_index != MAP_SENTINEL) { index = fr.entry_index; } else { index = string_set__add_entry(s, key); - if (fr.entry_prev >= 0) { + if (fr.entry_prev != MAP_SENTINEL) { s->entries[fr.entry_prev].next = index; } else { s->hashes[fr.hash_index] = index; @@ -137,9 +131,9 @@ void string_set_add(StringSet *s, String const &str) { } -void string_set__erase(StringSet *s, StringSetFindResult fr) { - StringSetFindResult last; - if (fr.entry_prev < 0) { +void string_set__erase(StringSet *s, MapFindResult fr) { + MapFindResult last; + if (fr.entry_prev == MAP_SENTINEL) { s->hashes[fr.hash_index] = s->entries[fr.entry_index].next; } else { s->entries[fr.entry_prev].next = s->entries[fr.entry_index].next; @@ -152,7 +146,7 @@ void string_set__erase(StringSet *s, StringSetFindResult fr) { *entry = s->entries[s->entries.count-1]; StringHashKey key = {entry->hash, entry->value}; last = string_set__find(s, key); - if (last.entry_prev >= 0) { + if (last.entry_prev != MAP_SENTINEL) { s->entries[last.entry_prev].next = fr.entry_index; } else { s->hashes[last.hash_index] = fr.entry_index; @@ -161,13 +155,15 @@ void string_set__erase(StringSet *s, StringSetFindResult fr) { void string_set_remove(StringSet *s, String const &str) { StringHashKey key = string_hash_string(str); - StringSetFindResult fr = string_set__find(s, key); - if (fr.entry_index >= 0) { + MapFindResult fr = string_set__find(s, key); + if (fr.entry_index != MAP_SENTINEL) { string_set__erase(s, fr); } } gb_inline void string_set_clear(StringSet *s) { - array_clear(&s->hashes); array_clear(&s->entries); + for_array(i, s->hashes) { + s->hashes.data[i] = MAP_SENTINEL; + } } From 0c9bb9d920e0af4e6fe8299390c542f01ef77177 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 17:32:17 +0000 Subject: [PATCH 25/29] Clean up logic --- src/ptr_set.cpp | 2 +- src/string_set.cpp | 81 ++++++++++++++++++++++++++++------------------ 2 files changed, 51 insertions(+), 32 deletions(-) diff --git a/src/ptr_set.cpp b/src/ptr_set.cpp index 4ab3d3259..37815c057 100644 --- a/src/ptr_set.cpp +++ b/src/ptr_set.cpp @@ -94,7 +94,7 @@ gb_internal bool ptr_set__full(PtrSet *s) { template gb_inline void ptr_set_grow(PtrSet *s) { - isize new_count = s->hashes.count*2; + isize new_count = gb_max(s->hashes.count<<1, 16); ptr_set_rehash(s, new_count); } diff --git a/src/string_set.cpp b/src/string_set.cpp index 1f2ea96a4..e27145289 100644 --- a/src/string_set.cpp +++ b/src/string_set.cpp @@ -5,7 +5,7 @@ struct StringSetEntry { }; struct StringSet { - Array hashes; + Slice hashes; Array entries; }; @@ -21,13 +21,18 @@ void string_set_rehash (StringSet *s, isize new_count); gb_inline void string_set_init(StringSet *s, gbAllocator a, isize capacity) { - array_init(&s->hashes, a); - array_init(&s->entries, a); + capacity = next_pow2_isize(gb_max(16, capacity)); + + slice_init(&s->hashes, a, capacity); + array_init(&s->entries, a, 0, capacity); + for (isize i = 0; i < capacity; i++) { + s->hashes.data[i] = MAP_SENTINEL; + } } gb_inline void string_set_destroy(StringSet *s) { + slice_free(&s->hashes, s->entries.allocator); array_free(&s->entries); - array_free(&s->hashes); } gb_internal MapIndex string_set__add_entry(StringSet *s, StringHashKey const &key) { @@ -42,7 +47,6 @@ gb_internal MapIndex string_set__add_entry(StringSet *s, StringHashKey const &ke gb_internal MapFindResult string_set__find(StringSet *s, StringHashKey const &key) { MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; if (s->hashes.count > 0) { - // fr.hash_index = u128_to_i64(key.key % u128_from_i64(s->hashes.count)); fr.hash_index = cast(MapIndex)(((u64)key.hash) % s->hashes.count); fr.entry_index = s->hashes[fr.hash_index]; while (fr.entry_index != MAP_SENTINEL) { @@ -56,47 +60,62 @@ gb_internal MapFindResult string_set__find(StringSet *s, StringHashKey const &ke } return fr; } +gb_internal MapFindResult string_set__find_from_entry(StringSet *s, StringSetEntry *e) { + MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; + if (s->hashes.count > 0) { + fr.hash_index = cast(MapIndex)(e->hash % s->hashes.count); + fr.entry_index = s->hashes[fr.hash_index]; + while (fr.entry_index != MAP_SENTINEL) { + if (&s->entries[fr.entry_index] == e) { + return fr; + } + fr.entry_prev = fr.entry_index; + fr.entry_index = s->entries[fr.entry_index].next; + } + } + return fr; +} + gb_internal b32 string_set__full(StringSet *s) { return 0.75f * s->hashes.count <= s->entries.count; } gb_inline void string_set_grow(StringSet *s) { - isize new_count = ARRAY_GROW_FORMULA(s->entries.count); + isize new_count = gb_max(s->hashes.count<<1, 16); string_set_rehash(s, new_count); } -void string_set_rehash(StringSet *s, isize new_count) { - isize i, j; - StringSet ns = {}; - string_set_init(&ns, s->hashes.allocator); - array_resize(&ns.hashes, new_count); - array_reserve(&ns.entries, s->entries.count); - for (i = 0; i < new_count; i++) { - ns.hashes[i] = MAP_SENTINEL; + +void string_set_reset_entries(StringSet *s) { + for (isize i = 0; i < s->hashes.count; i++) { + s->hashes.data[i] = MAP_SENTINEL; } - for (i = 0; i < s->entries.count; i++) { - StringSetEntry *e = &s->entries[i]; + for (isize i = 0; i < s->entries.count; i++) { MapFindResult fr; - if (ns.hashes.count == 0) { - string_set_grow(&ns); - } - StringHashKey key = {e->hash, e->value}; - fr = string_set__find(&ns, key); - j = string_set__add_entry(&ns, key); + StringSetEntry *e = &s->entries.data[i]; + e->next = MAP_SENTINEL; + fr = string_set__find_from_entry(s, e); if (fr.entry_prev == MAP_SENTINEL) { - ns.hashes[fr.hash_index] = cast(MapIndex)j; + s->hashes[fr.hash_index] = cast(MapIndex)i; } else { - ns.entries[fr.entry_prev].next = cast(MapIndex)j; - } - ns.entries[j].next = fr.entry_index; - ns.entries[j].value = e->value; - if (string_set__full(&ns)) { - string_set_grow(&ns); + s->entries[fr.entry_prev].next = cast(MapIndex)i; } } - string_set_destroy(s); - *s = ns; +} + +void string_set_reserve(StringSet *s, isize cap) { + array_reserve(&s->entries, cap); + if (s->entries.count*2 < s->hashes.count) { + return; + } + slice_resize(&s->hashes, s->entries.allocator, cap*2); + string_set_reset_entries(s); +} + + +void string_set_rehash(StringSet *s, isize new_count) { + string_set_reserve(s, new_count); } gb_inline bool string_set_exists(StringSet *s, String const &str) { From 7be18b4a80ea1a52bb6d9d01d158d3eada9ca40e Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 17:36:00 +0000 Subject: [PATCH 26/29] Be more correct with `MapIndex` usage --- src/ptr_map.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp index 7937e6968..ac74dcfbc 100644 --- a/src/ptr_map.cpp +++ b/src/ptr_map.cpp @@ -168,7 +168,7 @@ void map_rehash(PtrMap *h, isize new_count) { template V *map_get(PtrMap *h, K key) { - isize index = map__find(h, key).entry_index; + MapIndex index = map__find(h, key).entry_index; if (index != MAP_SENTINEL) { return &h->entries.data[index].value; } @@ -177,7 +177,7 @@ V *map_get(PtrMap *h, K key) { template V &map_must_get(PtrMap *h, K key) { - isize index = map__find(h, key).entry_index; + MapIndex index = map__find(h, key).entry_index; GB_ASSERT(index != MAP_SENTINEL); return h->entries.data[index].value; } @@ -251,7 +251,7 @@ gb_inline void map_clear(PtrMap *h) { #if PTR_MAP_ENABLE_MULTI_MAP template PtrMapEntry *multi_map_find_first(PtrMap *h, K key) { - isize i = map__find(h, key).entry_index; + MapIndex i = map__find(h, key).entry_index; if (i == MAP_SENTINEL) { return nullptr; } @@ -260,7 +260,7 @@ PtrMapEntry *multi_map_find_first(PtrMap *h, K key) { template PtrMapEntry *multi_map_find_next(PtrMap *h, PtrMapEntry *e) { - isize i = e->next; + MapIndex i = e->next; while (i != MAP_SENTINEL) { if (h->entries.data[i].key == e->key) { return &h->entries.data[i]; From 899cc719905b1b2f261c74867a322e8db9c1ac44 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 17:55:09 +0000 Subject: [PATCH 27/29] Improve `ptr_map_hash_key` --- src/ptr_map.cpp | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp index ac74dcfbc..66a6f0fc5 100644 --- a/src/ptr_map.cpp +++ b/src/ptr_map.cpp @@ -14,10 +14,9 @@ template struct PtrMapEntry { static_assert(sizeof(K) == sizeof(void *), "Key size must be pointer size"); - u32 hash; - MapIndex next; K key; V value; + MapIndex next; }; template @@ -27,14 +26,33 @@ struct PtrMap { }; -u32 ptr_map_hash_key(void const *key) { - // TODO(bill): Improve ptr_map_hash_key - return fnv32a(&key, gb_size_of(key)); -} u32 ptr_map_hash_key(uintptr key) { +#if defined(GB_ARCH_64_BIT) // TODO(bill): Improve ptr_map_hash_key - return fnv32a(&key, gb_size_of(key)); + u32 key0 = (u32)(key & 0xffffffff); + u32 key1 = (u32)(key >> 32); + + u32 word; + u32 state = 0; + + state += key0 * 747796405u + 2891336453u; + word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; + state = (word >> 22u) ^ word; + state += key1 * 747796405u + 2891336453u; + word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; + state = (word >> 22u) ^ word; + return state; + +#elif defined(GB_ARCH_32_BIT) + u32 state = ((u32)key) * 747796405u + 2891336453u; + u32 word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; + return (word >> 22u) ^ word; +#endif } +u32 ptr_map_hash_key(void const *key) { + return ptr_map_hash_key((uintptr)key); +} + template void map_init (PtrMap *h, gbAllocator a, isize capacity = 16); template void map_destroy (PtrMap *h); @@ -77,7 +95,6 @@ gb_inline void map_destroy(PtrMap *h) { template gb_internal MapIndex map__add_entry(PtrMap *h, K key) { PtrMapEntry e = {}; - e.hash = ptr_map_hash_key(key); e.key = key; e.next = MAP_SENTINEL; array_add(&h->entries, e); @@ -109,7 +126,8 @@ gb_internal MapFindResult map__find_from_entry(PtrMap *h, PtrMapEntryhashes.count == 0) { return fr; } - fr.hash_index = cast(MapIndex)(e->hash & (h->hashes.count-1)); + u32 hash = ptr_map_hash_key(e->key); + fr.hash_index = cast(MapIndex)(hash & (h->hashes.count-1)); fr.entry_index = h->hashes.data[fr.hash_index]; while (fr.entry_index != MAP_SENTINEL) { if (&h->entries.data[fr.entry_index] == e) { From eb0faf9602224eb1ab381e28ac7b41b71ada3fbc Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 17:58:11 +0000 Subject: [PATCH 28/29] Unify hash logic for `PtrSet` --- src/ptr_set.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/ptr_set.cpp b/src/ptr_set.cpp index 37815c057..8dd3cb4dc 100644 --- a/src/ptr_set.cpp +++ b/src/ptr_set.cpp @@ -53,9 +53,8 @@ template gb_internal MapFindResult ptr_set__find(PtrSet *s, T ptr) { MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; if (s->hashes.count != 0) { - u64 hash = 0xcbf29ce484222325ull ^ cast(u64)cast(uintptr)ptr; - u64 n = cast(u64)s->hashes.count; - fr.hash_index = cast(MapIndex)(hash & (n-1)); + u32 hash = ptr_map_hash_key(ptr); + fr.hash_index = cast(MapIndex)(hash & (s->hashes.count-1)); fr.entry_index = s->hashes.data[fr.hash_index]; while (fr.entry_index != MAP_SENTINEL) { if (s->entries.data[fr.entry_index].ptr == ptr) { @@ -72,9 +71,8 @@ template gb_internal MapFindResult ptr_set__find_from_entry(PtrSet *s, PtrSetEntry *e) { MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL}; if (s->hashes.count != 0) { - u64 hash = 0xcbf29ce484222325ull ^ cast(u64)cast(uintptr)e->ptr; - u64 n = cast(u64)s->hashes.count; - fr.hash_index = cast(MapIndex)(hash & (n-1)); + u32 hash = ptr_map_hash_key(e->ptr); + fr.hash_index = cast(MapIndex)(hash & (s->hashes.count-1)); fr.entry_index = s->hashes.data[fr.hash_index]; while (fr.entry_index != MAP_SENTINEL) { if (&s->entries.data[fr.entry_index] == e) { From 36985f8da0cea59cb1912f62ae4e700983159b6a Mon Sep 17 00:00:00 2001 From: gingerBill Date: Fri, 5 Nov 2021 18:04:18 +0000 Subject: [PATCH 29/29] Simplification to `ptr_map_hash_key` --- src/ptr_map.cpp | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/src/ptr_map.cpp b/src/ptr_map.cpp index 66a6f0fc5..3d6be1d44 100644 --- a/src/ptr_map.cpp +++ b/src/ptr_map.cpp @@ -28,21 +28,11 @@ struct PtrMap { u32 ptr_map_hash_key(uintptr key) { #if defined(GB_ARCH_64_BIT) - // TODO(bill): Improve ptr_map_hash_key - u32 key0 = (u32)(key & 0xffffffff); - u32 key1 = (u32)(key >> 32); - - u32 word; - u32 state = 0; - - state += key0 * 747796405u + 2891336453u; - word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; - state = (word >> 22u) ^ word; - state += key1 * 747796405u + 2891336453u; - word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; - state = (word >> 22u) ^ word; - return state; - + u64 x = (u64)key; + u8 count = (u8)(x >> 59); + x ^= x >> (5 + count); + x *= 12605985483714917081ull; + return (u32)(x ^ (x >> 43)); #elif defined(GB_ARCH_32_BIT) u32 state = ((u32)key) * 747796405u + 2891336453u; u32 word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;