web/lib/Zend/Locale/Math/PhpMath.php
changeset 64 162c1de6545a
parent 19 1c2f13fd785c
child 68 ecaf28ffe26e
equal deleted inserted replaced
63:5b37998e522e 64:162c1de6545a
       
     1 <?php
       
     2 /**
       
     3  * Zend Framework
       
     4  *
       
     5  * LICENSE
       
     6  *
       
     7  * This source file is subject to the new BSD license that is bundled
       
     8  * with this package in the file LICENSE.txt.
       
     9  * It is also available through the world-wide-web at this URL:
       
    10  * http://framework.zend.com/license/new-bsd
       
    11  * If you did not receive a copy of the license and are unable to
       
    12  * obtain it through the world-wide-web, please send an email
       
    13  * to license@zend.com so we can send you a copy immediately.
       
    14  *
       
    15  * @category   Zend
       
    16  * @package    Zend_Locale
       
    17  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    18  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    19  * @version    $Id: PhpMath.php 20096 2010-01-06 02:05:09Z bkarwin $
       
    20  */
       
    21 
       
    22 
       
    23 /**
       
    24  * Utility class for proxying math function to bcmath functions, if present,
       
    25  * otherwise to PHP builtin math operators, with limited detection of overflow conditions.
       
    26  * Sampling of PHP environments and platforms suggests that at least 80% to 90% support bcmath.
       
    27  * This file should only be loaded for the 10% to 20% lacking access to the bcmath extension.
       
    28  *
       
    29  * @category   Zend
       
    30  * @package    Zend_Locale
       
    31  * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
       
    32  * @license    http://framework.zend.com/license/new-bsd     New BSD License
       
    33  */
       
    34 class Zend_Locale_Math_PhpMath extends Zend_Locale_Math
       
    35 {
       
    36     public static function disable()
       
    37     {
       
    38         self::$_bcmathDisabled = true;
       
    39         self::$add   = array('Zend_Locale_Math_PhpMath', 'Add');
       
    40         self::$sub   = array('Zend_Locale_Math_PhpMath', 'Sub');
       
    41         self::$pow   = array('Zend_Locale_Math_PhpMath', 'Pow');
       
    42         self::$mul   = array('Zend_Locale_Math_PhpMath', 'Mul');
       
    43         self::$div   = array('Zend_Locale_Math_PhpMath', 'Div');
       
    44         self::$comp  = array('Zend_Locale_Math_PhpMath', 'Comp');
       
    45         self::$sqrt  = array('Zend_Locale_Math_PhpMath', 'Sqrt');
       
    46         self::$mod   = array('Zend_Locale_Math_PhpMath', 'Mod');
       
    47         self::$scale = array('Zend_Locale_Math_PhpMath', 'Scale');
       
    48 
       
    49         self::$defaultScale     = 0;
       
    50         self::$defaultPrecision = 1;
       
    51     }
       
    52 
       
    53     public static $defaultScale;
       
    54     public static $defaultPrecision;
       
    55 
       
    56 
       
    57     public static function Add($op1, $op2, $scale = null)
       
    58     {
       
    59         if ($scale === null) {
       
    60             $scale     = Zend_Locale_Math_PhpMath::$defaultScale;
       
    61             $precision = Zend_Locale_Math_PhpMath::$defaultPrecision;
       
    62         } else {
       
    63             $precision = pow(10, -$scale);
       
    64         }
       
    65 
       
    66         if (empty($op1)) {
       
    67             $op1 = 0;
       
    68         }
       
    69         $op1 = self::normalize($op1);
       
    70         $op2 = self::normalize($op2);
       
    71         $result = $op1 + $op2;
       
    72         if (is_infinite($result)  or  (abs($result - $op2 - $op1) > $precision)) {
       
    73             require_once 'Zend/Locale/Math/Exception.php';
       
    74             throw new Zend_Locale_Math_Exception("addition overflow: $op1 + $op2 != $result", $op1, $op2, $result);
       
    75         }
       
    76 
       
    77         return self::round(self::normalize($result), $scale);
       
    78     }
       
    79 
       
    80     public static function Sub($op1, $op2, $scale = null)
       
    81     {
       
    82         if ($scale === null) {
       
    83             $scale     = Zend_Locale_Math_PhpMath::$defaultScale;
       
    84             $precision = Zend_Locale_Math_PhpMath::$defaultPrecision;
       
    85         } else {
       
    86             $precision = pow(10, -$scale);
       
    87         }
       
    88 
       
    89         if (empty($op1)) {
       
    90             $op1 = 0;
       
    91         }
       
    92         $op1  = self::normalize($op1);
       
    93         $op2  = self::normalize($op2);
       
    94         $result = $op1 - $op2;
       
    95         if (is_infinite($result)  or  (abs($result + $op2 - $op1) > $precision)) {
       
    96             require_once 'Zend/Locale/Math/Exception.php';
       
    97             throw new Zend_Locale_Math_Exception("subtraction overflow: $op1 - $op2 != $result", $op1, $op2, $result);
       
    98         }
       
    99 
       
   100         return self::round(self::normalize($result), $scale);
       
   101     }
       
   102 
       
   103     public static function Pow($op1, $op2, $scale = null)
       
   104     {
       
   105         if ($scale === null) {
       
   106             $scale = Zend_Locale_Math_PhpMath::$defaultScale;
       
   107         }
       
   108 
       
   109         $op1 = self::normalize($op1);
       
   110         $op2 = self::normalize($op2);
       
   111 
       
   112         // BCMath extension doesn't use decimal part of the power
       
   113         // Provide the same behavior
       
   114         $op2 = ($op2 > 0) ? floor($op2) : ceil($op2);
       
   115 
       
   116         $result = pow($op1, $op2);
       
   117         if (is_infinite($result)  or  is_nan($result)) {
       
   118             require_once 'Zend/Locale/Math/Exception.php';
       
   119             throw new Zend_Locale_Math_Exception("power overflow: $op1 ^ $op2", $op1, $op2, $result);
       
   120         }
       
   121 
       
   122         return self::round(self::normalize($result), $scale);
       
   123     }
       
   124 
       
   125     public static function Mul($op1, $op2, $scale = null)
       
   126     {
       
   127         if ($scale === null) {
       
   128             $scale = Zend_Locale_Math_PhpMath::$defaultScale;
       
   129         }
       
   130 
       
   131         if (empty($op1)) {
       
   132             $op1 = 0;
       
   133         }
       
   134         $op1 = self::normalize($op1);
       
   135         $op2 = self::normalize($op2);
       
   136         $result = $op1 * $op2;
       
   137         if (is_infinite($result)  or  is_nan($result)) {
       
   138             require_once 'Zend/Locale/Math/Exception.php';
       
   139             throw new Zend_Locale_Math_Exception("multiplication overflow: $op1 * $op2 != $result", $op1, $op2, $result);
       
   140         }
       
   141 
       
   142         return self::round(self::normalize($result), $scale);
       
   143     }
       
   144 
       
   145     public static function Div($op1, $op2, $scale = null)
       
   146     {
       
   147         if ($scale === null) {
       
   148             $scale = Zend_Locale_Math_PhpMath::$defaultScale;
       
   149         }
       
   150 
       
   151         if (empty($op2)) {
       
   152             require_once 'Zend/Locale/Math/Exception.php';
       
   153             throw new Zend_Locale_Math_Exception("can not divide by zero", $op1, $op2, null);
       
   154         }
       
   155         if (empty($op1)) {
       
   156             $op1 = 0;
       
   157         }
       
   158         $op1 = self::normalize($op1);
       
   159         $op2 = self::normalize($op2);
       
   160         $result = $op1 / $op2;
       
   161         if (is_infinite($result)  or  is_nan($result)) {
       
   162             require_once 'Zend/Locale/Math/Exception.php';
       
   163             throw new Zend_Locale_Math_Exception("division overflow: $op1 / $op2 != $result", $op1, $op2, $result);
       
   164         }
       
   165 
       
   166         return self::round(self::normalize($result), $scale);
       
   167     }
       
   168 
       
   169     public static function Sqrt($op1, $scale = null)
       
   170     {
       
   171         if ($scale === null) {
       
   172             $scale = Zend_Locale_Math_PhpMath::$defaultScale;
       
   173         }
       
   174 
       
   175         if (empty($op1)) {
       
   176             $op1 = 0;
       
   177         }
       
   178         $op1 = self::normalize($op1);
       
   179         $result = sqrt($op1);
       
   180         if (is_nan($result)) {
       
   181             return NULL;
       
   182         }
       
   183 
       
   184         return self::round(self::normalize($result), $scale);
       
   185     }
       
   186 
       
   187     public static function Mod($op1, $op2)
       
   188     {
       
   189         if (empty($op1)) {
       
   190             $op1 = 0;
       
   191         }
       
   192         if (empty($op2)) {
       
   193             return NULL;
       
   194         }
       
   195         $op1 = self::normalize($op1);
       
   196         $op2 = self::normalize($op2);
       
   197         if ((int)$op2 == 0) {
       
   198             return NULL;
       
   199         }
       
   200         $result = $op1 % $op2;
       
   201         if (is_nan($result)  or  (($op1 - $result) % $op2 != 0)) {
       
   202             require_once 'Zend/Locale/Math/Exception.php';
       
   203             throw new Zend_Locale_Math_Exception("modulus calculation error: $op1 % $op2 != $result", $op1, $op2, $result);
       
   204         }
       
   205 
       
   206         return self::normalize($result);
       
   207     }
       
   208 
       
   209     public static function Comp($op1, $op2, $scale = null)
       
   210     {
       
   211         if ($scale === null) {
       
   212             $scale     = Zend_Locale_Math_PhpMath::$defaultScale;
       
   213         }
       
   214 
       
   215         if (empty($op1)) {
       
   216             $op1 = 0;
       
   217         }
       
   218         $op1 = self::normalize($op1);
       
   219         $op2 = self::normalize($op2);
       
   220         if ($scale <> 0) {
       
   221             $op1 = self::round($op1, $scale);
       
   222             $op2 = self::round($op2, $scale);
       
   223         } else {
       
   224             $op1 = ($op1 > 0) ? floor($op1) : ceil($op1);
       
   225             $op2 = ($op2 > 0) ? floor($op2) : ceil($op2);
       
   226         }
       
   227         if ($op1 > $op2) {
       
   228             return 1;
       
   229         } else if ($op1 < $op2) {
       
   230             return -1;
       
   231         }
       
   232         return 0;
       
   233     }
       
   234 
       
   235     public static function Scale($scale)
       
   236     {
       
   237         if ($scale > 9) {
       
   238             require_once 'Zend/Locale/Math/Exception.php';
       
   239             throw new Zend_Locale_Math_Exception("can not scale to precision $scale", $scale, null, null);
       
   240         }
       
   241         self::$defaultScale     = $scale;
       
   242         self::$defaultPrecision = pow(10, -$scale);
       
   243         return true;
       
   244     }
       
   245 }
       
   246 
       
   247 Zend_Locale_Math_PhpMath::disable(); // disable use of bcmath functions