This repository has been archived on 2020-06-07. You can view files and clone it, but cannot push or open issues or pull requests.
php-armadillo/src/resizable.cc

229 lines
7.3 KiB
C++

//
// php-armadillo/resizable.cc
//
// @Author CismonX
//
#include "resizable.hh"
#include "base.hh"
#include "subview.hh"
#include "diagonal.hh"
#include "mat.hh"
#include "constants.hh"
#include "common/stream_utils.hh"
#include <variant>
namespace php_arma
{
#ifdef ARMA_USE_HDF5
zend_always_inline
arma::hdf5_name zend_array_to_hdf5_name(zend_array *ht)
{
auto fname_z = zend_hash_str_find(ht, "file_name", sizeof("file_name") - 1);
std::string fname(fname_z && Z_TYPE_P(fname_z) == IS_STRING ? Z_STRVAL_P(fname_z) : "");
auto dsname_z = zend_hash_str_find(ht, "dataset_name", sizeof("dataset_name") - 1);
std::string dsname(dsname_z && Z_TYPE_P(dsname_z) == IS_STRING ? Z_STRVAL_P(dsname_z) : "");
auto opts_z = zend_hash_str_find(ht, "options", sizeof("options") - 1);
arma::hdf5_opts::opts opts(opts_z && Z_TYPE_P(opts_z) == IS_LONG ? Z_LVAL_P(opts_z) : hdf5_opts::none);
return { fname, dsname, opts };
}
#endif
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), subview_ce)) {
if (instanceof_function(Z_OBJCE_P(other), diagonal_ce)) {
other_native_v = to_native_object<ds::diagview>(Z_OBJ_P(other));
} else {
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>
PHP_ARMA_METHOD(resizable, reset, T, T1)
{
auto native = THIS_NATIVE;
native->reset();
}
template <typename T, typename ChildT>
PHP_ARMA_METHOD(resizable, setReal, T, ChildT)
{
zval *other;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_OBJECT(other)
ZEND_PARSE_PARAMETERS_END();
using pod_t = typename ChildT::with_pod_elem_t;
using n_pod_t = typename pod_t::native_t;
if (UNEXPECTED(pod_t::ce != Z_OBJCE_P(other))) {
ex_bad_type(get_type_name<pod_t>(), zval_get_type_name(other));
return;
}
auto native = THIS_NATIVE;
try {
native->set_real(*to_native_object<n_pod_t>(Z_OBJ_P(other)));
} catch (const std::logic_error& err) {
// Incompatible size.
throw_error(err.what());
}
}
template <typename T, typename ChildT>
PHP_ARMA_METHOD(resizable, setImag, T, ChildT)
{
if constexpr (std::is_same_v<T, cx_double>) {
zval *other;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_OBJECT(other)
ZEND_PARSE_PARAMETERS_END();
using pod_t = typename ChildT::with_pod_elem_t;
using n_pod_t = typename pod_t::native_t;
if (UNEXPECTED(pod_t::ce != Z_OBJCE_P(other))) {
ex_bad_type(get_type_name<pod_t>(), zval_get_type_name(other));
return;
}
auto native = THIS_NATIVE;
try {
native->set_imag(*to_native_object<n_pod_t>(Z_OBJ_P(other)));
} catch (const std::logic_error& err) {
// Incompatible size.
throw_error(err.what());
}
} else {
throw_error("no such operation for objects with non-complex elements");
}
}
template <typename T, typename T1>
PHP_ARMA_METHOD(resizable, save, T, T1)
{
zval *dest;
zend_long file_type = file_type::arma_binary;
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_ZVAL(dest)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(file_type)
ZEND_PARSE_PARAMETERS_END();
auto native = THIS_NATIVE;
auto ftype = file_type::native(file_type);
zend_bool retval;
if (Z_TYPE_P(dest) == IS_STRING) {
RETURN_BOOL(native->save(Z_STRVAL_P(dest), ftype, false));
}
if (Z_TYPE_P(dest) == IS_RESOURCE) {
Z_OSTREAM_P(dest, os);
if constexpr (zval_to_iostream_supported) {
RETURN_BOOL(native->save(os, ftype, false));
} else {
RETURN_FALSE;
}
}
#ifdef ARMA_USE_HDF5
if (Z_TYPE_P(dest) == IS_ARRAY) {
if (ftype != arma::file_type::hdf5_binary) {
ex_bad_type("string or resource", zval_get_type_name(dest));
RETURN_FALSE;
}
RETURN_BOOL(native->save(zend_array_to_hdf5_name(Z_ARR_P(dest)), ftype, false));
}
ex_bad_type("string, resource or array", zval_get_type_name(dest));
#else
ex_bad_type("string or resource", zval_get_type_name(dest));
#endif // ARMA_USE_HDF5
RETURN_FALSE;
}
template <typename T, typename T1>
PHP_ARMA_METHOD(resizable, load, T, T1)
{
zval *from;
zend_long file_type = file_type::auto_detect;
ZEND_PARSE_PARAMETERS_START(1, 2)
Z_PARAM_ZVAL(from)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(file_type)
ZEND_PARSE_PARAMETERS_END();
auto native = THIS_NATIVE;
auto ftype = file_type::native(file_type);
zend_bool retval;
if (Z_TYPE_P(from) == IS_STRING) {
RETURN_BOOL(native->load(Z_STRVAL_P(from), ftype, false));
}
if (Z_TYPE_P(from) == IS_RESOURCE) {
Z_ISTREAM_P(from, is);
if constexpr (zval_to_iostream_supported) {
RETURN_BOOL(native->load(is, ftype, false));
} else {
RETURN_FALSE;
}
}
#ifdef ARMA_USE_HDF5
if (Z_TYPE_P(from) == IS_ARRAY) {
if (ftype != arma::file_type::hdf5_binary) {
ex_bad_type("string or resource", zval_get_type_name(from));
RETURN_FALSE;
}
RETURN_BOOL(native->load(zend_array_to_hdf5_name(Z_ARR_P(from)), ftype, false));
}
ex_bad_type("string, resource or array", zval_get_type_name(from));
#else
ex_bad_type("string or resource", zval_get_type_name(from));
#endif // ARMA_USE_HDF5
RETURN_FALSE;
}
template <typename T, typename T1>
PHP_ARMA_START_ME(resizable, T, T1)
PHP_ARMA_ME(copySize, ZEND_ACC_PUBLIC)
PHP_ARMA_ME(reset, ZEND_ACC_PUBLIC)
PHP_ARMA_ME(setReal, ZEND_ACC_PUBLIC)
PHP_ARMA_ME(setImag, ZEND_ACC_PUBLIC)
PHP_ARMA_ME(save, ZEND_ACC_PUBLIC)
PHP_ARMA_ME(load, ZEND_ACC_PUBLIC)
PHP_ARMA_END_ME();
void resizable_init()
{
resizable_ce = interface_register<resizable_php_name>();
}
PHP_ARMA_INSTANTIATE(resizable, mat);
}