/*
===========================================================================
This function computes the arbitrary-precision exponential frunction.
x = Argument as numeric string, like $x = '1.0123456789'
so as not to be mistaken for a standard double-precision
variable.
ERRORS:
FALSE is returned if non-numeric argument.
NO DEPENDENCIES
===========================================================================
*/
function BC_Exp ($xArgStr, $Decimals=16)
{
// Read (x) argument.
$x = trim($xArgStr);
// -------------------------------------
// Error if (x) argument is non-numeric.
if (!Is_Numeric($x)) {return FALSE;}
// -----------------------------------------------------
// Set internal working precision limit to 100 decimals.
$Q = 100;
// ----------------------------------------------------------------
// Limit output decimals range from 1 to a maximum of 100 decimals.
$q = trim($Decimals); if ($q > 100){$q = 100;} if ($q < 1) {$q = 1;}
$flag = ''; if (bcComp($x, '-1', $Q) == 0) {$x = '1'; $flag = 'TRUE';}
// --------------------------
// Initial control variables.
$denom = $numer = $prevSum = $CurrSum = '1';
$prevSum = $w = '';
// -----------------------------
// Set decimals precision limit.
$PrecisionLimit = '0.' . Str_Repeat('0', $q-1) . '1';
/* ---------------------------------------------------
Perform summation loop and stop when set precision
limit is reached or when (n == 100).
*/
for ($n=1; $n < 100; $n++)
{
$numer = bcMul($numer, $x, $Q);
$denom = bcMul($n, $denom);
$term = bcDiv($numer, $denom, $Q);
$CurrSum = bcAdd($CurrSum, $term, $Q);
$absDiff = Str_Replace('-', '', bcSub($CurrSum, $prevSum, $Q));
// -------------------------------------
// Stop when precision limit is reached.
if (bcComp($absDiff, $PrecisionLimit, $Q) < 0) {break;}
// ---------------------------------------
// Replace previous sum value with current
// sum value for the next cycle, if any.
$prevSum = $CurrSum;
}
// -------------------------------------
// Account for special case of (x = -1).
if ($flag) {$CurrSum = bcDiv('1', $CurrSum, $Q);}
// -------------------------------------------------
// Round off result to specified number of decimals.
$CurrSum = trim(bcAdd($CurrSum, '0.'.Str_Repeat('0', $q).'5', $q));
// ------------------------------------------------
// Remove any redundant zeros and/or decimal point.
return Rtrim(Rtrim($CurrSum, '0'), '.');
} // End of BC_Exp()