/*
 Copyright (C) 2008 Richard Gomes

 This source code is release under the BSD License.

 This file is part of JQuantLib, a free-software/open-source library
 for financial quantitative analysts and developers - http://jquantlib.org/

 JQuantLib is free software: you can redistribute it and/or modify it
 under the terms of the JQuantLib license.  You should have received a
 copy of the license along with this program; if not, please email
 . The license is also available online at
 .

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the license for more details.

 JQuantLib is based on QuantLib. http://quantlib.org/
 When applicable, the original copyright notice follows this notice.
 */

/*
 Copyright (C) 2002, 2003 Ferdinando Ametrano
 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl
 Copyright (C) 2003, 2004, 2005, 2006 StatPro Italia srl

 This file is part of QuantLib, a free-software/open-source library
 for financial quantitative analysts and developers - http://quantlib.org/

 QuantLib is free software: you can redistribute it and/or modify it
 under the terms of the QuantLib license.  You should have received a
 copy of the license along with this program; if not, please email
 . The license is also available online at
 .

 This program is distributed in the hope that it will be useful, but WITHOUT
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 FOR A PARTICULAR PURPOSE.  See the license for more details.
 */

package org.jquantlib.math.interpolations;

import static org.jquantlib.math.Closeness.isClose;

import org.jquantlib.QL;
import org.jquantlib.Settings;
import org.jquantlib.math.matrixutilities.Array;


/** Abstract base class for 1-D interpolations.
 * 

* Classes derived from this class will provide interpolated * values from two sequences of equal length, representing * discretized values of a variable and a function of the former, * respectively. * * @author Richard Gomes */ public abstract class AbstractInterpolation implements Interpolation { protected Impl impl; @Override public boolean empty() /* @ReadOnly */ { return impl==null; } @Override public /*@Real*/ double op(final /*@Real*/ double x) /* @ReadOnly */ { return op(x, false); } @Override public /*@Real*/ double op(final /*@Real*/ double x, final boolean allowExtrapolation) /* @ReadOnly */ { checkRange(x, allowExtrapolation); return impl.op(x); } @Override public /*@Real*/ double primitive(final /*@Real*/ double x) /* @ReadOnly */ { return primitive(x, false); } @Override public /*@Real*/ double primitive(final /*@Real*/ double x, final boolean allowExtrapolation) /* @ReadOnly */ { checkRange(x, allowExtrapolation); return impl.primitive(x); } @Override public /*@Real*/ double derivative(final /*@Real*/ double x) /* @ReadOnly */ { return derivative(x, false); } @Override public /*@Real*/ double derivative(final /*@Real*/ double x, final boolean allowExtrapolation) /* @ReadOnly */ { checkRange(x, allowExtrapolation); return impl.derivative(x); } @Override public /*@Real*/ double secondDerivative(final /*@Real*/ double x) /* @ReadOnly */ { return secondDerivative(x, false); } @Override public /*@Real*/ double secondDerivative(final /*@Real*/ double x, final boolean allowExtrapolation) /* @ReadOnly */ { checkRange(x, allowExtrapolation); return impl.secondDerivative(x); } @Override public /*@Real*/ double xMin() /* @ReadOnly */ { return impl.xMin(); } @Override public /*@Real*/ double xMax() /* @ReadOnly */ { return impl.xMax(); } @Override public boolean isInRange(final /*@Real*/ double x) /* @ReadOnly */ { return impl.isInRange(x); } @Override public void update() { impl.update(); } // // protected methods // /** * This method verifies if *

  • extrapolation is enabled;
  • *
  • requested x is valid
  • * * @param x * @param extrapolate * * @throws IllegalStateException if extrapolation is not enabled. * @throws IllegalArgumentException if x is out of range */ protected final void checkRange(final double x, final boolean extrapolate) /* @ReadOnly */ { if (! (extrapolate || allowsExtrapolation() || impl.isInRange(x)) ) { final StringBuilder sb = new StringBuilder(); sb.append("interpolation range is ["); sb.append(xMin()).append(", ").append(xMax()); sb.append("]: extrapolation at "); sb.append(x); sb.append(" not allowed"); throw new IllegalArgumentException(sb.toString()); } } // // implements Extrapolator // /** * Implements multiple inheritance via delegate pattern to an inner class * * @see Extrapolator */ private final DefaultExtrapolator delegatedExtrapolator = new DefaultExtrapolator(); @Override public final boolean allowsExtrapolation() { return delegatedExtrapolator.allowsExtrapolation(); } @Override public void disableExtrapolation() { delegatedExtrapolator.disableExtrapolation(); } @Override public void enableExtrapolation() { delegatedExtrapolator.enableExtrapolation(); } // // protected inner classes // protected abstract class Impl { /** * @note Derived classes are responsible for initializing vx and vy */ protected Array vx; /** * @note Derived classes are responsible for initializing vx and vy */ protected Array vy; protected Impl(final Array vx, final Array vy) { this.vx = vx; // TODO: clone? this.vy = vy; // TODO: clone? QL.require(vx.size() >= 2 , "not enough points to interpolate"); // TODO: message QL.require(extraSafetyChecks(), "unsorted values on array X"); // TODO: message } // // final public methods // public final double xMin() /* @ReadOnly */ { return vx.first(); } public final double xMax() /* @ReadOnly */ { return vx.last(); } public final boolean isInRange(final double x) { QL.require(extraSafetyChecks(), "unsorted values on array X"); // TODO: message final double x1 = xMin(), x2 = xMax(); return (x >= x1 && x <= x2) || isClose(x,x1) || isClose(x,x2); } public final double op(final double x, final boolean allowExtrapolation) { checkRange(x, allowExtrapolation); return op(x); } public final double primitive(final double x, final boolean allowExtrapolation) { checkRange(x, allowExtrapolation); return primitive(x); } public final double derivative(final double x, final boolean allowExtrapolation) { checkRange(x, allowExtrapolation); return derivative(x); } public final double secondDerivative(final double x, final boolean allowExtrapolation) { checkRange(x, allowExtrapolation); return secondDerivative(x); } // // virtual public methods // public abstract void update(); public abstract double op(final double x) /* @ReadOnly */; public abstract double primitive(final double x) /* @ReadOnly */; public abstract double derivative(final double x) /* @ReadOnly */; public abstract double secondDerivative(final double x) /* @ReadOnly */; // // protected methods // protected int locate(final double x) /* @ReadOnly */ { QL.require(extraSafetyChecks(), "unsorted values on array X"); // TODO: message if (x < vx.first()) return 0; else if (x > vx.last()) return vx.size()-2; else { //return vx.upperBound(x)-1; final int ub = vx.upperBound(vx.begin(), vx.end()-1, x)-1; return ub; } } // // private methods // private boolean extraSafetyChecks() { if (new Settings().isExtraSafetyChecks()) { for (int i=0; i vx.get(i+1)) return false; } } return true; } } protected class LogInterpolationImpl extends Impl { private final Array logY_; private final Interpolation interpolation_; public LogInterpolationImpl(final Array vx, final Array vy, final Interpolation.Interpolator factory) { super(vx, vy); this.logY_ = new Array(vx.size()); this.interpolation_ = factory.interpolate(vx, logY_); } @Override public void update() { for (int i=0; i0.0, "invalid value"); // TODO: message logY_.set(i, Math.log(vy.get(i))); } interpolation_.update(); } @Override public double op(final double x) /* @ReadOnly */ { return Math.exp(interpolation_.op(x, true)); } @Override public double primitive(final double x) /* @ReadOnly */ { throw new UnsupportedOperationException("LogInterpolation primitive not implemented"); // TODO: message } @Override public double derivative(final double x) /* @ReadOnly */ { return op(x)*interpolation_.derivative(x, true); } @Override public double secondDerivative(final double x) /* @ReadOnly */ { return derivative(x)*interpolation_.derivative(x, true) + op(x)*interpolation_.secondDerivative(x, true); } } }

    Ads help maintain this website.