package org.enumerable.lambda.enumerable.primitives;
import static java.lang.System.*;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Comparator;
import org.enumerable.lambda.enumerable.Enumerable;
import org.enumerable.lambda.enumerable.collection.EList;
import org.enumerable.lambda.enumerable.collection.ESet;
import org.enumerable.lambda.primitives.Fn1DtoB;
import org.enumerable.lambda.primitives.Fn1DtoD;
import org.enumerable.lambda.primitives.Fn1DtoI;
import org.enumerable.lambda.primitives.Fn1DtoL;
import org.enumerable.lambda.primitives.Fn1DtoO;
import org.enumerable.lambda.primitives.Fn2DDtoD;
import org.enumerable.lambda.primitives.Fn2DDtoO;
/**
* Ruby/Smalltalk style internal iterators for Java 5 using bytecode
* transformation to capture expressions as closures.
*
* <p>
* <a href="http://ruby-doc.org/core/classes/Enumerable.html"/>Ruby's Enumerable
* module in 1.8.6</a>
* </p>
*/
public class EnumerableDoubles {
// If changing this file, remember to run PrimitiveEnumerableGenerator.
/**
* Passes each element of the array to the given block. The method returns
* true if the block never returns false.
*/
public static <E> boolean all(double[] array, Fn1DtoB block) {
for (double each : array)
if (!block.call(each))
return false;
return true;
}
/**
* Passes each element of the array to the given block. The method returns
* true if the block ever returns a value other than false.
*/
public static <E> boolean any(double[] array, Fn1DtoB block) {
for (double each : array)
if (block.call(each))
return true;
return false;
}
/**
* Returns a new list with the results of running block once for every
* element in array.
*/
public static <R> Object[] collect(double[] array, Fn1DtoO<R> block) {
Object[] result = new Object[array.length];
int i = 0;
for (double each : array)
result[i++] = block.call(each);
return result;
}
/**
* @see #collect(double[], Fn1DtoO)
*/
public static/* don't change */double[] collect(double[] array, Fn1DtoD block) {
/* don't change */double[] result = new /* don't change */double[array.length];
int i = 0;
for (double each : array)
result[i++] = block.call(each);
return result;
}
/**
* @see #collect(double[], Fn1DtoO)
*/
public static int[] collect(double[] array, Fn1DtoI block) {
int[] result = new int[array.length];
int i = 0;
for (double each : array)
result[i++] = block.call(each);
return result;
}
/**
* @see #collect(double[], Fn1DtoO)
*/
public static long[] collect(double[] array, Fn1DtoL block) {
long[] result = new long[array.length];
int i = 0;
for (double each : array)
result[i++] = block.call(each);
return result;
}
/**
* Returns a new list with the results of running block once for every
* element in array.
*/
@SuppressWarnings("unchecked")
public static <R> R[] collect(double[] array, Fn1DtoO<R> block, Class<R> type) {
R[] result = (R[]) Array.newInstance(type, array.length);
int i = 0;
for (double each : array)
result[i++] = block.call(each);
return result;
}
// /**
// * Passes each entry in array to block. Returns the first for which block
// is
// * not false. If no value matches, it returns null.
// */
// public static <E> E detect(double[] array, Fn1DtoB block) {
// return Enumerable.detect(asList(array), block);
// }
/**
* Passes each entry in array to block. Returns the first for which block is
* not false. If no value matches, it returns ifNone.
*/
public static double detect(double[] array, double ifNone, Fn1DtoB block) {
for (double each : array)
if (block.call(each))
return each;
return ifNone;
}
/**
* Calls block for each item in array.
*/
public static <R> double[] each(double[] array, Fn1DtoO<R> block) {
for (double each : array)
block.call(each);
return array;
}
/**
* @see #each(double[], Fn1DtoO)
*/
public static double[] each(double[] array, Fn1DtoD block) {
for (double each : array)
block.call(each);
return array;
}
/**
* @see #each(double[], Fn1DtoO)
*/
public static double[] each(double[] array, Fn1DtoI block) {
for (double each : array)
block.call(each);
return array;
}
/**
* @see #each(double[], Fn1DtoO)
*/
public static double[] each(double[] array, Fn1DtoL block) {
for (double each : array)
block.call(each);
return array;
}
/**
* @see #each(double[], Fn1DtoO)
*/
public static double[] each(double[] array, Fn1DtoB block) {
for (double each : array)
block.call(each);
return array;
}
/**
* Calls block with two arguments, the item and its index, for each item in
* array.
*/
public static <R> double[] eachWithIndex(double[] array, Fn2DDtoO<R> block) {
double idx = 0;
for (double each : array)
block.call(each, idx++);
return array;
}
/**
* @see #eachWithIndex(double[], Fn2DDtoO)
*/
public static double[] eachWithIndex(double[] array, Fn2DDtoD block) {
double idx = 0;
for (double each : array)
block.call(each, idx++);
return array;
}
/**
* @see #toList(double[])
*/
public static <E> EList<Double> entries(double[] array) {
return toList(array);
}
// /**
// * @see #detect(double[], Fn1)
// */
// public static <E> E find(double[] array, Fn1DtoB block) {
// return Enumerable.detect(asList(array), block);
// }
//
/**
* @see #detect(double[], double, Fn1DtoB)
*/
public static double find(double[] array, double ifNone, Fn1DtoB block) {
return detect(array, ifNone, block);
}
/**
* @see #select(double[], Fn1DtoB)
*/
public static double[] findAll(double[] array, Fn1DtoB block) {
return select(array, block);
}
/**
* Named parameter for detect.
*
* @see #detect(double[], double, Fn1DtoB)
* @see #find(double[], double, Fn1DtoB)
*/
public static double ifNone(double defaultValue) {
return defaultValue;
}
/**
* @see #member(double[], double)
*/
public static boolean include(double[] array, double value) {
return member(array, value);
}
/**
* Combines the elements of array by applying the block to an accumulator
* value (memo) and each element in turn. At each step, memo is set to the
* value returned by the block. This form uses the first element of the
* array as a the initial value (and skips that element while iterating).
*/
public static double inject(double[] array, Fn2DDtoD block) {
double initial = array[0];
for (int i = 1; i < array.length; i++)
initial = block.call(initial, array[i]);
return initial;
}
/**
* Combines the elements of array by applying the block to an accumulator
* value (memo) and each element in turn. At each step, memo is set to the
* value returned by the block. This form lets you supply an initial value
* for memo.
*/
public static double inject(double[] array, double initial, Fn2DDtoD block) {
for (double each : array)
initial = block.call(initial, each);
return initial;
}
/**
* @see #collect(double[], Fn1DtoO)
*/
public static <R> Object[] map(double[] array, Fn1DtoO<R> block) {
return collect(array, block);
}
/**
* @see #collect(double[], Fn1DtoO)
*/
public static/* don't change */double[] map(double[] array, Fn1DtoD block) {
return collect(array, block);
}
/**
* @see #collect(double[], Fn1DtoO)
*/
public static int[] map(double[] array, Fn1DtoI block) {
return collect(array, block);
}
/**
* @see #collect(double[], Fn1DtoO)
*/
public static long[] map(double[] array, Fn1DtoL block) {
return collect(array, block);
}
/**
* @see #collect(double[], Fn1DtoO, Class)
*/
public static <R> R[] map(double[] array, Fn1DtoO<R> block, Class<R> type) {
return collect(array, block, type);
}
/**
* Returns the maximum value in array.
*/
public static double max(double[] array) {
return min(array, new ReverseNaturalOrderDoubleComparator(new NaturalOrderPrimitiveComparator()));
}
/**
* Returns the maximum value in array. This form uses the block to
* {@link Comparator#compare}.
*/
public static double max(double[] array, Fn2DDtoD block) {
return min(array, new ReverseNaturalOrderDoubleComparator(new BlockDoubleComparator(block)));
}
/**
* Returns true if any member of array equals value. Equality is tested
* using {@link Object#equals(Object)}.
*/
public static boolean member(double[] array, double value) {
return Arrays.binarySearch(sort(array), value) >= 0;
}
/**
* Returns the minimum value in array.
*/
public static double min(double[] array) {
return min(array, new NaturalOrderPrimitiveComparator());
}
/**
* Returns the minimum value in array. This form uses the block to
* {@link Comparator#compare}.
*/
public static double min(double[] array, Fn2DDtoD block) {
return min(array, new BlockDoubleComparator(block));
}
/**
* Returns two lists, the first containing the elements of array for which
* the block evaluates to true, the second containing the rest.
*/
public static double[][] partition(double[] array, Fn1DtoB block) {
double[][] result = new double[2][];
result[0] = select(array, block);
result[1] = reject(array, block);
return result;
}
/**
* Returns an array containing all elements of array for which block is
* false.
*/
public static double[] reject(double[] array, Fn1DtoB block) {
return selectOrReject(array, block, false);
}
/**
* Returns an array containing all elements of array for which block is not
* false.
*/
public static double[] select(double[] array, Fn1DtoB block) {
return selectOrReject(array, block, true);
}
private static double[] selectOrReject(double[] array, Fn1DtoB block, boolean select) {
double[] result = new double[array.length];
int i = 0;
for (double each : array)
if (block.call(each) == select)
result[i++] = each;
return copy(result, i);
}
/**
* Returns an array containing the items in array sorted, according to their
* own compareTo method.
*/
public static double[] sort(double[] array) {
double[] result = copy(array, array.length);
Arrays.sort(result);
return result;
}
// /**
// * Returns an array containing the items in array sorted by using the
// * results of the supplied block.
// */
// public static double[] sort(double[] array, Fn2DDtoD block) {
// }
//
// /**
// * Sorts array using a set of keys generated by mapping the values in
// array
// * through the given block.
// */
// public static <E, R extends Object & Comparable<? super R>> double[]
// sortBy(double[] array, final Fn1<E, R> block) {
// return Enumerable.sortBy(asList(array),
// block).toArray(newEmptyArray(array));
// }
//
/**
* Returns a list containing the items in array.
*/
public static EList<Double> toList(double[] array) {
EList<Double> result = new EList<Double>(array.length);
for (double each : array)
result.add(each);
return result;
}
/**
* Creates a new Set containing the elements of the given array.
*/
public static ESet<Double> toSet(double[] array) {
return Enumerable.toSet(toList(array));
}
/**
* Creates a new Set containing the elements of the given array, the
* elements are preprocessed by the given block.
*/
public static <R> ESet<R> toSet(double[] array, Fn1DtoO<R> block) {
return Enumerable.toSet(toList(array), block);
}
// /**
// * Converts any arguments to iterators, then merges elements of array with
// * corresponding elements from each argument. This generates a sequence of
// * array#size n-element list, where n is one more that the count of
// * arguments. If the size of any argument is less than array#length, null
// * values are supplied.
// *
// * <p>
// * Due to varargs this version doesn't support taking a block like in
// Ruby.
// * Feed the result into {@link #collect(double[], Fn1) to achieve the same
// * effect.
// * </p>
// */
// public static <E> Object[][] zip(double[] array, double[]... args) {
// Iterable<?>[] lists = new Iterable<?>[args.length];
// for (int i = 0; i < args.length; i++)
// lists[i] = asList(args[i]);
//
// List<List<?>> zip = Enumerable.zip(asList(array), lists);
//
// Object[][] result = new Object[zip.size()][];
// for (int i = 0; i < zip.size(); i++)
// result[i] = zip.get(i).toArray();
// return result;
// }
static double min(double[] array, DoubleComparator comparator) {
double result = array[0];
for (int i = 1; i < array.length; i++) {
double each = array[i];
if (comparator.compare(each, result) < 0)
result = each;
}
return result;
}
static interface DoubleComparator {
int compare(double a, double b);
}
static class NaturalOrderPrimitiveComparator implements DoubleComparator {
public int compare(/* don't change */double a, /* don't change */double b) {
return /* don't change */Double.compare(a, b);
}
public int compare(long a, long b) {
return (a < b) ? -1 : ((a > b) ? 1 : 0);
}
public int compare(int a, int b) {
return (a < b) ? -1 : ((a > b) ? 1 : 0);
}
}
static class BlockDoubleComparator implements DoubleComparator {
Fn2DDtoD block;
BlockDoubleComparator(Fn2DDtoD block) {
this.block = block;
}
public int compare(double a, double b) {
return (int) block.call(a, b);
}
}
static class ReverseNaturalOrderDoubleComparator implements DoubleComparator {
DoubleComparator comparator;
ReverseNaturalOrderDoubleComparator(DoubleComparator comparator) {
this.comparator = comparator;
}
public int compare(double a, double b) {
return -comparator.compare(a, b);
}
}
static double[] copy(double[] array, int length) {
double[] result = new double[length];
arraycopy(array, 0, result, 0, length);
return result;
}
}