AbstractSquareRangedList.java
package handist.collections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.function.Consumer;
import handist.collections.dist.TeamedPlaceGroup;
import handist.collections.function.LongTBiConsumer;
import handist.collections.function.SquareIndexTConsumer;
import handist.collections.util.Splitter;
/**
* AbstractSquareRangedList is a general interface for SquareRangedList and
* RangedListProduct.
*
* @param <T> represents the type of each element
* @param <X> represents the type used for the return type of method
* {@link #subView(SquareRange)}or {@link #split(int, int)} methods.
* In practice, SquareChunk or SquareRangedListView uses
* SquareRangedList as X and RangedListProduct uses RangedListProduct
* as X.
*/
public interface AbstractSquareRangedList<T, X extends AbstractSquareRangedList<T, X>> extends Iterable<T> {
public static int hashCode(SquareRangedList<?> rlist) {
int hashCode = 1;
// code from JavaAPI doc of List
for (final Object o : rlist) {
hashCode = 31 * hashCode + (o == null ? 0 : o.hashCode());
}
return hashCode;
}
/**
* Returns a list of each column of this instance.
*
* @return a list of each column of this instance.
*/
RangedList<RangedList<T>> asColumnList();
/**
* Returns a list of each row of this instance
*
* @return a list of each row of this instance.
*/
RangedList<RangedList<T>> asRowList();
/**
* Indicates if this list contains the provided object. More formally if the
* list contains at least one object {@code a} such that
* <code>(a == null) ? o == null : a.equals(o);</code> is true.
*
* @param v the object whose presence is to be checked
* @return {@code true} if the collection contains {@code o}, {@code false}
* otherwise
*/
boolean contains(Object v);
/**
* Performs the provided action on every element in the collection
*
* @param action the action for each element
*/
@Override
void forEach(Consumer<? super T> action);
/**
* Performs the provided action on every element in the collection
*
* @param action the action for each element
*/
void forEach(SquareIndexTConsumer<? super T> action);
/**
* Performs the provided action on every element in the collection for provided
* range.
*
* @param subrange the range of provided action
* @param action the action for each element
*/
void forEach(SquareRange subrange, Consumer<? super T> action);
/**
* Performs the provided action with an index on every element in the collection
* for provided range.
*
* @param subrange the range of provided action
* @param action the action for each element
*/
void forEach(SquareRange subrange, SquareIndexTConsumer<? super T> action);
/**
* Performs the provided action with an index on every column in the collection
* for provided range.
*
* @param range the range of provided action
* @param columnAction the action for each column
*/
void forEachColumn(LongRange range, LongTBiConsumer<RangedList<T>> columnAction);
/**
* Performs the provided action with an index on every column in the
* collection..
*
* @param columnAction the action for each column
*/
void forEachColumn(LongTBiConsumer<RangedList<T>> columnAction);
/**
* Performs the provided action with an index on every row in the collection for
* provided range.
*
* @param range the range of provided action
* @param rowAction the action for each row
*/
void forEachRow(LongRange range, LongTBiConsumer<RangedList<T>> rowAction);
/**
* Performs the provided action with an index on every row in the collection..
*
* @param rowAction the action for each row
*/
void forEachRow(LongTBiConsumer<RangedList<T>> rowAction);
/**
* Performs the provided action with {@link SquareSiblingAccessor} on every
* element in the collection for provided range.
*
* @param range the range of provided action
* @param action the action for each element
*/
void forEachWithSiblings(SquareRange range, Consumer<SquareSiblingAccessor<T>> action);
/**
* Returns the value associated with the provided {@code long} indexes.
*
* @param index outer index of the value to return
* @param index2 inner index of the value to return
* @return the value associated with this index
*/
T get(long index, long index2);
/**
* Returns the view for the provided column in Square.
*
* @param column the column for view
* @return the {@link RangedList} view of provided column
*/
RangedList<T> getColumnView(long column);
/**
* Obtain the {@link SquareRange} on which this instance is defined.
*
* @return the {@link SquareRange} object representing
*/
SquareRange getRange();
/**
* Returns the view for the provided row in Square.
*
* @param row the row for view
* @return the {@link RangedList} view of provide row
*/
RangedList<T> getRowView(long row);
/**
* Returns the view for the provided ranges in Square.
*
* @param ranges the {@link SquareRange} for views
* @return the views of provided {@link SquareRange}.
*/
default List<X> getViews(List<SquareRange> ranges) {
final List<X> results = new ArrayList<>();
ranges.forEach((SquareRange range) -> {
results.add(subView(range));
});
return results;
}
@Override
abstract Iterator<T> iterator();
/**
* Checks if the provided {@code long index} point is included in the range this
* instance is defined on, i.e. if method {@link #get(long, long)}, or
* {@link #set(long,long,Object)} can be safely called with the provided
* parameter.
*
* @param outer the long value whose represents the outer index of the point
* @param inner the long value whose represents the inner index of the point
* @throws IndexOutOfBoundsException if the provided index is outside the range
* this instance is defined on
*/
public default void rangeCheck(long outer, long inner) {
if (!this.getRange().contains(outer, inner)) {
throw new IndexOutOfBoundsException("[SquareRangedListAbstract] range mismatch: " + this.getRange()
+ " does not include point(" + outer + "," + inner + ")");
}
}
/**
* Checks if the provided {@link SquareRange} is included in the range of this
* instance.
*
* @param target LongRange whose inclusion in this instance is to be checked
* @throws ArrayIndexOutOfBoundsException if the provided {@link SquareRange} is
* not included in this instance
*/
public default void rangeCheck(SquareRange target) {
if (!this.getRange().contains(target)) {
throw new ArrayIndexOutOfBoundsException(
"[SquareRangedListAbstract] range mismatch:" + this.getRange() + " does not include " + target);
}
}
/**
* Sets the provided value at the specified index.
*
* @param index the outer index
* @param index2 the inner index
* @param value the value to set.
* @return previous value that was stored at this index, {@code null} if there
* was no previous value or the previous value stored was {@code null}
*/
T set(long index, long index2, T value);
/**
* Return the list of {@link SquareRangedList} that split into <em>outer</em> +
* <em>inner</em> {@link SquareRangedList} instances of equal size (or near
* equal size if the size of this instance is not divisible.
*
* @param outer the number of split of outer loop.
* @param inner the number of split of outer loop.
* @return a list of <em>outer</em> * <em>inner</em> {@link SquareRangedList}
* instance.
*/
default List<X> split(int outer, int inner) {
return getViews(splitRange(outer, inner));
}
/**
* Splits equally squares into <em>outer</em> * <em>inner</em> and squares are
* divided to list of sizes <em>num</em>.
*
* @param outer the number of split outer range.
* @param inner the number ot split inner range.
* @param num the number dividing squares to {@link List}.
* @param randomize if true, splited squares are added in order from begining,
* else, added in random.
* @return List of list of {@link SquareRangedList}. Size of outer list is
* numTherads. Size of inner list is number of {@link SquareRangedList}
* for each thread.
*/
default List<List<X>> splitN(int outer, int inner, int num, boolean randomize) {
final List<SquareRange> ranges = splitRange(outer, inner);
if (randomize) {
Collections.shuffle(ranges);
}
final List<List<X>> results = new ArrayList<>();
final Splitter split = new Splitter(ranges.size(), num);
for (int i = 0; i < num; i++) {
final List<SquareRange> assigned = split.getIth(i, ranges);
results.add(getViews(assigned));
}
return results;
}
/**
* Return the list of {@link SquareRange} that split into <em>outer</em> +
* <em>inner</em> {@link SquareRange} instances of equal size (or near equal
* size if the size of this instance is not divisible.
*
* @param outer the number of split of outer loop.
* @param inner the number of split of outer loop.
* @return a list of <em>outer</em> * <em>inner</em> {@link SquareRange}
* instance.
*/
default List<SquareRange> splitRange(int outer, int inner) {
return getRange().split(outer, inner);
}
abstract Iterator<T> subIterator(SquareRange range);
/**
* Provides a SquareRangedList of the elements contained in this instance on the
* specified {@link SquareRange}.
* <p>
* If the provided range exceeds the indices contained in this instance the
* method will return the elements it contains that fit within the provided
* range.
*
* @param range range of indices of which a copy is desired
* @return a ranged list of the elements contained in this
* {@link SquareRangedList} that fit in the provided range.
*/
X subView(SquareRange range);
/**
* Splits equally squares into <em>outer</em> * <em>inner</em> and return some
* squares for each host equally. Assigned squares are divided to list of sizes
* nThreads.
*
* @param outer the number of split outer range.
* @param inner the number ot split inner range.
* @param pg the group between which this ranged list is split
* @param numThreads the number of threads to whom squares should be assigned to
* @param seed seed used to randomly assign squares to hosts, must the
* same on all hosts
* @return List of list of {@link SquareRangedList}. Size of outer list is
* numTherads. Size of inner list is number of {@link SquareRangedList}
* for each thread.
*/
default List<List<X>> teamedSplitNM(int outer, int inner, TeamedPlaceGroup pg, int numThreads, long seed) {
final int numHosts = pg.size();
final int ithHost = pg.rank();
final Random rand = new Random(seed);
final List<SquareRange> ranges = splitRange(outer, inner);
if (rand != null) {
Collections.shuffle(ranges, rand);
}
final List<List<X>> results = new ArrayList<>();
final Splitter split = new Splitter(ranges.size(), numHosts);
final Splitter splitIn = new Splitter(split.ith(ithHost), split.ith(ithHost + 1), numThreads);
for (int i = 0; i < numThreads; i++) {
final List<SquareRange> assigned = splitIn.getIth(i, ranges);
results.add(getViews(assigned));
}
return results;
}
/**
* Returns the elements contained in this instance in a one-dimensional array.
* Ordered by outer and inner loop in {@link SquareRange}.
*
* @return array containing the objects contained in this instance
*/
Object[] toArray();
/**
* Returns the elements contained in this instance in a one-dimensional array.
* Ordered by outer and inner loop in {@link SquareRange}.
*
* @param newRange the range of elements to take
* @return array containing the objects contained in this instance
*/
Object[] toArray(SquareRange newRange);
/**
* Returns the elements contained in this instance in a one-dimensional
* {@link Chunk}. Ordered by outer and inner loop in {@link SquareRange}.
*
* @param newRange the range of elements to take
* @return chunk containing the objects contained in this instance
*/
SquareChunk<T> toChunk(SquareRange newRange);
/**
* Returns the elements contained in this instance in a one-dimensional
* {@link List}. Ordered by outer and inner loop in {@link SquareRange}.
*
* @param newRange the range of elements to take
* @return list containing the objects contained in this instance
*/
List<T> toList(SquareRange newRange);
}