@Test
 public void testFunctionalSurface3() {
   final StandardSmileSurfaceDataBundle data =
       new StandardSmileSurfaceDataBundle(
           new double[] {1, 2, 3, 4},
           new double[] {4, 5, 6, 7},
           new double[][] {
             new double[] {1, 2, 3, 4},
             new double[] {1, 2, 3, 4},
             new double[] {1, 2, 3, 4},
             new double[] {1, 2, 3, 4}
           },
           new double[][] {
             new double[] {0.1, 0.1, 0.1, 0.1},
             new double[] {0.1, 0.1, 0.1, 0.1},
             new double[] {0.1, 0.1, 0.1, 0.1},
             new double[] {0.1, 0.1, 0.1, 0.1}
           },
           true,
           CombinedInterpolatorExtrapolatorFactory.getInterpolator(
               Interpolator1DFactory.LINEAR, Interpolator1DFactory.FLAT_EXTRAPOLATOR));
   final BlackVolatilitySurfaceMoneyness s1 =
       new MoneynessPiecewiseSABRSurfaceFitter(true, false, 100).getVolatilitySurface(data);
   @SuppressWarnings("unchecked")
   final Surface<Double, Double, Double> s2 = cycleObject(Surface.class, s1.getSurface());
   assertSurfaceEquals(s1.getSurface(), s2);
 }
  static {
    final IborIndex index =
        new IborIndex(
            CCY,
            Period.ofMonths(1),
            0,
            new MondayToFridayCalendar("A"),
            DayCountFactory.INSTANCE.getDayCount("Actual/365"),
            BusinessDayConventionFactory.INSTANCE.getBusinessDayConvention("Following"),
            true);
    CASH = new ArrayList<InstrumentDerivative>();
    FRA = new ArrayList<InstrumentDerivative>();
    MIXED_INSTRUMENT = new ArrayList<InstrumentDerivative>();
    FORWARD_NODES = new double[N];
    FUNDING_NODES = new double[M];
    final double[] dataN = new double[N];
    final double[] dataM = new double[M];
    final double[] dataNpM = new double[N + M];
    for (int i = 0; i < N; i++) {
      final InstrumentDerivative ird =
          new ForwardRateAgreement(
              CCY, i, FUNDING_CURVE_NAME, 0.5, 1, index, i, i, i + 0.5, 0.5, 0, FORWARD_CURVE_NAME);
      FRA.add(ird);
      MIXED_INSTRUMENT.add(ird);
      FORWARD_NODES[i] = i + 1;
      dataN[i] = Math.random() / 10;
      dataNpM[i] = dataN[i];
    }

    for (int i = 0; i < M; i++) {
      final InstrumentDerivative ird = new Cash(CCY, 0, i, 1, 0.0, i, FUNDING_CURVE_NAME);
      CASH.add(ird);
      MIXED_INSTRUMENT.add(ird);
      FUNDING_NODES[i] = i;
      dataM[i] = Math.random() / 10;
      dataNpM[i + N] = dataM[i];
    }
    EXTRAPOLATOR =
        CombinedInterpolatorExtrapolatorFactory.getInterpolator(
            Interpolator1DFactory.LINEAR, Interpolator1DFactory.FLAT_EXTRAPOLATOR);

    CASH_NODES = new LinkedHashMap<String, double[]>();
    CASH_NODES.put(FUNDING_CURVE_NAME, FUNDING_NODES);
    FRA_NODES = new LinkedHashMap<String, double[]>();
    FRA_NODES.put(FORWARD_CURVE_NAME, FORWARD_NODES);
    MIXED_NODES = new LinkedHashMap<String, double[]>();
    MIXED_NODES.put(FORWARD_CURVE_NAME, FORWARD_NODES);
    MIXED_NODES.put(FUNDING_CURVE_NAME, FUNDING_NODES);
    CASH_INTERPOLATORS = new LinkedHashMap<String, Interpolator1D>();
    CASH_INTERPOLATORS.put(FUNDING_CURVE_NAME, EXTRAPOLATOR);
    FRA_INTERPOLATORS = new LinkedHashMap<String, Interpolator1D>();
    FRA_INTERPOLATORS.put(FORWARD_CURVE_NAME, EXTRAPOLATOR);
    MIXED_INTERPOLATORS = new LinkedHashMap<String, Interpolator1D>();
    MIXED_INTERPOLATORS.put(FORWARD_CURVE_NAME, EXTRAPOLATOR);
    MIXED_INTERPOLATORS.put(FUNDING_CURVE_NAME, EXTRAPOLATOR);

    XM = new DoubleMatrix1D(dataM);
    XN = new DoubleMatrix1D(dataN);
    XNM = new DoubleMatrix1D(dataNpM);
    CASH_ONLY =
        new MultipleYieldCurveFinderJacobian(
            new MultipleYieldCurveFinderDataBundle(
                CASH, new double[CASH.size()], null, CASH_NODES, CASH_INTERPOLATORS, false),
            SENSITIVITY_CALCULATOR);
    FRA_ONLY =
        new MultipleYieldCurveFinderJacobian(
            new MultipleYieldCurveFinderDataBundle(
                FRA, new double[FRA.size()], null, FRA_NODES, FRA_INTERPOLATORS, false),
            SENSITIVITY_CALCULATOR);
    MIXED =
        new MultipleYieldCurveFinderJacobian(
            new MultipleYieldCurveFinderDataBundle(
                MIXED_INSTRUMENT,
                new double[MIXED_INSTRUMENT.size()],
                null,
                MIXED_NODES,
                MIXED_INTERPOLATORS,
                false),
            SENSITIVITY_CALCULATOR);
  }