247 Zeilen
		
	
	
	
		
			8 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			247 Zeilen
		
	
	
	
		
			8 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * Zend Framework
 | |
|  *
 | |
|  * LICENSE
 | |
|  *
 | |
|  * This source file is subject to the new BSD license that is bundled
 | |
|  * with this package in the file LICENSE.txt.
 | |
|  * It is also available through the world-wide-web at this URL:
 | |
|  * http://framework.zend.com/license/new-bsd
 | |
|  * If you did not receive a copy of the license and are unable to
 | |
|  * obtain it through the world-wide-web, please send an email
 | |
|  * to license@zend.com so we can send you a copy immediately.
 | |
|  *
 | |
|  * @category   Zend
 | |
|  * @package    Zend_Locale
 | |
|  * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 | |
|  * @license    http://framework.zend.com/license/new-bsd     New BSD License
 | |
|  * @version    $Id$
 | |
|  */
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * Utility class for proxying math function to bcmath functions, if present,
 | |
|  * otherwise to PHP builtin math operators, with limited detection of overflow conditions.
 | |
|  * Sampling of PHP environments and platforms suggests that at least 80% to 90% support bcmath.
 | |
|  * This file should only be loaded for the 10% to 20% lacking access to the bcmath extension.
 | |
|  *
 | |
|  * @category   Zend
 | |
|  * @package    Zend_Locale
 | |
|  * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 | |
|  * @license    http://framework.zend.com/license/new-bsd     New BSD License
 | |
|  */
 | |
| class Zend_Locale_Math_PhpMath extends Zend_Locale_Math
 | |
| {
 | |
|     public static function disable()
 | |
|     {
 | |
|         self::$_bcmathDisabled = true;
 | |
|         self::$add   = array('Zend_Locale_Math_PhpMath', 'Add');
 | |
|         self::$sub   = array('Zend_Locale_Math_PhpMath', 'Sub');
 | |
|         self::$pow   = array('Zend_Locale_Math_PhpMath', 'Pow');
 | |
|         self::$mul   = array('Zend_Locale_Math_PhpMath', 'Mul');
 | |
|         self::$div   = array('Zend_Locale_Math_PhpMath', 'Div');
 | |
|         self::$comp  = array('Zend_Locale_Math_PhpMath', 'Comp');
 | |
|         self::$sqrt  = array('Zend_Locale_Math_PhpMath', 'Sqrt');
 | |
|         self::$mod   = array('Zend_Locale_Math_PhpMath', 'Mod');
 | |
|         self::$scale = array('Zend_Locale_Math_PhpMath', 'Scale');
 | |
| 
 | |
|         self::$defaultScale     = 0;
 | |
|         self::$defaultPrecision = 1;
 | |
|     }
 | |
| 
 | |
|     public static $defaultScale;
 | |
|     public static $defaultPrecision;
 | |
| 
 | |
| 
 | |
|     public static function Add($op1, $op2, $scale = null)
 | |
|     {
 | |
|         if ($scale === null) {
 | |
|             $scale     = Zend_Locale_Math_PhpMath::$defaultScale;
 | |
|             $precision = Zend_Locale_Math_PhpMath::$defaultPrecision;
 | |
|         } else {
 | |
|             $precision = pow(10, -$scale);
 | |
|         }
 | |
| 
 | |
|         if (empty($op1)) {
 | |
|             $op1 = 0;
 | |
|         }
 | |
|         $op1 = self::normalize($op1);
 | |
|         $op2 = self::normalize($op2);
 | |
|         $result = $op1 + $op2;
 | |
|         if (is_infinite($result)  or  (abs($result - $op2 - $op1) > $precision)) {
 | |
|             require_once 'Zend/Locale/Math/Exception.php';
 | |
|             throw new Zend_Locale_Math_Exception("addition overflow: $op1 + $op2 != $result", $op1, $op2, $result);
 | |
|         }
 | |
| 
 | |
|         return self::round(self::normalize($result), $scale);
 | |
|     }
 | |
| 
 | |
|     public static function Sub($op1, $op2, $scale = null)
 | |
|     {
 | |
|         if ($scale === null) {
 | |
|             $scale     = Zend_Locale_Math_PhpMath::$defaultScale;
 | |
|             $precision = Zend_Locale_Math_PhpMath::$defaultPrecision;
 | |
|         } else {
 | |
|             $precision = pow(10, -$scale);
 | |
|         }
 | |
| 
 | |
|         if (empty($op1)) {
 | |
|             $op1 = 0;
 | |
|         }
 | |
|         $op1  = self::normalize($op1);
 | |
|         $op2  = self::normalize($op2);
 | |
|         $result = $op1 - $op2;
 | |
|         if (is_infinite($result)  or  (abs($result + $op2 - $op1) > $precision)) {
 | |
|             require_once 'Zend/Locale/Math/Exception.php';
 | |
|             throw new Zend_Locale_Math_Exception("subtraction overflow: $op1 - $op2 != $result", $op1, $op2, $result);
 | |
|         }
 | |
| 
 | |
|         return self::round(self::normalize($result), $scale);
 | |
|     }
 | |
| 
 | |
|     public static function Pow($op1, $op2, $scale = null)
 | |
|     {
 | |
|         if ($scale === null) {
 | |
|             $scale = Zend_Locale_Math_PhpMath::$defaultScale;
 | |
|         }
 | |
| 
 | |
|         $op1 = self::normalize($op1);
 | |
|         $op2 = self::normalize($op2);
 | |
| 
 | |
|         // BCMath extension doesn't use decimal part of the power
 | |
|         // Provide the same behavior
 | |
|         $op2 = ($op2 > 0) ? floor($op2) : ceil($op2);
 | |
| 
 | |
|         $result = pow($op1, $op2);
 | |
|         if (is_infinite($result)  or  is_nan($result)) {
 | |
|             require_once 'Zend/Locale/Math/Exception.php';
 | |
|             throw new Zend_Locale_Math_Exception("power overflow: $op1 ^ $op2", $op1, $op2, $result);
 | |
|         }
 | |
| 
 | |
|         return self::round(self::normalize($result), $scale);
 | |
|     }
 | |
| 
 | |
|     public static function Mul($op1, $op2, $scale = null)
 | |
|     {
 | |
|         if ($scale === null) {
 | |
|             $scale = Zend_Locale_Math_PhpMath::$defaultScale;
 | |
|         }
 | |
| 
 | |
|         if (empty($op1)) {
 | |
|             $op1 = 0;
 | |
|         }
 | |
|         $op1 = self::normalize($op1);
 | |
|         $op2 = self::normalize($op2);
 | |
|         $result = $op1 * $op2;
 | |
|         if (is_infinite($result)  or  is_nan($result)) {
 | |
|             require_once 'Zend/Locale/Math/Exception.php';
 | |
|             throw new Zend_Locale_Math_Exception("multiplication overflow: $op1 * $op2 != $result", $op1, $op2, $result);
 | |
|         }
 | |
| 
 | |
|         return self::round(self::normalize($result), $scale);
 | |
|     }
 | |
| 
 | |
|     public static function Div($op1, $op2, $scale = null)
 | |
|     {
 | |
|         if ($scale === null) {
 | |
|             $scale = Zend_Locale_Math_PhpMath::$defaultScale;
 | |
|         }
 | |
| 
 | |
|         if (empty($op2)) {
 | |
|             require_once 'Zend/Locale/Math/Exception.php';
 | |
|             throw new Zend_Locale_Math_Exception("can not divide by zero", $op1, $op2, null);
 | |
|         }
 | |
|         if (empty($op1)) {
 | |
|             $op1 = 0;
 | |
|         }
 | |
|         $op1 = self::normalize($op1);
 | |
|         $op2 = self::normalize($op2);
 | |
|         $result = $op1 / $op2;
 | |
|         if (is_infinite($result)  or  is_nan($result)) {
 | |
|             require_once 'Zend/Locale/Math/Exception.php';
 | |
|             throw new Zend_Locale_Math_Exception("division overflow: $op1 / $op2 != $result", $op1, $op2, $result);
 | |
|         }
 | |
| 
 | |
|         return self::round(self::normalize($result), $scale);
 | |
|     }
 | |
| 
 | |
|     public static function Sqrt($op1, $scale = null)
 | |
|     {
 | |
|         if ($scale === null) {
 | |
|             $scale = Zend_Locale_Math_PhpMath::$defaultScale;
 | |
|         }
 | |
| 
 | |
|         if (empty($op1)) {
 | |
|             $op1 = 0;
 | |
|         }
 | |
|         $op1 = self::normalize($op1);
 | |
|         $result = sqrt($op1);
 | |
|         if (is_nan($result)) {
 | |
|             return NULL;
 | |
|         }
 | |
| 
 | |
|         return self::round(self::normalize($result), $scale);
 | |
|     }
 | |
| 
 | |
|     public static function Mod($op1, $op2)
 | |
|     {
 | |
|         if (empty($op1)) {
 | |
|             $op1 = 0;
 | |
|         }
 | |
|         if (empty($op2)) {
 | |
|             return NULL;
 | |
|         }
 | |
|         $op1 = self::normalize($op1);
 | |
|         $op2 = self::normalize($op2);
 | |
|         if ((int)$op2 == 0) {
 | |
|             return NULL;
 | |
|         }
 | |
|         $result = $op1 % $op2;
 | |
|         if (is_nan($result)  or  (($op1 - $result) % $op2 != 0)) {
 | |
|             require_once 'Zend/Locale/Math/Exception.php';
 | |
|             throw new Zend_Locale_Math_Exception("modulus calculation error: $op1 % $op2 != $result", $op1, $op2, $result);
 | |
|         }
 | |
| 
 | |
|         return self::normalize($result);
 | |
|     }
 | |
| 
 | |
|     public static function Comp($op1, $op2, $scale = null)
 | |
|     {
 | |
|         if ($scale === null) {
 | |
|             $scale     = Zend_Locale_Math_PhpMath::$defaultScale;
 | |
|         }
 | |
| 
 | |
|         if (empty($op1)) {
 | |
|             $op1 = 0;
 | |
|         }
 | |
|         $op1 = self::normalize($op1);
 | |
|         $op2 = self::normalize($op2);
 | |
|         if ($scale <> 0) {
 | |
|             $op1 = self::round($op1, $scale);
 | |
|             $op2 = self::round($op2, $scale);
 | |
|         } else {
 | |
|             $op1 = ($op1 > 0) ? floor($op1) : ceil($op1);
 | |
|             $op2 = ($op2 > 0) ? floor($op2) : ceil($op2);
 | |
|         }
 | |
|         if ($op1 > $op2) {
 | |
|             return 1;
 | |
|         } else if ($op1 < $op2) {
 | |
|             return -1;
 | |
|         }
 | |
|         return 0;
 | |
|     }
 | |
| 
 | |
|     public static function Scale($scale)
 | |
|     {
 | |
|         if ($scale > 9) {
 | |
|             require_once 'Zend/Locale/Math/Exception.php';
 | |
|             throw new Zend_Locale_Math_Exception("can not scale to precision $scale", $scale, null, null);
 | |
|         }
 | |
|         self::$defaultScale     = $scale;
 | |
|         self::$defaultPrecision = pow(10, -$scale);
 | |
|         return true;
 | |
|     }
 | |
| }
 | |
| 
 | |
| Zend_Locale_Math_PhpMath::disable(); // disable use of bcmath functions
 |