Skip to content

Commit

Permalink
xrange 0.0.6 supported, unit tests for subvectorByRange method added,…
Browse files Browse the repository at this point in the history
… subvector method fixed
  • Loading branch information
gyrdym committed Jun 3, 2019
1 parent a30099d commit d2ccdd1
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 8 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,8 @@
# Changelog

## 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`

Expand Down
2 changes: 2 additions & 0 deletions lib/linalg.dart
@@ -1,3 +1,5 @@
export 'package:ml_linalg/distance.dart';
export 'package:ml_linalg/dtype.dart';
export 'package:ml_linalg/matrix.dart';
export 'package:ml_linalg/norm.dart';
export 'package:ml_linalg/vector.dart';
15 changes: 14 additions & 1 deletion lib/src/vector/base_vector.dart
Expand Up @@ -9,6 +9,7 @@ import 'package:ml_linalg/src/common/typed_list_helper/typed_list_helper.dart';
import 'package:ml_linalg/src/vector/common/simd_helper.dart';
import 'package:ml_linalg/vector.dart';
import 'package:quiver/core.dart';
import 'package:xrange/zrange.dart';

abstract class BaseVector<E, S extends List<E>> with IterableMixin<double>
implements Vector {
Expand Down Expand Up @@ -313,11 +314,23 @@ abstract class BaseVector<E, S extends List<E>> with IterableMixin<double>
return _innerTypedList[index];
}

@override
Vector subvectorByRange(ZRange range) =>
subvector(range.firstValue ?? 0, range.lastValue == null
? null : range.lastValue + 1);

@override
Vector subvector(int start, [int end]) {
if (start < 0) throw RangeError.range(start, 0, length - 1, '`start` cannot'
' be negative');
if (end != null && start >= end) throw RangeError.range(start, 0,
length - 1, '`start` cannot be greater than or equal to `end`');
if (start >= length) throw RangeError.range(start, 0,
length - 1, '`start` cannot be greater than or equal to the vector'
'length');
final collection = _typedListHelper
.getBufferAsList((_innerSimdList as TypedData).buffer, start,
(end > length ? length : end) - start);
(end == null || end > length ? length : end) - start);
return Vector.fromList(collection, dtype: dtype);
}

Expand Down
5 changes: 5 additions & 0 deletions lib/vector.dart
Expand Up @@ -3,6 +3,7 @@ import 'dart:typed_data';
import 'package:ml_linalg/distance.dart';
import 'package:ml_linalg/dtype.dart';
import 'package:ml_linalg/src/vector/float32/float32_vector.dart';
import 'package:xrange/zrange.dart';

import 'norm.dart';

Expand Down Expand Up @@ -130,6 +131,10 @@ abstract class Vector implements Iterable<double> {

Vector fastMap<E>(E mapper(E element));

/// Returns a new vector formed by a specific part of [this] vector using
/// integer range
Vector subvectorByRange(ZRange range);

/// Returns a new vector formed by a specific part of [this] vector
Vector subvector(int start, [int end]);
}
2 changes: 1 addition & 1 deletion pubspec.lock
Expand Up @@ -546,7 +546,7 @@ packages:
name: xrange
url: "https://pub.dartlang.org"
source: hosted
version: "0.0.5"
version: "0.0.6"
yaml:
dependency: transitive
description:
Expand Down
4 changes: 2 additions & 2 deletions pubspec.yaml
@@ -1,6 +1,6 @@
name: ml_linalg
description: SIMD-based linear algebra (1 operation on 4 float32 values, 1 operation on 2 float64 values)
version: 10.0.4
version: 10.1.0
author: Ilia Gyrdymov <ilgyrd@gmail.com>
homepage: https://github.com/gyrdym/ml_linalg

Expand All @@ -9,7 +9,7 @@ environment:

dependencies:
quiver: '>=2.0.0 <3.0.0'
xrange: ^0.0.4
xrange: ^0.0.6

dev_dependencies:
benchmark_harness: ">=1.0.0 <2.0.0"
Expand Down
98 changes: 94 additions & 4 deletions test/float32_vector_test.dart
Expand Up @@ -5,6 +5,7 @@ import 'package:ml_linalg/linalg.dart';
import 'package:ml_linalg/src/matrix/float32/float32_matrix.dart';
import 'package:ml_linalg/src/vector/float32/float32_vector.dart';
import 'package:test/test.dart';
import 'package:xrange/zrange.dart';

import 'unit_test_helpers/float_iterable_almost_equal_to.dart';

Expand Down Expand Up @@ -461,7 +462,8 @@ void main() {
expect(result, isNot(vector));
});

test('`query` method', () {
test('should create a vector using elements on specific inidces from '
'given list', () {
final vector = Float32Vector.fromList([10.0, 3.0, 4.0, 7.0, 9.0, 12.0]);
final query = vector.query([1, 1, 0, 3]);
expect(query, equals([3.0, 3.0, 10.0, 7.0]));
Expand Down Expand Up @@ -568,12 +570,100 @@ void main() {
expect(() => vector[1], throwsRangeError);
expect(() => vector[100], throwsRangeError);
});
});

group('Float32x4Vector.subvector', () {
test('should cut out a subvector (`end` exclusive)', () {
final vector = Float32Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final actual = vector.subvector(1, 4);
final expected = [2.0, 3.0, 4.0];
expect(actual, expected);
});

test('should cut out a subvector', () {
test('should cut out a subvector of length 1 if `start` is equal to the '
'last index of the vector', () {
final vector = Float32Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final actual = vector.subvector(1, 5);
final expected = [2.0, 3.0, 4.0, 5.0];
final actual = vector.subvector(4, 5);
final expected = [5.0];
expect(actual, expected);
});

test('should cut out rest of the vector if `end` is not specified', () {
final vector = Float32Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0, 7.0]);
final actual = vector.subvector(1);
final expected = [2.0, 3.0, 4.0, 5.0, 7.0];
expect(actual, expected);
});

test('should cut out rest of the vector if `end` is specified and greater'
'that the vector length', () {
final vector = Float32Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0, 7.0]);
final actual = vector.subvector(1, 20);
final expected = [2.0, 3.0, 4.0, 5.0, 7.0];
expect(actual, expected);
});

test('should throw a range error if `start` is negative', () {
final vector = Float32Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0, 7.0]);
final actual = () => vector.subvector(-1, 20);
expect(actual, throwsRangeError);
});

test('should throw a range error if `start` is greater than `end`', () {
final vector = Float32Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0, 7.0]);
final actual = () => vector.subvector(3, 2);
expect(actual, throwsRangeError);
});

test('should throw a range error if `start` is equal to the `end`', () {
final vector = Float32Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final actual = () => vector.subvector(4, 4);
expect(actual, throwsRangeError);
});
});

group('Float32x4Vector.subvectorByRange', () {
test('should return a proper vector using closed range', () {
final vector = Float32Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final actual = vector.subvectorByRange(ZRange.closed(1, 3));
expect(actual, equals([2.0, 3.0, 4.0]));
});

test('should return a proper vector using open range', () {
final vector = Float32Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final actual = vector.subvectorByRange(ZRange.open(1, 3));
expect(actual, equals([3.0]));
});

test('should return a proper vector using open-closed range', () {
final vector = Float32Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final actual = vector.subvectorByRange(ZRange.openClosed(1, 3));
expect(actual, equals([3.0, 4.0]));
});

test('should return a proper vector using closed-open range', () {
final vector = Float32Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final actual = vector.subvectorByRange(ZRange.closedOpen(1, 3));
expect(actual, equals([2.0, 3.0]));
});

test('should return a proper vector using upper boundless range', () {
final vector = Float32Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final actual = vector.subvectorByRange(ZRange.atLeast(2));
expect(actual, equals([3.0, 4.0, 5.0]));
});

test('should return a proper vector using lower boundless range', () {
final vector = Float32Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final actual = vector.subvectorByRange(ZRange.atMost(2));
expect(actual, equals([1.0, 2.0, 3.0]));
});

test('should return a copy of the vector using absolutely boundless '
'range', () {
final vector = Float32Vector.fromList([1.0, 2.0, 3.0, 4.0, 5.0]);
final actual = vector.subvectorByRange(ZRange.all());
expect(actual, equals([1.0, 2.0, 3.0, 4.0, 5.0]));
});
});
}

0 comments on commit d2ccdd1

Please sign in to comment.