/*
|
* Java port of Bullet (c) 2008 Martin Dvorak <jezek2@advel.cz>
|
*
|
* Bullet Continuous Collision Detection and Physics Library
|
* Copyright (c) 2003-2008 Erwin Coumans http://www.bulletphysics.com/
|
*
|
* This software is provided 'as-is', without any express or implied warranty.
|
* In no event will the authors be held liable for any damages arising from
|
* the use of this software.
|
*
|
* Permission is granted to anyone to use this software for any purpose,
|
* including commercial applications, and to alter it and redistribute it
|
* freely, subject to the following restrictions:
|
*
|
* 1. The origin of this software must not be misrepresented; you must not
|
* claim that you wrote the original software. If you use this software
|
* in a product, an acknowledgment in the product documentation would be
|
* appreciated but is not required.
|
* 2. Altered source versions must be plainly marked as such, and must not be
|
* misrepresented as being the original software.
|
* 3. This notice may not be removed or altered from any source distribution.
|
*/
|
|
package com.bulletphysics.linearmath;
|
|
import java.util.Comparator;
|
import com.bulletphysics.util.FloatArrayList;
|
import com.bulletphysics.util.IntArrayList;
|
import com.bulletphysics.util.ObjectArrayList;
|
|
/**
|
* Miscellaneous utility functions.
|
*
|
* @author jezek2
|
*/
|
public class MiscUtil {
|
|
public static int getListCapacityForHash(ObjectArrayList<?> list) {
|
return getListCapacityForHash(list.size());
|
}
|
|
public static int getListCapacityForHash(int size) {
|
int n = 2;
|
while (n < size) {
|
n <<= 1;
|
}
|
return n;
|
}
|
|
/**
|
* Ensures valid index in provided list by filling list with provided values
|
* until the index is valid.
|
*/
|
public static <T> void ensureIndex(ObjectArrayList<T> list, int index, T value) {
|
while (list.size() <= index) {
|
list.add(value);
|
}
|
}
|
|
/**
|
* Resizes list to exact size, filling with given value when expanding.
|
*/
|
public static void resize(IntArrayList list, int size, int value) {
|
while (list.size() < size) {
|
list.add(value);
|
}
|
|
while (list.size() > size) {
|
list.remove(list.size() - 1);
|
}
|
}
|
|
/**
|
* Resizes list to exact size, filling with given value when expanding.
|
*/
|
public static void resize(FloatArrayList list, int size, float value) {
|
while (list.size() < size) {
|
list.add(value);
|
}
|
|
while (list.size() > size) {
|
list.remove(list.size() - 1);
|
}
|
}
|
|
/**
|
* Resizes list to exact size, filling with new instances of given class type
|
* when expanding.
|
*/
|
public static <T> void resize(ObjectArrayList<T> list, int size, Class<T> valueCls) {
|
try {
|
while (list.size() < size) {
|
list.add(valueCls != null? valueCls.newInstance() : null);
|
}
|
|
while (list.size() > size) {
|
list.removeQuick(list.size() - 1);
|
}
|
}
|
catch (IllegalAccessException e) {
|
throw new IllegalStateException(e);
|
}
|
catch (InstantiationException e) {
|
throw new IllegalStateException(e);
|
}
|
}
|
|
/**
|
* Searches object in array.
|
*
|
* @return first index of match, or -1 when not found
|
*/
|
public static <T> int indexOf(T[] array, T obj) {
|
for (int i=0; i<array.length; i++) {
|
if (array[i] == obj) return i;
|
}
|
return -1;
|
}
|
|
public static float GEN_clamped(float a, float lb, float ub) {
|
return a < lb ? lb : (ub < a ? ub : a);
|
}
|
|
private static <T> void downHeap(ObjectArrayList<T> pArr, int k, int n, Comparator<T> comparator) {
|
/* PRE: a[k+1..N] is a heap */
|
/* POST: a[k..N] is a heap */
|
|
T temp = pArr.getQuick(k - 1);
|
/* k has child(s) */
|
while (k <= n / 2) {
|
int child = 2 * k;
|
|
if ((child < n) && comparator.compare(pArr.getQuick(child - 1), pArr.getQuick(child)) < 0) {
|
child++;
|
}
|
/* pick larger child */
|
if (comparator.compare(temp, pArr.getQuick(child - 1)) < 0) {
|
/* move child up */
|
pArr.setQuick(k - 1, pArr.getQuick(child - 1));
|
k = child;
|
}
|
else {
|
break;
|
}
|
}
|
pArr.setQuick(k - 1, temp);
|
}
|
|
/**
|
* Sorts list using heap sort.<p>
|
*
|
* Implementation from: http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Sort/Heap/
|
*/
|
public static <T> void heapSort(ObjectArrayList<T> list, Comparator<T> comparator) {
|
/* sort a[0..N-1], N.B. 0 to N-1 */
|
int k;
|
int n = list.size();
|
for (k = n / 2; k > 0; k--) {
|
downHeap(list, k, n, comparator);
|
}
|
|
/* a[1..N] is now a heap */
|
while (n >= 1) {
|
swap(list, 0, n - 1); /* largest of a[0..n-1] */
|
|
n = n - 1;
|
/* restore a[1..i-1] heap */
|
downHeap(list, 1, n, comparator);
|
}
|
}
|
|
private static <T> void swap(ObjectArrayList<T> list, int index0, int index1) {
|
T temp = list.getQuick(index0);
|
list.setQuick(index0, list.getQuick(index1));
|
list.setQuick(index1, temp);
|
}
|
|
/**
|
* Sorts list using quick sort.<p>
|
*/
|
public static <T> void quickSort(ObjectArrayList<T> list, Comparator<T> comparator) {
|
// don't sort 0 or 1 elements
|
if (list.size() > 1) {
|
quickSortInternal(list, comparator, 0, list.size() - 1);
|
}
|
}
|
|
private static <T> void quickSortInternal(ObjectArrayList<T> list, Comparator<T> comparator, int lo, int hi) {
|
// lo is the lower index, hi is the upper index
|
// of the region of array a that is to be sorted
|
int i = lo, j = hi;
|
T x = list.getQuick((lo + hi) / 2);
|
|
// partition
|
do {
|
while (comparator.compare(list.getQuick(i), x) < 0) i++;
|
while (comparator.compare(x, list.getQuick(j)) < 0) j--;
|
|
if (i <= j) {
|
swap(list, i, j);
|
i++;
|
j--;
|
}
|
}
|
while (i <= j);
|
|
// recursion
|
if (lo < j) {
|
quickSortInternal(list, comparator, lo, j);
|
}
|
if (i < hi) {
|
quickSortInternal(list, comparator, i, hi);
|
}
|
}
|
|
}
|