implement arithmetic operations.
This commit is contained in:
parent
586bbe2046
commit
9033f84132
35
src/base.cc
35
src/base.cc
|
@ -26,13 +26,23 @@ namespace php_arma
|
|||
template <typename T, typename 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>
|
||||
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>
|
||||
|
@ -44,19 +54,34 @@ namespace php_arma
|
|||
template <typename T, typename 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>
|
||||
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>
|
||||
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>
|
||||
|
|
101
src/base.hh
101
src/base.hh
|
@ -8,6 +8,7 @@
|
|||
#define PHP_ARMA_BASE_HH
|
||||
|
||||
#include "php_arma.hh"
|
||||
#include "complex.hh"
|
||||
|
||||
namespace php_arma
|
||||
{
|
||||
|
@ -18,6 +19,71 @@ namespace php_arma
|
|||
|
||||
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
|
||||
static int count_elements(zval *zv, zend_long *count)
|
||||
{
|
||||
|
@ -59,7 +125,40 @@ namespace php_arma
|
|||
template <typename T, typename ChildT>
|
||||
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.
|
||||
*
|
||||
* @param mixed $other
|
||||
* @param static|number|Complex $other
|
||||
* @return static
|
||||
*/
|
||||
function add($other);
|
||||
|
@ -30,7 +30,7 @@ interface Base extends Countable
|
|||
/**
|
||||
* Subtraction of two objects.
|
||||
*
|
||||
* @param mixed $other
|
||||
* @param static|number|Complex $other
|
||||
* @return static
|
||||
*/
|
||||
function sub($other);
|
||||
|
@ -45,7 +45,7 @@ interface Base extends Countable
|
|||
/**
|
||||
* Matrix multiplication of two objects.
|
||||
*
|
||||
* @param mixed $other
|
||||
* @param static|number|Complex $other
|
||||
* @return static
|
||||
*/
|
||||
function mul($other);
|
||||
|
@ -61,7 +61,7 @@ interface Base extends Countable
|
|||
/**
|
||||
* Element-wise division of an object by another object or a scalar.
|
||||
*
|
||||
* @param mixed $other
|
||||
* @param static|number|Complex $other
|
||||
* @return static
|
||||
*/
|
||||
function div($other);
|
||||
|
|
Reference in New Issue
Block a user