SumToOne { public double[] inverseTransform(final double[] modelParms) { ArgumentChecker.isTrue(modelParms.length == _n, "length of modelParms is {}, but must be {} ", modelParms.length, _n); final double[] res = new double[_n - 1]; final double[] cum = new double[_n + 1]; double sum = 0.0; for (int i = 0; i < _n; i++) { sum += modelParms[i]; cum[i + 1] = sum; } ArgumentChecker.isTrue(Math.abs(sum - 1.0) < TOL, "sum of elements is {}. Must be 1.0", sum); cal(cum, 1.0, 0, _n, 0, res); for (int i = 0; i < _n - 1; i++) { res[i] = Math.asin(Math.sqrt(res[i])); } return res; } SumToOne(final int n); double[] transform(final double[] fitParms); DoubleMatrix1D transform(final DoubleMatrix1D fitParms); double[] inverseTransform(final double[] modelParms); DoubleMatrix1D inverseTransform(final DoubleMatrix1D modelParms); double[][] jacobian(final double[] fitParms); DoubleMatrix2D jacobian(final DoubleMatrix1D fitParms);  }
@Test public void inverseTransformTest() { for (int n = 2; n < 13; n++) { double[] theta = new double[n - 1]; for (int j = 0; j < n - 1; j++) { theta[j] = RANDOM.nextDouble() * Math.PI / 2; } SumToOne trans = new SumToOne(n); DoubleMatrix1D w = trans.transform(new DoubleMatrix1D(theta)); DoubleMatrix1D theta2 = trans.inverseTransform(w); for (int j = 0; j < n - 1; j++) { assertEquals("element " + j + ", of vector length " + n, theta[j], theta2.getEntry(j), 1e-9); } } }