aligned_storage -> optional; add copySize().

This commit is contained in:
CismonX 2019-09-21 07:23:59 +08:00
parent 3fb50eff30
commit cb593e3a39
5 changed files with 72 additions and 33 deletions

View File

@ -67,16 +67,16 @@ namespace php_arma
using n_orig_t = typename ChildT::orig_t::native_t;
using n_subview_t = typename ChildT::subview_t::native_t;
try {
std::aligned_storage_t<sizeof(n_orig_t)> ret;
std::optional<n_orig_t> ret;
auto o1 = Z_OBJ_P(zv1);
decltype(o1) o2;
if (zv2_is_scalar) {
if constexpr (AcceptScalar) {
auto scalar_val = zval_get_scalar<T>(zv2);
if (Z_OBJCE_P(zv1) == ChildT::orig_t::ce) {
call_zobj_scalar_bifunc_op<n_orig_t, n_orig_t>(o1, &scalar_val, &ret, func);
ret = func(to_native_object<n_orig_t>(o1), &scalar_val);
} else if (EXPECTED(Z_OBJCE_P(zv1) == ChildT::subview_t::ce)) {
call_zobj_scalar_bifunc_op<n_orig_t, n_subview_t>(o1, &scalar_val, &ret, func);
ret = func(to_native_object<n_subview_t>(o1), &scalar_val);
} else {
goto not_orig_or_subview;
}
@ -87,17 +87,17 @@ namespace php_arma
o2 = Z_OBJ_P(zv2);
if (Z_OBJCE_P(zv1) == ChildT::orig_t::ce) {
if (Z_OBJCE_P(zv2) == ChildT::orig_t::ce) {
call_zobj_bifunc_op<n_orig_t, n_orig_t>(o1, o2, &ret, func);
ret = func(to_native_object<n_orig_t>(o1), to_native_object<n_orig_t>(o2));
} else if (EXPECTED(Z_OBJCE_P(zv2) == ChildT::subview_t::ce)) {
call_zobj_bifunc_op<n_orig_t, n_orig_t, n_subview_t>(o1, o2, &ret, func);
ret = func(to_native_object<n_orig_t>(o1), to_native_object<n_subview_t>(o2));
} 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) {
call_zobj_bifunc_op<n_orig_t, n_subview_t, n_orig_t>(o1, o2, &ret, func);
ret = func(to_native_object<n_subview_t>(o1), to_native_object<n_orig_t>(o2));
} else if (EXPECTED(Z_OBJCE_P(zv2) == ChildT::subview_t::ce)) {
call_zobj_bifunc_op<n_orig_t, n_subview_t>(o1, o2, &ret, func);
ret = func(to_native_object<n_subview_t>(o1), to_native_object<n_subview_t>(o2));
} else {
goto not_orig_or_subview;
}
@ -111,7 +111,7 @@ namespace php_arma
// Release first operand in case of assign operator to prevent memory leak.
zval_ptr_dtor(zv1);
}
RETVAL_OBJ(ChildT::orig_t::create(std::move(*reinterpret_cast<n_orig_t*>(&ret))));
RETVAL_OBJ(ChildT::orig_t::create(std::move(*ret)));
return true;
} catch (const std::logic_error& err) {
throw_error(err.what());

View File

@ -50,24 +50,23 @@ namespace php_arma
using n_subview_t = typename ChildT::subview_t::native_t;
using dest_t = typename ChildT::with_int_elem_t::orig_t;
using dest_native_t = typename dest_t::native_t;
using n_uint_t = std::invoke_result_t<F, n_orig_t*, n_orig_t*>;
try {
std::aligned_storage_t<sizeof(n_uint_t)> ret;
std::optional<std::invoke_result_t<F, n_orig_t*, n_orig_t*>> ret;
auto o1 = Z_OBJ_P(zv1);
auto o2 = Z_OBJ_P(zv2);
if (Z_OBJCE_P(zv1) == ChildT::orig_t::ce) {
if (Z_OBJCE_P(zv2) == ChildT::orig_t::ce) {
call_zobj_bifunc_op<n_uint_t, n_orig_t>(o1, o2, &ret, func);
ret = func(to_native_object<n_orig_t>(o1), to_native_object<n_orig_t>(o2));
} else if (EXPECTED(Z_OBJCE_P(zv2) == ChildT::subview_t::ce)) {
call_zobj_bifunc_op<n_uint_t, n_orig_t, n_subview_t>(o1, o2, &ret, func);
ret = func(to_native_object<n_orig_t>(o1), to_native_object<n_subview_t>(o2));
} 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) {
call_zobj_bifunc_op<n_uint_t, n_subview_t, n_orig_t>(o1, o2, &ret, func);
ret = func(to_native_object<n_subview_t>(o1), to_native_object<n_orig_t>(o2));
} else if (EXPECTED(Z_OBJCE_P(zv2) == ChildT::subview_t::ce)) {
call_zobj_bifunc_op<n_uint_t, n_subview_t>(o1, o2, &ret, func);
ret = func(to_native_object<n_subview_t>(o1), to_native_object<n_subview_t>(o2));
} else {
goto not_orig_or_subview;
}
@ -76,8 +75,7 @@ namespace php_arma
throw_exception_ex(zend_ce_type_error, "bad comparison, object types should be the same");
return false;
}
RETVAL_OBJ(dest_t::create(std::move(
arma::conv_to<dest_native_t>::from(*reinterpret_cast<n_uint_t*>(&ret)))));
RETVAL_OBJ(dest_t::create(std::move(arma::conv_to<dest_native_t>::from(*ret))));
return true;
} catch (const std::logic_error& err) {
throw_error(err.what());

View File

@ -194,6 +194,35 @@ namespace php_arma
};
}
// Data structures
namespace ds
{
/// Non-subview container objects
struct base {
const arma::uword n_rows;
const arma::uword n_cols;
const arma::uword n_elem;
};
/// Subview objects
struct subview {
arma_aligned const base& parent;
const arma::uword n_rows;
const arma::uword n_cols;
const arma::uword n_elem;
};
/// Diagonal subview objects
struct diagview {
arma_aligned const base& parent;
const arma::uword row_offset;
const arma::uword col_offset;
const arma::uword n_rows;
const arma::uword n_elem;
static constexpr const arma::uword n_cols = 1;
};
}
/// Helper functions for throwing exceptions when errors occur.
zend_always_inline
@ -422,22 +451,6 @@ namespace php_arma
return zend_objects_new(ce);
}
// Helper functions for handling function calls.
template <typename R, typename T1, typename T2 = typename T1::elem_type, typename F>
zend_always_inline
void call_zobj_scalar_bifunc_op(zend_object *o, T2 *v, std::aligned_storage_t<sizeof(R)>* ret, F&& func)
{
new(ret) R(std::move(func(to_native_object<T1>(o), v)));
}
template <typename R, typename T1, typename T2 = T1, typename F>
zend_always_inline
void call_zobj_bifunc_op(zend_object *o1, zend_object *o2, std::aligned_storage_t<sizeof(R)>* ret, F&& func)
{
new(ret) R(std::move(func(to_native_object<T1>(o1), to_native_object<T2>(o2))));
}
/// Helper functions for handling scalar types.
template <typename>

View File

@ -5,10 +5,15 @@
//
#include "resizable.hh"
#include "base.hh"
#include "subview.hh"
#include "diagonal.hh"
#include "mat.hh"
#include "constants.hh"
#include "stream_utils.hh"
#include <variant>
namespace php_arma
{
#ifdef ARMA_USE_HDF5
@ -31,7 +36,30 @@ namespace php_arma
template <typename T, typename T1>
PHP_ARMA_METHOD(resizable, copySize, T, T1)
{
zval *other;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ZVAL(other)
ZEND_PARSE_PARAMETERS_END();
if (UNEXPECTED(Z_TYPE_P(other) != IS_OBJECT || instanceof_function(Z_OBJCE_P(other), base_ce))) {
ex_bad_type(ZSTR_VAL(base_ce->name), zval_get_type_name(other));
return;
}
std::variant<ds::base*, ds::subview*, ds::diagview*> other_native_v;
if (instanceof_function(Z_OBJCE_P(other), diagonal_ce)) {
other_native_v = to_native_object<ds::diagview>(Z_OBJ_P(other));
} else if (instanceof_function(Z_OBJCE_P(other), subview_ce)) {
other_native_v = to_native_object<ds::subview>(Z_OBJ_P(other));
} else {
other_native_v = to_native_object<ds::base>(Z_OBJ_P(other));
}
std::visit([native = THIS_NATIVE, &other_native_v](auto other_native) {
if (std::holds_alternative<decltype(other_native)>(other_native_v)) {
native->set_size(other_native->n_rows, other_native->n_cols);
}
}, other_native_v);
}
template <typename T, typename T1>

View File

@ -18,7 +18,7 @@ interface Resizable
*
* The given object must be of the same root type as the calling object.
*
* @param static $other
* @param Base $other
* @return void
*/
function copySize($other);