/* Imported from Mahout. */package org.carrot2.mahout.math.list; import org.carrot2.mahout.math.function.DoubleProcedure; public class DoubleArrayList extends AbstractDoubleList implements Cloneable { private double[] elements; public DoubleArrayList() { this(10); } public DoubleArrayList(double[] elements) { elements(elements); } public DoubleArrayList(int initialCapacity) { this(new double[initialCapacity]); setSizeRaw(0); } public void add(double element) { // overridden for performance only. if (size == elements.length) { ensureCapacity(size + 1); } elements[size++] = element; } public void beforeInsert(int index, double element) { // overridden for performance only. if (size == index) { add(element); return; } if (index > size || index < 0) { throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); } ensureCapacity(size + 1); System.arraycopy(elements, index, elements, index + 1, size - index); elements[index] = element; size++; } @Override public int binarySearchFromTo(double key, int from, int to) { return org.carrot2.mahout.math.Sorting.binarySearchFromTo(elements, key, from, to); } @Override public Object clone() { // overridden for performance only. DoubleArrayList clone = new DoubleArrayList(elements.clone()); clone.setSizeRaw(size); return clone; } public DoubleArrayList copy() { return (DoubleArrayList) clone(); } public double[] elements() { return elements; } public AbstractDoubleList elements(double[] elements) { this.elements = elements; this.size = elements.length; return this; } public void ensureCapacity(int minCapacity) { elements = org.carrot2.mahout.math.Arrays.ensureCapacity(elements, minCapacity); } public boolean equals(Object otherObj) { //delta if (otherObj == null) { return false; } // overridden for performance only. if (!(otherObj instanceof DoubleArrayList)) { return super.equals(otherObj); } if (this == otherObj) { return true; } DoubleArrayList other = (DoubleArrayList) otherObj; if (size() != other.size()) { return false; } double[] theElements = elements(); double[] otherElements = other.elements(); for (int i = size(); --i >= 0;) { if (theElements[i] != otherElements[i]) { return false; } } return true; } public boolean forEach(DoubleProcedure procedure) { // overridden for performance only. double[] theElements = elements; int theSize = size; for (int i = 0; i < theSize;) { if (!procedure.apply(theElements[i++])) { return false; } } return true; } public double get(int index) { // overridden for performance only. if (index >= size || index < 0) { throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); } return elements[index]; } @Override public double getQuick(int index) { return elements[index]; } @Override public int indexOfFromTo(double element, int from, int to) { // overridden for performance only. if (size == 0) { return -1; } checkRangeFromTo(from, to, size); double[] theElements = elements; for (int i = from; i <= to; i++) { if (element == theElements[i]) { return i; } //found } return -1; //not found } @Override public int lastIndexOfFromTo(double element, int from, int to) { // overridden for performance only. if (size == 0) { return -1; } checkRangeFromTo(from, to, size); double[] theElements = elements; for (int i = to; i >= from; i--) { if (element == theElements[i]) { return i; } //found } return -1; //not found } @Override public AbstractDoubleList partFromTo(int from, int to) { if (size == 0) { return new DoubleArrayList(0); } checkRangeFromTo(from, to, size); double[] part = new double[to - from + 1]; System.arraycopy(elements, from, part, 0, to - from + 1); return new DoubleArrayList(part); } @Override public boolean removeAll(AbstractDoubleList other) { // overridden for performance only. if (!(other instanceof DoubleArrayList)) { return super.removeAll(other); } /* There are two possibilities to do the thing a) use other.indexOf(...) b) sort other, then use other.binarySearch(...) Let's try to figure out which one is faster. Let M=size, N=other.size, then a) takes O(M*N) steps b) takes O(N*logN + M*logN) steps (sorting is O(N*logN) and binarySearch is O(logN)) Hence, if N*logN + M*logN < M*N, we use b) otherwise we use a). */ if (other.isEmpty()) { return false; } //nothing to do int limit = other.size() - 1; int j = 0; double[] theElements = elements; int mySize = size(); double N = (double) other.size(); double M = (double) mySize; if ((N + M) * org.carrot2.mahout.collections.Arithmetic.log2(N) < M * N) { // it is faster to sort other before searching in it DoubleArrayList sortedList = (DoubleArrayList) other.clone(); sortedList.quickSort(); for (int i = 0; i < mySize; i++) { if (sortedList.binarySearchFromTo(theElements[i], 0, limit) < 0) { theElements[j++] = theElements[i]; } } } else { // it is faster to search in other without sorting for (int i = 0; i < mySize; i++) { if (other.indexOfFromTo(theElements[i], 0, limit) < 0) { theElements[j++] = theElements[i]; } } } boolean modified = (j != mySize); setSize(j); return modified; } @Override public void replaceFromToWithFrom(int from, int to, AbstractDoubleList other, int otherFrom) { // overridden for performance only. if (!(other instanceof DoubleArrayList)) { // slower super.replaceFromToWithFrom(from, to, other, otherFrom); return; } int length = to - from + 1; if (length > 0) { checkRangeFromTo(from, to, size()); checkRangeFromTo(otherFrom, otherFrom + length - 1, other.size()); System.arraycopy(((DoubleArrayList) other).elements, otherFrom, elements, from, length); } } @Override public boolean retainAll(AbstractDoubleList other) { // overridden for performance only. if (!(other instanceof DoubleArrayList)) { return super.retainAll(other); } /* There are two possibilities to do the thing a) use other.indexOf(...) b) sort other, then use other.binarySearch(...) Let's try to figure out which one is faster. Let M=size, N=other.size, then a) takes O(M*N) steps b) takes O(N*logN + M*logN) steps (sorting is O(N*logN) and binarySearch is O(logN)) Hence, if N*logN + M*logN < M*N, we use b) otherwise we use a). */ int limit = other.size() - 1; int j = 0; double[] theElements = elements; int mySize = size(); double N = (double) other.size(); double M = (double) mySize; if ((N + M) * org.carrot2.mahout.collections.Arithmetic.log2(N) < M * N) { // it is faster to sort other before searching in it DoubleArrayList sortedList = (DoubleArrayList) other.clone(); sortedList.quickSort(); for (int i = 0; i < mySize; i++) { if (sortedList.binarySearchFromTo(theElements[i], 0, limit) >= 0) { theElements[j++] = theElements[i]; } } } else { // it is faster to search in other without sorting for (int i = 0; i < mySize; i++) { if (other.indexOfFromTo(theElements[i], 0, limit) >= 0) { theElements[j++] = theElements[i]; } } } boolean modified = (j != mySize); setSize(j); return modified; } @Override public void reverse() { // overridden for performance only. int limit = size / 2; int j = size - 1; double[] theElements = elements; for (int i = 0; i < limit;) { //swap double tmp = theElements[i]; theElements[i++] = theElements[j]; theElements[j--] = tmp; } } @Override public void set(int index, double element) { // overridden for performance only. if (index >= size || index < 0) { throw new IndexOutOfBoundsException("Index: " + index + ", Size: " + size); } elements[index] = element; } @Override public void setQuick(int index, double element) { elements[index] = element; } @Override public void sortFromTo(int from, int to) { /* * Computes min and max and decides on this basis. * In practice the additional overhead is very small compared to the potential gains. */ if (size == 0) { return; } checkRangeFromTo(from, to, size); // determine minimum and maximum. double min = elements[from]; double max = elements[from]; double[] theElements = elements; for (int i = from + 1; i <= to;) { double elem = theElements[i++]; if (elem > max) { max = elem; } else if (elem < min) { min = elem; } } quickSortFromTo(from, to); } @Override public void trimToSize() { elements = org.carrot2.mahout.math.Arrays.trimToCapacity(elements, size()); } }