Skip to content

[ADD] C++ STL Algorithms & Binary Search Suites Integration (v1.1.4)#16

Merged
AnshMNSoni merged 2 commits into
mainfrom
pr11
Jun 12, 2026
Merged

[ADD] C++ STL Algorithms & Binary Search Suites Integration (v1.1.4)#16
AnshMNSoni merged 2 commits into
mainfrom
pr11

Conversation

@AnshMNSoni

Copy link
Copy Markdown
Owner

This PR implements and integrates the C++ STL Algorithms Suite and the Binary Search Suite into PythonSTL. It exposes high-performance Rust-compiled backends using PyO3/Maturin and registers them as part of the public facade API, while introducing robust, optimized pure-Python fallback implementations.

Key Features Added

  1. STL Algorithms Suite ( replicas)
  • next_permutation / prev_permutation: Lexicographical permutation generator operating in-place on Python lists.
  • nth_element: Quickselect implementation to find elements at a sorted index in $O(N)$ expected time.
  • partition: In-place array partitioning based on custom Python predicates.
  1. Binary Search Suite
  • lower_bound: First element index not comparing less than target ($\ge$).
  • upper_bound: First element index comparing greater than target ($>$).
  • binary_search: $O(\log N)$ presence check in a sorted range.
  • equal_range: Returns (lower_bound, upper_bound) index bounds.

Performance Benchmarks & Systems Insights

  1. Algorithms Benchmark Results
  • next_permutation: Achieved a 1.7x speedup over pure Python.
  • nth_element: Bypassed a severe Lomuto partition worst-case vulnerability ($O(N^2)$ taking 70.85s on reversed arrays) by introducing middle-pivot selection, reducing the runtime to 0.0028s (a 25,000x+ speedup).
  • partition: Shows 1.3x speedup; performance is dominated by FFI callback transitions to evaluate the Python predicate function.
  1. Binary Search Benchmark Results (5,000 queries on 1,000,000 elements)
  • Standard (< comparison): 7.5x speedup (0.0028s vs 0.0214s).
  • Custom Comparator (lambda): 3.4x speedup (0.0074s vs 0.0251s).
  1. Key Systems Design Decisions:
  • GIL-Bound Indexing Optimization: Rust implementations for binary search access elements directly using arr.get_item(mid) rather than copy-extracting the entire list. This preserves the $O(\log N)$ time and $O(1)$ space constraints.
  • FFI Callback vs. Compiled Loop Overhead: Custom lambdas require crossing the Python-Rust FFI boundary to evaluate comparison predicates. While this slows Rust down (from 0.0028s to 0.0074s), Rust's loop compiling easily overcomes Python's bytecode interpreter overhead, resulting in a 3.4x net speedup.

Verifications & Quality Gates

  • Unit Tests: Created comprehensive pytest suites in tests/test_algorithms.py and tests/test_binary_search.py covering duplicate elements, out-of-bounds inputs, empty lists, and custom comparators. All 81 package tests are passing.
  • Packaging: Configured and validated package distributions on PyPI (Twine validation: PASSED). Version 1.1.4 is live on PyPI.

@AnshMNSoni AnshMNSoni self-assigned this Jun 12, 2026
@AnshMNSoni AnshMNSoni added the enhancement New feature or request label Jun 12, 2026
@deepsource-io

deepsource-io Bot commented Jun 12, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in 2bd671c...263431f on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
Rust Jun 12, 2026 9:06a.m. Review ↗
Python Jun 12, 2026 9:06a.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

# Add project root to path to run directly from development folder
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from pythonstl import next_permutation, nth_element, partition, stl_set

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused stl_set imported from pythonstl


An object has been imported but is not used anywhere in the file.
It should either be used or the import should be removed.


def run_py_permutation():
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
while next_permutation(arr, use_rust=False):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Body doesn't contain any code


In most cases, an empty body of for, while or if implies some piece of code is missing.
Such empty block must be either filled or removed.


def run_rust_permutation():
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
while next_permutation(arr, use_rust=True):

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Body doesn't contain any code


In most cases, an empty body of for, while or if implies some piece of code is missing.
Such empty block must be either filled or removed.

Comment on lines +48 to +52
subprocess.run(
["g++", "-O3", str(cpp_source), "-o", str(cpp_exe)],
check=True,
capture_output=True
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Starting a process with a partial executable path


Python possesses many mechanisms to invoke an external executable. If the desired executable path is not fully qualified relative to the filesystem root then this may present a potential security risk.

Comment on lines +46 to +50
subprocess.run(
["g++", "-O3", str(cpp_source), "-o", str(cpp_exe)],
check=True,
capture_output=True
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Starting a process with a partial executable path


Python possesses many mechanisms to invoke an external executable. If the desired executable path is not fully qualified relative to the filesystem root then this may present a potential security risk.

if self._is_rust:
new_vector._impl.set_data(self._impl.get_data())
else:
new_vector._impl._data = self._impl._data.copy()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Access to a protected member _data of a client class


Accessing a protected member (a member prefixed with _) of a class from outside that class is not recommended, since the creator of that class did not intend this member to be exposed. If accesing this attribute outside of the class is absolutely needed, refactor it such that it becomes part of the public interface of the class.

if self._is_rust:
new_vector._impl.set_data(self._impl.get_data())
else:
new_vector._impl._data = self._impl._data.copy()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Access to a protected member _data of a client class


Accessing a protected member (a member prefixed with _) of a class from outside that class is not recommended, since the creator of that class did not intend this member to be exposed. If accesing this attribute outside of the class is absolutely needed, refactor it such that it becomes part of the public interface of the class.

new_vector._impl.set_data(self._impl.get_data())
else:
new_vector._impl._data = self._impl._data.copy()
new_vector._impl._capacity = self._impl._capacity

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Access to a protected member _capacity of a client class


Accessing a protected member (a member prefixed with _) of a class from outside that class is not recommended, since the creator of that class did not intend this member to be exposed. If accesing this attribute outside of the class is absolutely needed, refactor it such that it becomes part of the public interface of the class.

new_vector._impl.set_data(self._impl.get_data())
else:
new_vector._impl._data = self._impl._data.copy()
new_vector._impl._capacity = self._impl._capacity

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Access to a protected member _capacity of a client class


Accessing a protected member (a member prefixed with _) of a class from outside that class is not recommended, since the creator of that class did not intend this member to be exposed. If accesing this attribute outside of the class is absolutely needed, refactor it such that it becomes part of the public interface of the class.

@@ -0,0 +1,104 @@
import pytest

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import pytest


An object has been imported but is not used anywhere in the file.
It should either be used or the import should be removed.

@AnshMNSoni AnshMNSoni merged commit 042898b into main Jun 12, 2026
3 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant