1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 5 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Author: Andi Gutmans <andi@zend.com> |
16 : +----------------------------------------------------------------------+
17 : */
18 :
19 : /* $Id: bcmath.c 272374 2008-12-31 11:17:49Z sebastian $ */
20 :
21 : #ifdef HAVE_CONFIG_H
22 : #include "config.h"
23 : #endif
24 :
25 : #include "php.h"
26 :
27 : #if HAVE_BCMATH
28 :
29 : #include "php_ini.h"
30 : #include "ext/standard/info.h"
31 : #include "php_bcmath.h"
32 : #include "libbcmath/src/bcmath.h"
33 :
34 : ZEND_DECLARE_MODULE_GLOBALS(bcmath)
35 : static PHP_GINIT_FUNCTION(bcmath);
36 : static PHP_GSHUTDOWN_FUNCTION(bcmath);
37 :
38 : /* {{{ arginfo */
39 : static
40 : ZEND_BEGIN_ARG_INFO_EX(arginfo_bcadd, 0, 0, 2)
41 : ZEND_ARG_INFO(0, left_operand)
42 : ZEND_ARG_INFO(0, right_operand)
43 : ZEND_ARG_INFO(0, scale)
44 : ZEND_END_ARG_INFO()
45 :
46 : static
47 : ZEND_BEGIN_ARG_INFO_EX(arginfo_bcsub, 0, 0, 2)
48 : ZEND_ARG_INFO(0, left_operand)
49 : ZEND_ARG_INFO(0, right_operand)
50 : ZEND_ARG_INFO(0, scale)
51 : ZEND_END_ARG_INFO()
52 :
53 : static
54 : ZEND_BEGIN_ARG_INFO_EX(arginfo_bcmul, 0, 0, 2)
55 : ZEND_ARG_INFO(0, left_operand)
56 : ZEND_ARG_INFO(0, right_operand)
57 : ZEND_ARG_INFO(0, scale)
58 : ZEND_END_ARG_INFO()
59 :
60 : static
61 : ZEND_BEGIN_ARG_INFO_EX(arginfo_bcdiv, 0, 0, 2)
62 : ZEND_ARG_INFO(0, left_operand)
63 : ZEND_ARG_INFO(0, right_operand)
64 : ZEND_ARG_INFO(0, scale)
65 : ZEND_END_ARG_INFO()
66 :
67 : static
68 : ZEND_BEGIN_ARG_INFO(arginfo_bcmod, 0)
69 : ZEND_ARG_INFO(0, left_operand)
70 : ZEND_ARG_INFO(0, right_operand)
71 : ZEND_END_ARG_INFO()
72 :
73 : static
74 : ZEND_BEGIN_ARG_INFO_EX(arginfo_bcpowmod, 0, 0, 3)
75 : ZEND_ARG_INFO(0, x)
76 : ZEND_ARG_INFO(0, y)
77 : ZEND_ARG_INFO(0, mod)
78 : ZEND_ARG_INFO(0, scale)
79 : ZEND_END_ARG_INFO()
80 :
81 : static
82 : ZEND_BEGIN_ARG_INFO_EX(arginfo_bcpow, 0, 0, 2)
83 : ZEND_ARG_INFO(0, x)
84 : ZEND_ARG_INFO(0, y)
85 : ZEND_ARG_INFO(0, scale)
86 : ZEND_END_ARG_INFO()
87 :
88 : static
89 : ZEND_BEGIN_ARG_INFO_EX(arginfo_bcsqrt, 0, 0, 1)
90 : ZEND_ARG_INFO(0, operand)
91 : ZEND_ARG_INFO(0, scale)
92 : ZEND_END_ARG_INFO()
93 :
94 : static
95 : ZEND_BEGIN_ARG_INFO_EX(arginfo_bccomp, 0, 0, 2)
96 : ZEND_ARG_INFO(0, left_operand)
97 : ZEND_ARG_INFO(0, right_operand)
98 : ZEND_ARG_INFO(0, scale)
99 : ZEND_END_ARG_INFO()
100 :
101 : static
102 : ZEND_BEGIN_ARG_INFO(arginfo_bcscale, 0)
103 : ZEND_ARG_INFO(0, scale)
104 : ZEND_END_ARG_INFO()
105 :
106 : /* }}} */
107 :
108 : zend_function_entry bcmath_functions[] = {
109 : PHP_FE(bcadd, arginfo_bcadd)
110 : PHP_FE(bcsub, arginfo_bcsub)
111 : PHP_FE(bcmul, arginfo_bcmul)
112 : PHP_FE(bcdiv, arginfo_bcdiv)
113 : PHP_FE(bcmod, arginfo_bcmod)
114 : PHP_FE(bcpow, arginfo_bcpow)
115 : PHP_FE(bcsqrt, arginfo_bcsqrt)
116 : PHP_FE(bcscale, arginfo_bcscale)
117 : PHP_FE(bccomp, arginfo_bccomp)
118 : PHP_FE(bcpowmod, arginfo_bcpowmod)
119 : {NULL, NULL, NULL}
120 : };
121 :
122 : zend_module_entry bcmath_module_entry = {
123 : STANDARD_MODULE_HEADER,
124 : "bcmath",
125 : bcmath_functions,
126 : PHP_MINIT(bcmath),
127 : PHP_MSHUTDOWN(bcmath),
128 : NULL,
129 : NULL,
130 : PHP_MINFO(bcmath),
131 : NO_VERSION_YET,
132 : PHP_MODULE_GLOBALS(bcmath),
133 : PHP_GINIT(bcmath),
134 : PHP_GSHUTDOWN(bcmath),
135 : NULL,
136 : STANDARD_MODULE_PROPERTIES_EX
137 : };
138 :
139 : #ifdef COMPILE_DL_BCMATH
140 : ZEND_GET_MODULE(bcmath)
141 : #endif
142 :
143 : /* {{{ PHP_INI */
144 : PHP_INI_BEGIN()
145 : STD_PHP_INI_ENTRY("bcmath.scale", "0", PHP_INI_ALL, OnUpdateLongGEZero, bc_precision, zend_bcmath_globals, bcmath_globals)
146 : PHP_INI_END()
147 : /* }}} */
148 :
149 : /* {{{ PHP_GINIT_FUNCTION
150 : */
151 : static PHP_GINIT_FUNCTION(bcmath)
152 13565 : {
153 13565 : bcmath_globals->bc_precision = 0;
154 13565 : bc_init_numbers(TSRMLS_C);
155 13565 : }
156 : /* }}} */
157 :
158 : /* {{{ PHP_GSHUTDOWN_FUNCTION
159 : */
160 : static PHP_GSHUTDOWN_FUNCTION(bcmath)
161 13597 : {
162 13597 : _bc_free_num_ex(&bcmath_globals->_zero_, 1);
163 13597 : _bc_free_num_ex(&bcmath_globals->_one_, 1);
164 13597 : _bc_free_num_ex(&bcmath_globals->_two_, 1);
165 13597 : }
166 : /* }}} */
167 :
168 : /* {{{ PHP_MINIT_FUNCTION
169 : */
170 : PHP_MINIT_FUNCTION(bcmath)
171 13565 : {
172 13565 : REGISTER_INI_ENTRIES();
173 :
174 13565 : return SUCCESS;
175 : }
176 : /* }}} */
177 :
178 : /* {{{ PHP_MSHUTDOWN_FUNCTION
179 : */
180 : PHP_MSHUTDOWN_FUNCTION(bcmath)
181 13597 : {
182 13597 : UNREGISTER_INI_ENTRIES();
183 :
184 13597 : return SUCCESS;
185 : }
186 : /* }}} */
187 :
188 : /* {{{ PHP_MINFO_FUNCTION
189 : */
190 : PHP_MINFO_FUNCTION(bcmath)
191 6 : {
192 6 : php_info_print_table_start();
193 6 : php_info_print_table_row(2, "BCMath support", "enabled");
194 6 : php_info_print_table_end();
195 6 : }
196 : /* }}} */
197 :
198 : /* {{{ php_str2num
199 : Convert to bc_num detecting scale */
200 : static void php_str2num(bc_num *num, char *str TSRMLS_DC)
201 47 : {
202 : char *p;
203 :
204 47 : if (!(p = strchr(str, '.'))) {
205 44 : bc_str2num(num, str, 0 TSRMLS_CC);
206 44 : return;
207 : }
208 :
209 3 : bc_str2num(num, str, strlen(p+1) TSRMLS_CC);
210 : }
211 : /* }}} */
212 :
213 : /* {{{ proto string bcadd(string left_operand, string right_operand [, int scale])
214 : Returns the sum of two arbitrary precision numbers */
215 : PHP_FUNCTION(bcadd)
216 7 : {
217 : zval **left, **right, **scale_param;
218 : bc_num first, second, result;
219 7 : int scale = BCG(bc_precision);
220 :
221 7 : switch (ZEND_NUM_ARGS()) {
222 : case 2:
223 5 : if (zend_get_parameters_ex(2, &left, &right) == FAILURE) {
224 0 : WRONG_PARAM_COUNT;
225 : }
226 5 : break;
227 : case 3:
228 2 : if (zend_get_parameters_ex(3, &left, &right, &scale_param) == FAILURE) {
229 0 : WRONG_PARAM_COUNT;
230 : }
231 2 : convert_to_long_ex(scale_param);
232 2 : scale = (int) ((int)Z_LVAL_PP(scale_param) < 0) ? 0 : Z_LVAL_PP(scale_param);
233 2 : break;
234 : default:
235 0 : WRONG_PARAM_COUNT;
236 : break;
237 : }
238 7 : convert_to_string_ex(left);
239 7 : convert_to_string_ex(right);
240 7 : bc_init_num(&first TSRMLS_CC);
241 7 : bc_init_num(&second TSRMLS_CC);
242 7 : bc_init_num(&result TSRMLS_CC);
243 7 : php_str2num(&first, Z_STRVAL_PP(left) TSRMLS_CC);
244 7 : php_str2num(&second, Z_STRVAL_PP(right) TSRMLS_CC);
245 7 : bc_add (first, second, &result, scale);
246 7 : if (result->n_scale > scale) {
247 0 : result->n_scale = scale;
248 : }
249 7 : Z_STRVAL_P(return_value) = bc_num2str(result);
250 7 : Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
251 7 : Z_TYPE_P(return_value) = IS_STRING;
252 7 : bc_free_num(&first);
253 7 : bc_free_num(&second);
254 7 : bc_free_num(&result);
255 7 : return;
256 : }
257 : /* }}} */
258 :
259 : /* {{{ proto string bcsub(string left_operand, string right_operand [, int scale])
260 : Returns the difference between two arbitrary precision numbers */
261 : PHP_FUNCTION(bcsub)
262 3 : {
263 : zval **left, **right, **scale_param;
264 : bc_num first, second, result;
265 3 : int scale = BCG(bc_precision);
266 :
267 3 : switch (ZEND_NUM_ARGS()) {
268 : case 2:
269 1 : if (zend_get_parameters_ex(2, &left, &right) == FAILURE) {
270 0 : WRONG_PARAM_COUNT;
271 : }
272 1 : break;
273 : case 3:
274 2 : if (zend_get_parameters_ex(3, &left, &right, &scale_param) == FAILURE) {
275 0 : WRONG_PARAM_COUNT;
276 : }
277 2 : convert_to_long_ex(scale_param);
278 2 : scale = (int) ((int)Z_LVAL_PP(scale_param) < 0) ? 0 : Z_LVAL_PP(scale_param);
279 2 : break;
280 : default:
281 0 : WRONG_PARAM_COUNT;
282 : break;
283 : }
284 3 : convert_to_string_ex(left);
285 3 : convert_to_string_ex(right);
286 3 : bc_init_num(&first TSRMLS_CC);
287 3 : bc_init_num(&second TSRMLS_CC);
288 3 : bc_init_num(&result TSRMLS_CC);
289 3 : php_str2num(&first, Z_STRVAL_PP(left) TSRMLS_CC);
290 3 : php_str2num(&second, Z_STRVAL_PP(right) TSRMLS_CC);
291 3 : bc_sub (first, second, &result, scale);
292 3 : if (result->n_scale > scale) {
293 0 : result->n_scale = scale;
294 : }
295 3 : Z_STRVAL_P(return_value) = bc_num2str(result);
296 3 : Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
297 3 : Z_TYPE_P(return_value) = IS_STRING;
298 3 : bc_free_num(&first);
299 3 : bc_free_num(&second);
300 3 : bc_free_num(&result);
301 3 : return;
302 : }
303 : /* }}} */
304 :
305 : /* {{{ proto string bcmul(string left_operand, string right_operand [, int scale])
306 : Returns the multiplication of two arbitrary precision numbers */
307 : PHP_FUNCTION(bcmul)
308 4 : {
309 : zval **left, **right, **scale_param;
310 : bc_num first, second, result;
311 4 : int scale = BCG(bc_precision);
312 :
313 4 : switch (ZEND_NUM_ARGS()) {
314 : case 2:
315 3 : if (zend_get_parameters_ex(2, &left, &right) == FAILURE) {
316 0 : WRONG_PARAM_COUNT;
317 : }
318 3 : break;
319 : case 3:
320 1 : if (zend_get_parameters_ex(3, &left, &right, &scale_param) == FAILURE) {
321 0 : WRONG_PARAM_COUNT;
322 : }
323 1 : convert_to_long_ex(scale_param);
324 1 : scale = (int) ((int)Z_LVAL_PP(scale_param) < 0) ? 0 : Z_LVAL_PP(scale_param);
325 1 : break;
326 : default:
327 0 : WRONG_PARAM_COUNT;
328 : break;
329 : }
330 4 : convert_to_string_ex(left);
331 4 : convert_to_string_ex(right);
332 4 : bc_init_num(&first TSRMLS_CC);
333 4 : bc_init_num(&second TSRMLS_CC);
334 4 : bc_init_num(&result TSRMLS_CC);
335 4 : php_str2num(&first, Z_STRVAL_PP(left) TSRMLS_CC);
336 4 : php_str2num(&second, Z_STRVAL_PP(right) TSRMLS_CC);
337 4 : bc_multiply (first, second, &result, scale TSRMLS_CC);
338 4 : if (result->n_scale > scale) {
339 0 : result->n_scale = scale;
340 : }
341 4 : Z_STRVAL_P(return_value) = bc_num2str(result);
342 4 : Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
343 4 : Z_TYPE_P(return_value) = IS_STRING;
344 4 : bc_free_num(&first);
345 4 : bc_free_num(&second);
346 4 : bc_free_num(&result);
347 4 : return;
348 : }
349 : /* }}} */
350 :
351 : /* {{{ proto string bcdiv(string left_operand, string right_operand [, int scale])
352 : Returns the quotient of two arbitrary precision numbers (division) */
353 : PHP_FUNCTION(bcdiv)
354 6 : {
355 : zval **left, **right, **scale_param;
356 : bc_num first, second, result;
357 6 : int scale = BCG(bc_precision);
358 :
359 6 : switch (ZEND_NUM_ARGS()) {
360 : case 2:
361 2 : if (zend_get_parameters_ex(2, &left, &right) == FAILURE) {
362 0 : WRONG_PARAM_COUNT;
363 : }
364 2 : break;
365 : case 3:
366 3 : if (zend_get_parameters_ex(3, &left, &right, &scale_param) == FAILURE) {
367 0 : WRONG_PARAM_COUNT;
368 : }
369 3 : convert_to_long_ex(scale_param);
370 3 : scale = (int) ((int)Z_LVAL_PP(scale_param) < 0) ? 0 : Z_LVAL_PP(scale_param);
371 3 : break;
372 : default:
373 1 : WRONG_PARAM_COUNT;
374 : break;
375 : }
376 5 : convert_to_string_ex(left);
377 5 : convert_to_string_ex(right);
378 5 : bc_init_num(&first TSRMLS_CC);
379 5 : bc_init_num(&second TSRMLS_CC);
380 5 : bc_init_num(&result TSRMLS_CC);
381 5 : php_str2num(&first, Z_STRVAL_PP(left) TSRMLS_CC);
382 5 : php_str2num(&second, Z_STRVAL_PP(right) TSRMLS_CC);
383 5 : switch (bc_divide(first, second, &result, scale TSRMLS_CC)) {
384 : case 0: /* OK */
385 4 : if (result->n_scale > scale) {
386 0 : result->n_scale = scale;
387 : }
388 4 : Z_STRVAL_P(return_value) = bc_num2str(result);
389 4 : Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
390 4 : Z_TYPE_P(return_value) = IS_STRING;
391 4 : break;
392 : case -1: /* division by zero */
393 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Division by zero");
394 : break;
395 : }
396 5 : bc_free_num(&first);
397 5 : bc_free_num(&second);
398 5 : bc_free_num(&result);
399 5 : return;
400 : }
401 : /* }}} */
402 :
403 : /* {{{ proto string bcmod(string left_operand, string right_operand)
404 : Returns the modulus of the two arbitrary precision operands */
405 : PHP_FUNCTION(bcmod)
406 4 : {
407 : zval **left, **right;
408 : bc_num first, second, result;
409 :
410 4 : switch (ZEND_NUM_ARGS()) {
411 : case 2:
412 3 : if (zend_get_parameters_ex(2, &left, &right) == FAILURE) {
413 0 : WRONG_PARAM_COUNT;
414 : }
415 : break;
416 : default:
417 1 : WRONG_PARAM_COUNT;
418 : break;
419 : }
420 3 : convert_to_string_ex(left);
421 3 : convert_to_string_ex(right);
422 3 : bc_init_num(&first TSRMLS_CC);
423 3 : bc_init_num(&second TSRMLS_CC);
424 3 : bc_init_num(&result TSRMLS_CC);
425 3 : bc_str2num(&first, Z_STRVAL_PP(left), 0 TSRMLS_CC);
426 3 : bc_str2num(&second, Z_STRVAL_PP(right), 0 TSRMLS_CC);
427 3 : switch (bc_modulo(first, second, &result, 0 TSRMLS_CC)) {
428 : case 0:
429 3 : Z_STRVAL_P(return_value) = bc_num2str(result);
430 3 : Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
431 3 : Z_TYPE_P(return_value) = IS_STRING;
432 3 : break;
433 : case -1:
434 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Division by zero");
435 : break;
436 : }
437 3 : bc_free_num(&first);
438 3 : bc_free_num(&second);
439 3 : bc_free_num(&result);
440 3 : return;
441 : }
442 : /* }}} */
443 :
444 : /* {{{ proto string bcpowmod(string x, string y, string mod [, int scale])
445 : Returns the value of an arbitrary precision number raised to the power of another reduced by a modulous */
446 : PHP_FUNCTION(bcpowmod)
447 3 : {
448 : char *left, *right, *modulous;
449 : int left_len, right_len, modulous_len;
450 : bc_num first, second, mod, result;
451 3 : long scale = BCG(bc_precision);
452 : int scale_int;
453 :
454 3 : if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|l", &left, &left_len, &right, &right_len, &modulous, &modulous_len, &scale) == FAILURE) {
455 3 : return;
456 : }
457 :
458 0 : bc_init_num(&first TSRMLS_CC);
459 0 : bc_init_num(&second TSRMLS_CC);
460 0 : bc_init_num(&mod TSRMLS_CC);
461 0 : bc_init_num(&result TSRMLS_CC);
462 0 : php_str2num(&first, left TSRMLS_CC);
463 0 : php_str2num(&second, right TSRMLS_CC);
464 0 : php_str2num(&mod, modulous TSRMLS_CC);
465 :
466 0 : scale_int = (int) ((int)scale < 0) ? 0 : scale;
467 :
468 0 : if (bc_raisemod(first, second, mod, &result, scale_int TSRMLS_CC) != -1) {
469 0 : if (result->n_scale > scale) {
470 0 : result->n_scale = scale;
471 : }
472 0 : Z_STRVAL_P(return_value) = bc_num2str(result);
473 0 : Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
474 0 : Z_TYPE_P(return_value) = IS_STRING;
475 : } else {
476 0 : RETVAL_FALSE;
477 : }
478 :
479 0 : bc_free_num(&first);
480 0 : bc_free_num(&second);
481 0 : bc_free_num(&mod);
482 0 : bc_free_num(&result);
483 0 : return;
484 : }
485 : /* }}} */
486 :
487 : /* {{{ proto string bcpow(string x, string y [, int scale])
488 : Returns the value of an arbitrary precision number raised to the power of another */
489 : PHP_FUNCTION(bcpow)
490 3 : {
491 : zval **left, **right, **scale_param;
492 : bc_num first, second, result;
493 3 : int scale = BCG(bc_precision);
494 :
495 3 : switch (ZEND_NUM_ARGS()) {
496 : case 2:
497 2 : if (zend_get_parameters_ex(2, &left, &right) == FAILURE) {
498 0 : WRONG_PARAM_COUNT;
499 : }
500 2 : break;
501 : case 3:
502 1 : if (zend_get_parameters_ex(3, &left, &right, &scale_param) == FAILURE) {
503 0 : WRONG_PARAM_COUNT;
504 : }
505 1 : convert_to_long_ex(scale_param);
506 1 : scale = (int) ((int)Z_LVAL_PP(scale_param) < 0) ? 0 : Z_LVAL_PP(scale_param);
507 1 : break;
508 : default:
509 0 : WRONG_PARAM_COUNT;
510 : break;
511 : }
512 3 : convert_to_string_ex(left);
513 3 : convert_to_string_ex(right);
514 3 : bc_init_num(&first TSRMLS_CC);
515 3 : bc_init_num(&second TSRMLS_CC);
516 3 : bc_init_num(&result TSRMLS_CC);
517 3 : php_str2num(&first, Z_STRVAL_PP(left) TSRMLS_CC);
518 3 : php_str2num(&second, Z_STRVAL_PP(right) TSRMLS_CC);
519 3 : bc_raise (first, second, &result, scale TSRMLS_CC);
520 3 : if (result->n_scale > scale) {
521 0 : result->n_scale = scale;
522 : }
523 3 : Z_STRVAL_P(return_value) = bc_num2str(result);
524 3 : Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
525 3 : Z_TYPE_P(return_value) = IS_STRING;
526 3 : bc_free_num(&first);
527 3 : bc_free_num(&second);
528 3 : bc_free_num(&result);
529 3 : return;
530 : }
531 : /* }}} */
532 :
533 : /* {{{ proto string bcsqrt(string operand [, int scale])
534 : Returns the square root of an arbitray precision number */
535 : PHP_FUNCTION(bcsqrt)
536 3 : {
537 : zval **left, **scale_param;
538 : bc_num result;
539 3 : int scale = BCG(bc_precision);
540 :
541 3 : switch (ZEND_NUM_ARGS()) {
542 : case 1:
543 2 : if (zend_get_parameters_ex(1, &left) == FAILURE) {
544 0 : WRONG_PARAM_COUNT;
545 : }
546 2 : break;
547 : case 2:
548 1 : if (zend_get_parameters_ex(2, &left, &scale_param) == FAILURE) {
549 0 : WRONG_PARAM_COUNT;
550 : }
551 1 : convert_to_long_ex(scale_param);
552 1 : scale = (int) ((int)Z_LVAL_PP(scale_param) < 0) ? 0 : Z_LVAL_PP(scale_param);
553 1 : break;
554 : default:
555 0 : WRONG_PARAM_COUNT;
556 : break;
557 : }
558 3 : convert_to_string_ex(left);
559 3 : bc_init_num(&result TSRMLS_CC);
560 3 : php_str2num(&result, Z_STRVAL_PP(left) TSRMLS_CC);
561 3 : if (bc_sqrt (&result, scale TSRMLS_CC) != 0) {
562 2 : if (result->n_scale > scale) {
563 0 : result->n_scale = scale;
564 : }
565 2 : Z_STRVAL_P(return_value) = bc_num2str(result);
566 2 : Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
567 2 : Z_TYPE_P(return_value) = IS_STRING;
568 : } else {
569 1 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "Square root of negative number");
570 : }
571 3 : bc_free_num(&result);
572 3 : return;
573 : }
574 : /* }}} */
575 :
576 : /* {{{ proto int bccomp(string left_operand, string right_operand [, int scale])
577 : Compares two arbitrary precision numbers */
578 : PHP_FUNCTION(bccomp)
579 4 : {
580 : zval **left, **right, **scale_param;
581 : bc_num first, second;
582 4 : int scale = BCG(bc_precision);
583 :
584 4 : switch (ZEND_NUM_ARGS()) {
585 : case 2:
586 2 : if (zend_get_parameters_ex(2, &left, &right) == FAILURE) {
587 0 : WRONG_PARAM_COUNT;
588 : }
589 2 : break;
590 : case 3:
591 2 : if (zend_get_parameters_ex(3, &left, &right, &scale_param) == FAILURE) {
592 0 : WRONG_PARAM_COUNT;
593 : }
594 2 : convert_to_long_ex(scale_param);
595 2 : scale = (int) ((int)Z_LVAL_PP(scale_param) < 0) ? 0 : Z_LVAL_PP(scale_param);
596 2 : break;
597 : default:
598 0 : WRONG_PARAM_COUNT;
599 : break;
600 : }
601 :
602 4 : convert_to_string_ex(left);
603 4 : convert_to_string_ex(right);
604 4 : bc_init_num(&first TSRMLS_CC);
605 4 : bc_init_num(&second TSRMLS_CC);
606 :
607 4 : bc_str2num(&first, Z_STRVAL_PP(left), scale TSRMLS_CC);
608 4 : bc_str2num(&second, Z_STRVAL_PP(right), scale TSRMLS_CC);
609 4 : Z_LVAL_P(return_value) = bc_compare(first, second);
610 4 : Z_TYPE_P(return_value) = IS_LONG;
611 :
612 4 : bc_free_num(&first);
613 4 : bc_free_num(&second);
614 4 : return;
615 : }
616 : /* }}} */
617 :
618 : /* {{{ proto bool bcscale(int scale)
619 : Sets default scale parameter for all bc math functions */
620 : PHP_FUNCTION(bcscale)
621 3 : {
622 : zval **new_scale;
623 :
624 3 : if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &new_scale) == FAILURE) {
625 0 : WRONG_PARAM_COUNT;
626 : }
627 :
628 3 : convert_to_long_ex(new_scale);
629 3 : BCG(bc_precision) = (Z_LVAL_PP(new_scale) < 0) ? 0 : Z_LVAL_PP(new_scale);
630 :
631 3 : RETURN_TRUE;
632 : }
633 : /* }}} */
634 :
635 :
636 : #endif
637 :
638 : /*
639 : * Local variables:
640 : * tab-width: 4
641 : * c-basic-offset: 4
642 : * End:
643 : * vim600: sw=4 ts=4 fdm=marker
644 : * vim<600: sw=4 ts=4
645 : */
|