-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extract all Error functions from the Engineering class into a dedicat…
…ed Erf and ErfC classes (#1850) * Extract all Error functions from the Engineering class into a dedicated Erf and ErfC classes Retain the original methods in the Engineering class as stubs for BC, but deprecate them. They will be removed for PHPSpreadsheet v2 Note that unit tests still point to the Engineering class stubs; these should be modified to use the Erf and ErfC classes directly when the stubs are removed * Reminder that ERF is used (either directly or Indirectly) in some of the statistical functions as well
- Loading branch information
Mark Baker
authored
Feb 13, 2021
1 parent
61d2e6d
commit be328c3
Showing
5 changed files
with
172 additions
and
88 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
<?php | ||
|
||
namespace PhpOffice\PhpSpreadsheet\Calculation\Engineering; | ||
|
||
use PhpOffice\PhpSpreadsheet\Calculation\Functions; | ||
|
||
class Erf | ||
{ | ||
private static $twoSqrtPi = 1.128379167095512574; | ||
|
||
/** | ||
* ERF. | ||
* | ||
* Returns the error function integrated between the lower and upper bound arguments. | ||
* | ||
* Note: In Excel 2007 or earlier, if you input a negative value for the upper or lower bound arguments, | ||
* the function would return a #NUM! error. However, in Excel 2010, the function algorithm was | ||
* improved, so that it can now calculate the function for both positive and negative ranges. | ||
* PhpSpreadsheet follows Excel 2010 behaviour, and accepts negative arguments. | ||
* | ||
* Excel Function: | ||
* ERF(lower[,upper]) | ||
* | ||
* @param float $lower lower bound for integrating ERF | ||
* @param float $upper upper bound for integrating ERF. | ||
* If omitted, ERF integrates between zero and lower_limit | ||
* | ||
* @return float|string | ||
*/ | ||
public static function ERF($lower, $upper = null) | ||
{ | ||
$lower = Functions::flattenSingleValue($lower); | ||
$upper = Functions::flattenSingleValue($upper); | ||
|
||
if (is_numeric($lower)) { | ||
if ($upper === null) { | ||
return self::erfValue($lower); | ||
} | ||
if (is_numeric($upper)) { | ||
return self::erfValue($upper) - self::erfValue($lower); | ||
} | ||
} | ||
|
||
return Functions::VALUE(); | ||
} | ||
|
||
/** | ||
* ERFPRECISE. | ||
* | ||
* Returns the error function integrated between the lower and upper bound arguments. | ||
* | ||
* Excel Function: | ||
* ERF.PRECISE(limit) | ||
* | ||
* @param float $limit bound for integrating ERF | ||
* | ||
* @return float|string | ||
*/ | ||
public static function ERFPRECISE($limit) | ||
{ | ||
$limit = Functions::flattenSingleValue($limit); | ||
|
||
return self::ERF($limit); | ||
} | ||
|
||
// | ||
// Private method to calculate the erf value | ||
// | ||
public static function erfValue($value) | ||
{ | ||
if (abs($value) > 2.2) { | ||
return 1 - ErfC::ERFC($value); | ||
} | ||
$sum = $term = $value; | ||
$xsqr = ($value * $value); | ||
$j = 1; | ||
do { | ||
$term *= $xsqr / $j; | ||
$sum -= $term / (2 * $j + 1); | ||
++$j; | ||
$term *= $xsqr / $j; | ||
$sum += $term / (2 * $j + 1); | ||
++$j; | ||
if ($sum == 0.0) { | ||
break; | ||
} | ||
} while (abs($term / $sum) > Functions::PRECISION); | ||
|
||
return self::$twoSqrtPi * $sum; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
<?php | ||
|
||
namespace PhpOffice\PhpSpreadsheet\Calculation\Engineering; | ||
|
||
use PhpOffice\PhpSpreadsheet\Calculation\Functions; | ||
|
||
class ErfC | ||
{ | ||
/** | ||
* ERFC. | ||
* | ||
* Returns the complementary ERF function integrated between x and infinity | ||
* | ||
* Note: In Excel 2007 or earlier, if you input a negative value for the lower bound argument, | ||
* the function would return a #NUM! error. However, in Excel 2010, the function algorithm was | ||
* improved, so that it can now calculate the function for both positive and negative x values. | ||
* PhpSpreadsheet follows Excel 2010 behaviour, and accepts nagative arguments. | ||
* | ||
* Excel Function: | ||
* ERFC(x) | ||
* | ||
* @param float $value The lower bound for integrating ERFC | ||
* | ||
* @return float|string | ||
*/ | ||
public static function ERFC($value) | ||
{ | ||
$value = Functions::flattenSingleValue($value); | ||
|
||
if (is_numeric($value)) { | ||
return self::erfcValue($value); | ||
} | ||
|
||
return Functions::VALUE(); | ||
} | ||
|
||
// | ||
// Private method to calculate the erfc value | ||
// | ||
private static $oneSqrtPi = 0.564189583547756287; | ||
|
||
private static function erfcValue($value) | ||
{ | ||
if (abs($value) < 2.2) { | ||
return 1 - Erf::erfValue($value); | ||
} | ||
if ($value < 0) { | ||
return 2 - self::ERFC(-$value); | ||
} | ||
$a = $n = 1; | ||
$b = $c = $value; | ||
$d = ($value * $value) + 0.5; | ||
$q1 = $q2 = $b / $d; | ||
do { | ||
$t = $a * $n + $b * $value; | ||
$a = $b; | ||
$b = $t; | ||
$t = $c * $n + $d * $value; | ||
$c = $d; | ||
$d = $t; | ||
$n += 0.5; | ||
$q1 = $q2; | ||
$q2 = $b / $d; | ||
} while ((abs($q1 - $q2) / $q2) > Functions::PRECISION); | ||
|
||
return self::$oneSqrtPi * exp(-$value * $value) * $q2; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters