/** * @param s an iterator * @param factor a factor * @return an iterator whose elements are multiplied by factor */ public static ImmutableIterator<Double> multiply(Iterator<Double> s, double factor) { return map(s, x -> x * factor); }
/** * @param s an iterator * @param t another iterator * @return the element wise sum of s and t */ public static ImmutableIterator<Double> add(Iterator<Double> s, Iterator<Double> t) { return map(s, t, (x, y) -> x + y); }
/** * @param s an iterator * @param inc the increment * @return an iterator all of whose elements are incremented by inc */ public static ImmutableIterator<Double> add(Iterator<Double> s, double inc) { return map(s, x -> x + inc); }
/** * @return the iterator of the exp coefficients */ public static ImmutableIterator<Double> exp() { return map(faculty(), (Long x) -> 1.0 / x); }
/** * @param t an iterator of non-descending timestamps * @param f a function mapping timestamps to values */ public TimeSeries(Iterator<T> t, Function<T, V> f) { this(map(t, x -> pairOf(x, f.apply(x)))); }
/** * @param f the function to be applied to each element * @param <V> the type to which the elements of this will be mapped * @return the iterator of mapped elements */ public <V extends Comparable<V>> FluentIterator<V> map(Function<T, V> f) { return fluent(Iterators.map(this, f)); }
/** * @param t the second iterator to be mapped, may contain nulls * @param f the function to be applied to each pair of elements from this and t * @return the iterator of mapped elements */ public FluentIterator<T> map(Iterator<T> t, BinaryOperator<T> f) { return fluent(Iterators.map(this, t, f)); }
/** * @param first the first iterator to be mapped, may contain nulls * @param second the second iterator to be mapped, may contain nulls * @param mapper the function to be applied to each pair of elements from first and second * @param <T> the type to which will be mapped * @return the iterator of mapped elements */ public static <T> ImmutableIterator<T> map(Iterator<T> first, Iterator<T> second, BinaryOperator<T> mapper) { ImmutableIterator<List<T>> aux = zip(asList(first, second)); return map(aux, (List<T> xs) -> mapper.apply(xs.get(0), xs.get(1))); }
/** * @param n the number of forks * @return list of n iterator clones to be iterated on independently * After calling tee, this must not be iterated on! */ public List<FluentIterator<T>> tee(int n) { Function<Iterator<T>, FluentIterator<T>> f = FluentIterator::fluent; return Iterators.takeAll(Iterators.map(Iterators.tee(this, n).iterator(), f)); }
/** * @return the iterator of the cosine coefficients */ public static ImmutableIterator<Double> cos() { return map(cycle(1.0, 0.0, -1.0, 0.0), exp(), (a, b) -> a * b); }
/** * @param <A> any type * @param <B> any type * @param iterators a pair of iterators * @return an iterator of pairs */ public static <A, B> ImmutableIterator<Pair<A, B>> zip(Pair<Iterator<A>, Iterator<B>> iterators, boolean weak) { List input = iterators.asList(); Iterator<List> output = zip(input, weak); // no way to avoid warnings return map(output, (List xs) -> pairOf((A) xs.get(0), (B) xs.get(1))); }
/** * @return the iterator of the sine coefficients */ public static ImmutableIterator<Double> sin() { return map(cycle(0.0, 1.0, 0.0, -1.0), exp(), (a, b) -> a * b); }
/** * @param <T> any type * @param zippedIterator iterator of lists; must not be empty. * The lists are typically but not necessarily * of equal size. * @return list of iterators to be iterated on independently * The result's size is that of the first list; subsequent lists * are truncated if longer and padded with nulls if shorter */ public static <T> List<ImmutableIterator<T>> unzip(Iterator<List<T>> zippedIterator) { List<T> firstColumn = zippedIterator.next(); int n = firstColumn.size(); @SuppressWarnings("unchecked") List<ImmutableIterator<List<T>>> aux = tee(concat(of(firstColumn), zippedIterator), n); List<ImmutableIterator<T>> result = new ArrayList<>(n); for (int i = 0; i < n; i++) { int j = i; // j is effectively final, i is not result.add(j, map(aux.get(j), xs -> j < xs.size() ? xs.get(j) : null)); } return result; }
/** * @param ts a time series * @param <T> the time type * @param <V> the value type * @return a new time series unioning all time stamps given, * the value being the list of all values valid at that time */ public static <T extends Comparable<T>, V> TimeSeries<T, List<V>> merge(Iterable<TimeSeries<T, V>> ts) { Iterator<Pair<T, List<V>>> aux = new TimeSeriesMerge<>(map(asIterator(ts), Iterable::iterator)); return new TimeSeries<>(aux); }
/** * @param tv the first time series * @param tw the second time series * @param f a function mapping V x V -> U (e.g. x, y -> x <= y) * @param <T> type of timestamps * @param <V> type of values * @param <U> return type of f * @return a new time series unioning all time stamps given, * the value being the result of f (e.g. lessThan, equals) */ public static <T extends Comparable<T>, V, U> TimeSeries<T, U> merge(TimeSeries<T, V> tv, TimeSeries<T, V> tw, BiFunction<V, V, U> f) { Iterator<Pair<T, List<V>>> aux1 = asIterator(merge(asList(tv, tw))); Iterator<Pair<T, U>> aux2 = map(aux1, (Pair<T, List<V>> p) -> pairOf(p.getFirst(), f.apply(p.getSecond().get(0), p.getSecond().get(1)))); return new TimeSeries<>(aux2); }
/** * @param ts a time series * @param <T> the time type * @param <V> the value type * @param op an operator reducing the value list * @return a new time series unioning all time stamps given, * the value being the result of the reducing by op (e.g. min, max, avg) */ public static <T extends Comparable<T>, V> TimeSeries<T, V> merge(Iterable<TimeSeries<T, V>> ts, BinaryOperator<V> op) { BinaryOperator<V> wop = weakBinaryOperator(op); Iterator<Pair<T, List<V>>> aux1 = new TimeSeriesMerge<>(map(asIterator(ts), Iterable::iterator)); Iterator<Pair<T, V>> aux2 = map(aux1, (Pair<T, List<V>> p) -> pairOf(p.getFirst(), reduce(asIterator(p.getSecond()), wop))); return new TimeSeries<>(aux2); }
/** * This method merges n time series into one according to the following strategy: * The timestamps are merged; the resulting sequence is the union of the given ones. * On each timestamp, the new value is computed by reducing the given operator to * the vector of values at that time stamp. * Typical operators are min, max, sum, avg. * * @param input an iterable of time series to be merged * @param op the operator to be applied * @param <T> type of timestamps * @param <V> type of values * @return iterator of merged timeValuePairs */ public static <T extends Comparable<T>, V> Iterator<Pair<T, V>> merge(Iterable<Iterator<Pair<T, V>>> input, BinaryOperator<V> op) { return map(merge(input), (Pair<T, List<V>> p) -> pairOf(p.getFirst(), reduce(asIterator(p.getSecond()), weakBinaryOperator(op)))); }