diff --git a/Cantera/src/base/Makefile.in b/Cantera/src/base/Makefile.in index f12b52bfd..5960403ae 100644 --- a/Cantera/src/base/Makefile.in +++ b/Cantera/src/base/Makefile.in @@ -29,12 +29,12 @@ PIC_FLAG=@PIC@ CXX_FLAGS = @CXXFLAGS@ $(LOCAL_DEFS) $(CXX_OPT) $(PIC_FLAG) $(DEBUG_FLAG) BASE_OBJ = ct2ctml.o ctml.o misc.o plots.o stringUtils.o xml.o clockWC.o\ - PrintCtrl.o LogPrintCtrl.o + PrintCtrl.o LogPrintCtrl.o mdp_allo.o BASE_H = ct_defs.h ctexceptions.h logger.h XML_Writer.h \ ctml.h plots.h stringUtils.h xml.h config.h utilities.h \ Array.h vec_functions.h global.h FactoryBase.h clockWC.h \ - PrintCtrl.h LogPrintCtrl.h + PrintCtrl.h LogPrintCtrl.h mdp_allo.h CXX_INCLUDES = -I. @CXX_INCLUDES@ LIB = @buildlib@/libctbase.a diff --git a/Cantera/src/base/checkFinite.cpp b/Cantera/src/base/checkFinite.cpp new file mode 100644 index 000000000..4910b1a0a --- /dev/null +++ b/Cantera/src/base/checkFinite.cpp @@ -0,0 +1,112 @@ +/** + * @file checkFinite.cpp + * Declarations for Multi Dimensional Pointer (mdp) routines that + * check for the presence of NaNs in the code. + */ +/* + * $Revision$ + * $Date$ + */ +/* + * Copywrite 2004 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government + * retains certain rights in this software. + * See file License.txt for licensing information. + */ + +#include +#include + +#include +#include +#include + +// We expect that there will be special casing based on the computer +// system here + +#ifdef SOLARIS +#include +#include +#endif + + +using namespace std; + +namespace mdp { + + // Utility routine to check to see that a number is finite. + /* + * @param tmp number to be checked + */ + void checkFinite(const double tmp) throw(std::range_error) { + if (! finite(tmp)) { + if(isnan(tmp)) { + printf("ERROR: we have encountered a nan!\n"); + } else if (isinf(tmp) == 1) { + printf("ERROR: we have encountered a pos inf!\n"); + } else { + printf("ERROR: we have encountered a neg inf!\n"); + } + const std::string s = "checkFinite()"; + throw std::range_error(s); + } + } + + + // Utility routine to link checkFinte() to fortran program + /* + * This routine is accessible from fortran, usually + * + * @param tmp Pointer to the number to check + * + * @todo link it into the usual way Cantera handles Fortran calls + */ + extern "C" void checkfinite_(double * tmp) { + checkFinite(*tmp); + } + + + // Utility routine to check that a double stays bounded + /* + * This routine checks to see if a number stays bounded. The absolute + * value of the number is required to stay below the trigger. + * + * @param tmp Number to be checked + * @param trigger bounds on the number. Defaults to 1.0E20 + */ + void checkMagnitude(const double tmp, const double trigger) throw(std::range_error) { + checkFinite(tmp); + if (fabs(tmp) >= trigger) { + char sbuf[64]; + sprintf(sbuf, "checkMagnitude: Trigger %g exceeded: %g\n", trigger, + tmp); + throw std::range_error(sbuf); + } + } + + // Utility routine to check to see that a number is neither zero + // nor indefinite. + /* + * This check can be used before using the number in a denominator. + * + * @param tmp number to be checked + */ + void checkZeroFinite(const double tmp) throw(std::range_error) { + if ((tmp == 0.0) || (! finite(tmp))) { + if (tmp == 0.0) { + printf("ERROR: we have encountered a zero!\n"); + } else if(isnan(tmp)) { + printf("ERROR: we have encountered a nan!\n"); + } else if (isinf(tmp) == 1) { + printf("ERROR: we have encountered a pos inf!\n"); + } else { + printf("ERROR: we have encountered a neg inf!\n"); + } + char sbuf[64]; + sprintf(sbuf, "checkZeroFinite: zero or indef exceeded: %g\n", + tmp); + throw std::range_error(sbuf); + } + } + +} diff --git a/Cantera/src/base/ctexceptions.h b/Cantera/src/base/ctexceptions.h index b28d5f541..2ea56fa6f 100755 --- a/Cantera/src/base/ctexceptions.h +++ b/Cantera/src/base/ctexceptions.h @@ -16,6 +16,7 @@ #define CT_CTEXCEPTIONS_H #include +#include // See file misc.cpp for implementations of methods/functions declared // here. @@ -64,14 +65,17 @@ namespace Cantera { * */ - + //! Base class for exceptions thrown by Cantera classes. /*! * This class is the base class for exceptions thrown by Cantera. + * It inherits from std::exception so that normal error handling + * operations from applications may automatically handle the + * errors in their own way. * * @ingroup errorhandling */ - class CanteraError { + class CanteraError : public std::exception { public: //! Normal Constructor for the CanteraError base class /*! @@ -86,7 +90,7 @@ namespace Cantera { CanteraError(std::string procedure, std::string msg); //! Destructor for base class does nothing - virtual ~CanteraError(){} + virtual ~CanteraError() throw() {} protected: //! Empty base constructor is made protected so that it may be used only by //! inherited classes. diff --git a/Cantera/src/base/mdp_allo.cpp b/Cantera/src/base/mdp_allo.cpp new file mode 100644 index 000000000..3ed6490ff --- /dev/null +++ b/Cantera/src/base/mdp_allo.cpp @@ -0,0 +1,1790 @@ +/** + * @file mdp_allo.cpp + * Definitions for dynamic allocation of multidimensional pointer arrays + */ +/* + * $Revision$ + * $Date$ + */ +/* + * Copywrite 2004 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government + * retains certain rights in this software. + * See file License.txt for licensing information. + */ +#include + +#include +#include +#include +#include + +#include "mdp_allo.h" + +using namespace std; + +namespace mdp { + /* + * Allocate global storage for 2 debugging ints that are used in IO of + * error information. + */ +#ifdef MDP_MPDEBUGIO + int MDP_MP_Nprocs = 1; + int MDP_MP_myproc = 0; +#endif + /* + * Error Handling + * 7 print and exit + * 6 exit + * 5 print and create a divide by zero for stack trace analysis. + * 4 create a divide by zero for stack analysis trace + * 3 print a message and throw the bad_alloc exception. + * 2 throw the bad_alloc exception and be quite + * 1 print a message and return from package with the NULL pointer + * 0 Keep completely silent about the matter and return with + * a null pointer. + * + * -> Right now, the only way to change this option is to right here + */ + int MDP_ALLO_errorOption = 3; + + inline int MinI(const int &x, const int &y) { + return ( ( x < y ) ? x : y ); + } + inline int MaxI(const int &x, const int &y) { + return ( ( x > y ) ? x : y ); + } + + + const int MDP_ALLOC_INTERFACE_ERROR = -230346; + + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + static void mdp_alloc_eh(const char * const rname, const int bytes) + throw(std::bad_alloc, std::exception) + + /************************************************************************* + * + * mdp_alloc_eh: + * + * Error Handling + * 7 print and exit + * 6 exit + * 5 print and create a divide by zero for stack trace analysis. + * 4 create a divide by zero for stack trace analysis. + * 3 print a message and throw the bad_alloc exception. + * 2 throw the bad_alloc exception and be quite + * 1 print a message and return from package with the NULL pointer + * 0 Keep completely silent about the matter and return with + * a null pointer. + **************************************************************************/ + { + double cd = 0.0; + static char mesg[64]; + if (bytes == MDP_ALLOC_INTERFACE_ERROR) { +#ifdef MDP_MPDEBUGIO + sprintf(mesg,"MDP_ALLOC Interface ERROR P_%d: %s", MDP_MP_my_proc, + rname); +#else + sprintf(mesg,"MDP_ALLOC Interface ERROR: %s", rname); +#endif + } else { + sprintf(mesg,"%s ERROR: out of memory while mallocing %d bytes", + rname, bytes); + } + if (MDP_ALLO_errorOption % 2 == 1) { + fprintf(stderr, "\n%s", mesg); +#ifdef MDP_MPDEBUGIO + if (MDP_MP_Nprocs > 1) { + fprintf(stderr,": proc = %d\n", MDP_MP_myproc); + } else { + fprintf(stderr,"\n"); + } +#else + fprintf(stderr,"\n"); +#endif + } + fflush(stderr); + if (MDP_ALLO_errorOption == 2 || MDP_ALLO_errorOption == 3) { + throw std::bad_alloc(); + } + if (MDP_ALLO_errorOption == 4 || MDP_ALLO_errorOption == 5) cd = 1.0 / cd; + if (MDP_ALLO_errorOption > 5) { + std::exit(-1); + } + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + static void mdp_alloc_eh2(const char * const rname) + + /************************************************************************* + * + * mdp_alloc_eh2: + * + * Second Level Error Handling + * This routine is used at the second level. + * It will be called within the routine whenever another routine + * returns a NULL pointer. + * + **************************************************************************/ + { + if (MDP_ALLO_errorOption == 1 || + MDP_ALLO_errorOption == 3 || + MDP_ALLO_errorOption == 5 || + MDP_ALLO_errorOption == 7) { +#ifdef MDP_MPDEBUGIO + if (MDP_MP_Nprocs > 1) { + fprintf(stderr,": proc = %d, %s ERROR: returning with null pointer\n", + MDP_MP_myproc, rname); + } else { + fprintf(stderr,"%s ERROR: returning with null pointer", rname); + } +#else + fprintf(stderr,"%s ERROR: returning with null pointer", rname); +#endif + } + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + /****************************************************************************/ +#ifndef HAVE_ARRAY_ALLOC + /****************************************************************************/ + static double *smalloc(size_t n); + + /***************************************************************************** + * + * Dynamic Allocation of Multidimensional Arrays + *---------------------------------------------------------------------------- + * + * Example Usage: + * + * typedef struct + * { int bus1; + * int bus2; + * int dest; + * } POINT; + * + * POINT **points, corner; + * + * points = (POINT **) array_alloc (2, x, y, sizeof(POINT)); + * ^ ^ ^ + * | | | + * number of dimensions----------+ | | + * | | + * first dimension max-------------+ | + * | + * second dimension max----------------+ + * + * (points may be now be used as if it were declared + * POINT points[x][y]) + * + * This particular version is limited to dimensions of 3 or less. + * + * corner = points[2][3]; (refer to the structure as you would any array) + * + * free (points); (frees the entire structure in one fell swoop) + * + ****************************************************************************/ + /***************************************************************************** + * The following section is a commented section containing + * an example main code: + ****************************************************************************** + *double *array_alloc(); + *main() + *{ + * int ***temp; + * int *temp2; + * int i, j, k; + * int il, jl, kl; + * + * malloc_debug(2); + * il = 2; + * jl = 3; + * kl = 3; + * temp = (int ***) array_alloc(3,il,jl,kl,sizeof(int)); + * for (i=0; i 4) { + (void) fprintf(stderr, + "mdp_array_alloc ERROR: number of dimensions, %d, is > 4\n", + numdim); + return NULL; + } + + dim[0].index = va_arg(va, int); + + if (dim[0].index <= 0) { +#ifdef MDP_MEMDEBUG + (void) fprintf(stderr, "WARNING: mdp_array_alloc called with first " + "dimension <= 0, %d\n\twill return the nil pointer\n", + (int) (dim[0].index)); +#endif + return((double *) NULL); + } + + dim[0].total = dim[0].index; + dim[0].size = sizeof(void *); + dim[0].off = 0; + for (i = 1; i < numdim; i++) { + dim[i].index = va_arg(va, int); + if (dim[i].index <= 0) { + (void) fprintf(stderr, + "WARNING: mdp_array_alloc called with dimension %d <= 0, " + "%d\n", i+1, (int) (dim[i].index)); + fprintf(stderr, "\twill return the nil pointer\n"); + return((double *) NULL); + } + dim[i].total = dim[i-1].total * dim[i].index; + dim[i].size = sizeof(void *); + dim[i].off = dim[i-1].off + dim[i-1].total * dim[i-1].size; + } + + dim[numdim-1].size = va_arg(va, int); + va_end(va); + + /* + * Round up the last offset value so data is properly aligned. + */ + + dim[numdim-1].off = dim[numdim-1].size * + ((dim[numdim-1].off+dim[numdim-1].size-1)/dim[numdim-1].size); + + total = dim[numdim-1].off + dim[numdim-1].total * dim[numdim-1].size; + + dfield = (double *) smalloc((size_t) total); + field = (char *) dfield; + + for (i = 0; i < numdim - 1; i++) { + ptr = (char **) (field + dim[i].off); + data = (char *) (field + dim[i+1].off); + for (j = 0; j < dim[i].total; j++) { + ptr[j] = data + j * dim[i+1].size * dim[i+1].index; + } + } + + return dfield; + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + static double *smalloc(size_t n) + + /************************************************************************** + * smalloc: safe version of malloc + * + * This version of smalloc assigns space in even chunks of 8 bytes only + * + **************************************************************************/ + { +#ifdef MDP_MEMDEBUG + static int firsttime = 1; + FILE *file; +#endif + double *pntr; + if (n < 0) { + if (MDP_ALLO_errorOption == 7 || + MDP_ALLO_errorOption == 5 || MDP_ALLO_errorOption == 3 || + MDP_ALLO_errorOption == 1) { + (void) fprintf(stderr, "smalloc ERROR: Non-positive argument. (%d)\n", n); + return NULL; + } + } + else if (n == 0) pntr = NULL; + else { + n = ((n - 1) / 8); + n = (n + 1) * 8; + pntr = (double *) malloc((size_t) n); + } + if (pntr == NULL && n != 0) { + if (MDP_ALLO_errorOption == 7 || + MDP_ALLO_errorOption == 5 || MDP_ALLO_errorOption == 3 || + MDP_ALLO_errorOption == 1) { + fprintf(stderr, "smalloc : Out of space - number of bytes " + "requested = %d\n", n); + } + } +#ifdef MDP_MEMDEBUG + if (firsttime) { + firsttime = 0; + file = fopen("memops.txt", "w"); + } else { + file = fopen("memops.txt", "a"); + } + fprintf(file, "%x %d malloc\n", pntr, n); + fclose(file); +#endif + return pntr; + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_safe_free (void **ptr) + + /************************************************************************* + * + * mdp_safe_free(): + * + * This version of free calls the system's free function + * with maximum error checking. It also doesn't call free if ptr is + * the NULL pointer already. + * It will then set the freed pointer to NULL. Thus, a convention may + * be established wherein all pointers that can be malloced can be + * set to NULL if they are not malloced. + **************************************************************************/ + { +#ifdef MDP_MEMDEBUG + FILE *file; +#endif + if (ptr == NULL) { + mdp_alloc_eh("mdp_safe_free: handle is NULL", MDP_ALLOC_INTERFACE_ERROR); + } + if (*ptr != NULL) { +#ifdef MDP_MEMDEBUG + file = fopen("memops.txt", "a"); + Fprintf(file, "%x free\n", *ptr); + fflush(file); + if ( (int) *ptr == 0x00000001) { + Fprintf(stderr, "FOUND IT!\n"); + exit(-1); + } + fclose(file); +#endif + free(*ptr); + /* + * Set the value of ptr to NULL, so that further references + * to it will be flagged. + */ + *ptr = NULL; + } + } + /****************************************************************************/ +#endif + /***************************************************************************** + * + * Wrapper Functions + * -------------------- + * + * The function definitions below are wrappers around array_alloc for + * common operations. The following principles are followed: + * + * Argument dimensions le 0 are increased to 1 before calling array_alloc. + * Thus, something is always malloced during a call. The reason for this is + * that it minimizes the number of special cases in the calling program. + * + * A pointer to something else other than NULL indicates that that pointer + * has been previously malloced. Thus, it can be freed. Note, after a free + * operation, this package always sets the pointer to NULL before returning. + * + * "safe_alloc" routines try to free the pointer if nonNULL, before calling + * the base alloc_int_#() routines. + * + * The regular routines initialize the malloced space, unless told to not + * do so. + * + * The function memcpy and memset are used where possible to increase speed. + * + * Naming Convention: + * + * The names of functions have the following format: + * + * mdp_[safe]_[operation]_[underlyingDataType]_[Dimension]() + * + * safe -> optional name added to the function name. These + * functions differ in that a handle to the pointer is passed + * to the function instead of just the pointer being + * returned. A check to see whether the pointer has been + * previously malloced is made, before a new allocation + * is made. If previously malloced, the pointer is freed + * first. + * + * operation -> name of the operation, such as alloc, realloc, + * init, or copy. + * + * underlyingDataType -> dble, int, ptr, or char + * + * dimension -> 1 or 2. For dimensions greater than 1, the data + * is laid out in F77 or blas-compatible format + * where data is contiguous wrt rows being the + * inner loop. + * + *****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + int *mdp_alloc_int_1(int nvalues, const int val) + + /************************************************************************** + * + * mdp_alloc_int_1: + * + * Allocate and initialize a one dimensional array of integers. + * + * Input + * ------- + * nvalues = Length of the array + * val = intialization value + * Return + * ------ + * Pointer to the intialized integer array + * Failures are indicated by returning the NULL pointer. + **************************************************************************/ + { + int *array; + if (nvalues <= 0) nvalues = 1; + array= (int *) mdp_array_alloc(1, nvalues, sizeof(int)); + if (array != NULL) { + if (val != MDP_INT_NOINIT) { + if (val == 0) { + (void) memset(array, 0, sizeof(int)*nvalues); + } else { + for (int i = 0; i < nvalues; i++) array[i] = val; + } + } + } else { + mdp_alloc_eh("mdp_alloc_int_1", nvalues * sizeof(int)); + } + return array; + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_safe_alloc_int_1(int **array_hdl, int nvalues, const int val) + + /************************************************************************* + * + * mdp_safe_alloc_int_1: + * + * Allocates and/or initializse a one dimensional array of integers. + * + * Input + * ------- + * *array_hdl = Previous value of pointer. If non-NULL will try + * to free the memory at this address. + * nvalues = Length of the array + * val = intialization value + * Output + * ------ + * *array_hdl = This value is initialized to the correct address + * of the array. + * A NULL value in the position indicates an error. + **************************************************************************/ + { + if (array_hdl == NULL) { + mdp_alloc_eh("mdp_safe_alloc_int_1: handle is NULL", + MDP_ALLOC_INTERFACE_ERROR); + return; + } + if (*array_hdl != NULL) mdp_safe_free((void **) array_hdl); + *array_hdl = mdp_alloc_int_1(nvalues, val); + if (*array_hdl == NULL) mdp_alloc_eh2("mdp_safe_alloc_int_1"); + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void + mdp_realloc_int_1(int **array_hdl, int new_length, int old_length, + const int defval) + + /************************************************************************* + * + * mdp_realloc_int_1_(array_hdl, new_num_ptrs, old_num_ptrs); + * + * Reallocates a one dimensional array of ints. + * This routine always allocates space for at least one int. + * Calls the smalloc() routine to ensure that all malloc + * calls go through one location. This routine will then copy + * the pertinent information from the old array to the + * new array. + * + * Input + * ------- + * array_hdl = Pointer to the global variable that + * holds the old and (eventually new) + * address of the array of integers to be reallocated + * new_length = Length of the array + * old_length = Length of the old array + **************************************************************************/ + { + if (new_length == old_length) return; + if (new_length <= 0) { +#ifdef MDP_MPDEBUGIO + fprintf(stderr, + "Warning: mdp_realloc_int_1 P_%d: called with n = %d\n", + MDP_MP_myproc, new_length); +#else + fprintf(stderr, + "Warning: mdp_realloc_int_1: called with n = %d\n", + new_length); +#endif + new_length = 1; + } + if (old_length < 0) old_length = 0; + if (new_length == old_length) return; + size_t bytenum = new_length * sizeof(int); + int *array = (int *) smalloc(bytenum); + if (array != NULL) { + if (*array_hdl) { + if (old_length > 0) bytenum = sizeof(int) * old_length; + else bytenum = 0; + if (new_length < old_length) bytenum = sizeof(int) * new_length; + if (bytenum > 0) { + (void) memcpy((void *) array, (const void *) *array_hdl, bytenum); + } + mdp_safe_free((void **) array_hdl); + } else { + old_length = 0; + } + *array_hdl = array; + if ((defval != MDP_INT_NOINIT) && (new_length > old_length)) { + if (defval == 0) { + bytenum = sizeof(int) * (new_length - old_length); + (void) memset((void *)(array+old_length), 0, bytenum); + } else { + for (int i = old_length; i < new_length; i++) { + array[i] = defval; + } + } + } + } else { + mdp_alloc_eh("mdp_realloc_int_1", static_cast(bytenum)); + } + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + int **mdp_alloc_int_2(int ndim1, int ndim2, const int val) + + /************************************************************************* + * + * mdp_alloc_int_2: + * + * Allocate and initialize a two dimensional array of ints. + * + * Input + * ------- + * ndim1 = Length of the first dimension of the array + * ndim2 = Length of the second dimension of the array + * val = intialization value + * Return + * ------ + * Pointer to the intialized integer array + * Failures are indicated by returning the NULL pointer. + **************************************************************************/ + { + int i; + int **array, *dptr; + if (ndim1 <= 0) ndim1 = 1; + if (ndim2 <= 0) ndim2 = 1; + array = (int **) mdp_array_alloc(2, ndim1, ndim2, sizeof(int)); + if (array != NULL) { + if (val != MDP_INT_NOINIT) { + if (val == 0) { + (void) memset((void *) array[0], 0, ndim1 * ndim2 * sizeof(int)); + } else { + dptr = &(array[0][0]); + for (i = 0; i < ndim1 * ndim2; i++) dptr[i] = val; + } + } + } else { + mdp_alloc_eh("mdp_alloc_int_2", + sizeof(int) * ndim1 * ndim2 + + ndim1 * sizeof(void *)); + } + return array; + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + double *mdp_alloc_dbl_1(int nvalues, const double val) + + /************************************************************************* + * + * mdp_alloc_dbl_1: + * + * Allocate and initialize a one dimensional array of doubles. + * + * Input + * ------- + * nvalues = Length of the array + * val = intialization value + * Return + * ------ + * Pointer to the intialized array of doubles + * Failures are indicated by returning the NULL pointer. + **************************************************************************/ + { + int i; + double *array; + if (nvalues <= 0) nvalues = 1; + array = (double *) mdp_array_alloc(1, nvalues, sizeof(double)); + if (array != NULL) { + if (val != MDP_DBL_NOINIT) { + if (val == 0.0) { + (void) memset((void *) array, 0, nvalues * sizeof(double)); + } else { + for (i = 0; i < nvalues; i++) array[i] = val; + } + } + } else { + mdp_alloc_eh("mdp_alloc_dbl_1", nvalues * sizeof(double)); + } + return array; + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_safe_alloc_dbl_1(double **array_hdl, int nvalues, const double val) + + /************************************************************************* + * + * mdp_safe_alloc_dbl_1: + * + * Allocates and/or initializse a one dimensional array of doubles. + * + * Input + * ------- + * *array_hdl = Previous value of pointer. If non-NULL will try + * to free the memory at this address. + * nvalues = Length of the array + * val = intialization value + * Output + * ------ + * *array_hdl = This value is initialized to the correct address + * of the array. + * A NULL value in the position indicates an error. + **************************************************************************/ + { + if (array_hdl == NULL) { + mdp_alloc_eh("mdp_safe_alloc_dbl_1: handle is NULL", + MDP_ALLOC_INTERFACE_ERROR); + return; + } + if (*array_hdl != NULL) mdp_safe_free((void **) array_hdl); + *array_hdl = mdp_alloc_dbl_1(nvalues, val); + if (*array_hdl == NULL) mdp_alloc_eh2("mdp_safe_alloc_dbl_1"); + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_realloc_dbl_1(double **array_hdl, int new_length, + int old_length, const double defval) + + /************************************************************************* + * + * mdp_realloc_dbl_1_(array_hdl, new_num_ptrs, old_num_ptrs); + * + * Reallocates a one dimensional array of doubles. + * This routine always allocates space for at least one dbl. + * Calls the smalloc() routine to ensure that all malloc + * calls go through one location. This routine will then copy + * the pertinent information from the old array to the + * new array. + * + * Input + * ------- + * array_hdl = Pointer to the global variable that + * holds the old and (eventually new) + * address of the array of doubles to be reallocated + * new_length = Length of the array + * old_length = Length of the old array + **************************************************************************/ + { + if (new_length == old_length) return; + if (new_length <= 0) { +#ifdef MDP_MPDEBUGIO + fprintf(stderr, "Warning: mdp_realloc_dbl_1 P_%d: called with n = %d\n", + MDP_MP_myproc, new_length); +#else + fprintf(stderr, "Warning: mdp_realloc_dbl_1: called with n = %d\n", + new_length); +#endif + new_length = 1; + } + if (old_length < 0) old_length = 0; + if (new_length == old_length) return; + size_t bytenum = new_length * sizeof(double); + double *array = (double *) smalloc(bytenum); + if (array != NULL) { + if (*array_hdl) { + if (old_length > 0) bytenum = sizeof(double) * old_length; + else bytenum = 0; + if (new_length < old_length) bytenum = sizeof(double) * new_length; + (void) memcpy((void *) array, (const void *) *array_hdl, bytenum); + mdp_safe_free((void **) array_hdl); + } else { + old_length = 0; + } + *array_hdl = array; + if ((defval != MDP_DBL_NOINIT) && (new_length > old_length)) { + if (defval == 0) { + bytenum = sizeof(double) * (new_length - old_length); + (void) memset((void *)(array+old_length), 0, bytenum); + } else { + for (int i = old_length; i < new_length; i++) { + array[i] = defval; + } + } + } + } else { + mdp_alloc_eh("mdp_realloc_dbl_1", static_cast(bytenum)); + } + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + double **mdp_alloc_dbl_2(int ndim1, int ndim2, const double val) + + /************************************************************************* + * + * mdp_alloc_dbl_2: + * + * Allocate a two dimensional array of doubles. The array is in + * fortran order and can be accessed via the following form: + * + * dblArray[ndim1][ndim2] + * + * Note, ndim2 is the inner dimension. i.e., the array is + * in column ordering. + * + * Input + * ------- + * ndim1 = Length of the first dimension of the array + * ndim2 = Length of the second dimension of the array + * val = intialization value + * Return + * ------ + * Pointer to the intialized integer array + * Failures are indicated by returning the NULL pointer. + **************************************************************************/ + { + int i; + double **array, *dptr; + if (ndim1 <= 0) ndim1 = 1; + if (ndim2 <= 0) ndim2 = 1; + array = (double **) mdp_array_alloc(2, ndim1, ndim2, sizeof(double)); + if (array != NULL) { + if (val != MDP_DBL_NOINIT) { + if (val == 0.0) { + (void) memset((void *) array[0], 0, ndim1*ndim2 * sizeof(double)); + } else { + dptr = &(array[0][0]); + for (i = 0; i < ndim1*ndim2; i++) dptr[i] = val; + } + } + } else { + mdp_alloc_eh("mdp_alloc_dbl_2", + sizeof(double) * ndim1 * ndim2 + + ndim1 * sizeof(void *)); + } + return array; + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + char *mdp_alloc_char_1(int nvalues, const char val) + + /************************************************************************* + * + * mdp_alloc_char_1: + * + * Allocate and initialize a one dimensional array of characters. + * + * Input + * ------- + * nvalues = Length of the array + * val = intialization value + * Return + * ------ + * Pointer to the intialized character array + * Failures are indicated by returning the NULL pointer. + **************************************************************************/ + { + int i; + char *array; + if (nvalues <= 0) nvalues = 1; + array = (char *) mdp_array_alloc(1, nvalues, sizeof(char)); + if (array != NULL) { + if (val == '\0') { + (void) memset((void *)array, 0, sizeof(char)*nvalues); + } else { + for (i = 0; i < nvalues; i++) array[i] = val; + } + } else { + mdp_alloc_eh("mdp_alloc_char_1", nvalues * sizeof(char)); + } + return array; + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_safe_alloc_char_1(char **array_hdl, int nvalues, const char val) + + /************************************************************************* + * + * mdp_safe_alloc_char_1: + * + * Allocate and initialize a one dimensional array of characters, + * deallocating the space before hand. + * + * This routine will free any old memory that was located at that + * position, before it will allocate a new vector. + * Allocates and/or initializse a one dimensional array of characters. + * + * Input + * ------- + * array_hdl = Previous value of pointer. If non-NULL will try + * to free the memory at this address. + * nvalues = Length of the array + * val = intialization value + * Output + * ------ + * *array_hdl = This value is initialized to the correct address + * of the array. + * A NULL value in the position indicates an error. + **************************************************************************/ + { + if (array_hdl == NULL) { + mdp_alloc_eh("mdp_safe_alloc_char_1: handle is NULL", + MDP_ALLOC_INTERFACE_ERROR); + return; + } + if (*array_hdl != NULL) mdp_safe_free((void **) array_hdl); + *array_hdl = mdp_alloc_char_1(nvalues, val); + if (*array_hdl == NULL) mdp_alloc_eh2("mdp_safe_alloc_char_1"); + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + + + void mdp_safe_alloc_dbl_2(double ***array_hdl, int ndim1, int ndim2, + const double val) + + /************************************************************************* + * + * mdp_safe_alloc_dbl_2: + * + * Allocate and initialize a two dimensional array of doubles. + * + * Input + * ------- + * *array_hdl = Previous value of pointer. If non-NULL will try + * to free the memory at this address. + * ndim1 = Length of the array + * ndim2 = Length of inner loop of the array + * val = intialization value + * Return + * ------ + * *array_hdl = This value is initialized to the correct address + * of the array. + * A NULL value in the position indicates an error. + **************************************************************************/ + { + if (array_hdl == NULL) { + mdp_alloc_eh("mdp_safe_alloc_dbl_2: handle is NULL", + MDP_ALLOC_INTERFACE_ERROR); + return; + } + if (*array_hdl != NULL) mdp_safe_free((void **) array_hdl); + *array_hdl = mdp_alloc_dbl_2(ndim1, ndim2, val); + if (*array_hdl == NULL) mdp_alloc_eh2("mdp_safe_alloc_dbl_2"); + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_realloc_dbl_2(double ***array_hdl, int ndim1, int ndim2, + int ndim1Old, int ndim2Old, const double val) + + /************************************************************************* + * + * mdp_realloc_dbl_2: + * + * mdp_realloc_dbl_2(array_hdl, int ndim1, int ndim2, + * int ndim1Old, int ndim2Old, const double val) + * + * Reallocates a two dimensional array of doubles. + * This routine will then copy the pertinent information from + * the old array to the new array. + * + * If both old dimensions are set to zero or less, then this routine + * will free the old memory before mallocing the new memory. This may + * be a benefit for extremely large mallocs. + * In all other cases, the new and the old malloced arrays will + * exist for a short time together. + * + * Input + * ------- + * array_hdl = Pointer to the global variable that + * holds the old and (eventually new) + * address of the array of doubles to be reallocated + * ndim1 = First dimension of the new array + * ndim2 = Second dimension of the new array + * ndim1Old = First dimension of the old array + * ndim2Old = Second dimension of the old array + * val = Default fill value. + **************************************************************************/ + { + if (ndim1 <= 0) ndim1 = 1; + if (ndim2 <= 0) ndim2 = 1; + ndim1Old = MaxI(ndim1Old, 0); + ndim2Old = MaxI(ndim2Old, 0); + /* + * One way to do it, if old information isn't needed. In this algorithm + * the arrays are never malloced at the same time. + */ + if ((*array_hdl == NULL) || (ndim1Old <= 0 && ndim2Old <= 0)) { + mdp_safe_free((void **) array_hdl); + *array_hdl = mdp_alloc_dbl_2(ndim1, ndim2, val); + if (*array_hdl == NULL) mdp_alloc_eh2("mdp_realloc_dbl_2"); + } + /* + * Other way to do when old information is available and needed + */ + else { + double **array_old = *array_hdl; + *array_hdl = (double **) mdp_array_alloc(2, ndim1, ndim2, sizeof(double)); + if (*array_hdl == NULL) { + mdp_alloc_eh2("mdp_realloc_dbl_2"); + } else { + /* + * Now, let's initialize the arrays + */ + int ndim1Min = MinI(ndim1, ndim1Old); + int ndim2Min = MinI(ndim2, ndim2Old); + double **array_new = *array_hdl; + /* + * When the second dimensions are equal, we can copy blocks + * using the very efficient bit moving kernels. + */ + if (ndim2 == ndim2Old) { + size_t sz = ndim1Min * ndim2 * sizeof(double); + (void) memcpy((void *) array_new[0], (const void *) array_old[0], sz); + } + /* + * If the second dimensions aren't equal, then we have to + * break up the bit operations even more + */ + else { + size_t sz = ndim2Min * sizeof(double); + size_t sz2 = (ndim2 - ndim2Min) * sizeof(double); + for (int i = 0; i < ndim1Min; i++) { + (void) memcpy((void *) array_new[i], + (const void *) array_old[i], sz); + if (ndim2 > ndim2Min && val != MDP_DBL_NOINIT) { + if (val == 0.0) { + (void) memset((void *) (array_new[i] + ndim2Min), 0, sz2); + } else { + double *dptr = array_new[i]; + for (int j = ndim2Min; j < ndim2; j++) dptr[j] = val; + } + } + } + } + /* + * finish up initializing the rest of the array + */ + if (ndim1 > ndim1Min && val != MDP_DBL_NOINIT) { + if (val == 0.0) { + size_t sz = (ndim1 - ndim1Min) * ndim2 * sizeof(double); + (void) memset((void *) array_new[ndim1Min], 0, sz); + } else { + double *dptr = array_new[ndim1Min]; + int num = (ndim1 - ndim1Min) * ndim2; + for (int i = 0; i < num; i++) { + dptr[i] = val; + } + } + } + /* + * Free the old array + */ + mdp_safe_free((void **) &array_old); + } + } + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + char **mdp_alloc_VecFixedStrings(int numStrings, int lenString) + + /************************************************************************* + * + * mdp_alloc_VecFixedStrings: + * + * Allocate and initialize a vector of fixed-length + * strings. Each string is initialized to the NULL string. + * + * Input + * ------- + * numStrings = Number of strings + * lenString = Length of each string including the trailing null + * character + * Return + * ------ + * This value is initialized to the correct address of the array. + * A NULL value in the position indicates an error. + **************************************************************************/ + { + int i; + char **array; + if (numStrings <= 0) numStrings = 1; + if (lenString <= 0) lenString = 1; + array = (char **) mdp_array_alloc(2, numStrings, lenString, sizeof(char)); + if (array != NULL) { + for (i = 0; i < numStrings; i++) { + array[i][0] = '\0'; + array[i][lenString - 1] = '\0'; + } + } else { + mdp_alloc_eh("mdp_alloc_VecFixedStrings", + sizeof(char) * numStrings * lenString + + numStrings * sizeof(void *)); + } + return array; + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_realloc_VecFixedStrings(char ***array_hdl, int numStrings, + int numOldStrings, int lenString) + + /************************************************************************* + * + * mdp_realloc_VecFixedStrings: + * + * Reallocate and initialize a vector of fixed-length + * strings. Each new string is initialized to the NULL string. + * old strings are copied. + * + * Input + * ------- + * ***array_hdl = The pointer to the char ** location holding + * the data to be reallocated. + * numStrings = Number of strings + * numOldStrings = Number of old strings + * lenString = Length of each string including the trailing null + * character + **************************************************************************/ + { + int i; + char **array, **ao; + if (numStrings <= 0) numStrings = 1; + if (numStrings == numOldStrings) return; + if (lenString <= 0) lenString = 1; + array = (char **) mdp_array_alloc(2, numStrings, lenString, sizeof(char)); + if (array != NULL) { + int len = MinI(numStrings, numOldStrings); + ao = *array_hdl; + if (ao) { + for (i = 0; i < len; i++) { + strncpy(array[i], ao[i], lenString); + } + } + if (numStrings > numOldStrings) { + for (i = numOldStrings; i < numStrings; i++) { + array[i][0] = '\0'; + array[i][lenString - 1] = '\0'; + } + } + mdp_safe_free((void **) array_hdl); + *array_hdl = array; + + } else { + mdp_alloc_eh("mdp_realloc_VecFixedStrings", + sizeof(char) * numStrings * lenString + + numStrings * sizeof(void *)); + } + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_safe_alloc_VecFixedStrings(char ***array_hdl, + int numStrings, int lenString) + + /************************************************************************* + * + * mdp_safe_alloc_VecFixedStrings + * + * Allocate and initialize an array of strings of fixed length + * + * Input + * ------- + * *array_hdl = Previous value of pointer. If non-NULL will try + * to free the memory at this address. + * numStrings = Number of strings + * lenString = Length of each string including the trailing null + * character + * Output + * ------ + * *array_hdl = This value is initialized to the correct address + * of the array. + * A NULL value in the position indicates an error. + **************************************************************************/ + { + if (array_hdl == NULL) { + mdp_alloc_eh("mdp_safe_alloc_VecFixedStrings: handle is NULL", + MDP_ALLOC_INTERFACE_ERROR); + return; + } + if (*array_hdl != NULL) mdp_safe_free((void **) array_hdl); + *array_hdl = mdp_alloc_VecFixedStrings(numStrings, lenString); + if (*array_hdl == NULL) + mdp_alloc_eh2("mdp_safe_alloc_VecFixedStrings"); + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void **mdp_alloc_ptr_1(int numPointers) + + /************************************************************************* + * + * mdp_alloc_ptr_1: + * + * Allocate and initialize a vector of pointers + * of type pointer to void. All pointers are initialized to the NULL + * value. + * + * Input + * ------- + * numPointers = Number of pointers + * Return + * ------ + * This value is initialized to the correct address of the vector. + * A NULL value in the position indicates an error. + **************************************************************************/ + { + int i; + void **array; + if (numPointers <= 0) numPointers = 1; + array = (void **) mdp_array_alloc(1, numPointers, sizeof(void *)); + if (array != NULL) { + for (i = 0; i < numPointers; i++) { + array[i] = NULL; + } + } else { + mdp_alloc_eh("mdp_alloc_ptr_1", + sizeof(void *) * numPointers); + } + return array; + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_safe_alloc_ptr_1(void ***array_hdl, int numPointers) + + /************************************************************************** + * + * mdp_safe_alloc_ptr_1: + * + * Allocate and initialize a vector of pointers + * of type pointer to void. All pointers are initialized to the NULL + * value. + * + * Input + * ------- + * *array_hdl = Previous value of pointer. If non-NULL will try + * to free the memory at this address. + * numPointers = Number of pointers + * Output + * ------ + * *array_hdl = This value is initialized to the correct address + * of the array. + * A NULL value in the position indicates an error. + **************************************************************************/ + { + if (array_hdl == NULL) { + mdp_alloc_eh("mdp_safe_alloc_ptr_1: handle is NULL", + MDP_ALLOC_INTERFACE_ERROR); + return; + } + if (*array_hdl != NULL) mdp_safe_free((void **) array_hdl); + *array_hdl = mdp_alloc_ptr_1(numPointers); + if (*array_hdl == NULL) mdp_alloc_eh2("mdp_safe_alloc_ptr_1"); + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_realloc_ptr_1(void ***array_hdl, int numLen, int numOldLen) + + /************************************************************************* + * + * mdp_realloc__ptr_1: + * + * Reallocate and initialize a vector of pointers + * Each new pointer is initialized to NULL. + * old Pointers are copied. + * + * Input + * ------- + * ***array_hdl = The pointer to the char ** location holding + * the data to be reallocated. + * numLen = Number of strings + * numOldLen = Number of old strings + **************************************************************************/ + { + if (array_hdl == NULL) { + mdp_alloc_eh("mdp_safe_alloc_ptr_1: handle is NULL", + MDP_ALLOC_INTERFACE_ERROR); + return; + } + if (numLen <= 0) numLen = 1; + if (numOldLen < 0) numOldLen = 0; + if (numLen == numOldLen) return; + size_t bytenum = sizeof(void *) * numLen; + void **array = (void **) smalloc(bytenum); + if (array != NULL) { + int len = MinI(numLen, numOldLen); + if (*array_hdl) { + void **ao = *array_hdl; + for (int i = 0; i < len; i++) array[i] = ao[i]; + } else { + numOldLen = 0; + } + if (numLen > numOldLen) { + bytenum = sizeof(void *) * (numLen - numOldLen); + (void) memset((void *) (array + numOldLen), 0, bytenum); + } + mdp_safe_free((void **) array_hdl); + *array_hdl = array; + } else { + mdp_alloc_eh("mdp_realloc_ptr_1", sizeof(void *) * numLen); + } + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_copy_VecFixedStrings(char ** const copyTo, + const char ** const copyFrom, + int numStrings, size_t maxLenString) + + /************************************************************************* + * + * mdp_copy_VecFixedStrings + * + * Copies an array of string vectors. + * + * Input + * ------- + * copyFrom = vector of C strings. It should be null terminated + * numStrings = number of strings + * maxLenString = maximum of the size of the string arrays, + * copyTo and copyFrom. This is used as the + * argument to strncpy() function. + * + * Output + * copyTo = vector of strings + * + **************************************************************************/ + { + if (maxLenString > 0) { + char *dTo; + const char *dFrom; + for (int i = 0; i < numStrings; i++) { + dTo = copyTo[i]; + dFrom = copyFrom[i]; + if (!dTo) { + mdp_alloc_eh2("mdp_copy_VecFixedStrings"); + } + if (!dFrom) { + mdp_alloc_eh2("mdp_copy_VecFixedStrings"); + } + (void) strncpy(dTo, dFrom, maxLenString); + dTo[maxLenString-1] = '\0'; + } + } + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + char *mdp_copy_string(const char * const copyFrom) + + /************************************************************************* + * + * mdp_copy_string: + * + * Allocates space for and copies a string + * + * Input + * ------- + * copyFrom = null terminated string. If NULL is supplied, then + * nothing is malloced and a NULL value is returned. + * Return + * ------ + * This value is initialized to the correct address of the array. + * A NULL value in the position either indicates an error, or + * that the original pointer to the string was NULL. + **************************************************************************/ + { + char *cptr; + if (copyFrom == NULL) return NULL; + cptr = (char *) mdp_array_alloc(1, strlen(copyFrom) + 1, sizeof(char)); + if (cptr != NULL) { + (void) strcpy(cptr, copyFrom); + } else { + mdp_alloc_eh("mdp_copy_string", + static_cast(sizeof(char) * (strlen(copyFrom) + 1))); + } + return cptr; + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_safe_copy_string(char **string_hdl, const char *copyFrom) + + /************************************************************************* + * + * mdp_safe_copy_string: + * + * Allocates space for and copies a string + * + * Input + * ------- + * *string_hdl = Previous value of pointer. If non-NULL will try + * to free the memory at this address. + * *copyFrom = String to be copied + * Output + * ------ + * *string_hdl = Pointer to the copied string + * A NULL value in the position indicates an error. + **************************************************************************/ + { + if (string_hdl == NULL) { + mdp_alloc_eh("mdp_safe_copy_string: string_hdl is NULL", + MDP_ALLOC_INTERFACE_ERROR); + return; + } + if (*string_hdl != NULL) mdp_safe_free((void **) string_hdl); + if (copyFrom == NULL) { + *string_hdl = NULL; + return; + } + *string_hdl = mdp_copy_string(copyFrom); + if (*string_hdl == NULL) { + mdp_alloc_eh2("mdp_safe_copy_string"); + } + return; + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_copy_dbl_1(double * const copyTo, + const double * const copyFrom, const int len) + + /************************************************************************** + * + * mdp_copy_dbl_1: + * + * Copies one Double vector into another double vector + * + * Input + * ------------- + * *copyFrom = Vector of values to be copied + * len = Length of the vector + * + * Output + * ------------ + * *copyTo = Vector of values to receive the copy + * + **************************************************************************/ + { + if (len > 0) { + (void) memcpy((void *)copyTo, (const void *)copyFrom, len * sizeof(double)); + } + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_copy_dbl_2(double ** const copyTo, + const double ** const copyFrom, const int len1, + const int len2) + + /************************************************************************** + * + * mdp_copy_dbl_2: + * + * Copies one double array into another double array + * + * Input + * ------------- + * *copyFrom = Vector of values to be copied + * len1 = Length of the first array + * len2 = length of the second array + * + * Output + * ------------ + * *copyTo = array of values to receive the copy + * + **************************************************************************/ + { + if (len1 > 0 && len2 > 0) { + size_t bytelen = len1 * len2 * sizeof(double); + const double * const dFrom = copyFrom[0]; + double * const dTo = copyTo[0]; + (void) memcpy((void *)dTo, (const void *)dFrom, bytelen); + } + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_copy_int_1(int *const copyTo, + const int * const copyFrom, int len) + + /************************************************************************** + * + * mdp_copy_int_1: + * + * Copies one int vector into int double vector + * + * Input + * ------------- + * *copyFrom = Vector of values to be copied + * len = Length of the vector + * + * Output + * ------------ + * *copyTo = Vector of values to receive the copy + * + **************************************************************************/ + { + if (len > 0) { + size_t bytelen = len * sizeof(int); + (void) memcpy((void *)copyTo, (const void *)copyFrom, bytelen); + } + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_copy_int_2(int **const copyTo, + const int ** const copyFrom, const int len1, + const int len2) + + /************************************************************************** + * + * mdp_copy_int_2: + * + * Copies one 2D int array into another 2D int array + * + * Input + * ------------- + * *copyFrom = Vector of values to be copied + * len1 = Length of the first array + * len2 = Length of the second array + * + * Output + * ------------ + * *copyTo = array of values to receive the copy + * + **************************************************************************/ + { + if (len1 > 0 && len2 > 0) { + size_t bytelen = len1 * len2 * sizeof(int); + const int * const dFrom = copyFrom[0]; + int * const dTo = copyTo[0]; + (void) memcpy((void *)dTo, (const void *)dFrom, bytelen); + } + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_copy_ptr_1(void *const copyTo, + const void * const copyFrom, int len) + + /************************************************************************** + * + * mdp_copy_ptr_1: + * + * Copies one ptr vector into another ptr vector + * + * Input + * ------------- + * *copyFrom = Vector of ptr values to be copied + * len = Length of the vector + * + * Output + * ------------ + * *copyTo = Vector of values to receive the copy + * + **************************************************************************/ + { + if (len > 0) { + size_t bytelen = len * sizeof(void *); + (void) memcpy((void *)copyTo, (const void *)copyFrom, bytelen); + } + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void **mdp_dupl_ptr_1(const void * const copyFrom, int len) + + /************************************************************************** + * + * mdp_dupl_ptr_1: + * + * duplicates one ptr vector into another ptr vector + * + * Input + * ------------- + * *copyFrom = Vector of ptr values to be copied + * len = Length of the vector + * + * Output + * ------------ + * *copyTo = Vector of values to receive the copy + * + **************************************************************************/ + { + if (len > 0) { + void **array = mdp_alloc_ptr_1(len); + if (copyFrom) { + size_t bytelen = len * sizeof(void *); + (void) memcpy((void *)array, (const void *)copyFrom, bytelen); + } + return array; + } + return 0; + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_init_dbl_1(double * const v, const double value, const int len) + + /************************************************************************** + * + * mdp_init_dbl_1: + * + * Assigns a single value to a double vector + * + * Input + * ------------- + * v = Vector of values to be assigned + * value = value to assign with + * len = Length of the vector + * + **************************************************************************/ + { + if (len > 0) { + if (value == 0.0) { + (void) memset((void *)v, 0, len * sizeof(double)); + } else { + int m = len % 7; + if (m != 0) { + for (int i = 0; i < m; m++) { + v[i] = value; + } + if (len < 7) return; + } + for (int i = m; i < len; i += 7) { + v[i ] = value; + v[i+1] = value; + v[i+2] = value; + v[i+3] = value; + v[i+4] = value; + v[i+5] = value; + v[i+6] = value; + } + } + } + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_zero_dbl_1(double * const v, const int len) + + /************************************************************************** + * + * mdp_zero_dbl_1: + * + * Zeroes out a double vector (special form of mdp_allo_dbl_1()) + * + * Input + * ------------- + * v = Vector of values to be set to zero + * len = Length of the vector + **************************************************************************/ + { + if (len > 0) { + (void) memset((void *)v, 0, len * sizeof(double)); + } + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_init_dbl_2(double ** const v, double value, int len1, int len2) + + /************************************************************************** + * + * mdp_init_dbl_2: + * + * Assigns a single value to a double matrix. Contiguous data for the + * matrix is assumed. + * + * Input + * ------------- + * v = matrix of values to be assigned + * value = value to assign with + * len = Length of the vector + * + **************************************************************************/ + { + int len = len1 * len2; + if (len > 0 && len1 > 0 && v) { + double * const dstart = v[0]; + if (value == 0.0) { + size_t bytelen = len * sizeof(double); + (void) memset((void *)dstart, 0, bytelen); + } else { + int m = len % 7; + if (m != 0) { + for (int i = 0; i < m; m++) { + dstart[i] = value; + } + if (len < 7) return; + } + for (int i = m; i < len; i += 7) { + dstart[i ] = value; + dstart[i+1] = value; + dstart[i+2] = value; + dstart[i+3] = value; + dstart[i+4] = value; + dstart[i+5] = value; + dstart[i+6] = value; + } + } + } + } + /****************************************************************************/ + /****************************************************************************/ + /****************************************************************************/ + + void mdp_init_int_1(int * const v, const int value, const int len) + + /************************************************************************** + * + * mdp_init_int_1: + * + * Assigns a single value to an int vector + * + * Input + * ------------- + * v = Vector of values to be assigned + * value = value to assign with + * len = Length of the vector + * + **************************************************************************/ + { + if (len > 0) { + if (value == 0) { + size_t bytelen = len * sizeof(int); + (void) memset((void *)v, 0, bytelen); + } else { + int m = len % 7; + if (m != 0) { + for (int i = 0; i < m; m++) { + v[i] = value; + } + if (len < 7) return; + } + for (int i = m; i < len; i += 7) { + v[i ] = value; + v[i+1] = value; + v[i+2] = value; + v[i+3] = value; + v[i+4] = value; + v[i+5] = value; + v[i+6] = value; + } + } + } + } +} +/****************************************************************************/ +/* END of mdp_allo.cpp */ +/****************************************************************************/ diff --git a/Cantera/src/base/mdp_allo.h b/Cantera/src/base/mdp_allo.h new file mode 100644 index 000000000..7dc744407 --- /dev/null +++ b/Cantera/src/base/mdp_allo.h @@ -0,0 +1,739 @@ +/** + * @file mdp_allo.h + * Declarations for Multi Dimensional Pointer (mdp) malloc routines, which + * allow for dimensioning of arbitrarily dimensioned pointer arrays using + * one call. + */ +/* + * $Revision$ + * $Date$ + */ +/* + * Copywrite 2004 Sandia Corporation. Under the terms of Contract + * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government + * retains certain rights in this software. + * See file License.txt for licensing information. + */ + +#ifndef MDP_ALLO_H +#define MDP_ALLO_H + +#include + +/* + * Include the header here in order to pick up size_t definition + */ +#include + +/** + * The mdp routines are extremely lightweight and fast fortran compatibile + * malloc routines for allocating multiple dimensioned arrays of doubles + * ints, char, and pointers using a single call. These routines don't + * use the std C+ lib routines. + * + * All calls are essentially wrappers around the routine mdp_alloc_array() + * which allocates multidimensioned arrays. The arrays contain room for + * the data and the pointer information that is used to access data + * in the object. + * + * One convention that is always used is that a pointer that is + * not malloced always has a value of zero. If the pointer is nonnull, + * then it may be freed, always (and vica-versa). + * + * Where possible, the low leve routines + * memcopy and memset are used to copy or zero memory. + * + * No array bounds checking is ever done within these routines. buyer beware. + * The bounds of arrays are not carried with the array object, ever. + * Bounds of arrays are input via the parameter list. Normally, + * for applications this is not a problem, since the application + * knows what the array dimensions are. + * + * There are several other general principles. + * + * If an allocation size is set to 0, then the actual + * allocation size is set to 1 within the program. + * Something is always allocated whenever a call is made + * to an mdp routine. + * + * All checks for allocations are always checked for success. + * If a failure is found, thene mdp_alloc_eh() is called + * for disposition of the error condition. + * + * Error handling behavior is set by the MDP_ALLO_errorOption external + * int. The default error behavior is to print an error message to stderr, and + * then throw an exception that inherited from std::exception. Usually + * std::bad_alloc() is thrown whenever there is a problem. + * + */ +namespace mdp { + + /** + * If we have array_alloc() from another Sandia program, we will not use + * the one from this mdp_array_alloc. Instead we will redefine the names + */ +#ifdef HAVE_ARRAY_ALLOC +# define mdp_array_alloc array_alloc +# define mdp_safe_free safe_free +#endif + + /*! + * MDP_INT_NOINIT is a poor man's way of specifying whether a value should be + * initialized. These are seldom used numbers which can be used in place + * of real ints and dbls to indicate that initialization shouldn't take + * place. + */ +#define MDP_INT_NOINIT -68361 + + /*! + * MDP_DBL_NOINIT is a poor man's way of specifying whether a value should be + * initialized. These are seldom used numbers which can be used in place + * of real ints and dbls to indicate that initialization shouldn't take + * place. + */ +#define MDP_DBL_NOINIT -1.241E11 + + /*! + * Error Handling + * 7 print and exit + * 6 exit + * 5 print and create a divide by zero for stack trace analysis. + * 4 create a divide by zero for stack analysis trace + * 3 print a message and throw the std::bad_alloc() exception. + * 2 throw the std::bad_alloc() exception and be quiet. + * 1 print a message and return from package with the NULL pointer + * 0 Keep completely silent about the matter and return with + * a null pointer. + * + * -> Right now, the only way to change this option is to right here + * + * The default is to set it to 3. + */ + extern int MDP_ALLO_errorOption; + + + /****************************************************************************/ + /* + * Externals that should be set by the calling program. + * These are only used for debugging purposes. + */ +#ifdef MDP_MPDEBUGIO + extern int MDP_MP_Nprocs; + extern int MDP_MP_myproc; +#endif + + /****************************************************************************/ + /* + * MDP_SAFE_DELETE() + * This useful define is great for delete single instances of + * mallocing using new. + */ +#define MDP_SAFE_DELETE(a) if (a) { delete (a); a = 0; } + + + /****************************************************************************/ + +#define mdp_alloc_struct(x, num) (x *) mdp_array_alloc(1, (num), sizeof(x)) + + + /* function declarations for dynamic array allocation */ + + //! allocates multidimensional pointer arrays of arbitrary length + //! via a single malloc call + /*! + * The first dimension is the number of dimensions in the allocation + */ + extern double *mdp_array_alloc(int numdim, ...); + + //! Free a vector and set its value to 0 + /*! + * This function carries out the following operation + * @code + * free(*hndVec); + * *hndVec = 0; + * @endcode + * + * @param hndVec This is the address of the pointer, expressed as + * a void ** + * + * Note, a key idea behind the mdp suite of routines is that + * a pointer that can be malloced is either malloced or its value + * is 0. This routine enforces this convention. + */ + extern void mdp_safe_free(void ** hndVec); + + //! Allocate a vector of integers + /*! + * The vector is initialized, unless the default int value is set + * to MDP_INT_NOINIT + * + * @param len Length of the vector + * @param defval Default value for the int, defaults to MDP_INT_NOINIT + * + * @return returns a pointer to the vector + */ + extern int *mdp_alloc_int_1(int len, const int defval = MDP_INT_NOINIT); + + //! Allocate a vector of integers, potentially freeing memory first + /*! + * The vector is initialized, unless the default int value is set + * to MDP_INT_NOINIT + * + * Input + * -------------- + * @param array_hdl Previous value of pointer. If non-NULL will try + * to free the memory at this address before doing + * a new alloc + * @param len Length of the vector + * @param defval Default value for the int, defaults to MDP_INT_NOINIT + * + * Output + * --------- + * @return *array_hdl = This value is initialized to the correct address + * of the array. + * A NULL value in the position indicates an error. + */ + extern void mdp_safe_alloc_int_1(int **array_hdl, int len, + const int defval = MDP_INT_NOINIT); + + //! Reallocates a one dimensional array of ints, copying old + //! information to the new array + /*! + * Reallocates a one dimensional array of ints. + * This routine always allocates space for at least one int. + * Calls the smalloc() routine to ensure that all malloc + * calls go through one location. This routine will then copy + * the pertinent information from the old array to the + * new array. + * + * NewArray[0:old_len-1] = OldArray[0:old_len-1]; + * NewArray[old_len:new_len-1] = defval; + * + * Input + * -------------- + * @param array_hdl Previous value of pointer. If non-NULL will try + * to free the memory at this address before doing + * a new alloc + * @param new_len New Length of the vector + * @param old_len New Length of the vector + * @param defval Default value for the int, defaults to MDP_INT_NOINIT + * + * Output + * --------- + * @return *array_hdl = This value is initialized to the correct address + * of the array. + * A NULL value in the position indicates an error. + */ + extern void mdp_realloc_int_1(int **array_hdl, int new_len, int old_len, + const int defval = MDP_INT_NOINIT); + + + //! Allocate a 2D matrix of integers + /*! + * The matrix is initialized, unless the default int value is set + * to MDP_INT_NOINIT, which is the default. + * + * matrix[len1][len2] + * + * All int data entries are contiguous. Therefore, it may + * be used as input into BLAS matrix function calls. + * This can be considered to be in fortran order format with + * len2 as the number of rows, and len1 as the number of columns. + * + * matrix[jcol] refers to the jcol column of the matrix. + * Therefore, matrix[0] is a pointer to the beginning of the + * data portion of the structure. + * The structure will have len1 pointers at the beginning + * that holds pointers into the top of the columns of the + * contiguous data. + * + * The entire structure may be deallocated via one free call. + * + * @param len1 Outer Length of the vector + * @param len2 Inner length of the matrix + * @param defval Default value for the int, defaults to MDP_INT_NOINIT + * + * @return returns a pointer to the matrix + */ + extern int **mdp_alloc_int_2(int len1, int len2, + const int defval = MDP_INT_NOINIT); + + + //! Allocate and initialize a one dimensional array of doubles. + /*! + * As per the convention in mdp, this routine always initializes + * at least one slot. + * + * @param nvalues Length of the array. If this number is + * less than one, it is set to one. Therefore, + * This routine always initializes at least + * one double. + * @param val intialization value. Set it to the + * constant MDP_DBL_NOINIT if you don't + * want any initialization. memset() is + * used for zero initialization for fast + * execution speed. + * + * @return Pointer to the intialized array of doubles + * Failures are indicated by returning the NULL pointer. + */ + extern double *mdp_alloc_dbl_1(int nvalues, const double val=MDP_DBL_NOINIT); + + //! Allocates and/or initialises a one dimensional array of doubles. + /*! + * This routine will free any old memory that was located at that + * position, before it will allocate a new vector. + * + * @param hndVec Previous value of pointer. If non-NULL will try + * to free the memory at this address. On output, + * this value is initialized to the correct address + * of the array. A NULL value in the position + * indicates an error. + * @param nvalues Length of the array + * @param val initialization value + * + */ + extern void mdp_safe_alloc_dbl_1(double **hndVec, int nvalues, + const double val=MDP_DBL_NOINIT); + + //! Reallocate a vector of doubles possibly retaining a subset of values + /*! + * Reallocates the array and sets: + * + * (*hndVec)[0:oldLen-1] = oldVec[0:oldLen-1] + * (*hndVec)[oldLen:newLen] = defVal + * + * Input + * ------ + * @param newLen New Length of the vector + * + * Output + * ------- + * @param oldLen Old Length of the vector + * + */ + extern void mdp_realloc_dbl_1(double ** hndVec, int newLen, int oldLen, + const double defVal=MDP_DBL_NOINIT); + + //! Allocate and initialize a two dimensional array of doubles. + /*! + * Allocate a two dimensional array of doubles. The array is in + * fortran order and can be accessed via the following form: + * + * dblArray[ndim1][ndim2] + * + * Note, ndim2 is the inner dimension. i.e., the array is + * in column ordering. + * + * Input + * ------- + * @param ndim1 Length of the first dimension of the array + * @param ndim2 Length of the second dimension of the array + * @param val Intialization value + * + * + * @return Pointer to the initialized array of doubles. + * Failures are indicated by returning the NULL pointer. + */ + extern double **mdp_alloc_dbl_2(int ndim1, int ndim2, const double val); + + //! Allocate and initialize a two dimensional array of doubles. + /*! + * Allocate a two dimensional array of doubles. The array is in + * fortran order and can be accessed via the following form: + * + * (*arrayHndl)[ndim1][ndim2] + * + * Note, ndim2 is the inner dimension. i.e., the array is + * in column ordering. + * + * Input + * ------- + * @param ndim1 Length of the first dimension of the array + * @param ndim2 Length of the second dimension of the array + * @param val Intialization value + * @param arrayHndl Handle to the array. If nonnull, the array + * is first freed. Failures are indicated + * by returning the NULL pointer. + */ + extern void mdp_safe_alloc_dbl_2(double ***arrayHndl, int ndim1, int ndim2, + const double val = MDP_DBL_NOINIT); + + //! Reallocates a two dimensional array of doubles to a new set of + //! dimensions, copying the old results into the new array. + /*! + * This routine will then copy the pertinent information from + * the old array to the new array. + * + * If both old dimensions are set to zero or less, then this routine + * will free the old memory before mallocing the new memory. This may + * be a benefit for extremely large mallocs. + * In all other cases, the new and the old malloced arrays will + * exist for a short time together. + * + * Input + * ------- + * @param hndArray = Pointer to the global variable that + * holds the old and (eventually new) + * address of the array of doubles to be reallocated + * @param ndim1 = First dimension of the new array + * @param ndim2 = Second dimension of the new array + * @param ndim1Old = First dimension of the old array + * @param ndim2Old = Second dimension of the old array + * @param defVal = Default fill value. + * + * Output + * -------------- + * The resulting vector looks like this: + * + * (*hndArray)[0:ndim1Old-1][0:ndim2Old-1] = oldVec[0:ndim1Old-1][0:ndim2Old-1] + * (*hndArray)[ndim1Old:ndim1][ndim2Old:ndim2] = defVal + * + */ + extern void mdp_realloc_dbl_2(double *** hndArray, int ndim1, int ndim2, + int ndim1Old, int ndim2Old, + const double defVal=MDP_DBL_NOINIT); + + //! Allocate and initialize a one dimensional array of characters. + /*! + * The array is always initialized. + * + * Input + * ------- + * @param nvalues Length of the array + * @param val intialization value. defaults to the NULL char + * + * @return Pointer to the intialized character array + * Failures are indicated by returning the NULL pointer. + */ + extern char *mdp_alloc_char_1(int nvalues, const char val = '\0'); + + //! Allocate and initialize a one dimensional array of characters, + //! deallocating the space before hand. + /*! + * This routine will free any old memory that was located at that + * position, before it will allocate a new vector. + * + * The array is always initialized. + * + * @param arrayHnd Pointer to the global variable that + * holds the old and (eventually new) + * address of the array of char to be reallocated + * @param nvalues Length of the array + * @param val intialization value. defaults to the NULL char + * + * @return Pointer to the intialized character array + * Failures are indicated by returning the NULL pointer. + */ + extern void mdp_safe_alloc_char_1(char **arrayHnd, int nvalues, + const char val = '\0'); + + //! Allocate and initialize a vector of fixed-length + //! strings. Each string is initialized to the NULL string. + /*! + * @param numStrings Number of strings + * @param lenString Length of each string including the trailing null + * character + * + * @return Value is initialized to the correct address + * of the new array on exit. + * A NULL value in the position indicates an error. + */ + extern char **mdp_alloc_VecFixedStrings(int numStrings, int lenString); + + //! Allocate and initialize an array of strings of fixed length + /*! + * @param numStrings Number of strings + * @param lenString Length of each string including the trailing null + * character + * + * @param array_hdl Value is initialized to the correct address + * of the new array on exit. + * A NULL value in the position indicates an error. + * If non-NULL on entry the routine will first + * free the memory at the address. + */ + extern void mdp_safe_alloc_VecFixedStrings(char ***arrayHnd, int numStrings, + int lenString); + + //! Reallocate and initialize a vector of fixed-length strings. + /*! + * Each new string is initialized to the NULL string. + * Old strings are copied. + * + * @param array_hdl The pointer to the char ** location holding + * the data to be reallocated. + * @param numStrings Number of strings + * @param numOldStrings Number of old strings + * @param lenString Length of each string including the trailing null + * character + */ + extern void mdp_realloc_VecFixedStrings(char ***array_hdl, int numStrings, + int numOldStrings, int lenString); + + //! Allocate and initialize a vector of pointers of type pointer to void. + /*! + * All pointers are initialized to the NULL value. + * + * @param numPointers Number of pointers + * + * @return This value is initialized to the correct address of the vector. + * A NULL value in the position indicates an error. + */ + extern void **mdp_alloc_ptr_1(int numPointers); + + //! Allocate and initialize a vector of pointers of type pointer to void. + /*! + * All pointers are initialized to the NULL value. + * + * @param numPointers Number of pointers + * @param array_hdl This value is initialized to the correct address + * of the array. + * A NULL value in the position indicates an error. + * Previous value of pointer. If non-NULL will try + * to free the memory at this address. + */ + extern void mdp_safe_alloc_ptr_1(void ***array_hnd, int numPointers); + + //! Reallocate and initialize a vector of pointers + /*! + * All old pointers are copied + * Each new pointer not associated with an old pointer is + * initialized to NULL. + * + * @param array_hdl The pointer to the char ** location holding + * the data to be reallocated. + * @param numLen Number of new pointers + * @param numOldLen Number of old pointers + */ + extern void mdp_realloc_ptr_1(void ***array_hdl, int numLen, int numOldLen); + + //! Copies one ptr vector into another ptr vector + /*! + * + * @param copyFrom Vector of ptr values to be copied + * @param len Length of the vector + * + * @param copyTo Vector of values to receive the copy + */ + extern void mdp_copy_ptr_1(void *const copyTo, + const void * const copyFrom, const int len); + + //! Duplicates one ptr vector into another ptr vector + /*! + * Mallocs a copy of one vector of pointers and returns the pointer + * to the copy. + * + * Input + * ------------- + * @param *copyFrom Vector of ptr values to be copied + * @param len Length of the vector + * + * Output + * ------------ + * @return Vector of values to receive the copy + */ + extern void **mdp_dupl_ptr_1(const void * const copyFrom, int len); + + //! Copies an array of string vectors from one char ** vector to + //! another + /*! + * The space must have already been allocated within copyFrom and copyTo + * arrays. Overwrites are prevented by the proper application of the + * variable maxLenString. Strings are forced to be null-terminated + * Therefore copyTo[maxLenString-1] = '/0' + * + * Input + * ------- + * @param copyFrom vector of C strings. It should be null terminated + * @param numStrings number of strings + * @param maxLenString maximum of the size of the string arrays, + * copyTo and copyFrom. This is used as the + * argument to strncpy() function. + * + * Output + * ------ + * @param copyTo vector of strings + * + */ + extern void mdp_copy_VecFixedStrings(char ** const copyTo, + const char ** const copyFrom, + int numStrings, size_t maxLenString); + + //! Allocates space for and copies a string + /*! + * + * @param copyFrom null terminated string. If NULL is supplied, then + * nothing is malloced and a NULL value is returned. + * + * @return This value is initialized to the correct address of the array. + * A NULL value in the position either indicates an error, or + * that the original pointer to the string was NULL. + */ + extern char *mdp_copy_string(const char * const copyFrom); + + //! Allocates space for and copies a string + /*! + * @param stringHnd Previous value of pointer. If non-NULL will try + * to free the memory at this address. + * + * @param copyFrom null terminated string. If NULL is supplied, then + * nothing is malloced and a NULL value is returned. + * + * @return This value is initialized to the correct address of the array. + * A NULL value in the position either indicates an error, or + * that the original pointer to the string was NULL. + */ + extern void mdp_safe_copy_string(char **stringHnd, const char * const copyFrom); + + //! Copy a double vector to a double vector + /*! + * copyTo[len] = copyFrom[len] + * + * Input + * ------- + * @param copyFrom Vector to copy ( length >= len) + * @param len Length of the copy + * + * Output + * ------- + * @param copyTo Vector to receive the copy ( length >= len) + */ + extern void mdp_copy_dbl_1(double * const copyTo, + const double * const copyFrom, + const int len); + + //! Copy a double array to a double array + /*! + * This routine carries out a straight copy on the effective 1D description + * of each of the arrays. It copies + * the first len1*len2 doubless storred within copyFrom into the + * the first len1*len2 double slots in copyTo. It does not account + * for the actual dimensions of the two arrays. + * + * Input + * -------- + * @param copyFrom Vector to copy ( length >= len1 * len2) + * @param len1 Length of the first dimension + * @param len2 Length of the second dimension + * + * Output + * ---------- + * @param copyTo Array to receive the copy ( length >= len1 * len2) + */ + extern void mdp_copy_dbl_2(double ** const copyTo, const double ** const copyFrom, + const int len1, const int len2); + + //! Copies one int vector into one int vector + /*! + * Input + * ------------- + * @param copyFrom Vector of values to be copied + * @param len Length of the vector + * + * Output + * ------------ + * *copyTo = Vector of values to receive the copy + */ + extern void mdp_copy_int_1(int * const copyTo, const int * const copyFrom, + const int len); + + //! Copies one 2D int array into another 2D int array + /*! + * This routine carries out a straight copy. Actually it copies + * the first len1*len2 ints storred within copyFrom into the + * the first len1*len2 int slots in copyTo. It does not account + * for the actual dimensions of the two arrays. + * + * @param copyFrom Vector of values to be copied + * @param len1 Length of the first array + * @param len2 Length of the second array + * Output + * ------------ + * @param copyTo Vector of values to receive the copy + */ + extern void mdp_copy_int_2(int ** const copyTo, const int ** const copyFrom, + const int len1, const int len2); + + //! Assigns a single value to a double vector + /*! + * @param v Vector of values to be assigned + * @param value Value to assign with + * @param len Length of the vector + */ + extern void mdp_init_dbl_1(double * const v, const double value, const int len); + + //! Zeroes a double vector + /*! + * @param v = Vector of values to be assigned + * @param len = Length of the vector + */ + extern void mdp_zero_dbl_1(double * const v , const int len); + + //! Assigns a single value to a double matrix. Contiguous data for the + //! matrix is assumed. + /*! + * Input + * ------------- + * @param v matrix of values to be assigned + * @param value value to assign with + * @param len1 Length one of the vector + * @param len2 length two of the vector + */ + extern void mdp_init_dbl_2(double ** const v, const double value, + const int len1, const int len2); + + //! Assigns a single value to an int vector + /*! + * @param v Vector of values to be assigned + * @param value Value to assign with + * @param len Length of the vector + */ + extern void mdp_init_int_1(int * const v, const int value, const int len); + + + /* + * Utility routines to check that a number is finite + */ + + //! Utility routine to check to see that a number is neither zero + //! nor indefinite. + /*! + * This check can be used before using the number in a denominator. + * + * @param tmp number to be checked + */ + extern void checkZeroFinite(const double tmp) throw(std::range_error); + + //! Utility routine to check to see that a number is finite. + /*! + * @param tmp number to be checked + */ + extern void checkFinite(const double tmp) throw(std::range_error); + + //! Utility routine to link checkFinte() to fortran program + /*! + * This routine is accessible from fortran, usually + * + * @param tmp Pointer to the number to check + * + * @todo link it into the usual way Cantera handles Fortran calls + */ + extern "C" void checkfinite_(double *tmp); + + //! utility routine to check that a double stays bounded + /*! + * This routine checks to see if a number stays bounded. The absolute + * value of the number is required to stay below the trigger. + * + * @param tmp Number to be checked + * @param trigger bounds on the number. Defaults to 1.0E20 + */ + extern void checkMagnitude(const double tmp, const double trigger = 1.0E20) + throw(std::range_error); + +} /* end of mdp namespace */ +/****************************************************************************/ +#endif +/****************************************************************************/ + diff --git a/Cantera/src/base/xml.cpp b/Cantera/src/base/xml.cpp index 39fd774e2..ef096de5d 100755 --- a/Cantera/src/base/xml.cpp +++ b/Cantera/src/base/xml.cpp @@ -60,7 +60,7 @@ namespace Cantera { } //! destructor - virtual ~XML_Error() {} + virtual ~XML_Error() throw() {} protected: //! Line number of the file @@ -94,7 +94,7 @@ namespace Cantera { } //! Destructor - virtual ~XML_TagMismatch() {} + virtual ~XML_TagMismatch() throw() {} }; //! Class representing a specific type of XML file formatting error @@ -130,7 +130,7 @@ namespace Cantera { } //! Destructor - virtual ~XML_NoChild() {} + virtual ~XML_NoChild() throw() {} }; //! Class representing a specific type of XML file formatting error @@ -157,7 +157,7 @@ namespace Cantera { } //! Destructor - virtual ~XML_IllegalUnits() {} + virtual ~XML_IllegalUnits() throw() {} };