/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.financial.model.tree;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.Validate;
import com.opengamma.util.ArgumentChecker;
/**
*
* @param <T>
*/
public abstract class RecombiningTree<T> implements Lattice<T> {
private final T[][] _tree;
public RecombiningTree(final T[][] data) {
Validate.notNull(data, "data");
ArgumentChecker.notEmpty(data, "data");
_tree = data;
}
protected abstract int getMaxNodesForStep(int step);
@Override
public T getNode(final int step, final int node) {
if (step < 0) {
throw new IllegalArgumentException("Step number cannot be negative");
}
if (node < 0) {
throw new IllegalArgumentException("Node number cannot be negative");
}
if (step > _tree.length) {
throw new IllegalArgumentException("Step number " + step + " is greater than maximum in this tree (max = " + _tree.length + ")");
}
final int max = getMaxNodesForStep(step);
if (node > max) {
throw new IllegalArgumentException("Node number " + node + " is greater than the number of nodes at this step number (max = " + max + ")");
}
return _tree[step][node];
}
@Override
public T[][] getNodes() {
return _tree;
}
public int getDepth() {
return _tree.length;
}
public int getNumberOfTerminatingNodes() {
return _tree[_tree.length - 1].length;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
final int steps = _tree.length;
result = prime * result + steps;
int count = 0;
for (int i = 0; i < steps; i++) {
final int nodes = _tree[i].length;
result = prime * result + nodes;
for (int j = 0; j < nodes; j++) {
result = prime * result + _tree[i][j].hashCode();
if (count == 10) {
break;
}
count++;
}
if (count == 10) {
break;
}
}
return result;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final RecombiningTree<?> other = (RecombiningTree<?>) obj;
if (ObjectUtils.equals(_tree, other._tree)) {
return true;
}
final int length = _tree.length;
if (length != other._tree.length) {
return false;
}
for (int i = 0; i < length; i++) {
final int width = _tree[i].length;
if (width != other._tree[i].length) {
return false;
}
for (int j = 0; j < width; j++) {
if (!ObjectUtils.equals(_tree[i][j], other._tree[i][j])) {
return false;
}
}
}
return true;
}
}