/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.analytics.math.surface;
import java.util.HashMap;
import java.util.Map;
/**
* Contains methods for performing shifts on {@link Surface} without needing to know the exact type of the surface.
*/
public class SurfaceShiftFunctionFactory {
/** Additive shift function for {@link ConstantDoublesSurface} */
public static final ConstantSurfaceAdditiveShiftFunction CONSTANT_ADDITIVE = new ConstantSurfaceAdditiveShiftFunction();
/** Multiplicative shift function for {@link ConstantDoublesSurface} */
public static final ConstantSurfaceMultiplicativeShiftFunction CONSTANT_MULTIPLICATIVE = new ConstantSurfaceMultiplicativeShiftFunction();
/** Additive shift function for {@link FunctionalDoublesSurface} */
public static final FunctionalSurfaceAdditiveShiftFunction FUNCTIONAL_ADDITIVE = new FunctionalSurfaceAdditiveShiftFunction();
/** Multiplicative shift function for {@link FunctionalDoublesSurface} */
public static final FunctionalSurfaceMultiplicativeShiftFunction FUNCTIONAL_MULTIPLICATIVE = new FunctionalSurfaceMultiplicativeShiftFunction();
/** Additive shift function for {@link InterpolatedDoublesSurface} */
public static final InterpolatedSurfaceAdditiveShiftFunction INTERPOLATED_ADDITIVE = new InterpolatedSurfaceAdditiveShiftFunction();
/** Multiplicative shift function for {@link InterpolatedDoublesSurface} */
public static final InterpolatedSurfaceMultiplicativeShiftFunction INTERPOLATED_MULTIPLICATIVE = new InterpolatedSurfaceMultiplicativeShiftFunction();
/** Additive shift function for {@link InterpolatedFromCurvesDoublesSurface} */
public static final InterpolatedFromCurvesSurfaceAdditiveShiftFunction INTERPOLATED_FROM_CURVES_ADDITIVE = new InterpolatedFromCurvesSurfaceAdditiveShiftFunction();
/** Additive shift function for {@link NodalDoublesSurface} */
public static final NodalSurfaceAdditiveShiftFunction NODAL_ADDITIVE = new NodalSurfaceAdditiveShiftFunction();
/** Multiplicative shift function for {@link NodalDoublesSurface} */
public static final NodalSurfaceMultiplicativeShiftFunction NODAL_MULTIPLICATIVE = new NodalSurfaceMultiplicativeShiftFunction();
private static final Map<Class<?>, SurfaceShiftFunction<?>> s_instances = new HashMap<>();
static {
s_instances.put(ConstantSurfaceAdditiveShiftFunction.class, CONSTANT_ADDITIVE);
s_instances.put(ConstantSurfaceMultiplicativeShiftFunction.class, CONSTANT_MULTIPLICATIVE);
s_instances.put(FunctionalSurfaceAdditiveShiftFunction.class, FUNCTIONAL_ADDITIVE);
s_instances.put(FunctionalSurfaceMultiplicativeShiftFunction.class, FUNCTIONAL_MULTIPLICATIVE);
s_instances.put(InterpolatedSurfaceAdditiveShiftFunction.class, INTERPOLATED_ADDITIVE);
s_instances.put(InterpolatedSurfaceMultiplicativeShiftFunction.class, INTERPOLATED_MULTIPLICATIVE);
s_instances.put(InterpolatedFromCurvesSurfaceAdditiveShiftFunction.class, INTERPOLATED_FROM_CURVES_ADDITIVE);
s_instances.put(NodalSurfaceAdditiveShiftFunction.class, NODAL_ADDITIVE);
s_instances.put(NodalSurfaceMultiplicativeShiftFunction.class, NODAL_MULTIPLICATIVE);
}
/**
* Gets the function for a class type.
* @param clazz The class
* @return The function
* @throws IllegalArgumentException If the function is not one of the static instances
*/
public static SurfaceShiftFunction<?> getFunction(final Class<?> clazz) {
final SurfaceShiftFunction<?> f = s_instances.get(clazz);
if (f == null) {
throw new IllegalArgumentException("Could not get function for " + clazz.getName());
}
return f;
}
/**
* For a surface Surface<Double, Double, Double>, return a parallel-shifted surface.
* @param surface The original surface
* @param shift The shift
* @param useAdditive true if the shift is additive, false if the shift is multiplicative (i.e. a percentage shift)
* @return A shifted surface with automatically-generated name
* @throws IllegalArgumentException If the surface type is not constant, functional, interpolated, nodal or spread
*/
public static Surface<Double, Double, Double> getShiftedSurface(final Surface<Double, Double, Double> surface, final double shift, final boolean useAdditive) {
if (surface instanceof ConstantDoublesSurface) {
return useAdditive ? CONSTANT_ADDITIVE.evaluate((ConstantDoublesSurface) surface, shift) : CONSTANT_MULTIPLICATIVE
.evaluate((ConstantDoublesSurface) surface, shift);
}
if (surface instanceof FunctionalDoublesSurface) {
return useAdditive ? FUNCTIONAL_ADDITIVE.evaluate((FunctionalDoublesSurface) surface, shift) : FUNCTIONAL_MULTIPLICATIVE.evaluate(
(FunctionalDoublesSurface) surface, shift);
}
if (surface instanceof InterpolatedDoublesSurface) {
return useAdditive ? INTERPOLATED_ADDITIVE.evaluate((InterpolatedDoublesSurface) surface, shift) : INTERPOLATED_MULTIPLICATIVE.evaluate(
(InterpolatedDoublesSurface) surface, shift);
}
if (surface instanceof InterpolatedFromCurvesDoublesSurface && useAdditive) {
return INTERPOLATED_FROM_CURVES_ADDITIVE.evaluate((InterpolatedFromCurvesDoublesSurface) surface, shift);
}
if (surface instanceof NodalDoublesSurface) {
return useAdditive ? NODAL_ADDITIVE.evaluate((NodalDoublesSurface) surface, shift) : NODAL_MULTIPLICATIVE.evaluate((NodalDoublesSurface) surface, shift);
}
throw new IllegalArgumentException("Do not have a surface shift function for surface " + surface.getClass());
}
/**
* For a surface Surface<Double, Double, Double>, return a surface shifted at one point.
* @param surface The original surface
* @param x The <i>x</i> value of the shift
* @param y The <i>y</i> value of the shift
* @param shift The shift
* @param useAdditive true if the shift is additive, false if the shift is multiplicative (i.e. a percentage shift)
* @return A shifted surface with automatically-generated name
* @throws IllegalArgumentException If the surface type is not constant, functional, interpolated, nodal or spread
*/
public static Surface<Double, Double, Double> getShiftedSurface(final Surface<Double, Double, Double> surface, final double x, final double y, final double shift,
final boolean useAdditive) {
if (surface instanceof ConstantDoublesSurface) {
throw new UnsupportedOperationException("Cannot shift a single point on a constant curve");
}
if (surface instanceof FunctionalDoublesSurface) {
throw new UnsupportedOperationException("Cannot shift a single point on a functional curve");
}
if (surface instanceof InterpolatedDoublesSurface) {
return useAdditive ? INTERPOLATED_ADDITIVE.evaluate((InterpolatedDoublesSurface) surface, x, y, shift) : INTERPOLATED_MULTIPLICATIVE.evaluate(
(InterpolatedDoublesSurface) surface, x, y, shift);
}
if (surface instanceof InterpolatedFromCurvesDoublesSurface && useAdditive) {
return INTERPOLATED_FROM_CURVES_ADDITIVE.evaluate((InterpolatedFromCurvesDoublesSurface) surface, x, y, shift);
}
if (surface instanceof NodalDoublesSurface) {
return useAdditive ? NODAL_ADDITIVE.evaluate((NodalDoublesSurface) surface, x, y, shift) : NODAL_MULTIPLICATIVE
.evaluate((NodalDoublesSurface) surface, x, y, shift);
}
throw new IllegalArgumentException("Do not have a surface shift function for surface " + surface.getClass());
}
/**
* For a surface Surface<Double, Double, Double>, return a parallel-shifted surface.
* @param surface The original surface
* @param x An array of <i>x</i> values to shift
* @param y An array of <i>y</i> values to shift
* @param shift The shifts
* @param useAdditive true if the shift is additive, false if the shift is multiplicative (i.e. a percentage shift)
* @return A shifted surface with an automatically-generated name
* @throws IllegalArgumentException If the surface type is not constant, functional, interpolated, nodal or spread
*/
public static Surface<Double, Double, Double> getShiftedSurface(final Surface<Double, Double, Double> surface, final double[] x, final double[] y,
final double[] shift, final boolean useAdditive) {
if (surface instanceof ConstantDoublesSurface) {
throw new UnsupportedOperationException("Cannot parallel shift a constant curve");
}
if (surface instanceof FunctionalDoublesSurface) {
throw new UnsupportedOperationException("Cannot parallel shift a functional curve");
}
if (surface instanceof InterpolatedDoublesSurface) {
return useAdditive ? INTERPOLATED_ADDITIVE.evaluate((InterpolatedDoublesSurface) surface, x, y, shift) : INTERPOLATED_MULTIPLICATIVE.evaluate(
(InterpolatedDoublesSurface) surface, x, y, shift);
}
if (surface instanceof InterpolatedFromCurvesDoublesSurface && useAdditive) {
return INTERPOLATED_FROM_CURVES_ADDITIVE.evaluate((InterpolatedFromCurvesDoublesSurface) surface, x, y, shift);
}
if (surface instanceof NodalDoublesSurface) {
return useAdditive ? NODAL_ADDITIVE.evaluate((NodalDoublesSurface) surface, x, y, shift) : NODAL_MULTIPLICATIVE
.evaluate((NodalDoublesSurface) surface, x, y, shift);
}
throw new IllegalArgumentException("Do not have a surface shift function for surface " + surface.getClass());
}
/**
* For a surface Surface<Double, Double, Double>, return a parallel-shifted surface.
* @param surface The original surface
* @param shift The shift
* @param newName The name of the shifted surface
* @param useAdditive true if the shift is additive, false if the shift is multiplicative (i.e. a percentage shift)
* @return A shifted surface
* @throws IllegalArgumentException If the surface type is not constant, functional, interpolated, nodal or spread
*/
public static Surface<Double, Double, Double> getShiftedSurface(final Surface<Double, Double, Double> surface, final double shift, final String newName,
final boolean useAdditive) {
if (surface instanceof ConstantDoublesSurface) {
return useAdditive ? CONSTANT_ADDITIVE.evaluate((ConstantDoublesSurface) surface, shift, newName) : CONSTANT_MULTIPLICATIVE.evaluate(
(ConstantDoublesSurface) surface, shift, newName);
}
if (surface instanceof FunctionalDoublesSurface) {
return useAdditive ? FUNCTIONAL_ADDITIVE.evaluate((FunctionalDoublesSurface) surface, shift, newName) : FUNCTIONAL_MULTIPLICATIVE.evaluate(
(FunctionalDoublesSurface) surface, shift, newName);
}
if (surface instanceof InterpolatedDoublesSurface) {
return useAdditive ? INTERPOLATED_ADDITIVE.evaluate((InterpolatedDoublesSurface) surface, shift, newName) : INTERPOLATED_MULTIPLICATIVE.evaluate(
(InterpolatedDoublesSurface) surface, shift, newName);
}
if (surface instanceof InterpolatedFromCurvesDoublesSurface && useAdditive) {
return INTERPOLATED_FROM_CURVES_ADDITIVE.evaluate((InterpolatedFromCurvesDoublesSurface) surface, shift, newName);
}
if (surface instanceof NodalDoublesSurface) {
return useAdditive ? NODAL_ADDITIVE.evaluate((NodalDoublesSurface) surface, shift, newName) : NODAL_MULTIPLICATIVE.evaluate((NodalDoublesSurface) surface, shift,
newName);
}
throw new IllegalArgumentException("Do not have a surface shift function for surface " + surface.getClass());
}
/**
* For a surface Surface<Double, Double, Double>, return a surface shifted at one point.
* @param surface The original surface
* @param x The <i>x</i> value of the shift
* @param y The <i>y</i> value of the shift
* @param shift The shift
* @param newName The name of the new surface
* @param useAdditive true if the shift is additive, false if the shift is multiplicative (i.e. a percentage shift)
* @return A shifted surface
* @throws IllegalArgumentException If the surface type is not constant, functional, interpolated, nodal or spread
*/
public static Surface<Double, Double, Double> getShiftedSurface(final Surface<Double, Double, Double> surface, final double x, final double y, final double shift,
final String newName, final boolean useAdditive) {
if (surface instanceof ConstantDoublesSurface) {
throw new UnsupportedOperationException("Cannot shift a single point on a constant curve");
}
if (surface instanceof FunctionalDoublesSurface) {
throw new UnsupportedOperationException("Cannot shift a single point on a functional curve");
}
if (surface instanceof InterpolatedDoublesSurface) {
return useAdditive ? INTERPOLATED_ADDITIVE.evaluate((InterpolatedDoublesSurface) surface, x, y, shift, newName) : INTERPOLATED_MULTIPLICATIVE.evaluate(
(InterpolatedDoublesSurface) surface, x, y, shift, newName);
}
if (surface instanceof InterpolatedFromCurvesDoublesSurface && useAdditive) {
return INTERPOLATED_FROM_CURVES_ADDITIVE.evaluate((InterpolatedFromCurvesDoublesSurface) surface, x, y, shift, newName);
}
if (surface instanceof NodalDoublesSurface) {
return useAdditive ? NODAL_ADDITIVE.evaluate((NodalDoublesSurface) surface, x, y, shift, newName) : NODAL_MULTIPLICATIVE.evaluate((NodalDoublesSurface) surface, x,
y, shift, newName);
}
throw new IllegalArgumentException("Do not have a surface shift function for surface " + surface.getClass());
}
/**
* For a surface Surface<Double, Double, Double>, return a parallel-shifted surface.
* @param surface The original surface
* @param x An array of <i>x</i> values to shift
* @param y An array of <i>y</i> values to shift
* @param shift The shifts
* @param newName The name of the shifted surface
* @param useAdditive true if the shift is additive, false if the shift is multiplicative (i.e. a percentage shift)
* @return A shifted surface
* @throws IllegalArgumentException If the surface type is not constant, functional, interpolated, nodal or spread
*/
public static Surface<Double, Double, Double> getShiftedSurface(final Surface<Double, Double, Double> surface, final double[] x, final double[] y,
final double[] shift, final String newName, final boolean useAdditive) {
if (surface instanceof ConstantDoublesSurface) {
throw new UnsupportedOperationException("Cannot parallel shift a constant curve");
}
if (surface instanceof FunctionalDoublesSurface) {
throw new UnsupportedOperationException("Cannot parallel shift a functional curve");
}
if (surface instanceof InterpolatedDoublesSurface) {
return useAdditive ? INTERPOLATED_ADDITIVE.evaluate((InterpolatedDoublesSurface) surface, x, y, shift, newName) : INTERPOLATED_MULTIPLICATIVE.evaluate(
(InterpolatedDoublesSurface) surface, x, y, shift, newName);
}
if (surface instanceof InterpolatedFromCurvesDoublesSurface && useAdditive) {
return INTERPOLATED_FROM_CURVES_ADDITIVE.evaluate((InterpolatedFromCurvesDoublesSurface) surface, x, y, shift, newName);
}
if (surface instanceof NodalDoublesSurface) {
return useAdditive ? NODAL_ADDITIVE.evaluate((NodalDoublesSurface) surface, x, y, shift, newName) : NODAL_MULTIPLICATIVE.evaluate((NodalDoublesSurface) surface, x,
y, shift, newName);
}
throw new IllegalArgumentException("Do not have a surface shift function for surface " + surface.getClass());
}
}