/*
 * 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.nonstiff;

import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;

import org.apache.commons.math.ode.AbstractIntegrator;
import org.apache.commons.math.ode.sampling.AbstractStepInterpolator;

/** This class represents an interpolator over the last step during an
 * ODE integration for Runge-Kutta and embedded Runge-Kutta integrators.
 *
 * @see RungeKuttaIntegrator
 * @see EmbeddedRungeKuttaIntegrator
 *
 * @version $Revision: 811827 $ $Date: 2009-09-06 17:32:50 +0200 (dim. 06 sept. 2009) $
 * @since 1.2
 */

abstract class RungeKuttaStepInterpolator
  extends AbstractStepInterpolator {

    /** Slopes at the intermediate points */
    protected double[][] yDotK;

    /** Reference to the integrator. */
    protected AbstractIntegrator integrator;

  /** Simple constructor.
   * This constructor builds an instance that is not usable yet, the
   * {@link #reinitialize} method should be called before using the
   * instance in order to initialize the internal arrays. This
   * constructor is used only in order to delay the initialization in
   * some cases. The {@link RungeKuttaIntegrator} and {@link
   * EmbeddedRungeKuttaIntegrator} classes use the prototyping design
   * pattern to create the step interpolators by cloning an
   * uninitialized model and latter initializing the copy.
   */
  protected RungeKuttaStepInterpolator() {
    super();
    yDotK      = null;
    integrator = null;
  }

  /** Copy constructor.

  * <p>The copied interpolator should have been finalized before the
  * copy, otherwise the copy will not be able to perform correctly any
  * interpolation and will throw a {@link NullPointerException}
  * later. Since we don't want this constructor to throw the
  * exceptions finalization may involve and since we don't want this
  * method to modify the state of the copied interpolator,
  * finalization is <strong>not</strong> done automatically, it
  * remains under user control.</p>

  * <p>The copy is a deep copy: its arrays are separated from the
  * original arrays of the instance.</p>

  * @param interpolator interpolator to copy from.

  */
  public RungeKuttaStepInterpolator(final RungeKuttaStepInterpolator interpolator) {

    super(interpolator);

    if (interpolator.currentState != null) {
      final int dimension = currentState.length;

      yDotK = new double[interpolator.yDotK.length][];
      for (int k = 0; k < interpolator.yDotK.length; ++k) {
        yDotK[k] = new double[dimension];
        System.arraycopy(interpolator.yDotK[k], 0,
                         yDotK[k], 0, dimension);
      }

    } else {
      yDotK = null;
    }

    // we cannot keep any reference to the equations in the copy
    // the interpolator should have been finalized before
    integrator = null;

  }

  /** Reinitialize the instance
   * <p>Some Runge-Kutta integrators need fewer functions evaluations
   * than their counterpart step interpolators. So the interpolator
   * should perform the last evaluations they need by themselves. The
   * {@link RungeKuttaIntegrator RungeKuttaIntegrator} and {@link
   * EmbeddedRungeKuttaIntegrator EmbeddedRungeKuttaIntegrator}
   * abstract classes call this method in order to let the step
   * interpolator perform the evaluations it needs. These evaluations
   * will be performed during the call to <code>doFinalize</code> if
   * any, i.e. only if the step handler either calls the {@link
   * AbstractStepInterpolator#finalizeStep finalizeStep} method or the
   * {@link AbstractStepInterpolator#getInterpolatedState
   * getInterpolatedState} method (for an interpolator which needs a
   * finalization) or if it clones the step interpolator.</p>
   * @param rkIntegrator integrator being used
   * @param y reference to the integrator array holding the state at
   * the end of the step
   * @param yDotArray reference to the integrator array holding all the
   * intermediate slopes
   * @param forward integration direction indicator
   */
  public void reinitialize(final AbstractIntegrator rkIntegrator,
                           final double[] y, final double[][] yDotArray, final boolean forward) {
    reinitialize(y, forward);
    this.yDotK = yDotArray;
    this.integrator = rkIntegrator;
  }

  /** {@inheritDoc} */
  @Override
  public void writeExternal(final ObjectOutput out)
    throws IOException {

    // save the state of the base class
    writeBaseExternal(out);

    // save the local attributes
    final int n = (currentState == null) ? -1 : currentState.length;
    final int kMax = (yDotK == null) ? -1 : yDotK.length;
    out.writeInt(kMax);
    for (int k = 0; k < kMax; ++k) {
      for (int i = 0; i < n; ++i) {
        out.writeDouble(yDotK[k][i]);
      }
    }

    // we do not save any reference to the equations

  }

  /** {@inheritDoc} */
  @Override
  public void readExternal(final ObjectInput in)
    throws IOException {

    // read the base class
    final double t = readBaseExternal(in);

    // read the local attributes
    final int n = (currentState == null) ? -1 : currentState.length;
    final int kMax = in.readInt();
    yDotK = (kMax < 0) ? null : new double[kMax][];
    for (int k = 0; k < kMax; ++k) {
      yDotK[k] = (n < 0) ? null : new double[n];
      for (int i = 0; i < n; ++i) {
        yDotK[k][i] = in.readDouble();
      }
    }

    integrator = null;

    if (currentState != null) {
        // we can now set the interpolated time and state
        setInterpolatedTime(t);
    } else {
        interpolatedTime = t;
    }

  }

}
