R1ShapeScaleDistribution.java

  1. package org.drip.measure.gamma;

  2. /*
  3.  * -*- mode: java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  4.  */

  5. /*!
  6.  * Copyright (C) 2020 Lakshmi Krishnamurthy
  7.  * Copyright (C) 2019 Lakshmi Krishnamurthy
  8.  *
  9.  *  This file is part of DROP, an open-source library targeting analytics/risk, transaction cost analytics,
  10.  *      asset liability management analytics, capital, exposure, and margin analytics, valuation adjustment
  11.  *      analytics, and portfolio construction analytics within and across fixed income, credit, commodity,
  12.  *      equity, FX, and structured products. It also includes auxiliary libraries for algorithm support,
  13.  *      numerical analysis, numerical optimization, spline builder, model validation, statistical learning,
  14.  *      and computational support.
  15.  *  
  16.  *      https://lakshmidrip.github.io/DROP/
  17.  *  
  18.  *  DROP is composed of three modules:
  19.  *  
  20.  *  - DROP Product Core - https://lakshmidrip.github.io/DROP-Product-Core/
  21.  *  - DROP Portfolio Core - https://lakshmidrip.github.io/DROP-Portfolio-Core/
  22.  *  - DROP Computational Core - https://lakshmidrip.github.io/DROP-Computational-Core/
  23.  *
  24.  *  DROP Product Core implements libraries for the following:
  25.  *  - Fixed Income Analytics
  26.  *  - Loan Analytics
  27.  *  - Transaction Cost Analytics
  28.  *
  29.  *  DROP Portfolio Core implements libraries for the following:
  30.  *  - Asset Allocation Analytics
  31.  *  - Asset Liability Management Analytics
  32.  *  - Capital Estimation Analytics
  33.  *  - Exposure Analytics
  34.  *  - Margin Analytics
  35.  *  - XVA Analytics
  36.  *
  37.  *  DROP Computational Core implements libraries for the following:
  38.  *  - Algorithm Support
  39.  *  - Computation Support
  40.  *  - Function Analysis
  41.  *  - Model Validation
  42.  *  - Numerical Analysis
  43.  *  - Numerical Optimizer
  44.  *  - Spline Builder
  45.  *  - Statistical Learning
  46.  *
  47.  *  Documentation for DROP is Spread Over:
  48.  *
  49.  *  - Main                     => https://lakshmidrip.github.io/DROP/
  50.  *  - Wiki                     => https://github.com/lakshmiDRIP/DROP/wiki
  51.  *  - GitHub                   => https://github.com/lakshmiDRIP/DROP
  52.  *  - Repo Layout Taxonomy     => https://github.com/lakshmiDRIP/DROP/blob/master/Taxonomy.md
  53.  *  - Javadoc                  => https://lakshmidrip.github.io/DROP/Javadoc/index.html
  54.  *  - Technical Specifications => https://github.com/lakshmiDRIP/DROP/tree/master/Docs/Internal
  55.  *  - Release Versions         => https://lakshmidrip.github.io/DROP/version.html
  56.  *  - Community Credits        => https://lakshmidrip.github.io/DROP/credits.html
  57.  *  - Issues Catalog           => https://github.com/lakshmiDRIP/DROP/issues
  58.  *  - JUnit                    => https://lakshmidrip.github.io/DROP/junit/index.html
  59.  *  - Jacoco                   => https://lakshmidrip.github.io/DROP/jacoco/index.html
  60.  *
  61.  *  Licensed under the Apache License, Version 2.0 (the "License");
  62.  *      you may not use this file except in compliance with the License.
  63.  *  
  64.  *  You may obtain a copy of the License at
  65.  *      http://www.apache.org/licenses/LICENSE-2.0
  66.  *  
  67.  *  Unless required by applicable law or agreed to in writing, software
  68.  *      distributed under the License is distributed on an "AS IS" BASIS,
  69.  *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  70.  *  
  71.  *  See the License for the specific language governing permissions and
  72.  *      limitations under the License.
  73.  */

  74. /**
  75.  * <i>R1ShapeScaleDistribution</i> implements the Shape and Scale Parameterization of the R<sup>1</sup> Gamma
  76.  *  Distribution. The References are:
  77.  *
  78.  * <br><br>
  79.  *  <ul>
  80.  *      <li>
  81.  *          Devroye, L. (1986): <i>Non-Uniform Random Variate Generation</i> <b>Springer-Verlag</b> New York
  82.  *      </li>
  83.  *      <li>
  84.  *          Gamma Distribution (2019): Gamma Distribution
  85.  *              https://en.wikipedia.org/wiki/Chi-squared_distribution
  86.  *      </li>
  87.  *      <li>
  88.  *          Louzada, F., P. L. Ramos, and E. Ramos (2019): A Note on Bias of Closed-Form Estimators for the
  89.  *              Gamma Distribution Derived From Likelihood Equations <i>The American Statistician</i> <b>73
  90.  *              (2)</b> 195-199
  91.  *      </li>
  92.  *      <li>
  93.  *          Minka, T. (2002): Estimating a Gamma distribution https://tminka.github.io/papers/minka-gamma.pdf
  94.  *      </li>
  95.  *      <li>
  96.  *          Ye, Z. S., and N. Chen (2017): Closed-Form Estimators for the Gamma Distribution Derived from
  97.  *              Likelihood Equations <i>The American Statistician</i> <b>71 (2)</b> 177-181
  98.  *      </li>
  99.  *  </ul>
  100.  *
  101.  *  <br><br>
  102.  *  <ul>
  103.  *      <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/ComputationalCore.md">Computational Core Module</a></li>
  104.  *      <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/NumericalAnalysisLibrary.md">Numerical Analysis Library</a></li>
  105.  *      <li><b>Project</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/measure/README.md">R<sup>d</sup> Continuous/Discrete Probability Measures</a></li>
  106.  *      <li><b>Package</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/measure/gamma/README.md">R<sup>1</sup> Gamma Distribution Implementation/Properties</a></li>
  107.  *  </ul>
  108.  *
  109.  * @author Lakshmi Krishnamurthy
  110.  */

  111. public class R1ShapeScaleDistribution
  112.     extends org.drip.measure.continuous.R1Univariate
  113. {
  114.     private double _cdfScaler = java.lang.Double.NaN;
  115.     private double _pdfScaler = java.lang.Double.NaN;
  116.     private org.drip.function.definition.R1ToR1 _gammaEstimator = null;
  117.     private org.drip.function.definition.R1ToR1 _digammaEstimator = null;
  118.     private org.drip.measure.gamma.ShapeScaleParameters _shapeScaleParameters = null;
  119.     private org.drip.function.definition.R2ToR1 _lowerIncompleteGammaEstimator = null;

  120.     /**
  121.      * Construct a Gamma Distribution from Shape and Rate Parameters
  122.      *
  123.      * @param shapeParameter Shape Parameter
  124.      * @param rateParameter Rate Parameter
  125.      * @param gammaEstimator Gamma Estimator
  126.      * @param digammaEstimator Digamma Estimator
  127.      * @param lowerIncompleteGammaEstimator Lower Incomplete Gamma Estimator
  128.      *
  129.      * @return Gamma Distribution from Shape Alpha and Rate Beta Parameters
  130.      */

  131.     public static final R1ShapeScaleDistribution ShapeRate (
  132.         final double shapeParameter,
  133.         final double rateParameter,
  134.         final org.drip.function.definition.R1ToR1 gammaEstimator,
  135.         final org.drip.function.definition.R1ToR1 digammaEstimator,
  136.         final org.drip.function.definition.R2ToR1 lowerIncompleteGammaEstimator)
  137.     {
  138.         return R1ShapeScaleDistribution.Standard (
  139.             shapeParameter,
  140.             1. / rateParameter,
  141.             gammaEstimator,
  142.             digammaEstimator,
  143.             lowerIncompleteGammaEstimator
  144.         );
  145.     }

  146.     /**
  147.      * Shape Summation Based ShapeScaleDistribution
  148.      *
  149.      * @param shapeParameterArray Shape Parameter Array
  150.      * @param scaleParameter Scale Parameter
  151.      * @param gammaEstimator Gamma Estimator
  152.      * @param digammaEstimator Digamma Estimator
  153.      * @param lowerIncompleteGammaEstimator Lower Incomplete Gamma Estimator
  154.      *
  155.      * @return Shape Summation Based ShapeScaleDistribution
  156.      */

  157.     public static final R1ShapeScaleDistribution ShapeSummation (
  158.         final double[] shapeParameterArray,
  159.         final double scaleParameter,
  160.         final org.drip.function.definition.R1ToR1 gammaEstimator,
  161.         final org.drip.function.definition.R1ToR1 digammaEstimator,
  162.         final org.drip.function.definition.R2ToR1 lowerIncompleteGammaEstimator)
  163.     {
  164.         if (null == shapeParameterArray)
  165.         {
  166.             return null;
  167.         }

  168.         double shapeParameter = 0.;
  169.         int shapeParameterArraySize = shapeParameterArray.length;

  170.         if (0 == shapeParameterArraySize)
  171.         {
  172.             return null;
  173.         }

  174.         for (int shapeParameterIndex = 0;
  175.             shapeParameterIndex < shapeParameterArraySize;
  176.             ++shapeParameterIndex)
  177.         {
  178.             if (!org.drip.numerical.common.NumberUtil.IsValid (
  179.                 shapeParameterArray[shapeParameterIndex]
  180.             ))
  181.             {
  182.                 return null;
  183.             }

  184.             shapeParameter += shapeParameterArray[shapeParameterIndex];
  185.         }

  186.         return R1ShapeScaleDistribution.Standard (
  187.             shapeParameter,
  188.             scaleParameter,
  189.             gammaEstimator,
  190.             digammaEstimator,
  191.             lowerIncompleteGammaEstimator
  192.         );
  193.     }

  194.     /**
  195.      * Construct the Standard R1ShapeScaleDistribution Instance
  196.      *
  197.      * @param shapeParameter Shape Parameter
  198.      * @param scaleParameter Scale Parameter
  199.      * @param gammaEstimator Gamma Estimator
  200.      * @param digammaEstimator Digamma Estimator
  201.      * @param lowerIncompleteGammaEstimator Lower Incomplete Gamma Estimator
  202.      *
  203.      * @return The R1ShapeScaleDistribution Instance
  204.      */

  205.     public static final R1ShapeScaleDistribution Standard (
  206.         final double shapeParameter,
  207.         final double scaleParameter,
  208.         final org.drip.function.definition.R1ToR1 gammaEstimator,
  209.         final org.drip.function.definition.R1ToR1 digammaEstimator,
  210.         final org.drip.function.definition.R2ToR1 lowerIncompleteGammaEstimator)
  211.     {
  212.         try
  213.         {
  214.             return new R1ShapeScaleDistribution (
  215.                 new org.drip.measure.gamma.ShapeScaleParameters (
  216.                     shapeParameter,
  217.                     scaleParameter
  218.                 ),
  219.                 gammaEstimator,
  220.                 digammaEstimator,
  221.                 lowerIncompleteGammaEstimator
  222.             );
  223.         }
  224.         catch (java.lang.Exception e)
  225.         {
  226.             e.printStackTrace();
  227.         }

  228.         return null;
  229.     }

  230.     private double randomMarsaglia1977 (
  231.         final double shapeParameterIn)
  232.         throws java.lang.Exception
  233.     {
  234.         double shapeParameter = shapeParameterIn < 1. ? shapeParameterIn + 1. : shapeParameterIn;
  235.         double d = shapeParameter - 1. / 3.;
  236.         double v = 0.;
  237.         double u = 0.;

  238.         double c = 1. / java.lang.Math.sqrt (
  239.             9. * d
  240.         );

  241.         while (true)
  242.         {
  243.             double x = org.drip.measure.gaussian.NormalQuadrature.Random();

  244.             u = java.lang.Math.random();

  245.             v = 1. + c * x;
  246.             v = v * v * v;

  247.             if (v > 0. &&
  248.                 0.5 * x * x + d - d * v + d * java.lang.Math.log (
  249.                     v
  250.                 ) > java.lang.Math.log (
  251.                     u
  252.                 )
  253.             )
  254.             {
  255.                 double marsagliaRandom =_shapeScaleParameters.scale() * d * v;

  256.                 return shapeParameter != shapeParameterIn ?
  257.                     marsagliaRandom * java.lang.Math.pow (
  258.                         u,
  259.                         1. / shapeParameterIn
  260.                     ) : marsagliaRandom;
  261.             }
  262.         }
  263.     }

  264.     /**
  265.      * R1ShapeScaleDistribution Constructor
  266.      *
  267.      * @param shapeScaleParameters Shape-Scale Parameters
  268.      * @param gammaEstimator Gamma Estimator
  269.      * @param digammaEstimator Digamma Estimator
  270.      * @param lowerIncompleteGammaEstimator Lower Incomplete Gamma Estimator
  271.      *
  272.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  273.      */

  274.     public R1ShapeScaleDistribution (
  275.         final org.drip.measure.gamma.ShapeScaleParameters shapeScaleParameters,
  276.         final org.drip.function.definition.R1ToR1 gammaEstimator,
  277.         final org.drip.function.definition.R1ToR1 digammaEstimator,
  278.         final org.drip.function.definition.R2ToR1 lowerIncompleteGammaEstimator)
  279.         throws java.lang.Exception
  280.     {
  281.         if (null == (_shapeScaleParameters = shapeScaleParameters) ||
  282.             null == (_gammaEstimator = gammaEstimator) ||
  283.             null == (_digammaEstimator = digammaEstimator) ||
  284.             null == (_lowerIncompleteGammaEstimator = lowerIncompleteGammaEstimator)
  285.         )
  286.         {
  287.             throw new java.lang.Exception (
  288.                 "R1ShapeScaleDistribution Constructor => Invalid Inputs"
  289.             );
  290.         }

  291.         double shape = _shapeScaleParameters.shape();

  292.         _pdfScaler = (
  293.             _cdfScaler = 1. / _gammaEstimator.evaluate (
  294.                 shape
  295.             )
  296.         ) * java.lang.Math.pow (
  297.             _shapeScaleParameters.scale(),
  298.             -1. * shape
  299.         );
  300.     }

  301.     /**
  302.      * Retrieve the Shape-Scale Parameters
  303.      *
  304.      * @return The Shape-Scale Parameters
  305.      */

  306.     public org.drip.measure.gamma.ShapeScaleParameters shapeScaleParameters()
  307.     {
  308.         return _shapeScaleParameters;
  309.     }

  310.     /**
  311.      * Retrieve the Gamma Estimator
  312.      *
  313.      * @return Gamma Estimator
  314.      */

  315.     public org.drip.function.definition.R1ToR1 gammaEstimator()
  316.     {
  317.         return _gammaEstimator;
  318.     }

  319.     /**
  320.      * Retrieve the Digamma Estimator
  321.      *
  322.      * @return Digamma Estimator
  323.      */

  324.     public org.drip.function.definition.R1ToR1 digammaEstimator()
  325.     {
  326.         return _digammaEstimator;
  327.     }

  328.     /**
  329.      * Retrieve the Lower Incomplete Gamma Estimator
  330.      *
  331.      * @return Lower Incomplete Gamma Estimator
  332.      */

  333.     public org.drip.function.definition.R2ToR1 lowerIncompleteGammaEstimator()
  334.     {
  335.         return _lowerIncompleteGammaEstimator;
  336.     }

  337.     @Override public double[] support()
  338.     {
  339.         return new double[]
  340.         {
  341.             0.,
  342.             java.lang.Double.POSITIVE_INFINITY
  343.         };
  344.     }

  345.     @Override public double density (
  346.         final double t)
  347.         throws java.lang.Exception
  348.     {
  349.         if (!supported (
  350.             t
  351.         ))
  352.         {
  353.             throw new java.lang.Exception (
  354.                 "ShapeScaleDistribution::density => Variate not in Range"
  355.             );
  356.         }

  357.         return _pdfScaler * java.lang.Math.pow (
  358.             t,
  359.             _shapeScaleParameters.shape() - 1.
  360.         ) * java.lang.Math.exp (
  361.             -1. * t / _shapeScaleParameters.scale()
  362.         );
  363.     }

  364.     @Override public double cumulative (
  365.         final double t)
  366.         throws java.lang.Exception
  367.     {
  368.         if (!supported (
  369.             t
  370.         ))
  371.         {
  372.             throw new java.lang.Exception (
  373.                 "ShapeScaleDistribution::cumulative => Invalid Inputs"
  374.             );
  375.         }

  376.         return _cdfScaler * _lowerIncompleteGammaEstimator.evaluate (
  377.             _shapeScaleParameters.shape(),
  378.             t / _shapeScaleParameters.scale()
  379.         );
  380.     }

  381.     @Override public double mean()
  382.         throws java.lang.Exception
  383.     {
  384.         return _shapeScaleParameters.shape() * _shapeScaleParameters.scale();
  385.     }

  386.     @Override public double mode()
  387.         throws java.lang.Exception
  388.     {
  389.         double shape = _shapeScaleParameters.shape();

  390.         if (shape < 1.)
  391.         {
  392.             throw new java.lang.Exception (
  393.                 "ShapeScaleDistribution::mode => No Closed Form Available"
  394.             );
  395.         }

  396.         return (shape - 1.) * _shapeScaleParameters.scale();
  397.     }

  398.     @Override public double variance()
  399.         throws java.lang.Exception
  400.     {
  401.         double scale = _shapeScaleParameters.scale();

  402.         return _shapeScaleParameters.shape() * scale * scale;
  403.     }

  404.     @Override public double skewness()
  405.         throws java.lang.Exception
  406.     {
  407.         return 2. * java.lang.Math.sqrt (1. / _shapeScaleParameters.shape());
  408.     }

  409.     @Override public double excessKurtosis()
  410.         throws java.lang.Exception
  411.     {
  412.         return 6. / _shapeScaleParameters.shape();
  413.     }

  414.     @Override public double differentialEntropy()
  415.         throws java.lang.Exception
  416.     {
  417.         double shape = _shapeScaleParameters.shape();

  418.         return shape + java.lang.Math.log (
  419.             _shapeScaleParameters.scale() / _cdfScaler
  420.         ) + (1. - shape) * _digammaEstimator.evaluate (
  421.             shape
  422.         );
  423.     }

  424.     @Override public org.drip.function.definition.R1ToR1 momentGeneratingFunction()
  425.     {
  426.         final double scale = _shapeScaleParameters.scale();

  427.         return new org.drip.function.definition.R1ToR1 (
  428.             null
  429.         )
  430.         {
  431.             @Override public double evaluate (
  432.                 final double t)
  433.                 throws java.lang.Exception
  434.             {
  435.                 if (!org.drip.numerical.common.NumberUtil.IsValid (
  436.                         t
  437.                     ) || t >= 1. / scale
  438.                 )
  439.                 {
  440.                     throw new java.lang.Exception (
  441.                         "ShapeScaleDistribution::momentGeneratingFunction::evaluate => Invalid Input"
  442.                     );
  443.                 }

  444.                 return java.lang.Math.pow (
  445.                     1. - scale * t,
  446.                     -1. * _shapeScaleParameters.shape()
  447.                 );
  448.             }
  449.         };
  450.     }

  451.     /**
  452.      * Retrieve the Central Limit Theorem Equivalent Normal Distribution Proxy
  453.      *
  454.      * @return The Central Limit Theorem Equivalent Normal Distribution Proxy
  455.      */

  456.     public org.drip.measure.gaussian.R1UnivariateNormal cltProxy()
  457.     {
  458.         double scale = _shapeScaleParameters.scale();

  459.         double shape = _shapeScaleParameters.shape();

  460.         try
  461.         {
  462.             return new org.drip.measure.gaussian.R1UnivariateNormal (
  463.                 shape * scale,
  464.                 scale * java.lang.Math.sqrt (
  465.                     shape
  466.                 )
  467.             );
  468.         }
  469.         catch (java.lang.Exception e)
  470.         {
  471.             e.printStackTrace();
  472.         }

  473.         return null;
  474.     }

  475.     /**
  476.      * Compute the Logarithmic Expectation
  477.      *
  478.      * @return The Logarithmic Expectation
  479.      *
  480.      * @throws java.lang.Exception Thrown if the Logarithmic Expectation cannot be computed
  481.      */

  482.     public double logarithmicExpectation()
  483.         throws java.lang.Exception
  484.     {
  485.         return _digammaEstimator.evaluate (
  486.             _shapeScaleParameters.shape()
  487.         ) - java.lang.Math.log (
  488.             _shapeScaleParameters.scale()
  489.         );
  490.     }

  491.     /**
  492.      * Compute the Banneheke-Ekayanake Approximation for the Median when k gte 1
  493.      *
  494.      * @return The Banneheke-Ekayanake Approximation for the Median
  495.      *
  496.      * @throws java.lang.Exception Thrown if the Median cannot be computed
  497.      */

  498.     public double bannehekeEkayanakeMedianApproximation()
  499.         throws java.lang.Exception
  500.     {
  501.         double shape = _shapeScaleParameters.shape();

  502.         if (1. > shape)
  503.         {
  504.             throw new java.lang.Exception (
  505.                 "ShapeScaleDistribution::bannehekeEkayanakeMedianApproximation => Invalid Shape Parameter"
  506.             );
  507.         }

  508.         return (3. * shape - 0.8) / (3. * shape - 0.2) * mean();
  509.     }

  510.     /**
  511.      * Compute the Ramanujan-Choi Approximation for the Median
  512.      *
  513.      * @return The Ramanujan-Choi Approximation for the Median
  514.      */

  515.     public double ramanujanChoiMedianApproximation()
  516.     {
  517.         double shape = _shapeScaleParameters.shape();

  518.         double inverseShapeParameter = 1. / shape;

  519.         return shape - 1. / 3. +
  520.             8. * inverseShapeParameter / 405. +
  521.             184. * inverseShapeParameter * inverseShapeParameter / 25515. +
  522.             2248. * inverseShapeParameter * inverseShapeParameter * inverseShapeParameter / 3444525.;
  523.     }

  524.     /**
  525.      * Compute the Chen-Rubin Median Lower Bound
  526.      *
  527.      * @return The Chen-Rubin Median Lower Bound
  528.      */

  529.     public double chenRubinMedianLowerBound()
  530.     {
  531.         return _shapeScaleParameters.shape() - 1. / 3.;
  532.     }

  533.     /**
  534.      * Compute the Chen-Rubin Median Upper Bound
  535.      *
  536.      * @return The Chen-Rubin Median Upper Bound
  537.      */

  538.     public double chenRubinMedianUpperBound()
  539.     {
  540.         return _shapeScaleParameters.shape();
  541.     }

  542.     /**
  543.      * Generate a Scaled Gamma Distribution
  544.      *
  545.      * @param scaleFactor The Gamma Distribution Scale Factor
  546.      *
  547.      * @return Scaled Gamma Distribution
  548.      */

  549.     public R1ShapeScaleDistribution scale (
  550.         final double scaleFactor)
  551.     {
  552.         try
  553.         {
  554.             return new R1ShapeScaleDistribution (
  555.                 new org.drip.measure.gamma.ShapeScaleParameters (
  556.                     _shapeScaleParameters.shape(),
  557.                     _shapeScaleParameters.scale() * scaleFactor
  558.                 ),
  559.                 _gammaEstimator,
  560.                 _digammaEstimator,
  561.                 _lowerIncompleteGammaEstimator
  562.             );
  563.         }
  564.         catch (java.lang.Exception e)
  565.         {
  566.             e.printStackTrace();
  567.         }

  568.         return null;
  569.     }

  570.     /**
  571.      * Retrieve the Array of Natural Parameters
  572.      *
  573.      * @return Array of Natural Parameters
  574.      */

  575.     public double[] naturalParameters()
  576.     {
  577.         return new double[]
  578.         {
  579.             _shapeScaleParameters.shape() - 1,
  580.             -1. / _shapeScaleParameters.scale()
  581.         };
  582.     }

  583.     /**
  584.      * Retrieve the Array of Natural Statistics
  585.      *
  586.      * @param x X
  587.      *
  588.      * @return Array of Natural Statistics
  589.      */

  590.     public double[] naturalStatistics (
  591.         final double x)
  592.     {
  593.         return org.drip.numerical.common.NumberUtil.IsValid (
  594.             x
  595.         ) ? new double[]
  596.         {
  597.             x,
  598.             java.lang.Math.log (
  599.                 x
  600.             )
  601.         } : null;
  602.     }

  603.     /**
  604.      * Generate the Exponential Family Representation
  605.      *
  606.      * @param x X
  607.      *
  608.      * @return Exponential Family Representation
  609.      */

  610.     public org.drip.measure.gamma.ExponentialFamilyRepresentation exponentialFamilyRepresentation (
  611.         final double x)
  612.     {
  613.         try
  614.         {
  615.             return new org.drip.measure.gamma.ExponentialFamilyRepresentation (
  616.                 naturalParameters(),
  617.                 naturalStatistics (
  618.                     x
  619.                 )
  620.             );
  621.         }
  622.         catch (java.lang.Exception e)
  623.         {
  624.             e.printStackTrace();
  625.         }

  626.         return null;
  627.     }

  628.     /**
  629.      * Compute the Laplacian
  630.      *
  631.      * @param s S
  632.      *
  633.      * @return The Laplacian
  634.      *
  635.      * @throws java.lang.Exception Thrown if the Inputs are Invalid
  636.      */

  637.     public double laplacian (
  638.         final double s)
  639.         throws java.lang.Exception
  640.     {
  641.         if (0. > s)
  642.         {
  643.             throw new java.lang.Exception (
  644.                 "ShapeScaleDistribution::laplacian => Invalid Shape Parameter"
  645.             );
  646.         }

  647.         return java.lang.Math.pow (
  648.             1. + s * _shapeScaleParameters.scale(),
  649.             -1. * _shapeScaleParameters.shape()
  650.         );
  651.     }

  652.     /**
  653.      * Generate a Random Variable using the Ahrens-Dieter (1982) Scheme
  654.      *
  655.      * @return Random Variable using the Ahrens-Dieter (1982) Scheme
  656.      *
  657.      * @throws java.lang.Exception Thrown if the Random Instance cannot be estimated
  658.      */

  659.     public double randomAhrensDieter1982()
  660.         throws java.lang.Exception
  661.     {
  662.         double shape = _shapeScaleParameters.shape();

  663.         double eta = 0.;
  664.         double random = 0.;
  665.         double epsilon = 0.;
  666.         int k = (int) shape;
  667.         double delta = shape - k;

  668.         for (int index = 0;
  669.             index < k;
  670.             ++index)
  671.         {
  672.             random = random - java.lang.Math.log (
  673.                 java.lang.Math.random()
  674.             );
  675.         }

  676.         if (0. == delta)
  677.         {
  678.             return random;
  679.         }

  680.         while (true)
  681.         {
  682.             double u = java.lang.Math.random();

  683.             double v = java.lang.Math.random();

  684.             double w = java.lang.Math.random();

  685.             if (u <= java.lang.Math.E / (java.lang.Math.E + delta))
  686.             {
  687.                 epsilon = java.lang.Math.pow (
  688.                     v,
  689.                     1. / delta
  690.                 );

  691.                 eta = w * java.lang.Math.pow (
  692.                     epsilon,
  693.                     delta - 1.
  694.                 );
  695.             }
  696.             else
  697.             {
  698.                 epsilon = 1. - java.lang.Math.log (
  699.                     v
  700.                 );

  701.                 eta = w * java.lang.Math.exp (
  702.                     -1. * epsilon
  703.                 );
  704.             }

  705.             if (eta <= java.lang.Math.pow (
  706.                 epsilon,
  707.                 delta - 1.
  708.             ) * java.lang.Math.exp (
  709.                 -1. * epsilon
  710.                 )
  711.             )
  712.             {
  713.                 break;
  714.             }
  715.         }

  716.         return _shapeScaleParameters.scale() * (random + epsilon);
  717.     }

  718.     /**
  719.      * Generate a Random Variable using the Marsaglia (1977) Scheme
  720.      *
  721.      * @return Random Variable using the Marsaglia (1977) Scheme
  722.      *
  723.      * @throws java.lang.Exception Thrown if the Random Instance cannot be estimated
  724.      */

  725.     public double randomMarsaglia1977()
  726.         throws java.lang.Exception
  727.     {
  728.         return randomMarsaglia1977 (
  729.             _shapeScaleParameters.shape()
  730.         );
  731.     }
  732. }