#include "pdl.h" /* Data structure declarations */
#include "pdlcore.h" /* Core declarations */
extern struct Core PDL;
#define XCODE(code, datatype, ctype, ...) \
ctype *ap = (ctype *) a->data; \
ctype *pp = (ctype *) a->vafftrans->from->data; \
pp += a->vafftrans->offs; \
for(i=0; i<a->nvals; i++) { \
code; \
for(j=0; j<a->ndims; j++) { \
pp += a->vafftrans->incs[j]; \
if((j < a->ndims - 1 && \
(i+1) % a->dimincs[j+1]) || \
j == a->ndims - 1) \
break; \
pp -= a->vafftrans->incs[j] * \
a->dims[j]; \
} \
ap ++; \
}
#define VAFF_IO(name, X) \
pdl_error pdl_ ## name(pdl *a) { \
pdl_error PDL_err = {0, NULL, 0}; \
PDL_Indx i, j; \
pdl_datatypes intype = a->datatype; \
if (!a->vafftrans) \
return pdl_make_error_simple(PDL_EUSERERROR, "pdl_" #name " without vafftrans"); \
if (a->nvals && !a->data) \
return pdl_make_error_simple(PDL_EUSERERROR, "pdl_" #name " non-empty with NULL data"); \
PDL_GENERICSWITCH(PDL_TYPELIST_ALL, intype, X, return pdl_make_error(PDL_EUSERERROR, "Not a known data type code=%d", intype)) \
return PDL_err; \
}
#define X(...) XCODE(*ap = *pp, __VA_ARGS__)
VAFF_IO(readdata_vaffine, X)
#undef X
#define X(...) XCODE(*pp = *ap, __VA_ARGS__)
VAFF_IO(writebackdata_vaffine, X)
#undef X
#undef XCODE
pdl_error pdl_converttype( pdl* a, pdl_datatypes targtype ) {
pdl_error PDL_err = {0, NULL, 0};
PDLDEBUG_f(printf("pdl_converttype to %d: ", targtype); pdl_dump(a));
if (a->state & PDL_DONTTOUCHDATA)
return pdl_make_error_simple(PDL_EUSERERROR, "Trying to converttype magical (mmaped?) pdl");
if (!a->data)
return pdl_make_error(PDL_EUSERERROR, "converttype called with NULL data on pdl %p", a);
PDL_RETERROR(PDL_err, pdl_make_physical(a));
pdl_datatypes intype = a->datatype;
if (intype == targtype)
return PDL_err;
STRLEN nbytes = a->nvals * pdl_howbig(targtype); /* Size of converted data */
STRLEN ncurr = a->nvals * pdl_howbig(intype);
PDL_Value value;
char diffsize = ncurr != nbytes,
was_useheap = (ncurr > sizeof(value)),
will_useheap = (nbytes > sizeof(value));
void *data_from_void = a->data, *data_to_void = a->data;
if (diffsize)
data_to_void = will_useheap ? pdl_smalloc(nbytes) : &value;
#define THIS_ISBAD(from_badval_isnan, from_badval, from_val) \
((from_badval_isnan) \
? isnan((double)(from_val)) \
: (from_val) == (from_badval))
#define X_OUTER(datatype_from, ctype_from, ppsym_from, ...) \
PDL_Indx i = a->nvals; \
ctype_from *data_from_typed = (ctype_from *) data_from_void; \
ctype_from from_badval = a->has_badvalue ? a->badvalue.value.ppsym_from : PDL.bvals.ppsym_from; \
char from_badval_isnan = PDL_ISNAN_##ppsym_from(from_badval);
#define X_INNER(datatype_to, ctype_to, ppsym_to, shortctype_to, defbval_to, ...) \
ctype_to *data_to_typed = (ctype_to *) data_to_void; \
data_to_typed += i-1; data_from_typed += i-1; \
if (a->state & PDL_BADVAL) { \
ctype_to to_badval = defbval_to; \
a->has_badvalue = 0; \
while (i--) { \
*data_to_typed-- = \
THIS_ISBAD(from_badval_isnan, from_badval, *data_from_typed) ? to_badval : \
PDL_GENTYPE_IS_UNSIGNED_##ppsym_to ? (ctype_to)(intmax_t) *data_from_typed : \
(ctype_to) *data_from_typed; \
data_from_typed--; \
} \
} else \
while (i--) \
*data_to_typed-- = \
PDL_GENTYPE_IS_UNSIGNED_##ppsym_to ? (ctype_to)(intmax_t) *data_from_typed-- : \
(ctype_to) *data_from_typed--;
PDL_GENERICSWITCH2(
PDL_TYPELIST_ALL, intype, X_OUTER, return pdl_make_error(PDL_EUSERERROR, "Not a known data type code=%d", intype),
PDL_TYPELIST_ALL_, targtype, X_INNER, return pdl_make_error(PDL_EUSERERROR, "Not a known data type code=%d", targtype))
#undef X_INNER
#undef X_OUTER
/* Store new data */
if (diffsize) {
if (!was_useheap && !will_useheap) {
memmove(&a->value, data_to_void, nbytes);
} else if (!will_useheap) {
/* was heap, now not */
memmove(a->data = &a->value, data_to_void, nbytes);
SvREFCNT_dec((SV*)a->datasv);
a->datasv = NULL;
} else {
/* now change to be heap */
if (a->datasv == NULL)
a->datasv = newSVpvn("", 0);
(void)SvGROW((SV*)a->datasv, nbytes);
SvCUR_set((SV*)a->datasv, nbytes);
memmove(a->data = SvPV_nolen((SV*)a->datasv), data_to_void, nbytes);
}
}
a->datatype = targtype;
PDLDEBUG_f(printf("pdl_converttype after: "); pdl_dump(a));
if (a->has_badvalue && a->badvalue.type != a->datatype)
return pdl_make_error(PDL_EUSERERROR, "Badvalue has type=%d != pdltype=%d", a->badvalue.type, a->datatype);
return PDL_err;
}
/* generated from:
pp_def(
'converttypei',
GlobalNew => 'converttypei_new',
OtherPars => 'pdl_datatypes totype;',
Identity => 1,
# Forced types
FTypes => {CHILD => '$COMP(totype)'},
Doc => 'internal',
);
*/
/* also in pdlaffine.c */
#define PDL_ALL_GENTYPES { PDL_SB, PDL_B, PDL_S, PDL_US, PDL_L, PDL_UL, PDL_IND, PDL_ULL, PDL_LL, PDL_F, PDL_D, PDL_LD, PDL_CF, PDL_CD, PDL_CLD, -1 }
typedef struct pdl_params_converttypei {
pdl_datatypes totype;
} pdl_params_converttypei;
pdl_error pdl_converttypei_redodims(pdl_trans *trans) {
pdl_error PDL_err = {0, NULL, 0};
pdl *__it = trans->pdls[1];
pdl_hdr_childcopy(trans);
PDL_Indx i;
PDL_RETERROR(PDL_err, pdl_reallocdims(__it, trans->pdls[0]->ndims));
for (i=0; i<trans->pdls[1]->ndims; i++)
trans->pdls[1]->dims[i] = trans->pdls[0]->dims[i];
PDL_RETERROR(PDL_err, pdl_setdims_careful(__it));
pdl_reallocbroadcastids(trans->pdls[1], trans->pdls[0]->nbroadcastids);
for (i=0; i<trans->pdls[0]->nbroadcastids; i++)
trans->pdls[1]->broadcastids[i] = trans->pdls[0]->broadcastids[i];
trans->dims_redone = 1;
return PDL_err;
}
#define COPYCONVERT(from, to, ppsym_to, ctype_to) \
PDL_Indx i, nvals = trans->pdls[1]->nvals; \
if (trans->bvalflag) \
for (i=0; i<nvals; i++) \
to ## _datap[i] = \
THIS_ISBAD(from ## _badval_isnan, from ## _badval, from ## _datap[i]) ? to ## _badval : \
PDL_GENTYPE_IS_UNSIGNED_##ppsym_to ? (ctype_to)(intmax_t) from ## _datap[i] : \
from ## _datap[i]; \
else \
for (i=0; i<nvals; i++) to ## _datap[i] = \
PDL_GENTYPE_IS_UNSIGNED_##ppsym_to ? (ctype_to)(intmax_t) from ## _datap[i] : \
from ## _datap[i];
pdl_error pdl_converttypei_readdata(pdl_trans *trans) {
pdl_error PDL_err = {0, NULL, 0};
pdl_params_converttypei *params = trans->params;
pdl_datatypes fromtype = trans->__datatype, totype = params->totype;
extern struct Core PDL;
struct Core *PDLptr = &PDL;
#define PDL PDLptr /* so PDL_DECLARE_PARAMETER_BADVAL can get bvals */
PDLDEBUG_f(printf("pdl_converttypei_readdata %s=%p to type=%d from parent: ", trans->vtable->name, trans, totype); pdl_dump(trans->pdls[0]));
#define FROMpdl_indx 0
#define TOpdl_indx 1
#define X_OUTER(datatype_from, ctype_from, ppsym_from, ...) \
PDL_DECLARE_PARAMETER_BADVAL(ctype_from, FROMpdl, (trans->pdls[FROMpdl_indx]), 1, ppsym_from)
#define X_INNER(datatype_to, ctype_to, ppsym_to, ...) \
PDL_DECLARE_PARAMETER_BADVAL(ctype_to, TOpdl, (trans->pdls[TOpdl_indx]), 1, ppsym_to) \
COPYCONVERT(FROMpdl, TOpdl, ppsym_to, ctype_to)
PDL_GENERICSWITCH2(
PDL_TYPELIST_ALL, fromtype, X_OUTER, return pdl_make_error(PDL_EUSERERROR, "Not a known data type code=%d", fromtype),
PDL_TYPELIST_ALL_, totype, X_INNER, return pdl_make_error(PDL_EUSERERROR, "Not a known data type code=%d", totype))
pdl *TOpdl = trans->pdls[TOpdl_indx];
#undef FROMpdl_indx
#undef TOpdl_indx
#undef PDL
if (TOpdl->has_badvalue && TOpdl->badvalue.type != TOpdl->datatype)
return pdl_make_error(PDL_EUSERERROR, "Badvalue has type=%d != pdltype=%d", TOpdl->badvalue.type, TOpdl->datatype);
return PDL_err;
}
pdl_error pdl_converttypei_writebackdata(pdl_trans *trans) {
pdl_error PDL_err = {0, NULL, 0};
pdl_params_converttypei *params = trans->params;
pdl_datatypes fromtype = params->totype, totype = trans->__datatype;
extern struct Core PDL;
struct Core *PDLptr = &PDL;
#define PDL PDLptr /* so PDL_DECLARE_PARAMETER_BADVAL can get bvals */
PDLDEBUG_f(printf("pdl_converttypei_writebackdata %s=%p from child to type=%d: ", trans->vtable->name, trans, totype); pdl_dump(trans->pdls[1]));
#define FROMpdl_indx 1
#define TOpdl_indx 0
PDL_GENERICSWITCH2(
PDL_TYPELIST_ALL, fromtype, X_OUTER, return pdl_make_error(PDL_EUSERERROR, "Not a known data type code=%d", fromtype),
PDL_TYPELIST_ALL_, totype, X_INNER, return pdl_make_error(PDL_EUSERERROR, "Not a known data type code=%d", totype))
#undef X_INNER
#undef X_OUTER
pdl *TOpdl = trans->pdls[TOpdl_indx];
#undef FROMpdl_indx
#undef TOpdl_indx
#undef PDL
if (TOpdl->has_badvalue && TOpdl->badvalue.type != TOpdl->datatype)
return pdl_make_error(PDL_EUSERERROR, "Badvalue has type=%d != pdltype=%d", TOpdl->badvalue.type, TOpdl->datatype);
return PDL_err;
}
static pdl_datatypes pdl_converttypei_vtable_gentypes[] = PDL_ALL_GENTYPES;
static char pdl_converttypei_vtable_flags[] = { 0, 0 }; /*CORE21*/
static PDL_Indx pdl_converttypei_vtable_realdims[] = { 0, 0 };
static char *pdl_converttypei_vtable_parnames[] = { "PARENT","CHILD" };
static short pdl_converttypei_vtable_parflags[] = {
PDL_PARAM_ALLOW_NULL|PDL_PARAM_ISPHYS,
PDL_PARAM_ISCREAT|PDL_PARAM_ISCREATEALWAYS|PDL_PARAM_ISIGNORE|PDL_PARAM_ISOUT|PDL_PARAM_ISPHYS|PDL_PARAM_ISWRITE
};
static pdl_datatypes pdl_converttypei_vtable_partypes[] = { -1, -1 };
static PDL_Indx pdl_converttypei_vtable_realdims_starts[] = { 0, 0 };
static PDL_Indx pdl_converttypei_vtable_realdims_ind_ids[] = { 0 };
static char *pdl_converttypei_vtable_indnames[] = { "" };
pdl_transvtable pdl_converttypei_vtable = {
PDL_TRANS_BADPROCESS, PDL_ITRANS_TWOWAY|PDL_ITRANS_DO_DATAFLOW_ANY, pdl_converttypei_vtable_gentypes, 1, 2, pdl_converttypei_vtable_flags /*CORE21*/,
pdl_converttypei_vtable_realdims, pdl_converttypei_vtable_parnames,
pdl_converttypei_vtable_parflags, pdl_converttypei_vtable_partypes,
pdl_converttypei_vtable_realdims_starts, pdl_converttypei_vtable_realdims_ind_ids, 0,
0, pdl_converttypei_vtable_indnames,
pdl_converttypei_redodims, pdl_converttypei_readdata, pdl_converttypei_writebackdata,
NULL,
sizeof(pdl_params_converttypei),"converttypei_new"
};
pdl_error pdl__set_output_type_badvalue(pdl_trans *trans, int recurse_count);
pdl_error pdl__converttypei_new_recprotect(pdl *PARENT, pdl *CHILD, pdl_datatypes totype, pdl_datatypes force_intype, int recurse_count) {
pdl_error PDL_err = {0, NULL, 0};
PDL_RECURSE_CHECK(recurse_count);
pdl_trans *trans = pdl_create_trans(&pdl_converttypei_vtable);
pdl_params_converttypei *params = trans->params;
trans->pdls[0] = PARENT;
trans->pdls[1] = CHILD;
trans->__datatype = PARENT->datatype = force_intype;
PDL_RETERROR(PDL_err, pdl__set_output_type_badvalue(trans, recurse_count + 1));
trans->pdls[1]->datatype = params->totype = totype;
PDL_RETERROR(PDL_err, pdl_make_trans_mutual((pdl_trans *)trans));
return PDL_err;
}
pdl_error pdl_converttypei_new(pdl *PARENT, pdl *CHILD, pdl_datatypes totype) {
return pdl__converttypei_new_recprotect(PARENT, CHILD, totype, PARENT->datatype, 0);
}