public Pair<MulticurveProviderForward, CurveBuildingBlockBundle> makeCurvesFromDerivatives(final InstrumentDerivative[][][] instruments,
final GeneratorYDCurve[][] curveGenerators, final String[][] curveNames, final double[][] parametersGuess, final MulticurveProviderForward knownData,
final LinkedHashMap<String, Currency> discountingMap, final LinkedHashMap<String, IborIndex> forwardIborMap, final LinkedHashMap<String, IndexON> forwardONMap,
final InstrumentDerivativeVisitor<MulticurveProviderInterface, Double> calculator, final InstrumentDerivativeVisitor<MulticurveProviderInterface, MulticurveSensitivity> sensitivityCalculator) {
final int nbUnits = curveGenerators.length;
final MulticurveProviderForward knownSoFarData = knownData.copy();
final List<InstrumentDerivative> instrumentsSoFar = new ArrayList<>();
final LinkedHashMap<String, GeneratorYDCurve> generatorsSoFar = new LinkedHashMap<>();
final LinkedHashMap<String, Pair<CurveBuildingBlock, DoubleMatrix2D>> unitBundleSoFar = new LinkedHashMap<>();
final List<Double> parametersSoFar = new ArrayList<>();
final LinkedHashMap<String, Pair<Integer, Integer>> unitMap = new LinkedHashMap<>();
int startUnit = 0;
for (int loopunit = 0; loopunit < nbUnits; loopunit++) {
final int nbCurve = curveGenerators[loopunit].length;
final int[] startCurve = new int[nbCurve]; // First parameter index of the curve in the unit.
final LinkedHashMap<String, GeneratorYDCurve> gen = new LinkedHashMap<>();
final int[] nbIns = new int[curveGenerators[loopunit].length];
int nbInsUnit = 0; // Number of instruments in the unit.
for (int loopcurve = 0; loopcurve < nbCurve; loopcurve++) {
startCurve[loopcurve] = nbInsUnit;
nbIns[loopcurve] = instruments[loopunit][loopcurve].length;
nbInsUnit += nbIns[loopcurve];
instrumentsSoFar.addAll(Arrays.asList(instruments[loopunit][loopcurve]));
}
final InstrumentDerivative[] instrumentsUnit = new InstrumentDerivative[nbInsUnit];
final InstrumentDerivative[] instrumentsSoFarArray = instrumentsSoFar.toArray(new InstrumentDerivative[instrumentsSoFar.size()]);
for (int loopcurve = 0; loopcurve < nbCurve; loopcurve++) {
System.arraycopy(instruments[loopunit][loopcurve], 0, instrumentsUnit, startCurve[loopcurve], nbIns[loopcurve]);
}
for (int loopcurve = 0; loopcurve < nbCurve; loopcurve++) {
final GeneratorYDCurve tmp = curveGenerators[loopunit][loopcurve].finalGenerator(instruments[loopunit][loopcurve]);
gen.put(curveNames[loopunit][loopcurve], tmp);
generatorsSoFar.put(curveNames[loopunit][loopcurve], tmp);
unitMap.put(curveNames[loopunit][loopcurve], new ObjectsPair<>(startUnit + startCurve[loopcurve], nbIns[loopcurve]));
}
final Pair<MulticurveProviderForward, Double[]> unitCal = makeUnit(instrumentsUnit, parametersGuess[loopunit], knownSoFarData, discountingMap, forwardIborMap, forwardONMap, gen, calculator,
sensitivityCalculator);
parametersSoFar.addAll(Arrays.asList(unitCal.getSecond()));
final DoubleMatrix2D[] mat = makeCurveMatrix(instrumentsSoFarArray, startUnit, nbIns, parametersSoFar.toArray(new Double[parametersSoFar.size()]), knownData,
discountingMap, forwardIborMap, forwardONMap, generatorsSoFar, sensitivityCalculator);
for (int loopcurve = 0; loopcurve < curveGenerators[loopunit].length; loopcurve++) {
unitBundleSoFar.put(curveNames[loopunit][loopcurve], new ObjectsPair<>(new CurveBuildingBlock(unitMap), mat[loopcurve]));
}
knownSoFarData.setAll(unitCal.getFirst());
startUnit = startUnit + nbInsUnit;
}
return new ObjectsPair<>(knownSoFarData, new CurveBuildingBlockBundle(unitBundleSoFar));
}