Add operator overloading for Complex.
This commit is contained in:
parent
e6b572a3eb
commit
8163e4af9d
|
@ -27,6 +27,6 @@ install:
|
|||
|
||||
script:
|
||||
- phpize
|
||||
- ./configure --enable-arma-operator
|
||||
- ./configure --enable-arma-operators
|
||||
- make
|
||||
- make test
|
||||
|
|
14
config.m4
14
config.m4
|
@ -1,8 +1,8 @@
|
|||
PHP_ARG_ENABLE(arma, for armadillo support,
|
||||
[ --enable-arma Enable armadillo support])
|
||||
PHP_ARG_ENABLE(arma, for armadillo support,
|
||||
[ --enable-arma Enable armadillo support])
|
||||
|
||||
PHP_ARG_ENABLE(arma-operator, for operator overloading support in armadillo,
|
||||
[ --enable-arma-operator Enable operator overloading for armadillo ], no, no)
|
||||
PHP_ARG_ENABLE(arma-operators, for operator overloading support in armadillo,
|
||||
[ --enable-arma-operators Enable operator overloading for armadillo ], no, no)
|
||||
|
||||
if test "$PHP_ARMA" != "no"; then
|
||||
PHP_REQUIRE_CXX()
|
||||
|
@ -15,9 +15,9 @@ if test "$PHP_ARMA" != "no"; then
|
|||
src/mapval.cc \
|
||||
"
|
||||
|
||||
if test "$PHP_ARMA_OPERATOR" != "no"; then
|
||||
AC_DEFINE(PHP_ARMA_OPERATOR, 1, [ Defined if operator overloading is enabled for armadillo. ])
|
||||
ARMA_SRC+="src/operator.cc"
|
||||
if test "$PHP_ARMA_OPERATORS" != "no"; then
|
||||
AC_DEFINE(PHP_ARMA_OPERATORS, 1, [ Defined if operator overloading is enabled for armadillo. ])
|
||||
ARMA_SRC+="src/operators.cc"
|
||||
fi
|
||||
|
||||
PHP_NEW_EXTENSION(arma, $ARMA_SRC, $ext_shared, , -std=c++17)
|
||||
|
|
|
@ -77,19 +77,9 @@ namespace php_arma
|
|||
Z_PARAM_ZVAL(other)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
auto current = zval_get_scalar<native_t>(getThis());
|
||||
|
||||
if (zval_is_scalar<native_t>(other)) {
|
||||
zval_set_scalar(return_value, current + zval_get_scalar<native_t>(other));
|
||||
return;
|
||||
if (!operators::add(getThis(), other, return_value)) {
|
||||
ex_bad_type<T>(other);
|
||||
}
|
||||
|
||||
if (zval_is_scalar<T>(other)) {
|
||||
zval_set_scalar(return_value, current + zval_get_scalar<T>(other));
|
||||
return;
|
||||
}
|
||||
|
||||
ex_bad_type<T>(other);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -100,19 +90,9 @@ namespace php_arma
|
|||
Z_PARAM_ZVAL(other)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
auto current = zval_get_scalar<native_t>(getThis());
|
||||
|
||||
if (zval_is_scalar<native_t>(other)) {
|
||||
zval_set_scalar(return_value, current - zval_get_scalar<native_t>(other));
|
||||
return;
|
||||
if (!operators::sub(getThis(), other, return_value)) {
|
||||
ex_bad_type<T>(other);
|
||||
}
|
||||
|
||||
if (zval_is_scalar<T>(other)) {
|
||||
zval_set_scalar(return_value, current - zval_get_scalar<T>(other));
|
||||
return;
|
||||
}
|
||||
|
||||
ex_bad_type<T>(other);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -131,19 +111,9 @@ namespace php_arma
|
|||
Z_PARAM_ZVAL(other)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
auto current = zval_get_scalar<native_t>(getThis());
|
||||
|
||||
if (zval_is_scalar<native_t>(other)) {
|
||||
zval_set_scalar(return_value, current * zval_get_scalar<native_t>(other));
|
||||
return;
|
||||
if (!operators::mul(getThis(), other, return_value)) {
|
||||
ex_bad_type<T>(other);
|
||||
}
|
||||
|
||||
if (zval_is_scalar<T>(other)) {
|
||||
zval_set_scalar(return_value, current * zval_get_scalar<T>(other));
|
||||
return;
|
||||
}
|
||||
|
||||
ex_bad_type<T>(other);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -154,19 +124,9 @@ namespace php_arma
|
|||
Z_PARAM_ZVAL(other)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
auto current = zval_get_scalar<native_t>(getThis());
|
||||
|
||||
if (zval_is_scalar<native_t>(other)) {
|
||||
zval_set_scalar(return_value, current / zval_get_scalar<native_t>(other));
|
||||
return;
|
||||
if (!operators::div(getThis(), other, return_value)) {
|
||||
ex_bad_type<T>(other);
|
||||
}
|
||||
|
||||
if (zval_is_scalar<T>(other)) {
|
||||
zval_set_scalar(return_value, current / zval_get_scalar<T>(other));
|
||||
return;
|
||||
}
|
||||
|
||||
ex_bad_type<T>(other);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -196,9 +156,7 @@ namespace php_arma
|
|||
template <typename T>
|
||||
PHP_ARMA_METHOD(complex, conj, T)
|
||||
{
|
||||
auto current = zval_get_scalar<native_t>(getThis());
|
||||
|
||||
zval_set_scalar(return_value, std::conj(current));
|
||||
operators::conj(getThis(), nullptr, return_value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -233,19 +191,9 @@ namespace php_arma
|
|||
Z_PARAM_ZVAL(other)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
auto current = zval_get_scalar<native_t>(getThis());
|
||||
|
||||
if (zval_is_scalar<native_t>(other)) {
|
||||
zval_set_scalar(return_value, std::pow(current, zval_get_scalar<native_t>(other)));
|
||||
return;
|
||||
if (!operators::pow(getThis(), other, return_value)) {
|
||||
ex_bad_type<T>(other);
|
||||
}
|
||||
|
||||
if (zval_is_scalar<T>(other)) {
|
||||
zval_set_scalar(return_value, std::pow(current, zval_get_scalar<T>(other)));
|
||||
return;
|
||||
}
|
||||
|
||||
ex_bad_type<T>(other);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
|
116
src/complex.hh
116
src/complex.hh
|
@ -11,6 +11,24 @@
|
|||
|
||||
#include <complex>
|
||||
|
||||
#ifdef PHP_ARMA_OPERATORS
|
||||
|
||||
#define PHP_ARMA_COMPLEX_OPERATOR(type, func) \
|
||||
if (instanceof_function(_ce, complex<type>::ce)) { \
|
||||
return complex<type>::operators::func(zv1, zv2, retval); \
|
||||
}
|
||||
|
||||
#define PHP_ARMA_COMPLEX_OPERATOR_ASSIGN(type, func) \
|
||||
if (instanceof_function(_ce, complex<type>::ce)) { \
|
||||
auto v = complex<type>::operators::func(zv1, zv2, zv1); \
|
||||
if (EX(opline)->result_type != IS_UNUSED) { \
|
||||
ZVAL_COPY(retval, zv1); \
|
||||
} \
|
||||
return v; \
|
||||
}
|
||||
|
||||
#endif // PHP_ARMA_OPERATORS
|
||||
|
||||
using cx_double = std::complex<double>;
|
||||
|
||||
namespace php_arma
|
||||
|
@ -20,6 +38,8 @@ namespace php_arma
|
|||
{
|
||||
using native_t = std::complex<T>;
|
||||
|
||||
struct operators;
|
||||
|
||||
friend void complex_init();
|
||||
|
||||
PHP_ARMA_CE_HANDLRES_DECLARE();
|
||||
|
@ -114,6 +134,102 @@ namespace php_arma
|
|||
ex_bad_type(expected, got);
|
||||
free(expected);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct complex<T>::operators
|
||||
{
|
||||
zend_always_inline
|
||||
static bool add(zval *zv1, zval *zv2, zval *retval)
|
||||
{
|
||||
auto v1 = zval_get_scalar<native_t>(zv1);
|
||||
|
||||
if (zval_is_scalar<native_t>(zv2)) {
|
||||
zval_set_scalar(retval, v1 + zval_get_scalar<native_t>(zv2));
|
||||
return true;
|
||||
}
|
||||
if (zval_is_scalar<T>(zv2)) {
|
||||
zval_set_scalar(retval, v1 + zval_get_scalar<T>(zv2));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
zend_always_inline
|
||||
static bool sub(zval *zv1, zval *zv2, zval *retval)
|
||||
{
|
||||
auto v1 = zval_get_scalar<native_t>(zv1);
|
||||
|
||||
if (zval_is_scalar<native_t>(zv2)) {
|
||||
zval_set_scalar(retval, v1 - zval_get_scalar<native_t>(zv2));
|
||||
return true;
|
||||
}
|
||||
if (zval_is_scalar<T>(zv2)) {
|
||||
zval_set_scalar(retval, v1 - zval_get_scalar<T>(zv2));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
zend_always_inline
|
||||
static bool mul(zval *zv1, zval *zv2, zval *retval)
|
||||
{
|
||||
auto v1 = zval_get_scalar<native_t>(zv1);
|
||||
|
||||
if (zval_is_scalar<native_t>(zv2)) {
|
||||
zval_set_scalar(retval, v1 * zval_get_scalar<native_t>(zv2));
|
||||
return true;
|
||||
}
|
||||
if (zval_is_scalar<T>(zv2)) {
|
||||
zval_set_scalar(retval, v1 * zval_get_scalar<T>(zv2));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
zend_always_inline
|
||||
static bool div(zval *zv1, zval *zv2, zval *retval)
|
||||
{
|
||||
auto v1 = zval_get_scalar<native_t>(zv1);
|
||||
|
||||
if (zval_is_scalar<native_t>(zv2)) {
|
||||
zval_set_scalar(retval, v1 / zval_get_scalar<native_t>(zv2));
|
||||
return true;
|
||||
}
|
||||
if (zval_is_scalar<T>(zv2)) {
|
||||
zval_set_scalar(retval, v1 / zval_get_scalar<T>(zv2));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
zend_always_inline
|
||||
static bool pow(zval *zv1, zval *zv2, zval *retval)
|
||||
{
|
||||
auto v1 = zval_get_scalar<native_t>(zv1);
|
||||
|
||||
if (zval_is_scalar<native_t>(zv2)) {
|
||||
zval_set_scalar(retval, std::pow(v1, zval_get_scalar<native_t>(zv2)));
|
||||
return true;
|
||||
}
|
||||
if (zval_is_scalar<T>(zv2)) {
|
||||
zval_set_scalar(retval, std::pow(v1, zval_get_scalar<T>(zv2)));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
zend_always_inline
|
||||
static bool conj(zval *zv, zval *unused, zval *retval)
|
||||
{
|
||||
zval_set_scalar(retval, std::conj(zval_get_scalar<native_t>(zv)));
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // !PHP_ARMA_COMPLEX_HH
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
// @Author CismonX
|
||||
//
|
||||
|
||||
#include "php_arma.hh"
|
||||
#include "constants.hh"
|
||||
|
||||
#include <tuple>
|
||||
|
@ -52,5 +51,8 @@ namespace php_arma
|
|||
std::tuple("APPEND", hdf5_opts::append),
|
||||
std::tuple("REPLACE", hdf5_opts::replace)
|
||||
);
|
||||
const_declare(features_ce = abstract_class_register<features_php_name>(),
|
||||
std::tuple("OPERATORS", features::operators)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#ifndef PHP_ARMA_CONSTANTS_HH
|
||||
#define PHP_ARMA_CONSTANTS_HH
|
||||
|
||||
#include <php.h>
|
||||
#include "php_arma.hh"
|
||||
|
||||
namespace php_arma
|
||||
{
|
||||
|
@ -49,17 +49,28 @@ namespace php_arma
|
|||
static constexpr auto replace = 1u << 2;
|
||||
};
|
||||
|
||||
struct features
|
||||
{
|
||||
#ifdef PHP_ARMA_OPERATORS
|
||||
static constexpr auto operators = true;
|
||||
#else
|
||||
static constexpr auto operators = false;
|
||||
#endif // PHP_ARMA_OPERATORS
|
||||
};
|
||||
|
||||
void constants_init();
|
||||
|
||||
constexpr const char fill_php_name[] = "Fill";
|
||||
constexpr const char file_type_php_name[] = "FileType";
|
||||
constexpr const char sort_direction_php_name[] = "SortDirection";
|
||||
constexpr const char hdf5_opts_php_name[] = "HDF5Opts";
|
||||
constexpr const char features_php_name[] = "Features";
|
||||
|
||||
inline zend_class_entry *fill_ce;
|
||||
inline zend_class_entry *file_type_ce;
|
||||
inline zend_class_entry *sort_direction_ce;
|
||||
inline zend_class_entry *hdf5_opts_ce;
|
||||
inline zend_class_entry *features_ce;
|
||||
}
|
||||
|
||||
#endif //!PHP_ARMA_CONSTANTS_HH
|
||||
|
|
|
@ -5,10 +5,9 @@
|
|||
//
|
||||
|
||||
#include "php_arma.hh"
|
||||
#include "operators.hh"
|
||||
#include "complex.hh"
|
||||
|
||||
#include <zend_compile.h>
|
||||
|
||||
#if PHP_VERSION_ID >= 70300
|
||||
// See https://github.com/php/php-src/blob/PHP-7.3/UPGRADING.INTERNALS#L61 section 3.1.b.
|
||||
#define EX_CONSTANT(op) RT_CONSTANT(EX(opline), op)
|
||||
|
@ -19,18 +18,18 @@ namespace php_arma
|
|||
zend_always_inline
|
||||
zval *get_zval_ptr_undef(
|
||||
zend_uchar op_type,
|
||||
znode_op op,
|
||||
const znode_op *op,
|
||||
zend_free_op *free_op,
|
||||
zend_execute_data *execute_data
|
||||
) {
|
||||
switch (op_type) {
|
||||
case IS_TMP_VAR:
|
||||
case IS_VAR:
|
||||
return *free_op = EX_VAR(op.var);
|
||||
return *free_op = EX_VAR(op->var);
|
||||
case IS_CONST:
|
||||
return EX_CONSTANT(op);
|
||||
return EX_CONSTANT(*op);
|
||||
case IS_CV:
|
||||
return EX_VAR(op.var);
|
||||
return EX_VAR(op->var);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -55,11 +54,15 @@ namespace php_arma
|
|||
const zend_op *opline = EX(opline);
|
||||
zend_free_op free_op1 = nullptr;
|
||||
zend_free_op free_op2 = nullptr;
|
||||
zval *op1 = get_zval_ptr_undef(opline->op1_type, opline->op1, &free_op1, execute_data);
|
||||
zval *op2 = get_zval_ptr_undef(opline->op2_type, opline->op2, &free_op2, execute_data);
|
||||
zval *op1 = get_zval_ptr_undef(opline->op1_type, &opline->op1, &free_op1, execute_data);
|
||||
zval *op2 = get_zval_ptr_undef(opline->op2_type, &opline->op2, &free_op2, execute_data);
|
||||
|
||||
ZVAL_DEREF(op1);
|
||||
ZVAL_DEREF(op2);
|
||||
if (op1) {
|
||||
ZVAL_DEREF(op1);
|
||||
}
|
||||
if (op2) {
|
||||
ZVAL_DEREF(op2);
|
||||
}
|
||||
|
||||
if (UNEXPECTED(opcode_is_greater(opline))) {
|
||||
std::swap(op1, op2);
|
||||
|
@ -83,7 +86,7 @@ namespace php_arma
|
|||
int add_handler(zend_execute_data *execute_data)
|
||||
{
|
||||
return op_handler(execute_data, [] (auto zv1, auto zv2, auto retval) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1)) != IS_OBJECT) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1) != IS_OBJECT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -97,8 +100,8 @@ namespace php_arma
|
|||
|
||||
int add_assign_handler(zend_execute_data *execute_data)
|
||||
{
|
||||
return op_handler(execute_data, [] (auto zv1, auto zv2, auto retval) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1)) != IS_OBJECT) {
|
||||
return op_handler(execute_data, [execute_data] (auto zv1, auto zv2, auto retval) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1) != IS_OBJECT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -113,7 +116,7 @@ namespace php_arma
|
|||
int sub_handler(zend_execute_data *execute_data)
|
||||
{
|
||||
return op_handler(execute_data, [] (auto zv1, auto zv2, auto retval) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1)) != IS_OBJECT) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1) != IS_OBJECT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -127,8 +130,8 @@ namespace php_arma
|
|||
|
||||
int sub_assign_handler(zend_execute_data *execute_data)
|
||||
{
|
||||
return op_handler(execute_data, [] (auto zv1, auto zv2, auto retval) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1)) != IS_OBJECT) {
|
||||
return op_handler(execute_data, [execute_data] (auto zv1, auto zv2, auto retval) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1) != IS_OBJECT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -143,7 +146,7 @@ namespace php_arma
|
|||
int mul_handler(zend_execute_data *execute_data)
|
||||
{
|
||||
return op_handler(execute_data, [] (auto zv1, auto zv2, auto retval) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1)) != IS_OBJECT) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1) != IS_OBJECT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -157,8 +160,8 @@ namespace php_arma
|
|||
|
||||
int mul_assign_handler(zend_execute_data *execute_data)
|
||||
{
|
||||
return op_handler(execute_data, [] (auto zv1, auto zv2, auto retval) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1)) != IS_OBJECT) {
|
||||
return op_handler(execute_data, [execute_data] (auto zv1, auto zv2, auto retval) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1) != IS_OBJECT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -173,7 +176,7 @@ namespace php_arma
|
|||
int div_handler(zend_execute_data *execute_data)
|
||||
{
|
||||
return op_handler(execute_data, [] (auto zv1, auto zv2, auto retval) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1)) != IS_OBJECT) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1) != IS_OBJECT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -187,8 +190,8 @@ namespace php_arma
|
|||
|
||||
int div_assign_handler(zend_execute_data *execute_data)
|
||||
{
|
||||
return op_handler(execute_data, [] (auto zv1, auto zv2, auto retval) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1)) != IS_OBJECT) {
|
||||
return op_handler(execute_data, [execute_data] (auto zv1, auto zv2, auto retval) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1) != IS_OBJECT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -203,7 +206,7 @@ namespace php_arma
|
|||
int pow_handler(zend_execute_data *execute_data)
|
||||
{
|
||||
return op_handler(execute_data, [] (auto zv1, auto zv2, auto retval) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1)) != IS_OBJECT) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1) != IS_OBJECT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -215,10 +218,25 @@ namespace php_arma
|
|||
});
|
||||
}
|
||||
|
||||
int pow_assign_handler(zend_execute_data *execute_data)
|
||||
{
|
||||
return op_handler(execute_data, [execute_data] (auto zv1, auto zv2, auto retval) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1) != IS_OBJECT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PHP_ARMA_OPERATOR_BEGIN(Z_OBJCE_P(zv1), complex_ce)
|
||||
PHP_ARMA_COMPLEX_OPERATOR_ASSIGN(double, pow)
|
||||
PHP_ARMA_OPERATOR_END();
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
int bw_not_handler(zend_execute_data *execute_data)
|
||||
{
|
||||
return op_handler(execute_data, [] (auto zv1, auto zv2, auto retval) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1)) != IS_OBJECT) {
|
||||
if (UNEXPECTED(Z_TYPE_P(zv1) != IS_OBJECT)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -230,7 +248,7 @@ namespace php_arma
|
|||
});
|
||||
}
|
||||
|
||||
void operator_init()
|
||||
void operators_init()
|
||||
{
|
||||
zend_set_user_opcode_handler(ZEND_ADD, add_handler);
|
||||
zend_set_user_opcode_handler(ZEND_ASSIGN_ADD, add_assign_handler);
|
||||
|
@ -241,6 +259,7 @@ namespace php_arma
|
|||
zend_set_user_opcode_handler(ZEND_DIV, div_handler);
|
||||
zend_set_user_opcode_handler(ZEND_ASSIGN_DIV, div_assign_handler);
|
||||
zend_set_user_opcode_handler(ZEND_POW, pow_handler);
|
||||
zend_set_user_opcode_handler(ZEND_ASSIGN_POW, pow_assign_handler);
|
||||
zend_set_user_opcode_handler(ZEND_BW_NOT, bw_not_handler);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
namespace php_arma
|
||||
{
|
||||
void operator_init();
|
||||
void operators_init();
|
||||
}
|
||||
|
||||
#endif // !PHP_ARMA_OPERATOR_HH
|
||||
|
|
|
@ -10,9 +10,9 @@
|
|||
#include "base.hh"
|
||||
#include "mapval.hh"
|
||||
|
||||
#ifdef PHP_ARMA_OPERATOR
|
||||
#include "operator.hh"
|
||||
#endif // PHP_ARMA_OPERATOR
|
||||
#ifdef PHP_ARMA_OPERATORS
|
||||
#include "operators.hh"
|
||||
#endif // PHP_ARMA_OPERATORS
|
||||
|
||||
#include <ext/standard/info.h>
|
||||
|
||||
|
@ -23,9 +23,9 @@ PHP_MINIT_FUNCTION(arma)
|
|||
php_arma::base_init();
|
||||
php_arma::mapval_init();
|
||||
|
||||
#ifdef PHP_ARMA_OPERATOR
|
||||
php_arma::operator_init();
|
||||
#endif // PHP_ARMA_OPERATOR
|
||||
#ifdef PHP_ARMA_OPERATORS
|
||||
php_arma::operators_init();
|
||||
#endif // PHP_ARMA_OPERATORS
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,22 @@ extern zend_module_entry arma_module_entry;
|
|||
static constexpr const char val[] = name; \
|
||||
}
|
||||
|
||||
#ifdef PHP_ARMA_OPERATORS
|
||||
|
||||
/// Helper macros for handling operator overloading.
|
||||
|
||||
#define PHP_ARMA_OPERATOR_BEGIN(ce, parent_ce) \
|
||||
{ \
|
||||
auto _ce = ce; \
|
||||
if (instanceof_function(_ce, parent_ce)) {
|
||||
|
||||
#define PHP_ARMA_OPERATOR_END() \
|
||||
return false; \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif // PHP_ARMA_OPERATORS
|
||||
|
||||
namespace php_arma
|
||||
{
|
||||
/// Helpers for compile-time string concatenation for better module startup performance.
|
||||
|
|
|
@ -1 +1,18 @@
|
|||
<?php
|
||||
|
||||
namespace Arma;
|
||||
|
||||
/**
|
||||
* Support status of option features.
|
||||
*
|
||||
* Values of constants in this class is dependent.
|
||||
*
|
||||
* @package Arma
|
||||
*/
|
||||
abstract class Features
|
||||
{
|
||||
/**
|
||||
* Whether operator overloading is supported.
|
||||
*/
|
||||
const OPERATORS = true;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
--TEST--
|
||||
Test for constants.
|
||||
--SKIPIF--
|
||||
<?php require_once 'includes/loaded.php'; ?>
|
||||
<?php
|
||||
require_once 'includes/loaded.php';
|
||||
is_php_arma_loaded();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
--TEST--
|
||||
Test for `Arma\Complex`.
|
||||
--SKIPIF--
|
||||
<?php require_once 'includes/loaded.php'; ?>
|
||||
<?php
|
||||
require_once 'includes/loaded.php';
|
||||
is_php_arma_loaded();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
|
|
|
@ -1 +1,38 @@
|
|||
--TEST--
|
||||
Test for `Arma\Complex`.
|
||||
--SKIPIF--
|
||||
<?php
|
||||
require_once 'includes/loaded.php';
|
||||
require_once 'includes/supports.php';
|
||||
if (is_php_arma_loaded()) {
|
||||
supports_operator_overloading();
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once 'includes/assert.php';
|
||||
|
||||
$foo = new Arma\CxDouble(1.2, 1.7);
|
||||
$bar = new Arma\CxDouble(2.3, 2.6);
|
||||
|
||||
batch_assert('operator overloading of Arma\\Complex',
|
||||
[$foo->add($bar), $foo + $bar],
|
||||
[$foo->sub($bar), $foo - $bar],
|
||||
[$foo->mul($bar), $foo * $bar],
|
||||
[$foo->div($bar), $foo / $bar],
|
||||
[$foo->pow($bar), $foo ** $bar],
|
||||
[$foo->conj(), ~$foo]
|
||||
);
|
||||
|
||||
$foo1 = $foo->add($bar);
|
||||
$bar1 = $bar->pow($foo1);
|
||||
$foo2 = $foo1->sub($bar1);
|
||||
$bar2 = $bar1->div($foo2);
|
||||
$foo3 = $foo2->mul($bar2);
|
||||
$foo *= $bar /= $foo -= $bar **= $foo += $bar;
|
||||
|
||||
batch_assert('operator overloading of Arma\\Complex', [$foo3, $foo]);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
|
|
|
@ -1,5 +1,14 @@
|
|||
<?php
|
||||
|
||||
if (!extension_loaded('arma')) {
|
||||
echo 'skip armadillo extension is not loaded.';
|
||||
/**
|
||||
* Check whether the php-armadillo extension is loaded.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function is_php_arma_loaded() {
|
||||
if (!extension_loaded('arma')) {
|
||||
echo 'skip armadillo extension is not loaded.';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1 +1,14 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Check whether operator overloading is supported.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function supports_operator_overloading() {
|
||||
if (!Arma\Features::OPERATORS) {
|
||||
echo 'skip operator overloading is not supported.';
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
Reference in New Issue