ext/numo/narray/array.c in numo-narray-0.9.0.5 vs ext/numo/narray/array.c in numo-narray-0.9.0.6
- old
+ new
@@ -30,151 +30,108 @@
static ID id_abs;
static ID id_cast;
static ID id_le;
static ID id_Complex;
-typedef struct {
- int ndim;
- size_t *shape;
- VALUE dtype;
-} na_compose_t;
-static size_t
-na_compose_memsize(const void *ptr)
-{
- const na_compose_t *nc = (const na_compose_t*)ptr;
-
- return sizeof(na_compose_t) + nc->ndim * sizeof(size_t);
-}
-
-static void
-na_compose_free(void *ptr)
-{
- na_compose_t *nc = (na_compose_t*)ptr;
-
- if (nc->shape)
- xfree(nc->shape);
- xfree(nc);
-}
-
-static void
-na_compose_gc_mark(void* nc)
-{
- rb_gc_mark(((na_compose_t*)nc)->dtype);
-}
-
-static const rb_data_type_t compose_data_type = {
- "Numo::NArray/compose",
- {na_compose_gc_mark, na_compose_free, na_compose_memsize,},
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
-};
-
-#define WrapCompose(p) TypedData_Wrap_Struct(rb_cData, &compose_data_type, (void*)(p));
-#define GetCompose(v,p) TypedData_Get_Struct(v, na_compose_t, &compose_data_type, p)
-
static VALUE
na_object_type(int type, VALUE v)
{
static VALUE int32_max = Qnil;
if (NIL_P(int32_max))
- int32_max = ULONG2NUM(2147483647);
+ int32_max = ULONG2NUM(2147483647);
switch(TYPE(v)) {
case T_TRUE:
case T_FALSE:
- if (type<NA_BIT)
- return NA_BIT;
- return type;
+ if (type<NA_BIT)
+ return NA_BIT;
+ return type;
#if SIZEOF_LONG == 4
case T_FIXNUM:
- if (type<NA_INT32)
- return NA_INT32;
- return type;
+ if (type<NA_INT32)
+ return NA_INT32;
+ return type;
case T_BIGNUM:
- if (type<NA_INT64) {
- v = rb_funcall(v,id_abs,0);
- if (RTEST(rb_funcall(v,id_le,1,int32_max))) {
- if (type<NA_INT32)
- return NA_INT32;
- } else {
- return NA_INT64;
- }
- }
- return type;
+ if (type<NA_INT64) {
+ v = rb_funcall(v,id_abs,0);
+ if (RTEST(rb_funcall(v,id_le,1,int32_max))) {
+ if (type<NA_INT32)
+ return NA_INT32;
+ } else {
+ return NA_INT64;
+ }
+ }
+ return type;
#elif SIZEOF_LONG == 8
case T_FIXNUM:
- if (type<NA_INT64) {
- long x = NUM2LONG(v);
- if (x<0) x=-x;
- if (x<=2147483647) {
- if (type<NA_INT32)
- return NA_INT32;
- } else {
- return NA_INT64;
- }
- }
- return type;
+ if (type<NA_INT64) {
+ long x = NUM2LONG(v);
+ if (x<0) x=-x;
+ if (x<=2147483647) {
+ if (type<NA_INT32)
+ return NA_INT32;
+ } else {
+ return NA_INT64;
+ }
+ }
+ return type;
case T_BIGNUM:
- if (type<NA_INT64)
- return NA_INT64;
- return type;
+ if (type<NA_INT64)
+ return NA_INT64;
+ return type;
#else
case T_FIXNUM:
case T_BIGNUM:
- if (type<NA_INT64) {
- v = rb_funcall(v,id_abs,0);
- if (RTEST(rb_funcall(v,id_le,1,int32_max))) {
- if (type<NA_INT32)
- return NA_INT32;
- } else {
- return NA_INT64;
- }
- }
- return type;
+ if (type<NA_INT64) {
+ v = rb_funcall(v,id_abs,0);
+ if (RTEST(rb_funcall(v,id_le,1,int32_max))) {
+ if (type<NA_INT32)
+ return NA_INT32;
+ } else {
+ return NA_INT64;
+ }
+ }
+ return type;
#endif
case T_FLOAT:
- if (type<NA_DFLOAT)
- return NA_DFLOAT;
- return type;
+ if (type<NA_DFLOAT)
+ return NA_DFLOAT;
+ return type;
case T_NIL:
- return type;
+ return type;
default:
- if (CLASS_OF(v) == rb_const_get( rb_cObject, id_Complex )) {
- return NA_DCOMPLEX;
- }
+ if (CLASS_OF(v) == rb_const_get( rb_cObject, id_Complex )) {
+ return NA_DCOMPLEX;
+ }
}
return NA_ROBJ;
}
-#define MDAI_ATTR_TYPE(tp,v,attr) \
- {tp = na_object_type(tp,rb_funcall(v,id_##attr,0));}
+#define MDAI_ATTR_TYPE(tp,v,attr) \
+ {tp = na_object_type(tp,rb_funcall(v,id_##attr,0));}
-void na_mdai_object_type(na_mdai_t *mdai, VALUE v)
+static int na_mdai_object_type(int type, VALUE v)
{
- if (IsNArray(v)) {
- if (NIL_P(mdai->na_type)) {
- mdai->na_type = CLASS_OF(v);
- } else {
- mdai->na_type = na_upcast(CLASS_OF(v), mdai->na_type);
- }
- } else if (rb_obj_is_kind_of(v, rb_cRange)) {
- MDAI_ATTR_TYPE(mdai->type,v,begin);
- MDAI_ATTR_TYPE(mdai->type,v,end);
+ if (rb_obj_is_kind_of(v, rb_cRange)) {
+ MDAI_ATTR_TYPE(type,v,begin);
+ MDAI_ATTR_TYPE(type,v,end);
} else if (rb_obj_is_kind_of(v, na_cStep)) {
- MDAI_ATTR_TYPE(mdai->type,v,begin);
- MDAI_ATTR_TYPE(mdai->type,v,end);
- MDAI_ATTR_TYPE(mdai->type,v,step);
+ MDAI_ATTR_TYPE(type,v,begin);
+ MDAI_ATTR_TYPE(type,v,end);
+ MDAI_ATTR_TYPE(type,v,step);
} else {
- mdai->type = na_object_type(mdai->type,v);
+ type = na_object_type(type,v);
}
+ return type;
}
static na_mdai_t *
na_mdai_alloc(VALUE ary)
@@ -184,12 +141,12 @@
mdai = ALLOC(na_mdai_t);
mdai->capa = n;
mdai->item = ALLOC_N( na_mdai_item_t, n );
for (i=0; i<n; i++) {
- mdai->item[i].shape = 0;
- mdai->item[i].val = Qnil;
+ mdai->item[i].shape = 0;
+ mdai->item[i].val = Qnil;
}
mdai->item[0].val = ary;
mdai->type = NA_NONE;
mdai->na_type = Qnil;
@@ -204,12 +161,12 @@
i = mdai->capa;
mdai->capa += n_extra;
n = mdai->capa;
REALLOC_N( mdai->item, na_mdai_item_t, n );
for (; i<n; i++) {
- mdai->item[i].shape = 0;
- mdai->item[i].val = Qnil;
+ mdai->item[i].shape = 0;
+ mdai->item[i].val = Qnil;
}
}
static void
na_mdai_free(void *ptr)
@@ -235,115 +192,156 @@
len = RARRAY_LEN(val);
for (i=0; i < RARRAY_LEN(val); i++) {
v = RARRAY_AREF(val,i);
- if (TYPE(v) == T_ARRAY) {
- /* check recursive array */
- for (j=0; j<ndim; j++) {
- if (mdai->item[j].val == v)
- rb_raise(rb_eStandardError,
- "cannot convert from a recursive Array to NArray");
- }
- if ( ndim >= mdai->capa ) {
- na_mdai_realloc(mdai,4);
- }
- mdai->item[ndim].val = v;
- if ( na_mdai_investigate(mdai,ndim+1) ) {
- len--; /* Array is empty */
- }
- }
- else
+ if (TYPE(v) == T_ARRAY) {
+ /* check recursive array */
+ for (j=0; j<ndim; j++) {
+ if (mdai->item[j].val == v)
+ rb_raise(rb_eStandardError,
+ "cannot convert from a recursive Array to NArray");
+ }
+ if ( ndim >= mdai->capa ) {
+ na_mdai_realloc(mdai,4);
+ }
+ mdai->item[ndim].val = v;
+ if ( na_mdai_investigate(mdai,ndim+1) ) {
+ len--; /* Array is empty */
+ }
+ }
+ else
if (rb_obj_is_kind_of(v, rb_cRange) || rb_obj_is_kind_of(v, na_cStep)) {
- nary_step_sequence(v,&length,&dbeg,&dstep);
- len += length-1;
- na_mdai_object_type(mdai,v);
- }
- else {
- na_mdai_object_type(mdai,v);
-
- if (IsNArray(v)) {
- int r;
- narray_t *na;
- GetNArray(v,na);
- if ( na->ndim == 0 ) {
- len--; /* NArray is empty */
- } else {
- if ( ndim+na->ndim > mdai->capa ) {
- na_mdai_realloc(mdai,((na->ndim-1)/4+1)*4);
- }
- for ( j=0,r=ndim; j < na->ndim ; j++,r++ ) {
- if ( mdai->item[r].shape < na->shape[j] )
- mdai->item[r].shape = na->shape[j];
- }
- }
- }
- }
+ nary_step_sequence(v,&length,&dbeg,&dstep);
+ len += length-1;
+ mdai->type = na_mdai_object_type(mdai->type, v);
+ }
+ else if (IsNArray(v)) {
+ int r;
+ narray_t *na;
+ GetNArray(v,na);
+ if ( na->ndim == 0 ) {
+ len--; /* NArray is empty */
+ } else {
+ if ( ndim+na->ndim > mdai->capa ) {
+ na_mdai_realloc(mdai,((na->ndim-1)/4+1)*4);
+ }
+ for ( j=0,r=ndim; j < na->ndim ; j++,r++ ) {
+ if ( mdai->item[r].shape < na->shape[j] )
+ mdai->item[r].shape = na->shape[j];
+ }
+ }
+ // type
+ if (NIL_P(mdai->na_type)) {
+ mdai->na_type = CLASS_OF(v);
+ } else {
+ mdai->na_type = na_upcast(CLASS_OF(v), mdai->na_type);
+ }
+ } else {
+ mdai->type = na_mdai_object_type(mdai->type, v);
+ }
}
if (len==0) return 1; /* this array is empty */
if (mdai->item[ndim-1].shape < len) {
- mdai->item[ndim-1].shape = len;
+ mdai->item[ndim-1].shape = len;
}
return 0;
}
-static void
-na_mdai_result(na_mdai_t *mdai, na_compose_t *nc)
-{
- int i, ndim;
- VALUE tp;
- size_t *shape;
+static inline int
+na_mdai_ndim(na_mdai_t *mdai)
+{
+ int i;
// Dimension
for (i=0; i < mdai->capa && mdai->item[i].shape > 0; i++) ;
- nc->ndim = ndim = i;
- nc->shape = NULL;
- nc->dtype = Qnil;
+ return i;
+}
- if (ndim>0) {
- // Shape
- nc->shape = shape = ALLOC_N(size_t,ndim);
- for (i=0; i<ndim; i++) {
- shape[i] = mdai->item[i].shape;
+static inline void
+na_mdai_shape(na_mdai_t *mdai, int ndim, size_t *shape)
+{
+ int i;
+ for (i=0; i<ndim; i++) {
+ shape[i] = mdai->item[i].shape;
+ }
+}
+
+static VALUE
+na_mdai_dtype_numeric(int type)
+{
+ VALUE tp;
+ // DataType
+ switch(type) {
+ case NA_BIT:
+ tp = numo_cBit;
+ break;
+ case NA_INT32:
+ tp = numo_cInt32;
+ break;
+ case NA_INT64:
+ tp = numo_cInt64;
+ break;
+ case NA_DFLOAT:
+ tp = numo_cDFloat;
+ break;
+ case NA_DCOMPLEX:
+ tp = numo_cDComplex;
+ break;
+ case NA_ROBJ:
+ tp = numo_cRObject;
+ break;
+ default:
+ tp = Qnil;
+ }
+ return tp;
+}
+
+static VALUE
+na_mdai_dtype(na_mdai_t *mdai)
+{
+ VALUE tp;
+
+ tp = na_mdai_dtype_numeric(mdai->type);
+
+ if (!NIL_P(mdai->na_type)) {
+ if (NIL_P(tp)) {
+ tp = mdai->na_type;
+ } else {
+ tp = na_upcast(mdai->na_type,tp);
}
+ }
+ return tp;
+}
- // DataType
- switch(mdai->type) {
- case NA_BIT:
- tp = numo_cBit;
- break;
- case NA_INT32:
- tp = numo_cInt32;
- break;
- case NA_INT64:
- tp = numo_cInt64;
- break;
- case NA_DFLOAT:
- tp = numo_cDFloat;
- break;
- case NA_DCOMPLEX:
- tp = numo_cDComplex;
- break;
- case NA_ROBJ:
- tp = numo_cRObject;
- break;
- default:
- tp = Qnil;
- }
- if (!NIL_P(mdai->na_type)) {
- if (NIL_P(tp)) {
- tp = mdai->na_type;
- } else {
- tp = na_upcast(mdai->na_type,tp);
- }
- }
- nc->dtype = tp;
+
+static inline VALUE
+update_type(VALUE *ptype, VALUE dtype)
+{
+ if (ptype) {
+ if (*ptype == cNArray || !RTEST(*ptype)) {
+ *ptype = dtype;
+ } else {
+ dtype = *ptype;
+ }
}
+ return dtype;
}
+static inline void
+check_subclass_of_narray(VALUE dtype)
+{
+ if (RTEST(rb_obj_is_kind_of(dtype, rb_cClass))) {
+ if (RTEST(rb_funcall(dtype, id_le, 1, cNArray))) {
+ return;
+ }
+ }
+ rb_raise(nary_eCastError, "cannot convert to NArray");
+}
+
static size_t
na_mdai_memsize(const void *ptr)
{
const na_mdai_t *mdai = (const na_mdai_t*)ptr;
@@ -354,92 +352,110 @@
"Numo::NArray/mdai",
{NULL, na_mdai_free, na_mdai_memsize,},
0, 0, RUBY_TYPED_FREE_IMMEDIATELY|RUBY_TYPED_WB_PROTECTED
};
-VALUE
-na_ary_composition(VALUE ary)
+
+static void
+na_composition3_ary(VALUE ary, VALUE *ptype, VALUE *pshape, VALUE *pnary)
{
- volatile VALUE vmdai, vnc;
+ VALUE vmdai;
na_mdai_t *mdai;
- na_compose_t *nc;
- int j;
+ int i, ndim;
+ size_t *shape;
+ VALUE dtype, dshape;
- nc = ALLOC(na_compose_t);
- vnc = WrapCompose(nc);
- if (TYPE(ary) == T_ARRAY) {
- mdai = na_mdai_alloc(ary);
- vmdai = TypedData_Wrap_Struct(rb_cData, &mdai_data_type, (void*)mdai);
- if ( na_mdai_investigate(mdai, 1) ) {
- // empty
- nc->ndim = 1;
- nc->shape = ALLOC_N(size_t, 1);
- nc->shape[0] = 0;
- nc->dtype = Qnil;
- } else {
- na_mdai_result(mdai, nc);
+ mdai = na_mdai_alloc(ary);
+ vmdai = TypedData_Wrap_Struct(rb_cData, &mdai_data_type, (void*)mdai);
+ if ( na_mdai_investigate(mdai, 1) ) {
+ // empty
+ dtype = update_type(ptype, numo_cInt32);
+ if (pshape) {
+ *pshape = rb_ary_new3(1, INT2FIX(0));
}
- rb_gc_force_recycle(vmdai);
- } else if (IsNArray(ary)) {
- narray_t *na;
- GetNArray(ary,na);
- nc->ndim = na->ndim;
- nc->shape = ALLOC_N(size_t, na->ndim);
- for (j=0; j<na->ndim; j++) {
- nc->shape[j] = na->shape[j];
+ if (pnary) {
+ check_subclass_of_narray(dtype);
+ shape = ALLOCA_N(size_t, 1);
+ shape[0] = 0;
+ *pnary = nary_new(dtype, 1, shape);
}
- nc->dtype = CLASS_OF(ary);
} else {
- rb_bug("invalid type for md-array: %s", rb_class2name(CLASS_OF(ary)));
+ ndim = na_mdai_ndim(mdai);
+ shape = ALLOCA_N(size_t, ndim);
+ na_mdai_shape(mdai, ndim, shape);
+ dtype = update_type(ptype, na_mdai_dtype(mdai));
+ if (pshape) {
+ dshape = rb_ary_new2(ndim);
+ for (i=0; i<ndim; i++) {
+ rb_ary_push(dshape, SIZET2NUM(shape[i]));
+ }
+ *pshape = dshape;
+ }
+ if (pnary) {
+ check_subclass_of_narray(dtype);
+ *pnary = nary_new(dtype, ndim, shape);
+ }
}
- return vnc;
+ RB_GC_GUARD(vmdai);
}
static void
-na_ary_composition2(VALUE ary, VALUE *type, VALUE *shape)
+na_composition3(VALUE obj, VALUE *ptype, VALUE *pshape, VALUE *pnary)
{
- VALUE vnc, dshape;
- na_compose_t *nc;
- int i;
+ VALUE dtype, dshape;
- // investigate MD-Array
- vnc = na_ary_composition(ary);
- GetCompose(vnc,nc);
- dshape = rb_ary_new2(nc->ndim);
- for (i=0; i<nc->ndim; i++) {
- rb_ary_push(dshape, SIZET2NUM(nc->shape[i]));
+ if (TYPE(obj) == T_ARRAY) {
+ na_composition3_ary(obj, ptype, pshape, pnary);
}
- if (shape) {*shape = dshape;}
- if (type) {*type = nc->dtype;}
- RB_GC_GUARD(vnc);
+ else if (RTEST(rb_obj_is_kind_of(obj,rb_cNumeric))) {
+ dtype = na_mdai_dtype_numeric(na_mdai_object_type(NA_NONE, obj));
+ dtype = update_type(ptype, dtype);
+ if (pshape) {
+ *pshape = rb_ary_new();
+ }
+ if (pnary) {
+ check_subclass_of_narray(dtype);
+ *pnary = nary_new(dtype, 0, 0);
+ }
+ }
+ else if (IsNArray(obj)) {
+ int i, ndim;
+ narray_t *na;
+ GetNArray(obj,na);
+ ndim = na->ndim;
+ dtype = update_type(ptype, CLASS_OF(obj));
+ if (pshape) {
+ dshape = rb_ary_new2(ndim);
+ for (i=0; i<ndim; i++) {
+ rb_ary_push(dshape, SIZET2NUM(na->shape[i]));
+ }
+ *pshape = dshape;
+ }
+ if (pnary) {
+ *pnary = nary_new(dtype, ndim, na->shape);
+ }
+ } else {
+ rb_bug("invalid type for md-array: %s", rb_class2name(CLASS_OF(obj)));
+ }
}
+
static VALUE
na_s_array_shape(VALUE mod, VALUE ary)
{
VALUE shape;
- if (TYPE(ary)!=T_ARRAY) {
- // 0-dimension
- return rb_ary_new();
+ if (TYPE(ary) != T_ARRAY) {
+ // 0-dimension
+ return rb_ary_new();
}
- na_ary_composition2(ary, 0, &shape);
+ na_composition3(ary, 0, &shape, 0);
return shape;
}
-static inline void
-check_subclass_of_narray(VALUE dtype) {
- if (RTEST(rb_obj_is_kind_of(dtype, rb_cClass))) {
- if (RTEST(rb_funcall(dtype, id_le, 1, cNArray))) {
- return;
- }
- }
- rb_raise(nary_eCastError, "cannot convert to NArray");
-}
-
/*
Generate new unallocated NArray instance with shape and type defined from obj.
Numo::NArray.new_like(obj) returns instance whose type is defined from obj.
Numo::DFloat.new_like(obj) returns DFloat instance.
@@ -455,61 +471,33 @@
=> Numo::DComplex#shape=[3](empty)
*/
VALUE
na_s_new_like(VALUE type, VALUE obj)
{
- VALUE vnc, newary;
- na_compose_t *nc;
+ VALUE newary;
- if (RTEST(rb_obj_is_kind_of(obj,rb_cNumeric))) {
- // investigate type
- if (type == cNArray) {
- vnc = na_ary_composition(rb_ary_new3(1,obj));
- GetCompose(vnc,nc);
- type = nc->dtype;
- }
- check_subclass_of_narray(type);
- newary = nary_new(type, 0, 0);
- } else {
- // investigate MD-Array
- vnc = na_ary_composition(obj);
- GetCompose(vnc,nc);
- if (type == cNArray) {
- type = nc->dtype;
- }
- check_subclass_of_narray(type);
- newary = nary_new(type, nc->ndim, nc->shape);
- }
- RB_GC_GUARD(vnc);
+ na_composition3(obj, &type, 0, &newary);
return newary;
}
VALUE
na_ary_composition_dtype(VALUE ary)
{
- volatile VALUE vnc;
- na_compose_t *nc;
+ VALUE type = Qnil;
- switch(TYPE(ary)) {
- case T_ARRAY:
- vnc = na_ary_composition(ary);
- GetCompose(vnc,nc);
- return nc->dtype;
- }
- return CLASS_OF(ary);
+ na_composition3(ary, &type, 0, 0);
+ return type;
}
static VALUE
na_s_array_type(VALUE mod, VALUE ary)
{
return na_ary_composition_dtype(ary);
}
-
-
/*
Generate NArray object. NArray datatype is automatically selected.
@overload [](elements)
@param [Numeric,Array] elements
@return [NArray]
@@ -526,15 +514,16 @@
check_subclass_of_narray(dtype);
return rb_funcall(dtype, id_cast, 1, ary);
}
-VALUE
-nst_check_compatibility(VALUE self, VALUE ary);
+//VALUE
+//nst_check_compatibility(VALUE self, VALUE ary);
/* investigate ndim, shape, type of Array */
+/*
static int
na_mdai_for_struct(na_mdai_t *mdai, int ndim)
{
size_t i;
int j, r;
@@ -561,11 +550,11 @@
}
return 1;
}
if (TYPE(val) == T_ARRAY) {
- /* check recursive array */
+ // check recursive array
for (j=0; j<ndim-1; j++) {
if (mdai->item[j].val == val)
rb_raise(rb_eStandardError,
"cannot convert from a recursive Array to NArray");
}
@@ -606,12 +595,14 @@
}
//fprintf(stderr,"invalid for struct:"); rb_p(val); abort();
return 0;
}
+*/
+/*
VALUE
na_ary_composition_for_struct(VALUE nstruct, VALUE ary)
{
volatile VALUE vmdai, vnc;
na_mdai_t *mdai;
@@ -619,23 +610,23 @@
mdai = na_mdai_alloc(ary);
mdai->na_type = nstruct;
vmdai = TypedData_Wrap_Struct(rb_cData, &mdai_data_type, (void*)mdai);
na_mdai_for_struct(mdai, 0);
- nc = ALLOC(na_compose_t);
+ nc = na_compose_alloc();
vnc = WrapCompose(nc);
na_mdai_result(mdai, nc);
//fprintf(stderr,"nc->ndim=%d\n",nc->ndim);
rb_gc_force_recycle(vmdai);
return vnc;
}
+*/
void
Init_nary_array()
{
- //rb_define_singleton_method(cNArray, "mdai", na_mdai, 1);
rb_define_singleton_method(cNArray, "array_shape", na_s_array_shape, 1);
rb_define_singleton_method(cNArray, "array_type", na_s_array_type, 1);
rb_define_singleton_method(cNArray, "new_like", na_s_new_like, 1);
rb_define_singleton_method(cNArray, "[]", nary_s_bracket, -2);