Add operator overloading for Complex.
This commit is contained in:
parent
3e31b779e5
commit
e6b572a3eb
|
@ -1,20 +0,0 @@
|
|||
//
|
||||
// php-armadillo/operator.cc
|
||||
//
|
||||
// @Author CismonX
|
||||
//
|
||||
|
||||
#include "php_arma.hh"
|
||||
|
||||
namespace php_arma
|
||||
{
|
||||
int assign_handler(zend_execute_data *ex)
|
||||
{
|
||||
return ZEND_USER_OPCODE_DISPATCH;
|
||||
}
|
||||
|
||||
void operator_init()
|
||||
{
|
||||
zend_set_user_opcode_handler(ZEND_ASSIGN, assign_handler);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,246 @@
|
|||
//
|
||||
// php-armadillo/operators.cc
|
||||
//
|
||||
// @Author CismonX
|
||||
//
|
||||
|
||||
#include "php_arma.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)
|
||||
#endif
|
||||
|
||||
namespace php_arma
|
||||
{
|
||||
zend_always_inline
|
||||
zval *get_zval_ptr_undef(
|
||||
zend_uchar op_type,
|
||||
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);
|
||||
case IS_CONST:
|
||||
return EX_CONSTANT(op);
|
||||
case IS_CV:
|
||||
return EX_VAR(op.var);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
zend_always_inline
|
||||
bool opcode_is_greater(const zend_op *opline)
|
||||
{
|
||||
switch (opline->opcode) {
|
||||
case ZEND_IS_SMALLER:
|
||||
case ZEND_IS_SMALLER_OR_EQUAL:
|
||||
return opline->extended_value == 1;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename F>
|
||||
zend_always_inline
|
||||
int op_handler(zend_execute_data *execute_data, F handler)
|
||||
{
|
||||
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_DEREF(op1);
|
||||
ZVAL_DEREF(op2);
|
||||
|
||||
if (UNEXPECTED(opcode_is_greater(opline))) {
|
||||
std::swap(op1, op2);
|
||||
std::swap(free_op1, free_op2);
|
||||
}
|
||||
|
||||
if (!handler(op1, op2, EX_VAR(opline->result.var))) {
|
||||
return ZEND_USER_OPCODE_DISPATCH;
|
||||
}
|
||||
|
||||
if (free_op2) {
|
||||
zval_ptr_dtor_nogc(free_op2);
|
||||
}
|
||||
if (free_op1) {
|
||||
zval_ptr_dtor_nogc(free_op1);
|
||||
}
|
||||
EX(opline) = opline + 1;
|
||||
return ZEND_USER_OPCODE_CONTINUE;
|
||||
}
|
||||
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PHP_ARMA_OPERATOR_BEGIN(Z_OBJCE_P(zv1), complex_ce)
|
||||
PHP_ARMA_COMPLEX_OPERATOR(double, add)
|
||||
PHP_ARMA_OPERATOR_END();
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
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 false;
|
||||
}
|
||||
|
||||
PHP_ARMA_OPERATOR_BEGIN(Z_OBJCE_P(zv1), complex_ce)
|
||||
PHP_ARMA_COMPLEX_OPERATOR_ASSIGN(double, add)
|
||||
PHP_ARMA_OPERATOR_END();
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PHP_ARMA_OPERATOR_BEGIN(Z_OBJCE_P(zv1), complex_ce)
|
||||
PHP_ARMA_COMPLEX_OPERATOR(double, sub)
|
||||
PHP_ARMA_OPERATOR_END();
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
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 false;
|
||||
}
|
||||
|
||||
PHP_ARMA_OPERATOR_BEGIN(Z_OBJCE_P(zv1), complex_ce)
|
||||
PHP_ARMA_COMPLEX_OPERATOR_ASSIGN(double, sub)
|
||||
PHP_ARMA_OPERATOR_END();
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PHP_ARMA_OPERATOR_BEGIN(Z_OBJCE_P(zv1), complex_ce)
|
||||
PHP_ARMA_COMPLEX_OPERATOR(double, mul)
|
||||
PHP_ARMA_OPERATOR_END();
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
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 false;
|
||||
}
|
||||
|
||||
PHP_ARMA_OPERATOR_BEGIN(Z_OBJCE_P(zv1), complex_ce)
|
||||
PHP_ARMA_COMPLEX_OPERATOR_ASSIGN(double, mul)
|
||||
PHP_ARMA_OPERATOR_END();
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PHP_ARMA_OPERATOR_BEGIN(Z_OBJCE_P(zv1), complex_ce)
|
||||
PHP_ARMA_COMPLEX_OPERATOR(double, div)
|
||||
PHP_ARMA_OPERATOR_END();
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
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 false;
|
||||
}
|
||||
|
||||
PHP_ARMA_OPERATOR_BEGIN(Z_OBJCE_P(zv1), complex_ce)
|
||||
PHP_ARMA_COMPLEX_OPERATOR_ASSIGN(double, div)
|
||||
PHP_ARMA_OPERATOR_END();
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PHP_ARMA_OPERATOR_BEGIN(Z_OBJCE_P(zv1), complex_ce)
|
||||
PHP_ARMA_COMPLEX_OPERATOR(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) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PHP_ARMA_OPERATOR_BEGIN(Z_OBJCE_P(zv1), complex_ce)
|
||||
PHP_ARMA_COMPLEX_OPERATOR(double, conj)
|
||||
PHP_ARMA_OPERATOR_END();
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
void operator_init()
|
||||
{
|
||||
zend_set_user_opcode_handler(ZEND_ADD, add_handler);
|
||||
zend_set_user_opcode_handler(ZEND_ASSIGN_ADD, add_assign_handler);
|
||||
zend_set_user_opcode_handler(ZEND_SUB, sub_handler);
|
||||
zend_set_user_opcode_handler(ZEND_ASSIGN_SUB, sub_assign_handler);
|
||||
zend_set_user_opcode_handler(ZEND_MUL, mul_handler);
|
||||
zend_set_user_opcode_handler(ZEND_ASSIGN_MUL, mul_assign_handler);
|
||||
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_BW_NOT, bw_not_handler);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
//
|
||||
// php-armadillo/operator.hh
|
||||
// php-armadillo/operators.hh
|
||||
//
|
||||
// @Author CismonX
|
||||
//
|
|
@ -0,0 +1 @@
|
|||
<?php
|
|
@ -0,0 +1 @@
|
|||
<?php
|
|
@ -0,0 +1 @@
|
|||
<?php
|
Reference in New Issue