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/dense_matrix.cc

257 lines
7.5 KiB
C++

//
// 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 <typename T, typename ChildT>
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<ChildT>(&EX(This));
zend_object *zobj;
try {
if (EX_NUM_ARGS() == 1) {
zobj = mapval_dense<T>::create(parent, &native->operator()(i));
} else {
zobj = mapval_dense<T>::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 <typename T, typename ChildT>
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<ChildT>(&EX(This));
zend_object *zobj;
if (EX_NUM_ARGS() == 1) {
zobj = mapval_dense<T>::create(parent, &native->operator[](i));
} else {
zobj = mapval_dense<T>::create(parent, &native->at(i, j));
}
RETVAL_OBJ(zobj);
}
template <typename T, typename T1>
PHP_ARMA_METHOD(dense_matrix, col, T, T1)
{
}
template <typename T, typename T1>
PHP_ARMA_METHOD(dense_matrix, row, T, T1)
{
}
template <typename T, typename ChildT>
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<ChildT>(&EX(This));
auto zobj = ret_t::create(parent, std::move(native->cols(first_col, last_col)));
RETVAL_OBJ(zobj);
}
template <typename T, typename ChildT>
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<ChildT>(&EX(This));
auto zobj = ret_t::create(parent, std::move(native->rows(first_row, last_row)));
RETVAL_OBJ(zobj);
}
template <typename T, typename ChildT>
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<ChildT>(&EX(This));
auto zobj = ret_t::create(parent, std::move(native->submat(first_row, first_col, last_row, last_col)));
RETVAL_OBJ(zobj);
}
template <typename T, typename ChildT>
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<ChildT>(&EX(This));
zend_object *zobj;
try {
zobj = diagview<T>::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 <typename T, typename T1>
PHP_ARMA_METHOD(dense_matrix, eachRow, T, T1)
{
}
template <typename T, typename T1>
PHP_ARMA_METHOD(dense_matrix, eachCol, T, T1)
{
}
template <typename T, typename ChildT>
PHP_ARMA_METHOD(dense_matrix, i, T, ChildT)
{
if constexpr (std::is_same_v<T, zend_long>) {
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 <typename T, typename T1>
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<T, zend_long>) {
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<T>::result;
if (!zval_check_scalar<base_t>(tol)) {
return;
}
RETVAL_BOOL(native->is_sympd(zval_get_scalar<base_t>(tol)));
}
}
template <typename T, typename T1>
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_matrix_php_name>(dense_ce, matrix_ce);
}
PHP_ARMA_INSTANTIATE(dense_matrix, mat);
PHP_ARMA_INSTANTIATE(dense_matrix, subview_mat);
}