Radix Plus

Radix Plus Banner

A high performance, in place Radix Sort library for Dart and Flutter.
Fast. Efficient. Low level sorting for number intensive applications.

AboutFeaturesTech StackPrerequisitesInstallationQuick StartUsageBenchmarksArchitectureParametersScriptsTestingDeploymentTroubleshootingContributingLicense


About

Welcome to Radix Plus a blazing fast, in place sorting library for Dart and Flutter. Radix Plus provides a set of highly optimized, stable sorting algorithms that can be significantly faster than List.sort() for specific data types, especially large lists of numbers (int, double, and BigInt). It uses low-level byte manipulation to achieve top-tier performance, making it ideal for data-intensive applications, scientific computing, and real time data processing.


Features

🌟 Core Functionality

  • Multi-Type Support: Sorts List<int>, List<double>, and List<BigInt>.
  • Stable Sort: Preserves the relative order of equal elements.
  • Unified Integer API: A single function, radixSortInt, handles both signed and unsigned integers.
  • Comprehensive Float Support: radixSortDouble correctly handles positive/negative values, infinities, and zero.

🛠️ Advanced Capabilities

  • Parallel Sorting: radixSortParallelUnsigned and radixSortParallelSigned leverage multiple CPU cores using Isolates to sort very large lists even faster.
  • Memory Efficiency: Includes a buffer pooling mechanism (reuseBuffer: true) to minimize GC pressure during frequent sorting tasks.
  • Zero-Copy Operations: Works directly on TypedData lists (Int32List, Float64List, etc.) to avoid unnecessary memory copies.
  • Adaptive Algorithms: Uses hybrid strategies (like switching to insertion sort for small sub-lists under 32 elements) for optimal performance across different data sizes.

Tech Stack

  • Language: Dart 3.0.0+ / Flutter compatible
  • Core Library: dart:typed_data for low-level memory reinterpretation views
  • Concurrency: dart:isolate for multi-threaded parallel sorting
  • Testing: package:test
  • Benchmarking: package:benchmark_harness
  • Dependencies: package:collection for list utilities, package:lints for code health

Prerequisites

  • Dart SDK: >=3.0.0 <4.0.0
  • Flutter SDK (Optional): For integration with mobile, desktop, or web UI apps

Installation

📦 Add to your project

  1. Add this to your package's pubspec.yaml file:

    dependencies:
      radix_plus: ^1.0.6
    
  2. Install it from your terminal:

    dart pub get
    

    or

    flutter pub get
    

🚀 Quick Start

Import the library and call the appropriate sorting function.

import 'package:radix_plus/radix_plus.dart';

void main() {
  // Sort a list of signed integers
  final numbers = [40, -1, 900, -10, 0, 5];
  radixSortInt(numbers); // Automatically handles signed integers
  print(numbers); // [-10, -1, 0, 5, 40, 900]
}

📋 Usage Examples

Sorting Integers

Use radixSortInt for both signed and unsigned integer lists.

// Sort a list of signed integers (ascending)
final signedNumbers = [40, -1, 900, -10, 0, 5];
radixSortInt(signedNumbers, ascending: true);
print(signedNumbers); // [-10, -1, 0, 5, 40, 900]

// Sort a list of unsigned integers (descending)
final unsignedNumbers = [40, 1, 900, 10, 5];
radixSortInt(unsignedNumbers, signed: false, ascending: false);
print(unsignedNumbers); // [900, 40, 10, 5, 1]

Sorting Doubles

Use radixSortDouble for List<double>.

final doubleNumbers = [10.5, -1.2, 900.0, -10.0, 0.0];
radixSortDouble(doubleNumbers);
print(doubleNumbers); // [-10.0, -1.2, 0.0, 10.5, 900.0]

Sorting BigInts

Use radixSortBigInt for List<BigInt>.

final bigIntNumbers = [
  BigInt.parse('100000000000000000000'),
  BigInt.from(-100),
  BigInt.parse('-200000000000000000000'),
  BigInt.zero,
];
radixSortBigInt(bigIntNumbers);
print(bigIntNumbers);

Parallel Sorting

For very large lists, radixSortParallelUnsigned can provide a significant speed boost.

Note: Parallel sorting is not available on the Web platform.

// A large list of numbers
final largeList = List.generate(1000000, (i) => 999999 - i);

// Sort it in parallel across multiple isolates
await radixSortParallelUnsigned(largeList);

print(largeList.first); // 0
print(largeList.last); // 999999

🚀 Benchmarks

Performance is the core feature of Radix Plus. Our algorithms are consistently faster than the standard List.sort() for large numerical datasets, often by a significant margin.

To ensure accuracy, the results below are the average of 10 separate benchmark runs on a standard development machine AMD Ryzen™ 7 5800H, each sorting a list of 1,000,000 random elements.

🔹 Integers (List<int>)

Method Average Time (ms) Speedup vs. List.sort()
List.sort() ~1785 1.0x
radixSortInt ~282 ~6.3x faster

🔹 Typed Lists (32-bit Integers)

Typed lists (Int32List, Uint32List) achieve even better performance due to optimized memory layout.

🔸 Int32List

Method Average Time (ms) Speedup vs. List.sort()
List.sort() ~1490 1.0x
radixSortInt32 ~201 ~7.4x faster

🔸 Uint32List

Method Average Time (ms) Speedup vs. List.sort()
List.sort() ~1477 1.0x
radixSortUint32 ~183 ~8.1x faster

🔹 Floating Point Numbers

Supports both List<double> and optimized Float64List, including correct handling of NaN values.

🔸 List<double>

Method Average Time (ms) Speedup vs. List.sort()
List.sort() ~2634 1.0x
radixSortDouble ~578 ~4.6x faster

🔸 Float64List

Method Average Time (ms) Speedup vs. List.sort()
List.sort() ~1444 1.0x
radixSortFloat64 ~394 ~3.7x faster
radixSortFloat64WithNaN ~312 ~4.6x faster

🔹 BigInt

Efficient sorting for arbitrary-precision integers.

Method Average Time (ms) Speedup vs. List.sort()
List.sort() ~6667 1.0x
radixSortBigInt ~1074 ~6.2x faster
radixSortBigIntWithRange ~6869 ~0.97x faster

ℹ️ radixSortBigIntWithRange is optimized for specific range-based scenarios, not general-purpose sorting.


⚡ Parallel Sorting (Multi-threaded)

Leverages Dart Isolates to unlock massive speedups on multi-core CPUs.

Method Average Time (ms) Speedup vs. List.sort()
List.sort() (Standard int) ~1612 1.0x
radixSortParallelUnsigned ~26.6 ~60.7x faster
radixSortParallelSigned ~28.8 ~56.1x faster

Data Sort Lifecycle & Flows

[Input Double List] ──► Map bits to Unsigned (Positive XOR sign bit, Negative bitwise-negate)
                             │
                             ▼
[Memory View]       ──► Reinterpret Float64List buffer as Uint64List (zero-copy)
                             │
                             ▼
[Core 64-bit Radix] ──► Run 8 passes, 8-bits per pass. Skips pass if minBucket == maxBucket.
                             │
                             ▼
[Revert Mapping]    ──► Transform bitwise values back to native Double list
                             │
                             ▼
[Sorted Output]

Concurrency Model (K-Way Min-Heap Merge)

When parallel sorting is triggered:

  1. The list is sliced into balanced segments matching thread requirements.
  2. Isolates are spawned in parallel to sort each sub-slice sequentially.
  3. The main thread performs a zero-allocation k-Way Merge using a flat min-heap (backed by typed lists heapValues and heapChunkIndices to avoid object allocation GC overhead).

Configuration & Parameters

As a package library, configuration is handled via function parameters:

API Parameters

Parameter Type Default Description
signed bool true Tells radixSortInt whether to treat the list as signed or unsigned.
ascending bool true If false, reverses the sorted output in-place at the end.
reuseBuffer bool true Uses pooled buffers to reduce memory GC allocation cycles.
threads int? null Number of isolates to spawn (auto-calculates if null).
nanPlacement String 'end' Placement of NaN in floats ('start', 'end', 'remove').
maxBitLength int N/A Bit length parameter constraint for range-optimized BigInt sorting.

Contributing

Contributions are welcome! Here’s how to get started:

  1. Fork the repository.
  2. Create a new branch: git checkout -b feature/YourFeature
  3. Commit your changes: git commit -m "Add amazing feature"
  4. Push to your branch: git push origin feature/YourFeature
  5. Open a pull request.

💡 Please read our Contributing Guidelines and open an issue first for major feature ideas or changes.


⚖️ License

This project is dual-licensed:

  1. Open Source License: GPL-3.0

    • Free to use, modify, and distribute under GPL terms.
    • Any distributed modified version must also be GPL-3.0.
  2. Commercial License:

    • Required for using the library in proprietary / closed-source products.
    • Only available from the copyright holder (Mostafa Mahmoud).
    • Contact: mostafasensei106@gmail.com

Made with ❤️ by MostafaSensei106

Libraries

radix_plus
radix_Plus