1/*
2   +----------------------------------------------------------------------+
3   | PHP Version 7                                                        |
4   +----------------------------------------------------------------------+
5   | Copyright (c) 1997-2016 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   | Authors: Jim Winstead <jimw@php.net>                                 |
16   |          Stig Sæther Bakken <ssb@php.net>                            |
17   |          Zeev Suraski <zeev@zend.com>                                |
18   | PHP 4.0 patches by Thies C. Arntzen <thies@thieso.net>               |
19   +----------------------------------------------------------------------+
20*/
21
22/* $Id$ */
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/* {{{ php_intlog10abs
36   Returns floor(log10(fabs(val))), uses fast binary search */
37static 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		/* Do a binary search with 5 steps */
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/* {{{ php_intpow10
81       Returns pow(10.0, (double)power), uses fast lookup table for exact powers */
82static 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	/* Not in lookup table */
89	if (power < 0 || power > 22) {
90		return pow(10.0, (double)power);
91	}
92	return powers[power];
93}
94/* }}} */
95
96/* {{{ php_math_is_finite */
97static 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/* {{{ php_round_helper
109       Actually performs the rounding of a value to integer in a certain mode */
110static 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/* {{{ _php_math_round */
136/*
137 * Rounds a number to a certain number of decimal places in a certain rounding
138 * mode. For the specifics of the algorithm, see http://wiki.php.net/rfc/rounding
139 */
140PHPAPI 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	/* If the decimal precision guaranteed by FP arithmetic is higher than
155	   the requested places BUT is small enough to make sure a non-zero value
156	   is returned, pre-round the result to the precision */
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		/* preround the result (tmp_value will always be something * 1e14,
167		   thus never larger than 1e15 here) */
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		/* now correctly move the decimal point */
173		f2 = php_intpow10(abs((int)use_precision));
174		/* because places < precision_places */
175		tmp_value = tmp_value / f2;
176	} else {
177		/* adjust the value */
178		if (places >= 0) {
179			tmp_value = value * f1;
180		} else {
181			tmp_value = value / f1;
182		}
183		/* This value is beyond our precision, so rounding it is pointless */
184		if (fabs(tmp_value) >= 1e15) {
185			return value;
186		}
187	}
188
189	/* round the temp value */
190	tmp_value = php_round_helper(tmp_value, mode);
191
192	/* see if it makes sense to use simple division to round the value */
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		/* Simple division can't be used since that will cause wrong results.
201		   Instead, the number is converted to a string and back again using
202		   strtod(). strtod() will return the nearest possible FP value for
203		   that string. */
204
205		/* 40 Bytes should be more than enough for this format string. The
206		   float won't be larger than 1e15 anyway. But just in case, use
207		   snprintf() and make sure the buffer is zero-terminated */
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		/* couldn't convert to string and back */
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/* {{{ php_asinh
223*/
224static 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/* {{{ php_acosh
244*/
245static 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/* {{{ php_atanh
264*/
265static 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/* {{{ php_log1p
276*/
277static 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/* {{{ php_expm1
288*/
289static 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/* {{{ proto int abs(int number)
300   Return the absolute value of the number */
301PHP_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/* {{{ proto float ceil(float number)
331   Returns the next highest integer value of the number */
332PHP_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/* {{{ proto float floor(float number)
358   Returns the next lowest integer value from the number */
359PHP_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/* {{{ proto float round(float number [, int precision [, int mode]])
385   Returns the number rounded to specified precision */
386PHP_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			/* Simple case - long that doesn't need to be rounded. */
414			if (places >= 0) {
415				RETURN_DOUBLE((double) Z_LVAL_P(value));
416			}
417			/* break omitted intentionally */
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/* {{{ proto float sin(float number)
433   Returns the sine of the number in radians */
434PHP_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/* {{{ proto float cos(float number)
452   Returns the cosine of the number in radians */
453PHP_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/* {{{ proto float tan(float number)
471   Returns the tangent of the number in radians */
472PHP_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/* {{{ proto float asin(float number)
490   Returns the arc sine of the number in radians */
491PHP_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/* {{{ proto float acos(float number)
509   Return the arc cosine of the number in radians */
510PHP_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/* {{{ proto float atan(float number)
528   Returns the arc tangent of the number in radians */
529PHP_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/* {{{ proto float atan2(float y, float x)
547   Returns the arc tangent of y/x, with the resulting quadrant determined by the signs of y and x */
548PHP_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/* {{{ proto float sinh(float number)
567   Returns the hyperbolic sine of the number, defined as (exp(number) - exp(-number))/2 */
568PHP_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/* {{{ proto float cosh(float number)
586   Returns the hyperbolic cosine of the number, defined as (exp(number) + exp(-number))/2 */
587PHP_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/* {{{ proto float tanh(float number)
605   Returns the hyperbolic tangent of the number, defined as sinh(number)/cosh(number) */
606PHP_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/* {{{ proto float asinh(float number)
624   Returns the inverse hyperbolic sine of the number, i.e. the value whose hyperbolic sine is number */
625PHP_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/* {{{ proto float acosh(float number)
643   Returns the inverse hyperbolic cosine of the number, i.e. the value whose hyperbolic cosine is number */
644PHP_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/* {{{ proto float atanh(float number)
662   Returns the inverse hyperbolic tangent of the number, i.e. the value whose hyperbolic tangent is number */
663PHP_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/* {{{ proto float pi(void)
681   Returns an approximation of pi */
682PHP_FUNCTION(pi)
683{
684	RETURN_DOUBLE(M_PI);
685}
686/* }}} */
687
688/* {{{ proto bool is_finite(float val)
689   Returns whether argument is finite */
690PHP_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/* {{{ proto bool is_infinite(float val)
708   Returns whether argument is infinite */
709PHP_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/* {{{ proto bool is_nan(float val)
727   Returns whether argument is not a number */
728PHP_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/* {{{ proto number pow(number base, number exponent)
746   Returns base raised to the power of exponent. Returns integer result when possible */
747PHP_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/* {{{ proto float exp(float number)
760   Returns e raised to the power of the number */
761PHP_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/* {{{ proto float expm1(float number)
780   Returns exp(number) - 1, computed in a way that accurate even when the value of number is close to zero */
781/*
782   WARNING: this function is expermental: it could change its name or
783   disappear in the next version of PHP!
784*/
785PHP_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/* {{{ proto float log1p(float number)
804   Returns log(1 + number), computed in a way that accurate even when the value of number is close to zero */
805/*
806   WARNING: this function is expermental: it could change its name or
807   disappear in the next version of PHP!
808*/
809PHP_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/* {{{ proto float log(float number, [float base])
828   Returns the natural logarithm of the number, or the base log if base is specified */
829PHP_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/* {{{ proto float log10(float number)
873   Returns the base-10 logarithm of the number */
874PHP_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/* {{{ proto float sqrt(float number)
893   Returns the square root of the number */
894PHP_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/* {{{ proto float hypot(float num1, float num2)
913   Returns sqrt(num1*num1 + num2*num2) */
914PHP_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/* {{{ proto float deg2rad(float number)
940   Converts the number in degrees to the radian equivalent */
941PHP_FUNCTION(deg2rad)
942{
943	double deg;
944
945#ifndef FAST_ZPP
946	if (zend_parse_parameters(ZEND_NUM_ARGS(), "d", &deg) == 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/* {{{ proto float rad2deg(float number)
959   Converts the radian number to the equivalent number in degrees */
960PHP_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/* {{{ _php_math_basetolong */
979/*
980 * Convert a string representation of a base(2-36) number to a long.
981 */
982PHPAPI 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/* {{{ _php_math_basetozval */
1023/*
1024 * Convert a string representation of a base(2-36) number to a zval.
1025 */
1026PHPAPI 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		/* might not work for EBCDIC */
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: /* Integer */
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			/* fall-through */
1071		case 1: /* Float */
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/* {{{ _php_math_longtobase */
1086/*
1087 * Convert a long to a string containing a base(2-36) representation of
1088 * the number.
1089 */
1090PHPAPI 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/* {{{ _php_math_zvaltobase */
1116/*
1117 * Convert a zval to a string containing a base(2-36) representation of
1118 * the number.
1119 */
1120PHPAPI 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)); /* floor it just in case */
1130		char *ptr, *end;
1131		char buf[(sizeof(double) << 3) + 1];
1132
1133		/* Don't try to convert +/- infinity */
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/* {{{ proto int bindec(string binary_number)
1155   Returns the decimal equivalent of the binary number */
1156PHP_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/* {{{ proto int hexdec(string hexadecimal_number)
1171   Returns the decimal equivalent of the hexadecimal number */
1172PHP_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/* {{{ proto int octdec(string octal_number)
1187   Returns the decimal equivalent of an octal string */
1188PHP_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/* {{{ proto string decbin(int decimal_number)
1203   Returns a string containing a binary representation of the number */
1204PHP_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/* {{{ proto string decoct(int decimal_number)
1219   Returns a string containing an octal representation of the given number */
1220PHP_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/* {{{ proto string dechex(int decimal_number)
1235   Returns a string containing a hexadecimal representation of the given number */
1236PHP_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/* {{{ proto string base_convert(string number, int frombase, int tobase)
1251   Converts a number in a string from any base <= 36 to any base <= 36 */
1252PHP_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/* {{{ _php_math_number_format
1281*/
1282PHPAPI 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
1287PHPAPI 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;  /* source, target */
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	/* find decimal point, if expected */
1314	if (dec) {
1315		dp = strpbrk(ZSTR_VAL(tmpbuf), ".,");
1316	} else {
1317		dp = NULL;
1318	}
1319
1320	/* calculate the length of the return buffer */
1321	if (dp) {
1322		integral = (int)(dp - ZSTR_VAL(tmpbuf));
1323	} else {
1324		/* no decimal point was found */
1325		integral = (int)ZSTR_LEN(tmpbuf);
1326	}
1327
1328	/* allow for thousand separators */
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	/* add a byte for minus sign */
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	/* copy the decimal places.
1354	 * Take care, as the sprintf implementation may return less places than
1355	 * we requested due to internal buffer limitations */
1356	if (dec) {
1357		int declen = (int)(dp ? s - dp : 0);
1358		int topad = dec > declen ? dec - declen : 0;
1359
1360		/* pad with '0's */
1361		while (topad--) {
1362			*t-- = '0';
1363		}
1364
1365		if (dp) {
1366			s -= declen + 1; /* +1 to skip the point */
1367			t -= declen;
1368
1369			/* now copy the chars after the point */
1370			memcpy(t + 1, dp + 1, declen);
1371		}
1372
1373		/* add decimal point */
1374		if (dec_point) {
1375			t -= dec_point_len;
1376			memcpy(t + 1, dec_point, dec_point_len);
1377		}
1378	}
1379
1380	/* copy the numbers before the decimal point, adding thousand
1381	 * separator every three digits */
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	/* and a minus sign, if needed */
1391	if (is_negative) {
1392		*t-- = '-';
1393	}
1394
1395	ZSTR_LEN(res) = reslen;
1396	zend_string_release(tmpbuf);
1397	return res;
1398}
1399
1400/* {{{ proto string number_format(float number [, int num_decimal_places [, string dec_separator, string thousands_separator]])
1401   Formats a number with grouped thousands */
1402PHP_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/* {{{ proto float fmod(float x, float y)
1453   Returns the remainder of dividing x by y as a float */
1454PHP_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/* {{{ proto int intdiv(int dividend, int divisor)
1474   Returns the integer quotient of the division of dividend by divisor */
1475PHP_FUNCTION(intdiv)
1476{
1477	zend_long dividend, divisor;
1478
1479	if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &dividend, &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		/* Prevent overflow error/crash ... really should not happen:
1488		   We don't return a float here as that violates function contract */
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 * Local variables:
1499 * tab-width: 4
1500 * c-basic-offset: 4
1501 * End:
1502 * vim600: fdm=marker
1503 * vim: noet sw=4 ts=4
1504 */
1505