// Path: src/org/addition/epanet/msx/Solvers/JacobianInterface.java
// public interface JacobianInterface {
//     public static enum Operation{
//         PIPES_DC_DT_CONCENTRATIONS,
//         TANKS_DC_DT_CONCENTRATIONS,
//         PIPES_EQUIL,
//         TANKS_EQUIL,
//     }
// 
//     public void solve(double t, double[] y, int n, double[] f, int off,Operation op);
// }


import org.addition.epanet.msx.Solvers.JacobianInterface;
                  //void (*func)(double, double*, int, double*))

    {

        int    i, j;
        double temp, eps = 1.0e-7, eps2;

        for (j=1; j<=n; j++)
        {
            temp = x[j];
            x[j] = temp + eps;
            func.solve(0.0, x, n, f);
            if ( temp == 0.0 )
            {
                x[j] = temp;
                eps2 = eps;
            }
            else
            {
                x[j] = temp - eps;
                eps2 = 2.0*eps;
            }
            func.solve(0.0, x, n, w);
            for (i=1; i<=n; i++) a[i][j] = (f[i] - w[i]) / eps2;
            x[j] = temp;
        }

    }*/

    // computes Jacobian matrix of F(t,X) at given X
// Path: src/org/addition/epanet/msx/Solvers/JacobianInterface.java
// public interface JacobianInterface {
//     public static enum Operation{
//         PIPES_DC_DT_CONCENTRATIONS,
//         TANKS_DC_DT_CONCENTRATIONS,
//         PIPES_EQUIL,
//         TANKS_EQUIL,
//     }
// 
//     public void solve(double t, double[] y, int n, double[] f, int off,Operation op);
// }


// Path: src/org/addition/epanet/msx/Utilities.java
import org.addition.epanet.msx.Solvers.JacobianInterface;

                  //void (*func)(double, double*, int, double*))

    {

        int    i, j;
        double temp, eps = 1.0e-7, eps2;

        for (j=1; j<=n; j++)
        {
            temp = x[j];
            x[j] = temp + eps;
            func.solve(0.0, x, n, f);
            if ( temp == 0.0 )
            {
                x[j] = temp;
                eps2 = eps;
            }
            else
            {
                x[j] = temp - eps;
                eps2 = 2.0*eps;
            }
            func.solve(0.0, x, n, w);
            for (i=1; i<=n; i++) a[i][j] = (f[i] - w[i]) / eps2;
            x[j] = temp;
        }

    }*/

    // computes Jacobian matrix of F(t,X) at given X
    public static void jacobian(double [] x, int n, double [] f, double [] w, double [][]a, JacobianInterface jint, JacobianInterface.Operation op){