Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.0.x will end 8 May 2023 (12 months).
  • Bug fixes for security issues in 4.0.x will end 13 November 2023 (18 months).
  • PHP version: minimum PHP 7.3.0 Note: the minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is also supported.

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

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Calculation\Statistical\Distributions;
   4  
   5  use PhpOffice\PhpSpreadsheet\Calculation\Functions;
   6  
   7  class NewtonRaphson
   8  {
   9      private const MAX_ITERATIONS = 256;
  10  
  11      protected $callback;
  12  
  13      public function __construct(callable $callback)
  14      {
  15          $this->callback = $callback;
  16      }
  17  
  18      public function execute(float $probability)
  19      {
  20          $xLo = 100;
  21          $xHi = 0;
  22  
  23          $dx = 1;
  24          $x = $xNew = 1;
  25          $i = 0;
  26  
  27          while ((abs($dx) > Functions::PRECISION) && ($i++ < self::MAX_ITERATIONS)) {
  28              // Apply Newton-Raphson step
  29              $result = call_user_func($this->callback, $x);
  30              $error = $result - $probability;
  31  
  32              if ($error == 0.0) {
  33                  $dx = 0;
  34              } elseif ($error < 0.0) {
  35                  $xLo = $x;
  36              } else {
  37                  $xHi = $x;
  38              }
  39  
  40              // Avoid division by zero
  41              if ($result != 0.0) {
  42                  $dx = $error / $result;
  43                  $xNew = $x - $dx;
  44              }
  45  
  46              // If the NR fails to converge (which for example may be the
  47              // case if the initial guess is too rough) we apply a bisection
  48              // step to determine a more narrow interval around the root.
  49              if (($xNew < $xLo) || ($xNew > $xHi) || ($result == 0.0)) {
  50                  $xNew = ($xLo + $xHi) / 2;
  51                  $dx = $xNew - $x;
  52              }
  53              $x = $xNew;
  54          }
  55  
  56          if ($i == self::MAX_ITERATIONS) {
  57              return Functions::NA();
  58          }
  59  
  60          return $x;
  61      }
  62  }