257 lines
7.5 KiB
C++
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);
|
|
}
|