Implement Fill, Complex and internal interfaces.

This commit is contained in:
CismonX 2019-03-14 23:04:34 +08:00
parent 6c30cd7538
commit 053bf8ff3a
19 changed files with 536 additions and 109 deletions

View File

@ -2,6 +2,11 @@ PHP_ARG_ENABLE(arma, for armadillo support,
[ --enable-arma Enable armadillo support])
if test "$PHP_ARMA" != "no"; then
ARMA_SRC="src/arma.c"
PHP_NEW_EXTENSION(arma, $ARMA_SRC, $ext_shared)
PHP_REQUIRE_CXX()
ARMA_SRC=" \
src/arma.cc \
src/interfaces.cc \
src/fill.cc \
src/complex.cc"
PHP_NEW_EXTENSION(arma, $ARMA_SRC, $ext_shared, , -std=c++14)
fi

View File

@ -1,64 +0,0 @@
//
// php-armadillo/arma.c
//
// @Author CismonX
//
#include "php_arma.h"
#include <zend_interfaces.h>
#include <ext/standard/info.h>
#define ARMA_CE_INIT(cls, name) \
zend_class_entry cls##_ce; \
INIT_CLASS_ENTRY(cls##_ce, name, cls##_methods); \
arma_##cls##_ce = zend_register_internal_class(&cls##_ce)
#define ARMA_CONST_DECLARE(cls, name, val) \
zend_declare_class_constant_long(arma_##cls##_ce, name, sizeof(name) - 1, val)
#define ARMA_PROP_DECLARE(cls, name, flags) \
zend_declare_property_null(arma_##cls##_ce, name, sizeof(name) - 1, flags)
#define ARMA_HANDLERS_INIT(cls) \
memcpy(&cls##_handlers, &std_object_handlers, sizeof(zend_object_handlers))
#define ARMA_HANDLER_SET(cls, name) \
cls##_handlers.name = cls##_##name
ZEND_DECLARE_MODULE_GLOBALS(arma)
#ifdef ZTS
ZEND_TSRMLS_CACHE_DEFINE()
#endif
PHP_MINIT_FUNCTION(arma)
{
#ifdef ZTS
ZEND_INIT_MODULE_GLOBALS(arma, NULL, NULL);
#endif
// ...
return SUCCESS;
}
PHP_MINFO_FUNCTION(arma)
{
php_info_print_table_start();
php_info_print_table_header(2, "armadillo support", "enabled");
php_info_print_table_end();
}
zend_module_entry arma_module_entry = {
STANDARD_MODULE_HEADER,
"arma",
NULL,
PHP_MINIT(arma),
NULL,
NULL,
NULL,
PHP_MINFO(arma),
PHP_ARMA_VERSION,
STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_ARMA
ZEND_GET_MODULE(arma)
#endif

45
src/arma.cc Normal file
View File

@ -0,0 +1,45 @@
//
// php-armadillo/arma.cc
//
// @Author CismonX
//
#include "arma.hh"
#include "interfaces.hh"
#include "fill.hh"
#include "complex.hh"
#include <ext/standard/info.h>
PHP_MINIT_FUNCTION(arma)
{
php_arma::internal_interfaces_init();
php_arma::fill_init();
php_arma::complex_init();
return SUCCESS;
}
PHP_MINFO_FUNCTION(arma)
{
php_info_print_table_start();
php_info_print_table_header(2, "armadillo support", "enabled");
php_info_print_table_end();
}
zend_module_entry arma_module_entry = {
STANDARD_MODULE_HEADER,
"arma",
NULL,
PHP_MINIT(arma),
NULL,
NULL,
NULL,
PHP_MINFO(arma),
PHP_ARMA_VERSION,
STANDARD_MODULE_PROPERTIES
};
#ifdef COMPILE_DL_ARMA
ZEND_GET_MODULE(arma)
#endif

275
src/arma.hh Normal file
View File

@ -0,0 +1,275 @@
//
// php-armadillo/php_arma.hh
//
// @Author CismonX
//
#ifndef PHP_ARMA_HH
#define PHP_ARMA_HH
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "complex.hh"
#include <php.h>
#include <zend_exceptions.h>
#include <complex>
#if PHP_VERSION_ID >= 70400
#define ZEND_ACC_CTOR 0
#endif
extern zend_module_entry arma_module_entry;
#define PHP_ARMA_VERSION "0.0.1"
typedef std::complex<double> cx_double;
/// Helper functions.
#define PHP_ARMA_START_METHOD_ENTRY_1(name, t1) \
template <typename t1> \
struct name##_methods \
{ \
static constexpr zend_function_entry const val[] = {
#define PHP_ARMA_END_METHOD_ENTRY_1(name, t1) \
PHP_FE_END \
}; \
}; \
template <typename t1> \
constexpr zend_function_entry const name##_methods<t1>::val[];
#define PHP_ARMA_ME_1(cls, t1, name, flags) \
ZEND_FENTRY(name, ZEND_MN(cls##_##name<t1>), nullptr, flags)
#define PHP_ARMA_METHOD_1(name, t1) \
name##_methods<t1>::val
namespace php_arma
{
template <typename F>
zend_class_entry *ce_init(const char *name, const zend_function_entry *methods, F init_func)
{
char full_name[30] = { "Arma\\" };
strcat(full_name, name);
zend_class_entry tmp_ce;
INIT_CLASS_ENTRY_EX(tmp_ce, full_name, strlen(full_name), methods);
return init_func(&tmp_ce);
}
template <typename F, typename... Ts>
zend_class_entry *ce_init(const char *name, const zend_function_entry *methods, F init_func, Ts... parents)
{
auto ce = ce_init(name, methods, init_func);
zend_class_implements(ce, sizeof...(Ts), parents...);
return ce;
}
template <typename>
zend_class_entry *class_register(const char *name, const zend_function_entry *methods)
{
return ce_init(name, methods, zend_register_internal_class);
}
template <typename... Ts>
zend_class_entry *class_register(const char *name, const zend_function_entry *methods, Ts... parents)
{
return ce_init(name, methods, zend_register_internal_class, parents...);
}
// Although methods are declared in interfaces as you see in the stubs,
// nothing is declared in the internal interface implementation.
template <typename>
zend_class_entry *interface_register(const char *name)
{
return ce_init(name, nullptr, zend_register_internal_class);
}
template <typename... Ts>
zend_class_entry *interface_register(const char *name, Ts... parents)
{
return ce_init(name, nullptr, zend_register_internal_class, parents...);
}
zend_always_inline
void const_declare(zend_class_entry *ce, const char *name, zend_long val)
{
zend_declare_class_constant_long(ce, name, strlen(name), val);
}
zend_always_inline
void property_declare(zend_class_entry *ce, const char *name)
{
zend_declare_property_null(ce, name, strlen(name), ZEND_ACC_PUBLIC);
}
template <typename T>
zend_object *to_zend_object(T *obj)
{
return reinterpret_cast<zend_object*>(obj + 1);
}
template <typename T>
T *to_native_object(zend_object* zobj)
{
return reinterpret_cast<T*>(zobj) - 1;
}
/// Create a zend_object which wraps a native object.
template <typename T, typename F>
zend_object *object_create(zend_class_entry *ce, F init)
{
auto obj = reinterpret_cast<T*>(ecalloc(1,
sizeof(T) + sizeof(zend_object) + zend_object_properties_size(ce)));
init(obj);
auto zobj = to_zend_object(obj);
zend_object_std_init(zobj, ce);
zobj->handlers = &std_object_handlers;
return zobj;
}
/// Create a normal zend_object.
template <typename T>
zend_object *object_create(zend_class_entry *ce)
{
auto zobj = reinterpret_cast<zend_object*>(ecalloc(1,
sizeof(zend_object) + zend_object_properties_size(ce)));
zend_object_std_init(zobj, ce);
object_properties_init(zobj, ce);
zobj->handlers = &std_object_handlers;
return zobj;
}
zend_always_inline
void zval_set_scalar(zval *zv, double val)
{
ZVAL_DOUBLE(zv, val);
}
zend_always_inline
void zval_set_scalar(zval *zv, zend_long val)
{
ZVAL_LONG(zv, val);
}
template <typename T>
T zval_get_scalar(zval *zv)
{
assert(false);
}
template <> zend_always_inline
double zval_get_scalar<double>(zval *zv)
{
return Z_DVAL_P(zv);
}
template <> zend_always_inline
zend_long zval_get_scalar<zend_long>(zval *zv)
{
return Z_LVAL_P(zv);
}
template <typename>
bool zval_is_scalar(zval *zv)
{
assert(false);
}
template <> zend_always_inline
bool zval_is_scalar<double>(zval *zv)
{
return Z_TYPE_P(zv) == IS_DOUBLE;
}
template <> zend_always_inline
bool zval_is_scalar<zend_long>(zval *zv)
{
return Z_TYPE_P(zv) == IS_LONG;
}
template <> zend_always_inline
bool zval_is_scalar<cx_double>(zval *zv)
{
return Z_TYPE_P(zv) == IS_OBJECT && instanceof_function(Z_OBJCE_P(zv), cx_double_ce);
}
template <typename>
struct scalar_type {};
template <>
struct scalar_type<double> {
static const int value = IS_DOUBLE;
};
template <>
struct scalar_type<zend_long> {
static const int value = IS_LONG;
};
template <>
struct scalar_type<cx_double> {
static const int value = IS_OBJECT;
};
template <typename>
const char *scalar_type_name()
{
assert(false);
}
template <> zend_always_inline
const char *scalar_type_name<double>()
{
return zend_get_type_by_const(IS_DOUBLE);
}
template <> zend_always_inline
const char *scalar_type_name<zend_long>()
{
return zend_get_type_by_const(IS_LONG);
}
template <> zend_always_inline
const char *scalar_type_name<cx_double>()
{
return ZSTR_VAL(cx_double_ce->name);
}
zend_always_inline
const char *zval_get_type_name(zval *zv)
{
if (Z_TYPE_P(zv) == IS_OBJECT) {
return ZSTR_VAL(Z_OBJCE_P(zv)->name);
} else {
return zend_get_type_by_const(Z_TYPE_P(zv));
}
}
zend_always_inline
void ex_bad_type(const char *expected, const char *got)
{
zend_throw_exception_ex(zend_ce_type_error, -1, "Bad type. Expected %s, got %s.", expected, got);
}
template <typename T>
void zval_check_scalar(zval *zv)
{
if (!zval_is_scalar<T>(zv)) {
ex_bad_type(scalar_type_name<T>(), zval_get_type_name(zv));
}
}
zend_always_inline
void object_set_property(zend_object *obj, size_t idx, zval *val)
{
zval_ptr_dtor(OBJ_PROP_NUM(obj, idx));
ZVAL_COPY(OBJ_PROP_NUM(obj, idx), val);
}
}
#endif // !PHP_ARMA_HH

61
src/complex.cc Normal file
View File

@ -0,0 +1,61 @@
//
// php-armadillo/complex.cc
//
// @Author CismonX
//
#include "arma.hh"
#include "complex.hh"
namespace php_arma
{
PHP_ARMA_START_METHOD_ENTRY_1(complex, T)
PHP_ARMA_ME_1(Complex, T, __construct, ZEND_ACC_PUBLIC | ZEND_ACC_CTOR)
PHP_ARMA_END_METHOD_ENTRY_1(complex, T)
template <typename T>
PHP_METHOD(Complex, __construct)
{
zval *real, *imag;
ZEND_PARSE_PARAMETERS_START(0, 2)
Z_PARAM_OPTIONAL
Z_PARAM_ZVAL(real)
Z_PARAM_ZVAL(imag)
ZEND_PARSE_PARAMETERS_END();
auto num_args = EX_NUM_ARGS();
auto has_imag = num_args > 1;
auto has_real = num_args > 0;
zval zero_val;
zval_set_scalar(&zero_val, static_cast<T>(0));
zval *current = getThis();
if (EXPECTED(has_real)) {
zval_check_scalar<T>(real);
object_set_property(Z_OBJ_P(current), 0, real);
if (EXPECTED(has_imag)) {
zval_check_scalar<T>(imag);
object_set_property(Z_OBJ_P(current), 1, imag);
} else {
object_set_property(Z_OBJ_P(current), 1, &zero_val);
}
} else {
object_set_property(Z_OBJ_P(current), 0, &zero_val);
object_set_property(Z_OBJ_P(current), 1, &zero_val);
}
}
void complex_init()
{
complex_ce = interface_register("Complex");
cx_double_ce = class_register("CxDouble", PHP_ARMA_METHOD_1(complex, double), complex_ce);
property_declare(cx_double_ce, "real");
property_declare(cx_double_ce, "imag");
}
zend_class_entry *complex_ce;
zend_class_entry *cx_double_ce;
}

23
src/complex.hh Normal file
View File

@ -0,0 +1,23 @@
//
// php-armadillo/complex.hh
//
// @Author CismonX
//
#ifndef PHP_ARMA_COMPLEX_HH
#define PHP_ARMA_COMPLEX_HH
#include <php.h>
namespace php_arma
{
template <typename T>
PHP_METHOD(Complex, __construct);
void complex_init();
extern zend_class_entry *complex_ce;
extern zend_class_entry *cx_double_ce;
}
#endif //!PHP_ARMA_COMPLEX_HH

0
src/diagview.cc Normal file
View File

0
src/diagview.hh Normal file
View File

25
src/fill.cc Normal file
View File

@ -0,0 +1,25 @@
//
// php-armadillo/fill.cc
//
// @Author CismonX
//
#include "arma.hh"
#include "fill.hh"
namespace php_arma
{
void fill_init()
{
fill_ce = class_register("Fill", nullptr);
fill_ce->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
const_declare(fill_ce, "NONE", fill_none);
const_declare(fill_ce, "ZEROS", fill_zeros);
const_declare(fill_ce, "ONES", fill_ones);
const_declare(fill_ce, "EYE", fill_eye);
const_declare(fill_ce, "RANDU", fill_randu);
const_declare(fill_ce, "RANDN", fill_randn);
}
zend_class_entry *fill_ce;
}

26
src/fill.hh Normal file
View File

@ -0,0 +1,26 @@
//
// php-armadillo/fill.hh
//
// @Author CismonX
//
#ifndef PHP_ARMA_FILL_HH
#define PHP_ARMA_FILL_HH
#include <php.h>
namespace php_arma
{
constexpr auto fill_none = 0;
constexpr auto fill_zeros = 1;
constexpr auto fill_ones = 2;
constexpr auto fill_eye = 3;
constexpr auto fill_randu = 4;
constexpr auto fill_randn = 5;
void fill_init();
extern zend_class_entry *fill_ce;
}
#endif //!PHP_ARMA_FILL_HH

43
src/interfaces.cc Normal file
View File

@ -0,0 +1,43 @@
//
// php-armadillo/interfaces.cc
//
// @Author CismonX
//
#include "arma.hh"
#include "interfaces.hh"
#define N_INT "Internal\\"
namespace php_arma
{
void internal_interfaces_init()
{
common_ce = interface_register(N_INT "Common");
vector_ce = interface_register(N_INT "Vector");
matrix_ce = interface_register(N_INT "Matrix");
dense_ce = interface_register(N_INT "Dense", common_ce);
sparse_ce = interface_register(N_INT "Sparse", common_ce);
dense_vector_ce = interface_register(N_INT "DenseVector", vector_ce, dense_ce);
resizable_ce = interface_register(N_INT "Resizable");
resizable_vector_ce = interface_register(N_INT "ResizableVector", resizable_ce);
resizable_matrix_ce = interface_register(N_INT "ResizableMatrix", resizable_ce);
subview_ce = interface_register(N_INT "Subview");
diagonal_ce = interface_register(N_INT "Diagonal", subview_ce);
scalar_ce = interface_register(N_INT "Scalar", subview_ce);
}
zend_class_entry *common_ce;
zend_class_entry *vector_ce, *matrix_ce;
zend_class_entry *dense_ce, *sparse_ce;
zend_class_entry *dense_vector_ce;
zend_class_entry *resizable_ce;
zend_class_entry *resizable_vector_ce, *resizable_matrix_ce;
zend_class_entry *subview_ce;
zend_class_entry *diagonal_ce;
zend_class_entry *scalar_ce;
}

31
src/interfaces.hh Normal file
View File

@ -0,0 +1,31 @@
//
// php-armadillo/interfaces.hh
//
// @Author CismonX
//
#ifndef PHP_ARMA_INTERFACES_HH
#define PHP_ARMA_INTERFACES_HH
#include <php.h>
namespace php_arma
{
void internal_interfaces_init();
extern zend_class_entry *common_ce;
extern zend_class_entry *vector_ce, *matrix_ce;
extern zend_class_entry *dense_ce, *sparse_ce;
extern zend_class_entry *dense_vector_ce;
extern zend_class_entry *resizable_ce;
extern zend_class_entry *resizable_vector_ce, *resizable_matrix_ce;
extern zend_class_entry *subview_ce;
extern zend_class_entry *diagonal_ce;
extern zend_class_entry *scalar_ce;
}
#endif //!PHP_ARMA_INTERFACES_HH

0
src/mat.cc Normal file
View File

0
src/mat.hh Normal file
View File

View File

@ -1,43 +0,0 @@
//
// php-armadillo/php_arma.h
//
// @Author CismonX
//
#ifndef PHP_ARMA_H
#define PHP_ARMA_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <php.h>
extern zend_module_entry arma_module_entry;
#define PHP_ARMA_VERSION "0.0.1"
#ifdef PHP_WIN32
#define PHP_ARMA_API __declspec(dllexport)
#elif defined(__GNUC__) && __GNUC__ >= 4
#define PHP_ARMA_API __attribute__ ((visibility("default")))
#else
#define PHP_ARMA_API
#endif
ZEND_BEGIN_MODULE_GLOBALS(arma)
int unused;
ZEND_END_MODULE_GLOBALS(arma)
ZEND_EXTERN_MODULE_GLOBALS(arma)
#ifdef ZTS
#ifdef COMPILE_DL_ARMA
ZEND_TSRMLS_CACHE_EXTERN()
#endif
#define ARMA_G(v) TSRMG(arma_globals_id, zend_arma_globals*, v)
#else
#define ARMA_G(v) (arma_globals.v)
#endif
#endif // !PHP_ARMA_H

0
src/subview_val.cc Normal file
View File

0
src/subview_val.hh Normal file
View File

0
src/vec.cc Normal file
View File

0
src/vec.hh Normal file
View File