// // php-armadillo/dense.hh // // @Author CismonX // #ifndef PHP_ARMA_DENSE_HH #define PHP_ARMA_DENSE_HH #include "php_arma.hh" #include "complex.hh" #include #define PHP_ARMA_DENSE_OPERATOR_EX2(cls, type, func) \ PHP_ARMA_OPERATOR_EX2((dense>), cls, func) #define PHP_ARMA_DENSE_OPERATOR_EX(cls, func) \ PHP_ARMA_DENSE_OPERATOR_EX2(cls, double, func) \ PHP_ARMA_DENSE_OPERATOR_EX2(cls, zend_long, func) \ PHP_ARMA_DENSE_OPERATOR_EX2(cls, cx_double, func) #define PHP_ARMA_DENSE_OPERATOR(func) \ PHP_ARMA_OPERATOR_BEGIN(dense_ce) \ PHP_ARMA_DENSE_OPERATOR_EX(mat, func) \ PHP_ARMA_OPERATOR_END() namespace php_arma { template struct dense { using native_t = typename ChildT::native_t; struct operators; template zend_always_inline static bool compare_op(zval *zv1, zval *zv2, zval *return_value, F&& func) { if (Z_OBJCE_P(zv1) != Z_OBJCE_P(zv2)) { ex_bad_type(zval_get_type_name(zv1), zval_get_type_name(zv2)); return false; } if constexpr (!IsEq && std::is_same_v) { zend_throw_exception(zend_ce_error, "no such comparation for complex elements", 0); return false; } else { using dest_t = typename ChildT::with_int_elem_t; using dest_native_t = typename dest_t::native_t; try { auto ret = func(Z_NATIVE_OBJ_P(zv1), Z_NATIVE_OBJ_P(zv2)).eval(); RETVAL_OBJ(dest_t::create(std::move(arma::conv_to::from(ret)))); return true; } catch (const std::logic_error& err) { zend_throw_exception(zend_ce_error, err.what(), 0); return false; } } } PHP_ARMA_COMMON_DECLARE(); private: static PHP_FUNCTION(equals); static PHP_FUNCTION(notEquals); static PHP_FUNCTION(greaterThan); static PHP_FUNCTION(smallerThan); static PHP_FUNCTION(notGreaterThan); static PHP_FUNCTION(notSmallerThan); static PHP_FUNCTION(fill); static PHP_FUNCTION(imbue); template static void compare(INTERNAL_FUNCTION_PARAMETERS, F&&); }; void dense_init(); constexpr const char dense_php_name[] = "Dense"; inline zend_class_entry *dense_ce; template struct dense::operators { zend_always_inline static bool equals(zval *zv1, zval *zv2, zval *retval) { return compare_op(zv1, zv2, retval, [] (auto v1, auto v2) { return *v1 == *v2; }); } zend_always_inline static bool not_equals(zval *zv1, zval *zv2, zval *retval) { return compare_op(zv1, zv2, retval, [] (auto v1, auto v2) { return *v1 != *v2; }); } zend_always_inline static bool greater_than(zval *zv1, zval *zv2, zval *retval) { return compare_op(zv1, zv2, retval, [] (auto v1, auto v2) { return *v1 > *v2; }); } zend_always_inline static bool smaller_than(zval *zv1, zval *zv2, zval *retval) { return compare_op(zv1, zv2, retval, [] (auto v1, auto v2) { return *v1 < *v2; }); } zend_always_inline static bool not_greater_than(zval *zv1, zval *zv2, zval *retval) { return compare_op(zv1, zv2, retval, [] (auto v1, auto v2) { return *v1 <= *v2; }); } zend_always_inline static bool not_smaller_than(zval *zv1, zval *zv2, zval *retval) { return compare_op(zv1, zv2, retval, [] (auto v1, auto v2) { return *v1 >= *v2; }); } }; } #endif // !PHP_ARMA_DENSE_HH