## ml_linalg 12.7.1

SIMD-based Linear algebra with Dart

## Linear algebra #

In a few words, linear algebra is a branch of mathematics that is working with vectors and matrices.

Let's give a simple definition of Vector and Matrix. Vector is an ordered set of numbers, representing a point in the space where the vector is directed from the origin. Matrix is a collection of vectors, used to map vectors from one space to another.

Vectors and matrices are extremely powerful tools, which can be used in real-life applications, such as machine learning algorithms. There are many implementations of these great mathematical entities in a plenty of programming languages, and as Dart offers developers good instrumentarium, e.g. highly optimized virtual machine and rich out-of-the-box library, Dart-based implementation of vectors and matrices has to be quite performant.

Among myriad of standard Dart tools there are SIMD data types. Namely support of SIMD computational architecture served as a source of inspiration for creating this library.

## What is SIMD? #

SIMD stands for `Single instruction, multiple data` - it is a computer architecture, that allows to perform uniform operations in parallel on huge amount of data. For instance, one has two arrays:

• $a = [10, 20, 30, 40]$
• $b = [50, 60, 70, 80]$

and one needs to add these arrays element-wise. Using the regular architecture this operation could be done in this manner:

We need to do 4 operations one by one in a row. Using SIMD architecture we may perform one mathematical operation on several operands in parallel, thus element-wise sum of two arrays will be done for just one step:

## Vectors #

### A couple of words about the underlying architecture #

The library contains two high performant vector classes, based on Float32x4 and Float64x2 data types - Float32x4Vector and Float64x2Vector (the second one is generated from the source code of the first vector)

Most of element-wise operations in the first one are performed in four "threads" and in the second one - in two "threads".

Implementation of both classes is hidden from the library's users. You can create a `Float32x4Vector` or a `Float64x2Vector` instance via Vector factory (see examples below).

The vectors are immutable - once created, the vector cannot be changed. All vector operations lead to creation of a new vector instance (of course, if an operation is supposed to return `Vector`).

Both classes implement `Iterable<double>` interface - so it's possible to use them as regular iterable collections.

It's possible to use vector instances as keys for `HashMap` and similar data structures and to look up a value by the vector-key, since the hash code is the same for equal vectors:

``````import 'package:ml_linalg/vector.dart';

final map = HashMap<Vector, bool>();

map[Vector.fromList([1, 2, 3, 4, 5])] = true;

print(map[Vector.fromList([1, 2, 3, 4, 5])]); // true
print(Vector.fromList([1, 2, 3, 4, 5]).hashCode == Vector.fromList([1, 2, 3, 4, 5]).hashCode); // true
``````

### Vector benchmarks #

To see the performance gain provided by the library's vector classes, one may visit `benchmark` directory: one may find there a baseline benchmark - element-wise summation of two regular List instances and a benchmark of a similar operation, but performed with two `Float32x4Vector` instances on the same amount of elements and compare the timings:

• Baseline benchmark (executed on Macbook Air mid 2017), 2 regular lists each with 10,000,000 elements:

• Actual benchmark (executed on Macbook Air mid 2017), 2 vectors each with 10,000,000 elements:

It took 15 seconds to create a new regular list by summing the elements of two lists, and 0.7 second to sum two vectors - the difference is significant.

### Vector operations examples #

#### Vectors sum #

``````  import 'package:ml_linalg/linalg.dart';

final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final vector2 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1 + vector2;
print(result.toList()); // [3.0, 5.0, 7.0, 9.0, 11.0]
``````

#### Vectors subtraction #

``````  import 'package:ml_linalg/linalg.dart';

final vector1 = Vector.fromList([4.0, 5.0, 6.0, 7.0, 8.0]);
final vector2 = Vector.fromList([2.0, 3.0, 2.0, 3.0, 2.0]);
final result = vector1 - vector2;
print(result.toList()); // [2.0, 2.0, 4.0, 4.0, 6.0]
``````

#### Element wise vector by vector multiplication #

``````  import 'package:ml_linalg/linalg.dart';

final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final vector2 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1 * vector2;
print(result.toList()); // [2.0, 6.0, 12.0, 20.0, 30.0]
``````

#### Element wise vector by vector division #

``````  import 'package:ml_linalg/linalg.dart';

final vector1 = Vector.fromList([6.0, 12.0, 24.0, 48.0, 96.0]);
final vector2 = Vector.fromList([3.0, 4.0, 6.0, 8.0, 12.0]);
final result = vector1 / vector2;
print(result.toList()); // [2.0, 3.0, 4.0, 6.0, 8.0]
``````

#### Euclidean norm #

``````  import 'package:ml_linalg/linalg.dart';

final vector1 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1.norm();
print(result); // sqrt(2^2 + 3^2 + 4^2 + 5^2 + 6^2) = sqrt(90) ~~ 9.48
``````

#### Manhattan norm #

``````  import 'package:ml_linalg/linalg.dart';

final vector1 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1.norm(Norm.manhattan);
print(result); // 2 + 3 + 4 + 5 + 6 = 20.0
``````

#### Mean value #

``````  import 'package:ml_linalg/linalg.dart';

final vector1 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1.mean();
print(result); // (2 + 3 + 4 + 5 + 6) / 5 = 4.0
``````

#### Sum of all vector elements #

``````  import 'package:ml_linalg/linalg.dart';

final vector1 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1.sum();
print(result); // 2 + 3 + 4 + 5 + 6 = 20.0 (equivalent to Manhattan norm)
``````

#### Dot product of two vectors #

``````  import 'package:ml_linalg/linalg.dart';

final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final vector2 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1.dot(vector2);
print(result); // 1.0 * 2.0 + 2.0 * 3.0 + 3.0 * 4.0 + 4.0 * 5.0 + 5.0 * 6.0 = 70.0
``````

#### Sum of a vector and a scalar #

``````  import 'package:ml_linalg/linalg.dart';

final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final scalar = 5.0;
final result = vector1 + scalar;
print(result.toList()); // [6.0, 7.0, 8.0, 9.0, 10.0]
``````

#### Subtraction of a scalar from a vector #

``````  import 'package:ml_linalg/linalg.dart';

final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final scalar = 5.0;
final result = vector1 - scalar;
print(result.toList()); // [-4.0, -3.0, -2.0, -1.0, 0.0]
``````

#### Multiplication (scaling) of a vector by a scalar #

``````  import 'package:ml_linalg/linalg.dart';

final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final scalar = 5.0;
final result = vector1 * scalar;
print(result.toList()); // [5.0, 10.0, 15.0, 20.0, 25.0]
``````

#### Division (scaling) of a vector by a scalar value #

``````  import 'package:ml_linalg/linalg.dart';

final vector1 = Vector.fromList([25.0, 50.0, 75.0, 100.0, 125.0]);
final scalar = 5.0;
final result = vector1.scalarDiv(scalar);
print(result.toList()); // [5.0, 10.0, 15.0, 20.0, 25.0]
``````

#### Euclidean distance between two vectors #

``````  import 'package:ml_linalg/linalg.dart';

final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final vector2 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1.distanceTo(vector2, distance: Distance.euclidean);
print(result); // ~~2.23
``````

#### Manhattan distance between two vectors #

``````  import 'package:ml_linalg/linalg.dart';

final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final vector2 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1.distanceTo(vector2, distance: Distance.manhattan);
print(result); // 5.0
``````

#### Cosine distance between two vectors #

``````  import 'package:ml_linalg/linalg.dart';

final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final vector2 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1.distanceTo(vector2, distance: Distance.cosine);
print(result); // 0.00506
``````

#### Vector normalization using Euclidean norm #

``````  import 'package:ml_linalg/linalg.dart';

final vector = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final result = vector.normalize(Norm.euclidean);
print(result); // [0.134, 0.269, 0.404, 0.539, 0.674]
``````

#### Vector normalization using Manhattan norm #

``````  import 'package:ml_linalg/linalg.dart';

final vector = Vector.fromList([1.0, -2.0, 3.0, -4.0, 5.0]);
final result = vector.normalize(Norm.manhattan);
print(result); // [0.066, -0.133, 0.200, -0.266, 0.333]
``````

#### Vector rescaling (min-max normalization) #

``````  import 'package:ml_linalg/linalg.dart';

final vector = Vector.fromList([1.0, -2.0, 3.0, -4.0, 5.0, 0.0]);
final result = vector.rescale();
print(result); // [0.555, 0.222, 0.777, 0.0, 1.0, 0.444]
``````

## Matrices #

Along with SIMD vectors, the library presents SIMD-based Matrices. One can use the matrices via Matrix factory. The matrices are immutable as well as vectors and also they implement `Iterable`, to be precise - `Iterable<Iterable<double>>` interface, thus it's possible to use them as a regular iterable collection.

### Matrix operations examples #

#### Creation of diagonal matrix #

``````import 'package:ml_linalg/matrix.dart';

final matrix = Matrix.diagonal([1, 2, 3, 4, 5]);

print(matrix);
``````

The output:

``````Matrix 5 x 5:
(1.0, 0.0, 0.0, 0.0, 0.0)
(0.0, 2.0, 0.0, 0.0, 0.0)
(0.0, 0.0, 3.0, 0.0, 0.0)
(0.0, 0.0, 0.0, 4.0, 0.0)
(0.0, 0.0, 0.0, 0.0, 5.0)
``````

#### Creation of scalar matrix #

``````import 'package:ml_linalg/matrix.dart';

final matrix = Matrix.scalar(3, 5);

print(matrix);
``````

The output:

``````Matrix 5 x 5:
(3.0, 0.0, 0.0, 0.0, 0.0)
(0.0, 3.0, 0.0, 0.0, 0.0)
(0.0, 0.0, 3.0, 0.0, 0.0)
(0.0, 0.0, 0.0, 3.0, 0.0)
(0.0, 0.0, 0.0, 0.0, 3.0)
``````

#### Creation of identity matrix #

``````import 'package:ml_linalg/matrix.dart';

final matrix = Matrix.identity(5);

print(matrix);
``````

The output:

``````Matrix 5 x 5:
(1.0, 0.0, 0.0, 0.0, 0.0)
(0.0, 1.0, 0.0, 0.0, 0.0)
(0.0, 0.0, 1.0, 0.0, 0.0)
(0.0, 0.0, 0.0, 1.0, 0.0)
(0.0, 0.0, 0.0, 0.0, 1.0)
``````

#### Creation of column matrix #

``````final matrix = Matrix.column([1, 2, 3, 4, 5]);

print(matrix);
``````

The output:

``````Matrix 5 x 1:
(1.0)
(2.0)
(3.0)
(4.0)
(5.0)
``````

#### Creation of row matrix #

``````final matrix = Matrix.row([1, 2, 3, 4, 5]);

print(matrix);
``````

The output:

``````Matrix 1 x 5:
(1.0, 2.0, 3.0, 4.0, 5.0)
``````

#### Sum of a matrix and another matrix #

``````import 'package:ml_linalg/linalg.dart';

final matrix1 = Matrix.fromList([
[1.0, 2.0, 3.0, 4.0],
[5.0, 6.0, 7.0, 8.0],
[9.0, .0, -2.0, -3.0],
]);
final matrix2 = Matrix.fromList([
[10.0, 20.0, 30.0, 40.0],
[-5.0, 16.0, 2.0, 18.0],
[2.0, -1.0, -2.0, -7.0],
]);
print(matrix1 + matrix2);
// [
//  [11.0, 22.0, 33.0, 44.0],
//  [0.0, 22.0, 9.0, 26.0],
//  [11.0, -1.0, -4.0, -10.0],
// ];
``````

#### Sum of a matrix and a scalar #

``````import 'package:ml_linalg/linalg.dart';

final matrix = Matrix.fromList([
[1.0, 2.0, 3.0, 4.0],
[5.0, 6.0, 7.0, 8.0],
[9.0, .0, -2.0, -3.0],
]);
print(matrix + 7);
//  [
//    [8.0, 9.0, 10.0, 11.0],
//    [12.0, 13.0, 14.0, 15.0],
//    [16.0, 7.0, 5.0, 4.0],
//  ];
``````

#### Multiplication of a matrix and a vector #

``````  import 'package:ml_linalg/linalg.dart';

final matrix = Matrix.fromList([
[1.0, 2.0, 3.0, 4.0],
[5.0, 6.0, 7.0, 8.0],
[9.0, .0, -2.0, -3.0],
]);
final vector = Vector.fromList([2.0, 3.0, 4.0, 5.0]);
final result = matrix * vector;
print(result);
// a vector-column [
//  [40],
//  [96],
//  [-5],
//]
``````

#### Multiplication of a matrix and another matrix #

``````  import 'package:ml_linalg/linalg.dart';

final matrix1 = Matrix.fromList([
[1.0, 2.0, 3.0, 4.0],
[5.0, 6.0, 7.0, 8.0],
[9.0, .0, -2.0, -3.0],
]);
final matrix2 = Matrix.fromList([
[1.0, 2.0],
[5.0, 6.0],
[9.0, .0],
[-9.0, 1.0],
]);
final result = matrix1 * matrix2;
print(result);
//[
// [2.0, 18.0],
// [26.0, 54.0],
// [18.0, 15.0],
//]
``````

#### Multiplication of a matrix and a scalar #

``````import 'package:ml_linalg/linalg.dart';

final matrix = Matrix.fromList([
[1.0, 2.0, 3.0, 4.0],
[5.0, 6.0, 7.0, 8.0],
[9.0, .0, -2.0, -3.0],
]);
print(matrix * 3);
// [
//   [3.0, 6.0, 9.0, 12.0],
//   [15.0, 18.0, 21.0, 24.0],
//   [27.0, .0, -6.0, -9.0],
// ];
``````

#### Element wise matrices subtraction #

``````import 'package:ml_linalg/linalg.dart';

final matrix1 = Matrix.fromList([
[1.0, 2.0, 3.0, 4.0],
[5.0, 6.0, 7.0, 8.0],
[9.0, .0, -2.0, -3.0],
]);
final matrix2 = Matrix.fromList([
[10.0, 20.0, 30.0, 40.0],
[-5.0, 16.0, 2.0, 18.0],
[2.0, -1.0, -2.0, -7.0],
]);
print(matrix1 - matrix2);
// [
//   [-9.0, -18.0, -27.0, -36.0],
//   [10.0, -10.0, 5.0, -10.0],
//   [7.0, 1.0, .0, 4.0],
// ];
``````

#### Matrix transposition #

``````  import 'package:ml_linalg/linalg.dart';

final matrix = Matrix.fromList([
[1.0, 2.0, 3.0, 4.0],
[5.0, 6.0, 7.0, 8.0],
[9.0, .0, -2.0, -3.0],
]);
final result = matrix.transpose();
print(result);
//[
// [1.0, 5.0, 9.0],
// [2.0, 6.0, .0],
// [3.0, 7.0, -2.0],
// [4.0, 8.0, -3.0],
//]
``````

#### Matrix row wise reduce #

``````  import 'package:ml_linalg/linalg.dart';

final matrix = Matrix.fromList([
[1.0, 2.0, 3.0, 4.0],
[5.0, 6.0, 7.0, 8.0],
]);
final reduced = matrix.reduceRows((combine, row) => combine + row);
print(reduced); // [6.0, 8.0, 10.0, 12.0]
``````

#### Matrix column wise reduce #

``````  import 'package:ml_linalg/linalg.dart';

final matrix = Matrix.fromList([
[11.0, 12.0, 13.0, 14.0],
[15.0, 16.0, 17.0, 18.0],
[21.0, 22.0, 23.0, 24.0],
]);
final result = matrix.reduceColumns((combine, vector) => combine + vector);
print(result); // [50, 66, 90]
``````

#### Matrix row wise map #

``````  import 'package:ml_linalg/linalg.dart';

final matrix = Matrix.fromList([
[1.0, 2.0, 3.0, 4.0],
[5.0, 6.0, 7.0, 8.0],
]);
final modifier = Vector.filled(4, 2.0);
final newMatrix = matrix.rowsMap((row) => row + modifier);
print(newMatrix);
// [
//  [3.0, 4.0, 5.0, 6.0],
//  [7.0, 8.0, 9.0, 10.0],
// ]
``````

#### Matrix column wise map #

``````  import 'package:ml_linalg/linalg.dart';

final matrix = Matrix.fromList([
[1.0, 2.0, 3.0, 4.0],
[5.0, 6.0, 7.0, 8.0],
]);
final modifier = Vector.filled(2, 2.0);
final newMatrix = matrix.columnsMap((column) => column + modifier);
print(newMatrix);
// [
//  [3.0, 4.0, 5.0, 6.0],
//  [7.0, 8.0, 9.0, 10.0],
// ]
``````

#### Getting max value of the matrix #

``````  import 'package:ml_linalg/linalg.dart';

final matrix = Matrix.fromList([
[11.0, 12.0, 13.0, 14.0],
[15.0, 16.0, 17.0, 18.0],
[21.0, 22.0, 23.0, 24.0],
[24.0, 32.0, 53.0, 74.0],
]);
final maxValue = matrix.max();
print(maxValue);
// 74.0
``````

#### Getting min value of the matrix #

``````  import 'package:ml_linalg/linalg.dart';

final matrix = Matrix.fromList([
[11.0, 12.0, 13.0, 14.0],
[15.0, 16.0, 0.0, 18.0],
[21.0, 22.0, -23.0, 24.0],
[24.0, 32.0, 53.0, 74.0],
]);
final minValue = matrix.min();
print(minValue);
// -23.0
``````

#### Matrix indexing and sampling #

To access a certain row vector of the matrix one may use `[]` operator:

``````import 'package:ml_linalg/linalg.dart';

final matrix = Matrix.fromList([
[11.0, 12.0, 13.0, 14.0],
[15.0, 16.0, 0.0, 18.0],
[21.0, 22.0, -23.0, 24.0],
[24.0, 32.0, 53.0, 74.0],
]);

final row = matrix[2];

print(row); // [21.0, 22.0, -23.0, 24.0]
``````

The library's matrix interface offers `sample` method, that is supposed to return a new matrix, consisting of different segments of a source matrix. It's possible to build a new matrix from certain columns and vectors and they should not be necessarily subsequent.

For example, one needs to create a matrix from rows 1, 3, 5 and columns 1 and 3. To do so, it's needed to perform the following:

``````import 'package:ml_linalg/linalg.dart';

final matrix = Matrix.fromList([
//| 1 |         | 3 |
[4.0,   8.0,   12.0,   16.0,  34.0], // 1 Range(0, 1)
[20.0,  24.0,  28.0,   32.0,  23.0],
[36.0,  .0,   -8.0,   -12.0,  12.0], // 3 Range(2, 3)
[16.0,  1.0,  -18.0,   3.0,   11.0],
[112.0, 10.0,  34.0,   2.0,   10.0], // 5 Range(4, 5)
]);
final result = matrix.sample(
rowIndices: [0, 2, 4],
columnIndices: [0, 2],
);
print(result);
/*
[4.0,   12.0],
[36.0,  -8.0],
[112.0, 34.0]
*/
``````

#### Add new columns to a matrix #

``````import 'package:ml_linalg/linalg.dart';

final matrix = Matrix.fromList([
[11.0, 12.0, 13.0, 14.0],
[15.0, 16.0, 0.0, 18.0],
[21.0, 22.0, -23.0, 24.0],
[24.0, 32.0, 53.0, 74.0],
], dtype: DType.float32);

final updatedMatrix = matrix.insertColumns(0, [
Vector.fromList([1.0, 2.0, 3.0, 4.0]),
Vector.fromList([-1.0, -2.0, -3.0, -4.0]),
]);

print(updatedMatrix);
// [
//  [1.0, -1.0, 11.0, 12.0, 13.0, 14.0],
//  [2.0, -2.0, 15.0, 16.0, 0.0, 18.0],
//  [3.0, -3.0, 21.0, 22.0, -23.0, 24.0],
//  [4.0, -4.0, 24.0, 32.0, 53.0, 74.0],
// ]

print(updatedMatrix == matrix); // false
``````

### Contacts #

If you have questions, feel free to write me on

# Changelog #

## 12.7.1 #

• `Matrix`: `fromList` constructor, check for length of nested lists added

## 12.7.0 #

• `Matrix`: constructors speed up

## 12.6.0 #

• `Vector`: vector operations speed up
• `Float64x2Vector`: `Float64x2Vector` class created

## 12.5.1 #

• `Axis`: documentation added
• `DType`: documentation added
• `Matrix`: documentation extended and corrected

## 12.5.0 #

• `Matrix`:
• `Matrix.row` constructor added
• `Matrix.column` constructor added

## 12.4.0 #

• `Matrix`:
• `Matrix.diagonal` constructor added (for creation diagonal matrices)
• `Matrix.scalar` constructor added (for creation scalar matrices)
• `Matrix.identity` constructor added (for creation identity matrices)

## 12.3.0 #

• `Matrix`:
• `mean` method added
• `deviation` method added
• `hasData` getter added
• `empty` constructor added
• `Vector`:
• `empty` constructor added

## 12.2.0 #

• `Vector`:
• `sqrt` method added

## 12.1.0 #

• `Matrix`:
• `rowIndices` field added to the interface
• `columnIndices` field added to the interface

## 12.0.2 #

• `xrange` 0.0.8 version supported (`integers` function used instead of `ZRange`)

## 12.0.1 #

• `xrange` package version locked

## 12.0.0 #

• `Matrix`:
• `pick` method removed
• `submatrix` method replaced with `sample` method
• `[]` operator returns `Vector` from now
• `Vector`:
• `randomFilled` constructor api changed, `min` and `max` args are of `num` type now
• `fromList` constructor api changed, from now as a source expected `List<num>` instead of `List<doublet>`
• `filled` constructor api changed, from now sampling value is a `num` instead of `double`
• Dart sdk constraint returned to 2.2.0

## 11.0.0 #

• Dart sdk constraint changed: from 2.2.0 to 2.4.0
• `Matrix`: `pick` method refactored

## 10.3.7 #

• `Matrix`: `Iterable<Iterable<double>>` implemented

## 10.3.6 #

• `Vector`: `randomFilled` default parameters fixed
• Tests for `Vector`'s constructors added

## 10.3.4 #

• Images for readme.md updated (simd architecture explanation)

## 10.3.2 #

• `Vector`:
• `hashCode` speed up
• `randomFilled` constructor extended: `min` and `max` parameters added

## 10.3.1 #

• `Vector`: `hashCode` improvements

## 10.3.0 #

• `Vector`: `hashCode` re-implemented: now it's possible to use the vector as a map key

## 10.2.0 #

• `Matrix`: `sort` method added and implemented

## 10.1.0 #

• `Vector`: `subvectorByRange` method added and implemented (for float32 vector)

## 10.0.4 #

• `pubspec.yaml`: sdk version constraint changed from `>=2.3.0` to `>=2.2.0`

## 10.0.3 #

• `Float32Matrix.columns`: empty list supported as a source
• `Float32Matrix.rows`: empty list supported as a source

## 10.0.2 #

• `Float32Matrix.fromList`: empty list supported as a source

## 10.0.0 #

• `Vector`:
• removed possibility to mutate an instance of the Vector:
• `isMutable` flag removed
• `[]=` operator removed
• `Matrix`:
• removed possibility to mutate an instance of the Matrix:
• `setColumn` method removed
• `insertColumns` method added
• `Matrix.from` renamed to `Matrix.fromList`
• `Matrix.fromFlattened` renamed to `Matrix.fromFlattenedList`
• benchmarks added for checking matrix initialization performance
• Performance enhancements
• Dart 2.3.0 supported

## 9.0.0 #

• `Vector`:
• `Distance` enum added
• `distanceTo` method refactored

## 8.0.0 #

• `Matrix`:
• `rows` constructor renamed to `fromRows`
• `columns` constructor renamed to `fromColumns`
• `flattened` constructor renamed to `fromFlattened`
• `rows` getter added
• `columns` getter added

## 7.0.0 #

• `Matrix`: `ZRange` support (instead of the library built-in `Range`)

## 6.1.1 #

• `Vector`: `unique` method refactored

## 6.1.0 #

• `Vector`:
• normalize method added to interface and supported in `Float32x4Vector`
• rescale method added to interface and supported in `Float32x4Vector`
• `VectorBase`: cache for popular operations implemented

## 6.0.2 #

• `Matrix`: `MatrixMixin` corrected

## 6.0.1 #

• `Vector` class refactored (get rid of redundant mixins)

## 6.0.0 #

• prefix `ML` removed from entities' names
• Float32x4Vector: equality operator override added
• Matrix: `uniqueRows` method added

## 5.5.1 #

• MLMatrix: fixed bug in `setColumn` method when rows cache was not cleared

## 5.5.0 #

• MLMatrix: `setColumn` method implemented

## 5.4.0 #

• MLMatrix: dummy for `setColumn` method added

## 5.3.0 #

• MLMatrix: frobenius norm calculation added

## 5.2.0 #

• MLMatrix: `/` operator added
• MLMatrix: `rowsMap` method added
• MLMatrix: `columnsMap` method added

## 5.1.0 #

• `max` and `min` methods added for matrix

## 5.0.1 #

• `dartfmt` task added

## 5.0.0 #

• MLVector and MLMatrix now don't have generic type parameters

## 4.2.0 #

• Static factories converted into abstract factories

## 4.1.0 #

• `toString` method specified for matrix mixin
• examples for vector operations fixed

## 4.0.0 #

• Vector type removed (there are no longer `column` and `row` vectors)
• Matrix's method `getColumnVector` renamed to `getColumn`
• Matrix method `getRowVector` renamed to `getRow`
• Public api documentation for `MLMatrix<E>` added

## 3.5.0 #

• Mutable vectors supported in matrix

## 3.4.0 #

• Add possibility to create mutable vectors
• Add support for value assignment via []= operator

## 3.0.3 #

• build_runner dependency updated

## 3.0.0 #

• `vectorizedMap` vector's method improved: batch boundary indexes may be passed into a mapper function
• `columnsMap` and `rowsMap` matrix's method combined into one method - `vectorizedMap`
• Public factories `Float32x4VectorFactory` and `Float32x4MatrixFactory` renamed into `Float32x4Vector` and `Float32x4Matrix`
• `copy` vector's method removed

## 2.3.0 #

• `pick` method added to matrix api: it's possible now to combine a new matrix from different segments of a source matrix

## 2.2.2 #

• README.md updated (table of content)

## 2.2.0 #

• Support matrices in vector operations

## 2.1.0 #

• Column and row vectors added

## 2.0.0 #

• Unnecessary generic type argument removed from `MLMatrix` class
• Matrix logic split into separate mixins

## 1.3.0 #

• `MLVectorMixin` added, benchmark directory reorganized

## 1.2.0 #

• Map functions added to matrix

## 1.1.0 #

• `Float32x4MatrixFactory` extended

## 1.0.0 #

• Library public release

example/main.dart

``````import 'package:ml_linalg/distance.dart';
import 'package:ml_linalg/linalg.dart';

void main() {
subtraction();
multiplication();
division();
euclideanNorm();
manhattanNorm();
mean();
sum();
dot();
scalarSubtraction();
scalarMultiplication();
scalarDivision();
euclideanDistanceBetweenVectors();
manhattanDistanceBetweenVectors();
cosineDistanceBetweenVectors();
}

final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final vector2 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1 + vector2;
print(result); // [3.0, 5.0, 7.0, 9.0, 11.0]
}

void subtraction() {
final vector1 = Vector.fromList([4.0, 5.0, 6.0, 7.0, 8.0]);
final vector2 = Vector.fromList([2.0, 3.0, 2.0, 3.0, 2.0]);
final result = vector1 - vector2;
print(result); // [2.0, 2.0, 4.0, 4.0, 6.0]
}

void multiplication() {
final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final vector2 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1 * vector2;
print(result); // [2.0, 6.0, 12.0, 20.0, 30.0]
}

void division() {
final vector1 = Vector.fromList([6.0, 12.0, 24.0, 48.0, 96.0]);
final vector2 = Vector.fromList([3.0, 4.0, 6.0, 8.0, 12.0]);
final result = vector1 / vector2;
print(result); // [2.0, 3.0, 4.0, 6.0, 8.0]
}

void euclideanNorm() {
final vector1 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1.norm();
print(result); // sqrt(2^2 + 3^2 + 4^2 + 5^2 + 6^2) = sqrt(90) ~~ 9.48
}

void manhattanNorm() {
final vector1 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1.norm(Norm.manhattan);
print(result); // 2 + 3 + 4 + 5 + 6 = 20.0
}

void mean() {
final vector1 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1.mean();
print(result); // (2 + 3 + 4 + 5 + 6) / 5 = 4.0
}

void sum() {
final vector1 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1.sum();
print(result); // 2 + 3 + 4 + 5 + 6 = 20.0 (equivalent to Manhattan norm)
}

void dot() {
final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final vector2 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1.dot(vector2);
print(
result); // 1.0 * 2.0 + 2.0 * 3.0 + 3.0 * 4.0 + 4.0 * 5.0 + 5.0 * 6.0 = 70.0
}

final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final scalar = 5.0;
final result = vector1 + scalar;
print(result); // [6.0, 7.0, 8.0, 9.0, 10.0]
}

void scalarSubtraction() {
final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final scalar = 5.0;
final result = vector1 / scalar;
print(result); // [-4.0, -3.0, -2.0, -1.0, 0.0]
}

void scalarMultiplication() {
final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final scalar = 5.0;
final result = vector1 * scalar;
print(result); // [5.0, 10.0, 15.0, 20.0, 25.0]
}

void scalarDivision() {
final vector1 = Vector.fromList([25.0, 50.0, 75.0, 100.0, 125.0]);
final scalar = 5.0;
final result = vector1 / scalar;
print(result); // [5.0, 10.0, 15.0, 20.0, 25.0]
}

void euclideanDistanceBetweenVectors() {
final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final vector2 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1.distanceTo(vector2);
print(result); // ~~2.23
}

void manhattanDistanceBetweenVectors() {
final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final vector2 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1.distanceTo(vector2, distance: Distance.manhattan);
print(result); // 5.0
}

void cosineDistanceBetweenVectors() {
final vector1 = Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final vector2 = Vector.fromList([2.0, 3.0, 4.0, 5.0, 6.0]);
final result = vector1.distanceTo(vector2, distance: Distance.cosine);
print(result); // 0.00506
}
``````

## Use this package as a library

### 1. Depend on it

``````
dependencies:
ml_linalg: ^12.7.1

``````

### 2. Install it

You can install packages from the command line:

with pub:

``````
\$ pub get

``````

with Flutter:

``````
\$ flutter pub get

``````

Alternatively, your editor might support `pub get` or `flutter pub get`. Check the docs for your editor to learn more.

### 3. Import it

Now in your Dart code, you can use:

``````
import 'package:ml_linalg/axis.dart';
import 'package:ml_linalg/distance.dart';
import 'package:ml_linalg/dtype.dart';
import 'package:ml_linalg/linalg.dart';
import 'package:ml_linalg/matrix.dart';
import 'package:ml_linalg/matrix_norm.dart';
import 'package:ml_linalg/norm.dart';
import 'package:ml_linalg/sort_direction.dart';
import 'package:ml_linalg/vector.dart';
``````
 Popularity: Describes how popular the package is relative to other packages. [more] 65 Health: Code health derived from static analysis. [more] 100 Maintenance: Reflects how tidy and up-to-date the package is. [more] 100 Overall: Weighted score of the above. [more] 83

We analyzed this package on Jan 27, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

• Dart: 2.7.1
• pana: 0.13.4

#### Health suggestions

Format `lib/axis.dart`.

Run `dartfmt` to format `lib/axis.dart`.

Format `lib/distance.dart`.

Run `dartfmt` to format `lib/distance.dart`.

Format `lib/dtype.dart`.

Run `dartfmt` to format `lib/dtype.dart`.

Fix additional 20 files with analysis or formatting issues.

Additional issues in the following files:

• `lib/matrix.dart` (Run `dartfmt` to format `lib/matrix.dart`.)
• `lib/sort_direction.dart` (Run `dartfmt` to format `lib/sort_direction.dart`.)
• `lib/src/common/cache_manager/cache_manager.dart` (Run `dartfmt` to format `lib/src/common/cache_manager/cache_manager.dart`.)
• `lib/src/common/cache_manager/cache_manager_impl.dart` (Run `dartfmt` to format `lib/src/common/cache_manager/cache_manager_impl.dart`.)
• `lib/src/di/dependencies.dart` (Run `dartfmt` to format `lib/src/di/dependencies.dart`.)
• `lib/src/matrix/data_manager/float32_matrix_data_manager.dart` (Run `dartfmt` to format `lib/src/matrix/data_manager/float32_matrix_data_manager.dart`.)
• `lib/src/matrix/data_manager/float64_matrix_data_manager.dart` (Run `dartfmt` to format `lib/src/matrix/data_manager/float64_matrix_data_manager.dart`.)
• `lib/src/matrix/helper/get_2d_iterable_length.dart` (Run `dartfmt` to format `lib/src/matrix/helper/get_2d_iterable_length.dart`.)
• `lib/src/matrix/helper/get_length_of_first_or_zero.dart` (Run `dartfmt` to format `lib/src/matrix/helper/get_length_of_first_or_zero.dart`.)
• `lib/src/matrix/helper/get_zero_based_indices.dart` (Run `dartfmt` to format `lib/src/matrix/helper/get_zero_based_indices.dart`.)
• `lib/src/matrix/iterator/float32_matrix_iterator.dart` (Run `dartfmt` to format `lib/src/matrix/iterator/float32_matrix_iterator.dart`.)
• `lib/src/matrix/iterator/float64_matrix_iterator.dart` (Run `dartfmt` to format `lib/src/matrix/iterator/float64_matrix_iterator.dart`.)
• `lib/src/matrix/matrix_factory.dart` (Run `dartfmt` to format `lib/src/matrix/matrix_factory.dart`.)
• `lib/src/matrix/matrix_factory_impl.dart` (Run `dartfmt` to format `lib/src/matrix/matrix_factory_impl.dart`.)
• `lib/src/matrix/matrix_impl.dart` (Run `dartfmt` to format `lib/src/matrix/matrix_impl.dart`.)
• `lib/src/matrix/mixin/matrix_validator_mixin.dart` (Run `dartfmt` to format `lib/src/matrix/mixin/matrix_validator_mixin.dart`.)
• `lib/src/vector/float32x4_vector.dart` (Run `dartfmt` to format `lib/src/vector/float32x4_vector.dart`.)
• `lib/src/vector/float64x2_vector.dart` (Run `dartfmt` to format `lib/src/vector/float64x2_vector.dart`.)
• `lib/src/vector/simd_helper/float64x2_helper.dart` (Run `dartfmt` to format `lib/src/vector/simd_helper/float64x2_helper.dart`.)
• `lib/vector.dart` (Run `dartfmt` to format `lib/vector.dart`.)

#### Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.2.0 <3.0.0
injector ^1.0.8 1.0.8
quiver >=2.0.0 <3.0.0 2.1.2+1
xrange 0.0.8 0.0.8
Transitive dependencies
matcher 0.12.6
meta 1.1.8
path 1.6.4
stack_trace 1.9.3
Dev dependencies
benchmark_harness >=1.0.0 <2.0.0
build_runner ^1.1.2
build_test ^0.10.2
dartdoc any
grinder ^0.8.3
ml_tech ^0.0.5
mockito ^3.0.0
test ^1.2.0