This source file includes following definitions.
- php_intlog10abs
- php_intpow10
- php_math_is_finite
- php_round_helper
- _php_math_round
- php_asinh
- php_acosh
- php_atanh
- php_log1p
- php_expm1
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- _php_math_basetolong
- _php_math_basetozval
- _php_math_longtobase
- _php_math_zvaltobase
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- PHP_FUNCTION
- _php_math_number_format
- _php_math_number_format_ex_len
- _php_math_number_format_ex
- PHP_FUNCTION
- PHP_FUNCTION
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 #include "php.h"
25 #include "php_math.h"
26 #include "zend_multiply.h"
27
28 #include <math.h>
29 #include <float.h>
30 #include <stdlib.h>
31
32 #include "basic_functions.h"
33
34
35
36 static inline int php_intlog10abs(double value) {
37 int result;
38 value = fabs(value);
39
40 if (value < 1e-8 || value > 1e22) {
41 result = (int)floor(log10(value));
42 } else {
43 static const double values[] = {
44 1e-8, 1e-7, 1e-6, 1e-5, 1e-4, 1e-3, 1e-2, 1e-1,
45 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7,
46 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
47 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
48
49 result = 15;
50 if (value < values[result]) {
51 result -= 8;
52 } else {
53 result += 8;
54 }
55 if (value < values[result]) {
56 result -= 4;
57 } else {
58 result += 4;
59 }
60 if (value < values[result]) {
61 result -= 2;
62 } else {
63 result += 2;
64 }
65 if (value < values[result]) {
66 result -= 1;
67 } else {
68 result += 1;
69 }
70 if (value < values[result]) {
71 result -= 1;
72 }
73 result -= 8;
74 }
75 return result;
76 }
77
78
79
80
81 static inline double php_intpow10(int power) {
82 static const double powers[] = {
83 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7,
84 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15,
85 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22};
86
87
88 if (power < 0 || power > 22) {
89 return pow(10.0, (double)power);
90 }
91 return powers[power];
92 }
93
94
95
96 static inline int php_math_is_finite(double value) {
97 #if defined(PHP_WIN32)
98 return _finite(value);
99 #elif defined(isfinite)
100 return isfinite(value);
101 #else
102 return value == value && (value == 0. || value * 2. != value);
103 #endif
104 }
105
106
107
108
109 static inline double php_round_helper(double value, int mode) {
110 double tmp_value;
111
112 if (value >= 0.0) {
113 tmp_value = floor(value + 0.5);
114 if ((mode == PHP_ROUND_HALF_DOWN && value == (-0.5 + tmp_value)) ||
115 (mode == PHP_ROUND_HALF_EVEN && value == (0.5 + 2 * floor(tmp_value/2.0))) ||
116 (mode == PHP_ROUND_HALF_ODD && value == (0.5 + 2 * floor(tmp_value/2.0) - 1.0)))
117 {
118 tmp_value = tmp_value - 1.0;
119 }
120 } else {
121 tmp_value = ceil(value - 0.5);
122 if ((mode == PHP_ROUND_HALF_DOWN && value == (0.5 + tmp_value)) ||
123 (mode == PHP_ROUND_HALF_EVEN && value == (-0.5 + 2 * ceil(tmp_value/2.0))) ||
124 (mode == PHP_ROUND_HALF_ODD && value == (-0.5 + 2 * ceil(tmp_value/2.0) + 1.0)))
125 {
126 tmp_value = tmp_value + 1.0;
127 }
128 }
129
130 return tmp_value;
131 }
132
133
134
135
136
137
138
139 PHPAPI double _php_math_round(double value, int places, int mode) {
140 double f1, f2;
141 double tmp_value;
142 int precision_places;
143
144 if (!php_math_is_finite(value)) {
145 return value;
146 }
147
148 places = places < INT_MIN+1 ? INT_MIN+1 : places;
149 precision_places = 14 - php_intlog10abs(value);
150
151 f1 = php_intpow10(abs(places));
152
153
154
155
156 if (precision_places > places && precision_places - places < 15) {
157 int64_t use_precision = precision_places < INT_MIN+1 ? INT_MIN+1 : precision_places;
158
159 f2 = php_intpow10(abs((int)use_precision));
160 if (use_precision >= 0) {
161 tmp_value = value * f2;
162 } else {
163 tmp_value = value / f2;
164 }
165
166
167 tmp_value = php_round_helper(tmp_value, mode);
168
169 use_precision = places - precision_places;
170 use_precision = use_precision < INT_MIN+1 ? INT_MIN+1 : use_precision;
171
172 f2 = php_intpow10(abs((int)use_precision));
173
174 tmp_value = tmp_value / f2;
175 } else {
176
177 if (places >= 0) {
178 tmp_value = value * f1;
179 } else {
180 tmp_value = value / f1;
181 }
182
183 if (fabs(tmp_value) >= 1e15) {
184 return value;
185 }
186 }
187
188
189 tmp_value = php_round_helper(tmp_value, mode);
190
191
192 if (abs(places) < 23) {
193 if (places > 0) {
194 tmp_value = tmp_value / f1;
195 } else {
196 tmp_value = tmp_value * f1;
197 }
198 } else {
199
200
201
202
203
204
205
206
207 char buf[40];
208 snprintf(buf, 39, "%15fe%d", tmp_value, -places);
209 buf[39] = '\0';
210 tmp_value = zend_strtod(buf, NULL);
211
212 if (!zend_finite(tmp_value) || zend_isnan(tmp_value)) {
213 tmp_value = value;
214 }
215 }
216
217 return tmp_value;
218 }
219
220
221
222
223 static double php_asinh(double z)
224 {
225 #ifdef HAVE_ASINH
226 return(asinh(z));
227 #else
228 return(log(z + sqrt(1 + pow(z, 2))) / log(M_E));
229 #endif
230 }
231
232
233
234
235 static double php_acosh(double x)
236 {
237 #ifdef HAVE_ACOSH
238 return(acosh(x));
239 #else
240 return(log(x + sqrt(x * x - 1)));
241 #endif
242 }
243
244
245
246
247 static double php_atanh(double z)
248 {
249 #ifdef HAVE_ATANH
250 return(atanh(z));
251 #else
252 return(0.5 * log((1 + z) / (1 - z)));
253 #endif
254 }
255
256
257
258
259 static double php_log1p(double x)
260 {
261 #ifdef HAVE_LOG1P
262 return(log1p(x));
263 #else
264 return(log(1 + x));
265 #endif
266 }
267
268
269
270
271 static double php_expm1(double x)
272 {
273 #if !defined(PHP_WIN32) && !defined(NETWARE)
274 return(expm1(x));
275 #else
276 return(exp(x) - 1);
277 #endif
278 }
279
280
281
282
283 PHP_FUNCTION(abs)
284 {
285 zval **value;
286
287 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &value) == FAILURE) {
288 return;
289 }
290 convert_scalar_to_number_ex(value);
291
292 if (Z_TYPE_PP(value) == IS_DOUBLE) {
293 RETURN_DOUBLE(fabs(Z_DVAL_PP(value)));
294 } else if (Z_TYPE_PP(value) == IS_LONG) {
295 if (Z_LVAL_PP(value) == LONG_MIN) {
296 RETURN_DOUBLE(-(double)LONG_MIN);
297 } else {
298 RETURN_LONG(Z_LVAL_PP(value) < 0 ? -Z_LVAL_PP(value) : Z_LVAL_PP(value));
299 }
300 }
301 RETURN_FALSE;
302 }
303
304
305
306
307 PHP_FUNCTION(ceil)
308 {
309 zval **value;
310
311 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &value) == FAILURE) {
312 return;
313 }
314 convert_scalar_to_number_ex(value);
315
316 if (Z_TYPE_PP(value) == IS_DOUBLE) {
317 RETURN_DOUBLE(ceil(Z_DVAL_PP(value)));
318 } else if (Z_TYPE_PP(value) == IS_LONG) {
319 convert_to_double_ex(value);
320 RETURN_DOUBLE(Z_DVAL_PP(value));
321 }
322 RETURN_FALSE;
323 }
324
325
326
327
328 PHP_FUNCTION(floor)
329 {
330 zval **value;
331
332 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &value) == FAILURE) {
333 return;
334 }
335 convert_scalar_to_number_ex(value);
336
337 if (Z_TYPE_PP(value) == IS_DOUBLE) {
338 RETURN_DOUBLE(floor(Z_DVAL_PP(value)));
339 } else if (Z_TYPE_PP(value) == IS_LONG) {
340 convert_to_double_ex(value);
341 RETURN_DOUBLE(Z_DVAL_PP(value));
342 }
343 RETURN_FALSE;
344 }
345
346
347
348
349 PHP_FUNCTION(round)
350 {
351 zval **value;
352 int places = 0;
353 long precision = 0;
354 long mode = PHP_ROUND_HALF_UP;
355 double return_val;
356
357 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|ll", &value, &precision, &mode) == FAILURE) {
358 return;
359 }
360
361 if (ZEND_NUM_ARGS() >= 2) {
362 #if SIZEOF_LONG > SIZEOF_INT
363 if (precision >= 0) {
364 places = precision > INT_MAX ? INT_MAX : (int)precision;
365 } else {
366 places = precision <= INT_MIN ? INT_MIN+1 : (int)precision;
367 }
368 #else
369 places = precision;
370 #endif
371 }
372 convert_scalar_to_number_ex(value);
373
374 switch (Z_TYPE_PP(value)) {
375 case IS_LONG:
376
377 if (places >= 0) {
378 RETURN_DOUBLE((double) Z_LVAL_PP(value));
379 }
380
381
382 case IS_DOUBLE:
383 return_val = (Z_TYPE_PP(value) == IS_LONG) ? (double)Z_LVAL_PP(value) : Z_DVAL_PP(value);
384 return_val = _php_math_round(return_val, places, mode);
385 RETURN_DOUBLE(return_val);
386 break;
387
388 default:
389 RETURN_FALSE;
390 break;
391 }
392 }
393
394
395
396
397 PHP_FUNCTION(sin)
398 {
399 double num;
400
401 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
402 return;
403 }
404 RETURN_DOUBLE(sin(num));
405 }
406
407
408
409
410 PHP_FUNCTION(cos)
411 {
412 double num;
413
414 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
415 return;
416 }
417 RETURN_DOUBLE(cos(num));
418 }
419
420
421
422
423 PHP_FUNCTION(tan)
424 {
425 double num;
426
427 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
428 return;
429 }
430 RETURN_DOUBLE(tan(num));
431 }
432
433
434
435
436 PHP_FUNCTION(asin)
437 {
438 double num;
439
440 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
441 return;
442 }
443 RETURN_DOUBLE(asin(num));
444 }
445
446
447
448
449 PHP_FUNCTION(acos)
450 {
451 double num;
452
453 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
454 return;
455 }
456 RETURN_DOUBLE(acos(num));
457 }
458
459
460
461
462 PHP_FUNCTION(atan)
463 {
464 double num;
465
466 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
467 return;
468 }
469 RETURN_DOUBLE(atan(num));
470 }
471
472
473
474
475 PHP_FUNCTION(atan2)
476 {
477 double num1, num2;
478
479 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &num1, &num2) == FAILURE) {
480 return;
481 }
482 RETURN_DOUBLE(atan2(num1, num2));
483 }
484
485
486
487
488 PHP_FUNCTION(sinh)
489 {
490 double num;
491
492 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
493 return;
494 }
495 RETURN_DOUBLE(sinh(num));
496 }
497
498
499
500
501 PHP_FUNCTION(cosh)
502 {
503 double num;
504
505 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
506 return;
507 }
508 RETURN_DOUBLE(cosh(num));
509 }
510
511
512
513
514 PHP_FUNCTION(tanh)
515 {
516 double num;
517
518 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
519 return;
520 }
521 RETURN_DOUBLE(tanh(num));
522 }
523
524
525
526
527 PHP_FUNCTION(asinh)
528 {
529 double num;
530
531 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
532 return;
533 }
534 RETURN_DOUBLE(php_asinh(num));
535 }
536
537
538
539
540 PHP_FUNCTION(acosh)
541 {
542 double num;
543
544 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
545 return;
546 }
547 RETURN_DOUBLE(php_acosh(num));
548 }
549
550
551
552
553 PHP_FUNCTION(atanh)
554 {
555 double num;
556
557 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
558 return;
559 }
560 RETURN_DOUBLE(php_atanh(num));
561 }
562
563
564
565
566 PHP_FUNCTION(pi)
567 {
568 RETURN_DOUBLE(M_PI);
569 }
570
571
572
573
574 PHP_FUNCTION(is_finite)
575 {
576 double dval;
577
578 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
579 return;
580 }
581 RETURN_BOOL(zend_finite(dval));
582 }
583
584
585
586
587 PHP_FUNCTION(is_infinite)
588 {
589 double dval;
590
591 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
592 return;
593 }
594 RETURN_BOOL(zend_isinf(dval));
595 }
596
597
598
599
600 PHP_FUNCTION(is_nan)
601 {
602 double dval;
603
604 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
605 return;
606 }
607 RETURN_BOOL(zend_isnan(dval));
608 }
609
610
611
612
613 PHP_FUNCTION(pow)
614 {
615 zval *zbase, *zexp;
616
617 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z/", &zbase, &zexp) == FAILURE) {
618 return;
619 }
620
621 pow_function(return_value, zbase, zexp TSRMLS_CC);
622 }
623
624
625
626
627 PHP_FUNCTION(exp)
628 {
629 double num;
630
631 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
632 return;
633 }
634
635 RETURN_DOUBLE(exp(num));
636 }
637
638
639
640
641
642
643
644
645 PHP_FUNCTION(expm1)
646 {
647 double num;
648
649 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
650 return;
651 }
652 RETURN_DOUBLE(php_expm1(num));
653 }
654
655
656
657
658
659
660
661
662 PHP_FUNCTION(log1p)
663 {
664 double num;
665
666 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
667 return;
668 }
669 RETURN_DOUBLE(php_log1p(num));
670 }
671
672
673
674
675 PHP_FUNCTION(log)
676 {
677 double num, base = 0;
678
679 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|d", &num, &base) == FAILURE) {
680 return;
681 }
682 if (ZEND_NUM_ARGS() == 1) {
683 RETURN_DOUBLE(log(num));
684 }
685 if (base <= 0.0) {
686 php_error_docref(NULL TSRMLS_CC, E_WARNING, "base must be greater than 0");
687 RETURN_FALSE;
688 }
689 if (base == 1) {
690 RETURN_DOUBLE(php_get_nan());
691 } else {
692 RETURN_DOUBLE(log(num) / log(base));
693 }
694 }
695
696
697
698
699 PHP_FUNCTION(log10)
700 {
701 double num;
702
703 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
704 return;
705 }
706 RETURN_DOUBLE(log10(num));
707 }
708
709
710
711
712 PHP_FUNCTION(sqrt)
713 {
714 double num;
715
716 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
717 return;
718 }
719 RETURN_DOUBLE(sqrt(num));
720 }
721
722
723
724
725 PHP_FUNCTION(hypot)
726 {
727 double num1, num2;
728
729 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &num1, &num2) == FAILURE) {
730 return;
731 }
732 #if HAVE_HYPOT
733 RETURN_DOUBLE(hypot(num1, num2));
734 #elif defined(_MSC_VER)
735 RETURN_DOUBLE(_hypot(num1, num2));
736 #else
737 RETURN_DOUBLE(sqrt((num1 * num1) + (num2 * num2)));
738 #endif
739 }
740
741
742
743
744 PHP_FUNCTION(deg2rad)
745 {
746 double deg;
747
748 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", °) == FAILURE) {
749 return;
750 }
751 RETURN_DOUBLE((deg / 180.0) * M_PI);
752 }
753
754
755
756
757 PHP_FUNCTION(rad2deg)
758 {
759 double rad;
760
761 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &rad) == FAILURE) {
762 return;
763 }
764 RETURN_DOUBLE((rad / M_PI) * 180);
765 }
766
767
768
769
770
771
772 PHPAPI long _php_math_basetolong(zval *arg, int base)
773 {
774 long num = 0, digit, onum;
775 int i;
776 char c, *s;
777
778 if (Z_TYPE_P(arg) != IS_STRING || base < 2 || base > 36) {
779 return 0;
780 }
781
782 s = Z_STRVAL_P(arg);
783
784 for (i = Z_STRLEN_P(arg); i > 0; i--) {
785 c = *s++;
786
787 digit = (c >= '0' && c <= '9') ? c - '0'
788 : (c >= 'A' && c <= 'Z') ? c - 'A' + 10
789 : (c >= 'a' && c <= 'z') ? c - 'a' + 10
790 : base;
791
792 if (digit >= base) {
793 continue;
794 }
795
796 onum = num;
797 num = num * base + digit;
798 if (num > onum)
799 continue;
800
801 {
802 TSRMLS_FETCH();
803
804 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number '%s' is too big to fit in long", s);
805 return LONG_MAX;
806 }
807 }
808
809 return num;
810 }
811
812
813
814
815
816
817 PHPAPI int _php_math_basetozval(zval *arg, int base, zval *ret)
818 {
819 long num = 0;
820 double fnum = 0;
821 int i;
822 int mode = 0;
823 char c, *s;
824 long cutoff;
825 int cutlim;
826
827 if (Z_TYPE_P(arg) != IS_STRING || base < 2 || base > 36) {
828 return FAILURE;
829 }
830
831 s = Z_STRVAL_P(arg);
832
833 cutoff = LONG_MAX / base;
834 cutlim = LONG_MAX % base;
835
836 for (i = Z_STRLEN_P(arg); i > 0; i--) {
837 c = *s++;
838
839
840 if (c >= '0' && c <= '9')
841 c -= '0';
842 else if (c >= 'A' && c <= 'Z')
843 c -= 'A' - 10;
844 else if (c >= 'a' && c <= 'z')
845 c -= 'a' - 10;
846 else
847 continue;
848
849 if (c >= base)
850 continue;
851
852 switch (mode) {
853 case 0:
854 if (num < cutoff || (num == cutoff && c <= cutlim)) {
855 num = num * base + c;
856 break;
857 } else {
858 fnum = num;
859 mode = 1;
860 }
861
862 case 1:
863 fnum = fnum * base + c;
864 }
865 }
866
867 if (mode == 1) {
868 ZVAL_DOUBLE(ret, fnum);
869 } else {
870 ZVAL_LONG(ret, num);
871 }
872 return SUCCESS;
873 }
874
875
876
877
878
879
880
881 PHPAPI char * _php_math_longtobase(zval *arg, int base)
882 {
883 static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
884 char buf[(sizeof(unsigned long) << 3) + 1];
885 char *ptr, *end;
886 unsigned long value;
887
888 if (Z_TYPE_P(arg) != IS_LONG || base < 2 || base > 36) {
889 return STR_EMPTY_ALLOC();
890 }
891
892 value = Z_LVAL_P(arg);
893
894 end = ptr = buf + sizeof(buf) - 1;
895 *ptr = '\0';
896
897 do {
898 *--ptr = digits[value % base];
899 value /= base;
900 } while (ptr > buf && value);
901
902 return estrndup(ptr, end - ptr);
903 }
904
905
906
907
908
909
910
911 PHPAPI char * _php_math_zvaltobase(zval *arg, int base TSRMLS_DC)
912 {
913 static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
914
915 if ((Z_TYPE_P(arg) != IS_LONG && Z_TYPE_P(arg) != IS_DOUBLE) || base < 2 || base > 36) {
916 return STR_EMPTY_ALLOC();
917 }
918
919 if (Z_TYPE_P(arg) == IS_DOUBLE) {
920 double fvalue = floor(Z_DVAL_P(arg));
921 char *ptr, *end;
922 char buf[(sizeof(double) << 3) + 1];
923
924
925 if (fvalue == HUGE_VAL || fvalue == -HUGE_VAL) {
926 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number too large");
927 return STR_EMPTY_ALLOC();
928 }
929
930 end = ptr = buf + sizeof(buf) - 1;
931 *ptr = '\0';
932
933 do {
934 *--ptr = digits[(int) fmod(fvalue, base)];
935 fvalue /= base;
936 } while (ptr > buf && fabs(fvalue) >= 1);
937
938 return estrndup(ptr, end - ptr);
939 }
940
941 return _php_math_longtobase(arg, base);
942 }
943
944
945
946
947 PHP_FUNCTION(bindec)
948 {
949 zval **arg;
950
951 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
952 return;
953 }
954 convert_to_string_ex(arg);
955 if (_php_math_basetozval(*arg, 2, return_value) == FAILURE) {
956 RETURN_FALSE;
957 }
958 }
959
960
961
962
963 PHP_FUNCTION(hexdec)
964 {
965 zval **arg;
966
967 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
968 return;
969 }
970 convert_to_string_ex(arg);
971 if (_php_math_basetozval(*arg, 16, return_value) == FAILURE) {
972 RETURN_FALSE;
973 }
974 }
975
976
977
978
979 PHP_FUNCTION(octdec)
980 {
981 zval **arg;
982
983 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
984 return;
985 }
986 convert_to_string_ex(arg);
987 if (_php_math_basetozval(*arg, 8, return_value) == FAILURE) {
988 RETURN_FALSE;
989 }
990 }
991
992
993
994
995 PHP_FUNCTION(decbin)
996 {
997 zval **arg;
998 char *result;
999
1000 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
1001 return;
1002 }
1003 convert_to_long_ex(arg);
1004 result = _php_math_longtobase(*arg, 2);
1005 RETURN_STRING(result, 0);
1006 }
1007
1008
1009
1010
1011 PHP_FUNCTION(decoct)
1012 {
1013 zval **arg;
1014 char *result;
1015
1016 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
1017 return;
1018 }
1019 convert_to_long_ex(arg);
1020 result = _php_math_longtobase(*arg, 8);
1021 RETURN_STRING(result, 0);
1022 }
1023
1024
1025
1026
1027 PHP_FUNCTION(dechex)
1028 {
1029 zval **arg;
1030 char *result;
1031
1032 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
1033 return;
1034 }
1035 convert_to_long_ex(arg);
1036 result = _php_math_longtobase(*arg, 16);
1037 RETURN_STRING(result, 0);
1038 }
1039
1040
1041
1042
1043 PHP_FUNCTION(base_convert)
1044 {
1045 zval **number, temp;
1046 long frombase, tobase;
1047 char *result;
1048
1049 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zll", &number, &frombase, &tobase) == FAILURE) {
1050 return;
1051 }
1052 convert_to_string_ex(number);
1053
1054 if (frombase < 2 || frombase > 36) {
1055 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid `from base' (%ld)", frombase);
1056 RETURN_FALSE;
1057 }
1058 if (tobase < 2 || tobase > 36) {
1059 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid `to base' (%ld)", tobase);
1060 RETURN_FALSE;
1061 }
1062
1063 if(_php_math_basetozval(*number, frombase, &temp) == FAILURE) {
1064 RETURN_FALSE;
1065 }
1066 result = _php_math_zvaltobase(&temp, tobase TSRMLS_CC);
1067 RETVAL_STRING(result, 0);
1068 }
1069
1070
1071
1072
1073 PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char thousand_sep)
1074 {
1075 return _php_math_number_format_ex(d, dec, &dec_point, 1, &thousand_sep, 1);
1076 }
1077
1078 static char *_php_math_number_format_ex_len(double d, int dec, char *dec_point,
1079 size_t dec_point_len, char *thousand_sep, size_t thousand_sep_len,
1080 int *result_len)
1081 {
1082 char *tmpbuf = NULL, *resbuf;
1083 char *s, *t;
1084 char *dp;
1085 int integral;
1086 int tmplen, reslen=0;
1087 int count=0;
1088 int is_negative=0;
1089
1090 if (d < 0) {
1091 is_negative = 1;
1092 d = -d;
1093 }
1094
1095 dec = MAX(0, dec);
1096 d = _php_math_round(d, dec, PHP_ROUND_HALF_UP);
1097
1098 tmplen = spprintf(&tmpbuf, 0, "%.*F", dec, d);
1099
1100 if (tmpbuf == NULL || !isdigit((int)tmpbuf[0])) {
1101 if (result_len) {
1102 *result_len = tmplen;
1103 }
1104
1105 return tmpbuf;
1106 }
1107
1108
1109 if (dec) {
1110 dp = strpbrk(tmpbuf, ".,");
1111 } else {
1112 dp = NULL;
1113 }
1114
1115
1116 if (dp) {
1117 integral = dp - tmpbuf;
1118 } else {
1119
1120 integral = tmplen;
1121 }
1122
1123
1124 if (thousand_sep) {
1125 integral += thousand_sep_len * ((integral-1) / 3);
1126 }
1127
1128 reslen = integral;
1129
1130 if (dec) {
1131 reslen += dec;
1132
1133 if (dec_point) {
1134 reslen += dec_point_len;
1135 }
1136 }
1137
1138
1139 if (is_negative) {
1140 reslen++;
1141 }
1142 resbuf = (char *) emalloc(reslen+1);
1143
1144 s = tmpbuf+tmplen-1;
1145 t = resbuf+reslen;
1146 *t-- = '\0';
1147
1148
1149
1150
1151 if (dec) {
1152 int declen = dp ? s - dp : 0;
1153 int topad = dec > declen ? dec - declen : 0;
1154
1155
1156 while (topad--) {
1157 *t-- = '0';
1158 }
1159
1160 if (dp) {
1161 s -= declen + 1;
1162 t -= declen;
1163
1164
1165 memcpy(t + 1, dp + 1, declen);
1166 }
1167
1168
1169 if (dec_point) {
1170 t -= dec_point_len;
1171 memcpy(t + 1, dec_point, dec_point_len);
1172 }
1173 }
1174
1175
1176
1177 while(s >= tmpbuf) {
1178 *t-- = *s--;
1179 if (thousand_sep && (++count%3)==0 && s>=tmpbuf) {
1180 t -= thousand_sep_len;
1181 memcpy(t + 1, thousand_sep, thousand_sep_len);
1182 }
1183 }
1184
1185
1186 if (is_negative) {
1187 *t-- = '-';
1188 }
1189
1190 efree(tmpbuf);
1191
1192 if (result_len) {
1193 *result_len = reslen;
1194 }
1195
1196 return resbuf;
1197 }
1198
1199 PHPAPI char *_php_math_number_format_ex(double d, int dec, char *dec_point,
1200 size_t dec_point_len, char *thousand_sep, size_t thousand_sep_len)
1201 {
1202 return _php_math_number_format_ex_len(d, dec, dec_point, dec_point_len,
1203 thousand_sep, thousand_sep_len, NULL);
1204 }
1205
1206
1207
1208
1209 PHP_FUNCTION(number_format)
1210 {
1211 double num;
1212 long dec = 0;
1213 char *thousand_sep = NULL, *dec_point = NULL;
1214 char thousand_sep_chr = ',', dec_point_chr = '.';
1215 int thousand_sep_len = 0, dec_point_len = 0;
1216
1217 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|ls!s!", &num, &dec, &dec_point, &dec_point_len, &thousand_sep, &thousand_sep_len) == FAILURE) {
1218 return;
1219 }
1220
1221 switch(ZEND_NUM_ARGS()) {
1222 case 1:
1223 RETURN_STRING(_php_math_number_format(num, 0, dec_point_chr, thousand_sep_chr), 0);
1224 break;
1225 case 2:
1226 RETURN_STRING(_php_math_number_format(num, dec, dec_point_chr, thousand_sep_chr), 0);
1227 break;
1228 case 4:
1229 if (dec_point == NULL) {
1230 dec_point = &dec_point_chr;
1231 dec_point_len = 1;
1232 }
1233
1234 if (thousand_sep == NULL) {
1235 thousand_sep = &thousand_sep_chr;
1236 thousand_sep_len = 1;
1237 }
1238
1239 Z_TYPE_P(return_value) = IS_STRING;
1240 Z_STRVAL_P(return_value) = _php_math_number_format_ex_len(num, dec,
1241 dec_point, dec_point_len, thousand_sep, thousand_sep_len,
1242 &Z_STRLEN_P(return_value));
1243 break;
1244 default:
1245 WRONG_PARAM_COUNT;
1246 break;
1247 }
1248 }
1249
1250
1251
1252
1253 PHP_FUNCTION(fmod)
1254 {
1255 double num1, num2;
1256
1257 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &num1, &num2) == FAILURE) {
1258 return;
1259 }
1260 RETURN_DOUBLE(fmod(num1, num2));
1261 }
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273