mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 07:38:48 +00:00
Add sort.odin
This commit is contained in:
+209
@@ -0,0 +1,209 @@
|
|||||||
|
bubble_sort :: proc(array: []$T, f: proc(T, T) -> int) {
|
||||||
|
assert(f != nil);
|
||||||
|
count := len(array);
|
||||||
|
|
||||||
|
init_j, last_j := 0, count-1;
|
||||||
|
|
||||||
|
for {
|
||||||
|
init_swap, prev_swap := -1, -1;
|
||||||
|
|
||||||
|
for j in init_j..<last_j {
|
||||||
|
if f(array[j], array[j+1]) > 0 {
|
||||||
|
array[j], array[j+1] = array[j+1], array[j];
|
||||||
|
prev_swap = j;
|
||||||
|
if init_swap == -1 do init_swap = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if prev_swap == -1 do return;
|
||||||
|
|
||||||
|
init_j = max(init_swap-1, 0);
|
||||||
|
last_j = prev_swap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bubble_sort :: proc(array: []$T) {
|
||||||
|
count := len(array);
|
||||||
|
|
||||||
|
init_j, last_j := 0, count-1;
|
||||||
|
|
||||||
|
for {
|
||||||
|
init_swap, prev_swap := -1, -1;
|
||||||
|
|
||||||
|
for j in init_j..<last_j {
|
||||||
|
if array[j] > array[j+1] {
|
||||||
|
array[j], array[j+1] = array[j+1], array[j];
|
||||||
|
prev_swap = j;
|
||||||
|
if init_swap == -1 do init_swap = j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if prev_swap == -1 do return;
|
||||||
|
|
||||||
|
init_j = max(init_swap-1, 0);
|
||||||
|
last_j = prev_swap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quick_sort :: proc(array: []$T, f: proc(T, T) -> int) {
|
||||||
|
assert(f != nil);
|
||||||
|
a := array;
|
||||||
|
n := len(a);
|
||||||
|
if n < 2 do return;
|
||||||
|
|
||||||
|
p := a[n/2];
|
||||||
|
i, j := 0, n-1;
|
||||||
|
|
||||||
|
loop: for {
|
||||||
|
for f(a[i], p) < 0 do i += 1;
|
||||||
|
for f(p, a[j]) < 0 do j -= 1;
|
||||||
|
|
||||||
|
if i >= j do break loop;
|
||||||
|
|
||||||
|
a[i], a[j] = a[j], a[i];
|
||||||
|
i += 1;
|
||||||
|
j -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
quick_sort(a[0..<i], f);
|
||||||
|
quick_sort(a[i..<n], f);
|
||||||
|
}
|
||||||
|
|
||||||
|
quick_sort :: proc(array: []$T) {
|
||||||
|
a := array;
|
||||||
|
n := len(a);
|
||||||
|
if n < 2 do return;
|
||||||
|
|
||||||
|
p := a[n/2];
|
||||||
|
i, j := 0, n-1;
|
||||||
|
|
||||||
|
loop: for {
|
||||||
|
for a[i] < p do i += 1;
|
||||||
|
for p < a[j] do j -= 1;
|
||||||
|
|
||||||
|
if i >= j do break loop;
|
||||||
|
|
||||||
|
a[i], a[j] = a[j], a[i];
|
||||||
|
i += 1;
|
||||||
|
j -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
quick_sort(a[0..<i]);
|
||||||
|
quick_sort(a[i..<n]);
|
||||||
|
}
|
||||||
|
|
||||||
|
_log2 :: proc(n: int) -> int {
|
||||||
|
res := 0;
|
||||||
|
for ; n != 0; n >>= 1 do res++;
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
merge_sort :: proc(array: []$T, f: proc(T, T) -> int) {
|
||||||
|
merge_slices :: proc(arr1, arr2, out: []$T, f: proc(T, T) -> int) {
|
||||||
|
N1, N2 := len(arr1), len(arr2);
|
||||||
|
i, j := 0, 0;
|
||||||
|
for k in 0..<N1+N2 {
|
||||||
|
if j == N2 || i < N1 && j < N2 && f(arr1[i], arr2[j]) < 0 {
|
||||||
|
out[k] = arr1[i]; i++;
|
||||||
|
} else {
|
||||||
|
out[k] = arr2[j]; j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(f != nil);
|
||||||
|
|
||||||
|
arr1 := array;
|
||||||
|
N := len(arr1);
|
||||||
|
arr2 := make([]T, N);
|
||||||
|
defer free(arr2);
|
||||||
|
|
||||||
|
a, b, m, M := N/2, N, 1, _log2(N);
|
||||||
|
|
||||||
|
for i in 0..<M+1 {
|
||||||
|
for j in 0..<a {
|
||||||
|
k := 2*j*m;
|
||||||
|
merge_slices(arr1[k..<k+m], arr1[k+m..<k+m+m], arr2[k..], f);
|
||||||
|
}
|
||||||
|
if N-b > m {
|
||||||
|
k := 2*a*m;
|
||||||
|
merge_slices(arr1[k..<k+m], arr1[k+m..<k+m+(N-b)&(m-1)], arr2[k..], f);
|
||||||
|
} else {
|
||||||
|
copy(arr2[b..N-1], arr1[b..N-1]);
|
||||||
|
}
|
||||||
|
arr1, arr2 = arr2, arr1;
|
||||||
|
m <<= 1;
|
||||||
|
a >>= 1;
|
||||||
|
b = a << uint(i) << 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if M & 1 == 0 do copy(arr2, arr1);
|
||||||
|
}
|
||||||
|
|
||||||
|
merge_sort :: proc(array: []$T) {
|
||||||
|
merge_slices :: proc(arr1, arr2, out: []$T) {
|
||||||
|
N1, N2 := len(arr1), len(arr2);
|
||||||
|
i, j := 0, 0;
|
||||||
|
for k in 0..<N1+N2 {
|
||||||
|
if j == N2 || i < N1 && j < N2 && arr1[i] < arr2[j] {
|
||||||
|
out[k] = arr1[i]; i++;
|
||||||
|
} else {
|
||||||
|
out[k] = arr2[j]; j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
arr1 := array;
|
||||||
|
N := len(arr1);
|
||||||
|
arr2 := make([]T, N);
|
||||||
|
defer free(arr2);
|
||||||
|
|
||||||
|
a, b, m, M := N/2, N, 1, _log2(N);
|
||||||
|
|
||||||
|
for i in 0..<M+1 {
|
||||||
|
for j in 0..<a {
|
||||||
|
k := 2*j*m;
|
||||||
|
merge_slices(arr1[k..<k+m], arr1[k+m..<k+m+m], arr2[k..]);
|
||||||
|
}
|
||||||
|
if N-b > m {
|
||||||
|
k := 2*a*m;
|
||||||
|
merge_slices(arr1[k..<k+m], arr1[k+m..<k+m+(N-b)&(m-1)], arr2[k..]);
|
||||||
|
} else {
|
||||||
|
copy(arr2[b..N-1], arr1[b..N-1]);
|
||||||
|
}
|
||||||
|
arr1, arr2 = arr2, arr1;
|
||||||
|
m <<= 1;
|
||||||
|
a >>= 1;
|
||||||
|
b = a << uint(i) << 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if M & 1 == 0 do copy(arr2, arr1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
compare_ints :: proc(a, b: int) -> int {
|
||||||
|
match delta := a - b; {
|
||||||
|
case delta < 0: return -1;
|
||||||
|
case delta > 0: return +1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
compare_f32s :: proc(a, b: f32) -> int {
|
||||||
|
match delta := a - b; {
|
||||||
|
case delta < 0: return -1;
|
||||||
|
case delta > 0: return +1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
compare_f64s :: proc(a, b: f64) -> int {
|
||||||
|
match delta := a - b; {
|
||||||
|
case delta < 0: return -1;
|
||||||
|
case delta > 0: return +1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
compare_strings :: proc(a, b: string) -> int {
|
||||||
|
return __string_cmp(a, b);
|
||||||
|
}
|
||||||
+27
-11
@@ -194,6 +194,8 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ
|
|||||||
DeclInfo *old_decl = decl_info_of_entity(&c->info, base_entity);
|
DeclInfo *old_decl = decl_info_of_entity(&c->info, base_entity);
|
||||||
GB_ASSERT(old_decl != nullptr);
|
GB_ASSERT(old_decl != nullptr);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
gbAllocator a = heap_allocator();
|
gbAllocator a = heap_allocator();
|
||||||
|
|
||||||
Array<Operand> operands = {};
|
Array<Operand> operands = {};
|
||||||
@@ -214,6 +216,8 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ
|
|||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CheckerContext prev_context = c->context;
|
CheckerContext prev_context = c->context;
|
||||||
defer (c->context = prev_context);
|
defer (c->context = prev_context);
|
||||||
|
|
||||||
@@ -222,7 +226,7 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ
|
|||||||
c->context.scope = scope;
|
c->context.scope = scope;
|
||||||
c->context.allow_polymorphic_types = true;
|
c->context.allow_polymorphic_types = true;
|
||||||
if (param_operands == nullptr) {
|
if (param_operands == nullptr) {
|
||||||
c->context.no_polymorphic_errors = false;
|
// c->context.no_polymorphic_errors = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool generate_type_again = c->context.no_polymorphic_errors;
|
bool generate_type_again = c->context.no_polymorphic_errors;
|
||||||
@@ -233,6 +237,7 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ
|
|||||||
// Maybe it's better to check with the previous types first?
|
// Maybe it's better to check with the previous types first?
|
||||||
Type *final_proc_type = make_type_proc(c->allocator, scope, nullptr, 0, nullptr, 0, false, pt->calling_convention);
|
Type *final_proc_type = make_type_proc(c->allocator, scope, nullptr, 0, nullptr, 0, false, pt->calling_convention);
|
||||||
bool success = check_procedure_type(c, final_proc_type, pt->node, &operands);
|
bool success = check_procedure_type(c, final_proc_type, pt->node, &operands);
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -252,6 +257,7 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (generate_type_again) {
|
if (generate_type_again) {
|
||||||
// LEAK TODO(bill): This is technically a memory leak as it has to generate the type twice
|
// LEAK TODO(bill): This is technically a memory leak as it has to generate the type twice
|
||||||
|
|
||||||
@@ -350,6 +356,7 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool check_polymorphic_procedure_assignment(Checker *c, Operand *operand, Type *type, PolyProcData *poly_proc_data) {
|
bool check_polymorphic_procedure_assignment(Checker *c, Operand *operand, Type *type, PolyProcData *poly_proc_data) {
|
||||||
|
if (operand->expr == NULL) return false;
|
||||||
Entity *base_entity = entity_of_ident(&c->info, operand->expr);
|
Entity *base_entity = entity_of_ident(&c->info, operand->expr);
|
||||||
if (base_entity == nullptr) return false;
|
if (base_entity == nullptr) return false;
|
||||||
return find_or_generate_polymorphic_procedure(c, base_entity, type, nullptr, poly_proc_data, true);
|
return find_or_generate_polymorphic_procedure(c, base_entity, type, nullptr, poly_proc_data, true);
|
||||||
@@ -619,17 +626,24 @@ void check_assignment(Checker *c, Operand *operand, Type *type, String context_n
|
|||||||
// TODO(bill): is this a good enough error message?
|
// TODO(bill): is this a good enough error message?
|
||||||
// TODO(bill): Actually allow built in procedures to be passed around and thus be created on use
|
// TODO(bill): Actually allow built in procedures to be passed around and thus be created on use
|
||||||
error(operand->expr,
|
error(operand->expr,
|
||||||
"Cannot assign built-in procedure `%s` in %.*s",
|
"Cannot assign built-in procedure `%s` in %.*s",
|
||||||
expr_str,
|
expr_str,
|
||||||
LIT(context_name));
|
LIT(context_name));
|
||||||
|
} else if (operand->mode == Addressing_Type) {
|
||||||
|
// TODO(bill): is this a good enough error message?
|
||||||
|
// TODO(bill): Actually allow built in procedures to be passed around and thus be created on use
|
||||||
|
error(operand->expr,
|
||||||
|
"Cannot assign type `%s` as a value in %.*s",
|
||||||
|
op_type_str,
|
||||||
|
LIT(context_name));
|
||||||
} else {
|
} else {
|
||||||
// TODO(bill): is this a good enough error message?
|
// TODO(bill): is this a good enough error message?
|
||||||
error(operand->expr,
|
error(operand->expr,
|
||||||
"Cannot assign value `%s` of type `%s` to `%s` in %.*s",
|
"Cannot assign value `%s` of type `%s` to `%s` in %.*s",
|
||||||
expr_str,
|
expr_str,
|
||||||
op_type_str,
|
op_type_str,
|
||||||
type_str,
|
type_str,
|
||||||
LIT(context_name));
|
LIT(context_name));
|
||||||
}
|
}
|
||||||
operand->mode = Addressing_Invalid;
|
operand->mode = Addressing_Invalid;
|
||||||
|
|
||||||
@@ -1376,6 +1390,7 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c
|
|||||||
case Type_Record:
|
case Type_Record:
|
||||||
if (source->kind == Type_Record) {
|
if (source->kind == Type_Record) {
|
||||||
// TODO(bill): Polymorphic type assignment
|
// TODO(bill): Polymorphic type assignment
|
||||||
|
// return check_is_assignable_to(c, &o, poly);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
case Type_Tuple:
|
case Type_Tuple:
|
||||||
@@ -1383,8 +1398,9 @@ bool is_polymorphic_type_assignable(Checker *c, Type *poly, Type *source, bool c
|
|||||||
return false;
|
return false;
|
||||||
case Type_Proc:
|
case Type_Proc:
|
||||||
if (source->kind == Type_Proc) {
|
if (source->kind == Type_Proc) {
|
||||||
|
// return check_is_assignable_to(c, &o, poly);
|
||||||
// TODO(bill): Polymorphic type assignment
|
// TODO(bill): Polymorphic type assignment
|
||||||
#if 0
|
#if 1
|
||||||
TypeProc *x = &poly->Proc;
|
TypeProc *x = &poly->Proc;
|
||||||
TypeProc *y = &source->Proc;
|
TypeProc *y = &source->Proc;
|
||||||
if (x->calling_convention != y->calling_convention) {
|
if (x->calling_convention != y->calling_convention) {
|
||||||
@@ -5837,10 +5853,10 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
|
|||||||
CallArgumentError err = CallArgumentError_None;
|
CallArgumentError err = CallArgumentError_None;
|
||||||
CallArgumentData data = {};
|
CallArgumentData data = {};
|
||||||
CheckerContext prev_context = c->context;
|
CheckerContext prev_context = c->context;
|
||||||
|
defer (c->context = prev_context);
|
||||||
c->context.no_polymorphic_errors = true;
|
c->context.no_polymorphic_errors = true;
|
||||||
c->context.allow_polymorphic_types = is_type_polymorphic(pt);
|
c->context.allow_polymorphic_types = is_type_polymorphic(pt);
|
||||||
err = call_checker(c, call, pt, p, operands, CallArgumentMode_NoErrors, &data);
|
err = call_checker(c, call, pt, p, operands, CallArgumentMode_NoErrors, &data);
|
||||||
c->context = prev_context;
|
|
||||||
|
|
||||||
if (err == CallArgumentError_None) {
|
if (err == CallArgumentError_None) {
|
||||||
valids[valid_count].index = i;
|
valids[valid_count].index = i;
|
||||||
|
|||||||
Reference in New Issue
Block a user