implement arithmetic operations.
This commit is contained in:
parent
586bbe2046
commit
9033f84132
25
src/base.cc
25
src/base.cc
|
@ -26,13 +26,23 @@ namespace php_arma
|
||||||
template <typename T, typename T1>
|
template <typename T, typename T1>
|
||||||
PHP_ARMA_METHOD(base, add, T, T1)
|
PHP_ARMA_METHOD(base, add, T, T1)
|
||||||
{
|
{
|
||||||
|
zval *other;
|
||||||
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||||
|
Z_PARAM_ZVAL(other)
|
||||||
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
|
operators::add(&EX(This), other, return_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename T1>
|
template <typename T, typename T1>
|
||||||
PHP_ARMA_METHOD(base, sub, T, T1)
|
PHP_ARMA_METHOD(base, sub, T, T1)
|
||||||
{
|
{
|
||||||
|
zval *other;
|
||||||
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||||
|
Z_PARAM_ZVAL(other)
|
||||||
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
|
operators::sub(&EX(This), other, return_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename T1>
|
template <typename T, typename T1>
|
||||||
|
@ -44,19 +54,34 @@ namespace php_arma
|
||||||
template <typename T, typename T1>
|
template <typename T, typename T1>
|
||||||
PHP_ARMA_METHOD(base, mul, T, T1)
|
PHP_ARMA_METHOD(base, mul, T, T1)
|
||||||
{
|
{
|
||||||
|
zval *other;
|
||||||
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||||
|
Z_PARAM_ZVAL(other)
|
||||||
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
|
operators::add(&EX(This), other, return_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename T1>
|
template <typename T, typename T1>
|
||||||
PHP_ARMA_METHOD(base, dotMul, T, T1)
|
PHP_ARMA_METHOD(base, dotMul, T, T1)
|
||||||
{
|
{
|
||||||
|
zval *other;
|
||||||
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||||
|
Z_PARAM_ZVAL(other)
|
||||||
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
|
operators::dotMul(&EX(This), other, return_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename T1>
|
template <typename T, typename T1>
|
||||||
PHP_ARMA_METHOD(base, div, T, T1)
|
PHP_ARMA_METHOD(base, div, T, T1)
|
||||||
{
|
{
|
||||||
|
zval *other;
|
||||||
|
ZEND_PARSE_PARAMETERS_START(1, 1)
|
||||||
|
Z_PARAM_ZVAL(other)
|
||||||
|
ZEND_PARSE_PARAMETERS_END();
|
||||||
|
|
||||||
|
operators::div(&EX(This), other, return_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T, typename T1>
|
template <typename T, typename T1>
|
||||||
|
|
99
src/base.hh
99
src/base.hh
|
@ -8,6 +8,7 @@
|
||||||
#define PHP_ARMA_BASE_HH
|
#define PHP_ARMA_BASE_HH
|
||||||
|
|
||||||
#include "php_arma.hh"
|
#include "php_arma.hh"
|
||||||
|
#include "complex.hh"
|
||||||
|
|
||||||
namespace php_arma
|
namespace php_arma
|
||||||
{
|
{
|
||||||
|
@ -18,6 +19,71 @@ namespace php_arma
|
||||||
|
|
||||||
struct operators;
|
struct operators;
|
||||||
|
|
||||||
|
template <bool AcceptScalar, typename F>
|
||||||
|
zend_always_inline
|
||||||
|
static bool arithmetic_op(zval *zv1, zval *zv2, zval *return_value, F&& func)
|
||||||
|
{
|
||||||
|
bool zv2_is_scalar = false;
|
||||||
|
if (Z_TYPE_P(zv2) != IS_OBJECT) {
|
||||||
|
if constexpr (AcceptScalar && !std::is_same_v<T, cx_double>) {
|
||||||
|
if (EXPECTED(zval_is_scalar<T>(zv2))) {
|
||||||
|
zv2_is_scalar = true;
|
||||||
|
goto op_body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw_exception_ex(zend_ce_type_error, "bad arithmetic operation, unsupported type");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
op_body:
|
||||||
|
using n_orig_t = typename ChildT::orig_t::native_t;
|
||||||
|
using n_subview_t = typename ChildT::subview_t::native_t;
|
||||||
|
try {
|
||||||
|
n_orig_t ret;
|
||||||
|
auto o1 = Z_OBJ_P(zv1);
|
||||||
|
auto o2 = Z_OBJ_P(zv2);
|
||||||
|
if (zv2_is_scalar) {
|
||||||
|
if constexpr (AcceptScalar) {
|
||||||
|
auto scalar_val = zval_get_scalar<T>(zv2);
|
||||||
|
if (Z_OBJCE_P(zv1) == ChildT::orig_t::ce) {
|
||||||
|
ret = func(to_native_object<n_orig_t>(o1), &scalar_val).eval();
|
||||||
|
} else if (EXPECTED(Z_OBJCE_P(zv1) == ChildT::subview_t::ce)) {
|
||||||
|
ret = func(to_native_object<n_subview_t>(o1), &scalar_val).eval();
|
||||||
|
} else {
|
||||||
|
goto not_orig_or_subview;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (Z_OBJCE_P(zv1) == ChildT::orig_t::ce) {
|
||||||
|
if (Z_OBJCE_P(zv2) == ChildT::orig_t::ce) {
|
||||||
|
ret = func(to_native_object<n_orig_t>(o1), to_native_object<n_orig_t>(o2)).eval();
|
||||||
|
} else if (EXPECTED(Z_OBJCE_P(zv2) == ChildT::subview_t::ce)) {
|
||||||
|
ret = func(to_native_object<n_orig_t>(o1), to_native_object<n_subview_t>(o2)).eval();
|
||||||
|
} else {
|
||||||
|
goto not_orig_or_subview;
|
||||||
|
}
|
||||||
|
} else if (EXPECTED(Z_OBJCE_P(zv1) == ChildT::subview_t::ce)) {
|
||||||
|
if (Z_OBJCE_P(zv2) == ChildT::orig_t::ce) {
|
||||||
|
ret = func(to_native_object<n_subview_t>(o1), to_native_object<n_orig_t>(o2)).eval();
|
||||||
|
} else if (EXPECTED(Z_OBJCE_P(zv2) == ChildT::subview_t::ce)) {
|
||||||
|
ret = func(to_native_object<n_subview_t>(o1), to_native_object<n_subview_t>(o2)).eval();
|
||||||
|
} else {
|
||||||
|
goto not_orig_or_subview;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
not_orig_or_subview:
|
||||||
|
throw_exception_ex(zend_ce_type_error, "bad arithmetic operation, object types should be the same");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RETVAL_OBJ(ChildT::orig_t::create(std::move(ret)));
|
||||||
|
return true;
|
||||||
|
} catch (const std::logic_error& err) {
|
||||||
|
throw_error(err.what());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
zend_always_inline
|
zend_always_inline
|
||||||
static int count_elements(zval *zv, zend_long *count)
|
static int count_elements(zval *zv, zend_long *count)
|
||||||
{
|
{
|
||||||
|
@ -59,7 +125,40 @@ namespace php_arma
|
||||||
template <typename T, typename ChildT>
|
template <typename T, typename ChildT>
|
||||||
struct base<T, ChildT>::operators
|
struct base<T, ChildT>::operators
|
||||||
{
|
{
|
||||||
|
static bool add(zval *zv1, zval *zv2, zval *retval)
|
||||||
|
{
|
||||||
|
return arithmetic_op<true>(zv1, zv2, retval, [](auto v1, auto v2) {
|
||||||
|
return *v1 + *v2;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool sub(zval *zv1, zval *zv2, zval *retval)
|
||||||
|
{
|
||||||
|
return arithmetic_op<true>(zv1, zv2, retval, [](auto v1, auto v2) {
|
||||||
|
return *v1 - *v2;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool mul(zval *zv1, zval *zv2, zval *retval)
|
||||||
|
{
|
||||||
|
return arithmetic_op<true>(zv1, zv2, retval, [](auto v1, auto v2) {
|
||||||
|
return *v1 * *v2;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool dotMul(zval *zv1, zval *zv2, zval *retval)
|
||||||
|
{
|
||||||
|
return arithmetic_op<false>(zv1, zv2, retval, [](auto v1, auto v2) {
|
||||||
|
return *v1 % *v2;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool div(zval *zv1, zval *zv2, zval *retval)
|
||||||
|
{
|
||||||
|
return arithmetic_op<true>(zv1, zv2, retval, [](auto v1, auto v2) {
|
||||||
|
return *v1 / *v2;
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ interface Base extends Countable
|
||||||
/**
|
/**
|
||||||
* Addition of two objects.
|
* Addition of two objects.
|
||||||
*
|
*
|
||||||
* @param mixed $other
|
* @param static|number|Complex $other
|
||||||
* @return static
|
* @return static
|
||||||
*/
|
*/
|
||||||
function add($other);
|
function add($other);
|
||||||
|
@ -30,7 +30,7 @@ interface Base extends Countable
|
||||||
/**
|
/**
|
||||||
* Subtraction of two objects.
|
* Subtraction of two objects.
|
||||||
*
|
*
|
||||||
* @param mixed $other
|
* @param static|number|Complex $other
|
||||||
* @return static
|
* @return static
|
||||||
*/
|
*/
|
||||||
function sub($other);
|
function sub($other);
|
||||||
|
@ -45,7 +45,7 @@ interface Base extends Countable
|
||||||
/**
|
/**
|
||||||
* Matrix multiplication of two objects.
|
* Matrix multiplication of two objects.
|
||||||
*
|
*
|
||||||
* @param mixed $other
|
* @param static|number|Complex $other
|
||||||
* @return static
|
* @return static
|
||||||
*/
|
*/
|
||||||
function mul($other);
|
function mul($other);
|
||||||
|
@ -61,7 +61,7 @@ interface Base extends Countable
|
||||||
/**
|
/**
|
||||||
* Element-wise division of an object by another object or a scalar.
|
* Element-wise division of an object by another object or a scalar.
|
||||||
*
|
*
|
||||||
* @param mixed $other
|
* @param static|number|Complex $other
|
||||||
* @return static
|
* @return static
|
||||||
*/
|
*/
|
||||||
function div($other);
|
function div($other);
|
||||||
|
|
Reference in New Issue
Block a user