/**
* Copyright (C) 2013 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.financial.analytics;
import java.util.Arrays;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.CompareUtils;
import com.opengamma.util.money.Currency;
/**
* Represents a two-dimensional matrix labelled by tenor and currency.
*/
public class DoubleCurrencyLabelledMatrix2D extends LabelledMatrix2D<Double, Currency> {
private static final Logger s_logger = LoggerFactory.getLogger(DoubleCurrencyLabelledMatrix2D.class);
public DoubleCurrencyLabelledMatrix2D(final Double[] xKeys, final Currency[] yKeys, final double[][] values) {
super(xKeys, yKeys, values);
}
public DoubleCurrencyLabelledMatrix2D(final Double[] xKeys, final Object[] xLabels, final Currency[] yKeys, final Object[] yLabels, final double[][] values) {
super(xKeys, xLabels, yKeys, yLabels, values);
}
public DoubleCurrencyLabelledMatrix2D(Double[] xKeys, Object[] xLabels, String xTitle, Currency[] yKeys, Object[] yLabels, String yTitle, double[][] values, String valuesTitle) {
super(xKeys, xLabels, xTitle, yKeys, yLabels, yTitle, values, valuesTitle);
}
@Override
public <X> int compareX(Double d1, Double d2, X tolerance) {
try {
final double tol = (Double) tolerance;
return CompareUtils.compareWithTolerance(d1, d2, tol);
} catch (final Exception e) {
throw new OpenGammaRuntimeException(e.getMessage());
}
}
@Override
public <Y> int compareY(Currency key1, Currency key2, Y tolerance) {
return key1.compareTo(key2);
}
@Override
public DoubleCurrencyLabelledMatrix2D getMatrix(Double[] xKeys, Object[] xLabels, String xTitle, Currency[] yKeys, Object[] yLabels, String yTitle, double[][] values, String valuesTitle) {
return new DoubleCurrencyLabelledMatrix2D(xKeys, xLabels, xTitle, yKeys, yLabels, yTitle, values, valuesTitle);
}
@Override
public DoubleCurrencyLabelledMatrix2D getMatrix(Double[] xKeys, Object[] xLabels, Currency[] yKeys, Object[] yLabels, double[][] values) {
return new DoubleCurrencyLabelledMatrix2D(xKeys, xLabels, yKeys, yLabels, values);
}
/**
* Adds a matrix to this one and returns a new matrix.
*
* In this implementation, the labels are used in place of the numeric keys to aggregate in the first dimension, and
* the result matrix will contain the lowest-valued numeric key as its key for that label.
*
* @param other the matrix to add, not null
* @return the sum of the matrices, not null
*/
public DoubleCurrencyLabelledMatrix2D addUsingDoubleLabels(DoubleCurrencyLabelledMatrix2D other) {
ArgumentChecker.notNull(other, "other");
int maxXSize = getXKeys().length + other.getXKeys().length;
Object[] resultXLabels = new Object[maxXSize];
Double[] resultXKeys = new Double[maxXSize];
int[] xIdxMap = new int[maxXSize];
int[] otherXIdxMap = new int[maxXSize];
int x = 0;
int otherX = 0;
int resultIdx = 0;
while (x < getXLabels().length && otherX < other.getXLabels().length) {
Object xLabel = getXLabels()[x];
double xKey = getXKeys()[x];
Object otherXLabel = other.getXLabels()[otherX];
double otherXKey = other.getXKeys()[otherX];
int xIdxMapValue;
int otherXIdxMapValue;
if (xLabel.equals(otherXLabel)) {
resultXLabels[resultIdx] = xLabel;
resultXKeys[resultIdx] = Math.min(xKey, otherXKey);
xIdxMapValue = x;
otherXIdxMapValue = otherX;
x++;
otherX++;
} else if (xKey < otherXKey) {
resultXLabels[resultIdx] = xLabel;
resultXKeys[resultIdx] = xKey;
xIdxMapValue = x;
otherXIdxMapValue = -1;
x++;
} else if (otherXKey < xKey) {
resultXLabels[resultIdx] = otherXLabel;
resultXKeys[resultIdx] = otherXKey;
xIdxMapValue = -1;
otherXIdxMapValue = otherX;
otherX++;
} else {
s_logger.debug("Same key " + xKey + " used for different labels in the two matrices: " + xLabel + " and " + otherXLabel);
resultXLabels[resultIdx] = xLabel;
resultXKeys[resultIdx] = xKey;
xIdxMapValue = x;
otherXIdxMapValue = otherX;
x++;
otherX++;
}
xIdxMap[resultIdx] = xIdxMapValue;
otherXIdxMap[resultIdx] = otherXIdxMapValue;
resultIdx++;
}
for (; x < getXLabels().length; x++) {
resultXLabels[resultIdx] = getXLabels()[x];
resultXKeys[resultIdx] = getXKeys()[x];
xIdxMap[resultIdx] = x;
otherXIdxMap[resultIdx] = -1;
resultIdx++;
}
for (; otherX < other.getXLabels().length; otherX++) {
resultXLabels[resultIdx] = other.getXLabels()[otherX];
resultXKeys[resultIdx] = other.getXKeys()[otherX];
xIdxMap[resultIdx] = -1;
otherXIdxMap[resultIdx] = otherX;
resultIdx++;
}
resultXKeys = Arrays.copyOf(resultXKeys, resultIdx);
resultXLabels = Arrays.copyOf(resultXLabels, resultIdx);
resultIdx = 0;
int maxYSize = getYKeys().length + other.getYKeys().length;
Object[] resultYLabels = new Object[maxYSize];
Currency[] resultYKeys = new Currency[maxYSize];
int[] yIdxMap = new int[maxYSize];
int[] otherYIdxMap = new int[maxYSize];
int y = 0;
int otherY = 0;
while (y < getYLabels().length && otherY < other.getYLabels().length) {
Object yLabel = getYLabels()[y];
Currency yKey = getYKeys()[y];
Object otherYLabel = other.getYLabels()[otherY];
Currency otherYKey = other.getYKeys()[otherY];
int yIdxMapValue;
int otherYIdxMapValue;
if (yKey.equals(otherYKey)) {
resultYLabels[resultIdx] = yLabel;
resultYKeys[resultIdx] = yKey;
yIdxMapValue = y;
otherYIdxMapValue = otherY;
y++;
otherY++;
} else if (yKey.compareTo(otherYKey) < 0) {
resultYLabels[resultIdx] = yLabel;
resultYKeys[resultIdx] = yKey;
yIdxMapValue = y;
otherYIdxMapValue = -1;
y++;
} else {
resultYLabels[resultIdx] = otherYLabel;
resultYKeys[resultIdx] = otherYKey;
yIdxMapValue = -1;
otherYIdxMapValue = otherY;
otherY++;
}
yIdxMap[resultIdx] = yIdxMapValue;
otherYIdxMap[resultIdx] = otherYIdxMapValue;
resultIdx++;
}
for (; y < getYLabels().length; y++) {
resultYLabels[resultIdx] = getYLabels()[y];
resultYKeys[resultIdx] = getYKeys()[y];
yIdxMap[resultIdx] = y;
otherYIdxMap[resultIdx] = -1;
resultIdx++;
}
for (; otherY < other.getYKeys().length; otherY++) {
resultYLabels[resultIdx] = other.getYLabels()[otherY];
resultYKeys[resultIdx] = other.getYKeys()[otherY];
yIdxMap[resultIdx] = -1;
otherYIdxMap[resultIdx] = otherY;
resultIdx++;
}
resultYKeys = Arrays.copyOf(resultYKeys, resultIdx);
resultYLabels = Arrays.copyOf(resultYLabels, resultIdx);
double[][] resultValues = new double[resultYKeys.length][resultXKeys.length];
for (int resultX = 0; resultX < resultXKeys.length; resultX++) {
int xIdx = xIdxMap[resultX];
int otherXIdx = otherXIdxMap[resultX];
for (int resultY = 0; resultY < resultYKeys.length; resultY++) {
int yIdx = yIdxMap[resultY];
int otherYIdx = otherYIdxMap[resultY];
if (xIdx >= 0 && yIdx >= 0) {
resultValues[resultY][resultX] = getValues()[yIdx][xIdx];
}
if (otherXIdx >= 0 && otherYIdx >= 0) {
resultValues[resultY][resultX] += other.getValues()[otherYIdx][otherXIdx];
}
}
}
return getMatrix(resultXKeys, resultXLabels, getXTitle(), resultYKeys, resultYLabels, getYTitle(), resultValues, getValuesTitle());
}
}