/**
  * POISSON
  *
  * Returns the Poisson distribution. A common application of the Poisson distribution
  * is predicting the number of events over a specific time, such as the number of
  * cars arriving at a toll plaza in 1 minute.
  *
  * @param    float        $value
  * @param    float        $mean        Mean Value
  * @param    boolean        $cumulative
  * @return    float
  *
  */
 public static function POISSON($value, $mean, $cumulative)
 {
     $value = Functions::flattenSingleValue($value);
     $mean = Functions::flattenSingleValue($mean);
     if (is_numeric($value) && is_numeric($mean)) {
         if ($value < 0 || $mean <= 0) {
             return Functions::NAN();
         }
         if (is_numeric($cumulative) || is_bool($cumulative)) {
             if ($cumulative) {
                 $summer = 0;
                 for ($i = 0; $i <= floor($value); ++$i) {
                     $summer += pow($mean, $i) / MathTrig::FACT($i);
                 }
                 return exp(0 - $mean) * $summer;
             } else {
                 return exp(0 - $mean) * pow($mean, $value) / MathTrig::FACT($value);
             }
         }
     }
     return Functions::VALUE();
 }
 /**
  *    BESSELJ
  *
  *    Returns the Bessel function
  *
  *    Excel Function:
  *        BESSELJ(x,ord)
  *
  * @access    public
  * @category Engineering Functions
  * @param    float $x The value at which to evaluate the function.
  *                                If x is nonnumeric, BESSELJ returns the #VALUE! error value.
  * @param    integer $ord The order of the Bessel function. If n is not an integer, it is truncated.
  *                                If $ord is nonnumeric, BESSELJ returns the #VALUE! error value.
  *                                If $ord < 0, BESSELJ returns the #NUM! error value.
  * @return    float
  *
  */
 public static function BESSELJ($x, $ord)
 {
     $x = is_null($x) ? 0.0 : Functions::flattenSingleValue($x);
     $ord = is_null($ord) ? 0.0 : Functions::flattenSingleValue($ord);
     if (is_numeric($x) && is_numeric($ord)) {
         $ord = floor($ord);
         if ($ord < 0) {
             return Functions::NAN();
         }
         $fResult = 0;
         if (abs($x) <= 30) {
             $fResult = $fTerm = pow($x / 2, $ord) / MathTrig::FACT($ord);
             $ordK = 1;
             $fSqrX = $x * $x / -4;
             do {
                 $fTerm *= $fSqrX;
                 $fTerm /= $ordK * ($ordK + $ord);
                 $fResult += $fTerm;
             } while (abs($fTerm) > 1.0E-12 && ++$ordK < 100);
         } else {
             $f_PI_DIV_2 = M_PI / 2;
             $f_PI_DIV_4 = M_PI / 4;
             $fXAbs = abs($x);
             $fResult = sqrt(M_2DIVPI / $fXAbs) * cos($fXAbs - $ord * $f_PI_DIV_2 - $f_PI_DIV_4);
             if ($ord & 1 && $x < 0) {
                 $fResult = -$fResult;
             }
         }
         return is_nan($fResult) ? Functions::NAN() : $fResult;
     }
     return Functions::VALUE();
 }