[ZF-10089] Zend_Log
[zend/radio.git] / library / Zend / Locale / Math / PhpMath.php
blob0e1c63bfda918725a77215beef3ca660443db630
1 <?php
2 /**
3 * Zend Framework
5 * LICENSE
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.
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$
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.
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
34 class Zend_Locale_Math_PhpMath extends Zend_Locale_Math
36 public static function disable()
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');
49 self::$defaultScale = 0;
50 self::$defaultPrecision = 1;
53 public static $defaultScale;
54 public static $defaultPrecision;
57 public static function Add($op1, $op2, $scale = null)
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);
66 if (empty($op1)) {
67 $op1 = 0;
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);
77 return self::round(self::normalize($result), $scale);
80 public static function Sub($op1, $op2, $scale = null)
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);
89 if (empty($op1)) {
90 $op1 = 0;
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);
100 return self::round(self::normalize($result), $scale);
103 public static function Pow($op1, $op2, $scale = null)
105 if ($scale === null) {
106 $scale = Zend_Locale_Math_PhpMath::$defaultScale;
109 $op1 = self::normalize($op1);
110 $op2 = self::normalize($op2);
112 // BCMath extension doesn't use decimal part of the power
113 // Provide the same behavior
114 $op2 = ($op2 > 0) ? floor($op2) : ceil($op2);
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);
122 return self::round(self::normalize($result), $scale);
125 public static function Mul($op1, $op2, $scale = null)
127 if ($scale === null) {
128 $scale = Zend_Locale_Math_PhpMath::$defaultScale;
131 if (empty($op1)) {
132 $op1 = 0;
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);
142 return self::round(self::normalize($result), $scale);
145 public static function Div($op1, $op2, $scale = null)
147 if ($scale === null) {
148 $scale = Zend_Locale_Math_PhpMath::$defaultScale;
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);
155 if (empty($op1)) {
156 $op1 = 0;
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);
166 return self::round(self::normalize($result), $scale);
169 public static function Sqrt($op1, $scale = null)
171 if ($scale === null) {
172 $scale = Zend_Locale_Math_PhpMath::$defaultScale;
175 if (empty($op1)) {
176 $op1 = 0;
178 $op1 = self::normalize($op1);
179 $result = sqrt($op1);
180 if (is_nan($result)) {
181 return NULL;
184 return self::round(self::normalize($result), $scale);
187 public static function Mod($op1, $op2)
189 if (empty($op1)) {
190 $op1 = 0;
192 if (empty($op2)) {
193 return NULL;
195 $op1 = self::normalize($op1);
196 $op2 = self::normalize($op2);
197 if ((int)$op2 == 0) {
198 return NULL;
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);
206 return self::normalize($result);
209 public static function Comp($op1, $op2, $scale = null)
211 if ($scale === null) {
212 $scale = Zend_Locale_Math_PhpMath::$defaultScale;
215 if (empty($op1)) {
216 $op1 = 0;
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);
227 if ($op1 > $op2) {
228 return 1;
229 } else if ($op1 < $op2) {
230 return -1;
232 return 0;
235 public static function Scale($scale)
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);
241 self::$defaultScale = $scale;
242 self::$defaultPrecision = pow(10, -$scale);
243 return true;
247 Zend_Locale_Math_PhpMath::disable(); // disable use of bcmath functions