### Question:
SumToOne { public double[][] jacobian(double[] fitParms) { ArgChecker.isTrue(fitParms.length == _n - 1, "length of fitParms is {}, but must be {} ", fitParms.length, _n - 1); double[] sin = new double[_n - 1]; double[] cos = new double[_n - 1]; for (int j = 0; j < _n - 1; j++) { sin[j] = Math.sin(fitParms[j]); cos[j] = Math.cos(fitParms[j]); } double[] a = new double[_n]; for (int i = 0; i < _n; i++) { double prod = 1.0; for (int j = 0; j < _n - 1; j++) { if (_set[i][j] == 1) { prod *= sin[j]; } else if (_set[i][j] == -1) { prod *= cos[j]; } } a[i] = 2 * prod * prod; } double[][] res = new double[_n][_n - 1]; for (int i = 0; i < _n; i++) { for (int j = 0; j < _n - 1; j++) { if (_set[i][j] == 1 && a[i] != 0.0) { res[i][j] = a[i] * cos[j] / sin[j]; } else if (_set[i][j] == -1 && a[i] != 0.0) { res[i][j] = -a[i] * sin[j] / cos[j]; } } } return res; } SumToOne(int n); double[] transform(double[] fitParms); DoubleArray transform(DoubleArray fitParms); double[] inverseTransform(double[] modelParms); DoubleArray inverseTransform(DoubleArray modelParms); double[][] jacobian(double[] fitParms); DoubleMatrix jacobian(DoubleArray fitParms);  }### Answer:
@Test public void jacobianTest() { final int n = 5; final SumToOne trans = new SumToOne(n); Function<DoubleArray, DoubleArray> func = new Function<DoubleArray, DoubleArray>() { @Override public DoubleArray apply(DoubleArray theta) { return trans.transform(theta); } }; Function<DoubleArray, DoubleMatrix> jacFunc = new Function<DoubleArray, DoubleMatrix>() { @Override public DoubleMatrix apply(DoubleArray theta) { return trans.jacobian(theta); } }; Function<DoubleArray, DoubleMatrix> fdJacFunc = DIFFER.differentiate(func); for (int tries = 0; tries < 10; tries++) { DoubleArray vTheta = DoubleArray.of(n - 1, i -> RANDOM.nextDouble()); DoubleMatrix jac = jacFunc.apply(vTheta); DoubleMatrix fdJac = fdJacFunc.apply(vTheta); for (int j = 0; j < n - 1; j++) { double sum = 0.0; for (int i = 0; i < n; i++) { sum += jac.get(i, j); assertThat(jac.get(i, j)).as("element " + i + " " + j).isCloseTo(fdJac.get(i, j), offset(1e-6)); } assertThat(sum).as("wrong sum of sensitivities").isCloseTo(0.0, offset(1e-15)); } } }