/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.commons.math.ode.jacobians;

import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;

import org.apache.commons.math.MathRuntimeException;
import org.apache.commons.math.MaxEvaluationsExceededException;
import org.apache.commons.math.ode.DerivativeException;
import org.apache.commons.math.exception.util.LocalizedFormats;
import org.apache.commons.math.ode.ExtendedFirstOrderDifferentialEquations;
import org.apache.commons.math.ode.FirstOrderIntegrator;
import org.apache.commons.math.ode.IntegratorException;
import org.apache.commons.math.ode.events.EventException;
import org.apache.commons.math.ode.events.EventHandler;
import org.apache.commons.math.ode.sampling.StepHandler;
import org.apache.commons.math.ode.sampling.StepInterpolator;

/** This class enhances a first order integrator for differential equations to
 * compute also partial derivatives of the solution with respect to initial state
 * and parameters.
 * <p>In order to compute both the state and its derivatives, the ODE problem
 * is extended with jacobians of the raw ODE and the variational equations are
 * added to form a new compound problem of higher dimension. If the original ODE
 * problem has dimension n and there are p parameters, the compound problem will
 * have dimension n &times; (1 + n + p).</p>
 * @see ParameterizedODE
 * @see ODEWithJacobians
 * @version $Revision: 1073158 $ $Date: 2011-02-21 22:46:52 +0100 (lun. 21 févr. 2011) $
 * @since 2.1
 * @deprecated as of 2.2 the complete package is deprecated, it will be replaced
 * in 3.0 by a completely rewritten implementation
 */
@Deprecated
public class FirstOrderIntegratorWithJacobians {

    /** Underlying integrator for compound problem. */
    private final FirstOrderIntegrator integrator;

    /** Raw equations to integrate. */
    private final ODEWithJacobians ode;

    /** Maximal number of evaluations allowed. */
    private int maxEvaluations;

    /** Number of evaluations already performed. */
    private int evaluations;

    /** Build an enhanced integrator using internal differentiation to compute jacobians.
     * @param integrator underlying integrator to solve the compound problem
     * @param ode original problem (f in the equation y' = f(t, y))
     * @param p parameters array (may be null if {@link
     * ParameterizedODE#getParametersDimension()
     * getParametersDimension()} from original problem is zero)
     * @param hY step sizes to use for computing the jacobian df/dy, must have the
     * same dimension as the original problem
     * @param hP step sizes to use for computing the jacobian df/dp, must have the
     * same dimension as the original problem parameters dimension
     * @see #FirstOrderIntegratorWithJacobians(FirstOrderIntegrator,
     * ODEWithJacobians)
     */
    public FirstOrderIntegratorWithJacobians(final FirstOrderIntegrator integrator,
                                             final ParameterizedODE ode,
                                             final double[] p, final double[] hY, final double[] hP) {
        checkDimension(ode.getDimension(), hY);
        checkDimension(ode.getParametersDimension(), p);
        checkDimension(ode.getParametersDimension(), hP);
        this.integrator = integrator;
        this.ode = new FiniteDifferencesWrapper(ode, p, hY, hP);
        setMaxEvaluations(-1);
    }

    /** Build an enhanced integrator using ODE builtin jacobian computation features.
     * @param integrator underlying integrator to solve the compound problem
     * @param ode original problem, which can compute the jacobians by itself
     * @see #FirstOrderIntegratorWithJacobians(FirstOrderIntegrator,
     * ParameterizedODE, double[], double[], double[])
     */
    public FirstOrderIntegratorWithJacobians(final FirstOrderIntegrator integrator,
                                             final ODEWithJacobians ode) {
        this.integrator = integrator;
        this.ode = ode;
        setMaxEvaluations(-1);
    }

    /** Add a step handler to this integrator.
     * <p>The handler will be called by the integrator for each accepted
     * step.</p>
     * @param handler handler for the accepted steps
     * @see #getStepHandlers()
     * @see #clearStepHandlers()
     */
    public void addStepHandler(StepHandlerWithJacobians handler) {
        final int n = ode.getDimension();
        final int k = ode.getParametersDimension();
        integrator.addStepHandler(new StepHandlerWrapper(handler, n, k));
    }

    /** Get all the step handlers that have been added to the integrator.
     * @return an unmodifiable collection of the added events handlers
     * @see #addStepHandler(StepHandlerWithJacobians)
     * @see #clearStepHandlers()
     */
    public Collection<StepHandlerWithJacobians> getStepHandlers() {
        final Collection<StepHandlerWithJacobians> handlers =
            new ArrayList<StepHandlerWithJacobians>();
        for (final StepHandler handler : integrator.getStepHandlers()) {
            if (handler instanceof StepHandlerWrapper) {
                handlers.add(((StepHandlerWrapper) handler).getHandler());
            }
        }
        return handlers;
    }

    /** Remove all the step handlers that have been added to the integrator.
     * @see #addStepHandler(StepHandlerWithJacobians)
     * @see #getStepHandlers()
     */
    public void clearStepHandlers() {
        integrator.clearStepHandlers();
    }

    /** Add an event handler to the integrator.
     * @param handler event handler
     * @param maxCheckInterval maximal time interval between switching
     * function checks (this interval prevents missing sign changes in
     * case the integration steps becomes very large)
     * @param convergence convergence threshold in the event time search
     * @param maxIterationCount upper limit of the iteration count in
     * the event time search
     * @see #getEventHandlers()
     * @see #clearEventHandlers()
     */
    public void addEventHandler(EventHandlerWithJacobians handler,
                                double maxCheckInterval,
                                double convergence,
                                int maxIterationCount) {
        final int n = ode.getDimension();
        final int k = ode.getParametersDimension();
        integrator.addEventHandler(new EventHandlerWrapper(handler, n, k),
                                   maxCheckInterval, convergence, maxIterationCount);
    }

    /** Get all the event handlers that have been added to the integrator.
     * @return an unmodifiable collection of the added events handlers
     * @see #addEventHandler(EventHandlerWithJacobians, double, double, int)
     * @see #clearEventHandlers()
     */
    public Collection<EventHandlerWithJacobians> getEventHandlers() {
        final Collection<EventHandlerWithJacobians> handlers =
            new ArrayList<EventHandlerWithJacobians>();
        for (final EventHandler handler : integrator.getEventHandlers()) {
            if (handler instanceof EventHandlerWrapper) {
                handlers.add(((EventHandlerWrapper) handler).getHandler());
            }
        }
        return handlers;
    }

    /** Remove all the event handlers that have been added to the integrator.
     * @see #addEventHandler(EventHandlerWithJacobians, double, double, int)
     * @see #getEventHandlers()
     */
    public void clearEventHandlers() {
        integrator.clearEventHandlers();
    }

    /** Integrate the differential equations and the variational equations up to the given time.
     * <p>This method solves an Initial Value Problem (IVP) and also computes the derivatives
     * of the solution with respect to initial state and parameters. This can be used as
     * a basis to solve Boundary Value Problems (BVP).</p>
     * <p>Since this method stores some internal state variables made
     * available in its public interface during integration ({@link
     * #getCurrentSignedStepsize()}), it is <em>not</em> thread-safe.</p>
     * @param t0 initial time
     * @param y0 initial value of the state vector at t0
     * @param dY0dP initial value of the state vector derivative with respect to the
     * parameters at t0
     * @param t target time for the integration
     * (can be set to a value smaller than <code>t0</code> for backward integration)
     * @param y placeholder where to put the state vector at each successful
     *  step (and hence at the end of integration), can be the same object as y0
     * @param dYdY0 placeholder where to put the state vector derivative with respect
     * to the initial state (dy[i]/dy0[j] is in element array dYdY0[i][j]) at each successful
     *  step (and hence at the end of integration)
     * @param dYdP placeholder where to put the state vector derivative with respect
     * to the parameters (dy[i]/dp[j] is in element array dYdP[i][j]) at each successful
     *  step (and hence at the end of integration)
     * @return stop time, will be the same as target time if integration reached its
     * target, but may be different if some event handler stops it at some point.
     * @throws IntegratorException if the integrator cannot perform integration
     * @throws DerivativeException this exception is propagated to the caller if
     * the underlying user function triggers one
     */
    public double integrate(final double t0, final double[] y0, final double[][] dY0dP,
                            final double t, final double[] y,
                            final double[][] dYdY0, final double[][] dYdP)
        throws DerivativeException, IntegratorException {

        final int n = ode.getDimension();
        final int k = ode.getParametersDimension();
        checkDimension(n, y0);
        checkDimension(n, y);
        checkDimension(n, dYdY0);
        checkDimension(n, dYdY0[0]);
        if (k != 0) {
            checkDimension(n, dY0dP);
            checkDimension(k, dY0dP[0]);
            checkDimension(n, dYdP);
            checkDimension(k, dYdP[0]);
        }

        // set up initial state, including partial derivatives
        // the compound state z contains the raw state y and its derivatives
        // with respect to initial state y0 and to parameters p
        //    y[i]         is stored in z[i]
        //    dy[i]/dy0[j] is stored in z[n + i * n + j]
        //    dy[i]/dp[j]  is stored in z[n * (n + 1) + i * k + j]
        final double[] z = new double[n * (1 + n + k)];
        System.arraycopy(y0, 0, z, 0, n);
        for (int i = 0; i < n; ++i) {

            // set diagonal element of dy/dy0 to 1.0 at t = t0
            z[i * (1 + n) + n] = 1.0;

            // set initial derivatives with respect to parameters
            System.arraycopy(dY0dP[i], 0, z, n * (n + 1) + i * k, k);

        }

        // integrate the compound state variational equations
        evaluations = 0;
        final double stopTime = integrator.integrate(new MappingWrapper(), t0, z, t, z);

        // dispatch the final compound state into the state and partial derivatives arrays
        dispatchCompoundState(z, y, dYdY0, dYdP);

        return stopTime;

    }

    /** Dispatch a compound state array into state and jacobians arrays.
     * @param z compound state
     * @param y raw state array to fill
     * @param dydy0 jacobian array to fill
     * @param dydp jacobian array to fill
     */
    private static void dispatchCompoundState(final double[] z, final double[] y,
                                              final double[][] dydy0, final double[][] dydp) {

        final int n = y.length;
        final int k = dydp[0].length;

        // state
        System.arraycopy(z, 0, y, 0, n);

        // jacobian with respect to initial state
        for (int i = 0; i < n; ++i) {
            System.arraycopy(z, n * (i + 1), dydy0[i], 0, n);
        }

        // jacobian with respect to parameters
        for (int i = 0; i < n; ++i) {
            System.arraycopy(z, n * (n + 1) + i * k, dydp[i], 0, k);
        }

    }

    /** Get the current value of the step start time t<sub>i</sub>.
     * <p>This method can be called during integration (typically by
     * the object implementing the {@link org.apache.commons.math.ode.FirstOrderDifferentialEquations
     * differential equations} problem) if the value of the current step that
     * is attempted is needed.</p>
     * <p>The result is undefined if the method is called outside of
     * calls to <code>integrate</code>.</p>
     * @return current value of the step start time t<sub>i</sub>
     */
    public double getCurrentStepStart() {
        return integrator.getCurrentStepStart();
    }

    /** Get the current signed value of the integration stepsize.
     * <p>This method can be called during integration (typically by
     * the object implementing the {@link org.apache.commons.math.ode.FirstOrderDifferentialEquations
     * differential equations} problem) if the signed value of the current stepsize
     * that is tried is needed.</p>
     * <p>The result is undefined if the method is called outside of
     * calls to <code>integrate</code>.</p>
     * @return current signed value of the stepsize
     */
    public double getCurrentSignedStepsize() {
        return integrator.getCurrentSignedStepsize();
    }

    /** Set the maximal number of differential equations function evaluations.
     * <p>The purpose of this method is to avoid infinite loops which can occur
     * for example when stringent error constraints are set or when lots of
     * discrete events are triggered, thus leading to many rejected steps.</p>
     * @param maxEvaluations maximal number of function evaluations (negative
     * values are silently converted to maximal integer value, thus representing
     * almost unlimited evaluations)
     */
    public void setMaxEvaluations(int maxEvaluations) {
        this.maxEvaluations = (maxEvaluations < 0) ? Integer.MAX_VALUE : maxEvaluations;
    }

    /** Get the maximal number of functions evaluations.
     * @return maximal number of functions evaluations
     */
    public int getMaxEvaluations() {
        return maxEvaluations;
    }

    /** Get the number of evaluations of the differential equations function.
     * <p>
     * The number of evaluations corresponds to the last call to the
     * <code>integrate</code> method. It is 0 if the method has not been called yet.
     * </p>
     * @return number of evaluations of the differential equations function
     */
    public int getEvaluations() {
        return evaluations;
    }

    /** Check array dimensions.
     * @param expected expected dimension
     * @param array (may be null if expected is 0)
     * @throws IllegalArgumentException if the array dimension does not match the expected one
     */
    private void checkDimension(final int expected, final Object array)
        throws IllegalArgumentException {
        int arrayDimension = (array == null) ? 0 : Array.getLength(array);
        if (arrayDimension != expected) {
            throw MathRuntimeException.createIllegalArgumentException(
                  LocalizedFormats.DIMENSIONS_MISMATCH_SIMPLE, arrayDimension, expected);
        }
    }

    /** Wrapper class used to map state and jacobians into compound state. */
    private class MappingWrapper implements  ExtendedFirstOrderDifferentialEquations {

        /** Current state. */
        private final double[]   y;

        /** Time derivative of the current state. */
        private final double[]   yDot;

        /** Derivatives of yDot with respect to state. */
        private final double[][] dFdY;

        /** Derivatives of yDot with respect to parameters. */
        private final double[][] dFdP;

        /** Simple constructor.
         */
        public MappingWrapper() {

            final int n = ode.getDimension();
            final int k = ode.getParametersDimension();
            y    = new double[n];
            yDot = new double[n];
            dFdY = new double[n][n];
            dFdP = new double[n][k];

        }

        /** {@inheritDoc} */
        public int getDimension() {
            final int n = y.length;
            final int k = dFdP[0].length;
            return n * (1 + n + k);
        }

        /** {@inheritDoc} */
        public int getMainSetDimension() {
            return ode.getDimension();
        }

        /** {@inheritDoc} */
        public void computeDerivatives(final double t, final double[] z, final double[] zDot)
            throws DerivativeException {

            final int n = y.length;
            final int k = dFdP[0].length;

            // compute raw ODE and its jacobians: dy/dt, d[dy/dt]/dy0 and d[dy/dt]/dp
            System.arraycopy(z,    0, y,    0, n);
            if (++evaluations > maxEvaluations) {
                throw new DerivativeException(new MaxEvaluationsExceededException(maxEvaluations));
            }
            ode.computeDerivatives(t, y, yDot);
            ode.computeJacobians(t, y, yDot, dFdY, dFdP);

            // state part of the compound equations
            System.arraycopy(yDot, 0, zDot, 0, n);

            // variational equations: from d[dy/dt]/dy0 to d[dy/dy0]/dt
            for (int i = 0; i < n; ++i) {
                final double[] dFdYi = dFdY[i];
                for (int j = 0; j < n; ++j) {
                    double s = 0;
                    final int startIndex = n + j;
                    int zIndex = startIndex;
                    for (int l = 0; l < n; ++l) {
                        s += dFdYi[l] * z[zIndex];
                        zIndex += n;
                    }
                    zDot[startIndex + i * n] = s;
                }
            }

            // variational equations: from d[dy/dt]/dy0 and d[dy/dt]/dp to d[dy/dp]/dt
            for (int i = 0; i < n; ++i) {
                final double[] dFdYi = dFdY[i];
                final double[] dFdPi = dFdP[i];
                for (int j = 0; j < k; ++j) {
                    double s = dFdPi[j];
                    final int startIndex = n * (n + 1) + j;
                    int zIndex = startIndex;
                    for (int l = 0; l < n; ++l) {
                        s += dFdYi[l] * z[zIndex];
                        zIndex += k;
                    }
                    zDot[startIndex + i * k] = s;
                }
            }

        }

    }

    /** Wrapper class to compute jacobians by finite differences for ODE which do not compute them themselves. */
    private class FiniteDifferencesWrapper implements ODEWithJacobians {

        /** Raw ODE without jacobians computation. */
        private final ParameterizedODE ode;

        /** Parameters array (may be null if parameters dimension from original problem is zero) */
        private final double[] p;

        /** Step sizes to use for computing the jacobian df/dy. */
        private final double[] hY;

        /** Step sizes to use for computing the jacobian df/dp. */
        private final double[] hP;

        /** Temporary array for state derivatives used to compute jacobians. */
        private final double[] tmpDot;

        /** Simple constructor.
         * @param ode original ODE problem, without jacobians computations
         * @param p parameters array (may be null if parameters dimension from original problem is zero)
         * @param hY step sizes to use for computing the jacobian df/dy
         * @param hP step sizes to use for computing the jacobian df/dp
         */
        public FiniteDifferencesWrapper(final ParameterizedODE ode,
                                        final double[] p, final double[] hY, final double[] hP) {
            this.ode = ode;
            this.p  = p.clone();
            this.hY = hY.clone();
            this.hP = hP.clone();
            tmpDot = new double[ode.getDimension()];
        }

        /** {@inheritDoc} */
        public int getDimension() {
            return ode.getDimension();
        }

        /** {@inheritDoc} */
        public void computeDerivatives(double t, double[] y, double[] yDot) throws DerivativeException {
            // this call to computeDerivatives has already been counted,
            // we must not increment the counter again
            ode.computeDerivatives(t, y, yDot);
        }

        /** {@inheritDoc} */
        public int getParametersDimension() {
            return ode.getParametersDimension();
        }

        /** {@inheritDoc} */
        public void computeJacobians(double t, double[] y, double[] yDot,
                                     double[][] dFdY, double[][] dFdP)
            throws DerivativeException {

            final int n = hY.length;
            final int k = hP.length;

            evaluations += n + k;
            if (evaluations > maxEvaluations) {
                throw new DerivativeException(new MaxEvaluationsExceededException(maxEvaluations));
            }

            // compute df/dy where f is the ODE and y is the state array
            for (int j = 0; j < n; ++j) {
                final double savedYj = y[j];
                y[j] += hY[j];
                ode.computeDerivatives(t, y, tmpDot);
                for (int i = 0; i < n; ++i) {
                    dFdY[i][j] = (tmpDot[i] - yDot[i]) / hY[j];
                }
                y[j] = savedYj;
            }

            // compute df/dp where f is the ODE and p is the parameters array
            for (int j = 0; j < k; ++j) {
                ode.setParameter(j, p[j] +  hP[j]);
                ode.computeDerivatives(t, y, tmpDot);
                for (int i = 0; i < n; ++i) {
                    dFdP[i][j] = (tmpDot[i] - yDot[i]) / hP[j];
                }
                ode.setParameter(j, p[j]);
            }

        }

    }

    /** Wrapper for step handlers. */
    private static class StepHandlerWrapper implements StepHandler {

        /** Underlying step handler with jacobians. */
        private final StepHandlerWithJacobians handler;

        /** Dimension of the original ODE. */
        private final int n;

        /** Number of parameters. */
        private final int k;

        /** Simple constructor.
         * @param handler underlying step handler with jacobians
         * @param n dimension of the original ODE
         * @param k number of parameters
         */
        public StepHandlerWrapper(final StepHandlerWithJacobians handler,
                                  final int n, final int k) {
            this.handler = handler;
            this.n       = n;
            this.k       = k;
        }

        /** Get the underlying step handler with jacobians.
         * @return underlying step handler with jacobians
         */
        public StepHandlerWithJacobians getHandler() {
            return handler;
        }

        /** {@inheritDoc} */
        public void handleStep(StepInterpolator interpolator, boolean isLast)
            throws DerivativeException {
            handler.handleStep(new StepInterpolatorWrapper(interpolator, n, k), isLast);
        }

        /** {@inheritDoc} */
        public boolean requiresDenseOutput() {
            return handler.requiresDenseOutput();
        }

        /** {@inheritDoc} */
        public void reset() {
            handler.reset();
        }

    }

    /** Wrapper for step interpolators. */
    private static class StepInterpolatorWrapper
        implements StepInterpolatorWithJacobians {

        /** Wrapped interpolator. */
        private StepInterpolator interpolator;

        /** State array. */
        private double[] y;

        /** Jacobian with respect to initial state dy/dy0. */
        private double[][] dydy0;

        /** Jacobian with respect to parameters dy/dp. */
        private double[][] dydp;

        /** Time derivative of the state array. */
        private double[] yDot;

        /** Time derivative of the sacobian with respect to initial state dy/dy0. */
        private double[][] dydy0Dot;

        /** Time derivative of the jacobian with respect to parameters dy/dp. */
        private double[][] dydpDot;

        /** Simple constructor.
         * <p>This constructor is used only for externalization. It does nothing.</p>
         */
        @SuppressWarnings("unused")
        public StepInterpolatorWrapper() {
        }

        /** Simple constructor.
         * @param interpolator wrapped interpolator
         * @param n dimension of the original ODE
         * @param k number of parameters
         */
        public StepInterpolatorWrapper(final StepInterpolator interpolator,
                                       final int n, final int k) {
            this.interpolator = interpolator;
            y        = new double[n];
            dydy0    = new double[n][n];
            dydp     = new double[n][k];
            yDot     = new double[n];
            dydy0Dot = new double[n][n];
            dydpDot  = new double[n][k];
        }

        /** {@inheritDoc} */
        public void setInterpolatedTime(double time) {
            interpolator.setInterpolatedTime(time);
        }

        /** {@inheritDoc} */
        public boolean isForward() {
            return interpolator.isForward();
        }

        /** {@inheritDoc} */
        public double getPreviousTime() {
            return interpolator.getPreviousTime();
        }

        /** {@inheritDoc} */
        public double getInterpolatedTime() {
            return interpolator.getInterpolatedTime();
        }

        /** {@inheritDoc} */
        public double[] getInterpolatedY() throws DerivativeException {
            double[] extendedState = interpolator.getInterpolatedState();
            System.arraycopy(extendedState, 0, y, 0, y.length);
            return y;
        }

        /** {@inheritDoc} */
        public double[][] getInterpolatedDyDy0() throws DerivativeException {
            double[] extendedState = interpolator.getInterpolatedState();
            final int n = y.length;
            int start = n;
            for (int i = 0; i < n; ++i) {
                System.arraycopy(extendedState, start, dydy0[i], 0, n);
                start += n;
            }
            return dydy0;
        }

        /** {@inheritDoc} */
        public double[][] getInterpolatedDyDp() throws DerivativeException {
            double[] extendedState = interpolator.getInterpolatedState();
            final int n = y.length;
            final int k = dydp[0].length;
            int start = n * (n + 1);
            for (int i = 0; i < n; ++i) {
                System.arraycopy(extendedState, start, dydp[i], 0, k);
                start += k;
            }
            return dydp;
        }

        /** {@inheritDoc} */
        public double[] getInterpolatedYDot() throws DerivativeException {
            double[] extendedDerivatives = interpolator.getInterpolatedDerivatives();
            System.arraycopy(extendedDerivatives, 0, yDot, 0, yDot.length);
            return yDot;
        }

        /** {@inheritDoc} */
        public double[][] getInterpolatedDyDy0Dot() throws DerivativeException {
            double[] extendedDerivatives = interpolator.getInterpolatedDerivatives();
            final int n = y.length;
            int start = n;
            for (int i = 0; i < n; ++i) {
                System.arraycopy(extendedDerivatives, start, dydy0Dot[i], 0, n);
                start += n;
            }
            return dydy0Dot;
        }

        /** {@inheritDoc} */
        public double[][] getInterpolatedDyDpDot() throws DerivativeException {
            double[] extendedDerivatives = interpolator.getInterpolatedDerivatives();
            final int n = y.length;
            final int k = dydpDot[0].length;
            int start = n * (n + 1);
            for (int i = 0; i < n; ++i) {
                System.arraycopy(extendedDerivatives, start, dydpDot[i], 0, k);
                start += k;
            }
            return dydpDot;
        }

        /** {@inheritDoc} */
        public double getCurrentTime() {
            return interpolator.getCurrentTime();
        }

        /** {@inheritDoc} */
        public StepInterpolatorWithJacobians copy() throws DerivativeException {
            final int n = y.length;
            final int k = dydp[0].length;
            StepInterpolatorWrapper copied =
                new StepInterpolatorWrapper(interpolator.copy(), n, k);
            copyArray(y,        copied.y);
            copyArray(dydy0,    copied.dydy0);
            copyArray(dydp,     copied.dydp);
            copyArray(yDot,     copied.yDot);
            copyArray(dydy0Dot, copied.dydy0Dot);
            copyArray(dydpDot,  copied.dydpDot);
            return copied;
        }

        /** {@inheritDoc} */
        public void writeExternal(ObjectOutput out) throws IOException {
            out.writeObject(interpolator);
            out.writeInt(y.length);
            out.writeInt(dydp[0].length);
            writeArray(out, y);
            writeArray(out, dydy0);
            writeArray(out, dydp);
            writeArray(out, yDot);
            writeArray(out, dydy0Dot);
            writeArray(out, dydpDot);
        }

        /** {@inheritDoc} */
        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            interpolator = (StepInterpolator) in.readObject();
            final int n = in.readInt();
            final int k = in.readInt();
            y        = new double[n];
            dydy0    = new double[n][n];
            dydp     = new double[n][k];
            yDot     = new double[n];
            dydy0Dot = new double[n][n];
            dydpDot  = new double[n][k];
            readArray(in, y);
            readArray(in, dydy0);
            readArray(in, dydp);
            readArray(in, yDot);
            readArray(in, dydy0Dot);
            readArray(in, dydpDot);
        }

        /** Copy an array.
         * @param src source array
         * @param dest destination array
         */
        private static void copyArray(final double[] src, final double[] dest) {
            System.arraycopy(src, 0, dest, 0, src.length);
        }

        /** Copy an array.
         * @param src source array
         * @param dest destination array
         */
        private static void copyArray(final double[][] src, final double[][] dest) {
            for (int i = 0; i < src.length; ++i) {
                copyArray(src[i], dest[i]);
            }
        }

        /** Write an array.
         * @param out output stream
         * @param array array to write
         * @exception IOException if array cannot be read
         */
        private static void writeArray(final ObjectOutput out, final double[] array)
            throws IOException {
            for (int i = 0; i < array.length; ++i) {
                out.writeDouble(array[i]);
            }
        }

        /** Write an array.
         * @param out output stream
         * @param array array to write
         * @exception IOException if array cannot be read
         */
        private static void writeArray(final ObjectOutput out, final double[][] array)
            throws IOException {
            for (int i = 0; i < array.length; ++i) {
                writeArray(out, array[i]);
            }
        }

        /** Read an array.
         * @param in input stream
         * @param array array to read
         * @exception IOException if array cannot be read
         */
        private static void readArray(final ObjectInput in, final double[] array)
            throws IOException {
            for (int i = 0; i < array.length; ++i) {
                array[i] = in.readDouble();
            }
        }

        /** Read an array.
         * @param in input stream
         * @param array array to read
         * @exception IOException if array cannot be read
         */
        private static void readArray(final ObjectInput in, final double[][] array)
            throws IOException {
            for (int i = 0; i < array.length; ++i) {
                readArray(in, array[i]);
            }
        }

    }

    /** Wrapper for event handlers. */
    private static class EventHandlerWrapper implements EventHandler {

        /** Underlying event handler with jacobians. */
        private final EventHandlerWithJacobians handler;

        /** State array. */
        private double[] y;

        /** Jacobian with respect to initial state dy/dy0. */
        private double[][] dydy0;

        /** Jacobian with respect to parameters dy/dp. */
        private double[][] dydp;

        /** Simple constructor.
         * @param handler underlying event handler with jacobians
         * @param n dimension of the original ODE
         * @param k number of parameters
         */
        public EventHandlerWrapper(final EventHandlerWithJacobians handler,
                                   final int n, final int k) {
            this.handler = handler;
            y        = new double[n];
            dydy0    = new double[n][n];
            dydp     = new double[n][k];
        }

        /** Get the underlying event handler with jacobians.
         * @return underlying event handler with jacobians
         */
        public EventHandlerWithJacobians getHandler() {
            return handler;
        }

        /** {@inheritDoc} */
        public int eventOccurred(double t, double[] z, boolean increasing)
            throws EventException {
            dispatchCompoundState(z, y, dydy0, dydp);
            return handler.eventOccurred(t, y, dydy0, dydp, increasing);
        }

        /** {@inheritDoc} */
        public double g(double t, double[] z)
            throws EventException {
            dispatchCompoundState(z, y, dydy0, dydp);
            return handler.g(t, y, dydy0, dydp);
        }

        /** {@inheritDoc} */
        public void resetState(double t, double[] z)
            throws EventException {
            dispatchCompoundState(z, y, dydy0, dydp);
            handler.resetState(t, y, dydy0, dydp);
        }

    }

}
