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]

   1  <?php
   2  
   3  namespace PhpOffice\PhpSpreadsheet\Calculation\Engineering;
   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 BesselK
  11  {
  12      use ArrayEnabled;
  13  
  14      /**
  15       * BESSELK.
  16       *
  17       *    Returns the modified Bessel function Kn(x), which is equivalent to the Bessel functions evaluated
  18       *        for purely imaginary arguments.
  19       *
  20       *    Excel Function:
  21       *        BESSELK(x,ord)
  22       *
  23       * @param mixed $x A float value at which to evaluate the function.
  24       *                                If x is nonnumeric, BESSELK returns the #VALUE! error value.
  25       *                      Or can be an array of values
  26       * @param mixed $ord The integer order of the Bessel function.
  27       *                       If ord is not an integer, it is truncated.
  28       *                                If $ord is nonnumeric, BESSELK returns the #VALUE! error value.
  29       *                       If $ord < 0, BESSELKI returns the #NUM! error value.
  30       *                      Or can be an array of values
  31       *
  32       * @return array|float|string Result, or a string containing an error
  33       *         If an array of numbers is passed as an argument, then the returned result will also be an array
  34       *            with the same dimensions
  35       */
  36      public static function BESSELK($x, $ord)
  37      {
  38          if (is_array($x) || is_array($ord)) {
  39              return self::evaluateArrayArguments([self::class, __FUNCTION__], $x, $ord);
  40          }
  41  
  42          try {
  43              $x = EngineeringValidations::validateFloat($x);
  44              $ord = EngineeringValidations::validateInt($ord);
  45          } catch (Exception $e) {
  46              return $e->getMessage();
  47          }
  48  
  49          if (($ord < 0) || ($x <= 0.0)) {
  50              return ExcelError::NAN();
  51          }
  52  
  53          $fBk = self::calculate($x, $ord);
  54  
  55          return (is_nan($fBk)) ? ExcelError::NAN() : $fBk;
  56      }
  57  
  58      private static function calculate(float $x, int $ord): float
  59      {
  60          // special cases
  61          switch ($ord) {
  62              case 0:
  63                  return self::besselK0($x);
  64              case 1:
  65                  return self::besselK1($x);
  66          }
  67  
  68          return self::besselK2($x, $ord);
  69      }
  70  
  71      /**
  72       * Mollify Phpstan.
  73       *
  74       * @codeCoverageIgnore
  75       */
  76      private static function callBesselI(float $x, int $ord): float
  77      {
  78          $rslt = BesselI::BESSELI($x, $ord);
  79          if (!is_float($rslt)) {
  80              throw new Exception('Unexpected array or string');
  81          }
  82  
  83          return $rslt;
  84      }
  85  
  86      private static function besselK0(float $x): float
  87      {
  88          if ($x <= 2) {
  89              $fNum2 = $x * 0.5;
  90              $y = ($fNum2 * $fNum2);
  91  
  92              return -log($fNum2) * self::callBesselI($x, 0) +
  93                  (-0.57721566 + $y * (0.42278420 + $y * (0.23069756 + $y * (0.3488590e-1 + $y * (0.262698e-2 + $y *
  94                                      (0.10750e-3 + $y * 0.74e-5))))));
  95          }
  96  
  97          $y = 2 / $x;
  98  
  99          return exp(-$x) / sqrt($x) *
 100              (1.25331414 + $y * (-0.7832358e-1 + $y * (0.2189568e-1 + $y * (-0.1062446e-1 + $y *
 101                              (0.587872e-2 + $y * (-0.251540e-2 + $y * 0.53208e-3))))));
 102      }
 103  
 104      private static function besselK1(float $x): float
 105      {
 106          if ($x <= 2) {
 107              $fNum2 = $x * 0.5;
 108              $y = ($fNum2 * $fNum2);
 109  
 110              return log($fNum2) * self::callBesselI($x, 1) +
 111                  (1 + $y * (0.15443144 + $y * (-0.67278579 + $y * (-0.18156897 + $y * (-0.1919402e-1 + $y *
 112                                      (-0.110404e-2 + $y * (-0.4686e-4))))))) / $x;
 113          }
 114  
 115          $y = 2 / $x;
 116  
 117          return exp(-$x) / sqrt($x) *
 118              (1.25331414 + $y * (0.23498619 + $y * (-0.3655620e-1 + $y * (0.1504268e-1 + $y * (-0.780353e-2 + $y *
 119                                  (0.325614e-2 + $y * (-0.68245e-3)))))));
 120      }
 121  
 122      private static function besselK2(float $x, int $ord): float
 123      {
 124          $fTox = 2 / $x;
 125          $fBkm = self::besselK0($x);
 126          $fBk = self::besselK1($x);
 127          for ($n = 1; $n < $ord; ++$n) {
 128              $fBkp = $fBkm + $n * $fTox * $fBk;
 129              $fBkm = $fBk;
 130              $fBk = $fBkp;
 131          }
 132  
 133          return $fBk;
 134      }
 135  }