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