/******************************************************************************* * SAT4J: a SATisfiability library for Java Copyright (C) 2004-2008 Daniel Le Berre * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Alternatively, the contents of this file may be used under the terms of * either the GNU Lesser General Public License Version 2.1 or later (the * "LGPL"), in which case the provisions of the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of the LGPL, and not to allow others to use your version of * this file under the terms of the EPL, indicate your decision by deleting * the provisions above and replace them with the notice and other provisions * required by the LGPL. If you do not delete the provisions above, a recipient * may use your version of this file under the terms of the EPL or the LGPL. * * Based on the original MiniSat specification from: * * An extensible SAT solver. Niklas Een and Niklas Sorensson. Proceedings of the * Sixth International Conference on Theory and Applications of Satisfiability * Testing, LNCS 2919, pp 502-518, 2003. * * See www.minisat.se for the original solver in C++. * *******************************************************************************/ package org.sat4j.core; import java.util.Arrays; import java.util.Comparator; import java.util.Iterator; import java.util.NoSuchElementException; import org.sat4j.specs.IVec; /** * Simple but efficient vector implementation, based on the vector * implementation available in MiniSAT. Note that the elements are compared * using their references, not using the equals method. * * @author leberre */ public final class Vec<T> implements IVec<T> { // MiniSat -- Copyright (c) 2003-2005, Niklas Een, Niklas Sorensson // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. private static final long serialVersionUID = 1L; /** * Create a Vector with an initial capacity of 5 elements. */ public Vec() { this(5); } /** * Adapter method to translate an array of int into an IVec. * * The array is used inside the Vec, so the elements may be modified outside * the Vec. But it should not take much memory. The size of the created Vec * is the length of the array. * * @param elts * a filled array of T. */ public Vec(T[] elts) { // DLB findbugs ok myarray = elts; nbelem = elts.length; } /** * Create a Vector with a given capacity. * * @param size * the capacity of the vector. */ @SuppressWarnings("unchecked") public Vec(int size) { myarray = (T[]) new Object[size]; } /** * Construit un vecteur contenant de taille size rempli a l'aide de size * pad. * * @param size * la taille du vecteur * @param pad * l'objet servant a remplir le vecteur */ @SuppressWarnings("unchecked") public Vec(int size, T pad) { myarray = (T[]) new Object[size]; for (int i = 0; i < size; i++) { myarray[i] = pad; } nbelem = size; } public int size() { return nbelem; } /** * Remove nofelems from the Vector. It is assumed that the number of * elements to remove is smaller or equals to the current number of elements * in the vector * * @param nofelems * the number of elements to remove. */ public void shrink(int nofelems) { // assert nofelems <= nbelem; while (nofelems-- > 0) { myarray[--nbelem] = null; } } /** * reduce the Vector to exactly newsize elements * * @param newsize * the new size of the vector. */ public void shrinkTo(final int newsize) { // assert newsize <= size(); for (int i = nbelem; i > newsize; i--) { myarray[i - 1] = null; } nbelem = newsize; // assert size() == newsize; } /** * Pop the last element on the stack. It is assumed that the stack is not * empty! */ public void pop() { // assert size() > 0; myarray[--nbelem] = null; } public void growTo(final int newsize, final T pad) { // assert newsize >= size(); ensure(newsize); for (int i = nbelem; i < newsize; i++) { myarray[i] = pad; } nbelem = newsize; } @SuppressWarnings("unchecked") public void ensure(final int nsize) { if (nsize >= myarray.length) { T[] narray = (T[]) new Object[Math.max(nsize, nbelem * 2)]; System.arraycopy(myarray, 0, narray, 0, nbelem); myarray = narray; } } public IVec<T> push(final T elem) { ensure(nbelem + 1); myarray[nbelem++] = elem; return this; } public void unsafePush(final T elem) { myarray[nbelem++] = elem; } /** * Insert an element at the very begining of the vector. The former first * element is appended to the end of the vector in order to have a constant * time operation. * * @param elem * the element to put first in the vector. */ public void insertFirst(final T elem) { if (nbelem > 0) { push(myarray[0]); myarray[0] = elem; return; } push(elem); } public void insertFirstWithShifting(final T elem) { if (nbelem > 0) { ensure(nbelem + 1); for (int i = nbelem; i > 0; i--) { myarray[i] = myarray[i - 1]; } myarray[0] = elem; nbelem++; return; } push(elem); } public void clear() { Arrays.fill(myarray, 0, nbelem, null); nbelem = 0; } /** * return the latest element on the stack. It is assumed that the stack is * not empty! * * @return the last element on the stack (the one on the top) */ public T last() { // assert size() != 0; return myarray[nbelem - 1]; } public T get(final int index) { return myarray[index]; } public void set(int index, T elem) { myarray[index] = elem; } /** * Remove an element that belongs to the Vector. The method will break if * the element does not belong to the vector. * * @param elem * an element from the vector. */ public void remove(T elem) { // assert size() > 0; int j = 0; for (; myarray[j] != elem; j++) { assert j < size(); } // arraycopy is always faster than manual copy System.arraycopy(myarray, j + 1, myarray, j, size() - j - 1); myarray[--nbelem] = null; } /** * Delete the ith element of the vector. The latest element of the vector * replaces the removed element at the ith indexer. * * @param index * the indexer of the element in the vector * @return the former ith element of the vector that is now removed from the * vector */ public T delete(int index) { // assert index >= 0 && index < nbelem; T ith = myarray[index]; myarray[index] = myarray[--nbelem]; myarray[nbelem] = null; return ith; } /** * Ces operations devraient se faire en temps constant. Ce n'est pas le cas * ici. * * @param copy */ public void copyTo(IVec<T> copy) { final Vec<T> ncopy = (Vec<T>) copy; final int nsize = nbelem + ncopy.nbelem; copy.ensure(nsize); System.arraycopy(myarray, 0, ncopy.myarray, ncopy.nbelem, nbelem); ncopy.nbelem = nsize; } /** * @param dest */ public <E> void copyTo(E[] dest) { // assert dest.length >= nbelem; System.arraycopy(myarray, 0, dest, 0, nbelem); } /* * Copy one vector to another (cleaning the first), in constant time. */ public void moveTo(IVec<T> dest) { copyTo(dest); clear(); } public void moveTo(int dest, int source) { if (dest != source) { myarray[dest] = myarray[source]; myarray[source] = null; } } public T[] toArray() { // DLB findbugs ok return myarray; } private int nbelem; private T[] myarray; /* * (non-Javadoc) * * @see java.lang.Object#toString() */ @Override public String toString() { StringBuffer stb = new StringBuffer(); for (int i = 0; i < nbelem - 1; i++) { stb.append(myarray[i]); stb.append(","); //$NON-NLS-1$ } if (nbelem > 0) { stb.append(myarray[nbelem - 1]); } return stb.toString(); } void selectionSort(int from, int to, Comparator<T> cmp) { int i, j, best_i; T tmp; for (i = from; i < to - 1; i++) { best_i = i; for (j = i + 1; j < to; j++) { if (cmp.compare(myarray[j], myarray[best_i]) < 0) best_i = j; } tmp = myarray[i]; myarray[i] = myarray[best_i]; myarray[best_i] = tmp; } } void sort(int from, int to, Comparator<T> cmp) { int width = to - from; if (width <= 15) selectionSort(from, to, cmp); else { T pivot = myarray[width / 2 + from]; T tmp; int i = from - 1; int j = to; for (;;) { do i++; while (cmp.compare(myarray[i], pivot) < 0); do j--; while (cmp.compare(pivot, myarray[j]) < 0); if (i >= j) break; tmp = myarray[i]; myarray[i] = myarray[j]; myarray[j] = tmp; } sort(from, i, cmp); sort(i, to, cmp); } } /** * @param comparator */ public void sort(Comparator<T> comparator) { sort(0, nbelem, comparator); } public void sortUnique(Comparator<T> cmp) { int i, j; T last; if (nbelem == 0) return; sort(0, nbelem, cmp); i = 1; last = myarray[0]; for (j = 1; j < nbelem; j++) { if (cmp.compare(last, myarray[j]) < 0) { last = myarray[i] = myarray[j]; i++; } } nbelem = i; } /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj instanceof IVec) { IVec<?> v = (IVec<?>) obj; if (v.size() != size()) return false; for (int i = 0; i < size(); i++) { if (!v.get(i).equals(get(i))) { return false; } } return true; } return false; } /* * (non-Javadoc) * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { int sum = 0; for (int i = 0; i < nbelem; i++) { sum += myarray[i].hashCode() / nbelem; } return sum; } public Iterator<T> iterator() { return new Iterator<T>() { private int i = 0; public boolean hasNext() { return i < nbelem; } public T next() { if (i == nbelem) throw new NoSuchElementException(); return myarray[i++]; } public void remove() { throw new UnsupportedOperationException(); } }; } public boolean isEmpty() { return nbelem == 0; } }