/*
  ############################################################################
  This function computes the arbitrary-precision natural logarithm for any
  positive (x) argument to up to 100 decimals.

  SPECIAL CASE:
  If (x) is a decimal value (0 < x < 1), then Ln(x) = -Ln(1/x)

  ERRORS:
  Returns FALSE if non-numeric or if (x <= 0).

  NO DEPENDENCIES
  ############################################################################
*/


   function BC_Ln ($xArgStr, $Decimals=16)
{
   $x = trim($xArgStr);
   if (StrPos($x, '-') !== FALSE or $x <= 0 or !Is_Numeric($x))
      {return FALSE;}

   $q = trim($Decimals);
   $Q = 100;
   if ($q  > $Q) {$q = $Q;}
   if ($q <=  0) {$q =  1;}

// -------------------------------------------------------
// Handle case of fractional (x) values where (0 < x < 1).

   $sign = ''; if ($x > 0 and $x < 1) {$sign = '-'; $x = bcDiv('1', $x, $Q);}

// -------------------------------------------------------------------------------
// Natural logarithm of 10 to 110 decimals (used as internal conversion constant).

   $LN_10 = '2.30258509299404568401799145468436420760110148862877297603332790096757260967735248023599720508959829834196778403';

/* -----------------------------------------
   Determine power of 10 in positive (x) and
   where to place the decimal in the result.
*/
   $dpos = 1;
   if($x >= 10)
     {
      $dpos = floor(log10($x) + 1);
      $x = Str_Replace('.', '', $x);
      $x = substr($x,0,1).'.'.substr($x,1, StrLen($x));
     }

   $PrecisionLimit = '0.'.Str_Repeat('0', $q).'1';
   $n = $term = 1;
   $sum = 0;
   $k = bcDiv(bcSub($x, '1', $Q), $x, $Q);

   while (abs($term) > $PrecisionLimit)
  {
   $numer = bcpow($k, $n, $Q);
   $denom = $n;
   $term  = bcDiv($numer, $denom, $Q);
   $sum   = bcAdd($sum, $term, $Q);
   $n++;
  }
   $sum = bcAdd($sum, bcMul($dpos-1, $LN_10, $Q), $Q);

// ----------------------------------------------
// Round the sum to the given number of decimals.

   return $sign.bcAdd($sum, Str_Replace('1','5', $PrecisionLimit), $q);

} // End of  BC_Ln(...)