File indexing completed on 2024-12-22 05:36:49
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Locale 0017 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0018 * @license http://framework.zend.com/license/new-bsd New BSD License 0019 * @version $Id$ 0020 */ 0021 0022 0023 /** 0024 * Utility class for proxying math function to bcmath functions, if present, 0025 * otherwise to PHP builtin math operators, with limited detection of overflow conditions. 0026 * Sampling of PHP environments and platforms suggests that at least 80% to 90% support bcmath. 0027 * This file should only be loaded for the 10% to 20% lacking access to the bcmath extension. 0028 * 0029 * @category Zend 0030 * @package Zend_Locale 0031 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0032 * @license http://framework.zend.com/license/new-bsd New BSD License 0033 */ 0034 class Zend_Locale_Math_PhpMath extends Zend_Locale_Math 0035 { 0036 public static function disable() 0037 { 0038 self::$_bcmathDisabled = true; 0039 self::$add = array('Zend_Locale_Math_PhpMath', 'Add'); 0040 self::$sub = array('Zend_Locale_Math_PhpMath', 'Sub'); 0041 self::$pow = array('Zend_Locale_Math_PhpMath', 'Pow'); 0042 self::$mul = array('Zend_Locale_Math_PhpMath', 'Mul'); 0043 self::$div = array('Zend_Locale_Math_PhpMath', 'Div'); 0044 self::$comp = array('Zend_Locale_Math_PhpMath', 'Comp'); 0045 self::$sqrt = array('Zend_Locale_Math_PhpMath', 'Sqrt'); 0046 self::$mod = array('Zend_Locale_Math_PhpMath', 'Mod'); 0047 self::$scale = array('Zend_Locale_Math_PhpMath', 'Scale'); 0048 0049 self::$defaultScale = 0; 0050 self::$defaultPrecision = 1; 0051 } 0052 0053 public static $defaultScale; 0054 public static $defaultPrecision; 0055 0056 0057 public static function Add($op1, $op2, $scale = null) 0058 { 0059 if ($scale === null) { 0060 $scale = Zend_Locale_Math_PhpMath::$defaultScale; 0061 $precision = Zend_Locale_Math_PhpMath::$defaultPrecision; 0062 } else { 0063 $precision = pow(10, -$scale); 0064 } 0065 0066 if (empty($op1)) { 0067 $op1 = 0; 0068 } 0069 $op1 = self::normalize($op1); 0070 $op2 = self::normalize($op2); 0071 $result = $op1 + $op2; 0072 if (is_infinite($result) or (abs($result - $op2 - $op1) > $precision)) { 0073 // require_once 'Zend/Locale/Math/Exception.php'; 0074 throw new Zend_Locale_Math_Exception("addition overflow: $op1 + $op2 != $result", $op1, $op2, $result); 0075 } 0076 0077 return self::round(self::normalize($result), $scale); 0078 } 0079 0080 public static function Sub($op1, $op2, $scale = null) 0081 { 0082 if ($scale === null) { 0083 $scale = Zend_Locale_Math_PhpMath::$defaultScale; 0084 $precision = Zend_Locale_Math_PhpMath::$defaultPrecision; 0085 } else { 0086 $precision = pow(10, -$scale); 0087 } 0088 0089 if (empty($op1)) { 0090 $op1 = 0; 0091 } 0092 $op1 = self::normalize($op1); 0093 $op2 = self::normalize($op2); 0094 $result = $op1 - $op2; 0095 if (is_infinite($result) or (abs($result + $op2 - $op1) > $precision)) { 0096 // require_once 'Zend/Locale/Math/Exception.php'; 0097 throw new Zend_Locale_Math_Exception("subtraction overflow: $op1 - $op2 != $result", $op1, $op2, $result); 0098 } 0099 0100 return self::round(self::normalize($result), $scale); 0101 } 0102 0103 public static function Pow($op1, $op2, $scale = null) 0104 { 0105 if ($scale === null) { 0106 $scale = Zend_Locale_Math_PhpMath::$defaultScale; 0107 } 0108 0109 $op1 = self::normalize($op1); 0110 $op2 = self::normalize($op2); 0111 0112 // BCMath extension doesn't use decimal part of the power 0113 // Provide the same behavior 0114 $op2 = ($op2 > 0) ? floor($op2) : ceil($op2); 0115 0116 $result = pow($op1, $op2); 0117 if (is_infinite($result) or is_nan($result)) { 0118 // require_once 'Zend/Locale/Math/Exception.php'; 0119 throw new Zend_Locale_Math_Exception("power overflow: $op1 ^ $op2", $op1, $op2, $result); 0120 } 0121 0122 return self::round(self::normalize($result), $scale); 0123 } 0124 0125 public static function Mul($op1, $op2, $scale = null) 0126 { 0127 if ($scale === null) { 0128 $scale = Zend_Locale_Math_PhpMath::$defaultScale; 0129 } 0130 0131 if (empty($op1)) { 0132 $op1 = 0; 0133 } 0134 $op1 = self::normalize($op1); 0135 $op2 = self::normalize($op2); 0136 $result = $op1 * $op2; 0137 if (is_infinite($result) or is_nan($result)) { 0138 // require_once 'Zend/Locale/Math/Exception.php'; 0139 throw new Zend_Locale_Math_Exception("multiplication overflow: $op1 * $op2 != $result", $op1, $op2, $result); 0140 } 0141 0142 return self::round(self::normalize($result), $scale); 0143 } 0144 0145 public static function Div($op1, $op2, $scale = null) 0146 { 0147 if ($scale === null) { 0148 $scale = Zend_Locale_Math_PhpMath::$defaultScale; 0149 } 0150 0151 if (empty($op2)) { 0152 // require_once 'Zend/Locale/Math/Exception.php'; 0153 throw new Zend_Locale_Math_Exception("can not divide by zero", $op1, $op2, null); 0154 } 0155 if (empty($op1)) { 0156 $op1 = 0; 0157 } 0158 $op1 = self::normalize($op1); 0159 $op2 = self::normalize($op2); 0160 $result = $op1 / $op2; 0161 if (is_infinite($result) or is_nan($result)) { 0162 // require_once 'Zend/Locale/Math/Exception.php'; 0163 throw new Zend_Locale_Math_Exception("division overflow: $op1 / $op2 != $result", $op1, $op2, $result); 0164 } 0165 0166 return self::round(self::normalize($result), $scale); 0167 } 0168 0169 public static function Sqrt($op1, $scale = null) 0170 { 0171 if ($scale === null) { 0172 $scale = Zend_Locale_Math_PhpMath::$defaultScale; 0173 } 0174 0175 if (empty($op1)) { 0176 $op1 = 0; 0177 } 0178 $op1 = self::normalize($op1); 0179 $result = sqrt($op1); 0180 if (is_nan($result)) { 0181 return NULL; 0182 } 0183 0184 return self::round(self::normalize($result), $scale); 0185 } 0186 0187 public static function Mod($op1, $op2) 0188 { 0189 if (empty($op1)) { 0190 $op1 = 0; 0191 } 0192 if (empty($op2)) { 0193 return NULL; 0194 } 0195 $op1 = self::normalize($op1); 0196 $op2 = self::normalize($op2); 0197 if ((int)$op2 == 0) { 0198 return NULL; 0199 } 0200 $result = $op1 % $op2; 0201 if (is_nan($result) or (($op1 - $result) % $op2 != 0)) { 0202 // require_once 'Zend/Locale/Math/Exception.php'; 0203 throw new Zend_Locale_Math_Exception("modulus calculation error: $op1 % $op2 != $result", $op1, $op2, $result); 0204 } 0205 0206 return self::normalize($result); 0207 } 0208 0209 public static function Comp($op1, $op2, $scale = null) 0210 { 0211 if ($scale === null) { 0212 $scale = Zend_Locale_Math_PhpMath::$defaultScale; 0213 } 0214 0215 if (empty($op1)) { 0216 $op1 = 0; 0217 } 0218 $op1 = self::normalize($op1); 0219 $op2 = self::normalize($op2); 0220 if ($scale <> 0) { 0221 $op1 = self::round($op1, $scale); 0222 $op2 = self::round($op2, $scale); 0223 } else { 0224 $op1 = ($op1 > 0) ? floor($op1) : ceil($op1); 0225 $op2 = ($op2 > 0) ? floor($op2) : ceil($op2); 0226 } 0227 if ($op1 > $op2) { 0228 return 1; 0229 } else if ($op1 < $op2) { 0230 return -1; 0231 } 0232 return 0; 0233 } 0234 0235 public static function Scale($scale) 0236 { 0237 if ($scale > 9) { 0238 // require_once 'Zend/Locale/Math/Exception.php'; 0239 throw new Zend_Locale_Math_Exception("can not scale to precision $scale", $scale, null, null); 0240 } 0241 self::$defaultScale = $scale; 0242 self::$defaultPrecision = pow(10, -$scale); 0243 return true; 0244 } 0245 } 0246 0247 Zend_Locale_Math_PhpMath::disable(); // disable use of bcmath functions