Skip to content

Commit a3e2572

Browse files
authored
Merge branch 'codezonediitj:main' into dfs-backend
2 parents aa53deb + dcc0175 commit a3e2572

File tree

7 files changed

+683
-4
lines changed

7 files changed

+683
-4
lines changed

AUTHORS

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,5 @@ Pratik Goyal <[email protected]>
1111
Jay Thorat <[email protected]>
1212
Rajveer Singh Bharadwaj <[email protected]>
1313
Kishan Ved <[email protected]>
14-
Arvinder Singh Dhoul <[email protected]>
14+
Arvinder Singh Dhoul <[email protected]>
15+
Harshita Kalani <[email protected]>

environment.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
name: pyds-env
22
channels:
33
- conda-forge
4-
- defaults
54
dependencies:
6-
- python=3.8
5+
- python=3.9
76
- pip
87
- pytest
98
- pip:
@@ -15,3 +14,4 @@ dependencies:
1514
- sphinx-readable-theme==1.3.0
1615
- myst_nb==0.17.2
1716
- lcov
17+
- llvmlite

pydatastructs/linear_data_structures/_backend/cpp/algorithms/algorithms.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ static PyMethodDef algorithms_PyMethodDef[] = {
1010
METH_VARARGS | METH_KEYWORDS, ""},
1111
{"bubble_sort_llvm", (PyCFunction)bubble_sort_llvm,
1212
METH_VARARGS | METH_KEYWORDS, ""},
13+
{"selection_sort_llvm", (PyCFunction)selection_sort_llvm,
14+
METH_VARARGS | METH_KEYWORDS, ""},
1315
{"selection_sort", (PyCFunction) selection_sort,
1416
METH_VARARGS | METH_KEYWORDS, ""},
1517
{"insertion_sort", (PyCFunction) insertion_sort,

pydatastructs/linear_data_structures/_backend/cpp/algorithms/llvm_algorithms.py

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,3 +167,131 @@ def _materialize(dtype: str) -> int:
167167

168168
except Exception as e:
169169
raise RuntimeError(f"Failed to materialize function for dtype {dtype}: {e}")
170+
171+
def get_selection_sort_ptr(dtype: str) -> int:
172+
"""Get function pointer for selection sort with specified dtype."""
173+
dtype = dtype.lower().strip()
174+
if dtype not in _SUPPORTED:
175+
raise ValueError(f"Unsupported dtype '{dtype}'. Supported: {list(_SUPPORTED)}")
176+
177+
return _materialize_selection(dtype)
178+
179+
180+
def _build_selection_sort_ir(dtype: str) -> str:
181+
if dtype not in _SUPPORTED:
182+
raise ValueError(f"Unsupported dtype '{dtype}'. Supported: {list(_SUPPORTED)}")
183+
184+
T, _ = _SUPPORTED[dtype]
185+
i32 = ir.IntType(32)
186+
i64 = ir.IntType(64)
187+
188+
mod = ir.Module(name=f"selection_sort_{dtype}_module")
189+
fn_name = f"selection_sort_{dtype}"
190+
191+
fn_ty = ir.FunctionType(ir.VoidType(), [T.as_pointer(), i32])
192+
fn = ir.Function(mod, fn_ty, name=fn_name)
193+
194+
arr, n = fn.args
195+
arr.name, n.name = "arr", "n"
196+
197+
# Basic blocks
198+
b_entry = fn.append_basic_block("entry")
199+
b_outer = fn.append_basic_block("outer")
200+
b_inner = fn.append_basic_block("inner")
201+
b_inner_latch = fn.append_basic_block("inner.latch")
202+
b_swap = fn.append_basic_block("swap")
203+
b_exit = fn.append_basic_block("exit")
204+
205+
b = ir.IRBuilder(b_entry)
206+
cond_trivial = b.icmp_signed("<=", n, ir.Constant(i32, 1))
207+
b.cbranch(cond_trivial, b_exit, b_outer)
208+
209+
# Outer loop
210+
b.position_at_end(b_outer)
211+
i_phi = b.phi(i32, name="i")
212+
i_phi.add_incoming(ir.Constant(i32, 0), b_entry) # start at 0
213+
214+
cond_outer = b.icmp_signed("<", i_phi, n)
215+
b.cbranch(cond_outer, b_inner, b_exit)
216+
217+
# Inner loop: find min index
218+
b.position_at_end(b_inner)
219+
min_idx = b_phi = b_phi_i = b.phi(i32, name="min_idx")
220+
min_idx.add_incoming(i_phi, b_outer) # initial min_idx = i
221+
222+
j_phi = b.phi(i32, name="j")
223+
j_phi.add_incoming(b.add(i_phi, ir.Constant(i32, 1)), b_outer)
224+
225+
cond_inner = b.icmp_signed("<", j_phi, n)
226+
b.cbranch(cond_inner, b_inner_latch, b_swap)
227+
228+
# Compare and update min_idx
229+
b.position_at_end(b_inner_latch)
230+
j64 = b.sext(j_phi, i64)
231+
min64 = b.sext(min_idx, i64)
232+
arr_j_ptr = b.gep(arr, [j64], inbounds=True)
233+
arr_min_ptr = b.gep(arr, [min64], inbounds=True)
234+
arr_j_val = b.load(arr_j_ptr)
235+
arr_min_val = b.load(arr_min_ptr)
236+
237+
if isinstance(T, ir.IntType):
238+
cmp = b.icmp_signed("<", arr_j_val, arr_min_val)
239+
else:
240+
cmp = b.fcmp_ordered("<", arr_j_val, arr_min_val)
241+
242+
with b.if_then(cmp):
243+
min_idx = j_phi # update min_idx
244+
245+
j_next = b.add(j_phi, ir.Constant(i32, 1))
246+
j_phi.add_incoming(j_next, b_inner_latch)
247+
min_idx.add_incoming(min_idx, b_inner_latch) # propagate current min_idx
248+
b.branch(b_inner)
249+
250+
# Swap arr[i] and arr[min_idx]
251+
b.position_at_end(b_swap)
252+
i64 = b.sext(i_phi, i64)
253+
min64 = b.sext(min_idx, i64)
254+
ptr_i = b.gep(arr, [i64], inbounds=True)
255+
ptr_min = b.gep(arr, [min64], inbounds=True)
256+
val_i = b.load(ptr_i)
257+
val_min = b.load(ptr_min)
258+
b.store(val_min, ptr_i)
259+
b.store(val_i, ptr_min)
260+
261+
# Increment i
262+
i_next = b.add(i_phi, ir.Constant(i32, 1))
263+
i_phi.add_incoming(i_next, b_swap)
264+
b.branch(b_outer)
265+
266+
# Exit
267+
b.position_at_end(b_exit)
268+
b.ret_void()
269+
270+
return str(mod)
271+
272+
273+
def _materialize_selection(dtype: str) -> int:
274+
_ensure_target_machine()
275+
276+
name = f"selection_sort_{dtype}"
277+
if dtype in _fn_ptr_cache:
278+
return _fn_ptr_cache[dtype]
279+
280+
try:
281+
llvm_ir = _build_selection_sort_ir(dtype)
282+
mod = binding.parse_assembly(llvm_ir)
283+
mod.verify()
284+
285+
engine = binding.create_mcjit_compiler(mod, _target_machine)
286+
engine.finalize_object()
287+
engine.run_static_constructors()
288+
289+
addr = engine.get_function_address(name)
290+
if not addr:
291+
raise RuntimeError(f"Failed to get address for {name}")
292+
293+
_fn_ptr_cache[dtype] = addr
294+
_engines[dtype] = engine
295+
return addr
296+
except Exception as e:
297+
raise RuntimeError(f"Failed to materialize function for dtype {dtype}: {e}")

0 commit comments

Comments
 (0)