/**
* Copyright (C) 2016 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.strata.market.surface.interpolator;
import static com.opengamma.strata.market.curve.interpolator.CurveExtrapolators.FLAT;
import java.io.Serializable;
import java.util.Arrays;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import org.joda.beans.Bean;
import org.joda.beans.BeanBuilder;
import org.joda.beans.BeanDefinition;
import org.joda.beans.ImmutableBean;
import org.joda.beans.JodaBeanUtils;
import org.joda.beans.MetaProperty;
import org.joda.beans.Property;
import org.joda.beans.PropertyDefinition;
import org.joda.beans.impl.direct.DirectFieldsBeanBuilder;
import org.joda.beans.impl.direct.DirectMetaBean;
import org.joda.beans.impl.direct.DirectMetaProperty;
import org.joda.beans.impl.direct.DirectMetaPropertyMap;
import com.google.common.collect.ImmutableList;
import com.opengamma.strata.collect.array.DoubleArray;
import com.opengamma.strata.market.curve.interpolator.BoundCurveExtrapolator;
import com.opengamma.strata.market.curve.interpolator.BoundCurveInterpolator;
import com.opengamma.strata.market.curve.interpolator.CurveExtrapolator;
import com.opengamma.strata.market.curve.interpolator.CurveInterpolator;
/**
* A surface interpolator that is based on two curve interpolators.
* <p>
* The surface parameters are divided into rows and columns based on the x-values
* and y-values. There must be at least two y-values for each x-value.
* In most cases, the parameters will form a rectangular grid.
* <p>
* The interpolation operates in two stages.
* First, the parameters are grouped into sets, each with the same x value.
* Second, the y curve interpolator is used on each set of y values.
* Finally, the x curve interpolator is used on the results of the y interpolation.
* <p>
* There should be at least two different y-values for each x-value.
* If there is only one, then the associated z-value will always be returned.
*/
@BeanDefinition(builderScope = "private")
public final class GridSurfaceInterpolator
implements SurfaceInterpolator, ImmutableBean, Serializable {
/**
* The x-value interpolator.
*/
@PropertyDefinition
private final CurveInterpolator xInterpolator;
/**
* The x-value left extrapolator.
*/
@PropertyDefinition
private final CurveExtrapolator xExtrapolatorLeft;
/**
* The x-value right extrapolator.
*/
@PropertyDefinition
private final CurveExtrapolator xExtrapolatorRight;
/**
* The y-value interpolator.
*/
@PropertyDefinition
private final CurveInterpolator yInterpolator;
/**
* The y-value left extrapolator.
*/
@PropertyDefinition
private final CurveExtrapolator yExtrapolatorLeft;
/**
* The y-value right extrapolator.
*/
@PropertyDefinition
private final CurveExtrapolator yExtrapolatorRight;
//-------------------------------------------------------------------------
/**
* Obtains an instance from the specified interpolators, using flat extrapolation.
*
* @param xInterpolator the x-value interpolator
* @param yInterpolator the y-value interpolator
* @return the index
* @throws IllegalArgumentException if the name is not known
*/
public static GridSurfaceInterpolator of(CurveInterpolator xInterpolator, CurveInterpolator yInterpolator) {
return new GridSurfaceInterpolator(xInterpolator, FLAT, FLAT, yInterpolator, FLAT, FLAT);
}
/**
* Obtains an instance from the specified interpolators and extrapolators.
*
* @param xInterpolator the x-value interpolator
* @param xExtrapolator the x-value extrapolator
* @param yInterpolator the y-value interpolator
* @param yExtrapolator the y-value extrapolator
* @return the index
* @throws IllegalArgumentException if the name is not known
*/
public static GridSurfaceInterpolator of(
CurveInterpolator xInterpolator,
CurveExtrapolator xExtrapolator,
CurveInterpolator yInterpolator,
CurveExtrapolator yExtrapolator) {
return new GridSurfaceInterpolator(
xInterpolator, xExtrapolator, xExtrapolator, yInterpolator, yExtrapolator, yExtrapolator);
}
/**
* Obtains an instance from the specified interpolators and extrapolators.
*
* @param xInterpolator the x-value interpolator
* @param xExtrapolatorLeft the x-value left extrapolator
* @param xExtrapolatorRight the x-value right extrapolator
* @param yInterpolator the y-value interpolator
* @param yExtrapolatorLeft the y-value left extrapolator
* @param yExtrapolatorRight the y-value right extrapolator
* @return the index
* @throws IllegalArgumentException if the name is not known
*/
public static GridSurfaceInterpolator of(
CurveInterpolator xInterpolator,
CurveExtrapolator xExtrapolatorLeft,
CurveExtrapolator xExtrapolatorRight,
CurveInterpolator yInterpolator,
CurveExtrapolator yExtrapolatorLeft,
CurveExtrapolator yExtrapolatorRight) {
return new GridSurfaceInterpolator(
xInterpolator, xExtrapolatorLeft, xExtrapolatorRight, yInterpolator, yExtrapolatorLeft, yExtrapolatorRight);
}
//-------------------------------------------------------------------------
@Override
public BoundSurfaceInterpolator bind(DoubleArray xValues, DoubleArray yValues, DoubleArray zValues) {
// single loop around all parameters, collecting data
int size = xValues.size();
int countUniqueX = 0;
double[] uniqueX = new double[size];
double[] tempY = new double[size];
double[] tempZ = new double[size];
ImmutableList.Builder<BoundCurveInterpolator> yInterpBuilder = ImmutableList.builder();
int i = 0;
while (i < size) {
double currentX = xValues.get(i);
uniqueX[countUniqueX] = currentX;
if (countUniqueX > 0 && uniqueX[countUniqueX - 1] > uniqueX[countUniqueX]) {
throw new IllegalArgumentException("Array of x-values must be sorted");
}
int countSameX = 0;
while (i < size && xValues.get(i) == currentX) {
tempY[countSameX] = yValues.get(i);
tempZ[countSameX] = zValues.get(i);
if (countSameX > 0 && tempY[countSameX - 1] >= tempY[countSameX]) {
throw new IllegalArgumentException("Array of y-values must be sorted and unique within x-values");
}
countSameX++;
i++;
}
// create a curve for the same x-value
if (countSameX == 1) {
// when there is only one point, there is not enough data for a curve
// so the value must be returned without using the configured interpolator or extrapolator
yInterpBuilder.add(new ConstantCurveInterpolator(tempZ[0]));
} else {
// normal case, where the curve is created
DoubleArray yValuesSameX = DoubleArray.ofUnsafe(Arrays.copyOf(tempY, countSameX));
DoubleArray zValuesSameX = DoubleArray.ofUnsafe(Arrays.copyOf(tempZ, countSameX));
yInterpBuilder.add(yInterpolator.bind(yValuesSameX, zValuesSameX, yExtrapolatorLeft, yExtrapolatorRight));
}
countUniqueX++;
}
if (countUniqueX == 1) {
throw new IllegalArgumentException("Surface interpolator requires at least two different x-values");
}
DoubleArray uniqueXArray = DoubleArray.ofUnsafe(Arrays.copyOf(uniqueX, countUniqueX));
BoundCurveInterpolator[] yInterps = yInterpBuilder.build().toArray(new BoundCurveInterpolator[0]);
return new Bound(xInterpolator, xExtrapolatorLeft, xExtrapolatorRight, size, uniqueXArray, yInterps);
}
//-------------------------------------------------------------------------
/**
* Bound interpolator.
*/
static class Bound implements BoundSurfaceInterpolator {
private final CurveInterpolator xInterpolator;
private final CurveExtrapolator xExtrapolatorLeft;
private final CurveExtrapolator xExtrapolatorRight;
private final DoubleArray xValuesUnique;
private final int paramSize;
private final BoundCurveInterpolator[] yInterpolators;
Bound(
CurveInterpolator xInterpolator,
CurveExtrapolator xExtrapolatorLeft,
CurveExtrapolator xExtrapolatorRight,
int paramSize,
DoubleArray xValuesUnique,
BoundCurveInterpolator[] yInterpolators) {
this.xInterpolator = xInterpolator;
this.xExtrapolatorLeft = xExtrapolatorLeft;
this.xExtrapolatorRight = xExtrapolatorRight;
this.xValuesUnique = xValuesUnique;
this.paramSize = paramSize;
this.yInterpolators = yInterpolators;
}
//-------------------------------------------------------------------------
@Override
public double interpolate(double x, double y) {
// use each y-interpolator to find the z-value for each unique x
DoubleArray zValuesEffective = DoubleArray.of(yInterpolators.length, i -> yInterpolators[i].interpolate(y));
// interpolate unique x-values against derived z-values
return xInterpolator.bind(xValuesUnique, zValuesEffective, xExtrapolatorLeft, xExtrapolatorRight).interpolate(x);
}
@Override
public DoubleArray parameterSensitivity(double x, double y) {
int uniqueX = yInterpolators.length;
final DoubleArray[] ySens = new DoubleArray[uniqueX];
// use each y-interpolator to find the z-value sensitivity for each unique x
for (int i = 0; i < uniqueX; i++) {
ySens[i] = yInterpolators[i].parameterSensitivity(y);
}
// use each y-interpolator to find the z-value for each unique x
DoubleArray zValuesEffective = DoubleArray.of(uniqueX, i -> yInterpolators[i].interpolate(y));
// find the sensitivity of the unique x-values against derived z-values
DoubleArray xSens = xInterpolator
.bind(xValuesUnique, zValuesEffective, xExtrapolatorLeft, xExtrapolatorRight)
.parameterSensitivity(x);
return project(xSens, ySens);
}
// project sensitivities back to parameters
private DoubleArray project(DoubleArray xSens, DoubleArray[] ySens) {
int countParam = 0;
double[] paramSens = new double[paramSize];
for (int i = 0; i < xSens.size(); i++) {
double xs = xSens.get(i);
DoubleArray ys = ySens[i];
for (int j = 0; j < ys.size(); j++) {
paramSens[countParam++] = xs * ys.get(j);
}
}
return DoubleArray.ofUnsafe(paramSens);
}
}
//-------------------------------------------------------------------------
/**
* An interpolator that returns the single known value.
*/
static class ConstantCurveInterpolator implements BoundCurveInterpolator {
private final double value;
public ConstantCurveInterpolator(double value) {
this.value = value;
}
@Override
public double interpolate(double x) {
return value;
}
@Override
public double firstDerivative(double x) {
return 0;
}
@Override
public DoubleArray parameterSensitivity(double x) {
return DoubleArray.of(1);
}
@Override
public BoundCurveInterpolator bind(BoundCurveExtrapolator extrapolatorLeft, BoundCurveExtrapolator extrapolatorRight) {
return this;
}
}
//------------------------- AUTOGENERATED START -------------------------
///CLOVER:OFF
/**
* The meta-bean for {@code GridSurfaceInterpolator}.
* @return the meta-bean, not null
*/
public static GridSurfaceInterpolator.Meta meta() {
return GridSurfaceInterpolator.Meta.INSTANCE;
}
static {
JodaBeanUtils.registerMetaBean(GridSurfaceInterpolator.Meta.INSTANCE);
}
/**
* The serialization version id.
*/
private static final long serialVersionUID = 1L;
private GridSurfaceInterpolator(
CurveInterpolator xInterpolator,
CurveExtrapolator xExtrapolatorLeft,
CurveExtrapolator xExtrapolatorRight,
CurveInterpolator yInterpolator,
CurveExtrapolator yExtrapolatorLeft,
CurveExtrapolator yExtrapolatorRight) {
this.xInterpolator = xInterpolator;
this.xExtrapolatorLeft = xExtrapolatorLeft;
this.xExtrapolatorRight = xExtrapolatorRight;
this.yInterpolator = yInterpolator;
this.yExtrapolatorLeft = yExtrapolatorLeft;
this.yExtrapolatorRight = yExtrapolatorRight;
}
@Override
public GridSurfaceInterpolator.Meta metaBean() {
return GridSurfaceInterpolator.Meta.INSTANCE;
}
@Override
public <R> Property<R> property(String propertyName) {
return metaBean().<R>metaProperty(propertyName).createProperty(this);
}
@Override
public Set<String> propertyNames() {
return metaBean().metaPropertyMap().keySet();
}
//-----------------------------------------------------------------------
/**
* Gets the x-value interpolator.
* @return the value of the property
*/
public CurveInterpolator getXInterpolator() {
return xInterpolator;
}
//-----------------------------------------------------------------------
/**
* Gets the x-value left extrapolator.
* @return the value of the property
*/
public CurveExtrapolator getXExtrapolatorLeft() {
return xExtrapolatorLeft;
}
//-----------------------------------------------------------------------
/**
* Gets the x-value right extrapolator.
* @return the value of the property
*/
public CurveExtrapolator getXExtrapolatorRight() {
return xExtrapolatorRight;
}
//-----------------------------------------------------------------------
/**
* Gets the y-value interpolator.
* @return the value of the property
*/
public CurveInterpolator getYInterpolator() {
return yInterpolator;
}
//-----------------------------------------------------------------------
/**
* Gets the y-value left extrapolator.
* @return the value of the property
*/
public CurveExtrapolator getYExtrapolatorLeft() {
return yExtrapolatorLeft;
}
//-----------------------------------------------------------------------
/**
* Gets the y-value right extrapolator.
* @return the value of the property
*/
public CurveExtrapolator getYExtrapolatorRight() {
return yExtrapolatorRight;
}
//-----------------------------------------------------------------------
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (obj != null && obj.getClass() == this.getClass()) {
GridSurfaceInterpolator other = (GridSurfaceInterpolator) obj;
return JodaBeanUtils.equal(xInterpolator, other.xInterpolator) &&
JodaBeanUtils.equal(xExtrapolatorLeft, other.xExtrapolatorLeft) &&
JodaBeanUtils.equal(xExtrapolatorRight, other.xExtrapolatorRight) &&
JodaBeanUtils.equal(yInterpolator, other.yInterpolator) &&
JodaBeanUtils.equal(yExtrapolatorLeft, other.yExtrapolatorLeft) &&
JodaBeanUtils.equal(yExtrapolatorRight, other.yExtrapolatorRight);
}
return false;
}
@Override
public int hashCode() {
int hash = getClass().hashCode();
hash = hash * 31 + JodaBeanUtils.hashCode(xInterpolator);
hash = hash * 31 + JodaBeanUtils.hashCode(xExtrapolatorLeft);
hash = hash * 31 + JodaBeanUtils.hashCode(xExtrapolatorRight);
hash = hash * 31 + JodaBeanUtils.hashCode(yInterpolator);
hash = hash * 31 + JodaBeanUtils.hashCode(yExtrapolatorLeft);
hash = hash * 31 + JodaBeanUtils.hashCode(yExtrapolatorRight);
return hash;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder(224);
buf.append("GridSurfaceInterpolator{");
buf.append("xInterpolator").append('=').append(xInterpolator).append(',').append(' ');
buf.append("xExtrapolatorLeft").append('=').append(xExtrapolatorLeft).append(',').append(' ');
buf.append("xExtrapolatorRight").append('=').append(xExtrapolatorRight).append(',').append(' ');
buf.append("yInterpolator").append('=').append(yInterpolator).append(',').append(' ');
buf.append("yExtrapolatorLeft").append('=').append(yExtrapolatorLeft).append(',').append(' ');
buf.append("yExtrapolatorRight").append('=').append(JodaBeanUtils.toString(yExtrapolatorRight));
buf.append('}');
return buf.toString();
}
//-----------------------------------------------------------------------
/**
* The meta-bean for {@code GridSurfaceInterpolator}.
*/
public static final class Meta extends DirectMetaBean {
/**
* The singleton instance of the meta-bean.
*/
static final Meta INSTANCE = new Meta();
/**
* The meta-property for the {@code xInterpolator} property.
*/
private final MetaProperty<CurveInterpolator> xInterpolator = DirectMetaProperty.ofImmutable(
this, "xInterpolator", GridSurfaceInterpolator.class, CurveInterpolator.class);
/**
* The meta-property for the {@code xExtrapolatorLeft} property.
*/
private final MetaProperty<CurveExtrapolator> xExtrapolatorLeft = DirectMetaProperty.ofImmutable(
this, "xExtrapolatorLeft", GridSurfaceInterpolator.class, CurveExtrapolator.class);
/**
* The meta-property for the {@code xExtrapolatorRight} property.
*/
private final MetaProperty<CurveExtrapolator> xExtrapolatorRight = DirectMetaProperty.ofImmutable(
this, "xExtrapolatorRight", GridSurfaceInterpolator.class, CurveExtrapolator.class);
/**
* The meta-property for the {@code yInterpolator} property.
*/
private final MetaProperty<CurveInterpolator> yInterpolator = DirectMetaProperty.ofImmutable(
this, "yInterpolator", GridSurfaceInterpolator.class, CurveInterpolator.class);
/**
* The meta-property for the {@code yExtrapolatorLeft} property.
*/
private final MetaProperty<CurveExtrapolator> yExtrapolatorLeft = DirectMetaProperty.ofImmutable(
this, "yExtrapolatorLeft", GridSurfaceInterpolator.class, CurveExtrapolator.class);
/**
* The meta-property for the {@code yExtrapolatorRight} property.
*/
private final MetaProperty<CurveExtrapolator> yExtrapolatorRight = DirectMetaProperty.ofImmutable(
this, "yExtrapolatorRight", GridSurfaceInterpolator.class, CurveExtrapolator.class);
/**
* The meta-properties.
*/
private final Map<String, MetaProperty<?>> metaPropertyMap$ = new DirectMetaPropertyMap(
this, null,
"xInterpolator",
"xExtrapolatorLeft",
"xExtrapolatorRight",
"yInterpolator",
"yExtrapolatorLeft",
"yExtrapolatorRight");
/**
* Restricted constructor.
*/
private Meta() {
}
@Override
protected MetaProperty<?> metaPropertyGet(String propertyName) {
switch (propertyName.hashCode()) {
case 1411950943: // xInterpolator
return xInterpolator;
case -382665134: // xExtrapolatorLeft
return xExtrapolatorLeft;
case 1027943729: // xExtrapolatorRight
return xExtrapolatorRight;
case 1118547936: // yInterpolator
return yInterpolator;
case 970644563: // yExtrapolatorLeft
return yExtrapolatorLeft;
case 30871376: // yExtrapolatorRight
return yExtrapolatorRight;
}
return super.metaPropertyGet(propertyName);
}
@Override
public BeanBuilder<? extends GridSurfaceInterpolator> builder() {
return new GridSurfaceInterpolator.Builder();
}
@Override
public Class<? extends GridSurfaceInterpolator> beanType() {
return GridSurfaceInterpolator.class;
}
@Override
public Map<String, MetaProperty<?>> metaPropertyMap() {
return metaPropertyMap$;
}
//-----------------------------------------------------------------------
/**
* The meta-property for the {@code xInterpolator} property.
* @return the meta-property, not null
*/
public MetaProperty<CurveInterpolator> xInterpolator() {
return xInterpolator;
}
/**
* The meta-property for the {@code xExtrapolatorLeft} property.
* @return the meta-property, not null
*/
public MetaProperty<CurveExtrapolator> xExtrapolatorLeft() {
return xExtrapolatorLeft;
}
/**
* The meta-property for the {@code xExtrapolatorRight} property.
* @return the meta-property, not null
*/
public MetaProperty<CurveExtrapolator> xExtrapolatorRight() {
return xExtrapolatorRight;
}
/**
* The meta-property for the {@code yInterpolator} property.
* @return the meta-property, not null
*/
public MetaProperty<CurveInterpolator> yInterpolator() {
return yInterpolator;
}
/**
* The meta-property for the {@code yExtrapolatorLeft} property.
* @return the meta-property, not null
*/
public MetaProperty<CurveExtrapolator> yExtrapolatorLeft() {
return yExtrapolatorLeft;
}
/**
* The meta-property for the {@code yExtrapolatorRight} property.
* @return the meta-property, not null
*/
public MetaProperty<CurveExtrapolator> yExtrapolatorRight() {
return yExtrapolatorRight;
}
//-----------------------------------------------------------------------
@Override
protected Object propertyGet(Bean bean, String propertyName, boolean quiet) {
switch (propertyName.hashCode()) {
case 1411950943: // xInterpolator
return ((GridSurfaceInterpolator) bean).getXInterpolator();
case -382665134: // xExtrapolatorLeft
return ((GridSurfaceInterpolator) bean).getXExtrapolatorLeft();
case 1027943729: // xExtrapolatorRight
return ((GridSurfaceInterpolator) bean).getXExtrapolatorRight();
case 1118547936: // yInterpolator
return ((GridSurfaceInterpolator) bean).getYInterpolator();
case 970644563: // yExtrapolatorLeft
return ((GridSurfaceInterpolator) bean).getYExtrapolatorLeft();
case 30871376: // yExtrapolatorRight
return ((GridSurfaceInterpolator) bean).getYExtrapolatorRight();
}
return super.propertyGet(bean, propertyName, quiet);
}
@Override
protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) {
metaProperty(propertyName);
if (quiet) {
return;
}
throw new UnsupportedOperationException("Property cannot be written: " + propertyName);
}
}
//-----------------------------------------------------------------------
/**
* The bean-builder for {@code GridSurfaceInterpolator}.
*/
private static final class Builder extends DirectFieldsBeanBuilder<GridSurfaceInterpolator> {
private CurveInterpolator xInterpolator;
private CurveExtrapolator xExtrapolatorLeft;
private CurveExtrapolator xExtrapolatorRight;
private CurveInterpolator yInterpolator;
private CurveExtrapolator yExtrapolatorLeft;
private CurveExtrapolator yExtrapolatorRight;
/**
* Restricted constructor.
*/
private Builder() {
}
//-----------------------------------------------------------------------
@Override
public Object get(String propertyName) {
switch (propertyName.hashCode()) {
case 1411950943: // xInterpolator
return xInterpolator;
case -382665134: // xExtrapolatorLeft
return xExtrapolatorLeft;
case 1027943729: // xExtrapolatorRight
return xExtrapolatorRight;
case 1118547936: // yInterpolator
return yInterpolator;
case 970644563: // yExtrapolatorLeft
return yExtrapolatorLeft;
case 30871376: // yExtrapolatorRight
return yExtrapolatorRight;
default:
throw new NoSuchElementException("Unknown property: " + propertyName);
}
}
@Override
public Builder set(String propertyName, Object newValue) {
switch (propertyName.hashCode()) {
case 1411950943: // xInterpolator
this.xInterpolator = (CurveInterpolator) newValue;
break;
case -382665134: // xExtrapolatorLeft
this.xExtrapolatorLeft = (CurveExtrapolator) newValue;
break;
case 1027943729: // xExtrapolatorRight
this.xExtrapolatorRight = (CurveExtrapolator) newValue;
break;
case 1118547936: // yInterpolator
this.yInterpolator = (CurveInterpolator) newValue;
break;
case 970644563: // yExtrapolatorLeft
this.yExtrapolatorLeft = (CurveExtrapolator) newValue;
break;
case 30871376: // yExtrapolatorRight
this.yExtrapolatorRight = (CurveExtrapolator) newValue;
break;
default:
throw new NoSuchElementException("Unknown property: " + propertyName);
}
return this;
}
@Override
public Builder set(MetaProperty<?> property, Object value) {
super.set(property, value);
return this;
}
@Override
public Builder setString(String propertyName, String value) {
setString(meta().metaProperty(propertyName), value);
return this;
}
@Override
public Builder setString(MetaProperty<?> property, String value) {
super.setString(property, value);
return this;
}
@Override
public Builder setAll(Map<String, ? extends Object> propertyValueMap) {
super.setAll(propertyValueMap);
return this;
}
@Override
public GridSurfaceInterpolator build() {
return new GridSurfaceInterpolator(
xInterpolator,
xExtrapolatorLeft,
xExtrapolatorRight,
yInterpolator,
yExtrapolatorLeft,
yExtrapolatorRight);
}
//-----------------------------------------------------------------------
@Override
public String toString() {
StringBuilder buf = new StringBuilder(224);
buf.append("GridSurfaceInterpolator.Builder{");
buf.append("xInterpolator").append('=').append(JodaBeanUtils.toString(xInterpolator)).append(',').append(' ');
buf.append("xExtrapolatorLeft").append('=').append(JodaBeanUtils.toString(xExtrapolatorLeft)).append(',').append(' ');
buf.append("xExtrapolatorRight").append('=').append(JodaBeanUtils.toString(xExtrapolatorRight)).append(',').append(' ');
buf.append("yInterpolator").append('=').append(JodaBeanUtils.toString(yInterpolator)).append(',').append(' ');
buf.append("yExtrapolatorLeft").append('=').append(JodaBeanUtils.toString(yExtrapolatorLeft)).append(',').append(' ');
buf.append("yExtrapolatorRight").append('=').append(JodaBeanUtils.toString(yExtrapolatorRight));
buf.append('}');
return buf.toString();
}
}
///CLOVER:ON
//-------------------------- AUTOGENERATED END --------------------------
}