Annotation of embedaddon/php/ext/bcmath/bcmath.c, revision 1.1.1.2
1.1 misho 1: /*
2: +----------------------------------------------------------------------+
3: | PHP Version 5 |
4: +----------------------------------------------------------------------+
5: | Copyright (c) 1997-2012 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:
1.1.1.2 ! misho 19: /* $Id$ */
1.1 misho 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: ZEND_BEGIN_ARG_INFO_EX(arginfo_bcadd, 0, 0, 2)
40: ZEND_ARG_INFO(0, left_operand)
41: ZEND_ARG_INFO(0, right_operand)
42: ZEND_ARG_INFO(0, scale)
43: ZEND_END_ARG_INFO()
44:
45: ZEND_BEGIN_ARG_INFO_EX(arginfo_bcsub, 0, 0, 2)
46: ZEND_ARG_INFO(0, left_operand)
47: ZEND_ARG_INFO(0, right_operand)
48: ZEND_ARG_INFO(0, scale)
49: ZEND_END_ARG_INFO()
50:
51: ZEND_BEGIN_ARG_INFO_EX(arginfo_bcmul, 0, 0, 2)
52: ZEND_ARG_INFO(0, left_operand)
53: ZEND_ARG_INFO(0, right_operand)
54: ZEND_ARG_INFO(0, scale)
55: ZEND_END_ARG_INFO()
56:
57: ZEND_BEGIN_ARG_INFO_EX(arginfo_bcdiv, 0, 0, 2)
58: ZEND_ARG_INFO(0, left_operand)
59: ZEND_ARG_INFO(0, right_operand)
60: ZEND_ARG_INFO(0, scale)
61: ZEND_END_ARG_INFO()
62:
63: ZEND_BEGIN_ARG_INFO(arginfo_bcmod, 0)
64: ZEND_ARG_INFO(0, left_operand)
65: ZEND_ARG_INFO(0, right_operand)
66: ZEND_END_ARG_INFO()
67:
68: ZEND_BEGIN_ARG_INFO_EX(arginfo_bcpowmod, 0, 0, 3)
69: ZEND_ARG_INFO(0, x)
70: ZEND_ARG_INFO(0, y)
71: ZEND_ARG_INFO(0, mod)
72: ZEND_ARG_INFO(0, scale)
73: ZEND_END_ARG_INFO()
74:
75: ZEND_BEGIN_ARG_INFO_EX(arginfo_bcpow, 0, 0, 2)
76: ZEND_ARG_INFO(0, x)
77: ZEND_ARG_INFO(0, y)
78: ZEND_ARG_INFO(0, scale)
79: ZEND_END_ARG_INFO()
80:
81: ZEND_BEGIN_ARG_INFO_EX(arginfo_bcsqrt, 0, 0, 1)
82: ZEND_ARG_INFO(0, operand)
83: ZEND_ARG_INFO(0, scale)
84: ZEND_END_ARG_INFO()
85:
86: ZEND_BEGIN_ARG_INFO_EX(arginfo_bccomp, 0, 0, 2)
87: ZEND_ARG_INFO(0, left_operand)
88: ZEND_ARG_INFO(0, right_operand)
89: ZEND_ARG_INFO(0, scale)
90: ZEND_END_ARG_INFO()
91:
92: ZEND_BEGIN_ARG_INFO(arginfo_bcscale, 0)
93: ZEND_ARG_INFO(0, scale)
94: ZEND_END_ARG_INFO()
95:
96: /* }}} */
97:
98: const zend_function_entry bcmath_functions[] = {
99: PHP_FE(bcadd, arginfo_bcadd)
100: PHP_FE(bcsub, arginfo_bcsub)
101: PHP_FE(bcmul, arginfo_bcmul)
102: PHP_FE(bcdiv, arginfo_bcdiv)
103: PHP_FE(bcmod, arginfo_bcmod)
104: PHP_FE(bcpow, arginfo_bcpow)
105: PHP_FE(bcsqrt, arginfo_bcsqrt)
106: PHP_FE(bcscale, arginfo_bcscale)
107: PHP_FE(bccomp, arginfo_bccomp)
108: PHP_FE(bcpowmod, arginfo_bcpowmod)
109: PHP_FE_END
110: };
111:
112: zend_module_entry bcmath_module_entry = {
113: STANDARD_MODULE_HEADER,
114: "bcmath",
115: bcmath_functions,
116: PHP_MINIT(bcmath),
117: PHP_MSHUTDOWN(bcmath),
118: NULL,
119: NULL,
120: PHP_MINFO(bcmath),
121: NO_VERSION_YET,
122: PHP_MODULE_GLOBALS(bcmath),
123: PHP_GINIT(bcmath),
124: PHP_GSHUTDOWN(bcmath),
125: NULL,
126: STANDARD_MODULE_PROPERTIES_EX
127: };
128:
129: #ifdef COMPILE_DL_BCMATH
130: ZEND_GET_MODULE(bcmath)
131: #endif
132:
133: /* {{{ PHP_INI */
134: PHP_INI_BEGIN()
135: STD_PHP_INI_ENTRY("bcmath.scale", "0", PHP_INI_ALL, OnUpdateLongGEZero, bc_precision, zend_bcmath_globals, bcmath_globals)
136: PHP_INI_END()
137: /* }}} */
138:
139: /* {{{ PHP_GINIT_FUNCTION
140: */
141: static PHP_GINIT_FUNCTION(bcmath)
142: {
143: bcmath_globals->bc_precision = 0;
144: bc_init_numbers(TSRMLS_C);
145: }
146: /* }}} */
147:
148: /* {{{ PHP_GSHUTDOWN_FUNCTION
149: */
150: static PHP_GSHUTDOWN_FUNCTION(bcmath)
151: {
152: _bc_free_num_ex(&bcmath_globals->_zero_, 1);
153: _bc_free_num_ex(&bcmath_globals->_one_, 1);
154: _bc_free_num_ex(&bcmath_globals->_two_, 1);
155: }
156: /* }}} */
157:
158: /* {{{ PHP_MINIT_FUNCTION
159: */
160: PHP_MINIT_FUNCTION(bcmath)
161: {
162: REGISTER_INI_ENTRIES();
163:
164: return SUCCESS;
165: }
166: /* }}} */
167:
168: /* {{{ PHP_MSHUTDOWN_FUNCTION
169: */
170: PHP_MSHUTDOWN_FUNCTION(bcmath)
171: {
172: UNREGISTER_INI_ENTRIES();
173:
174: return SUCCESS;
175: }
176: /* }}} */
177:
178: /* {{{ PHP_MINFO_FUNCTION
179: */
180: PHP_MINFO_FUNCTION(bcmath)
181: {
182: php_info_print_table_start();
183: php_info_print_table_row(2, "BCMath support", "enabled");
184: php_info_print_table_end();
185: DISPLAY_INI_ENTRIES();
186: }
187: /* }}} */
188:
189: /* {{{ php_str2num
190: Convert to bc_num detecting scale */
191: static void php_str2num(bc_num *num, char *str TSRMLS_DC)
192: {
193: char *p;
194:
195: if (!(p = strchr(str, '.'))) {
196: bc_str2num(num, str, 0 TSRMLS_CC);
197: return;
198: }
199:
200: bc_str2num(num, str, strlen(p+1) TSRMLS_CC);
201: }
202: /* }}} */
203:
204: /* {{{ proto string bcadd(string left_operand, string right_operand [, int scale])
205: Returns the sum of two arbitrary precision numbers */
206: PHP_FUNCTION(bcadd)
207: {
208: char *left, *right;
209: long scale_param = 0;
210: bc_num first, second, result;
211: int left_len, right_len;
212: int scale = BCG(bc_precision), argc = ZEND_NUM_ARGS();
213:
214: if (zend_parse_parameters(argc TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale_param) == FAILURE) {
215: return;
216: }
217:
218: if (argc == 3) {
219: scale = (int) ((int)scale_param < 0) ? 0 : scale_param;
220: }
221:
222: bc_init_num(&first TSRMLS_CC);
223: bc_init_num(&second TSRMLS_CC);
224: bc_init_num(&result TSRMLS_CC);
225: php_str2num(&first, left TSRMLS_CC);
226: php_str2num(&second, right TSRMLS_CC);
227: bc_add (first, second, &result, scale);
228:
229: if (result->n_scale > scale) {
230: result->n_scale = scale;
231: }
232:
233: Z_STRVAL_P(return_value) = bc_num2str(result);
234: Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
235: Z_TYPE_P(return_value) = IS_STRING;
236: bc_free_num(&first);
237: bc_free_num(&second);
238: bc_free_num(&result);
239: return;
240: }
241: /* }}} */
242:
243: /* {{{ proto string bcsub(string left_operand, string right_operand [, int scale])
244: Returns the difference between two arbitrary precision numbers */
245: PHP_FUNCTION(bcsub)
246: {
247: char *left, *right;
248: int left_len, right_len;
249: long scale_param = 0;
250: bc_num first, second, result;
251: int scale = BCG(bc_precision), argc = ZEND_NUM_ARGS();
252:
253: if (zend_parse_parameters(argc TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale_param) == FAILURE) {
254: return;
255: }
256:
257: if (argc == 3) {
258: scale = (int) ((int)scale_param < 0) ? 0 : scale_param;
259: }
260:
261: bc_init_num(&first TSRMLS_CC);
262: bc_init_num(&second TSRMLS_CC);
263: bc_init_num(&result TSRMLS_CC);
264: php_str2num(&first, left TSRMLS_CC);
265: php_str2num(&second, right TSRMLS_CC);
266: bc_sub (first, second, &result, scale);
267:
268: if (result->n_scale > scale) {
269: result->n_scale = scale;
270: }
271:
272: Z_STRVAL_P(return_value) = bc_num2str(result);
273: Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
274: Z_TYPE_P(return_value) = IS_STRING;
275: bc_free_num(&first);
276: bc_free_num(&second);
277: bc_free_num(&result);
278: return;
279: }
280: /* }}} */
281:
282: /* {{{ proto string bcmul(string left_operand, string right_operand [, int scale])
283: Returns the multiplication of two arbitrary precision numbers */
284: PHP_FUNCTION(bcmul)
285: {
286: char *left, *right;
287: int left_len, right_len;
288: long scale_param = 0;
289: bc_num first, second, result;
290: int scale = BCG(bc_precision), argc = ZEND_NUM_ARGS();
291:
292: if (zend_parse_parameters(argc TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale_param) == FAILURE) {
293: return;
294: }
295:
296: if (argc == 3) {
297: scale = (int) ((int)scale_param < 0) ? 0 : scale_param;
298: }
299:
300: bc_init_num(&first TSRMLS_CC);
301: bc_init_num(&second TSRMLS_CC);
302: bc_init_num(&result TSRMLS_CC);
303: php_str2num(&first, left TSRMLS_CC);
304: php_str2num(&second, right TSRMLS_CC);
305: bc_multiply (first, second, &result, scale TSRMLS_CC);
306:
307: if (result->n_scale > scale) {
308: result->n_scale = scale;
309: }
310:
311: Z_STRVAL_P(return_value) = bc_num2str(result);
312: Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
313: Z_TYPE_P(return_value) = IS_STRING;
314: bc_free_num(&first);
315: bc_free_num(&second);
316: bc_free_num(&result);
317: return;
318: }
319: /* }}} */
320:
321: /* {{{ proto string bcdiv(string left_operand, string right_operand [, int scale])
322: Returns the quotient of two arbitrary precision numbers (division) */
323: PHP_FUNCTION(bcdiv)
324: {
325: char *left, *right;
326: int left_len, right_len;
327: long scale_param = 0;
328: bc_num first, second, result;
329: int scale = BCG(bc_precision), argc = ZEND_NUM_ARGS();
330:
331: if (zend_parse_parameters(argc TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale_param) == FAILURE) {
332: return;
333: }
334:
335: if (argc == 3) {
336: scale = (int) ((int)scale_param < 0) ? 0 : scale_param;
337: }
338:
339: bc_init_num(&first TSRMLS_CC);
340: bc_init_num(&second TSRMLS_CC);
341: bc_init_num(&result TSRMLS_CC);
342: php_str2num(&first, left TSRMLS_CC);
343: php_str2num(&second, right TSRMLS_CC);
344:
345: switch (bc_divide(first, second, &result, scale TSRMLS_CC)) {
346: case 0: /* OK */
347: if (result->n_scale > scale) {
348: result->n_scale = scale;
349: }
350: Z_STRVAL_P(return_value) = bc_num2str(result);
351: Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
352: Z_TYPE_P(return_value) = IS_STRING;
353: break;
354: case -1: /* division by zero */
355: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Division by zero");
356: break;
357: }
358:
359: bc_free_num(&first);
360: bc_free_num(&second);
361: bc_free_num(&result);
362: return;
363: }
364: /* }}} */
365:
366: /* {{{ proto string bcmod(string left_operand, string right_operand)
367: Returns the modulus of the two arbitrary precision operands */
368: PHP_FUNCTION(bcmod)
369: {
370: char *left, *right;
371: int left_len, right_len;
372: bc_num first, second, result;
373:
374: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss", &left, &left_len, &right, &right_len) == FAILURE) {
375: return;
376: }
377:
378: bc_init_num(&first TSRMLS_CC);
379: bc_init_num(&second TSRMLS_CC);
380: bc_init_num(&result TSRMLS_CC);
381: bc_str2num(&first, left, 0 TSRMLS_CC);
382: bc_str2num(&second, right, 0 TSRMLS_CC);
383:
384: switch (bc_modulo(first, second, &result, 0 TSRMLS_CC)) {
385: case 0:
386: Z_STRVAL_P(return_value) = bc_num2str(result);
387: Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
388: Z_TYPE_P(return_value) = IS_STRING;
389: break;
390: case -1:
391: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Division by zero");
392: break;
393: }
394:
395: bc_free_num(&first);
396: bc_free_num(&second);
397: bc_free_num(&result);
398: return;
399: }
400: /* }}} */
401:
402: /* {{{ proto string bcpowmod(string x, string y, string mod [, int scale])
403: Returns the value of an arbitrary precision number raised to the power of another reduced by a modulous */
404: PHP_FUNCTION(bcpowmod)
405: {
406: char *left, *right, *modulous;
407: int left_len, right_len, modulous_len;
408: bc_num first, second, mod, result;
409: long scale = BCG(bc_precision);
410: int scale_int;
411:
412: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|l", &left, &left_len, &right, &right_len, &modulous, &modulous_len, &scale) == FAILURE) {
413: return;
414: }
415:
416: bc_init_num(&first TSRMLS_CC);
417: bc_init_num(&second TSRMLS_CC);
418: bc_init_num(&mod TSRMLS_CC);
419: bc_init_num(&result TSRMLS_CC);
420: php_str2num(&first, left TSRMLS_CC);
421: php_str2num(&second, right TSRMLS_CC);
422: php_str2num(&mod, modulous TSRMLS_CC);
423:
424: scale_int = (int) ((int)scale < 0) ? 0 : scale;
425:
426: if (bc_raisemod(first, second, mod, &result, scale_int TSRMLS_CC) != -1) {
427: if (result->n_scale > scale) {
428: result->n_scale = scale;
429: }
430: Z_STRVAL_P(return_value) = bc_num2str(result);
431: Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
432: Z_TYPE_P(return_value) = IS_STRING;
433: } else {
434: RETVAL_FALSE;
435: }
436:
437: bc_free_num(&first);
438: bc_free_num(&second);
439: bc_free_num(&mod);
440: bc_free_num(&result);
441: return;
442: }
443: /* }}} */
444:
445: /* {{{ proto string bcpow(string x, string y [, int scale])
446: Returns the value of an arbitrary precision number raised to the power of another */
447: PHP_FUNCTION(bcpow)
448: {
449: char *left, *right;
450: int left_len, right_len;
451: long scale_param = 0;
452: bc_num first, second, result;
453: int scale = BCG(bc_precision), argc = ZEND_NUM_ARGS();
454:
455: if (zend_parse_parameters(argc TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale_param) == FAILURE) {
456: return;
457: }
458:
459: if (argc == 3) {
460: scale = (int) ((int)scale_param < 0) ? 0 : scale_param;
461: }
462:
463: bc_init_num(&first TSRMLS_CC);
464: bc_init_num(&second TSRMLS_CC);
465: bc_init_num(&result TSRMLS_CC);
466: php_str2num(&first, left TSRMLS_CC);
467: php_str2num(&second, right TSRMLS_CC);
468: bc_raise (first, second, &result, scale TSRMLS_CC);
469:
470: if (result->n_scale > scale) {
471: result->n_scale = scale;
472: }
473:
474: Z_STRVAL_P(return_value) = bc_num2str(result);
475: Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
476: Z_TYPE_P(return_value) = IS_STRING;
477: bc_free_num(&first);
478: bc_free_num(&second);
479: bc_free_num(&result);
480: return;
481: }
482: /* }}} */
483:
484: /* {{{ proto string bcsqrt(string operand [, int scale])
485: Returns the square root of an arbitray precision number */
486: PHP_FUNCTION(bcsqrt)
487: {
488: char *left;
489: int left_len;
490: long scale_param = 0;
491: bc_num result;
492: int scale = BCG(bc_precision), argc = ZEND_NUM_ARGS();
493:
494: if (zend_parse_parameters(argc TSRMLS_CC, "s|l", &left, &left_len, &scale_param) == FAILURE) {
495: return;
496: }
497:
498: if (argc == 2) {
499: scale = (int) ((int)scale_param < 0) ? 0 : scale_param;
500: }
501:
502: bc_init_num(&result TSRMLS_CC);
503: php_str2num(&result, left TSRMLS_CC);
504:
505: if (bc_sqrt (&result, scale TSRMLS_CC) != 0) {
506: if (result->n_scale > scale) {
507: result->n_scale = scale;
508: }
509: Z_STRVAL_P(return_value) = bc_num2str(result);
510: Z_STRLEN_P(return_value) = strlen(Z_STRVAL_P(return_value));
511: Z_TYPE_P(return_value) = IS_STRING;
512: } else {
513: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Square root of negative number");
514: }
515:
516: bc_free_num(&result);
517: return;
518: }
519: /* }}} */
520:
521: /* {{{ proto int bccomp(string left_operand, string right_operand [, int scale])
522: Compares two arbitrary precision numbers */
523: PHP_FUNCTION(bccomp)
524: {
525: char *left, *right;
526: int left_len, right_len;
527: long scale_param = 0;
528: bc_num first, second;
529: int scale = BCG(bc_precision), argc = ZEND_NUM_ARGS();
530:
531: if (zend_parse_parameters(argc TSRMLS_CC, "ss|l", &left, &left_len, &right, &right_len, &scale_param) == FAILURE) {
532: return;
533: }
534:
535: if (argc == 3) {
536: scale = (int) ((int)scale_param < 0) ? 0 : scale_param;
537: }
538:
539: bc_init_num(&first TSRMLS_CC);
540: bc_init_num(&second TSRMLS_CC);
541:
542: bc_str2num(&first, left, scale TSRMLS_CC);
543: bc_str2num(&second, right, scale TSRMLS_CC);
544: Z_LVAL_P(return_value) = bc_compare(first, second);
545: Z_TYPE_P(return_value) = IS_LONG;
546:
547: bc_free_num(&first);
548: bc_free_num(&second);
549: return;
550: }
551: /* }}} */
552:
553: /* {{{ proto bool bcscale(int scale)
554: Sets default scale parameter for all bc math functions */
555: PHP_FUNCTION(bcscale)
556: {
557: long new_scale;
558:
559: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &new_scale) == FAILURE) {
560: return;
561: }
562:
563: BCG(bc_precision) = ((int)new_scale < 0) ? 0 : new_scale;
564:
565: RETURN_TRUE;
566: }
567: /* }}} */
568:
569:
570: #endif
571:
572: /*
573: * Local variables:
574: * tab-width: 4
575: * c-basic-offset: 4
576: * End:
577: * vim600: sw=4 ts=4 fdm=marker
578: * vim<600: sw=4 ts=4
579: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>