Example #1
0
        public static double inv_m1_approx_smart(double beta, double f, double sigma)
        {
            // Compute some relevant bounds
            var log_001 = -4.605170186;
            var lo      = log_001 * (1 - beta) - 0.5 * sigma * sigma;
            var hi      = Math.Min(37 - 0.5 * sigma * sigma, 0.5 * sigma * sigma); //! < 10
            // Evaluate the function on those points
            // Using the actual function to too costly
            var zz      = 0.0;
            var vlo     = m1_beta_black(beta, lo, sigma);
            var dhi_dmu = 0.0;
            var vhi     = m1_beta_black_b(beta, hi, sigma, ref zz, ref dhi_dmu, ref zz, 1.0);

            // Treat bounds
            if (f < vlo)
            {
                return(inv_g(beta, f));          // no convexity
            }
            if (f > vhi)
            {
                return(inv_g(beta, f) - 0.5 * sigma * sigma);            // full convexity
            }
            //! Middle region, fit approximately
            // a + b x + c exp(d x)
            var d = dhi_dmu / vhi;
            var c = vhi / Math.Exp(dhi_dmu * hi / vhi);
            var b = -(vlo - c * Math.Exp(d * lo)) / (hi - lo);
            var a = -b * hi;
            //! The invert in closed form
            var aw = Math.Exp(-d * (a - f) / b) * c * d / b;

            return(-(b * SpecialFunction.wapr(aw) + a * d - d * f) / (b * d));
        }
Example #2
0
        public static double inv_g(double beta, double y)
        {
            if (beta == 0.0 || y >= 1.0)
            {
                return(Math.Log(y));
            }
            var expo = -(beta * beta - 2.0 * beta + y) / (beta * (beta - 1.0));

            if (expo > 700.0)
            {
                //! This happens only for small beta
                //! Need solution here - default to newton iteration?
                //! For the time being we use an expansion
                var l1  = expo + Math.Log((1 - beta) / beta); // no risk here, beta is small
                var l12 = l1 * l1;
                var l13 = l12 * l1;
                var l14 = l12 * l12;
                var l15 = l14 * l12;
                var l2  = Math.Log(l1);
                var l22 = l2 * l2;
                var l23 = l22 * l2;
                var l24 = l23 * l2;
                var wwb = l1 - l2 + l2 / l1 + l2 * (-2.0 + l2) / (2.0 * l12)
                          + l2 * (6.0 - 9.0 * l2 + 2.0 * l22) / (6.0 * l13)
                          + l2 * (-12.0 + 36.0 * l2 - 22.0 * l22 + 3.0 * l23) / (12.0 * l14)
                          + l2 * (60.0 - 300.0 * l2 + 350.0 * l22 - 125.0 * l23 + 12.0 * l24) / (60.0 * l15);
                return(beta * wwb - wwb + beta - 2.0 + y / beta);
            }

            var aw = Math.Exp(expo) * (1.0 - beta) / beta;
            var wb = SpecialFunction.wapr(aw);

            return(beta * wb - wb + beta - 2.0 + y / beta);
        }
Example #3
0
        public static double inv_m1_beta_black_approx_2(double beta, double f, double sigma)
        {
            //! Numerical
            var expArg = -1.0 * (SpecialFunction.pow2(beta) - 2.0 * beta + f) / ((-1.0 + beta) * beta);

            if (expArg > 37.0)
            {
                return(inv_g(beta, f));
            }
            var aw = -0.5000000000 * (2.0 * SpecialFunction.pow2(beta) + SpecialFunction.pow2(sigma) - 4.0 * beta + 2.0)
                     * Math.Exp(expArg)
                     / ((-1.0 + beta) * beta);
            var wb = SpecialFunction.wapr(aw);

            return(beta * wb - wb + beta - 2.0 + f / beta);
        }