Example usage for org.apache.commons.math3.util MathArrays checkOrder

List of usage examples for org.apache.commons.math3.util MathArrays checkOrder

Introduction

In this page you can find the example usage for org.apache.commons.math3.util MathArrays checkOrder.

Prototype

public static void checkOrder(double[] val) throws NonMonotonicSequenceException 

Source Link

Document

Check that the given array is sorted in strictly increasing order.

Usage

From source file:es.uvigo.ei.sing.laimages.core.operations.BilinearInterpolator.java

@Override
public BilinearInterpolatingFunction interpolate(double[] xval, double[] yval, double[][] fval)
        throws NoDataException, DimensionMismatchException, NonMonotonicSequenceException {
    if (xval.length == 0 || yval.length == 0 || fval.length == 0) {
        throw new NoDataException();
    }/*  w ww  . ja  v a  2 s. co  m*/
    if (xval.length != fval.length) {
        throw new DimensionMismatchException(xval.length, fval.length);
    }
    if (yval.length != fval[0].length) {
        throw new DimensionMismatchException(yval.length, fval[0].length);
    }

    MathArrays.checkOrder(xval);
    MathArrays.checkOrder(yval);

    return new BilinearInterpolatingFunction(xval, yval, fval);
}

From source file:de.bund.bfr.math.LinearFunction.java

public LinearFunction(double[] x, double[] y) throws NullArgumentException, NoDataException,
        DimensionMismatchException, NonMonotonicSequenceException {
    if (x == null || y == null) {
        throw new NullArgumentException();
    }/*from  w w  w . j  ava2  s . co m*/
    if (x.length == 0 || y.length == 0) {
        throw new NoDataException();
    }
    if (y.length != x.length) {
        throw new DimensionMismatchException(y.length, x.length);
    }
    MathArrays.checkOrder(x);

    abscissa = MathArrays.copyOf(x);
    ordinate = MathArrays.copyOf(y);
}

From source file:es.uvigo.ei.sing.laimages.core.operations.BilinearInterpolatingFunction.java

public BilinearInterpolatingFunction(double[] xval, double[] yval, double[][] fval)
        throws DimensionMismatchException, NoDataException, NonMonotonicSequenceException {
    if (xval.length == 0 || yval.length == 0 || fval.length == 0) {
        throw new NoDataException();
    }// w ww .  j  av a 2  s.  c  o m
    if (xval.length != fval.length) {
        throw new DimensionMismatchException(xval.length, fval.length);
    }
    if (yval.length != fval[0].length) {
        throw new DimensionMismatchException(yval.length, fval[0].length);
    }

    MathArrays.checkOrder(xval);
    MathArrays.checkOrder(yval);

    this.xval = xval;
    this.yval = yval;
    this.fval = fval;
}

From source file:au.gov.ga.conn4d.utils.BicubicSplineInterpolator.java

/**
 * {@inheritDoc}//  ww w .j av  a2 s . co m
 */
public BicubicSplineInterpolatingFunction interpolate(final double[] xval, final double[] yval,
        final float[][] fval) throws NoDataException, DimensionMismatchException, NonMonotonicSequenceException,
        NumberIsTooSmallException {
    if (xval.length == 0 || yval.length == 0 || fval.length == 0) {
        throw new NoDataException();
    }
    if (xval.length != fval.length) {
        throw new DimensionMismatchException(xval.length, fval.length);
    }

    MathArrays.checkOrder(xval);
    MathArrays.checkOrder(yval);

    final int xLen = xval.length;
    final int yLen = yval.length;

    // Samples (first index is y-coordinate, i.e. subarray variable is x)
    // 0 <= i < xval.length
    // 0 <= j < yval.length
    // fX[j][i] = f(xval[i], yval[j])
    final double[][] fX = new double[yLen][xLen];
    for (int i = 0; i < xLen; i++) {
        if (fval[i].length != yLen) {
            throw new DimensionMismatchException(fval[i].length, yLen);
        }

        for (int j = 0; j < yLen; j++) {
            fX[j][i] = fval[i][j];
        }
    }

    final SplineInterpolator spInterpolator = new SplineInterpolator();

    // For each line y[j] (0 <= j < yLen), construct a 1D spline with
    // respect to variable x
    final PolynomialSplineFunction[] ySplineX = new PolynomialSplineFunction[yLen];
    for (int j = 0; j < yLen; j++) {
        ySplineX[j] = spInterpolator.interpolate(xval, fX[j]);
    }

    // For each line x[i] (0 <= i < xLen), construct a 1D spline with
    // respect to variable y generated by array fY_1[i]
    final PolynomialSplineFunction[] xSplineY = new PolynomialSplineFunction[xLen];
    for (int i = 0; i < xLen; i++) {
        xSplineY[i] = spInterpolator.interpolate(yval, fval[i]);
    }

    // Partial derivatives with respect to x at the grid knots
    final double[][] dFdX = new double[xLen][yLen];
    for (int j = 0; j < yLen; j++) {
        final UnivariateFunction f = ySplineX[j].derivative();
        for (int i = 0; i < xLen; i++) {
            dFdX[i][j] = f.value(xval[i]);
        }
    }

    // Partial derivatives with respect to y at the grid knots
    final double[][] dFdY = new double[xLen][yLen];
    for (int i = 0; i < xLen; i++) {
        final UnivariateFunction f = xSplineY[i].derivative();
        for (int j = 0; j < yLen; j++) {
            dFdY[i][j] = f.value(yval[j]);
        }
    }

    // Cross partial derivatives
    final double[][] d2FdXdY = new double[xLen][yLen];
    for (int i = 0; i < xLen; i++) {
        final int nI = nextIndex(i, xLen);
        final int pI = previousIndex(i);
        for (int j = 0; j < yLen; j++) {
            final int nJ = nextIndex(j, yLen);
            final int pJ = previousIndex(j);
            d2FdXdY[i][j] = (fval[nI][nJ] - fval[nI][pJ] - fval[pI][nJ] + fval[pI][pJ])
                    / ((xval[nI] - xval[pI]) * (yval[nJ] - yval[pJ]));
        }
    }

    // Create the interpolating splines
    return new BicubicSplineInterpolatingFunction(xval, yval, fval, dFdX, dFdY, d2FdXdY);
}

From source file:au.gov.ga.conn4d.utils.TricubicSplineInterpolator.java

/**
 * {@inheritDoc}//from   w  w w . j  ava  2 s. co  m
 */
public TricubicSplineInterpolatingFunction interpolate(final double[] zval, final double[] yval,
        final double[] xval, final double[][][] fval)
        throws NoDataException, DimensionMismatchException, NonMonotonicSequenceException {
    if (zval.length == 0 || yval.length == 0 || xval.length == 0 || fval.length == 0) {
        throw new NoDataException();
    }
    if (zval.length != fval.length) {
        throw new DimensionMismatchException(zval.length, fval.length);
    }

    MathArrays.checkOrder(zval);
    MathArrays.checkOrder(yval);

    final int zLen = zval.length;
    final int yLen = yval.length;
    final int xLen = xval.length;

    final double[] zzval;
    final double[][][] ffval = new double[zLen][][];

    if (zval[0] > zval[zLen - 1]) {
        zzval = VectorMath.selectionSort(zval);
        for (int i = 0; i < zLen; i++) {
            ffval[i] = fval[zLen - 1 - i];
        }
    } else {
        zzval = zval;
    }

    // Samples, re-ordered as (z, x, y) and (y, z, x) tuplets
    // fvalXY[k][i][j] = f(xval[i], yval[j], zval[k])
    // fvalZX[j][k][i] = f(xval[i], yval[j], zval[k])
    final double[][][] fvalXY = new double[xLen][zLen][yLen];
    final double[][][] fvalZX = new double[yLen][xLen][zLen];
    for (int i = 0; i < zLen; i++) {
        if (ffval[i].length != yLen) {
            throw new DimensionMismatchException(ffval[i].length, yLen);
        }

        for (int j = 0; j < yLen; j++) {
            if (ffval[i][j].length != xLen) {
                throw new DimensionMismatchException(ffval[i][j].length, xLen);
            }

            for (int k = 0; k < xLen; k++) {
                final double v = ffval[i][j][k];
                fvalXY[k][i][j] = v;
                fvalZX[j][k][i] = v;
            }
        }
    }

    final BicubicSplineInterpolator bsi = new BicubicSplineInterpolator();

    // For each line x[i] (0 <= i < xLen), construct a 2D spline in y and z
    final BicubicSplineInterpolatingFunction[] xSplineYZ = new BicubicSplineInterpolatingFunction[zLen];
    for (int i = 0; i < zLen; i++) {
        xSplineYZ[i] = bsi.interpolate(yval, xval, ffval[i]);
    }

    // For each line y[j] (0 <= j < yLen), construct a 2D spline in z and x
    final BicubicSplineInterpolatingFunction[] ySplineZX = new BicubicSplineInterpolatingFunction[yLen];
    for (int j = 0; j < yLen; j++) {
        ySplineZX[j] = bsi.interpolate(xval, zzval, fvalZX[j]);
    }

    // For each line z[k] (0 <= k < zLen), construct a 2D spline in x and y
    final BicubicSplineInterpolatingFunction[] zSplineXY = new BicubicSplineInterpolatingFunction[xLen];
    for (int k = 0; k < xLen; k++) {
        zSplineXY[k] = bsi.interpolate(zzval, yval, fvalXY[k]);
    }

    // Partial derivatives wrt x and wrt y
    final double[][][] dFdX = new double[zLen][yLen][xLen];
    final double[][][] dFdY = new double[zLen][yLen][xLen];
    final double[][][] d2FdXdY = new double[zLen][yLen][xLen];
    for (int k = 0; k < xLen; k++) {
        final BicubicSplineInterpolatingFunction f = zSplineXY[k];
        for (int i = 0; i < zLen; i++) {
            final double z = zzval[i];
            for (int j = 0; j < yLen; j++) {
                final double y = yval[j];
                dFdX[i][j][k] = f.partialDerivativeX(z, y);
                dFdY[i][j][k] = f.partialDerivativeY(z, y);
                d2FdXdY[i][j][k] = f.partialDerivativeXY(z, y);
            }
        }
    }

    // Partial derivatives wrt y and wrt z
    final double[][][] dFdZ = new double[zLen][yLen][xLen];
    final double[][][] d2FdYdZ = new double[zLen][yLen][xLen];
    for (int i = 0; i < zLen; i++) {
        final BicubicSplineInterpolatingFunction f = xSplineYZ[i];
        for (int j = 0; j < yLen; j++) {
            final double y = yval[j];
            for (int k = 0; k < xLen; k++) {
                final double x = xval[k];
                dFdZ[i][j][k] = f.partialDerivativeY(y, x);
                d2FdYdZ[i][j][k] = f.partialDerivativeXY(y, x);
            }
        }
    }

    // Partial derivatives wrt x and wrt z
    final double[][][] d2FdZdX = new double[zLen][yLen][xLen];
    for (int j = 0; j < yLen; j++) {
        final BicubicSplineInterpolatingFunction f = ySplineZX[j];
        for (int k = 0; k < xLen; k++) {
            final double x = xval[k];
            for (int i = 0; i < zLen; i++) {
                final double z = zzval[i];
                d2FdZdX[i][j][k] = f.partialDerivativeXY(x, z);
            }
        }
    }

    // Third partial cross-derivatives
    final double[][][] d3FdXdYdZ = new double[zLen][yLen][xLen];
    for (int i = 0; i < zLen; i++) {
        final int nI = nextIndex(i, zLen);
        final int pI = previousIndex(i);
        for (int j = 0; j < yLen; j++) {
            final int nJ = nextIndex(j, yLen);
            final int pJ = previousIndex(j);
            for (int k = 0; k < xLen; k++) {
                final int nK = nextIndex(k, xLen);
                final int pK = previousIndex(k);

                // XXX Not sure about this formula
                d3FdXdYdZ[i][j][k] = (ffval[nI][nJ][nK] - ffval[nI][pJ][nK] - ffval[pI][nJ][nK]
                        + ffval[pI][pJ][nK] - ffval[nI][nJ][pK] + ffval[nI][pJ][pK] + ffval[pI][nJ][pK]
                        - ffval[pI][pJ][pK])
                        / ((zzval[nI] - zzval[pI]) * (yval[nJ] - yval[pJ]) * (xval[nK] - xval[pK]));
            }
        }
    }

    // Create the interpolating splines
    return new TricubicSplineInterpolatingFunction(zzval, yval, xval, ffval, dFdX, dFdY, dFdZ, d2FdXdY, d2FdZdX,
            d2FdYdZ, d3FdXdYdZ);
}

From source file:au.gov.ga.conn4d.utils.SplineInterpolator.java

/**
 * Computes an interpolating function for the data set.
 * /*from  w w w  .  j ava2 s . co m*/
 * @param x
 *            the arguments for the interpolation points
 * @param y
 *            the values for the interpolation points
 * @return a function which interpolates the data set
 * @throws DimensionMismatchException
 *             if {@code x} and {@code y} have different sizes.
 * @throws NonMonotonicSequenceException
 *             if {@code x} is not sorted in strict increasing order.
 * @throws NumberIsTooSmallException
 *             if the size of {@code x} is smaller than 3.
 */
public PolynomialSplineFunction interpolate(double x[], double y[])
        throws DimensionMismatchException, NumberIsTooSmallException, NonMonotonicSequenceException {
    if (x.length != y.length) {
        throw new DimensionMismatchException(x.length, y.length);
    }

    if (x.length < 3) {
        throw new NumberIsTooSmallException(LocalizedFormats.NUMBER_OF_POINTS, x.length, 3, true);
    }

    // Number of intervals. The number of data points is n + 1.
    final int n = x.length - 1;

    MathArrays.checkOrder(x);

    // Differences between knot points
    final double h[] = new double[n];
    for (int i = 0; i < n; i++) {
        h[i] = x[i + 1] - x[i];
    }

    final double mu[] = new double[n];
    final double z[] = new double[n + 1];
    mu[0] = 0d;
    z[0] = 0d;
    double g = 0;
    for (int i = 1; i < n; i++) {
        g = 2d * (x[i + 1] - x[i - 1]) - h[i - 1] * mu[i - 1];
        mu[i] = h[i] / g;
        z[i] = (3d * (y[i + 1] * h[i - 1] - y[i] * (x[i + 1] - x[i - 1]) + y[i - 1] * h[i]) / (h[i - 1] * h[i])
                - h[i - 1] * z[i - 1]) / g;
    }

    // cubic spline coefficients -- b is linear, c quadratic, d is cubic
    // (original y's are constants)
    final double b[] = new double[n];
    final double c[] = new double[n + 1];
    final double d[] = new double[n];

    z[n] = 0d;
    c[n] = 0d;

    for (int j = n - 1; j >= 0; j--) {
        c[j] = z[j] - mu[j] * c[j + 1];
        b[j] = (y[j + 1] - y[j]) / h[j] - h[j] * (c[j + 1] + 2d * c[j]) / 3d;
        d[j] = (c[j + 1] - c[j]) / (3d * h[j]);
    }

    final PolynomialFunction polynomials[] = new PolynomialFunction[n];
    final double coefficients[] = new double[4];
    for (int i = 0; i < n; i++) {
        coefficients[0] = y[i];
        coefficients[1] = b[i];
        coefficients[2] = c[i];
        coefficients[3] = d[i];
        polynomials[i] = new PolynomialFunction(coefficients);
    }

    return new PolynomialSplineFunction(x, polynomials);
}

From source file:au.gov.ga.conn4d.utils.BicubicSplineInterpolator.java

public BicubicSplineInterpolatingFunction interpolate(final double[] xval, final double[] yval,
        final double[][] fval) throws NoDataException, DimensionMismatchException,
        NonMonotonicSequenceException, NumberIsTooSmallException {
    if (xval.length == 0 || yval.length == 0 || fval.length == 0) {
        throw new NoDataException();
    }//from   w  w  w  . ja v  a2s. c  om
    if (xval.length != fval.length) {
        throw new DimensionMismatchException(xval.length, fval.length);
    }

    MathArrays.checkOrder(xval);
    MathArrays.checkOrder(yval);

    final int xLen = xval.length;
    final int yLen = yval.length;

    // Samples (first index is y-coordinate, i.e. subarray variable is x)
    // 0 <= i < xval.length
    // 0 <= j < yval.length
    // fX[j][i] = f(xval[i], yval[j])
    final double[][] fX = new double[yLen][xLen];
    for (int i = 0; i < xLen; i++) {
        if (fval[i].length != yLen) {
            throw new DimensionMismatchException(fval[i].length, yLen);
        }

        for (int j = 0; j < yLen; j++) {
            fX[j][i] = fval[i][j];
        }
    }

    final SplineInterpolator spInterpolator = new SplineInterpolator();

    // For each line y[j] (0 <= j < yLen), construct a 1D spline with
    // respect to variable x
    final PolynomialSplineFunction[] ySplineX = new PolynomialSplineFunction[yLen];
    for (int j = 0; j < yLen; j++) {
        ySplineX[j] = spInterpolator.interpolate(xval, fX[j]);
    }

    // For each line x[i] (0 <= i < xLen), construct a 1D spline with
    // respect to variable y generated by array fY_1[i]
    final PolynomialSplineFunction[] xSplineY = new PolynomialSplineFunction[xLen];
    for (int i = 0; i < xLen; i++) {
        xSplineY[i] = spInterpolator.interpolate(yval, fval[i]);
    }

    // Partial derivatives with respect to x at the grid knots
    final double[][] dFdX = new double[xLen][yLen];
    for (int j = 0; j < yLen; j++) {
        final UnivariateFunction f = ySplineX[j].derivative();
        for (int i = 0; i < xLen; i++) {
            dFdX[i][j] = f.value(xval[i]);
        }
    }

    // Partial derivatives with respect to y at the grid knots
    final double[][] dFdY = new double[xLen][yLen];
    for (int i = 0; i < xLen; i++) {
        final UnivariateFunction f = xSplineY[i].derivative();
        for (int j = 0; j < yLen; j++) {
            dFdY[i][j] = f.value(yval[j]);
        }
    }

    // Cross partial derivatives
    final double[][] d2FdXdY = new double[xLen][yLen];
    for (int i = 0; i < xLen; i++) {
        final int nI = nextIndex(i, xLen);
        final int pI = previousIndex(i);
        for (int j = 0; j < yLen; j++) {
            final int nJ = nextIndex(j, yLen);
            final int pJ = previousIndex(j);
            d2FdXdY[i][j] = (fval[nI][nJ] - fval[nI][pJ] - fval[pI][nJ] + fval[pI][pJ])
                    / ((xval[nI] - xval[pI]) * (yval[nJ] - yval[pJ]));
        }
    }

    // Create the interpolating splines
    return new BicubicSplineInterpolatingFunction(xval, yval, fval, dFdX, dFdY, d2FdXdY);
}

From source file:au.gov.ga.conn4d.utils.BicubicSplineInterpolatingFunction.java

/**
 * @param x Sample values of the x-coordinate, in increasing order.
 * @param y Sample values of the y-coordinate, in increasing order.
 * @param f Values of the function on every grid point.
 * @param dFdX Values of the partial derivative of function with respect
 * to x on every grid point.//from   w w w.j av a 2 s . co m
 * @param dFdY Values of the partial derivative of function with respect
 * to y on every grid point.
 * @param d2FdXdY Values of the cross partial derivative of function on
 * every grid point.
 * @throws DimensionMismatchException if the various arrays do not contain
 * the expected number of elements.
 * @throws NonMonotonicSequenceException if {@code x} or {@code y} are
 * not strictly increasing.
 * @throws NoDataException if any of the arrays has zero length.
 */
public BicubicSplineInterpolatingFunction(double[] x, double[] y, float[][] f, double[][] dFdX, double[][] dFdY,
        double[][] d2FdXdY) throws DimensionMismatchException, NoDataException, NonMonotonicSequenceException {
    final int xLen = x.length;
    final int yLen = y.length;

    if (xLen == 0 || yLen == 0 || f.length == 0 || f[0].length == 0) {
        throw new NoDataException();
    }
    if (xLen != f.length) {
        throw new DimensionMismatchException(xLen, f.length);
    }
    if (xLen != dFdX.length) {
        throw new DimensionMismatchException(xLen, dFdX.length);
    }
    if (xLen != dFdY.length) {
        throw new DimensionMismatchException(xLen, dFdY.length);
    }
    if (xLen != d2FdXdY.length) {
        throw new DimensionMismatchException(xLen, d2FdXdY.length);
    }

    MathArrays.checkOrder(x);
    MathArrays.checkOrder(y);

    xval = x.clone();
    yval = y.clone();

    final int lastI = xLen - 1;
    final int lastJ = yLen - 1;
    splines = new BicubicSplineFunction[lastI][lastJ];

    for (int i = 0; i < lastI; i++) {
        if (f[i].length != yLen) {
            throw new DimensionMismatchException(f[i].length, yLen);
        }
        if (dFdX[i].length != yLen) {
            throw new DimensionMismatchException(dFdX[i].length, yLen);
        }
        if (dFdY[i].length != yLen) {
            throw new DimensionMismatchException(dFdY[i].length, yLen);
        }
        if (d2FdXdY[i].length != yLen) {
            throw new DimensionMismatchException(d2FdXdY[i].length, yLen);
        }
        final int ip1 = i + 1;
        for (int j = 0; j < lastJ; j++) {
            final int jp1 = j + 1;
            final double[] beta = new double[] { f[i][j], f[ip1][j], f[i][jp1], f[ip1][jp1], dFdX[i][j],
                    dFdX[ip1][j], dFdX[i][jp1], dFdX[ip1][jp1], dFdY[i][j], dFdY[ip1][j], dFdY[i][jp1],
                    dFdY[ip1][jp1], d2FdXdY[i][j], d2FdXdY[ip1][j], d2FdXdY[i][jp1], d2FdXdY[ip1][jp1] };

            splines[i][j] = new BicubicSplineFunction(computeSplineCoefficients(beta));
        }
    }
}

From source file:au.gov.ga.conn4d.utils.SplineInterpolator.java

public PolynomialSplineFunction interpolate(double x[], float y[])
        throws DimensionMismatchException, NumberIsTooSmallException, NonMonotonicSequenceException {
    if (x.length != y.length) {
        throw new DimensionMismatchException(x.length, y.length);
    }//from   ww w. j a  v a  2 s.c  om

    if (x.length < 3) {
        throw new NumberIsTooSmallException(LocalizedFormats.NUMBER_OF_POINTS, x.length, 3, true);
    }

    // Number of intervals. The number of data points is n + 1.
    final int n = x.length - 1;

    MathArrays.checkOrder(x);

    // Differences between knot points
    final double h[] = new double[n];
    for (int i = 0; i < n; i++) {
        h[i] = x[i + 1] - x[i];
    }

    final double mu[] = new double[n];
    final double z[] = new double[n + 1];
    mu[0] = 0d;
    z[0] = 0d;
    double g = 0;
    for (int i = 1; i < n; i++) {
        g = 2d * (x[i + 1] - x[i - 1]) - h[i - 1] * mu[i - 1];
        mu[i] = h[i] / g;
        z[i] = (3d * (y[i + 1] * h[i - 1] - y[i] * (x[i + 1] - x[i - 1]) + y[i - 1] * h[i]) / (h[i - 1] * h[i])
                - h[i - 1] * z[i - 1]) / g;
    }

    // cubic spline coefficients -- b is linear, c quadratic, d is cubic
    // (original y's are constants)
    final double b[] = new double[n];
    final double c[] = new double[n + 1];
    final double d[] = new double[n];

    z[n] = 0d;
    c[n] = 0d;

    for (int j = n - 1; j >= 0; j--) {
        c[j] = z[j] - mu[j] * c[j + 1];
        b[j] = (y[j + 1] - y[j]) / h[j] - h[j] * (c[j + 1] + 2d * c[j]) / 3d;
        d[j] = (c[j + 1] - c[j]) / (3d * h[j]);
    }

    final PolynomialFunction polynomials[] = new PolynomialFunction[n];
    final double coefficients[] = new double[4];
    for (int i = 0; i < n; i++) {
        coefficients[0] = y[i];
        coefficients[1] = b[i];
        coefficients[2] = c[i];
        coefficients[3] = d[i];
        polynomials[i] = new PolynomialFunction(coefficients);
    }

    return new PolynomialSplineFunction(x, polynomials);
}

From source file:au.gov.ga.conn4d.utils.TricubicSplineInterpolator.java

public TricubicSplineInterpolatingFunction interpolate(final double[] zval, final double[] yval,
        final double[] xval, final float[][][] fval)
        throws NoDataException, DimensionMismatchException, NonMonotonicSequenceException {
    if (zval.length == 0 || yval.length == 0 || xval.length == 0 || fval.length == 0) {
        throw new NoDataException();
    }// w  w w .  j a va  2 s .c o  m
    if (zval.length != fval.length) {
        throw new DimensionMismatchException(zval.length, fval.length);
    }

    MathArrays.checkOrder(yval);
    MathArrays.checkOrder(xval);

    final int zLen = zval.length;
    final int yLen = yval.length;
    final int xLen = xval.length;

    final double[] zzval;
    float[][][] ffval = new float[zLen][][];

    if (zval[0] > zval[zLen - 1]) {
        zzval = VectorMath.selectionSort(zval);
        for (int i = 0; i < zLen; i++) {
            ffval[i] = fval[zLen - 1 - i];
        }
    } else {
        zzval = zval;
        ffval = fval;
    }

    // Samples, re-ordered as (z, x, y) and (y, z, x) tuplets
    // fvalXY[k][i][j] = f(xval[i], yval[j], zval[k])
    // fvalZX[j][k][i] = f(xval[i], yval[j], zval[k])
    final double[][][] fvalXY = new double[xLen][zLen][yLen];
    final double[][][] fvalZX = new double[yLen][xLen][zLen];
    for (int i = 0; i < zLen; i++) {
        if (ffval[i].length != yLen) {
            throw new DimensionMismatchException(ffval[i].length, yLen);
        }

        for (int j = 0; j < yLen; j++) {
            if (ffval[i][j].length != xLen) {
                throw new DimensionMismatchException(ffval[i][j].length, xLen);
            }

            for (int k = 0; k < xLen; k++) {
                final double v = ffval[i][j][k];
                fvalXY[k][i][j] = v;
                fvalZX[j][k][i] = v;
            }
        }
    }

    final BicubicSplineInterpolator bsi = new BicubicSplineInterpolator();

    // For each line x[i] (0 <= i < xLen), construct a 2D spline in y and z
    final BicubicSplineInterpolatingFunction[] xSplineYZ = new BicubicSplineInterpolatingFunction[zLen];
    for (int i = 0; i < zLen; i++) {
        xSplineYZ[i] = bsi.interpolate(yval, xval, ffval[i]);
    }

    // For each line y[j] (0 <= j < yLen), construct a 2D spline in z and x
    final BicubicSplineInterpolatingFunction[] ySplineZX = new BicubicSplineInterpolatingFunction[yLen];
    for (int j = 0; j < yLen; j++) {
        ySplineZX[j] = bsi.interpolate(xval, zzval, fvalZX[j]);
    }

    // For each line z[k] (0 <= k < zLen), construct a 2D spline in x and y
    final BicubicSplineInterpolatingFunction[] zSplineXY = new BicubicSplineInterpolatingFunction[xLen];
    for (int k = 0; k < xLen; k++) {
        zSplineXY[k] = bsi.interpolate(zzval, yval, fvalXY[k]);
    }

    // Partial derivatives wrt x and wrt y
    final double[][][] dFdX = new double[zLen][yLen][xLen];
    final double[][][] dFdY = new double[zLen][yLen][xLen];
    final double[][][] d2FdXdY = new double[zLen][yLen][xLen];
    for (int k = 0; k < xLen; k++) {
        final BicubicSplineInterpolatingFunction f = zSplineXY[k];
        for (int i = 0; i < zLen; i++) {
            final double x = zzval[i];
            for (int j = 0; j < yLen; j++) {
                final double y = yval[j];
                dFdX[i][j][k] = f.partialDerivativeX(x, y);
                dFdY[i][j][k] = f.partialDerivativeY(x, y);
                d2FdXdY[i][j][k] = f.partialDerivativeXY(x, y);
            }
        }
    }

    // Partial derivatives wrt y and wrt z
    final double[][][] dFdZ = new double[zLen][yLen][xLen];
    final double[][][] d2FdYdZ = new double[zLen][yLen][xLen];
    for (int i = 0; i < zLen; i++) {
        final BicubicSplineInterpolatingFunction f = xSplineYZ[i];
        for (int j = 0; j < yLen; j++) {
            final double y = yval[j];
            for (int k = 0; k < xLen; k++) {
                final double z = xval[k];
                dFdZ[i][j][k] = f.partialDerivativeY(y, z);
                d2FdYdZ[i][j][k] = f.partialDerivativeXY(y, z);
            }
        }
    }

    // Partial derivatives wrt x and wrt z
    final double[][][] d2FdZdX = new double[zLen][yLen][xLen];
    for (int j = 0; j < yLen; j++) {
        final BicubicSplineInterpolatingFunction f = ySplineZX[j];
        for (int k = 0; k < xLen; k++) {
            final double z = xval[k];
            for (int i = 0; i < zLen; i++) {
                final double x = zzval[i];
                d2FdZdX[i][j][k] = f.partialDerivativeXY(z, x);
            }
        }
    }

    // Third partial cross-derivatives
    final double[][][] d3FdXdYdZ = new double[zLen][yLen][xLen];
    for (int i = 0; i < zLen; i++) {
        final int nI = nextIndex(i, zLen);
        final int pI = previousIndex(i);
        for (int j = 0; j < yLen; j++) {
            final int nJ = nextIndex(j, yLen);
            final int pJ = previousIndex(j);
            for (int k = 0; k < xLen; k++) {
                final int nK = nextIndex(k, xLen);
                final int pK = previousIndex(k);

                // XXX Not sure about this formula
                d3FdXdYdZ[i][j][k] = (ffval[nI][nJ][nK] - ffval[nI][pJ][nK] - ffval[pI][nJ][nK]
                        + ffval[pI][pJ][nK] - ffval[nI][nJ][pK] + ffval[nI][pJ][pK] + ffval[pI][nJ][pK]
                        - ffval[pI][pJ][pK])
                        / ((zzval[nI] - zzval[pI]) * (yval[nJ] - yval[pJ]) * (xval[nK] - xval[pK]));
            }
        }
    }

    // Create the interpolating splines
    return new TricubicSplineInterpolatingFunction(zzval, yval, xval, ffval, dFdX, dFdY, dFdZ, d2FdXdY, d2FdZdX,
            d2FdYdZ, d3FdXdYdZ);
}