/* This is included into MPI.xs. It's just here to unclutter MPI.xs a bit */
static double
constant(name, arg)
char *name;
int arg;
{
errno = 0;
if (strEQ(name, "MPI_2COMPLEX"))
#ifdef MPI_2COMPLEX
return MPI_2COMPLEX;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_2DOUBLE_COMPLEX"))
#ifdef MPI_2DOUBLE_COMPLEX
return MPI_2DOUBLE_COMPLEX;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_2DOUBLE_PRECISION"))
#ifdef MPI_2DOUBLE_PRECISION
return MPI_2DOUBLE_PRECISION;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_2INT"))
#ifdef MPI_2INT
return MPI_2INT;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_2INTEGER"))
#ifdef MPI_2INTEGER
return MPI_2INTEGER;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_2REAL"))
#ifdef MPI_2REAL
return MPI_2REAL;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_ANY_SOURCE"))
#ifdef MPI_ANY_SOURCE
return MPI_ANY_SOURCE;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_ANY_TAG"))
#ifdef MPI_ANY_TAG
return MPI_ANY_TAG;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_BAND"))
#ifdef MPI_BAND
return MPI_BAND;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_BOR"))
#ifdef MPI_BOR
return MPI_BOR;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_BSEND_OVERHEAD"))
#ifdef MPI_BSEND_OVERHEAD
return MPI_BSEND_OVERHEAD;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_BXOR"))
#ifdef MPI_BXOR
return MPI_BXOR;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_BYTE"))
#ifdef MPI_BYTE
return MPI_BYTE;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_CART"))
#ifdef MPI_CART
return MPI_CART;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_CHAR"))
#ifdef MPI_CHAR
return MPI_CHAR;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_CHARACTER"))
#ifdef MPI_CHARACTER
return MPI_CHARACTER;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_COMM_NULL"))
#ifdef MPI_COMM_NULL
return MPI_COMM_NULL;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_COMM_SELF"))
#ifdef MPI_COMM_SELF
return MPI_COMM_SELF;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_COMM_WORLD"))
#ifdef MPI_COMM_WORLD
return MPI_COMM_WORLD;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_COMPLEX"))
#ifdef MPI_COMPLEX
return MPI_COMPLEX;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_CONGRUENT"))
#ifdef MPI_CONGRUENT
return MPI_CONGRUENT;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_DATATYPE_NULL"))
#ifdef MPI_DATATYPE_NULL
return MPI_DATATYPE_NULL;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_DOUBLE"))
#ifdef MPI_DOUBLE
return MPI_DOUBLE;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_DOUBLE_COMPLEX"))
#ifdef MPI_DOUBLE_COMPLEX
return MPI_DOUBLE_COMPLEX;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_DOUBLE_INT"))
#ifdef MPI_DOUBLE_INT
return MPI_DOUBLE_INT;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_DOUBLE_PRECISION"))
#ifdef MPI_DOUBLE_PRECISION
return MPI_DOUBLE_PRECISION;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_ERRHANDLER_NULL"))
#ifdef MPI_ERRHANDLER_NULL
return MPI_ERRHANDLER_NULL;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_ERRORS_ARE_FATAL"))
#ifdef MPI_ERRORS_ARE_FATAL
return MPI_ERRORS_ARE_FATAL;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_ERRORS_RETURN"))
#ifdef MPI_ERRORS_RETURN
return MPI_ERRORS_RETURN;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_FLOAT"))
#ifdef MPI_FLOAT
return MPI_FLOAT;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_FLOAT_INT"))
#ifdef MPI_FLOAT_INT
return MPI_FLOAT_INT;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_GRAPH"))
#ifdef MPI_GRAPH
return MPI_GRAPH;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_GROUP_EMPTY"))
#ifdef MPI_GROUP_EMPTY
return MPI_GROUP_EMPTY;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_GROUP_NULL"))
#ifdef MPI_GROUP_NULL
return MPI_GROUP_NULL;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_HOST"))
#ifdef MPI_HOST
return MPI_HOST;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_IDENT"))
#ifdef MPI_IDENT
return MPI_IDENT;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_INT"))
#ifdef MPI_INT
return MPI_INT;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_INTEGER"))
#ifdef MPI_INTEGER
return MPI_INTEGER;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_IO"))
#ifdef MPI_IO
return MPI_IO;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_KEYVAL_INVALID"))
#ifdef MPI_KEYVAL_INVALID
return MPI_KEYVAL_INVALID;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_LAND"))
#ifdef MPI_LAND
return MPI_LAND;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_LB"))
#ifdef MPI_LB
return MPI_LB;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_LOGICAL"))
#ifdef MPI_LOGICAL
return MPI_LOGICAL;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_LONG"))
#ifdef MPI_LONG
return MPI_LONG;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_LONG_DOUBLE"))
#ifdef MPI_LONG_DOUBLE
return MPI_LONG_DOUBLE;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_LONG_DOUBLE_INT"))
#ifdef MPI_LONG_DOUBLE_INT
return MPI_LONG_DOUBLE_INT;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_LONG_INT"))
#ifdef MPI_LONG_INT
return MPI_LONG_INT;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_LONG_LONG_INT"))
#ifdef MPI_LONG_LONG_INT
return MPI_LONG_LONG_INT;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_LOR"))
#ifdef MPI_LOR
return MPI_LOR;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_LXOR"))
#ifdef MPI_LXOR
return MPI_LXOR;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_MAX"))
#ifdef MPI_MAX
return MPI_MAX;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_MAXLOC"))
#ifdef MPI_MAXLOC
return MPI_MAXLOC;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_MAX_ERROR_STRING"))
#ifdef MPI_MAX_ERROR_STRING
return MPI_MAX_ERROR_STRING;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_MAX_NAME_STRING"))
#ifdef MPI_MAX_NAME_STRING
return MPI_MAX_NAME_STRING;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_MAX_PROCESSOR_NAME"))
#ifdef MPI_MAX_PROCESSOR_NAME
return MPI_MAX_PROCESSOR_NAME;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_MIN"))
#ifdef MPI_MIN
return MPI_MIN;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_MINLOC"))
#ifdef MPI_MINLOC
return MPI_MINLOC;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_OP_NULL"))
#ifdef MPI_OP_NULL
return MPI_OP_NULL;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_PACKED"))
#ifdef MPI_PACKED
return MPI_PACKED;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_PROC_NULL"))
#ifdef MPI_PROC_NULL
return MPI_PROC_NULL;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_PROD"))
#ifdef MPI_PROD
return MPI_PROD;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_REAL"))
#ifdef MPI_REAL
return MPI_REAL;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_SHORT"))
#ifdef MPI_SHORT
return MPI_SHORT;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_SHORT_INT"))
#ifdef MPI_SHORT_INT
return MPI_SHORT_INT;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_SIMILAR"))
#ifdef MPI_SIMILAR
return MPI_SIMILAR;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_STRING"))
#ifdef MPI_STRING
return MPI_STRING;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_SUBVERSION"))
#ifdef MPI_SUBVERSION
return MPI_SUBVERSION;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_SUM"))
#ifdef MPI_SUM
return MPI_SUM;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_TAG_UB"))
#ifdef MPI_TAG_UB
return MPI_TAG_UB;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_UB"))
#ifdef MPI_UB
return MPI_UB;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_UNDEFINED"))
#ifdef MPI_UNDEFINED
return MPI_UNDEFINED;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_UNDEFINED_RANK"))
#ifdef MPI_UNDEFINED_RANK
return MPI_UNDEFINED_RANK;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_UNEQUAL"))
#ifdef MPI_UNEQUAL
return MPI_UNEQUAL;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_UNSIGNED"))
#ifdef MPI_UNSIGNED
return MPI_UNSIGNED;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_UNSIGNED_CHAR"))
#ifdef MPI_UNSIGNED_CHAR
return MPI_UNSIGNED_CHAR;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_UNSIGNED_LONG"))
#ifdef MPI_UNSIGNED_LONG
return MPI_UNSIGNED_LONG;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_UNSIGNED_SHORT"))
#ifdef MPI_UNSIGNED_SHORT
return MPI_UNSIGNED_SHORT;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_VERSION"))
#ifdef MPI_VERSION
return MPI_VERSION;
#else
goto not_there;
#endif
if (strEQ(name, "MPI_WTIME_IS_GLOBAL"))
#ifdef MPI_WTIME_IS_GLOBAL
return MPI_WTIME_IS_GLOBAL;
#else
goto not_there;
#endif
errno = EINVAL;
return 0;
goto not_there; /* -Wall */
not_there:
errno = ENOENT;
return 0;
}
int MPIpm_bufsize(MPI_Datatype datatype, SV* scalar, int count) {
switch (datatype) {
case MPI_INT:
case MPI_INTEGER:
return count * sizeof(int);
break;
case MPI_DOUBLE:
return count * sizeof(double);
break;
#ifndef FLOAT_HACK
case MPI_FLOAT:
return count * sizeof(float);
break;
#endif
case MPI_CHAR:
return (count + 1) * sizeof(char);
break;
case MPI_STRING:
case MPI_2COMPLEX:
case MPI_2DOUBLE_COMPLEX:
case MPI_2DOUBLE_PRECISION:
case MPI_2INT:
case MPI_2INTEGER:
case MPI_2REAL:
case MPI_BYTE:
case MPI_COMPLEX:
case MPI_DATATYPE_NULL:
case MPI_DOUBLE_COMPLEX:
case MPI_DOUBLE_INT:
case MPI_DOUBLE_PRECISION:
case MPI_FLOAT_INT:
case MPI_LONG:
case MPI_LONG_DOUBLE:
case MPI_LONG_DOUBLE_INT:
case MPI_LONG_INT:
case MPI_LONG_LONG_INT:
case MPI_REAL:
case MPI_SHORT:
case MPI_SHORT_INT:
case MPI_UNSIGNED:
case MPI_UNSIGNED_CHAR:
case MPI_UNSIGNED_LONG:
case MPI_UNSIGNED_SHORT:
croak("Unsupported datatype %d in MPIpm_bufsize()", datatype);
break;
default:
croak("Unrecognized datatype %d in MPIpm_bufsize()", datatype);
break;
}
return(-1);
}
int MPIpm_packarray(void** buf, AV* array, MPI_Datatype datatype, int count) {
int i,len=0,avl;
SV** sv_tmp;
char* t;
avl = av_len(array);
if(avl < 0) {
*buf = NULL;
return 0;
}
if(count > 0) {
avl = count-1;
}
switch(datatype) {
case MPI_STRING:
for(i=0 ; i<=avl ; i++) {
sv_tmp = av_fetch(array, i, 0);
if(sv_tmp != NULL)
len += SvCUR(*sv_tmp)+1+sizeof(int);
}
t = *buf = (void*) malloc(len);
for(i=0;i<=avl;i++) {
int n;
sv_tmp = av_fetch(array, i, 0);
n = htonl(SvCUR(*sv_tmp)+1);
memcpy(t, &n, sizeof(int));
memcpy(t+sizeof(int), SvPV(*sv_tmp, PL_na), SvCUR(*sv_tmp)+1);
t += SvCUR(*sv_tmp)+1+sizeof(int);
}
return(len);
break;
case MPI_INT:
case MPI_INTEGER:
len = (avl+1) * sizeof(int);
t = *buf = (void*) malloc(len);
for(i=0;i<=avl;i++) {
int n;
sv_tmp = av_fetch(array, i, 0);
n = SvIV(*sv_tmp);
memcpy(t, &n, sizeof(int));
t += sizeof(int);
}
return(len);
#ifndef FLOAT_HACK
case MPI_FLOAT:
len = (avl+1) * sizeof(float);
t = *buf = (void*) malloc(len);
for(i=0;i<=avl;i++) {
float n;
sv_tmp = av_fetch(array, i, 0);
n = (float)SvNV(*sv_tmp);
memcpy(t, &n, sizeof(float));
t += sizeof(float);
}
return(len);
#endif
case MPI_DOUBLE:
len = (avl+1) * sizeof(double);
t = *buf = (void*) malloc(len);
for(i=0;i<=avl;i++) {
double n;
sv_tmp = av_fetch(array, i, 0);
n = SvNV(*sv_tmp);
memcpy(t, &n, sizeof(double));
t += sizeof(double);
}
return(len);
default:
croak("Unrecognized or unsupported datatype %d in MPIpm_packscalar()",
datatype);
break;
}
return(-1);
}
void MPIpm_unpackarray(void* buf, AV** array, MPI_Datatype datatype, int count)
{
int i;
char* t = buf;
av_clear(*array);
switch(datatype) {
case MPI_STRING:
croak("Unrecognized or unsupported datatype %d in MPIpm_packscalar()",
datatype);
break;
case MPI_INT:
case MPI_INTEGER:
av_extend(*array, count);
for(i=0;i<count;i++) {
int u;
memcpy(&u, t, sizeof(int));
#ifdef SEND_DEBUG
printf("[%d] u=%d\n", getpid(), u);
#endif
av_push(*array, newSViv(u));
t += sizeof(int);
}
break;
#ifndef FLOAT_HACK
case MPI_FLOAT:
break;
#endif
case MPI_DOUBLE:
av_extend(*array, count);
for(i=0;i<count;i++) {
double u;
memcpy(&u, t, sizeof(double));
#ifdef SEND_DEBUG
printf("[%d] u=%g\n", getpid(), u);
#endif
av_push(*array, newSVnv(u));
t += sizeof(double);
}
break;
default:
croak("Unrecognized or unsupported datatype %d in MPIpm_packscalar()",
datatype);
break;
}
}
void MPIpm_packscalar(char* buf, SV* scalar, MPI_Datatype datatype) {
switch (datatype) {
case MPI_INT:
case MPI_INTEGER:
*(int*)buf = SvIV(scalar);
break;
case MPI_DOUBLE:
*(double*)buf = SvNV(scalar);
break;
#ifndef FLOAT_HACK
case MPI_FLOAT:
*(float*)buf = (float)SvNV(scalar);
break;
#endif
case MPI_CHAR:
memcpy(buf, SvPV(scalar, PL_na), SvCUR(scalar));
*(char*)(buf + SvCUR(scalar)) = '\0';
break;
case MPI_2COMPLEX:
case MPI_2DOUBLE_COMPLEX:
case MPI_2DOUBLE_PRECISION:
case MPI_2INT:
case MPI_2INTEGER:
case MPI_2REAL:
case MPI_BYTE:
case MPI_COMPLEX:
case MPI_DATATYPE_NULL:
case MPI_DOUBLE_COMPLEX:
case MPI_DOUBLE_INT:
case MPI_DOUBLE_PRECISION:
case MPI_FLOAT_INT:
case MPI_LONG:
case MPI_LONG_DOUBLE:
case MPI_LONG_DOUBLE_INT:
case MPI_LONG_INT:
case MPI_LONG_LONG_INT:
case MPI_REAL:
case MPI_SHORT:
case MPI_SHORT_INT:
case MPI_UNSIGNED:
case MPI_UNSIGNED_CHAR:
case MPI_UNSIGNED_LONG:
case MPI_UNSIGNED_SHORT:
croak("Unsupported datatype %d in MPIpm_packscalar()", datatype);
break;
default:
croak("Unrecognized datatype %d in MPIpm_packscalar()", datatype);
break;
}
}
void MPIpm_unpackscalar(void* buf, SV* scalar, MPI_Datatype datatype) {
switch (datatype) {
case MPI_INT:
case MPI_INTEGER:
sv_setiv(scalar, *(int*)buf);
break;
case MPI_DOUBLE:
sv_setnv(scalar, *(double*)buf);
break;
#ifndef FLOAT_HACK
case MPI_FLOAT:
sv_setnv(scalar, (double)*(float*)buf);
break;
#endif
case MPI_CHAR:
sv_setpv(scalar, buf);
break;
case MPI_2COMPLEX:
case MPI_2DOUBLE_COMPLEX:
case MPI_2DOUBLE_PRECISION:
case MPI_2INT:
case MPI_2INTEGER:
case MPI_2REAL:
case MPI_BYTE:
case MPI_COMPLEX:
case MPI_DATATYPE_NULL:
case MPI_DOUBLE_COMPLEX:
case MPI_DOUBLE_INT:
case MPI_DOUBLE_PRECISION:
case MPI_FLOAT_INT:
case MPI_LONG:
case MPI_LONG_DOUBLE:
case MPI_LONG_DOUBLE_INT:
case MPI_LONG_INT:
case MPI_LONG_LONG_INT:
case MPI_REAL:
case MPI_SHORT:
case MPI_SHORT_INT:
case MPI_UNSIGNED:
case MPI_UNSIGNED_CHAR:
case MPI_UNSIGNED_LONG:
case MPI_UNSIGNED_SHORT:
croak("Unsupported datatype %d in MPIpm_unpackscalar()", datatype);
break;
default:
croak("Unrecognized datatype %d in MPIpm_unpackscalar()", datatype);
break;
}
}
void MPIpm_errhandler(char* func, int mpi_errno) {
char buf[1024];
SV *sv_errno, *sv_errstr;
switch (mpi_errno) {
case MPI_SUCCESS:
return;
case MPI_ERR_BUFFER:
sprintf(buf,"%s: MPI_ERR_BUFFER: Invald buffer pointer",func);
break;
case MPI_ERR_COUNT:
sprintf(buf,"%s: MPI_ERR_COUNT: Invalid count argument",func);
break;
case MPI_ERR_TYPE:
sprintf(buf,"%s: MPI_ERR_TYPE: Invalid datatype argument",func);
break;
case MPI_ERR_TAG:
sprintf(buf,"%s: MPI_ERR_TAG: Invalid tag argument",func);
break;
case MPI_ERR_COMM:
sprintf(buf,"%s: MPI_ERR_COMM: Invalid Communicator",func);
break;
case MPI_ERR_RANK:
sprintf(buf,"%s: MPI_ERR_RANK: Invalid rank",func);
break;
case MPI_ERR_ROOT:
sprintf(buf,"%s: MPI_ERR_ROOT: Invalid root",func);
break;
case MPI_ERR_GROUP:
sprintf(buf,"%s: MPI_ERR_GROUP: Null group passed to function",func);
break;
case MPI_ERR_OP:
sprintf(buf,"%s: MPI_ERR_OP: Invalid operation",func);
break;
case MPI_ERR_TOPOLOGY:
sprintf(buf,"%s: MPI_ERR_TOPOLOGY: Invalid topology",func);
break;
case MPI_ERR_DIMS:
sprintf(buf,"%s: MPI_ERR_DIMS: Invalid dimension argument",func);
break;
case MPI_ERR_ARG:
sprintf(buf,"%s: MPI_ERR_ARG: Invalid argument",func);
break;
case MPI_ERR_UNKNOWN:
sprintf(buf,"%s: MPI_ERR_UNKNOWN: Unknown error",func);
break;
case MPI_ERR_TRUNCATE:
sprintf(buf,"%s: MPI_ERR_TRUNCATE: message truncated on receive",func);
break;
case MPI_ERR_OTHER:
sprintf(buf,"%s: MPI_ERR_OTHER: other error",func);
break;
case MPI_ERR_INTERN:
sprintf(buf,"%s: MPI_ERR_INTERN: internal error code",func);
break;
case MPI_ERR_IN_STATUS:
sprintf(buf,"%s: MPI_ERR_IN_STATUS: look in status for error value",func);
break;
case MPI_ERR_PENDING:
sprintf(buf,"%s: MPI_ERR_PENDING: pending request",func);
break;
case MPI_ERR_REQUEST:
sprintf(buf,"%s: MPI_ERR_REQUEST: illegal mpi_request handle",func);
break;
default:
sprintf(buf,"%s: MPI Error %d occurred",func,errno);
break;
}
sv_errno = perl_get_sv("$MPI:errno", TRUE);
sv_errstr = perl_get_sv("$MPI:errstr", TRUE);
sv_setiv(sv_errno,mpi_errno);
sv_setpv(sv_errstr,buf);
if (SvTRUE(perl_get_sv("$MPI::exceptions", TRUE))) {
die(buf);
}
}