| // |
| // Copyright 2014 Google Inc. All rights reserved. |
| // |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file or at |
| // https://developers.google.com/open-source/licenses/bsd |
| // |
| |
| part of charted.core.utils; |
| |
| /// Returns a sum of all values in the given list of values |
| num sum(List<num> values) => values == null || values.isEmpty |
| ? 0 |
| : values.fold(0.0, (num old, num next) => old + next); |
| |
| /// Returns the smallest number in the given list of values |
| num min(Iterable<num> values) => values == null || values.isEmpty |
| ? null |
| : values.fold(values.elementAt(0), (x, y) => math.min(x, y)); |
| |
| /// Returns the largest number in the given list of values |
| num max(Iterable<num> values) => values == null || values.isEmpty |
| ? null |
| : values.fold(values.elementAt(0), (x, y) => math.max(x, y)); |
| |
| /// Represents a constant pair of values |
| class Pair<T1, T2> { |
| final T1 first; |
| final T2 last; |
| |
| const Pair(this.first, this.last); |
| |
| bool operator ==(other) => |
| other is Pair && first == other.first && last == other.last; |
| |
| int get hashCode => hash2(first, last); |
| } |
| |
| /// Represents a pair of mininum and maximum values in a List. |
| class Extent<T extends Comparable> extends Pair<T, T> { |
| T get min => first; |
| T get max => last; |
| |
| factory Extent.items(Iterable<T> items, |
| [Comparator<T> compare = Comparable.compare]) { |
| if (items.length == 0) return new Extent(null, null); |
| var max = items.first, min = items.first; |
| for (var value in items) { |
| if (compare(max, value) < 0) max = value; |
| if (compare(min, value) > 0) min = value; |
| } |
| return new Extent(min, max); |
| } |
| |
| const Extent(T min, T max) |
| : super(min, max); |
| } |
| |
| /// Iterable representing a range of values containing the start, stop |
| /// and each of the step values between them. |
| class Range extends DelegatingList<num> { |
| final num start; |
| final num stop; |
| final num step; |
| |
| factory Range.integers(num start, [num stop, num step = 1]) => |
| new Range(start, stop, step, true); |
| |
| factory Range(num start, [num stop, num step = 1, bool integers = false]) { |
| List<num> values = <num>[]; |
| |
| if (stop == null) { |
| stop = start; |
| start = 0; |
| } |
| |
| if (step == 0 || start < stop && step < 0 || start > stop && step > 0) { |
| throw new ArgumentError('Invalid range.'); |
| } |
| |
| num k = _integerConversionFactor(step.abs()), i = -1, j; |
| |
| start *= k; |
| stop *= k; |
| step *= k; |
| |
| if (step < 0) { |
| while ((j = start + step * ++i) > stop) { |
| values.add(integers ? j ~/ k : j / k); |
| } |
| } else { |
| while ((j = start + step * ++i) < stop) { |
| values.add(integers ? j ~/ k : j / k); |
| } |
| } |
| |
| return new Range._internal(start, stop, step, values); |
| } |
| |
| Range._internal(this.start, this.stop, this.step, List<num> values) |
| : super(values); |
| |
| static int _integerConversionFactor(num val) { |
| int k = 1; |
| while (val * k % 1 > 0) { |
| k *= 10; |
| } |
| return k; |
| } |
| } |