Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 400 and 401] [Versions 401 and 402] [Versions 401 and 403]

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions;
   4  
   5  use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
   6  use PhpOffice\PhpSpreadsheet\Calculation\Exception;
   7  use PhpOffice\PhpSpreadsheet\Calculation\Functions;
   8  use PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
   9  
  10  class StudentT
  11  {
  12      use ArrayEnabled;
  13  
  14      private const MAX_ITERATIONS = 256;
  15  
  16      /**
  17       * TDIST.
  18       *
  19       * Returns the probability of Student's T distribution.
  20       *
  21       * @param mixed $value Float value for the distribution
  22       *                      Or can be an array of values
  23       * @param mixed $degrees Integer value for degrees of freedom
  24       *                      Or can be an array of values
  25       * @param mixed $tails Integer value for the number of tails (1 or 2)
  26       *                      Or can be an array of values
  27       *
  28       * @return array|float|string The result, or a string containing an error
  29       *         If an array of numbers is passed as an argument, then the returned result will also be an array
  30       *            with the same dimensions
  31       */
  32      public static function distribution($value, $degrees, $tails)
  33      {
  34          if (is_array($value) || is_array($degrees) || is_array($tails)) {
  35              return self::evaluateArrayArguments([self::class, __FUNCTION__], $value, $degrees, $tails);
  36          }
  37  
  38          try {
  39              $value = DistributionValidations::validateFloat($value);
  40              $degrees = DistributionValidations::validateInt($degrees);
  41              $tails = DistributionValidations::validateInt($tails);
  42          } catch (Exception $e) {
  43              return $e->getMessage();
  44          }
  45  
  46          if (($value < 0) || ($degrees < 1) || ($tails < 1) || ($tails > 2)) {
  47              return ExcelError::NAN();
  48          }
  49  
  50          return self::calculateDistribution($value, $degrees, $tails);
  51      }
  52  
  53      /**
  54       * TINV.
  55       *
  56       * Returns the one-tailed probability of the chi-squared distribution.
  57       *
  58       * @param mixed $probability Float probability for the function
  59       *                      Or can be an array of values
  60       * @param mixed $degrees Integer value for degrees of freedom
  61       *                      Or can be an array of values
  62       *
  63       * @return array|float|string The result, or a string containing an error
  64       *         If an array of numbers is passed as an argument, then the returned result will also be an array
  65       *            with the same dimensions
  66       */
  67      public static function inverse($probability, $degrees)
  68      {
  69          if (is_array($probability) || is_array($degrees)) {
  70              return self::evaluateArrayArguments([self::class, __FUNCTION__], $probability, $degrees);
  71          }
  72  
  73          try {
  74              $probability = DistributionValidations::validateProbability($probability);
  75              $degrees = DistributionValidations::validateInt($degrees);
  76          } catch (Exception $e) {
  77              return $e->getMessage();
  78          }
  79  
  80          if ($degrees <= 0) {
  81              return ExcelError::NAN();
  82          }
  83  
  84          $callback = function ($value) use ($degrees) {
  85              return self::distribution($value, $degrees, 2);
  86          };
  87  
  88          $newtonRaphson = new NewtonRaphson($callback);
  89  
  90          return $newtonRaphson->execute($probability);
  91      }
  92  
  93      /**
  94       * @return float
  95       */
  96      private static function calculateDistribution(float $value, int $degrees, int $tails)
  97      {
  98          //    tdist, which finds the probability that corresponds to a given value
  99          //    of t with k degrees of freedom. This algorithm is translated from a
 100          //    pascal function on p81 of "Statistical Computing in Pascal" by D
 101          //    Cooke, A H Craven & G M Clark (1985: Edward Arnold (Pubs.) Ltd:
 102          //    London). The above Pascal algorithm is itself a translation of the
 103          //    fortran algoritm "AS 3" by B E Cooper of the Atlas Computer
 104          //    Laboratory as reported in (among other places) "Applied Statistics
 105          //    Algorithms", editied by P Griffiths and I D Hill (1985; Ellis
 106          //    Horwood Ltd.; W. Sussex, England).
 107          $tterm = $degrees;
 108          $ttheta = atan2($value, sqrt($tterm));
 109          $tc = cos($ttheta);
 110          $ts = sin($ttheta);
 111  
 112          if (($degrees % 2) === 1) {
 113              $ti = 3;
 114              $tterm = $tc;
 115          } else {
 116              $ti = 2;
 117              $tterm = 1;
 118          }
 119  
 120          $tsum = $tterm;
 121          while ($ti < $degrees) {
 122              $tterm *= $tc * $tc * ($ti - 1) / $ti;
 123              $tsum += $tterm;
 124              $ti += 2;
 125          }
 126  
 127          $tsum *= $ts;
 128          if (($degrees % 2) == 1) {
 129              $tsum = Functions::M_2DIVPI * ($tsum + $ttheta);
 130          }
 131  
 132          $tValue = 0.5 * (1 + $tsum);
 133          if ($tails == 1) {
 134              return 1 - abs($tValue);
 135          }
 136  
 137          return 1 - abs((1 - $tValue) - $tValue);
 138      }
 139  }