998951619f
We did not intend to imply our copyrights last forever Closes #759
235 linhas
7.1 KiB
C++
235 linhas
7.1 KiB
C++
/*
|
|
+----------------------------------------------------------------------+
|
|
| HipHop for PHP |
|
|
+----------------------------------------------------------------------+
|
|
| Copyright (c) 2010-2013 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 "hphp/runtime/ext/ext_bcmath.h"
|
|
#include "hphp/runtime/ext/bcmath/bcmath.h"
|
|
|
|
namespace HPHP {
|
|
IMPLEMENT_DEFAULT_EXTENSION(bcmath);
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
class bcmath_data {
|
|
public:
|
|
bcmath_data() {
|
|
// we can't really call bc_init_numbers() that calls into this constructor
|
|
data._zero_ = _bc_new_num_ex (1,0,1);
|
|
data._one_ = _bc_new_num_ex (1,0,1);
|
|
data._one_->n_value[0] = 1;
|
|
data._two_ = _bc_new_num_ex (1,0,1);
|
|
data._two_->n_value[0] = 2;
|
|
data.bc_precision = 0;
|
|
}
|
|
BCMathGlobals data;
|
|
};
|
|
static IMPLEMENT_THREAD_LOCAL(bcmath_data, s_globals);
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
static void php_str2num(bc_num *num, const char *str) {
|
|
const char *p;
|
|
if (!(p = strchr(str, '.'))) {
|
|
bc_str2num(num, (char*)str, 0);
|
|
} else {
|
|
bc_str2num(num, (char*)str, strlen(p + 1));
|
|
}
|
|
}
|
|
|
|
bool f_bcscale(int64_t scale) {
|
|
BCG(bc_precision) = scale < 0 ? 0 : scale;
|
|
return true;
|
|
}
|
|
|
|
String f_bcadd(CStrRef left, CStrRef right, int64_t scale /* = -1 */) {
|
|
if (scale < 0) scale = BCG(bc_precision);
|
|
bc_num first, second, result;
|
|
bc_init_num(&first);
|
|
bc_init_num(&second);
|
|
bc_init_num(&result);
|
|
php_str2num(&first, (char*)left.data());
|
|
php_str2num(&second, (char*)right.data());
|
|
bc_add(first, second, &result, scale);
|
|
if (result->n_scale > scale) {
|
|
result->n_scale = scale;
|
|
}
|
|
String ret(bc_num2str(result), AttachString);
|
|
bc_free_num(&first);
|
|
bc_free_num(&second);
|
|
bc_free_num(&result);
|
|
return ret;
|
|
}
|
|
|
|
String f_bcsub(CStrRef left, CStrRef right, int64_t scale /* = -1 */) {
|
|
if (scale < 0) scale = BCG(bc_precision);
|
|
bc_num first, second, result;
|
|
bc_init_num(&first);
|
|
bc_init_num(&second);
|
|
bc_init_num(&result);
|
|
php_str2num(&first, (char*)left.data());
|
|
php_str2num(&second, (char*)right.data());
|
|
bc_sub(first, second, &result, scale);
|
|
if (result->n_scale > scale) {
|
|
result->n_scale = scale;
|
|
}
|
|
String ret(bc_num2str(result), AttachString);
|
|
bc_free_num(&first);
|
|
bc_free_num(&second);
|
|
bc_free_num(&result);
|
|
return ret;
|
|
}
|
|
|
|
int64_t f_bccomp(CStrRef left, CStrRef right, int64_t scale /* = -1 */) {
|
|
if (scale < 0) scale = BCG(bc_precision);
|
|
bc_num first, second;
|
|
bc_init_num(&first);
|
|
bc_init_num(&second);
|
|
bc_str2num(&first, (char*)left.data(), scale);
|
|
bc_str2num(&second, (char*)right.data(), scale);
|
|
int64_t ret = bc_compare(first, second);
|
|
bc_free_num(&first);
|
|
bc_free_num(&second);
|
|
return ret;
|
|
}
|
|
|
|
String f_bcmul(CStrRef left, CStrRef right, int64_t scale /* = -1 */) {
|
|
if (scale < 0) scale = BCG(bc_precision);
|
|
bc_num first, second, result;
|
|
bc_init_num(&first);
|
|
bc_init_num(&second);
|
|
bc_init_num(&result);
|
|
php_str2num(&first, (char*)left.data());
|
|
php_str2num(&second, (char*)right.data());
|
|
bc_multiply(first, second, &result, scale);
|
|
if (result->n_scale > scale) {
|
|
result->n_scale = scale;
|
|
}
|
|
String ret(bc_num2str(result), AttachString);
|
|
bc_free_num(&first);
|
|
bc_free_num(&second);
|
|
bc_free_num(&result);
|
|
return ret;
|
|
}
|
|
|
|
String f_bcdiv(CStrRef left, CStrRef right, int64_t scale /* = -1 */) {
|
|
if (scale < 0) scale = BCG(bc_precision);
|
|
bc_num first, second, result;
|
|
bc_init_num(&first);
|
|
bc_init_num(&second);
|
|
bc_init_num(&result);
|
|
php_str2num(&first, (char*)left.data());
|
|
php_str2num(&second, (char*)right.data());
|
|
if (bc_divide(first, second, &result, scale) == -1) {
|
|
raise_warning("Division by zero");
|
|
return String();
|
|
}
|
|
String ret(bc_num2str(result), AttachString);
|
|
bc_free_num(&first);
|
|
bc_free_num(&second);
|
|
bc_free_num(&result);
|
|
return ret;
|
|
}
|
|
|
|
String f_bcmod(CStrRef left, CStrRef right) {
|
|
bc_num first, second, result;
|
|
bc_init_num(&first);
|
|
bc_init_num(&second);
|
|
bc_init_num(&result);
|
|
php_str2num(&first, (char*)left.data());
|
|
php_str2num(&second, (char*)right.data());
|
|
if (bc_modulo(first, second, &result, 0) == -1) {
|
|
raise_warning("Division by zero");
|
|
return String();
|
|
}
|
|
String ret(bc_num2str(result), AttachString);
|
|
bc_free_num(&first);
|
|
bc_free_num(&second);
|
|
bc_free_num(&result);
|
|
return ret;
|
|
}
|
|
|
|
String f_bcpow(CStrRef left, CStrRef right, int64_t scale /* = -1 */) {
|
|
if (scale < 0) scale = BCG(bc_precision);
|
|
bc_num first, second, result;
|
|
bc_init_num(&first);
|
|
bc_init_num(&second);
|
|
bc_init_num(&result);
|
|
php_str2num(&first, (char*)left.data());
|
|
php_str2num(&second, (char*)right.data());
|
|
bc_raise(first, second, &result, scale);
|
|
if (result->n_scale > scale) {
|
|
result->n_scale = scale;
|
|
}
|
|
String ret(bc_num2str(result), AttachString);
|
|
bc_free_num(&first);
|
|
bc_free_num(&second);
|
|
bc_free_num(&result);
|
|
return ret;
|
|
}
|
|
|
|
Variant f_bcpowmod(CStrRef left, CStrRef right, CStrRef modulus,
|
|
int64_t scale /* = -1 */) {
|
|
if (scale < 0) scale = BCG(bc_precision);
|
|
bc_num first, second, mod, result;
|
|
bc_init_num(&first);
|
|
bc_init_num(&second);
|
|
bc_init_num(&mod);
|
|
bc_init_num(&result);
|
|
php_str2num(&first, (char*)left.data());
|
|
php_str2num(&second, (char*)right.data());
|
|
php_str2num(&mod, (char*)modulus.data());
|
|
if (bc_raisemod(first, second, mod, &result, scale) == -1) {
|
|
return false;
|
|
}
|
|
if (result->n_scale > scale) {
|
|
result->n_scale = scale;
|
|
}
|
|
String ret(bc_num2str(result), AttachString);
|
|
bc_free_num(&first);
|
|
bc_free_num(&second);
|
|
bc_free_num(&mod);
|
|
bc_free_num(&result);
|
|
return ret;
|
|
}
|
|
|
|
Variant f_bcsqrt(CStrRef operand, int64_t scale /* = -1 */) {
|
|
if (scale < 0) scale = BCG(bc_precision);
|
|
bc_num result;
|
|
bc_init_num(&result);
|
|
php_str2num(&result, (char*)operand.data());
|
|
Variant ret;
|
|
if (bc_sqrt(&result, scale) != 0) {
|
|
if (result->n_scale > scale) {
|
|
result->n_scale = scale;
|
|
}
|
|
ret = String(bc_num2str(result), AttachString);
|
|
} else {
|
|
raise_warning("Square root of negative number");
|
|
}
|
|
bc_free_num(&result);
|
|
return ret;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
extern "C" {
|
|
struct BCMathGlobals *get_bcmath_globals() {
|
|
return &HPHP::s_globals.get()->data;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
}
|