// // 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 "stream_utils.hh" #include 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 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 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(Z_OBJ_P(other)); } else { other_native_v = to_native_object(Z_OBJ_P(other)); } } else { other_native_v = to_native_object(Z_OBJ_P(other)); } std::visit([native = THIS_NATIVE, &other_native_v](auto other_native) { if (std::holds_alternative(other_native_v)) { native->set_size(other_native->n_rows, other_native->n_cols); } }, other_native_v); } template PHP_ARMA_METHOD(resizable, reset, T, T1) { auto native = THIS_NATIVE; native->reset(); } template 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(), zval_get_type_name(other)); return; } auto native = THIS_NATIVE; try { native->set_real(*to_native_object(Z_OBJ_P(other))); } catch (const std::logic_error& err) { // Incompatible size. throw_error(err.what()); } } template PHP_ARMA_METHOD(resizable, setImag, T, ChildT) { if constexpr (std::is_same_v) { 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(), zval_get_type_name(other)); return; } auto native = THIS_NATIVE; try { native->set_imag(*to_native_object(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 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 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 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(); } PHP_ARMA_INSTANTIATE(resizable, mat); }