Annotation of embedaddon/php/ext/standard/math.c, revision 1.1

1.1     ! misho       1: /*
        !             2:    +----------------------------------------------------------------------+
        !             3:    | PHP Version 5                                                        |
        !             4:    +----------------------------------------------------------------------+
        !             5:    | Copyright (c) 1997-2012 The PHP Group                                |
        !             6:    +----------------------------------------------------------------------+
        !             7:    | This source file is subject to version 3.01 of the PHP license,      |
        !             8:    | that is bundled with this package in the file LICENSE, and is        |
        !             9:    | available through the world-wide-web at the following url:           |
        !            10:    | http://www.php.net/license/3_01.txt                                  |
        !            11:    | If you did not receive a copy of the PHP license and are unable to   |
        !            12:    | obtain it through the world-wide-web, please send a note to          |
        !            13:    | license@php.net so we can mail you a copy immediately.               |
        !            14:    +----------------------------------------------------------------------+
        !            15:    | 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: math.c 321634 2012-01-01 13:15:04Z felipe $ */
        !            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: /* {{{ php_intlog10abs
        !            35:    Returns floor(log10(fabs(val))), uses fast binary search */
        !            36: static inline int php_intlog10abs(double value) {
        !            37:        int result;
        !            38:        value = fabs(value);
        !            39: 
        !            40:        if (value < 1e-8 || value > 1e23) {
        !            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:                /* Do a binary search with 5 steps */
        !            49:                result = 16;
        !            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: /* {{{ php_intpow10
        !            80:        Returns pow(10.0, (double)power), uses fast lookup table for exact powers */
        !            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:        /* Not in lookup table */
        !            88:        if (power < 0 || power > 22) {
        !            89:                return pow(10.0, (double)power);
        !            90:        }
        !            91:        return powers[power];
        !            92: }
        !            93: /* }}} */
        !            94: 
        !            95: /* {{{ php_math_is_finite */
        !            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: /* {{{ php_round_helper
        !           108:        Actually performs the rounding of a value to integer in a certain mode */
        !           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: /* {{{ _php_math_round */
        !           135: /*
        !           136:  * Rounds a number to a certain number of decimal places in a certain rounding
        !           137:  * mode. For the specifics of the algorithm, see http://wiki.php.net/rfc/rounding
        !           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:        precision_places = 14 - php_intlog10abs(value);
        !           149: 
        !           150:        f1 = php_intpow10(abs(places));
        !           151: 
        !           152:        /* If the decimal precision guaranteed by FP arithmetic is higher than
        !           153:           the requested places BUT is small enough to make sure a non-zero value
        !           154:           is returned, pre-round the result to the precision */
        !           155:        if (precision_places > places && precision_places - places < 15) {
        !           156:                f2 = php_intpow10(abs(precision_places));
        !           157:                if (precision_places >= 0) {
        !           158:                        tmp_value = value * f2;
        !           159:                } else {
        !           160:                        tmp_value = value / f2;
        !           161:                }
        !           162:                /* preround the result (tmp_value will always be something * 1e14,
        !           163:                   thus never larger than 1e15 here) */
        !           164:                tmp_value = php_round_helper(tmp_value, mode);
        !           165:                /* now correctly move the decimal point */
        !           166:                f2 = php_intpow10(abs(places - precision_places));
        !           167:                /* because places < precision_places */
        !           168:                tmp_value = tmp_value / f2;
        !           169:        } else {
        !           170:                /* adjust the value */
        !           171:                if (places >= 0) {
        !           172:                        tmp_value = value * f1;
        !           173:                } else {
        !           174:                        tmp_value = value / f1;
        !           175:                }
        !           176:                /* This value is beyond our precision, so rounding it is pointless */
        !           177:                if (fabs(tmp_value) >= 1e15) {
        !           178:                        return value;
        !           179:                }
        !           180:        }
        !           181: 
        !           182:        /* round the temp value */
        !           183:        tmp_value = php_round_helper(tmp_value, mode);
        !           184:        
        !           185:        /* see if it makes sense to use simple division to round the value */
        !           186:        if (abs(places) < 23) {
        !           187:                if (places > 0) {
        !           188:                        tmp_value = tmp_value / f1;
        !           189:                } else {
        !           190:                        tmp_value = tmp_value * f1;
        !           191:                }
        !           192:        } else {
        !           193:                /* Simple division can't be used since that will cause wrong results.
        !           194:                   Instead, the number is converted to a string and back again using
        !           195:                   strtod(). strtod() will return the nearest possible FP value for
        !           196:                   that string. */
        !           197: 
        !           198:                /* 40 Bytes should be more than enough for this format string. The
        !           199:                   float won't be larger than 1e15 anyway. But just in case, use
        !           200:                   snprintf() and make sure the buffer is zero-terminated */
        !           201:                char buf[40];
        !           202:                snprintf(buf, 39, "%15fe%d", tmp_value, -places);
        !           203:                buf[39] = '\0';
        !           204:                tmp_value = zend_strtod(buf, NULL);
        !           205:                /* couldn't convert to string and back */
        !           206:                if (!zend_finite(tmp_value) || zend_isnan(tmp_value)) {
        !           207:                        tmp_value = value;
        !           208:                }
        !           209:        }
        !           210: 
        !           211:        return tmp_value;
        !           212: }
        !           213: /* }}} */
        !           214: 
        !           215: /* {{{ php_asinh
        !           216: */
        !           217: static double php_asinh(double z)
        !           218: {
        !           219: #ifdef HAVE_ASINH
        !           220:        return(asinh(z));
        !           221: #else
        !           222:        return(log(z + sqrt(1 + pow(z, 2))) / log(M_E));
        !           223: #endif
        !           224: }
        !           225: /* }}} */
        !           226: 
        !           227: /* {{{ php_acosh
        !           228: */
        !           229: static double php_acosh(double x)
        !           230: {
        !           231: #ifdef HAVE_ACOSH
        !           232:        return(acosh(x));
        !           233: #else
        !           234:        return(log(x + sqrt(x * x - 1)));
        !           235: #endif
        !           236: }
        !           237: /* }}} */
        !           238: 
        !           239: /* {{{ php_atanh
        !           240: */
        !           241: static double php_atanh(double z)
        !           242: {
        !           243: #ifdef HAVE_ATANH
        !           244:        return(atanh(z));
        !           245: #else
        !           246:        return(0.5 * log((1 + z) / (1 - z)));
        !           247: #endif
        !           248: }
        !           249: /* }}} */
        !           250: 
        !           251: /* {{{ php_log1p
        !           252: */
        !           253: static double php_log1p(double x)
        !           254: {
        !           255: #ifdef HAVE_LOG1P
        !           256:        return(log1p(x));
        !           257: #else
        !           258:        return(log(1 + x));
        !           259: #endif
        !           260: }
        !           261: /* }}} */
        !           262: 
        !           263: /* {{{ php_expm1
        !           264: */
        !           265: static double php_expm1(double x)
        !           266: {
        !           267: #if !defined(PHP_WIN32) && !defined(NETWARE)
        !           268:        return(expm1(x));
        !           269: #else
        !           270:        return(exp(x) - 1);
        !           271: #endif
        !           272: }
        !           273: /* }}}*/
        !           274: 
        !           275: /* {{{ proto int abs(int number)
        !           276:    Return the absolute value of the number */
        !           277: PHP_FUNCTION(abs) 
        !           278: {
        !           279:        zval **value;
        !           280:        
        !           281:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &value) == FAILURE) {
        !           282:                return;
        !           283:        }
        !           284:        convert_scalar_to_number_ex(value);
        !           285:        
        !           286:        if (Z_TYPE_PP(value) == IS_DOUBLE) {
        !           287:                RETURN_DOUBLE(fabs(Z_DVAL_PP(value)));
        !           288:        } else if (Z_TYPE_PP(value) == IS_LONG) {
        !           289:                if (Z_LVAL_PP(value) == LONG_MIN) {
        !           290:                        RETURN_DOUBLE(-(double)LONG_MIN);
        !           291:                } else {
        !           292:                        RETURN_LONG(Z_LVAL_PP(value) < 0 ? -Z_LVAL_PP(value) : Z_LVAL_PP(value));
        !           293:                }
        !           294:        }
        !           295:        RETURN_FALSE;
        !           296: }
        !           297: /* }}} */ 
        !           298: 
        !           299: /* {{{ proto float ceil(float number)
        !           300:    Returns the next highest integer value of the number */
        !           301: PHP_FUNCTION(ceil) 
        !           302: {
        !           303:        zval **value;
        !           304:        
        !           305:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &value) == FAILURE) {
        !           306:                return;
        !           307:        }
        !           308:        convert_scalar_to_number_ex(value);
        !           309: 
        !           310:        if (Z_TYPE_PP(value) == IS_DOUBLE) {
        !           311:                RETURN_DOUBLE(ceil(Z_DVAL_PP(value)));
        !           312:        } else if (Z_TYPE_PP(value) == IS_LONG) {
        !           313:                convert_to_double_ex(value);
        !           314:                RETURN_DOUBLE(Z_DVAL_PP(value));
        !           315:        }
        !           316:        RETURN_FALSE;
        !           317: }
        !           318: /* }}} */
        !           319: 
        !           320: /* {{{ proto float floor(float number)
        !           321:    Returns the next lowest integer value from the number */
        !           322: PHP_FUNCTION(floor)
        !           323: {
        !           324:        zval **value;
        !           325:        
        !           326:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &value) == FAILURE) {
        !           327:                return;
        !           328:        }
        !           329:        convert_scalar_to_number_ex(value);
        !           330: 
        !           331:        if (Z_TYPE_PP(value) == IS_DOUBLE) {
        !           332:                RETURN_DOUBLE(floor(Z_DVAL_PP(value)));
        !           333:        } else if (Z_TYPE_PP(value) == IS_LONG) {
        !           334:                convert_to_double_ex(value);
        !           335:                RETURN_DOUBLE(Z_DVAL_PP(value));
        !           336:        }
        !           337:        RETURN_FALSE;
        !           338: }
        !           339: /* }}} */
        !           340: 
        !           341: /* {{{ proto float round(float number [, int precision [, int mode]])
        !           342:    Returns the number rounded to specified precision */
        !           343: PHP_FUNCTION(round)
        !           344: {
        !           345:        zval **value;
        !           346:        int places = 0;
        !           347:        long precision = 0;
        !           348:        long mode = PHP_ROUND_HALF_UP;
        !           349:        double return_val;
        !           350:        
        !           351:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|ll", &value, &precision, &mode) == FAILURE) {
        !           352:                return;
        !           353:        }
        !           354: 
        !           355:        if (ZEND_NUM_ARGS() >= 2) {
        !           356:                places = (int) precision;
        !           357:        }
        !           358:        convert_scalar_to_number_ex(value);
        !           359: 
        !           360:        switch (Z_TYPE_PP(value)) {
        !           361:                case IS_LONG:
        !           362:                        /* Simple case - long that doesn't need to be rounded. */
        !           363:                        if (places >= 0) {
        !           364:                                RETURN_DOUBLE((double) Z_LVAL_PP(value));
        !           365:                        }
        !           366:                        /* break omitted intentionally */
        !           367: 
        !           368:                case IS_DOUBLE:
        !           369:                        return_val = (Z_TYPE_PP(value) == IS_LONG) ? (double)Z_LVAL_PP(value) : Z_DVAL_PP(value);
        !           370:                        return_val = _php_math_round(return_val, places, mode);
        !           371:                        RETURN_DOUBLE(return_val);
        !           372:                        break;
        !           373: 
        !           374:                default:
        !           375:                        RETURN_FALSE;
        !           376:                        break;
        !           377:        }
        !           378: }
        !           379: /* }}} */
        !           380: 
        !           381: /* {{{ proto float sin(float number)
        !           382:    Returns the sine of the number in radians */
        !           383: PHP_FUNCTION(sin)
        !           384: {
        !           385:        double num;
        !           386: 
        !           387:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           388:                return;
        !           389:        }
        !           390:        RETURN_DOUBLE(sin(num));
        !           391: }
        !           392: /* }}} */
        !           393: 
        !           394: /* {{{ proto float cos(float number)
        !           395:    Returns the cosine of the number in radians */
        !           396: PHP_FUNCTION(cos)
        !           397: {
        !           398:        double num;
        !           399:        
        !           400:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           401:                return;
        !           402:        }
        !           403:        RETURN_DOUBLE(cos(num));
        !           404: }
        !           405: /* }}} */
        !           406: 
        !           407: /* {{{ proto float tan(float number)
        !           408:    Returns the tangent of the number in radians */
        !           409: PHP_FUNCTION(tan)
        !           410: {
        !           411:        double num;
        !           412: 
        !           413:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           414:                return;
        !           415:        }
        !           416:        RETURN_DOUBLE(tan(num));
        !           417: }
        !           418: /* }}} */
        !           419: 
        !           420: /* {{{ proto float asin(float number)
        !           421:    Returns the arc sine of the number in radians */
        !           422: PHP_FUNCTION(asin)
        !           423: {
        !           424:        double num;
        !           425: 
        !           426:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           427:                return;
        !           428:        }
        !           429:        RETURN_DOUBLE(asin(num));
        !           430: }
        !           431: /* }}} */
        !           432: 
        !           433: /* {{{ proto float acos(float number)
        !           434:    Return the arc cosine of the number in radians */
        !           435: PHP_FUNCTION(acos)
        !           436: {
        !           437:        double num;
        !           438: 
        !           439:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           440:                return;
        !           441:        }
        !           442:        RETURN_DOUBLE(acos(num));
        !           443: }
        !           444: /* }}} */
        !           445: 
        !           446: /* {{{ proto float atan(float number)
        !           447:    Returns the arc tangent of the number in radians */
        !           448: PHP_FUNCTION(atan)
        !           449: {
        !           450:        double num;
        !           451: 
        !           452:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           453:                return;
        !           454:        }
        !           455:        RETURN_DOUBLE(atan(num));
        !           456: }
        !           457: /* }}} */
        !           458: 
        !           459: /* {{{ proto float atan2(float y, float x)
        !           460:    Returns the arc tangent of y/x, with the resulting quadrant determined by the signs of y and x */
        !           461: PHP_FUNCTION(atan2)
        !           462: {
        !           463:        double num1, num2;
        !           464: 
        !           465:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &num1, &num2) == FAILURE) {
        !           466:                return;
        !           467:        }
        !           468:        RETURN_DOUBLE(atan2(num1, num2));
        !           469: }
        !           470: /* }}} */
        !           471: 
        !           472: /* {{{ proto float sinh(float number)
        !           473:    Returns the hyperbolic sine of the number, defined as (exp(number) - exp(-number))/2 */
        !           474: PHP_FUNCTION(sinh)
        !           475: {
        !           476:        double num;
        !           477: 
        !           478:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           479:                return;
        !           480:        }
        !           481:        RETURN_DOUBLE(sinh(num));
        !           482: }
        !           483: /* }}} */
        !           484: 
        !           485: /* {{{ proto float cosh(float number)
        !           486:    Returns the hyperbolic cosine of the number, defined as (exp(number) + exp(-number))/2 */
        !           487: PHP_FUNCTION(cosh)
        !           488: {
        !           489:        double num;
        !           490: 
        !           491:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           492:                return;
        !           493:        }
        !           494:        RETURN_DOUBLE(cosh(num));
        !           495: }
        !           496: /* }}} */
        !           497: 
        !           498: /* {{{ proto float tanh(float number)
        !           499:    Returns the hyperbolic tangent of the number, defined as sinh(number)/cosh(number) */
        !           500: PHP_FUNCTION(tanh)
        !           501: {
        !           502:        double num;
        !           503: 
        !           504:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           505:                return;
        !           506:        }
        !           507:        RETURN_DOUBLE(tanh(num));
        !           508: }
        !           509: /* }}} */
        !           510: 
        !           511: /* {{{ proto float asinh(float number)
        !           512:    Returns the inverse hyperbolic sine of the number, i.e. the value whose hyperbolic sine is number */
        !           513: PHP_FUNCTION(asinh)
        !           514: {
        !           515:        double num;
        !           516: 
        !           517:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           518:                return;
        !           519:        }
        !           520:        RETURN_DOUBLE(php_asinh(num));
        !           521: }
        !           522: /* }}} */
        !           523: 
        !           524: /* {{{ proto float acosh(float number)
        !           525:    Returns the inverse hyperbolic cosine of the number, i.e. the value whose hyperbolic cosine is number */
        !           526: PHP_FUNCTION(acosh)
        !           527: {
        !           528:        double num;
        !           529:        
        !           530:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           531:                return;
        !           532:        }
        !           533:        RETURN_DOUBLE(php_acosh(num));
        !           534: }
        !           535: /* }}} */
        !           536: 
        !           537: /* {{{ proto float atanh(float number)
        !           538:    Returns the inverse hyperbolic tangent of the number, i.e. the value whose hyperbolic tangent is number */
        !           539: PHP_FUNCTION(atanh)
        !           540: {
        !           541:        double num;
        !           542: 
        !           543:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           544:                return;
        !           545:        }
        !           546:        RETURN_DOUBLE(php_atanh(num));
        !           547: }
        !           548: /* }}} */
        !           549: 
        !           550: /* {{{ proto float pi(void)
        !           551:    Returns an approximation of pi */
        !           552: PHP_FUNCTION(pi)
        !           553: {
        !           554:        RETURN_DOUBLE(M_PI);
        !           555: }
        !           556: /* }}} */
        !           557: 
        !           558: /* {{{ proto bool is_finite(float val)
        !           559:    Returns whether argument is finite */
        !           560: PHP_FUNCTION(is_finite)
        !           561: {
        !           562:        double dval;
        !           563: 
        !           564:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
        !           565:                return;
        !           566:        }
        !           567:        RETURN_BOOL(zend_finite(dval));
        !           568: }
        !           569: /* }}} */
        !           570: 
        !           571: /* {{{ proto bool is_infinite(float val)
        !           572:    Returns whether argument is infinite */
        !           573: PHP_FUNCTION(is_infinite)
        !           574: {
        !           575:        double dval;
        !           576: 
        !           577:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
        !           578:                return;
        !           579:        }
        !           580:        RETURN_BOOL(zend_isinf(dval));
        !           581: }
        !           582: /* }}} */
        !           583: 
        !           584: /* {{{ proto bool is_nan(float val)
        !           585:    Returns whether argument is not a number */
        !           586: PHP_FUNCTION(is_nan)
        !           587: {
        !           588:        double dval;
        !           589: 
        !           590:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &dval) == FAILURE) {
        !           591:                return;
        !           592:        }
        !           593:        RETURN_BOOL(zend_isnan(dval));
        !           594: }
        !           595: /* }}} */
        !           596: 
        !           597: /* {{{ proto number pow(number base, number exponent)
        !           598:    Returns base raised to the power of exponent. Returns integer result when possible */
        !           599: PHP_FUNCTION(pow)
        !           600: {
        !           601:        zval *zbase, *zexp;
        !           602: 
        !           603:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z/z/", &zbase, &zexp) == FAILURE) {
        !           604:                return;
        !           605:        }
        !           606: 
        !           607:        /* make sure we're dealing with numbers */
        !           608:        convert_scalar_to_number(zbase TSRMLS_CC);
        !           609:        convert_scalar_to_number(zexp TSRMLS_CC);
        !           610: 
        !           611:        /* if both base and exponent were longs, we'll try to get a long out */
        !           612:        if (Z_TYPE_P(zbase) == IS_LONG && Z_TYPE_P(zexp) == IS_LONG && Z_LVAL_P(zexp) >= 0) {
        !           613:                long l1 = 1, l2 = Z_LVAL_P(zbase), i = Z_LVAL_P(zexp);
        !           614:                
        !           615:                if (i == 0) {
        !           616:                        RETURN_LONG(1L);
        !           617:                } else if (l2 == 0) {
        !           618:                        RETURN_LONG(0);
        !           619:                }
        !           620: 
        !           621:                /* calculate pow(long,long) in O(log exp) operations, bail if overflow */
        !           622:                while (i >= 1) {
        !           623:                        int overflow;
        !           624:                        double dval = 0.0;
        !           625: 
        !           626:                        if (i % 2) {
        !           627:                                --i;
        !           628:                                ZEND_SIGNED_MULTIPLY_LONG(l1,l2,l1,dval,overflow);
        !           629:                                if (overflow) RETURN_DOUBLE(dval * pow(l2,i));
        !           630:                        } else {
        !           631:                                i /= 2;
        !           632:                                ZEND_SIGNED_MULTIPLY_LONG(l2,l2,l2,dval,overflow);
        !           633:                                if (overflow) RETURN_DOUBLE((double)l1 * pow(dval,i));
        !           634:                        }
        !           635:                        if (i == 0) {
        !           636:                                RETURN_LONG(l1);
        !           637:                        }
        !           638:                }
        !           639:        }
        !           640:        convert_to_double(zbase);
        !           641:        convert_to_double(zexp);
        !           642:        
        !           643:        RETURN_DOUBLE(pow(Z_DVAL_P(zbase), Z_DVAL_P(zexp)));
        !           644: }
        !           645: /* }}} */
        !           646: 
        !           647: /* {{{ proto float exp(float number)
        !           648:    Returns e raised to the power of the number */
        !           649: PHP_FUNCTION(exp)
        !           650: {
        !           651:        double num;
        !           652: 
        !           653:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           654:                return;
        !           655:        }
        !           656: 
        !           657:        RETURN_DOUBLE(exp(num));
        !           658: }
        !           659: /* }}} */
        !           660: 
        !           661: /* {{{ proto float expm1(float number)
        !           662:    Returns exp(number) - 1, computed in a way that accurate even when the value of number is close to zero */
        !           663: /*
        !           664:    WARNING: this function is expermental: it could change its name or 
        !           665:    disappear in the next version of PHP!
        !           666: */
        !           667: PHP_FUNCTION(expm1)
        !           668: {
        !           669:        double num;
        !           670: 
        !           671:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           672:                return;
        !           673:        }
        !           674:        RETURN_DOUBLE(php_expm1(num));
        !           675: }
        !           676: /* }}} */
        !           677: 
        !           678: /* {{{ proto float log1p(float number)
        !           679:    Returns log(1 + number), computed in a way that accurate even when the value of number is close to zero */ 
        !           680: /*
        !           681:    WARNING: this function is expermental: it could change its name or 
        !           682:    disappear in the next version of PHP!
        !           683: */
        !           684: PHP_FUNCTION(log1p)
        !           685: {
        !           686:        double num;
        !           687: 
        !           688:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           689:                return;
        !           690:        }
        !           691:        RETURN_DOUBLE(php_log1p(num));
        !           692: }
        !           693: /* }}} */
        !           694: 
        !           695: /* {{{ proto float log(float number, [float base])
        !           696:    Returns the natural logarithm of the number, or the base log if base is specified */
        !           697: PHP_FUNCTION(log)
        !           698: {
        !           699:        double num, base = 0;
        !           700:        
        !           701:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d|d", &num, &base) == FAILURE) {
        !           702:                return;
        !           703:        }
        !           704:        if (ZEND_NUM_ARGS() == 1) {
        !           705:                RETURN_DOUBLE(log(num));
        !           706:        }
        !           707:        if (base <= 0.0) {
        !           708:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "base must be greater than 0");                             
        !           709:                RETURN_FALSE;
        !           710:        }
        !           711:        if (base == 1) {
        !           712:                RETURN_DOUBLE(php_get_nan());
        !           713:        } else {
        !           714:                RETURN_DOUBLE(log(num) / log(base));
        !           715:        }
        !           716: }
        !           717: /* }}} */
        !           718: 
        !           719: /* {{{ proto float log10(float number)
        !           720:    Returns the base-10 logarithm of the number */
        !           721: PHP_FUNCTION(log10)
        !           722: {
        !           723:        double num;
        !           724: 
        !           725:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           726:                return;
        !           727:        }
        !           728:        RETURN_DOUBLE(log10(num));
        !           729: }
        !           730: /* }}} */
        !           731: 
        !           732: /* {{{ proto float sqrt(float number)
        !           733:    Returns the square root of the number */
        !           734: PHP_FUNCTION(sqrt)
        !           735: {
        !           736:        double num;
        !           737: 
        !           738:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &num) == FAILURE) {
        !           739:                return;
        !           740:        }
        !           741:        RETURN_DOUBLE(sqrt(num));
        !           742: }
        !           743: /* }}} */
        !           744: 
        !           745: /* {{{ proto float hypot(float num1, float num2)
        !           746:    Returns sqrt(num1*num1 + num2*num2) */ 
        !           747: PHP_FUNCTION(hypot)
        !           748: {
        !           749:        double num1, num2;
        !           750: 
        !           751:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd", &num1, &num2) == FAILURE) {
        !           752:                return;
        !           753:        }
        !           754: #if HAVE_HYPOT
        !           755:        RETURN_DOUBLE(hypot(num1, num2));
        !           756: #elif defined(_MSC_VER)
        !           757:        RETURN_DOUBLE(_hypot(num1, num2));
        !           758: #else
        !           759:        RETURN_DOUBLE(sqrt((num1 * num1) + (num2 * num2)));
        !           760: #endif
        !           761: }
        !           762: /* }}} */
        !           763: 
        !           764: /* {{{ proto float deg2rad(float number)
        !           765:    Converts the number in degrees to the radian equivalent */
        !           766: PHP_FUNCTION(deg2rad)
        !           767: {
        !           768:        double deg;
        !           769: 
        !           770:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &deg) == FAILURE) {
        !           771:                return;
        !           772:        }
        !           773:        RETURN_DOUBLE((deg / 180.0) * M_PI);
        !           774: }
        !           775: /* }}} */
        !           776: 
        !           777: /* {{{ proto float rad2deg(float number)
        !           778:    Converts the radian number to the equivalent number in degrees */
        !           779: PHP_FUNCTION(rad2deg)
        !           780: {
        !           781:        double rad;
        !           782: 
        !           783:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &rad) == FAILURE) {
        !           784:                return;
        !           785:        }
        !           786:        RETURN_DOUBLE((rad / M_PI) * 180);
        !           787: }
        !           788: /* }}} */
        !           789: 
        !           790: /* {{{ _php_math_basetolong */
        !           791: /*
        !           792:  * Convert a string representation of a base(2-36) number to a long.
        !           793:  */
        !           794: PHPAPI long _php_math_basetolong(zval *arg, int base)
        !           795: {
        !           796:        long num = 0, digit, onum;
        !           797:        int i;
        !           798:        char c, *s;
        !           799: 
        !           800:        if (Z_TYPE_P(arg) != IS_STRING || base < 2 || base > 36) {
        !           801:                return 0;
        !           802:        }
        !           803: 
        !           804:        s = Z_STRVAL_P(arg);
        !           805: 
        !           806:        for (i = Z_STRLEN_P(arg); i > 0; i--) {
        !           807:                c = *s++;
        !           808:                
        !           809:                digit = (c >= '0' && c <= '9') ? c - '0'
        !           810:                        : (c >= 'A' && c <= 'Z') ? c - 'A' + 10
        !           811:                        : (c >= 'a' && c <= 'z') ? c - 'a' + 10
        !           812:                        : base;
        !           813:                
        !           814:                if (digit >= base) {
        !           815:                        continue;
        !           816:                }
        !           817: 
        !           818:                onum = num;
        !           819:                num = num * base + digit;
        !           820:                if (num > onum)
        !           821:                        continue;
        !           822: 
        !           823:                {
        !           824:                        TSRMLS_FETCH();
        !           825: 
        !           826:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number '%s' is too big to fit in long", s);
        !           827:                        return LONG_MAX;
        !           828:                }
        !           829:        }
        !           830: 
        !           831:        return num;
        !           832: }
        !           833: /* }}} */
        !           834: 
        !           835: /* {{{ _php_math_basetozval */
        !           836: /*
        !           837:  * Convert a string representation of a base(2-36) number to a zval.
        !           838:  */
        !           839: PHPAPI int _php_math_basetozval(zval *arg, int base, zval *ret)
        !           840: {
        !           841:        long num = 0;
        !           842:        double fnum = 0;
        !           843:        int i;
        !           844:        int mode = 0;
        !           845:        char c, *s;
        !           846:        long cutoff;
        !           847:        int cutlim;
        !           848: 
        !           849:        if (Z_TYPE_P(arg) != IS_STRING || base < 2 || base > 36) {
        !           850:                return FAILURE;
        !           851:        }
        !           852: 
        !           853:        s = Z_STRVAL_P(arg);
        !           854: 
        !           855:        cutoff = LONG_MAX / base;
        !           856:        cutlim = LONG_MAX % base;
        !           857:        
        !           858:        for (i = Z_STRLEN_P(arg); i > 0; i--) {
        !           859:                c = *s++;
        !           860: 
        !           861:                /* might not work for EBCDIC */
        !           862:                if (c >= '0' && c <= '9') 
        !           863:                        c -= '0';
        !           864:                else if (c >= 'A' && c <= 'Z') 
        !           865:                        c -= 'A' - 10;
        !           866:                else if (c >= 'a' && c <= 'z') 
        !           867:                        c -= 'a' - 10;
        !           868:                else
        !           869:                        continue;
        !           870: 
        !           871:                if (c >= base)
        !           872:                        continue;
        !           873:                
        !           874:                switch (mode) {
        !           875:                case 0: /* Integer */
        !           876:                        if (num < cutoff || (num == cutoff && c <= cutlim)) {
        !           877:                                num = num * base + c;
        !           878:                                break;
        !           879:                        } else {
        !           880:                                fnum = num;
        !           881:                                mode = 1;
        !           882:                        }
        !           883:                        /* fall-through */
        !           884:                case 1: /* Float */
        !           885:                        fnum = fnum * base + c;
        !           886:                }       
        !           887:        }
        !           888: 
        !           889:        if (mode == 1) {
        !           890:                ZVAL_DOUBLE(ret, fnum);
        !           891:        } else {
        !           892:                ZVAL_LONG(ret, num);
        !           893:        }
        !           894:        return SUCCESS;
        !           895: }
        !           896: /* }}} */
        !           897: 
        !           898: /* {{{ _php_math_longtobase */
        !           899: /*
        !           900:  * Convert a long to a string containing a base(2-36) representation of
        !           901:  * the number.
        !           902:  */
        !           903: PHPAPI char * _php_math_longtobase(zval *arg, int base)
        !           904: {
        !           905:        static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
        !           906:        char buf[(sizeof(unsigned long) << 3) + 1];
        !           907:        char *ptr, *end;
        !           908:        unsigned long value;
        !           909: 
        !           910:        if (Z_TYPE_P(arg) != IS_LONG || base < 2 || base > 36) {
        !           911:                return STR_EMPTY_ALLOC();
        !           912:        }
        !           913: 
        !           914:        value = Z_LVAL_P(arg);
        !           915: 
        !           916:        end = ptr = buf + sizeof(buf) - 1;
        !           917:        *ptr = '\0';
        !           918: 
        !           919:        do {
        !           920:                *--ptr = digits[value % base];
        !           921:                value /= base;
        !           922:        } while (ptr > buf && value);
        !           923: 
        !           924:        return estrndup(ptr, end - ptr);
        !           925: }
        !           926: /* }}} */
        !           927: 
        !           928: /* {{{ _php_math_zvaltobase */
        !           929: /*
        !           930:  * Convert a zval to a string containing a base(2-36) representation of
        !           931:  * the number.
        !           932:  */
        !           933: PHPAPI char * _php_math_zvaltobase(zval *arg, int base TSRMLS_DC)
        !           934: {
        !           935:        static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
        !           936: 
        !           937:        if ((Z_TYPE_P(arg) != IS_LONG && Z_TYPE_P(arg) != IS_DOUBLE) || base < 2 || base > 36) {
        !           938:                return STR_EMPTY_ALLOC();
        !           939:        }
        !           940: 
        !           941:        if (Z_TYPE_P(arg) == IS_DOUBLE) {
        !           942:                double fvalue = floor(Z_DVAL_P(arg)); /* floor it just in case */
        !           943:                char *ptr, *end;
        !           944:                char buf[(sizeof(double) << 3) + 1];
        !           945: 
        !           946:                /* Don't try to convert +/- infinity */
        !           947:                if (fvalue == HUGE_VAL || fvalue == -HUGE_VAL) {
        !           948:                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number too large");
        !           949:                        return STR_EMPTY_ALLOC();
        !           950:                }
        !           951: 
        !           952:                end = ptr = buf + sizeof(buf) - 1;
        !           953:                *ptr = '\0';
        !           954: 
        !           955:                do {
        !           956:                        *--ptr = digits[(int) fmod(fvalue, base)];
        !           957:                        fvalue /= base;
        !           958:                } while (ptr > buf && fabs(fvalue) >= 1);
        !           959: 
        !           960:                return estrndup(ptr, end - ptr);
        !           961:        }
        !           962:        
        !           963:        return _php_math_longtobase(arg, base);
        !           964: }      
        !           965: /* }}} */
        !           966: 
        !           967: /* {{{ proto int bindec(string binary_number)
        !           968:    Returns the decimal equivalent of the binary number */
        !           969: PHP_FUNCTION(bindec)
        !           970: {
        !           971:        zval **arg;
        !           972:        
        !           973:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
        !           974:                return;
        !           975:        }
        !           976:        convert_to_string_ex(arg);
        !           977:        if (_php_math_basetozval(*arg, 2, return_value) == FAILURE) {
        !           978:                RETURN_FALSE;
        !           979:        }
        !           980: }
        !           981: /* }}} */
        !           982: 
        !           983: /* {{{ proto int hexdec(string hexadecimal_number)
        !           984:    Returns the decimal equivalent of the hexadecimal number */
        !           985: PHP_FUNCTION(hexdec)
        !           986: {
        !           987:        zval **arg;
        !           988:        
        !           989:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
        !           990:                return;
        !           991:        }
        !           992:        convert_to_string_ex(arg);
        !           993:        if (_php_math_basetozval(*arg, 16, return_value) == FAILURE) {
        !           994:                RETURN_FALSE;
        !           995:        }
        !           996: }
        !           997: /* }}} */
        !           998: 
        !           999: /* {{{ proto int octdec(string octal_number)
        !          1000:    Returns the decimal equivalent of an octal string */
        !          1001: PHP_FUNCTION(octdec)
        !          1002: {
        !          1003:        zval **arg;
        !          1004:        
        !          1005:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
        !          1006:                return;
        !          1007:        }
        !          1008:        convert_to_string_ex(arg);
        !          1009:        if (_php_math_basetozval(*arg, 8, return_value) == FAILURE) {
        !          1010:                RETURN_FALSE;
        !          1011:        }
        !          1012: }
        !          1013: /* }}} */
        !          1014: 
        !          1015: /* {{{ proto string decbin(int decimal_number)
        !          1016:    Returns a string containing a binary representation of the number */
        !          1017: PHP_FUNCTION(decbin)
        !          1018: {
        !          1019:        zval **arg;
        !          1020:        char *result;
        !          1021: 
        !          1022:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
        !          1023:                return;
        !          1024:        }
        !          1025:        convert_to_long_ex(arg);
        !          1026:        result = _php_math_longtobase(*arg, 2);
        !          1027:        RETURN_STRING(result, 0);
        !          1028: }
        !          1029: /* }}} */
        !          1030: 
        !          1031: /* {{{ proto string decoct(int decimal_number)
        !          1032:    Returns a string containing an octal representation of the given number */
        !          1033: PHP_FUNCTION(decoct)
        !          1034: {
        !          1035:        zval **arg;
        !          1036:        char *result;
        !          1037: 
        !          1038:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
        !          1039:                return;
        !          1040:        }
        !          1041:        convert_to_long_ex(arg);
        !          1042:        result = _php_math_longtobase(*arg, 8);
        !          1043:        RETURN_STRING(result, 0);
        !          1044: }
        !          1045: /* }}} */
        !          1046: 
        !          1047: /* {{{ proto string dechex(int decimal_number)
        !          1048:    Returns a string containing a hexadecimal representation of the given number */
        !          1049: PHP_FUNCTION(dechex)
        !          1050: {
        !          1051:        zval **arg;
        !          1052:        char *result;
        !          1053: 
        !          1054:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &arg) == FAILURE) {
        !          1055:                return;
        !          1056:        }
        !          1057:        convert_to_long_ex(arg);
        !          1058:        result = _php_math_longtobase(*arg, 16);
        !          1059:        RETURN_STRING(result, 0);
        !          1060: }
        !          1061: /* }}} */
        !          1062: 
        !          1063: /* {{{ proto string base_convert(string number, int frombase, int tobase)
        !          1064:    Converts a number in a string from any base <= 36 to any base <= 36 */
        !          1065: PHP_FUNCTION(base_convert)
        !          1066: {
        !          1067:        zval **number, temp;
        !          1068:        long frombase, tobase;
        !          1069:        char *result;
        !          1070: 
        !          1071:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zll", &number, &frombase, &tobase) == FAILURE) {
        !          1072:                return;
        !          1073:        }
        !          1074:        convert_to_string_ex(number);
        !          1075:        
        !          1076:        if (frombase < 2 || frombase > 36) {
        !          1077:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid `from base' (%ld)", frombase);
        !          1078:                RETURN_FALSE;
        !          1079:        }
        !          1080:        if (tobase < 2 || tobase > 36) {
        !          1081:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid `to base' (%ld)", tobase);
        !          1082:                RETURN_FALSE;
        !          1083:        }
        !          1084: 
        !          1085:        if(_php_math_basetozval(*number, frombase, &temp) == FAILURE) {
        !          1086:                RETURN_FALSE;
        !          1087:        }
        !          1088:        result = _php_math_zvaltobase(&temp, tobase TSRMLS_CC);
        !          1089:        RETVAL_STRING(result, 0);
        !          1090: } 
        !          1091: /* }}} */
        !          1092: 
        !          1093: /* {{{ _php_math_number_format 
        !          1094: */
        !          1095: PHPAPI char *_php_math_number_format(double d, int dec, char dec_point, char thousand_sep)
        !          1096: {
        !          1097:        char *tmpbuf = NULL, *resbuf;
        !          1098:        char *s, *t;  /* source, target */
        !          1099:        char *dp;
        !          1100:        int integral;
        !          1101:        int tmplen, reslen=0;
        !          1102:        int count=0;
        !          1103:        int is_negative=0;
        !          1104: 
        !          1105:        if (d < 0) {
        !          1106:                is_negative = 1;
        !          1107:                d = -d;
        !          1108:        }
        !          1109: 
        !          1110:        dec = MAX(0, dec);
        !          1111:        d = _php_math_round(d, dec, PHP_ROUND_HALF_UP);
        !          1112: 
        !          1113:        tmplen = spprintf(&tmpbuf, 0, "%.*F", dec, d);
        !          1114: 
        !          1115:        if (tmpbuf == NULL || !isdigit((int)tmpbuf[0])) {
        !          1116:                return tmpbuf;
        !          1117:        }
        !          1118: 
        !          1119:        /* find decimal point, if expected */
        !          1120:        if (dec) {
        !          1121:                dp = strpbrk(tmpbuf, ".,");
        !          1122:        } else {
        !          1123:                dp = NULL;
        !          1124:        }
        !          1125: 
        !          1126:        /* calculate the length of the return buffer */
        !          1127:        if (dp) {
        !          1128:                integral = dp - tmpbuf;
        !          1129:        } else {
        !          1130:                /* no decimal point was found */
        !          1131:                integral = tmplen;
        !          1132:        }
        !          1133: 
        !          1134:        /* allow for thousand separators */
        !          1135:        if (thousand_sep) {
        !          1136:                integral += (integral-1) / 3;
        !          1137:        }
        !          1138:        
        !          1139:        reslen = integral;
        !          1140:        
        !          1141:        if (dec) {
        !          1142:                reslen += dec;
        !          1143: 
        !          1144:                if (dec_point) {
        !          1145:                        reslen++;
        !          1146:                }
        !          1147:        }
        !          1148: 
        !          1149:        /* add a byte for minus sign */
        !          1150:        if (is_negative) {
        !          1151:                reslen++;
        !          1152:        }
        !          1153:        resbuf = (char *) emalloc(reslen+1); /* +1 for NUL terminator */
        !          1154: 
        !          1155:        s = tmpbuf+tmplen-1;
        !          1156:        t = resbuf+reslen;
        !          1157:        *t-- = '\0';
        !          1158: 
        !          1159:        /* copy the decimal places.
        !          1160:         * Take care, as the sprintf implementation may return less places than
        !          1161:         * we requested due to internal buffer limitations */
        !          1162:        if (dec) {
        !          1163:                int declen = dp ? s - dp : 0;
        !          1164:                int topad = dec > declen ? dec - declen : 0;
        !          1165: 
        !          1166:                /* pad with '0's */
        !          1167:                while (topad--) {
        !          1168:                        *t-- = '0';
        !          1169:                }
        !          1170:                
        !          1171:                if (dp) {
        !          1172:                        s -= declen + 1; /* +1 to skip the point */
        !          1173:                        t -= declen;
        !          1174: 
        !          1175:                        /* now copy the chars after the point */
        !          1176:                        memcpy(t + 1, dp + 1, declen);
        !          1177:                }
        !          1178: 
        !          1179:                /* add decimal point */
        !          1180:                if (dec_point) {
        !          1181:                        *t-- = dec_point;
        !          1182:                }
        !          1183:        }
        !          1184: 
        !          1185:        /* copy the numbers before the decimal point, adding thousand
        !          1186:         * separator every three digits */
        !          1187:        while(s >= tmpbuf) {
        !          1188:                *t-- = *s--;
        !          1189:                if (thousand_sep && (++count%3)==0 && s>=tmpbuf) {
        !          1190:                        *t-- = thousand_sep;
        !          1191:                }
        !          1192:        }
        !          1193: 
        !          1194:        /* and a minus sign, if needed */
        !          1195:        if (is_negative) {
        !          1196:                *t-- = '-';
        !          1197:        }
        !          1198: 
        !          1199:        efree(tmpbuf);
        !          1200:        
        !          1201:        return resbuf;
        !          1202: }
        !          1203: /* }}} */
        !          1204: 
        !          1205: /* {{{ proto string number_format(float number [, int num_decimal_places [, string dec_seperator, string thousands_seperator]])
        !          1206:    Formats a number with grouped thousands */
        !          1207: PHP_FUNCTION(number_format)
        !          1208: {
        !          1209:        double num;
        !          1210:        long dec = 0;
        !          1211:        char *thousand_sep = NULL, *dec_point = NULL;
        !          1212:        char thousand_sep_chr = ',', dec_point_chr = '.';
        !          1213:        int thousand_sep_len = 0, dec_point_len = 0;
        !          1214:        
        !          1215:        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) {
        !          1216:                return;
        !          1217:        }
        !          1218: 
        !          1219:        switch(ZEND_NUM_ARGS()) {
        !          1220:        case 1:
        !          1221:                RETURN_STRING(_php_math_number_format(num, 0, dec_point_chr, thousand_sep_chr), 0);
        !          1222:                break;
        !          1223:        case 2:
        !          1224:                RETURN_STRING(_php_math_number_format(num, dec, dec_point_chr, thousand_sep_chr), 0);
        !          1225:                break;
        !          1226:        case 4:
        !          1227:                if (dec_point != NULL) {
        !          1228:                        if (dec_point_len) {
        !          1229:                                dec_point_chr = dec_point[0];
        !          1230:                        } else {
        !          1231:                                dec_point_chr = 0;
        !          1232:                        }
        !          1233:                }
        !          1234:                if (thousand_sep != NULL) {
        !          1235:                        if (thousand_sep_len) {
        !          1236:                                thousand_sep_chr = thousand_sep[0];
        !          1237:                        } else {
        !          1238:                                thousand_sep_chr = 0;   
        !          1239:                        }
        !          1240:                }
        !          1241:                RETURN_STRING(_php_math_number_format(num, dec, dec_point_chr, thousand_sep_chr), 0);
        !          1242:                break;
        !          1243:        default:
        !          1244:                WRONG_PARAM_COUNT;
        !          1245:                break;
        !          1246:        }
        !          1247: }
        !          1248: /* }}} */
        !          1249: 
        !          1250: /* {{{ proto float fmod(float x, float y)
        !          1251:    Returns the remainder of dividing x by y as a float */
        !          1252: PHP_FUNCTION(fmod)
        !          1253: {
        !          1254:        double num1, num2;
        !          1255: 
        !          1256:        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "dd",  &num1, &num2) == FAILURE) {
        !          1257:                return;
        !          1258:        }
        !          1259:        RETURN_DOUBLE(fmod(num1, num2));
        !          1260: }
        !          1261: /* }}} */
        !          1262: 
        !          1263: 
        !          1264: 
        !          1265: /*
        !          1266:  * Local variables:
        !          1267:  * tab-width: 4
        !          1268:  * c-basic-offset: 4
        !          1269:  * End:
        !          1270:  * vim600: fdm=marker
        !          1271:  * vim: noet sw=4 ts=4
        !          1272:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>