cantera/include/cantera/base/mdp_allo.h

750 lines
26 KiB
C++

/**
* @file mdp_allo.h
* Declarations for Multi Dimensional Pointer (mdp) malloc routines, which
* allow for dimensioning of arbitrarily dimensioned pointer arrays using
* one call.
*/
/*
* $Revision$
* $Date$
*/
/*
* Copyright 2004 Sandia Corporation. Under the terms of Contract
* DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
* retains certain rights in this software.
* See file License.txt for licensing information.
*/
#ifndef MDP_ALLO_H
#define MDP_ALLO_H
#ifdef WIN32
#pragma warning(disable:4290)
#endif
#include <stdexcept>
/*
* Include the header here in order to pick up size_t definition
*/
#include <cstring>
/**
* The mdp routines are extremely lightweight and fast fortran compatibile
* malloc routines for allocating multiple dimensioned arrays of doubles
* ints, char, and pointers using a single call. These routines don't
* use the std C+ lib routines.
*
* All calls are essentially wrappers around the routine mdp_alloc_array()
* which allocates multidimensioned arrays. The arrays contain room for
* the data and the pointer information that is used to access data
* in the object.
*
* One convention that is always used is that a pointer that is
* not malloced always has a value of zero. If the pointer is nonnull,
* then it may be freed, always (and vica-versa).
*
* Where possible, the low leve routines
* memcpy and memset are used to copy or zero memory.
*
* No array bounds checking is ever done within these routines. buyer beware.
* The bounds of arrays are not carried with the array object, ever.
* Bounds of arrays are input via the parameter list. Normally,
* for applications this is not a problem, since the application
* knows what the array dimensions are.
*
* There are several other general principles.
*
* If an allocation size is set to 0, then the actual
* allocation size is set to 1 within the program.
* Something is always allocated whenever a call is made
* to an mdp routine.
*
* All checks for allocations are always checked for success.
* If a failure is found, thene mdp_alloc_eh() is called
* for disposition of the error condition.
*
* Error handling behavior is set by the MDP_ALLO_errorOption external
* int. The default error behavior is to print an error message to stderr, and
* then throw an exception that inherited from std::exception. Usually
* std::bad_alloc() is thrown whenever there is a problem.
*
*/
namespace mdp
{
/**
* If we have array_alloc() from another Sandia program, we will not use
* the one from this mdp_array_alloc. Instead we will redefine the names
*/
#ifdef HAVE_ARRAY_ALLOC
# define mdp_array_alloc array_alloc
# define mdp_safe_free safe_free
#endif
/*!
* MDP_INT_NOINIT is a poor man's way of specifying whether a value should be
* initialized. These are seldom used numbers which can be used in place
* of real ints and dbls to indicate that initialization shouldn't take
* place.
*/
#define MDP_INT_NOINIT -68361
/*!
* MDP_DBL_NOINIT is a poor man's way of specifying whether a value should be
* initialized. These are seldom used numbers which can be used in place
* of real ints and dbls to indicate that initialization shouldn't take
* place.
*/
#define MDP_DBL_NOINIT -1.241E11
/*!
* Error Handling
* 7 print and exit
* 6 exit
* 5 print and create a divide by zero for stack trace analysis.
* 4 create a divide by zero for stack analysis trace
* 3 print a message and throw the std::bad_alloc() exception.
* 2 throw the std::bad_alloc() exception and be quiet.
* 1 print a message and return from package with the NULL pointer
* 0 Keep completely silent about the matter and return with
* a null pointer.
*
* -> Right now, the only way to change this option is to right here
*
* The default is to set it to 3.
*/
extern int MDP_ALLO_errorOption;
/****************************************************************************/
/*
* Externals that should be set by the calling program.
* These are only used for debugging purposes.
*/
#ifdef MDP_MPDEBUGIO
extern int MDP_MP_Nprocs;
extern int MDP_MP_myproc;
#endif
/****************************************************************************/
/*
* MDP_SAFE_DELETE()
* This useful define is great for delete single instances of
* mallocing using new.
*/
#define MDP_SAFE_DELETE(a) if (a) { delete (a); a = 0; }
/****************************************************************************/
#define mdp_alloc_struct(x, num) (x *) mdp_array_alloc(1, (num), sizeof(x))
/* function declarations for dynamic array allocation */
//! allocates multidimensional pointer arrays of arbitrary length
//! via a single malloc call
/*!
* The first dimension is the number of dimensions in the allocation
*/
extern double* mdp_array_alloc(int numdim, ...);
//! Free a vector and set its value to 0
/*!
* This function carries out the following operation
* @code
* free(*hndVec);
* *hndVec = 0;
* @endcode
*
* @param hndVec This is the address of the pointer, expressed as
* a void **
*
* Note, a key idea behind the mdp suite of routines is that
* a pointer that can be malloced is either malloced or its value
* is 0. This routine enforces this convention.
*/
extern void mdp_safe_free(void** hndVec);
//! Allocate a vector of integers
/*!
* The vector is initialized, unless the default int value is set
* to MDP_INT_NOINIT
*
* @param len Length of the vector
* @param defval Default value for the int, defaults to MDP_INT_NOINIT
*
* @return returns a pointer to the vector
*/
extern int* mdp_alloc_int_1(int len, const int defval = MDP_INT_NOINIT);
//! Allocate a vector of integers, potentially freeing memory first
/*!
* The vector is initialized, unless the default int value is set
* to MDP_INT_NOINIT
*
* Input
* --------------
* @param array_hdl Previous value of pointer. If non-NULL will try
* to free the memory at this address before doing
* a new alloc
* @param len Length of the vector
* @param defval Default value for the int, defaults to MDP_INT_NOINIT
*
* Output
* ---------
* @return *array_hdl = This value is initialized to the correct address
* of the array.
* A NULL value in the position indicates an error.
*/
extern void mdp_safe_alloc_int_1(int** array_hdl, int len,
const int defval = MDP_INT_NOINIT);
//! Reallocates a one dimensional array of ints, copying old
//! information to the new array
/*!
* Reallocates a one dimensional array of ints.
* This routine always allocates space for at least one int.
* Calls the smalloc() routine to ensure that all malloc
* calls go through one location. This routine will then copy
* the pertinent information from the old array to the
* new array.
*
* NewArray[0:old_len-1] = OldArray[0:old_len-1];
* NewArray[old_len:new_len-1] = defval;
*
* Input
* --------------
* @param array_hdl Previous value of pointer. If non-NULL will try
* to free the memory at this address before doing
* a new alloc
* @param new_len New Length of the vector
* @param old_len New Length of the vector
* @param defval Default value for the int, defaults to MDP_INT_NOINIT
*
* Output
* ---------
* @return *array_hdl = This value is initialized to the correct address
* of the array.
* A NULL value in the position indicates an error.
*/
extern void mdp_realloc_int_1(int** array_hdl, int new_len, int old_len,
const int defval = MDP_INT_NOINIT);
//! Allocate a 2D matrix of integers
/*!
* The matrix is initialized, unless the default int value is set
* to MDP_INT_NOINIT, which is the default.
*
* matrix[len1][len2]
*
* All int data entries are contiguous. Therefore, it may
* be used as input into BLAS matrix function calls.
* This can be considered to be in fortran order format with
* len2 as the number of rows, and len1 as the number of columns.
*
* matrix[jcol] refers to the jcol column of the matrix.
* Therefore, matrix[0] is a pointer to the beginning of the
* data portion of the structure.
* The structure will have len1 pointers at the beginning
* that holds pointers into the top of the columns of the
* contiguous data.
*
* The entire structure may be deallocated via one free call.
*
* @param len1 Outer Length of the vector
* @param len2 Inner length of the matrix
* @param defval Default value for the int, defaults to MDP_INT_NOINIT
*
* @return returns a pointer to the matrix
*/
extern int** mdp_alloc_int_2(int len1, int len2,
const int defval = MDP_INT_NOINIT);
//! Allocate and initialize a one dimensional array of doubles.
/*!
* As per the convention in mdp, this routine always initializes
* at least one slot.
*
* @param nvalues Length of the array. If this number is
* less than one, it is set to one. Therefore,
* This routine always initializes at least
* one double.
* @param val initialization value. Set it to the
* constant MDP_DBL_NOINIT if you don't
* want any initialization. memset() is
* used for zero initialization for fast
* execution speed.
*
* @return Pointer to the initialized array of doubles
* Failures are indicated by returning the NULL pointer.
*/
extern double* mdp_alloc_dbl_1(int nvalues, const double val=MDP_DBL_NOINIT);
//! Allocates and/or initializes a one dimensional array of doubles.
/*!
* This routine will free any old memory that was located at that
* position, before it will allocate a new vector.
*
* @param hndVec Previous value of pointer. If non-NULL will try
* to free the memory at this address. On output,
* this value is initialized to the correct address
* of the array. A NULL value in the position
* indicates an error.
* @param nvalues Length of the array
* @param val initialization value
*
*/
extern void mdp_safe_alloc_dbl_1(double** hndVec, int nvalues,
const double val=MDP_DBL_NOINIT);
//! Reallocate a vector of doubles possibly retaining a subset of values
/*!
* Reallocates the array and sets:
*
* (*hndVec)[0:oldLen-1] = oldVec[0:oldLen-1]
* (*hndVec)[oldLen:newLen] = defVal
*
* Input
* ------
* @param newLen New Length of the vector
*
* Output
* -------
* @param oldLen Old Length of the vector
*
*/
extern void mdp_realloc_dbl_1(double** hndVec, int newLen, int oldLen,
const double defVal=MDP_DBL_NOINIT);
//! Allocate and initialize a two dimensional array of doubles.
/*!
* Allocate a two dimensional array of doubles. The array is in
* fortran order and can be accessed via the following form:
*
* dblArray[ndim1][ndim2]
*
* Note, ndim2 is the inner dimension. i.e., the array is
* in column ordering.
*
* Input
* -------
* @param ndim1 Length of the first dimension of the array
* @param ndim2 Length of the second dimension of the array
* @param val Initialization value
*
*
* @return Pointer to the initialized array of doubles.
* Failures are indicated by returning the NULL pointer.
*/
extern double** mdp_alloc_dbl_2(int ndim1, int ndim2, const double val);
//! Allocate and initialize a two dimensional array of doubles.
/*!
* Allocate a two dimensional array of doubles. The array is in
* fortran order and can be accessed via the following form:
*
* (*arrayHndl)[ndim1][ndim2]
*
* Note, ndim2 is the inner dimension. i.e., the array is
* in column ordering.
*
* Input
* -------
* @param ndim1 Length of the first dimension of the array
* @param ndim2 Length of the second dimension of the array
* @param val Initialization value
* @param arrayHndl Handle to the array. If nonnull, the array
* is first freed. Failures are indicated
* by returning the NULL pointer.
*/
extern void mdp_safe_alloc_dbl_2(double** *arrayHndl, int ndim1, int ndim2,
const double val = MDP_DBL_NOINIT);
//! Reallocates a two dimensional array of doubles to a new set of
//! dimensions, copying the old results into the new array.
/*!
* This routine will then copy the pertinent information from
* the old array to the new array.
*
* If both old dimensions are set to zero or less, then this routine
* will free the old memory before mallocing the new memory. This may
* be a benefit for extremely large mallocs.
* In all other cases, the new and the old malloced arrays will
* exist for a short time together.
*
* Input
* -------
* @param hndArray = Pointer to the global variable that
* holds the old and (eventually new)
* address of the array of doubles to be reallocated
* @param ndim1 = First dimension of the new array
* @param ndim2 = Second dimension of the new array
* @param ndim1Old = First dimension of the old array
* @param ndim2Old = Second dimension of the old array
* @param defVal = Default fill value.
*
* Output
* --------------
* The resulting vector looks like this:
*
* (*hndArray)[0:ndim1Old-1][0:ndim2Old-1] = oldVec[0:ndim1Old-1][0:ndim2Old-1]
* (*hndArray)[ndim1Old:ndim1][ndim2Old:ndim2] = defVal
*
*/
extern void mdp_realloc_dbl_2(double** * hndArray, int ndim1, int ndim2,
int ndim1Old, int ndim2Old,
const double defVal=MDP_DBL_NOINIT);
//! Allocate and initialize a one dimensional array of characters.
/*!
* The array is always initialized.
*
* Input
* -------
* @param nvalues Length of the array
* @param val initialization value. defaults to the NULL char
*
* @return Pointer to the initialized character array
* Failures are indicated by returning the NULL pointer.
*/
extern char* mdp_alloc_char_1(int nvalues, const char val = '\0');
//! Allocate and initialize a one dimensional array of characters,
//! deallocating the space before hand.
/*!
* This routine will free any old memory that was located at that
* position, before it will allocate a new vector.
*
* The array is always initialized.
*
* @param arrayHnd Pointer to the global variable that
* holds the old and (eventually new)
* address of the array of char to be reallocated
* @param nvalues Length of the array
* @param val initialization value. defaults to the NULL char
*
* @return Pointer to the initialized character array
* Failures are indicated by returning the NULL pointer.
*/
extern void mdp_safe_alloc_char_1(char** arrayHnd, int nvalues,
const char val = '\0');
//! Allocate and initialize a vector of fixed-length
//! strings. Each string is initialized to the NULL string.
/*!
* @param numStrings Number of strings
* @param lenString Length of each string including the trailing null
* character
*
* @return Value is initialized to the correct address
* of the new array on exit.
* A NULL value in the position indicates an error.
*/
extern char** mdp_alloc_VecFixedStrings(int numStrings, int lenString);
//! Allocate and initialize an array of strings of fixed length
/*!
* @param numStrings Number of strings
* @param lenString Length of each string including the trailing null
* character
*
* @param array_hdl Value is initialized to the correct address
* of the new array on exit.
* A NULL value in the position indicates an error.
* If non-NULL on entry the routine will first
* free the memory at the address.
*/
extern void mdp_safe_alloc_VecFixedStrings(char** *arrayHnd, int numStrings,
int lenString);
//! Reallocate and initialize a vector of fixed-length strings.
/*!
* Each new string is initialized to the NULL string.
* Old strings are copied.
*
* @param array_hdl The pointer to the char ** location holding
* the data to be reallocated.
* @param numStrings Number of strings
* @param numOldStrings Number of old strings
* @param lenString Length of each string including the trailing null
* character
*/
extern void mdp_realloc_VecFixedStrings(char** *array_hdl, int numStrings,
int numOldStrings, int lenString);
//! Allocate and initialize a vector of pointers of type pointer to void.
/*!
* All pointers are initialized to the NULL value.
*
* @param numPointers Number of pointers
*
* @return This value is initialized to the correct address of the vector.
* A NULL value in the position indicates an error.
*/
extern void** mdp_alloc_ptr_1(int numPointers);
//! Allocate and initialize a vector of pointers of type pointer to void.
/*!
* All pointers are initialized to the NULL value.
*
* @param numPointers Number of pointers
* @param array_hdl This value is initialized to the correct address
* of the array.
* A NULL value in the position indicates an error.
* Previous value of pointer. If non-NULL will try
* to free the memory at this address.
*/
extern void mdp_safe_alloc_ptr_1(void** *array_hnd, int numPointers);
//! Reallocate and initialize a vector of pointers
/*!
* All old pointers are copied
* Each new pointer not associated with an old pointer is
* initialized to NULL.
*
* @param array_hdl The pointer to the char ** location holding
* the data to be reallocated.
* @param numLen Number of new pointers
* @param numOldLen Number of old pointers
*/
extern void mdp_realloc_ptr_1(void** *array_hdl, int numLen, int numOldLen);
//! Copies one ptr vector into another ptr vector
/*!
*
* @param copyFrom Vector of ptr values to be copied
* @param len Length of the vector
*
* @param copyTo Vector of values to receive the copy
*/
extern void mdp_copy_ptr_1(void* const copyTo,
const void* const copyFrom, const int len);
//! Duplicates one ptr vector into another ptr vector
/*!
* Mallocs a copy of one vector of pointers and returns the pointer
* to the copy.
*
* Input
* -------------
* @param *copyFrom Vector of ptr values to be copied
* @param len Length of the vector
*
* Output
* ------------
* @return Vector of values to receive the copy
*/
extern void** mdp_dupl_ptr_1(const void* const copyFrom, int len);
//! Copies an array of string vectors from one char ** vector to
//! another
/*!
* The space must have already been allocated within copyFrom and copyTo
* arrays. Overwrites are prevented by the proper application of the
* variable maxLenString. Strings are forced to be null-terminated
* Therefore copyTo[maxLenString-1] = '/0'
*
* Input
* -------
* @param copyFrom vector of C strings. It should be null terminated
* @param numStrings number of strings
* @param maxLenString maximum of the size of the string arrays,
* copyTo and copyFrom. This is used as the
* argument to strncpy() function.
*
* Output
* ------
* @param copyTo vector of strings
*
*/
extern void mdp_copy_VecFixedStrings(char** const copyTo,
const char** const copyFrom,
int numStrings, size_t maxLenString);
//! Allocates space for and copies a string
/*!
*
* @param copyFrom null terminated string. If NULL is supplied, then
* nothing is malloced and a NULL value is returned.
*
* @return This value is initialized to the correct address of the array.
* A NULL value in the position either indicates an error, or
* that the original pointer to the string was NULL.
*/
extern char* mdp_copy_string(const char* const copyFrom);
//! Allocates space for and copies a string
/*!
* @param stringHnd Previous value of pointer. If non-NULL will try
* to free the memory at this address.
*
* @param copyFrom null terminated string. If NULL is supplied, then
* nothing is malloced and a NULL value is returned.
*
* @return This value is initialized to the correct address of the array.
* A NULL value in the position either indicates an error, or
* that the original pointer to the string was NULL.
*/
extern void mdp_safe_copy_string(char** stringHnd, const char* const copyFrom);
//! Copy a double vector to a double vector
/*!
* copyTo[len] = copyFrom[len]
*
* Input
* -------
* @param copyFrom Vector to copy ( length >= len)
* @param len Length of the copy
*
* Output
* -------
* @param copyTo Vector to receive the copy ( length >= len)
*/
extern void mdp_copy_dbl_1(double* const copyTo,
const double* const copyFrom,
const int len);
//! Copy a double array to a double array
/*!
* This routine carries out a straight copy on the effective 1D description
* of each of the arrays. It copies
* the first len1*len2 doubless stored within copyFrom into the
* the first len1*len2 double slots in copyTo. It does not account
* for the actual dimensions of the two arrays.
*
* Input
* --------
* @param copyFrom Vector to copy ( length >= len1 * len2)
* @param len1 Length of the first dimension
* @param len2 Length of the second dimension
*
* Output
* ----------
* @param copyTo Array to receive the copy ( length >= len1 * len2)
*/
extern void mdp_copy_dbl_2(double** const copyTo, const double** const copyFrom,
const int len1, const int len2);
//! Copies one int vector into one int vector
/*!
* Input
* -------------
* @param copyFrom Vector of values to be copied
* @param len Length of the vector
*
* Output
* ------------
* *copyTo = Vector of values to receive the copy
*/
extern void mdp_copy_int_1(int* const copyTo, const int* const copyFrom,
const int len);
//! Copies one 2D int array into another 2D int array
/*!
* This routine carries out a straight copy. Actually it copies
* the first len1*len2 ints stored within copyFrom into the
* the first len1*len2 int slots in copyTo. It does not account
* for the actual dimensions of the two arrays.
*
* @param copyFrom Vector of values to be copied
* @param len1 Length of the first array
* @param len2 Length of the second array
* Output
* ------------
* @param copyTo Vector of values to receive the copy
*/
extern void mdp_copy_int_2(int** const copyTo, const int** const copyFrom,
const int len1, const int len2);
//! Assigns a single value to a double vector
/*!
* @param v Vector of values to be assigned
* @param value Value to assign with
* @param len Length of the vector
*/
extern void mdp_init_dbl_1(double* const v, const double value, const int len);
//! Zeroes a double vector
/*!
* @param v = Vector of values to be assigned
* @param len = Length of the vector
*/
extern void mdp_zero_dbl_1(double* const v , const int len);
//! Zeroes an int vector
/*!
* @param v = Vector of values to be assigned
* @param len = Length of the vector
*/
extern void mdp_zero_int_1(int* const v , const int len);
//! Assigns a single value to a double matrix. Contiguous data for the
//! matrix is assumed.
/*!
* Input
* -------------
* @param v matrix of values to be assigned
* @param value value to assign with
* @param len1 Length one of the vector
* @param len2 length two of the vector
*/
extern void mdp_init_dbl_2(double** const v, const double value,
const int len1, const int len2);
//! Assigns a single value to an int vector
/*!
* @param v Vector of values to be assigned
* @param value Value to assign with
* @param len Length of the vector
*/
extern void mdp_init_int_1(int* const v, const int value, const int len);
/*
* Utility routines to check that a number is finite
*/
//! Utility routine to check to see that a number is neither zero
//! nor indefinite.
/*!
* This check can be used before using the number in a denominator.
*
* @param tmp number to be checked
*/
extern void checkZeroFinite(const double tmp);
//! Utility routine to check to see that a number is finite.
/*!
* @param tmp number to be checked
*/
extern void checkFinite(const double tmp);
//! Utility routine to link checkFinte() to fortran program
/*!
* This routine is accessible from fortran, usually
*
* @param tmp Pointer to the number to check
*
* @todo link it into the usual way Cantera handles Fortran calls
*/
extern "C" void checkfinite_(double* tmp);
//! utility routine to check that a double stays bounded
/*!
* This routine checks to see if a number stays bounded. The absolute
* value of the number is required to stay below the trigger.
*
* @param tmp Number to be checked
* @param trigger bounds on the number. Defaults to 1.0E20
*/
extern void checkMagnitude(const double tmp, const double trigger = 1.0E20);
} /* end of mdp namespace */
/****************************************************************************/
#endif
/****************************************************************************/