Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/simphotonics/stride

Extension method for iterating Dart Lists and Iterables using a custom start index and step size (stride).
https://github.com/simphotonics/stride

array column-major dart iterable iterator multi-dimensional-array numerical-computation row-major stride

Last synced: about 1 month ago
JSON representation

Extension method for iterating Dart Lists and Iterables using a custom start index and step size (stride).

Awesome Lists containing this project

README

        

# Dart Stride Iterators
[![Dart](https://github.com/simphotonics/stride/actions/workflows/dart.yml/badge.svg)](https://github.com/simphotonics/stride/actions/workflows/dart.yml)

## Introduction

The package [stride][stride] provides **stride iterators** and extension
methods that make it possible to iterate data structures of type `List` and
`Iterable` using a custom start point and step size.

In the context of numerical computation it is often useful to store data
in multi-dimensional arrays. In Dart, a multi-dimensional array may be
represented as a list of lists.
To speed up arithmetical operations and minimize memory usage it may be advantageous to
store a multi-dimensional array as a flat list. For more details see
[numerical computation](https://dart.dev/articles/archive/numeric-computation)
with Dart.

The example below shows how the elements of a 2-dimensional array can
be stored as a 1-dimensional array (a Dart list).

![2D-Array](https://github.com/simphotonics/stride/raw/main/images/array.svg?sanitize=true)

In order to access the elements of the column with index 1
(highlighted using an orange rectangle), we
need to start the iteration at index 1. To move to the next element
we have to use a step size, or stride, that is equal to the number of columns in the
2D-array.

## Usage

To use this package, include [stride] as a dependency in your `pubspec.yaml` file.
The program below demonstrates how to use the
extension method [`stride`][stride-method] to iterate lists using a custom step size
and start index. Note that the iteration step size must not be zero. A negative step
size and suitable start index may be used to iterate in reverse direction.

Tip: When iterating *fixed* size lists, immutable lists views, or typed lists
it makes perfect sense to omit concurrent modification
checks by using the method [`fastStride`][fastStride-method].
The slight performance improvement
is evident when iterating very long lists.

```Dart
import 'dart:typed_data';

import 'package:stride/stride.dart';

main(List args) {
// 3x3 matrix.
final array2D = >[
['e00', 'e01', 'e02'],
['e10', 'e11', 'e12'],
['e20', 'e21', 'e22'],
];

/// Elements of 3x3 matrix in row major layout.
final list = ['e00', 'e01', 'e02', 'e10', 'e11', 'e12', 'e20', 'e21', 'e22'];

final stepSize = 3;
final startIndex = 1;
final strideIt0 = list.stride(stepSize, startIndex);

print('2D array:');
print(array2D[0]);
print(array2D[1]);
print(array2D[2]);
print('');

print('Column 1:');
print(strideIt0);
print('');

// Typed list (with fixed length).
final numericalList =
Float64List.fromList([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);

// Omitting concurrent modification checks:
final strideIt1 = numericalList.fastStride(
stepSize,
startIndex
);

print('Numerical list:');
print(numericalList);
print('');

print('start index: 1 and step-size: 3:');
print(strideIt1);
print('');

print('start index: 9 and step-size: -3:');
final reverseStrideIt1 = numericalList.stride(-3, 9);
print(reverseStrideIt1);
}

```
Running the program above produces the following console output:

```Console
$ dart example/bin/example.dart
2D array:
[e00, e01, e02]
[e10, e11, e12]
[e20, e21, e22]

Column 1:
(e01, e11, e21)

Numerical list:
[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]

start index: 1 and step-size: 3:
(1.0, 4.0, 7.0, 10.0)

start index: 9 and step-size: -3:
(9.0, 6.0, 3.0, 0.0)
```

## Row Major and Column Major Storage Layout

Consider an N-dimensional array, array_N, with length di along dimension i,
where i ∈ \[0, n-1\]. Let array_1 be a Dart list able to store all d0 · d1 · … · dn-1 elements of array_N.

Let array_N\[i0\]\[i1\]…\[in‑1\] be stored at location array_1\[s0·i0 + … + sn-1·in-1\], where the iteration step sizes, si, depend on the storage order.

For a *row major* storage order the step sizes are given by:

s0 = d1 · d2 ·   …   · dn-1

s1 = d2 · d3 ·   …   · dn-1

    ⋮

sn-2 = dn-1

sn-1 = 1.

For a *column major* storage order the step sizes are given by:

s0 = 1

s1 = d0

s2 = d0 · d1

    ⋮

sn-2 = d0 · d1 ·   …   · dn-3

sn-1 = d0 · d1 ·   …   · dn-2

For more information see [Row- and column-major order](https://en.wikipedia.org/wiki/Row-_and_column-major_order).

## Examples

A copy of the program shown in the section above can be found in the folder [example].

## Features and bugs

Please file feature requests and bugs at the [issue tracker].

[issue tracker]: https://github.com/simphotonics/stride/issues

[example]: https://github.com/simphotonics/stride/tree/main/example

[stride]: https://pub.dev/packages/stride

[Stride]: https://pub.dev/documentation/stride/latest/stride/Stride.html

[stride-method]: https://pub.dev/documentation/stride/latest/stride/Stride/stride.html

[fastStride-method]: https://pub.dev/documentation/stride/latest/stride/FastStride/fastStride.html