cantera/Cantera/src/base/mdp_allo.cpp
2009-11-09 23:36:49 +00:00

1794 lines
62 KiB
C++

/**
* @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 <new>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cstdarg>
#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<il; i++) {
* for (j=0; j<jl; j++) {
* for (k=0; k<kl; k++) temp[i][j][k] = 1;
* }
* }
*
* temp2 = (int *) malloc(10*sizeof(int));
* for (i=0; i<10; i++) temp2[i] = 0;
*
* for (i=0; i<il; i++) {
* for (j=0; j<jl; j++) {
* for (k=0; k<kl; k++) (void) printf(" %d\n", temp[i][j][k]);
* }
* }
* malloc_verify();
*}
*****************************************************************************/
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
double *mdp_array_alloc(int numdim, ...)
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
{
int i, j;
struct dim {
long index; /* Number of elements in the dimension */
long total; /* Total number of elements */
long size; /* Size of a single element in bytes */
long off; /* offset from beginning of array */
} dim[4]; /* Info about each dimension */
long total; /* Total size of the array */
double *dfield; /* ptr to avoid lint complaints */
char *field; /* The multi-dimensional array */
char **ptr; /* Pointer offset */
char *data; /* Data offset */
va_list va; /* Current pointer in the argument list */
va_start(va, numdim);
if (numdim <= 0) {
(void) fprintf(stderr,
"mdp_array_alloc ERROR: number of dimensions, %d, is <=0\n",
numdim);
return NULL;
}
else if (numdim > 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<int>(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<int>(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<int>(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 */
/****************************************************************************/