-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathenif_quick_sort.ex
More file actions
58 lines (51 loc) · 1.42 KB
/
enif_quick_sort.ex
File metadata and controls
58 lines (51 loc) · 1.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
defmodule ENIFQuickSort do
@moduledoc false
use Charms
alias Charms.{Pointer, Term}
defm swap(a :: Pointer.t(Term.t()), b :: Pointer.t(Term.t())) do
val_a = a[0]
val_b = b[0]
set! a[0], val_b
set! b[0], val_a
end
defm partition(arr :: Pointer.t(Term.t()), low :: i32(), high :: i32()) :: i32() do
pivot = arr[high]
i_ptr = tmp! i32()
set! i_ptr[0], low - 1
start = arr + low
for_loop {element, j} <- {start, high - low} do
if enif_compare(element, pivot) < 0 do
i = i_ptr[0] + 1
set! i_ptr[0], i
swap(arr + i, start + j)
end
end
i = i_ptr[0]
swap(arr + i + 1, arr + high)
i + 1
end
defm do_sort(arr :: Pointer.t(Term.t()), low :: i32(), high :: i32()) do
if low < high do
pi = partition(arr, low, high)
do_sort(arr, low, pi - 1)
do_sort(arr, pi + 1, high)
end
end
@err %ArgumentError{message: "list expected"}
defm sort(env, list) :: Term.t() do
len_ptr = tmp! i32()
if enif_get_list_length(env, list, len_ptr) != 0 do
movable_list_ptr = tmp! Term.t()
set! movable_list_ptr[0], list
len = len_ptr[0]
arr = new! Term.t(), len
SortUtil.copy_terms(env, movable_list_ptr, arr)
zero = const 0 :: i32()
do_sort(arr, zero, len - 1)
defer free! arr
enif_make_list_from_array(env, arr, len)
else
enif_raise_exception(env, @err)
end
end
end