#include "pdl.h" /* Data structure declarations */
#define PDL_IN_CORE
#include "pdlcore.h" /* Core declarations */
#include <stdarg.h>
extern Core PDL; /* for PDL_TYPENAME */
#define msgptr_advance() \
do { \
int N = strlen(msgptr); \
msgptr += N; \
remaining -= N; \
} while(0)
#define SET_SPACE(s, nspac) char spaces[PDL_MAXSPACE]; do { \
int i; \
if (nspac >= PDL_MAXSPACE) { \
printf("too many spaces requested: %d" \
" (increase PDL_MAXSPACE in pdlapi.c), returning\n",nspac); \
return; \
} \
for(i=0; i<nspac; i++) spaces[i]=' '; \
spaces[i] = '\0'; \
} while (0)
#define psp printf("%s",spaces)
/* modified from glibc printf(3) */
pdl_error pdl_make_error(pdl_error_type e, const char *fmt, ...) {
pdl_error PDL_err = {PDL_EFATAL, "make_error problem", 0};
PDLDEBUG_f(printf("pdl_make_error called: "));
va_list ap;
/* Determine required size */
va_start(ap, fmt);
int size = vsnprintf(NULL, 0, fmt, ap);
va_end(ap);
if (size < 0) return PDL_err;
char needs_free = 1;
char *p = NULL;
if (pdl_pthread_main_thread()) {
size++; /* For '\0' */
p = malloc(size);
if (p == NULL) return PDL_err;
va_start(ap, fmt);
size = vsnprintf(p, size, fmt, ap);
va_end(ap);
if (size < 0) {
free(p);
return PDL_err;
}
} else {
size_t len = 0;
va_start(ap, fmt);
pdl_pthread_realloc_vsnprintf(&p, &len, size, fmt, &ap, 0);
va_end(ap);
needs_free = 2;
}
PDLDEBUG_f(printf("%s\n", p));
return (pdl_error){e, p, needs_free};
}
pdl_error pdl_make_error_simple(pdl_error_type e, const char *msg) {
pdl_error PDL_err = {e, msg, 0};
return PDL_err;
}
pdl_error pdl_param_error(
pdl_transvtable *vtable, int paramIndex,
pdl **pdls, PDL_Indx nimpl, PDL_Indx *creating,
char *pat, ...
) {
// I make a pdl_error with a string such as "function(a,b,c): parameter 'b': errormessage"
char message [4096] = {'\0'};
int i,j,maxrealdims;
va_list args;
char* msgptr = message;
int remaining = sizeof(message);
if(paramIndex < 0 || paramIndex >= vtable->npdls) {
strcat(msgptr, "ERROR: UNKNOWN PARAMETER");
msgptr_advance();
} else {
snprintf(msgptr, remaining, "%s(", vtable->name);
msgptr_advance();
for(i=0; i<vtable->npdls; i++) {
snprintf(msgptr, remaining, "%s", vtable->par_names[i]);
msgptr_advance();
if(i < vtable->npdls-1) {
snprintf(msgptr, remaining, ",");
msgptr_advance();
}
}
snprintf(msgptr, remaining, "): parameter '%s': ",
vtable->par_names[paramIndex]);
msgptr_advance();
}
va_start(args,pat);
vsnprintf(msgptr, remaining, pat, args);
va_end(args);
msgptr_advance();
snprintf(msgptr, remaining,
"\nThere are %"IND_FLAG" PDLs in the expression; %"IND_FLAG" broadcast dim%s.\n",
vtable->npdls,nimpl,(nimpl==1)?"":"s"
);
msgptr_advance();
for(i=maxrealdims=0; i<vtable->npdls; i++)
if(vtable->par_realdims[i]>maxrealdims)
maxrealdims=vtable->par_realdims[i];
snprintf(msgptr, remaining, " PDL IN EXPR. ");
msgptr_advance();
if(maxrealdims > 0) {
char format[80];
snprintf(format, sizeof(format)-1, "%%%ds", 8 * maxrealdims + 3);
snprintf(msgptr,remaining,format,"ACTIVE DIMS | ");
msgptr_advance();
}
snprintf(msgptr, remaining,"BROADCAST DIMS\n");
msgptr_advance();
for(i=0; i<vtable->npdls; i++) {
snprintf(msgptr,remaining," #%3d (%s",i,creating[i]?"null)\n":"normal): ");
msgptr_advance();
if(creating[i])
continue;
if(maxrealdims == 1) {
snprintf(msgptr,remaining," ");
msgptr_advance();
}
for(j=0; j< maxrealdims - vtable->par_realdims[i]; j++) {
snprintf(msgptr,remaining,"%8s"," ");
msgptr_advance();
}
for(j=0; j< vtable->par_realdims[i]; j++) {
snprintf(msgptr,remaining,"%8"IND_FLAG,pdls[i]->dims[j]);
msgptr_advance();
}
if(maxrealdims) {
snprintf(msgptr,remaining," | ");
msgptr_advance();
}
for(j=0; j<nimpl && j + vtable->par_realdims[i] < pdls[i]->ndims; j++) {
snprintf(msgptr,remaining,"%8"IND_FLAG,pdls[i]->dims[j+vtable->par_realdims[i]]);
msgptr_advance();
}
snprintf(msgptr,remaining,"\n");
msgptr_advance();
}
return pdl_make_error(PDL_EUSERERROR, "%s", message);
}
void pdl_print_iarr(PDL_Indx *iarr, int n) {
int i;
printf("(");
for (i=0;i<n;i++) printf("%s%"IND_FLAG,(i?" ":""),iarr[i]);
printf(")");
}
void pdl_dump_transvtable(pdl_transvtable *vtable, int nspac) {
int i, j, found=0, sz=0;
SET_SPACE(spaces, nspac);
int paramflagval[] = {
#define X(f) f,
PDL_LIST_FLAGS_PARAMS(X)
#undef X
0
};
char *paramflagchar[] = {
#define X(f) #f,
PDL_LIST_FLAGS_PARAMS(X)
#undef X
NULL
};
int typeval[] = {
#define X(sym, ...) sym,
PDL_TYPELIST_ALL(X)
#undef X
-1
};
char *typechar[] = {
#define X(sym, ...) #sym,
PDL_TYPELIST_ALL(X)
#undef X
NULL
};
psp; printf("Funcname: %s\n",vtable->name);
psp; printf("Types: ");
found=0; sz=0;
for (i=0;vtable->gentypes[i]!=-1; i++) {
char *this_str = typechar[vtable->gentypes[i]] + 4; /* "PDL_" */
size_t thislen = strlen(this_str);
if ((sz+thislen)>PDL_MAXLIN) {sz=nspac+4; printf("\n%s ",spaces);}
printf("%s%s",found ? ",":"",this_str); found = 1;
sz += thislen;
}
printf("\n");
psp; printf("Parameters:\n");
for (i=0;i<vtable->npdls;i++) {
psp; sz = nspac + printf(" %s(",vtable->par_names[i]);
found=0;
for (j=0;j<vtable->par_realdims[i];j++) {
if (found) sz += printf(","); found=1;
sz += printf("%s",vtable->ind_names[PDL_IND_ID(vtable, i, j)]);
}
if (vtable->par_flags[i] & PDL_PARAM_ISTYPED)
sz += printf(") (%s", PDL_TYPENAME(vtable->par_types[i]));
sz += printf("): ");
found=0;
for (j=0;paramflagval[j]!=0; j++)
if (vtable->par_flags[i] & paramflagval[j]) {
char *this_str = paramflagchar[j];
size_t thislen = strlen(this_str);
if ((sz+thislen)>PDL_MAXLIN) {sz=nspac+8; printf("\n%s ",spaces);}
sz += printf("%s%s",found ? "|":"",this_str); found = 1;
}
if (!found) printf("(no flags set)");
printf("\n");
}
psp; printf("Indices:");
for (i=0;i<vtable->ninds;i++)
printf(" %s",vtable->ind_names[i]);
printf("\n");
}
void pdl_dump_broadcast(pdl_broadcast *broadcast) {
int i, j, found=0, sz=0, nspac=4;
SET_SPACE(spaces, nspac);
int flagval[] = {
#define X(f) f,
PDL_LIST_FLAGS_PDLBROADCAST(X)
#undef X
0
};
char *flagchar[] = {
#define X(f) #f,
PDL_LIST_FLAGS_PDLBROADCAST(X)
#undef X
NULL
};
printf("DUMPBROADCAST %p\n",broadcast);
if (broadcast->transvtable)
pdl_dump_transvtable(broadcast->transvtable, 4);
psp; printf("Flags: ");
found=0; sz=0;
for (i=0;flagval[i]!=0; i++)
if (broadcast->gflags & flagval[i]) {
char *this_str = flagchar[i];
size_t thislen = strlen(this_str);
if ((sz+thislen)>PDL_MAXLIN) {sz=nspac; printf("\n%s",spaces);}
printf("%s%s",found ? "|":"",this_str); found = 1;
sz += thislen;
}
printf("\n");
psp; printf("Ndims: %"IND_FLAG", Nimplicit: %"IND_FLAG", Npdls: %"IND_FLAG", Nextra: %"IND_FLAG"\n",
broadcast->ndims,broadcast->nimpl,broadcast->npdls,broadcast->nextra);
psp; printf("Mag_nth: %"IND_FLAG", Mag_nthpdl: %"IND_FLAG", Mag_nthr: %"IND_FLAG", Mag_skip: %"IND_FLAG", Mag_stride: %"IND_FLAG"\n",
broadcast->mag_nth,broadcast->mag_nthpdl,broadcast->mag_nthr,broadcast->mag_skip,broadcast->mag_stride);
if (broadcast->mag_nthr <= 0) {
psp; printf("Dims: "); pdl_print_iarr(broadcast->dims,broadcast->ndims); printf("\n");
psp; printf("Inds: "); pdl_print_iarr(broadcast->inds,broadcast->ndims); printf("\n");
psp; printf("Offs: "); pdl_print_iarr(broadcast->offs,broadcast->npdls); printf("\n");
} else {
psp; printf("Dims (per thread):\n");
for (i=0;i<broadcast->mag_nthr;i++) {
psp; psp; pdl_print_iarr(broadcast->dims + i*broadcast->ndims,broadcast->ndims);
printf("\n");
}
psp; printf("Inds (per thread):\n");
for (i=0;i<broadcast->mag_nthr;i++) {
psp; psp; pdl_print_iarr(broadcast->inds + i*broadcast->ndims,broadcast->ndims);
printf("\n");
}
psp; printf("Offs (per thread):\n");
for (i=0;i<broadcast->mag_nthr;i++) {
psp; psp; pdl_print_iarr(broadcast->offs + i*broadcast->npdls,broadcast->npdls);
printf("\n");
}
}
psp; printf("Incs (per dim):\n");
for (i=0;i<broadcast->ndims;i++) {
psp; psp; pdl_print_iarr(&PDL_BRC_INC(broadcast->incs, broadcast->npdls, 0, i),broadcast->npdls);
printf("\n");
}
psp; printf("Realdims: "); pdl_print_iarr(broadcast->realdims,broadcast->npdls); printf("\n");
psp; printf("Pdls: (");
for (i=0;i<broadcast->npdls;i++)
printf("%s%p",(i?" ":""),(broadcast->pdls[i]));
printf(")\n");
psp; printf("Per pdl flags: (");
for (i=0;i<broadcast->npdls;i++)
printf("%s%d",(i?" ":""),broadcast->flags[i]);
printf(")\n");
}
void pdl_dump_broadcasting_info(
int npdls, PDL_Indx* creating, int target_pthread,
PDL_Indx *nbroadcastedDims, PDL_Indx **broadcastedDims, PDL_Indx **broadcastedDimSizes,
int maxPthreadPDL, int maxPthreadDim, int maxPthread
) {
PDL_Indx j, k;
for(j=0; j<npdls; j++) {
if(creating[j]) continue;
printf("PDL %"IND_FLAG":\n", j);
for( k=0; k < nbroadcastedDims[j]; k++){
printf("Broadcast dim %"IND_FLAG", Dim No %"IND_FLAG", Size %"IND_FLAG"\n",
k, broadcastedDims[j][k], broadcastedDimSizes[j][k]);
}
}
printf("\nTarget Pthread = %d\n"
"maxPthread = %d, maxPthreadPDL = %d, maxPthreadDim = %d\n",
target_pthread, maxPthread, maxPthreadPDL, maxPthreadDim);
}
void pdl_dump_flags_fixspace(int flags, int nspac, pdl_flags type)
{
int i;
int found = 0;
size_t sz = 0;
int pdlflagval[] = {
#define X(f) f,
PDL_LIST_FLAGS_PDLSTATE(X)
#undef X
0
};
char *pdlflagchar[] = {
#define X(f) #f,
PDL_LIST_FLAGS_PDLSTATE(X)
#undef X
NULL
};
int transflagval[] = {
#define X(f) f,
PDL_LIST_FLAGS_PDLTRANS(X)
#undef X
0
};
char *transflagchar[] = {
#define X(f) #f,
PDL_LIST_FLAGS_PDLTRANS(X)
#undef X
NULL
};
int vtableflagval[] = {
#define X(f) f,
PDL_LIST_FLAGS_PDLVTABLE(X)
#undef X
0
};
char *vtableflagchar[] = {
#define X(f) #f,
PDL_LIST_FLAGS_PDLVTABLE(X)
#undef X
NULL
};
int *flagval;
char **flagchar;
SET_SPACE(spaces, nspac);
switch (type) {
case PDL_FLAGS_PDL: {
flagval = pdlflagval;
flagchar = pdlflagchar;
break; }
case PDL_FLAGS_VTABLE: {
flagval = vtableflagval;
flagchar = vtableflagchar;
break; }
default: {
flagval = transflagval;
flagchar = transflagchar;
}
}
printf("(%d) ",flags);
found = 0; sz = 0;
for (i=0;flagval[i]!=0; i++)
if (flags & flagval[i]) {
char *this_str = flagchar[i];
size_t thislen = strlen(this_str);
if ((sz+thislen)>PDL_MAXLIN) {sz=7+nspac; printf("\n %s",spaces);}
printf("%s%s",found ? "|":"",this_str); found = 1;
sz += thislen;
}
printf("\n");
}
/* Dump a transformation (don't dump the pdls, just pointers to them */
void pdl_dump_trans_fixspace (pdl_trans *it, int nspac) {
PDL_Indx i;
SET_SPACE(spaces, nspac);
printf("%sDUMPTRANS %p (%s)\n%s Flags: ",spaces,it,it->vtable->name,spaces);
pdl_dump_flags_fixspace(it->flags,nspac+3, PDL_FLAGS_TRANS);
printf("%s bvalflag: %d\n",spaces,it->bvalflag);
printf("%s vtable flags ",spaces);
pdl_dump_flags_fixspace(it->vtable->flags,nspac+3,PDL_FLAGS_VTABLE);
if(it->flags & PDL_ITRANS_ISAFFINE) {
if(it->pdls[1]->state & PDL_PARENTDIMSCHANGED) {
printf("%s AFFINE, BUT DIMSCHANGED\n",spaces);
} else {
printf("%s AFFINE: o:%"IND_FLAG", i:",spaces,it->offs);
if (it->incs)
pdl_print_iarr(it->incs, it->pdls[1]->ndims);
printf(" d:");
pdl_print_iarr(it->pdls[1]->dims, it->pdls[1]->ndims);
printf("\n");
}
}
/* if(it->vtable->dump) {it->vtable->dump(it);} */
printf("%s ind_sizes: ",spaces);
pdl_print_iarr(it->ind_sizes, it->vtable->ninds); printf("\n");
printf("%s inc_sizes: ",spaces);
pdl_print_iarr(it->inc_sizes, it->vtable->nind_ids); printf("\n");
printf("%s input trans_children_indices: ",spaces); /* CORE21 hook up to own data */
pdl_print_iarr(it->ind_sizes+it->vtable->ninds, it->vtable->nparents); printf("\n");
printf("%s INPUTS: (",spaces);
for(i=0; i<it->vtable->nparents; i++)
printf("%s%p",(i?" ":""),(it->pdls[i]));
printf(") OUTPUTS: (");
for(;i<it->vtable->npdls; i++)
printf("%s%p",(i>it->vtable->nparents?" ":""),(it->pdls[i]));
printf(")\n");
}
void pdl_dump_fixspace(pdl *it,int nspac) {
PDL_Indx i;
SET_SPACE(spaces, nspac);
printf("%sDUMPING %p datatype: %d\n%s State: ",spaces,it,it->datatype,spaces);
pdl_dump_flags_fixspace(it->state,nspac+3,PDL_FLAGS_PDL);
printf("%s transvtable: %p, trans: %p, sv: %p\n",spaces,
it->trans_parent?it->trans_parent->vtable:0, it->trans_parent, it->sv);
if (it->datasv)
printf("%s datasv: %p, Svlen: %lld, refcnt: %lld\n", spaces,
it->datasv, (long long)SvCUR((SV*)it->datasv), (long long)SvREFCNT((SV*)it->datasv));
if (it->data)
printf("%s data: %p, nbytes: %"IND_FLAG", nvals: %"IND_FLAG"\n", spaces,
it->data, it->nbytes, it->nvals);
if (it->hdrsv)
printf("%s hdrsv: %p, reftype %s\n", spaces,
it->hdrsv, sv_reftype((SV*)it->hdrsv, TRUE));
printf("%s Dims: %p ",spaces,it->dims);
pdl_print_iarr(it->dims, it->ndims);
printf("\n%s BroadcastIds: %p ",spaces,it->broadcastids);
pdl_print_iarr(it->broadcastids, it->nbroadcastids);
if (it->vafftrans) {
printf("\n%s Vafftrans: %p (parent), o:%"IND_FLAG", i:",
spaces,it->vafftrans->from,it->vafftrans->offs);
pdl_print_iarr(PDL_REPRINCS(it), it->vafftrans->ndims);
}
if (it->state & PDL_BADVAL) {
printf("\n%s Badvalue (%s): ",spaces, it->has_badvalue ? "bespoke" : "orig");
PDL_Anyval result = { PDL_INVALID, {0} };
if (!(it->has_badvalue && it->badvalue.type != it->datatype)) {
if (it->has_badvalue)
result = it->badvalue;
else {
#define X(datatype, ctype, ppsym, shortctype, defbval, ...) \
result.type = datatype; result.value.ppsym = defbval;
PDL_GENERICSWITCH(PDL_TYPELIST_ALL, it->datatype, X, )
#undef X
}
}
if (result.type < 0)
printf("ERROR getting badval");
else
pdl_dump_anyval(result);
}
if (it->state & PDL_ALLOCATED) {
printf("\n%s First values: (",spaces);
for (i=0; i<it->nvals && i<10; i++) {
if (i) printf(" ");
PDL_Anyval result = { PDL_INVALID, {0} };
ANYVAL_FROM_CTYPE_OFFSET(result, it->datatype, it->data, i);
pdl_dump_anyval(result);
}
} else {
printf("\n%s (not allocated",spaces);
}
printf(")\n");
if (it->trans_parent) {
pdl_dump_trans_fixspace(it->trans_parent,nspac+3);
}
if (it->ntrans_children) {
printf("%s CHILDREN:\n",spaces);
for (i = 0; i < it->ntrans_children_allocated; i++) {
pdl_trans *t = it->trans_children[i];
if (!t) continue;
pdl_dump_trans_fixspace(t, nspac+4);
}
}
}
void pdl_dump (pdl *it) {
pdl_dump_fixspace(it,0);
fflush(stdout);
}
void pdl_dump_anyval(PDL_Anyval v) {
if (v.type < PDL_CF) {
#define X(datatype, ctype, ppsym, ...) \
printf("%Lg", (long double)v.value.ppsym);
PDL_GENERICSWITCH(PDL_TYPELIST_REAL, v.type, X, printf("(UNKNOWN PDL_Anyval type=%d)", v.type))
#undef X
} else {
#define X(datatype, ctype, ppsym, ...) \
printf("%Lg%+Lgi", creall((complex long double)v.value.ppsym), cimagl((complex long double)v.value.ppsym));
PDL_GENERICSWITCH(PDL_TYPELIST_COMPLEX, v.type, X, printf("(UNKNOWN PDL_Anyval type=%d)", v.type))
#undef X
}
}
void pdl_error_free(pdl_error e) {
if (e.needs_free == 1) {
free((void *)e.message);
} else {
/* needs mutex-protected and de-Perl-ified */
pdl_pthread_free((void *)e.message);
}
}
void pdl_barf_if_error(pdl_error err) {
if (!err.error) return;
const char *msg = err.message;
if (err.needs_free) {
char *cpy = pdl_smalloc(strlen(msg) + 1);
strcpy(cpy, err.message);
pdl_error_free(err);
msg = cpy;
}
pdl_pdl_barf(msg);
}
pdl_error pdl_error_accumulate(pdl_error err_current, pdl_error err_new) {
if (!err_new.error) return err_current;
if (!err_current.error) return err_new;
pdl_error PDL_err = pdl_make_error(
PDLMAX(err_current.error, err_current.error),
"%s\n%s", err_current.message, err_new.message
);
if (err_current.needs_free) pdl_error_free(err_current);
if (err_new.needs_free) pdl_error_free(err_new);
return PDL_err;
}