/** * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies * * Please see distribution for license. */ package com.opengamma.analytics.math.curve; import java.util.Map; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.Validate; import org.joda.beans.Bean; import org.joda.beans.BeanBuilder; import org.joda.beans.BeanDefinition; 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.DirectBeanBuilder; import org.joda.beans.impl.direct.DirectMetaProperty; import org.joda.beans.impl.direct.DirectMetaPropertyMap; import com.opengamma.analytics.math.differentiation.ScalarFirstOrderDifferentiator; import com.opengamma.analytics.math.function.Function1D; import com.opengamma.analytics.math.interpolation.Interpolator1D; import com.opengamma.util.ArgumentChecker; /** * A curve that is defined by a function (i.e. <i>y = f(x)</i>, where <i>f(x)</i> is supplied). */ @BeanDefinition public class FunctionalDoublesCurve extends DoublesCurve { private static final ScalarFirstOrderDifferentiator DIFF = new ScalarFirstOrderDifferentiator(); /** * The function. */ @PropertyDefinition(validate = "notNull", get = "manual", set = "private") private Function1D<Double, Double> _function; /** * The first derivative function. */ @PropertyDefinition(validate = "notNull", get = "private", set = "private") private Function1D<Double, Double> _derivative; //------------------------------------------------------------------------- /** * Obtains the curve. * * @param function the function that defines the curve, not null * @return a functional curve with an automatically-generated name, not null */ public static FunctionalDoublesCurve from(final Function1D<Double, Double> function) { return new FunctionalDoublesCurve(function); } /** * Obtains the curve. * * @param function the function that defines the curve, not null * @param derivative the first derivative for the function, not null * @return A functional curve with an automatically-generated name, not null */ public static FunctionalDoublesCurve from(final Function1D<Double, Double> function, final Function1D<Double, Double> derivative) { return new FunctionalDoublesCurve(function, derivative); } /** * Obtains the curve. * * @param function the function that defines the curve, not null * @param name the name of the curve, not null * @return a functional curve, not null */ public static FunctionalDoublesCurve from(final Function1D<Double, Double> function, final String name) { return new FunctionalDoublesCurve(function, name); } /** * Obtains the curve. * * @param function the function that defines the curve, not null * @param derivative the first derivative for the function, not null * @param name the name of the curve, not null * @return a functional curve, not null */ public static FunctionalDoublesCurve from(final Function1D<Double, Double> function, final Function1D<Double, Double> derivative, final String name) { return new FunctionalDoublesCurve(function, derivative, name); } //------------------------------------------------------------------------- /** * Constructor for Joda-Beans. */ protected FunctionalDoublesCurve() { } /** * Creates a curve. * * @param function the function that defines the curve, not null */ public FunctionalDoublesCurve(final Function1D<Double, Double> function) { super(); Validate.notNull(function, "function"); _function = function; _derivative = DIFF.differentiate(_function); } /** * Creates a curve. * * @param function the function that defines the curve, not null * @param derivative the first derivative for the function, not null */ private FunctionalDoublesCurve(final Function1D<Double, Double> function, final Function1D<Double, Double> derivative) { super(); ArgumentChecker.notNull(function, "function"); ArgumentChecker.notNull(derivative, "derivative"); _function = function; _derivative = derivative; } /** * Creates a curve. * * @param function the function that defines the curve, not null * @param name the name of the curve, not null */ public FunctionalDoublesCurve(final Function1D<Double, Double> function, final String name) { super(name); Validate.notNull(function, "function"); _function = function; _derivative = DIFF.differentiate(_function); } /** * Creates a curve. * * @param function the function that defines the curve, not null * @param derivative the first derivative for the function, not null * @param name the name of the curve, not null */ private FunctionalDoublesCurve(final Function1D<Double, Double> function, final Function1D<Double, Double> derivative, final String name) { super(name); ArgumentChecker.notNull(function, "function"); ArgumentChecker.notNull(derivative, "derivative"); _function = function; _derivative = derivative; } //------------------------------------------------------------------------- /** * Throws an exception as there is no <i>x</i> data. * * @return throws UnsupportedOperationException * @throws UnsupportedOperationException always */ @Override public Double[] getXData() { throw new UnsupportedOperationException("Cannot get x data - this curve is defined by a function (x -> y)"); } /** * Throws an exception as there is no <i>y</i> data. * * @return throws UnsupportedOperationException * @throws UnsupportedOperationException always */ @Override public Double[] getYData() { throw new UnsupportedOperationException("Cannot get y data - this curve is defined by a function (x -> y)"); } @Override public Double getYValue(final Double x) { Validate.notNull(x, "x"); return _function.evaluate(x); } @Override public double getDyDx(final double x) { return _derivative.evaluate(x); } @Override public Double[] getYValueParameterSensitivity(final Double x) { throw new UnsupportedOperationException("Parameter sensitivity not supported yet for FunctionalDoublesCurve"); } /** * Throws an exception as there is no <i>x</i> or <i>y</i> data. * * @return throws UnsupportedOperationException * @throws UnsupportedOperationException always */ @Override public int size() { throw new UnsupportedOperationException("Cannot get size - this curve is defined by a function (x -> y)"); } /** * Creates an interpolated curve using the specified <i>x</i> values and the evaluated <i>y</i> values. * * @param x the array of <i>x</i> values, not null * @param interpolator the interpolator, not null * @return the interpolated curve with values <i>(x, f(x))</i>, not null */ public InterpolatedDoublesCurve toInterpolatedDoublesCurve(final double[] x, final Interpolator1D interpolator) { Validate.notNull(x, "x"); Validate.notNull(interpolator); final int n = x.length; final double[] y = new double[n]; for (int i = 0; i < n; i++) { y[i] = _function.evaluate(x[i]); } return InterpolatedDoublesCurve.from(x, y, interpolator); } /** * Gets the function. * * @return the function, not null */ public Function1D<Double, Double> getFunction() { return _function; } /** * Gets the first derivative function. * * @return the function, not null */ public Function1D<Double, Double> getFirstDerivativeFunction() { return _derivative; } //------------------------------------------------------------------------- @Override public boolean equals(final Object obj) { if (this == obj) { return true; } if (!super.equals(obj)) { return false; } if (getClass() != obj.getClass()) { return false; } final FunctionalDoublesCurve other = (FunctionalDoublesCurve) obj; return ObjectUtils.equals(_function, other._function); } @Override public int hashCode() { final int prime = 31; int result = super.hashCode(); result = prime * result + _function.hashCode(); return result; } //------------------------- AUTOGENERATED START ------------------------- ///CLOVER:OFF /** * The meta-bean for {@code FunctionalDoublesCurve}. * @return the meta-bean, not null */ public static FunctionalDoublesCurve.Meta meta() { return FunctionalDoublesCurve.Meta.INSTANCE; } static { JodaBeanUtils.registerMetaBean(FunctionalDoublesCurve.Meta.INSTANCE); } @Override public FunctionalDoublesCurve.Meta metaBean() { return FunctionalDoublesCurve.Meta.INSTANCE; } //----------------------------------------------------------------------- /** * Sets the function. * @param function the new value of the property, not null */ private void setFunction(Function1D<Double, Double> function) { JodaBeanUtils.notNull(function, "function"); this._function = function; } /** * Gets the the {@code function} property. * @return the property, not null */ public final Property<Function1D<Double, Double>> function() { return metaBean().function().createProperty(this); } //----------------------------------------------------------------------- /** * Gets the first derivative function. * @return the value of the property, not null */ private Function1D<Double, Double> getDerivative() { return _derivative; } /** * Sets the first derivative function. * @param derivative the new value of the property, not null */ private void setDerivative(Function1D<Double, Double> derivative) { JodaBeanUtils.notNull(derivative, "derivative"); this._derivative = derivative; } /** * Gets the the {@code derivative} property. * @return the property, not null */ public final Property<Function1D<Double, Double>> derivative() { return metaBean().derivative().createProperty(this); } //----------------------------------------------------------------------- @Override public FunctionalDoublesCurve clone() { return JodaBeanUtils.cloneAlways(this); } @Override public String toString() { StringBuilder buf = new StringBuilder(96); buf.append("FunctionalDoublesCurve{"); int len = buf.length(); toString(buf); if (buf.length() > len) { buf.setLength(buf.length() - 2); } buf.append('}'); return buf.toString(); } @Override protected void toString(StringBuilder buf) { super.toString(buf); buf.append("function").append('=').append(JodaBeanUtils.toString(getFunction())).append(',').append(' '); buf.append("derivative").append('=').append(JodaBeanUtils.toString(getDerivative())).append(',').append(' '); } //----------------------------------------------------------------------- /** * The meta-bean for {@code FunctionalDoublesCurve}. */ public static class Meta extends DoublesCurve.Meta { /** * The singleton instance of the meta-bean. */ static final Meta INSTANCE = new Meta(); /** * The meta-property for the {@code function} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty<Function1D<Double, Double>> _function = DirectMetaProperty.ofReadWrite( this, "function", FunctionalDoublesCurve.class, (Class) Function1D.class); /** * The meta-property for the {@code derivative} property. */ @SuppressWarnings({"unchecked", "rawtypes" }) private final MetaProperty<Function1D<Double, Double>> _derivative = DirectMetaProperty.ofReadWrite( this, "derivative", FunctionalDoublesCurve.class, (Class) Function1D.class); /** * The meta-properties. */ private final Map<String, MetaProperty<?>> _metaPropertyMap$ = new DirectMetaPropertyMap( this, (DirectMetaPropertyMap) super.metaPropertyMap(), "function", "derivative"); /** * Restricted constructor. */ protected Meta() { } @Override protected MetaProperty<?> metaPropertyGet(String propertyName) { switch (propertyName.hashCode()) { case 1380938712: // function return _function; case -1353885305: // derivative return _derivative; } return super.metaPropertyGet(propertyName); } @Override public BeanBuilder<? extends FunctionalDoublesCurve> builder() { return new DirectBeanBuilder<FunctionalDoublesCurve>(new FunctionalDoublesCurve()); } @Override public Class<? extends FunctionalDoublesCurve> beanType() { return FunctionalDoublesCurve.class; } @Override public Map<String, MetaProperty<?>> metaPropertyMap() { return _metaPropertyMap$; } //----------------------------------------------------------------------- /** * The meta-property for the {@code function} property. * @return the meta-property, not null */ public final MetaProperty<Function1D<Double, Double>> function() { return _function; } /** * The meta-property for the {@code derivative} property. * @return the meta-property, not null */ public final MetaProperty<Function1D<Double, Double>> derivative() { return _derivative; } //----------------------------------------------------------------------- @Override protected Object propertyGet(Bean bean, String propertyName, boolean quiet) { switch (propertyName.hashCode()) { case 1380938712: // function return ((FunctionalDoublesCurve) bean).getFunction(); case -1353885305: // derivative return ((FunctionalDoublesCurve) bean).getDerivative(); } return super.propertyGet(bean, propertyName, quiet); } @SuppressWarnings("unchecked") @Override protected void propertySet(Bean bean, String propertyName, Object newValue, boolean quiet) { switch (propertyName.hashCode()) { case 1380938712: // function ((FunctionalDoublesCurve) bean).setFunction((Function1D<Double, Double>) newValue); return; case -1353885305: // derivative ((FunctionalDoublesCurve) bean).setDerivative((Function1D<Double, Double>) newValue); return; } super.propertySet(bean, propertyName, newValue, quiet); } @Override protected void validate(Bean bean) { JodaBeanUtils.notNull(((FunctionalDoublesCurve) bean)._function, "function"); JodaBeanUtils.notNull(((FunctionalDoublesCurve) bean)._derivative, "derivative"); super.validate(bean); } } ///CLOVER:ON //-------------------------- AUTOGENERATED END -------------------------- }