/// <summary>
        /// Main ctor.
        /// </summary>
        /// <param name="discreteSurface">The discrete surface ie 2 dimensional.</param>
        /// <param name="forwards">The forwards to be used for calibration.</param>
        /// <param name="xInterpolation">The basic interpolation to be applied to the x axis.</param>
        /// <param name="yInterpolation">The interpolation type for the y axis</param>
        /// <param name="allowExtrapolation">Not implemented in EO.</param>
        protected ExtendedInterpolatedSurface(DiscreteSurface discreteSurface, ParametricAdjustmentPoint[] forwards, IInterpolation xInterpolation,
                                              IInterpolation yInterpolation, bool allowExtrapolation)
            : base(discreteSurface, xInterpolation, yInterpolation, allowExtrapolation)
        {
            var values = discreteSurface.GetMatrixOfValues();
            var x      = discreteSurface.XArray;
            var width  = values.ColumnCount;

            if (forwards != null)
            {
                SpotValue = (double)forwards[0].parameterValue;
                var length = forwards.Length;
                var fwds   = new double[length - 1];
                for (var index = 1; index < length; index++)
                {
                    fwds[index - 1] = (double)forwards[index].parameterValue;
                }
                var fwdCurve = new LinearInterpolation();
                fwdCurve.Initialize(x, fwds);
                ForwardCurve = fwdCurve;
            }
            if (yInterpolation.GetType() == typeof(SABRModelInterpolation))
            {
                var y      = discreteSurface.YArray;
                var length = values.RowCount;
                for (int i = 0; i < length; i++)
                {
                    //interpolate each maturity first (in strike) with SABR
                    var yinterp = (SABRModelInterpolation)yInterpolation.Clone();
                    yinterp.ExpiryTime = x[i];
                    if (Forward != null && Spot != null)
                    {
                        yinterp.AssetPrice = Convert.ToDecimal(Forward);
                    }
                    else
                    {
                        var fwd = ForwardCurve.ValueAt(yinterp.ExpiryTime, true);
                        yinterp.AssetPrice = Convert.ToDecimal(fwd);
                    }
                    yinterp.Initialize(y, values.Row(i).Data);
                    var curve           = new DiscreteCurve(y, values.Row(i).Data);
                    var interpolatedCol = new InterpolatedCurve(curve, yinterp, true);
                    _interpolatedColumns.Add(interpolatedCol);
                }
            }
            else //o.w interpolate at each strike point (in time)
            {
                for (int i = 0; i < width; i++)
                {
                    var interp = xInterpolation.Clone();
                    interp.Initialize(x, values.Column(i).Data);
                    var curve           = new DiscreteCurve(x, values.Column(i).Data);
                    var interpolatedCol = new InterpolatedCurve(curve, interp, true);
                    _interpolatedColumns.Add(interpolatedCol);
                }
            }
        }
        /// <summary>
        /// Main ctor.
        /// </summary>
        /// <param name="columns">The column values.</param>
        /// <param name="forwards">An array of forwards to the expiry dates. The length of this array is + 1, as the first element is the spot value.</param>
        /// <param name="values">The discrete surface ie 2 dimensional.</param>
        /// <param name="xInterpolation">The basic interpolation to be applied to the x axis.</param>
        /// <param name="yInterpolation">The basic interpolation to be applied to the y axis.</param>
        /// <param name="rows">The row values.</param>
        public ExtendedInterpolatedSurface(double[] rows, double[] columns, double[] forwards, Matrix values, IInterpolation xInterpolation, IInterpolation yInterpolation)
            : base(new DiscreteSurface(rows, columns, values), xInterpolation, yInterpolation, true)
        {
            var width           = values.ColumnCount;
            var discreteSurface = new DiscreteSurface(rows, columns, values);
            var x = discreteSurface.XArray;

            if (forwards != null)
            {
                SpotValue = forwards[0];
                var n    = forwards.Length;
                var fwds = new double[n - 1];
                for (var index = 1; index < n; index++)
                {
                    fwds[index - 1] = forwards[index];
                }
                ForwardCurve = new LinearInterpolation();
                ForwardCurve.Initialize(rows, fwds);
            }
            if (yInterpolation.GetType() == typeof(SABRModelInterpolation))
            {
                var length = values.RowCount;
                var y      = discreteSurface.YArray;
                for (int i = 0; i < length; i++)
                {
                    //interpolate each maturity first (in strike) with SABR
                    var yinterp = (SABRModelInterpolation)yInterpolation.Clone();
                    yinterp.ExpiryTime = x[i];
                    if (Forward != null && Spot != null)
                    {
                        yinterp.AssetPrice = Convert.ToDecimal(Forward);
                    }
                    else
                    {
                        var fwd = ForwardCurve.ValueAt(yinterp.ExpiryTime, true);
                        yinterp.AssetPrice = Convert.ToDecimal(fwd);
                    }
                    yinterp.Initialize(y, values.Row(i).Data);
                    var curve           = new DiscreteCurve(y, values.Row(i).Data);
                    var interpolatedCol = new InterpolatedCurve(curve, yinterp, true);
                    _interpolatedColumns.Add(interpolatedCol);
                }
            }
            else //o.w interpolate at each strike point (in time)
            {
                for (int i = 0; i < width; i++)
                {
                    var interp = xInterpolation.Clone();
                    interp.Initialize(x, values.Column(i).Data);
                    var curve           = new DiscreteCurve(x, values.Column(i).Data);
                    var interpolatedCol = new InterpolatedCurve(curve, interp, true);
                    _interpolatedColumns.Add(interpolatedCol);
                }
            }
        }