arrays.java

/*
 * Java Genetic Algorithm Library (@__identifier__@).
 * Copyright (c) @__year__@ Franz Wilhelmstötter
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Author:
 *    Franz Wilhelmstötter (franz.wilhelmstoetter@gmx.at)
 */
package org.jenetics.util;

import static java.lang.String.format;
import static java.util.Objects.requireNonNull;

import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Random;


/**
 * Static helper methods concerning arrays.
 *
 * @author <a href="mailto:franz.wilhelmstoetter@gmx.at">Franz Wilhelmstötter</a>
 * @since 1.0
 * @version 1.5 &mdash; <em>$Date: 2014-02-15 $</em>
 */
public final class arrays extends StaticObject {
	private arrays() {}


	/**
	 * Unified method for calculating the hash code of every {@link Seq}
	 * implementation. The hash code is defined as followed:
	 *
	 * [code]
	 * int hashCode = 1;
	 * final Iterator<E> it = seq.iterator();
	 * while (it.hasNext()) {
	 *     final E obj = it.next();
	 *     hashCode = 31*hashCode + (obj == null ? 0 : obj.hashCode());
	 * }
	 * [/code]
	 *
	 * @see Seq#hashCode()
	 * @see List#hashCode()
	 *
	 * @param seq the sequence to calculate the hash code for.
	 * @return the hash code of the given sequence.
	 */
	public static int hashCode(final Seq<?> seq) {
		int hash = 1;
		for (Object element : seq) {
			hash = 31*hash + (element == null ? 0: element.hashCode());
		}
		return hash;
	}

	/**
	 * Unified method for compare to sequences for equality.
	 *
	 * @see Seq#equals(Object)
	 *
	 * @param seq the sequence to test for equality.
	 * @param obj the object to test for equality with the sequence.
	 * @return {@code true} if the given objects are sequences and contain the
	 *          same objects in the same order, {@code false} otherwise.
	 */
	public static boolean equals(final Seq<?> seq, final Object obj) {
		if (obj == seq) {
			return true;
		}
		if (!(obj instanceof Seq<?>)) {
			return false;
		}

		final Seq<?> other = (Seq<?>)obj;
		boolean equals = (seq.length() == other.length());
		for (int i = seq.length(); equals && --i >= 0;) {
			final Object element = seq.get(i);
			if (element != null) {
				equals = element.equals(other.get(i));
			} else {
				equals = other.get(i) == null;
			}
		}
		return equals;
	}

	/**
	 * Swap two elements of an given list.
	 *
	 * @param <T> the list type.
	 * @param list the array
	 * @param i index of the first list element.
	 * @param j index of the second list element.
	 * @throws IndexOutOfBoundsException if <tt>i &lt; 0</tt> or
	 *			<tt>j &lt; 0</tt> or <tt>i &gt; a.length</tt> or
	 *			<tt>j &gt; a.length</tt>
	 * @throws NullPointerException if the give list is {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static <T> void swap(final List<T> list, final int i, final int j) {
		final T old = list.get(i);
		list.set(i, list.get(j));
		list.set(j, old);
	}

	/**
	 * Swap two elements of an given array.
	 *
	 * @param <T> the array type.
	 * @param array the array
	 * @param i index of the first array element.
	 * @param j index of the second array element.
	 * @throws IndexOutOfBoundsException if <tt>i &lt; 0</tt> or
	 *			<tt>j &lt; 0</tt> or <tt>i &gt; a.length</tt> or
	 *			<tt>j &gt; a.length</tt>
	 * @throws NullPointerException if the give array is {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static <T> void swap(final T[] array, final int i, final int j) {
		final T old = array[i];
		array[i] = array[j];
		array[j] = old;
	}

	/**
	 * Swap two byte elements of the given array.
	 *
	 * @param array the array
	 * @param i index of the first array element.
	 * @param j index of the second array element.
	 * @throws IndexOutOfBoundsException if <tt>i &lt; 0</tt> or
	 *			<tt>j &lt; 0</tt> or <tt>i &gt; a.length</tt> or
	 *			<tt>j &gt; a.length</tt>
	 * @throws NullPointerException if the give array is {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static void swap(final byte[] array, final int i, final int j) {
		final byte old = array[i];
		array[i] = array[j];
		array[j] = old;
	}

	/**
	 * Swap two elements of an given array.
	 *
	 * @param array the array
	 * @param i index of the first array element.
	 * @param j index of the second array element.
	 * @throws IndexOutOfBoundsException if <tt>i &lt; 0</tt> or
	 *			<tt>j &lt; 0</tt> or <tt>i &gt; a.length</tt> or
	 *			<tt>j &gt; a.length</tt>
	 * @throws NullPointerException if the give array is {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static void swap(final int[] array, final int i, final int j) {
		final int old = array[i];
		array[i] = array[j];
		array[j] = old;
	}

	/**
	 * Calls the sort method on the {@link Arrays} class.
	 *
	 * @throws NullPointerException if the give array is {@code null}.
	 * @throws UnsupportedOperationException if the array is sealed
	 * 		  ({@code array.isSealed() == true}).
	 */
	public static <T extends Object & Comparable<? super T>> MSeq<T>
	sort(final MSeq<T> array)
	{
		Collections.sort(array.asList());
		return array;
	}

	/**
	 * Test whether the given array is sorted in ascending order.
	 *
	 * @param seq the array to test.
	 * @return {@code true} if the given {@code array} is sorted in ascending
	 *         order, {@code false} otherwise.
	 * @throws NullPointerException if the given array or one of it's element is
	 *         {@code null}.
	 */
	public static <T extends Object & Comparable<? super T>>
	boolean isSorted(final Seq<T> seq)
	{
		boolean sorted = true;
		for (int i = 0, n = seq.length() - 1; i < n && sorted; ++i) {
			sorted = seq.get(i).compareTo(seq.get(i + 1)) <= 0;
		}

		return sorted;
	}

	/**
	 * Test whether the given array is sorted in ascending order. The order of
	 * the array elements is defined by the given comparator.
	 *
	 * @param seq the array to test.
	 * @param comparator the comparator which defines the order.
	 * @return {@code true} if the given {@code array} is sorted in ascending
	 *         order, {@code false} otherwise.
	 * @throws NullPointerException if the given array or one of it's element or
	 *         the comparator is {@code null}.
	 */
	public static <T> boolean isSorted(
		final Seq<T> seq, final Comparator<? super T> comparator
	) {
		boolean sorted = true;
		for (int i = 0, n = seq.length() - 1; i < n && sorted; ++i) {
			sorted = comparator.compare(seq.get(i), seq.get(i + 1)) <= 0;
		}

		return sorted;
	}

	/**
	 * Randomize the {@code array} using the given {@link Random} object. The used
	 * shuffling algorithm is from D. Knuth TAOCP, Seminumerical Algorithms,
	 * Third edition, page 142, Algorithm S (Selection sampling technique).
	 *
	 * @param array the {@code array} to randomize.
	 * @throws NullPointerException if the give array is {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static <T> T[] shuffle(final T[] array) {
		return shuffle(array, RandomRegistry.getRandom());
	}

	/**
	 * Randomize the {@code array} using the given {@link Random} object. The used
	 * shuffling algorithm is from D. Knuth TAOCP, Seminumerical Algorithms,
	 * Third edition, page 142, Algorithm S (Selection sampling technique).
	 *
	 * @param array the {@code array} to randomize.
	 * @param random the {@link Random} object to use for randomize.
	 * @param <T> the component type of the array to randomize.
	 * @throws NullPointerException if the give array or the random object is
	 *         {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static <T> T[] shuffle(final T[] array, final Random random) {
		for (int j = array.length - 1; j > 0; --j) {
			swap(array, j, random.nextInt(j + 1));
		}

		return array;
	}

	/**
	 * Randomize the {@code array} using the given {@link Random} object. The used
	 * shuffling algorithm is from D. Knuth TAOCP, Seminumerical Algorithms,
	 * Third edition, page 142, Algorithm S (Selection sampling technique).
	 *
	 * @param array the {@code array} to randomize.
	 * @throws NullPointerException if the give array is {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static <T> MSeq<T> shuffle(final MSeq<T> array) {
		return shuffle(array, RandomRegistry.getRandom());
	}

	/**
	 * Randomize the {@code array} using the given {@link Random} object. The used
	 * shuffling algorithm is from D. Knuth TAOCP, Seminumerical Algorithms,
	 * Third edition, page 142, Algorithm S (Selection sampling technique).
	 *
	 * @param array the {@code array} to randomize.
	 * @param random the {@link Random} object to use for randomize.
	 * @param <T> the component type of the array to randomize.
	 * @throws NullPointerException if the give array or the random object is
	 *          {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static <T> MSeq<T> shuffle(final MSeq<T> array, final Random random) {
		for (int j = array.length() - 1; j > 0; --j) {
			array.swap(j, random.nextInt(j + 1));
		}

		return array;
	}

	/**
	 * Randomize the {@code list} using the given {@link Random} object. The used
	 * shuffling algorithm is from D. Knuth TAOCP, Seminumerical Algorithms,
	 * Third edition, page 142, Algorithm S (Selection sampling technique).
	 *
	 * @param list the {@code array} to randomize.
	 * @param <T> the component type of the array to randomize.
	 * @throws NullPointerException if the give list is {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static <T> void shuffle(final List<T> list) {
		shuffle(list, RandomRegistry.getRandom());
	}

	/**
	 * Randomize the {@code list} using the given {@link Random} object. The used
	 * shuffling algorithm is from D. Knuth TAOCP, Seminumerical Algorithms,
	 * Third edition, page 142, Algorithm S (Selection sampling technique).
	 *
	 * @param list the {@code array} to randomize.
	 * @param random the {@link Random} object to use for randomize.
	 * @param <T> the component type of the array to randomize.
	 * @throws NullPointerException if the give list or the random object is
	 *          {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static <T> void shuffle(final List<T> list, final Random random) {
		for (int j = list.size() - 1; j > 0; --j) {
			swap(list, j, random.nextInt(j + 1));
		}
	}

	/**
	 * Randomize the {@code array} using the given {@link Random} object. The used
	 * shuffling algorithm is from D. Knuth TAOCP, Seminumerical Algorithms,
	 * Third edition, page 142, Algorithm S (Selection sampling technique).
	 *
	 * @param array the {@code array} to randomize.
	 * @throws NullPointerException if the give array is {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static void shuffle(final int[] array) {
		shuffle(array, RandomRegistry.getRandom());
	}

	/**
	 * Randomize the {@code array} using the given {@link Random} object. The used
	 * shuffling algorithm is from D. Knuth TAOCP, Seminumerical Algorithms,
	 * Third edition, page 142, Algorithm S (Selection sampling technique).
	 *
	 * @param array the {@code array} to randomize.
	 * @param random the {@link Random} object to use for randomize.
	 * @throws NullPointerException if the give array or the random object is
	 *          {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static void shuffle(final int[] array, final Random random) {
		for (int j = array.length - 1; j > 0; --j) {
			swap(array, j, random.nextInt(j + 1));
		}
	}

	/**
	 * Reverses the part of the array determined by the to indexes.
	 *
	 * @param <T> the array type.
	 * @param array the array to reverse
	 * @param from the first index (inclusive)
	 * @param to the second index (exclusive)
	 * @throws IllegalArgumentException if <tt>from &gt; to</tt>
	 * @throws IndexOutOfBoundsException if <tt>from &lt; 0</tt> or
	 *          <tt>to &gt; a.length</tt>
	 * @throws NullPointerException if the give array is {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static <T> T[] reverse(final T[] array, final int from, final int to) {
		rangeCheck(array.length, from, to);

		int i = from;
		int j = to;
		while (i < j) {
			swap(array, i++, --j);
		}

		return array;
	}

	/**
	 * Reverses the given array in place.
	 *
	 * @param <T> the array type.
	 * @param array the array to reverse.
	 * @throws NullPointerException if the give array is {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static <T> T[] reverse(final T[] array) {
		return reverse(array, 0, array.length);
	}

	@Deprecated
	static void reverse(final byte[] array) {
		int i = 0;
		int j = array.length;
		while (i < j) {
			_swap(array, i++, --j);
		}
	}
	private static void _swap(final byte[] array, final int i, final int j) {
		final byte old = array[i];
		array[i] = array[j];
		array[j] = old;
	}

	private static void rangeCheck(int length, int from, int to) {
		if (from > to) {
			throw new IllegalArgumentException(
				"fromIndex(" + from + ") > toIndex(" + to+ ")"
			);
		}
		if (from < 0) {
			throw new ArrayIndexOutOfBoundsException(from);
		}
		if (to > length) {
			throw new ArrayIndexOutOfBoundsException(to);
		}
	}

	/**
	 * Return a array with the indexes of the partitions of an array with the
	 * given size. The length of the returned array is {@code min(size, prts) + 1}.
	 * <p/>
	 * Some examples:
	 * <pre>
	 * 	 partition(10, 3): [0, 3, 6, 10]
	 * 	 partition(15, 6): [0, 2, 4, 6, 9, 12, 15]
	 * 	 partition(5, 10): [0, 1, 2, 3, 4, 5]
	 * </pre>
	 *
	 * The following examples prints the start index (inclusive) and the end
	 * index (exclusive) of the {@code partition(15, 6)}.
	 * [code]
	 * int[] parts = partition(15, 6);
	 * for (int i = 0; i < parts.length - 1; ++i) {
	 *     System.out.println(i + ": " + parts[i] + "\t" + parts[i + 1]);
	 * }
	 * [/code]
	 * <pre>
	 * 	 0: 0 	2
	 * 	 1: 2 	4
	 * 	 2: 4 	6
	 * 	 3: 6 	9
	 * 	 4: 9 	12
	 * 	 5: 12	15
	 * </pre>
	 *
	 * This example shows how this can be used in an concurrent environment:
	 * [code]
	 * try (final Concurrency c = Concurrency.start()) {
	 *     final int[] parts = arrays.partition(population.size(), _maxThreads);
	 *
	 *     for (int i = 0; i < parts.length - 1; ++i) {
	 *         final int part = i;
	 *         c.execute(new Runnable() { @Override public void run() {
	 *             for (int j = parts[part + 1]; --j >= parts[part];) {
	 *                 population.get(j).evaluate();
	 *             }
	 *         }});
	 *     }
	 * }
	 * [/code]
	 *
	 * @param size the size of the array to partition.
	 * @param parts the number of parts the (virtual) array should be partitioned.
	 * @return the partition array with the length of {@code min(size, parts) + 1}.
	 * @throws IllegalArgumentException if {@code size} or {@code p} is less than one.
	 */
	public static int[] partition(final int size, final int parts) {
		if (size < 1) {
			throw new IllegalArgumentException(
				"Size must greater than zero: " + size
			);
		}
		if (parts < 1) {
			throw new IllegalArgumentException(
				"Number of partitions must greater than zero: " + parts
			);
		}

		final int pts = Math.min(size, parts);
		final int[] partition = new int[pts + 1];

		final int bulk = size/pts;
		final int rest = size%pts;
		assert ((bulk*pts + rest) == size);

		for (int i = 0, n = pts - rest; i < n; ++i) {
			partition[i] = i*bulk;
		}
		for (int i = 0, n = rest + 1; i < n; ++i) {
			partition[pts - rest + i] = (pts - rest)*bulk + i*(bulk + 1);
		}

		return partition;
	}

	/**
	 * Selects a random subset of size {@code k} from a set of size {@code n}.
	 *
	 * @see #subset(int, int[])
	 *
	 * @param n the size of the set.
	 * @param k the size of the subset.
	 * @throws IllegalArgumentException if {@code n < k}, {@code k == 0} or if
	 *          {@code n*k} will cause an integer overflow.
	 * @return the subset array.
	 *
	 * @deprecated Use {@link math#subset(int, int)} instead.
	 */
	@Deprecated
	public static int[] subset(final int n, final int k) {
		return math.subset(n, k);
	}

	/**
	 * Selects a random subset of size {@code k} from a set of size {@code n}.
	 *
	 * @see #subset(int, int[], Random)
	 *
	 * @param n the size of the set.
	 * @param k the size of the subset.
	 * @param random the random number generator used.
	 * @throws NullPointerException if {@code random} is {@code null}.
	 * @throws IllegalArgumentException if {@code n < k}, {@code k == 0} or if
	 *          {@code n*k} will cause an integer overflow.
	 * @return the subset array.
	 *
	 * @deprecated Use {@link math#subset(int, int, Random)} instead.
	 */
	@Deprecated
	public static int[] subset(final int n, final int k, final Random random) {
		return math.subset(n, k, random);
	}

	/**
	 * <p>
	 * Selects a random subset of size {@code sub.length} from a set of size
	 * {@code n}.
	 * </p>
	 *
	 * <p>
	 * <em>Authors:</em>
	 * 	 FORTRAN77 original version by Albert Nijenhuis, Herbert Wilf. This
	 * 	 version based on the  C++ version by John Burkardt.
	 * </p>
	 *
	 * <p><em><a href="https://people.scs.fsu.edu/~burkardt/c_src/subset/subset.html">
	 *  Reference:</a></em>
	 * 	 Albert Nijenhuis, Herbert Wilf,
	 * 	 Combinatorial Algorithms for Computers and Calculators,
	 * 	 Second Edition,
	 * 	 Academic Press, 1978,
	 * 	 ISBN: 0-12-519260-6,
	 * 	 LC: QA164.N54.
	 * </p>
	 *
	 * @param n the size of the set.
	 * @param sub the sub set array.
	 * @throws NullPointerException if {@code sub} is {@code null}.
	 * @throws IllegalArgumentException if {@code n < sub.length},
	 *          {@code sub.length == 0} or {@code n*sub.length} will cause an
	 *          integer overflow.
	 *
	 * @deprecated Use {@link math#subset(int, int[])} instead.
	 */
	@Deprecated
	public static void subset(final int n, final int sub[]) {
		math.subset(n, sub);
	}

	/**
	 * <p>
	 * Selects a random subset of size {@code sub.length} from a set of size
	 * {@code n}.
	 * </p>
	 *
	 * <p>
	 * <em>Authors:</em>
	 *      FORTRAN77 original version by Albert Nijenhuis, Herbert Wilf. This
	 *      version based on the  C++ version by John Burkardt.
	 * </p>
	 *
	 * <p><em><a href="https://people.scs.fsu.edu/~burkardt/c_src/subset/subset.html">
	 *  Reference:</a></em>
	 *      Albert Nijenhuis, Herbert Wilf,
	 *      Combinatorial Algorithms for Computers and Calculators,
	 *      Second Edition,
	 *      Academic Press, 1978,
	 *      ISBN: 0-12-519260-6,
	 *      LC: QA164.N54.
	 * </p>
	 *
	 * @param n the size of the set.
	 * @param sub the sub set array.
	 * @param random the random number generator used.
	 * @throws NullPointerException if {@code sub} or {@code random} is
	 *         {@code null}.
	 * @throws IllegalArgumentException if {@code n < sub.length},
	 *         {@code sub.length == 0} or {@code n*sub.length} will cause an
	 *         integer overflow.
	 *
	 * @deprecated Use {@link math#subset(int, int[], Random)} instead.
	 */
	@Deprecated
	public static int[] subset(final int n, final int sub[], final Random random) {
		return math.subset(n, sub, random);
	}


	/**
	 * Calculates a random permutation.
	 *
	 * @param p the permutation array.
	 * @throws NullPointerException if the permutation array is {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static int[] permutation(final int[] p) {
		return permutation(p, RandomRegistry.getRandom());
	}

	/**
	 * Calculates a random permutation.
	 *
	 * @param p the permutation array.
	 * @param random the random number generator.
	 * @throws NullPointerException if the permutation array or the random number
	 *          generator is {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static int[] permutation(final int[] p, final Random random) {
		requireNonNull(p, "Permutation array");
		requireNonNull(random, "Random");

		for (int i = 0; i < p.length; ++i) {
			p[i] = i;
		}
		shuffle(p, random);

		return p;
	}

	/**
	 * Calculates the permutation with the given {@code rank}.
	 *
	 * <p>
	 * <em>Authors:</em>
	 *      FORTRAN77 original version by Albert Nijenhuis, Herbert Wilf. This
	 *      version based on the  C++ version by John Burkardt.
	 * </p>
	 *
	 * <p><em><a href="https://people.scs.fsu.edu/~burkardt/c_src/subset/subset.html">
	 *  Reference:</a></em>
	 *      Albert Nijenhuis, Herbert Wilf,
	 *      Combinatorial Algorithms for Computers and Calculators,
	 *      Second Edition,
	 *      Academic Press, 1978,
	 *      ISBN: 0-12-519260-6,
	 *      LC: QA164.N54.
	 * </p>
	 *
	 * @param p the permutation array.
	 * @param rank the permutation rank.
	 * @throws NullPointerException it the permutation array is {@code null}.
	 * @throws IllegalArgumentException if {@code rank < 1}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static int[] permutation(final int[] p, final long rank) {
		requireNonNull(p, "Permutation array");
		if (rank < 1) {
			throw new IllegalArgumentException(format(
					"Rank smaler than 1: %s", rank
				));
		}

		Arrays.fill(p, 0);

		long jrank = rank - 1;
		for (int i = 1; i <= p.length; ++i) {
			int iprev = p.length + 1 - i;
			int irem = (int)(jrank%iprev);
			jrank = jrank/iprev;

			int j = 0;
			int jdir = 0;
			if ((jrank%2) == 1) {
				j = 0;
				jdir = 1;
			} else {
				j = p.length + 1;
				jdir = -1;
			}

			int icount = 0;
			do {
				j = j + jdir;

				if (p[j - 1] == 0) {
					++icount;
				}
			} while (irem >= icount);

			p[j - 1] = iprev;
		}

		return p;
	}

	/**
	 * Returns the index of the first occurrence of the specified element in
	 * the {@code array}, or -1 if the {@code array} does not contain the element.
	 * @param array the array to search.
	 * @param start the start index of the search.
	 * @param element the element to search for.
	 * @return the index of the first occurrence of the specified element in the
	 *          given {@code array}, of -1 if the {@code array} does not contain
	 *          the element.
	 * @throws NullPointerException if the given {@code array} is {@code null}.
	 * @throws IndexOutOfBoundsException for an illegal end point index value
	 *          (start < 0 || end > length || start > end)
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static int indexOf(
		final Object[] array, final int start, final int end,
		final Object element
	) {
		requireNonNull(array, "Array");
		if (start < 0 || end > array.length || start > end) {
			throw new IndexOutOfBoundsException(format(
				"Invalid index range: [%d, %s]", start, end
			));
		}

		int index = -1;
		if (element != null) {
			for (int i = start; i < end && index == -1; ++i) {
				if (element.equals(array[i])) {
					index = i;
				}
			}
		} else {
			for (int i = start; i < end && index == -1; ++i) {
				if (array[i] == null) {
					index = i;
				}
			}
		}

		return index;
	}


	/**
	 * Returns the index of the first occurrence of the specified element in
	 * the {@code array}, or -1 if the {@code array} does not contain the element.
	 * @param array the array to search.
	 * @param element the element to search for.
	 * @return the index of the first occurrence of the specified element in the
	 *          given {@code array}, of -1 if the {@code array} does not contain
	 *          the element.
	 * @throws NullPointerException if the given {@code array} is {@code null}.
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static int indexOf(final Object[] array, final Object element) {
		return indexOf(array, 0, array.length, element);
	}

	/**
	 * @see #indexOf(Object[], Object)
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static <T> int indexWhere(
		final T[] array,
		final Function<? super T, Boolean> predicate
	) {
		requireNonNull(array, "Array");
		requireNonNull(predicate, "Predicate");

		int index = -1;

		for (int i = 0; i < array.length && index == -1; ++i) {
			if (predicate.apply(array[i])) {
				index = i;
			}
		}

		return index;
	}

	/**
	 * @see #indexOf(Object[], Object)
	 *
	 * @deprecated Not used in the <i>Jenetics</i> library. Will be removed.
	 */
	@Deprecated
	public static <T> int indexWhere(
		final Iterable<? extends T> values,
		final Function<? super T, Boolean> predicate
	) {
		requireNonNull(values, "Array");
		requireNonNull(predicate, "Predicate");

		int index = -1;
		int i = 0;
		for (Iterator<? extends T>
			it = values.iterator(); it.hasNext() && index == -1; ++i)
		{
			if (predicate.apply(it.next())) {
				index = i;
			}
		}

		return index;
	}

	/**
	 * @deprecated Align the naming with the upcomming JDK 1.8 release. Use
	 *             {@link #forEach(Object[], Function)} instead.
	 */
	@Deprecated
	public static <T, R> void foreach(
		final T[] array,
		final Function<? super T, ? extends R> f
	) {
		forEach(array, f);
	}

	/**
	 * Iterates over all elements of the given {@code array} as long as the
	 * {@code predicate} returns {@code true} (which means <i>continue</i>) and
	 * returns the index the iteration has been interrupted. -1 is returned if
	 * all elements were visited.
	 * <p/>
	 * Can be used to check all array elements for nullness.
	 *
	 * [code]
	 * public void foo(final Integer[] values) {
	 *     arrays.forEach(values, new Validator.NonNull());
	 *     ...
	 * }
	 * [/code]
	 *
	 * @param array the array to iterate.
	 * @param f the function to apply to every element.
	 * @throws NullPointerException if one of the elements are {@code null}.
	 */
	public static <T, R> void forEach(
		final T[] array,
		final Function<? super T, ? extends R> f
	) {
		requireNonNull(array, "Array");
		requireNonNull(f, "Predicate");

		for (int i = 0; i < array.length; ++i) {
			f.apply(array[i]);
		}
	}

	/**
	 * @deprecated Align the naming with the upcoming JDK 1.8 release. Use
	 *             {@link #forEach(Iterable, Function)} instead.
	 */
	@Deprecated
	public static <T, R> void foreach(
		final Iterable<? extends T> values,
		final Function<? super T, ? extends R> f
	) {
		forEach(values, f);
	}

	/**
	 * Iterates over all elements of the given {@code values}
	 *
	 * @param values the values to iterate.
	 * @param f the function to apply to each element.
	 * @throws NullPointerException if one of the elements are {@code null}.
	 */
	public static <T, R> void forEach(
		final Iterable<? extends T> values,
		final Function<? super T, ? extends R> f
	) {
		requireNonNull(values, "Array");
		requireNonNull(f, "Function");

		for (final T value : values) {
			f.apply(value);
		}
	}


	/**
	 * Map the array from type A to an other array of type B.
	 *
	 * @param <A> the source type.
	 * @param <B> the target type.
	 * @param a the source array.
	 * @param b the target array. If the given array is to short a new array
	 *        with the right size is created, mapped and returned. If the given
	 *        array is long enough <i>this</i> array is returned.
	 * @param converter the converter needed for mapping from type A to type B.
	 * @return the mapped array. If {@code b} is long enough {@code b} is
	 *         returned otherwise a new created array.
	 * @throws NullPointerException if one of the arguments is {@code null}.
	 */
	public static <A, B> B[] map(
		final A[] a,
		final B[] b,
		final Function<? super A, ? extends B> converter
	) {
		requireNonNull(a, "Source array");
		requireNonNull(b, "Target array");
		requireNonNull(converter, "Converter");

		B[] result = b;
		if (b.length < a.length) {
			@SuppressWarnings("unchecked")
			final B[] r = (B[])java.lang.reflect.Array.newInstance(
				b.getClass().getComponentType(), a.length
			);
			result = r;
		}

		for (int i = 0; i < result.length; ++i) {
			result[i] = converter.apply(a[i]);
		}

		return result;
	}

}