// // php-armadillo/dense_matrix.cc // // @Author CismonX // #include "dense_matrix.hh" #include "dense.hh" #include "matrix.hh" #include "mapval.hh" #include "mat.hh" #include "subview_mat.hh" #include "diagonal.hh" namespace php_arma { template PHP_ARMA_METHOD(dense_matrix, __invoke, T, ChildT) { zend_long i, j; ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_LONG(i) Z_PARAM_OPTIONAL Z_PARAM_LONG(j) ZEND_PARSE_PARAMETERS_END(); auto native = THIS_NATIVE; auto parent = get_parent_zval(&EX(This)); zend_object *zobj; try { if (EX_NUM_ARGS() == 1) { zobj = mapval_dense::create(parent, &native->operator()(i)); } else { zobj = mapval_dense::create(parent, &native->operator()(i, j)); } } catch (const std::logic_error& err) { // Index out of bounds. throw_exception(err.what()); return; } RETVAL_OBJ(zobj); } template PHP_ARMA_METHOD(dense_matrix, at, T, ChildT) { zend_long i, j; ZEND_PARSE_PARAMETERS_START(1, 2) Z_PARAM_LONG(i) Z_PARAM_OPTIONAL Z_PARAM_LONG(j) ZEND_PARSE_PARAMETERS_END(); auto native = THIS_NATIVE; auto parent = get_parent_zval(&EX(This)); zend_object *zobj; if (EX_NUM_ARGS() == 1) { zobj = mapval_dense::create(parent, &native->operator[](i)); } else { zobj = mapval_dense::create(parent, &native->at(i, j)); } RETVAL_OBJ(zobj); } template PHP_ARMA_METHOD(dense_matrix, col, T, T1) { } template PHP_ARMA_METHOD(dense_matrix, row, T, T1) { } template PHP_ARMA_METHOD(dense_matrix, cols, T, ChildT) { zend_long first_col, last_col; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_LONG(first_col) Z_PARAM_LONG(last_col) ZEND_PARSE_PARAMETERS_END(); using ret_t = typename ChildT::subview_t; auto native = THIS_NATIVE; auto parent = get_parent_zval(&EX(This)); auto zobj = ret_t::create(parent, std::move(native->cols(first_col, last_col))); RETVAL_OBJ(zobj); } template PHP_ARMA_METHOD(dense_matrix, rows, T, ChildT) { zend_long first_row, last_row; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_LONG(first_row) Z_PARAM_LONG(last_row) ZEND_PARSE_PARAMETERS_END(); using ret_t = typename ChildT::subview_t; auto native = THIS_NATIVE; auto parent = get_parent_zval(&EX(This)); auto zobj = ret_t::create(parent, std::move(native->rows(first_row, last_row))); RETVAL_OBJ(zobj); } template PHP_ARMA_METHOD(dense_matrix, submat, T, ChildT) { zend_long first_row, first_col, last_row, last_col; ZEND_PARSE_PARAMETERS_START(4, 4) Z_PARAM_LONG(first_row) Z_PARAM_LONG(first_col) Z_PARAM_LONG(last_row) Z_PARAM_LONG(last_col) ZEND_PARSE_PARAMETERS_END(); using ret_t = typename ChildT::subview_t; auto native = THIS_NATIVE; auto parent = get_parent_zval(&EX(This)); auto zobj = ret_t::create(parent, std::move(native->submat(first_row, first_col, last_row, last_col))); RETVAL_OBJ(zobj); } template PHP_ARMA_METHOD(dense_matrix, diag, T, ChildT) { zend_long k = 0; ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL Z_PARAM_LONG(k) ZEND_PARSE_PARAMETERS_END(); auto native = THIS_NATIVE; auto parent = get_parent_zval(&EX(This)); zend_object *zobj; try { zobj = diagview::create(parent, std::move(native->diag(k))); } catch (const std::logic_error& err) { // requested diagonal out of bounds throw_exception(err.what()); return; } RETVAL_OBJ(zobj); } template PHP_ARMA_METHOD(dense_matrix, eachRow, T, T1) { } template PHP_ARMA_METHOD(dense_matrix, eachCol, T, T1) { } template PHP_ARMA_METHOD(dense_matrix, i, T, ChildT) { if constexpr (std::is_same_v) { throw_error("cannot calculate inverse of IMat."); } else { zend_bool inv_sympd = false; ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL Z_PARAM_BOOL(inv_sympd) ZEND_PARSE_PARAMETERS_END(); using ret_t = typename ChildT::orig_t; auto native = THIS_NATIVE; zend_object *zobj; try { if (inv_sympd) { zobj = ret_t::create(std::move(arma::inv_sympd(*native).eval())); } else { zobj = ret_t::create(std::move(native->i().eval())); } } catch (const std::logic_error& err) { // Matrix not square sized. throw_error(err.what()); } catch (const std::runtime_error& err) { if (inv_sympd) { throw_exception("matrix is singular or not positive definite"); } else { throw_exception("matrix seems singular"); } return; } RETVAL_OBJ(zobj); } } template PHP_ARMA_METHOD(dense_matrix, isSympd, T, T1) { zval *tol = nullptr; ZEND_PARSE_PARAMETERS_START(0, 1) Z_PARAM_OPTIONAL Z_PARAM_ZVAL(tol) ZEND_PARSE_PARAMETERS_END(); auto native = THIS_NATIVE; if constexpr (std::is_same_v) { throw_error("method isSympd() is not supported on IMat"); } else { if (tol == nullptr) { RETURN_BOOL(native->is_sympd()); } using base_t = typename arma::get_pod_type::result; if (!zval_check_scalar(tol)) { return; } RETVAL_BOOL(native->is_sympd(zval_get_scalar(tol))); } } template PHP_ARMA_START_ME(dense_matrix, T, T1) PHP_ARMA_ME(__invoke, ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER) PHP_ARMA_ME(at, ZEND_ACC_PUBLIC) PHP_ARMA_ME(col, ZEND_ACC_PUBLIC) PHP_ARMA_ME(row, ZEND_ACC_PUBLIC) PHP_ARMA_ME(cols, ZEND_ACC_PUBLIC) PHP_ARMA_ME(rows, ZEND_ACC_PUBLIC) PHP_ARMA_ME(submat, ZEND_ACC_PUBLIC) PHP_ARMA_ME(diag, ZEND_ACC_PUBLIC) PHP_ARMA_ME(eachRow, ZEND_ACC_PUBLIC) PHP_ARMA_ME(eachCol, ZEND_ACC_PUBLIC) PHP_ARMA_ME(i, ZEND_ACC_PUBLIC) PHP_ARMA_ME(isSympd, ZEND_ACC_PUBLIC) PHP_ARMA_END_ME(); void dense_matrix_init() { dense_matrix_ce = interface_register(dense_ce, matrix_ce); } PHP_ARMA_INSTANTIATE(dense_matrix, mat); PHP_ARMA_INSTANTIATE(dense_matrix, subview_mat); }