Implement `Mat::fromArray()`. Add tests.

This commit is contained in:
CismonX 2019-05-30 00:50:39 +08:00
parent c3402e0abe
commit 6cf646a6d0
6 changed files with 120 additions and 0 deletions

View File

@ -48,10 +48,60 @@ namespace php_arma
RETVAL_OBJ(zobj);
}
template <typename T>
PHP_ARMA_METHOD(mat, fromArray, T)
{
zval *arr;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_ARRAY_DEREF(arr)
ZEND_PARSE_PARAMETERS_END();
auto num_rows = zend_hash_num_elements(Z_ARR_P(arr));
if (UNEXPECTED(num_rows == 0)) {
RETURN_OBJ(create());
}
auto first_row = zend_hash_index_find(Z_ARR_P(arr), 0);
if (UNEXPECTED(first_row == nullptr || Z_TYPE_P(first_row) != IS_ARRAY)) {
zend_throw_exception(zend_ce_error, "bad input matrix", 0);
RETURN_NULL();
}
auto num_cols = zend_hash_num_elements(Z_ARR_P(first_row));
if (UNEXPECTED(num_rows == 0)) {
RETURN_OBJ(create());
}
auto zobj = create(num_rows, num_cols);
auto native = ZOBJ_NATIVE(zobj);
size_t idx_row = 0;
size_t idx_col = 0;
ZEND_HASH_FOREACH_VAL(Z_ARR_P(arr), zval *row)
if (idx_row > num_rows - 1) {
break;
}
if (UNEXPECTED(Z_TYPE_P(row) != IS_ARRAY)) {
zend_throw_exception(zend_ce_error, "bad input matrix", 0);
break;
}
ZEND_HASH_FOREACH_VAL(Z_ARR_P(row), zval *elem)
if (idx_col > num_cols - 1) {
break;
}
if (UNEXPECTED(!zval_check_scalar<T>(elem))) {
break;
}
native->at(idx_row, idx_col++) = zval_get_scalar<T>(elem);
ZEND_HASH_FOREACH_END();
++idx_row;
idx_col = 0;
ZEND_HASH_FOREACH_END();
RETVAL_OBJ(zobj);
}
template <typename T>
PHP_ARMA_START_ME(mat, T)
PHP_ARMA_ME(init, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ARMA_ME(fromString, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ARMA_ME(fromArray, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)
PHP_ARMA_END_ME();
template <typename T>

View File

@ -40,6 +40,7 @@ namespace php_arma
static PHP_FUNCTION(init);
static PHP_FUNCTION(fromString);
static PHP_FUNCTION(fromArray);
static void ce_init(zend_class_entry*);
};

View File

@ -80,11 +80,14 @@
Z_PARAM_LONG_EX2(dest, _dummy, 0, 1, 0)
#define Z_PARAM_STR_DEREF(dest) \
Z_PARAM_STR_EX2(dest, 0, 1, 0)
#define Z_PARAM_ARRAY_DEREF(dest) \
Z_PARAM_ARRAY_EX2(dest, 0, 1, 0)
#else
// Before PHP 7.2, parameter is dereferenced by default here.
#define Z_PARAM_DOUBLE_DEREF Z_PARAM_DOUBLE
#define Z_PARAM_LONG_DEREF Z_PARAM_LONG
#define Z_PARAM_STR_DEREF Z_PARAM_STR
#define Z_PARAM_ARRAY_DEREF Z_PARAM_ARRAY
#endif
#ifdef PHP_ARMA_OPERATORS

View File

@ -30,4 +30,14 @@ abstract class Mat implements Internal\DenseResizableMatrix
static function fromString($text) {
return new static;
}
/**
* Create the matrix from a PHP array.
*
* @param array $arr
* @return Mat
*/
static function fromArray($arr) {
return new static;
}
}

View File

@ -30,6 +30,14 @@ interface Vector
*/
static function fromString($text);
/**
* Create the vector from a PHP array.
*
* @param array $arr
* @return static
*/
static function fromArray($arr);
// Vector subview
/**

48
tests/003-mat-init.phpt Normal file
View File

@ -0,0 +1,48 @@
--TEST--
Test for initialization of `Mat`
--SKIPIF--
<?php
require_once 'includes/loaded.php';
is_php_arma_loaded();
?>
--FILE--
<?php
require_once 'includes/assert.php';
$mat = Arma\DMat::init(3, 4, Arma\Fill::ZEROS);
batch_assert('initialization of `Arma\\Mat`',
[3, $mat->nRows()],
[4, $mat->nCols()],
[3 * 4, $mat->nElem()],
[0., $mat->max()],
[0., $mat->min()]
);
$mat1 = Arma\IMat::fromString('1 2; 3 4');
batch_assert('initialization from string of `Arma\\Mat`',
[2, $mat1->nRows()],
[2, $mat1->nCols()],
[2 * 2, $mat1->nElem()],
[1, $mat1(0, 0)->val()],
[2, $mat1(0, 1)->val()],
[3, $mat1(1, 0)->val()],
[4, $mat1(1, 1)->val()]
);
$mat2 = Arma\IMat::fromArray([
[1, 2],
[3, 4]
]);
batch_assert('initialization from array of `Arma\\Mat`',
[2, $mat2->nRows()],
[2, $mat2->nCols()],
[2 * 2, $mat2->nElem()],
[1, $mat2(0, 0)->val()],
[2, $mat2(0, 1)->val()],
[3, $mat2(1, 0)->val()],
[4, $mat2(1, 1)->val()]
);
?>
--EXPECT--