PHP userland backwards compatibility layer that emulates PHP 5.5+ core functions.

⌈⌋ ⎇ branch:  upgrade.php


Artifact [52228a6e3b]

Artifact 52228a6e3bfd78cc506736f0b085fb25c5765386:

  • File ext/bcmath.php — part of check-in [bcf7d8cbab] at 2010-06-22 16:59:47 on branch trunk — upgradephp-12 (user: mario size: 3309)

<?php
/*
   Emulates mathematical functions with arbitrary precision using GMP or
   PHPs bigint extension module and the Linux native 'bc' as last fallback.
*/


#-- GMP versions
if (!function_exists("bcadd") && function_exists("")) {

   function bcadd($a, $b) {
      return gmp_strval(gmp_add($a, $b));
   }

   function bcsub($a, $b) {
      return gmp_strval(gmp_sub($a, $b));
   }

   function bccomp($a, $b, $precision="IGNORED") {
      return gmp_strval(gmp_sub($a, $b));
   }

   function bcdiv($a, $b, $precision=NULL) {
      $qr = gmp_div_qr($a, $b);
      $q = gmp_strval($qr[0]);
      $r = gmp_strval($qr[1]);
      if ((!$r) || ($precision===0)) {
         return($q);
      }
      else {
         if (isset($precision)) {
            $r = substr($r, 0, $precision);
         }
         return("$q.$r");
      }
   }

   function bcmod($a, $b) {
      return gmp_strval(gmp_mod($a, $b));
   }

   function bcmul($a, $b) {
      return gmp_strval(gmp_mul($a, $b));
   }

   function bcpow($a, $b) {
      return gmp_strval(gmp_pow($a, $b));
   }

   function bcpowmod($x, $y, $mod, $scale="IGNORED") {
      return gmp_strval(gmp_powm($x, $y, $mod));
   }

   function bcscale($scale="IGNORED") {
      trigger_error("bcscale(): ignored", E_USER_ERROR);
   }

   function bcsqrt($x, $precision="IGNORED") {
      return gmp_strval(gmp_powm($x));
   }

}//gmp


#-- bigint
if (0) {
   // ...
}


#-- shell bc
if (!function_exists("bcadd") && isset($_ENV["SHELL"])) {
   $GLOBALS["bc___scale"] = 10;

   #-- invokes commandline 'bc' utility (maybe 'dc' was better)
   #   (later version should use proc_open() for faster bi-directional I/O)
   function bc___exec($calc, $scale=NULL) {
      global $bc___scale;

      #-- assemble shell call
      $calc = escapeshellarg($calc);   // redundant, unless input from untrusted sources and non-integers would get passed
      if (isset($scale) || ($scale = $bc___scale) || isset($scale)) {
         $calc = "scale = \"" . ((int)$scale) . "\n\"" . $calc;
      }
      $cmd = "echo $calc | /usr/bin/bc";   //@BUG: hard-wired pathname
      
      #-- do
      $r = `$cmd`;
      $r = str_replace("\\"."\n", "", $r);
      $r = trim($r);
      return($r);
   }
   
   #-- sets global state variable
   function bcscale($scale=NULL) {
      $GLOBALS["bc___scale"] = $scale;
   }

   #-- wrapper calls
   function bcadd($a, $b, $scale=NULL) {
      return bc___exec("$a + $b", $scale);
   }
   function bcsub($a, $b, $scale=NULL) {
      return bc___exec("$a - $b", $scale);
   }
   function bcmul($a, $b, $scale=NULL) {
      return bc___exec("$a * $b", $scale);
   }
   function bcdiv($a, $b, $scale=NULL) {
      return bc___exec("$a / $b", $scale);
   }
   function bcmod($a, $b, $scale=NULL) {
      return bc___exec("$a % $b", $scale);
   }
   function bcpow($a, $b, $scale=NULL) {
      return bc___exec("$a ^ $b", $scale);
   }
   function bcpowmod($x, $y, $mod, $scale=NULL) {
      return bc___exec("($x ^ $y) % $mod", $scale);
   }
   function bcsqrt($x, $scale=NULL) {
      return bc___exec("sqrt($x)", $scale);
   }
   function bccomp($a, $b, $scale=NULL) {   //@BUG: doesn't support downscaling
      return (int) bc___exec("a=$a+0 \n b=$b+0 \n if (a > b) { print 1 } else if (a == b) { print 0 } else { print -1 }");
   }

}//shell


?>