radix_pulse 1.0.1 copy "radix_pulse: ^1.0.1" to clipboard
radix_pulse: ^1.0.1 copied to clipboard

A high-performance, in-place Radix Sort implementation for Dart and Flutter, providing significant speed improvements over standard sorting for number lists.

example/lib/main.dart

import 'dart:math';
import 'dart:isolate';
import 'package:flutter/material.dart';
import 'package:radix_pulse/radix_pulse.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Radix Pulse Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.blue,
          brightness: Brightness.dark,
        ),
        useMaterial3: true,
      ),
      home: const BenchmarkPage(),
    );
  }
}

class BenchmarkResult {
  final String name;
  final int listSortTime;
  final int radixSortTime;
  final int listSize;

  BenchmarkResult(
    this.name,
    this.listSortTime,
    this.radixSortTime,
    this.listSize,
  );

  double get improvement =>
      ((listSortTime - radixSortTime) / listSortTime) * 100;
}

class BenchmarkPage extends StatefulWidget {
  const BenchmarkPage({super.key});

  @override
  State<BenchmarkPage> createState() => _BenchmarkPageState();
}

class _BenchmarkPageState extends State<BenchmarkPage>
    with TickerProviderStateMixin {
  final GlobalKey<AnimatedListState> _listKey = GlobalKey<AnimatedListState>();
  final List<BenchmarkResult> _results = [];
  bool _isRunning = false;
  String _message = 'Press the button to run all benchmarks.';

  late final AnimationController _bgController = AnimationController(
    vsync: this,
    duration: const Duration(seconds: 10),
  )..repeat(reverse: true);

  late final Animation<Alignment> _topAlignmentAnimation = AlignmentTween(
    begin: Alignment.topLeft,
    end: Alignment.topRight,
  ).animate(_bgController);
  late final Animation<Alignment> _bottomAlignmentAnimation = AlignmentTween(
    begin: Alignment.bottomLeft,
    end: Alignment.bottomRight,
  ).animate(_bgController);

  Future<void> _runAllBenchmarks() async {
    if (_isRunning) return;

    // Clear old results
    for (var i = _results.length - 1; i >= 0; i--) {
      _listKey.currentState?.removeItem(
        i,
        (context, animation) => const SizedBox.shrink(),
      );
    }
    _results.clear();

    setState(() {
      _isRunning = true;
      _message = 'Warming up the engines...';
    });

    final resultData = await Isolate.run(_performSorts);

    setState(() {
      _isRunning = false;
      _message = 'Benchmark Results (List size: ${resultData.first.listSize})';
    });

    for (var i = 0; i < resultData.length; i++) {
      await Future.delayed(const Duration(milliseconds: 150));
      _results.add(resultData[i]);
      _listKey.currentState?.insertItem(i);
    }
  }

  static Future<List<BenchmarkResult>> _performSorts() async {
    const size = 100000;
    final random = Random();
    final results = <BenchmarkResult>[];

    // --- 1. Signed Integers ---
    final signedInts = List.generate(
      size,
      (_) => random.nextInt(0x7FFFFFFF) - 0x40000000,
    );
    final listCopy1 = List.of(signedInts);
    final radixCopy1 = List.of(signedInts);
    final sw1 = Stopwatch()..start();
    listCopy1.sort();
    sw1.stop();
    final sw2 = Stopwatch()..start();
    radixSortInt(radixCopy1, signed: true);
    sw2.stop();
    results.add(
      BenchmarkResult(
        'Signed Integers',
        sw1.elapsedMicroseconds,
        sw2.elapsedMicroseconds,
        size,
      ),
    );

    // --- 2. Unsigned Integers ---
    final unsignedInts = List.generate(size, (_) => random.nextInt(0x7FFFFFFF));
    final listCopy2 = List.of(unsignedInts);
    final radixCopy2 = List.of(unsignedInts);
    final sw3 = Stopwatch()..start();
    listCopy2.sort();
    sw3.stop();
    final sw4 = Stopwatch()..start();
    radixSortInt(radixCopy2, signed: false);
    sw4.stop();
    results.add(
      BenchmarkResult(
        'Unsigned Integers',
        sw3.elapsedMicroseconds,
        sw4.elapsedMicroseconds,
        size,
      ),
    );

    // --- 3. Doubles ---
    final doubles = List.generate(
      size,
      (_) => (random.nextDouble() - 0.5) * 1e6,
    );
    final listCopy3 = List.of(doubles);
    final radixCopy3 = List.of(doubles);
    final sw5 = Stopwatch()..start();
    listCopy3.sort();
    sw5.stop();
    final sw6 = Stopwatch()..start();
    radixSortDouble(radixCopy3);
    sw6.stop();
    results.add(
      BenchmarkResult(
        'Doubles',
        sw5.elapsedMicroseconds,
        sw6.elapsedMicroseconds,
        size,
      ),
    );

    // --- 4. BigInts ---
    final bigInts = List.generate(
      size,
      (_) =>
          BigInt.from(random.nextInt(1 << 30)) *
          BigInt.from(random.nextInt(1 << 30)) *
          (random.nextBool() ? BigInt.one : -BigInt.one),
    );
    final listCopy4 = List.of(bigInts);
    final radixCopy4 = List.of(bigInts);
    final sw7 = Stopwatch()..start();
    listCopy4.sort();
    sw7.stop();
    final sw8 = Stopwatch()..start();
    radixSortBigInt(radixCopy4);
    sw8.stop();
    results.add(
      BenchmarkResult(
        'BigInts',
        sw7.elapsedMicroseconds,
        sw8.elapsedMicroseconds,
        size,
      ),
    );

    // --- 5. Parallel Unsigned Integers ---
    final parallelInts = List.generate(size, (_) => random.nextInt(0x7FFFFFFF));
    final listCopy5 = List.of(parallelInts);
    final radixCopy5 = List.of(parallelInts);
    final sw9 = Stopwatch()..start();
    listCopy5.sort();
    sw9.stop();
    final sw10 = Stopwatch()..start();
    await radixSortParallelUnsigned(radixCopy5, threads: 4);
    sw10.stop();
    results.add(
      BenchmarkResult(
        'Parallel Unsigned (4 Threads)',
        sw9.elapsedMicroseconds,
        sw10.elapsedMicroseconds,
        size,
      ),
    );

    return results;
  }

  @override
  void dispose() {
    _bgController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
      animation: _bgController,
      builder: (context, child) {
        return Container(
          decoration: BoxDecoration(
            gradient: LinearGradient(
              colors: const [Color(0xFF1E1E2E), Color(0xFF45456E)],
              begin: _topAlignmentAnimation.value,
              end: _bottomAlignmentAnimation.value,
            ),
          ),
          child: child,
        );
      },
      child: Scaffold(
        backgroundColor: Colors.transparent,
        appBar: AppBar(
          title: const Text('Radix Pulse Benchmark'),
          backgroundColor: Colors.transparent,
          elevation: 0,
        ),
        body: Center(
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                const Text(
                  'Time Performance: Radix Pulse vs List.sort()',
                  style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
                  textAlign: TextAlign.center,
                ),
                const SizedBox(height: 24),
                AnimatedSwitcher(
                  duration: const Duration(milliseconds: 300),
                  child: _isRunning
                      ? Column(
                          children: [
                            const CircularProgressIndicator(),
                            const SizedBox(height: 16),
                            Text(
                              _message,
                              style: const TextStyle(fontSize: 16),
                            ),
                          ],
                        )
                      : ElevatedButton.icon(
                          style: ElevatedButton.styleFrom(
                            padding: const EdgeInsets.symmetric(
                              horizontal: 24,
                              vertical: 12,
                            ),
                            textStyle: const TextStyle(fontSize: 18),
                          ),
                          onPressed: _runAllBenchmarks,
                          icon: const Icon(Icons.rocket_launch),
                          label: const Text('Run All Benchmarks'),
                        ),
                ),
                const SizedBox(height: 24),
                if (!_isRunning && _results.isEmpty)
                  Text(_message, style: const TextStyle(fontSize: 16)),
                Expanded(
                  child: AnimatedList(
                    key: _listKey,
                    initialItemCount: _results.length,
                    itemBuilder: (context, index, animation) {
                      return _buildResultCard(_results[index], animation);
                    },
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildResultCard(BenchmarkResult result, Animation<double> animation) {
    final isPositive = result.improvement > 0;
    final improvementColor = isPositive ? Colors.greenAccent : Colors.redAccent;
    final sign = isPositive ? '+' : '';

    return FadeTransition(
      opacity: animation,
      child: SlideTransition(
        position: Tween<Offset>(
          begin: const Offset(0, 0.5),
          end: Offset.zero,
        ).animate(CurvedAnimation(parent: animation, curve: Curves.easeOut)),
        child: Card(
          color: Colors.white.withOpacity(0.1),
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(12),
          ),
          margin: const EdgeInsets.symmetric(vertical: 8),
          child: Padding(
            padding: const EdgeInsets.all(16.0),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  result.name,
                  style: const TextStyle(
                    fontSize: 18,
                    fontWeight: FontWeight.bold,
                    color: Colors.white,
                  ),
                ),
                const Divider(color: Colors.white24, height: 20),
                _buildStatRow(
                  Icons.timer_outlined,
                  'List.sort()',
                  '${result.listSortTime} µs',
                ),
                _buildStatRow(
                  Icons.flash_on,
                  'Radix Pulse',
                  '${result.radixSortTime} µs',
                ),
                const SizedBox(height: 8),
                Container(
                  padding: const EdgeInsets.symmetric(
                    horizontal: 12,
                    vertical: 8,
                  ),
                  decoration: BoxDecoration(
                    color: improvementColor.withOpacity(0.2),
                    borderRadius: BorderRadius.circular(8),
                    border: Border.all(color: improvementColor, width: 1),
                  ),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Icon(
                        isPositive ? Icons.trending_up : Icons.trending_down,
                        color: improvementColor,
                        size: 20,
                      ),
                      const SizedBox(width: 8),
                      Text(
                        'Improvement: $sign${result.improvement.toStringAsFixed(2)}%',
                        style: TextStyle(
                          fontSize: 16,
                          fontWeight: FontWeight.bold,
                          color: improvementColor,
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildStatRow(IconData icon, String label, String value) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 4.0),
      child: Row(
        children: [
          Icon(icon, size: 18, color: Colors.white70),
          const SizedBox(width: 12),
          Text(
            '$label:',
            style: const TextStyle(fontSize: 15, color: Colors.white70),
          ),
          const Spacer(),
          Text(
            value,
            style: const TextStyle(
              fontSize: 15,
              fontWeight: FontWeight.bold,
              color: Colors.white,
            ),
          ),
        ],
      ),
    );
  }
}
0
likes
145
points
156
downloads

Publisher

unverified uploader

Weekly Downloads

A high-performance, in-place Radix Sort implementation for Dart and Flutter, providing significant speed improvements over standard sorting for number lists.

Repository (GitHub)
View/report issues
Contributing

Documentation

API reference

License

MIT (license)

More

Packages that depend on radix_pulse