/** * @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; #ifdef WIN32 #pragma warning(disable:4996) #endif 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", (int) 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", (int) 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 */ /****************************************************************************/