org.ddogleg.struct.DogArray_B Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ddogleg Show documentation
Show all versions of ddogleg Show documentation
DDogleg Numerics is a high performance Java library for non-linear optimization, robust model fitting, polynomial root finding, sorting, and more.
The newest version!
/*
* Copyright (c) 2012-2024, Peter Abeles. All Rights Reserved.
*
* This file is part of DDogleg (http://ddogleg.org).
*
* 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.
*/
package org.ddogleg.struct;
import java.util.Arrays;
import java.util.Random;
/**
* Growable array composed of booleans.
*
* @author Peter Abeles
*/
public class DogArray_B implements DogArrayPrimitive {
public boolean[] data;
public int size;
public DogArray_B( int reserve ) {
data = new boolean[reserve];
this.size = 0;
}
public DogArray_B() {
this(10);
}
/**
* Creates a queue with the specified length as its size filled with false
*/
public static DogArray_B zeros( int length ) {
DogArray_B out = new DogArray_B(length);
out.size = length;
return out;
}
public static DogArray_B array( boolean... values ) {
DogArray_B out = zeros(values.length);
for (int i = 0; i < values.length; i++) {
out.data[i] = values[i];
}
return out;
}
/**
* Non-zero values are set to true
*/
public static DogArray_B array( int... values ) {
DogArray_B out = zeros(values.length);
for (int i = 0; i < values.length; i++) {
out.data[i] = values[i] != 0;
}
return out;
}
/**
* Counts the number of times the specified value occurs in the list
*/
public int count( boolean value ) {
int total = 0;
for (int i = 0; i < size; i++) {
if (data[i] == value)
total++;
}
return total;
}
/**
* Sees is the primitive array is equal to the values in this array
*
* @param values primitive array
* @return true if equal or false if not
*/
public boolean isEquals( int... values ) {
if (size != values.length)
return false;
for (int i = 0; i < size; i++) {
boolean v = values[i] != 0;
if (data[i] != v)
return false;
}
return true;
}
public boolean isEquals( boolean... values ) {
if (size != values.length)
return false;
for (int i = 0; i < size; i++) {
if (data[i] != values[i])
return false;
}
return true;
}
public boolean isEquals( DogArray_B values ) {
if (size != values.size)
return false;
for (int i = 0; i < size; i++) {
if (data[i] != values.data[i])
return false;
}
return true;
}
@Override
public DogArray_B reset() {
size = 0;
return this;
}
public void addAll( DogArray_B queue ) {
if (size + queue.size > data.length) {
boolean[] temp = new boolean[(size + queue.size)*2];
System.arraycopy(data, 0, temp, 0, size);
data = temp;
}
System.arraycopy(queue.data, 0, data, size, queue.size);
size += queue.size;
}
public void addAll( boolean[] array, int startIndex, int endIndex ) {
if (endIndex > array.length)
throw new IndexOutOfBoundsException("endIndex is larger than input array. " + endIndex + " > " + array.length);
int arraySize = endIndex - startIndex;
if (size + arraySize > data.length) {
boolean[] temp = new boolean[(size + arraySize)*2];
System.arraycopy(data, 0, temp, 0, size);
data = temp;
}
System.arraycopy(array, startIndex, data, size, arraySize);
size += arraySize;
}
public void add( boolean val ) {
push(val);
}
public void push( boolean val ) {
if (size == data.length) {
boolean[] temp;
try {
temp = new boolean[size*2 + 5];
} catch (OutOfMemoryError e) {
System.gc();
temp = new boolean[3*size/2];
}
System.arraycopy(data, 0, temp, 0, size);
data = temp;
}
data[size++] = val;
}
/**
* Sets this array to be equal to the array segment
*
* @param array (Input) source array
* @param offset first index
* @param length number of elements to copy
*/
public DogArray_B setTo( boolean[] array, int offset, int length ) {
resize(length);
System.arraycopy(array, offset, data, 0, length);
return this;
}
/**
* Set's the value of this array to the passed in raw array.
*
* @param src (Input) The input array
* @return A reference to "this" to allow chaining of commands
*/
public DogArray_B setTo( boolean... src ) {
setTo(src, 0, src.length);
return this;
}
/**
* Creates a new primitive array which is a copy.
*/
public boolean[] toArray() {
boolean[] out = new boolean[size];
System.arraycopy(data, 0, out, 0, size);
return out;
}
public void remove( int index ) {
for (int i = index + 1; i < size; i++) {
data[i - 1] = data[i];
}
size--;
}
/**
* Removes elements from the list starting at 'first' and ending at 'last'
*
* @param first First index you wish to remove. Inclusive.
* @param last Last index you wish to remove. Inclusive.
*/
public void remove( int first, int last ) {
if (last < first)
throw new IllegalArgumentException("first <= last. first=" + first + " last=" + last);
if (last >= size)
throw new IndexOutOfBoundsException("last=" + last + " >= size=" + size);
int delta = last - first + 1;
for (int i = last + 1; i < size; i++) {
data[i - delta] = data[i];
}
size -= delta;
}
/**
* Inserts the value at the specified index and shifts all the other values down.
*/
public void insert( int index, boolean value ) {
if (size == data.length) {
boolean[] temp = new boolean[size*2 + 5];
System.arraycopy(data, 0, temp, 0, index);
temp[index] = value;
System.arraycopy(data, index, temp, index + 1, size - index);
this.data = temp;
size++;
} else {
size++;
for (int i = size - 1; i > index; i--) {
data[i] = data[i - 1];
}
data[index] = value;
}
}
/**
* Removes the specified index from the array by swapping it with last element. Does not preserve order
* but has a runtime of O(1).
*
* @param index The index to be removed.
* @return The removed object
*/
public boolean removeSwap( int index ) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("index=" + index + " max size " + size);
boolean ret = data[index];
size -= 1;
data[index] = data[size];
return ret;
}
public boolean removeTail() {
if (size > 0) {
size--;
return data[size];
} else {
throw new RuntimeException("Size zero, no tail");
}
}
public boolean get( int index ) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("index = " + index + " size = " + size);
return data[index];
}
/**
* Copies a sequence of values into the specified array
*
* @param offset First index it will read from
* @param dst Array it will copy the values into
* @param dstOffset First index in dst array that it will write to
* @param length Number of elements it will copy
*/
public void get( int offset, boolean[] dst, int dstOffset, int length ) {
if (offset < 0 || offset + length > size)
throw new IndexOutOfBoundsException("range is out of bounds");
System.arraycopy(data, offset, dst, dstOffset, length);
}
public boolean getTail() {
if (size == 0)
throw new IndexOutOfBoundsException("Array is empty");
return data[size - 1];
}
/**
* Returns an element starting from the end of the list. 0 = size -1
*/
public boolean getTail( int index ) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("index = " + index + " size = " + size);
return data[size - index - 1];
}
public void setTail( int index, boolean value ) {
if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("index = " + index + " size = " + size);
data[size - index - 1] = value;
}
public boolean unsafe_get( int index ) {
return data[index];
}
public void set( int index, boolean value ) {
data[index] = value;
}
@Override public DogArray_B setTo( DogArray_B original ) {
resize(original.size);
System.arraycopy(original.data, 0, data, 0, size());
return this;
}
@Override public DogArray_B resize( int size ) {
reserve(size);
this.size = size;
return this;
}
/**
* Resizes the array and assigns the default value to every new element.
*
* @param size New size
* @param value Default value
*/
public DogArray_B resize( int size, boolean value ) {
int priorSize = this.size;
resize(size);
if (priorSize >= size)
return this;
fill(priorSize, size, value);
return this;
}
/**
* Convenience function that will first call {@link #reset} then {@link #resize(int, boolean)}, ensuring
* that every element in the array will have the specified value
*
* @param size New size
* @param value New value of every element
*/
@Deprecated
public void resetResize( int size, boolean value ) {
reset();
resize(size, value);
}
/**
* Resizes and assigns the new elements (if any) to the value specified by the lambda
*
* @param size New sie
* @param op Assigns default values
*/
public DogArray_B resize( int size, DogLambdas.AssignIdx_B op ) {
int priorSize = this.size;
resize(size);
for (int i = priorSize; i < size; i++) {
data[i] = op.assign(i);
}
return this;
}
public void fill( boolean value ) {
Arrays.fill(data, 0, size, value);
}
public void fill( int idx0, int idx1, boolean value ) {
Arrays.fill(data, idx0, idx1, value);
}
public boolean contains( boolean value ) {
for (int i = 0; i < size; i++) {
if (data[i] == value)
return true;
}
return false;
}
@Override public void extend( int size ) {
reserve(size);
this.size = size;
}
@SuppressWarnings("NullAway")
@Override public DogArray_B reserve( int amount ) {
if (data.length >= amount)
return this;
if (size == 0) {
// In this special case we can dereference the old array and this might allow the GC to free up memory
// before declaring the new array. Could be useful if the arrays are very large.
this.data = null;
this.data = new boolean[amount];
} else {
boolean[] tmp = new boolean[amount];
System.arraycopy(data, 0, tmp, 0, this.size);
data = tmp;
}
return this;
}
@Override public int size() {
return size;
}
@Override public void zero() {
Arrays.fill(data, 0, size, false);
}
@Override public DogArray_B copy() {
var ret = new DogArray_B(size);
ret.setTo(this);
return ret;
}
@Override public void flip() {
if (size <= 1)
return;
int D = size/2;
for (int i = 0, j = size - 1; i < D; i++, j--) {
boolean tmp = data[i];
data[i] = data[j];
data[j] = tmp;
}
}
public boolean pop() {
return data[--size];
}
/**
* Returns the index of the first element with the specified 'value'. return -1 if it wasn't found
*
* @param value Value to search for
* @return index or -1 if it's not in the list
*/
public int indexOf( boolean value ) {
for (int i = 0; i < size; i++) {
if (data[i] == value)
return i;
}
return -1;
}
@Override public void sort() {
throw new RuntimeException("Undefined for boolean");
}
/** Shuffle elements by randomly swapping them */
public void shuffle( Random rand ) {
for (int i = 0; i < size; i++) {
int src = rand.nextInt(size - i) + i;
boolean tmp = data[i];
data[i] = data[src];
data[src] = tmp;
}
}
public void forIdx( FunctionEachIdx func ) {
for (int i = 0; i < size; i++) {
func.process(i, data[i]);
}
}
public void forEach( FunctionEach func ) {
for (int i = 0; i < size; i++) {
func.process(data[i]);
}
}
public void applyIdx( FunctionApplyIdx func ) {
for (int i = 0; i < size; i++) {
data[i] = func.process(i, data[i]);
}
}
@FunctionalInterface
public interface FunctionEachIdx {
void process( int index, boolean value );
}
@FunctionalInterface
public interface FunctionEach {
void process( boolean value );
}
@FunctionalInterface
public interface FunctionApplyIdx {
boolean process( int index, boolean value );
}
}