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