Arquivos
hhvm/hphp/runtime/ext/ext_math.cpp
T
aalexandre 26178124a4 Eliminate int32, uint32, int16, uint16, int8, uint8.
This concludes the inttypes replacement.
These replacement have been mostly mechanical
with the use of cxx_replace.
2013-03-09 10:25:16 -08:00

219 linhas
6.3 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 1997-2010 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include <runtime/ext/ext_math.h>
#include <runtime/base/zend/zend_math.h>
#include <runtime/base/zend/zend_multiply.h>
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
const int64_t k_PHP_ROUND_HALF_UP = PHP_ROUND_HALF_UP;
const int64_t k_PHP_ROUND_HALF_DOWN = PHP_ROUND_HALF_DOWN;
const int64_t k_PHP_ROUND_HALF_EVEN = PHP_ROUND_HALF_EVEN;
const int64_t k_PHP_ROUND_HALF_ODD = PHP_ROUND_HALF_ODD;
Variant f_min(int _argc, CVarRef value, CArrRef _argv /* = null_array */) {
Variant ret;
if (_argv.empty() && value.is(KindOfArray)) {
Array v = value.toArray();
if (!v.empty()) {
ssize_t pos = v->iter_begin();
if (pos != ArrayData::invalid_index) {
ret = v->getValue(pos);
while (true) {
pos = v->iter_advance(pos);
if (pos == ArrayData::invalid_index) break;
Variant tmp = v->getValue(pos);
if (less(tmp, ret)) {
ret = tmp;
}
}
}
}
} else {
ret = value;
if (!_argv.empty()) {
for (ssize_t pos = _argv->iter_begin(); pos != ArrayData::invalid_index;
pos = _argv->iter_advance(pos)) {
Variant tmp = _argv->getValue(pos);
if (less(tmp, ret)) {
ret = tmp;
}
}
}
}
return ret;
}
Variant f_max(int _argc, CVarRef value, CArrRef _argv /* = null_array */) {
Variant ret;
if (_argv.empty() && value.is(KindOfArray)) {
Array v = value.toArray();
if (!v.empty()) {
ssize_t pos = v->iter_begin();
if (pos != ArrayData::invalid_index) {
ret = v->getValue(pos);
while (true) {
pos = v->iter_advance(pos);
if (pos == ArrayData::invalid_index) break;
Variant tmp = v->getValue(pos);
if (more(tmp, ret)) {
ret = tmp;
}
}
}
}
} else {
ret = value;
if (!_argv.empty()) {
for (ssize_t pos = _argv->iter_begin(); pos != ArrayData::invalid_index;
pos = _argv->iter_advance(pos)) {
Variant tmp = _argv->getValue(pos);
if (more(tmp, ret)) {
ret = tmp;
}
}
}
}
return ret;
}
Variant f_abs(CVarRef number) {
int64_t ival;
double dval;
DataType k = number.toNumeric(ival, dval, true);
if (k == KindOfDouble) {
return fabs(dval);
} else if (k == KindOfInt64) {
return ival >= 0 ? ival : -ival;
} else {
return 0;
}
}
double f_round(CVarRef val, int64_t precision /* = 0 */,
int64_t mode /* = PHP_ROUND_HALF_UP */) {
int64_t ival;
double dval;
DataType k = val.toNumeric(ival, dval, true);
if (k == KindOfInt64) {
if (precision >= 0) {
return ival;
} else {
dval = ival;
}
} else if (k != KindOfDouble) {
dval = val.toDouble();
}
dval = php_math_round(dval, precision, mode);
return dval;
}
Variant f_base_convert(CStrRef number, int64_t frombase, int64_t tobase) {
if (!string_validate_base(frombase)) {
throw_invalid_argument("Invalid frombase: %d", frombase);
return false;
}
if (!string_validate_base(tobase)) {
throw_invalid_argument("Invalid tobase: %d", tobase);
return false;
}
Variant v = string_base_to_numeric(number.data(), number.size(), frombase);
return String(string_numeric_to_base(v, tobase), AttachString);
}
Numeric f_pow(CVarRef base, CVarRef exp) {
int64_t bint, eint;
double bdbl, edbl;
DataType bt = base.toNumeric(bint, bdbl, true);
DataType et = exp.toNumeric(eint, edbl, true);
if (bt == KindOfInt64 && et == KindOfInt64 && eint >= 0) {
if (eint == 0) return 1LL;
if (bint == 0) return 0LL;
// calculate pow(long,long) in O(log exp) operations, bail if overflow
int64_t l1 = 1;
while (eint >= 1) {
int overflow;
double dval = 0.0;
if (eint % 2) {
--eint;
ZEND_SIGNED_MULTIPLY_LONG(l1, bint, l1, dval, overflow);
if (overflow) return dval * pow(bint, eint);
} else {
eint /= 2;
ZEND_SIGNED_MULTIPLY_LONG(bint, bint, bint, dval, overflow);
if (overflow) return (double)l1 * pow(dval, eint);
}
if (eint == 0) {
return l1;
}
}
}
if (bt != KindOfDouble) {
bdbl = base.toDouble();
}
if (et != KindOfDouble) {
edbl = exp.toDouble();
}
return pow(bdbl, edbl);
}
///////////////////////////////////////////////////////////////////////////////
static bool s_rand_is_seeded = false;
void f_srand(CVarRef seed /* = null_variant */) {
s_rand_is_seeded = true;
if (seed.isNull()) {
return srand(math_generate_seed());
}
if (seed.isNumeric(true)) {
srand(seed.toInt32());
} else {
raise_warning("srand() expects parameter 1 to be long");
}
}
int64_t f_rand(int64_t min /* = 0 */, int64_t max /* = RAND_MAX */) {
if (!s_rand_is_seeded) {
s_rand_is_seeded = true;
srand(math_generate_seed());
}
int64_t number = rand();
if (min != 0 || max != RAND_MAX) {
RAND_RANGE(number, min, max, RAND_MAX);
}
return number;
}
void f_mt_srand(CVarRef seed /* = null_variant */) {
if (seed.isNull()) {
return math_mt_srand(math_generate_seed());
}
if (seed.isNumeric(true)) {
math_mt_srand(seed.toInt32());
} else {
raise_warning("mt_srand() expects parameter 1 to be long");
}
}
///////////////////////////////////////////////////////////////////////////////
}