/*@@ @file MaskUtils.c @date October 2002 @author Denis Pollney @desc Utilities for registering/setting/checking the mask. @desc @version $Header$ @@*/ #include #include "cctk.h" #include "cctk_FortranString.h" #include "SpaceMask.h" static const char* rcsid = "$Header$"; CCTK_FILEVERSION(CACTUSEINSTEIN_SPACEMASK_MaskUtils_c); SpaceMask_Registry* spacemask_registry = NULL; /*@@ @routine SpaceMask_get_bit_nbr @author Denis Pollney @date 15 October 2002 @desc Return the number of bits required to represent a given number. Cheesy divide-by-two method, maybe something else is quicker. @enddesc @@*/ int SpaceMask_get_bit_nbr(int nstates) { int bstates; int bit_nbr; bstates = nstates-1; for (bit_nbr=0; bstates>0; ++bit_nbr) bstates /= 2; return bit_nbr; } /*@@ @routine SpaceMask_get_free_bits @author Denis Pollney @date 15 October 2002 @desc Determine the mask bits which have not yet been allocated. The return value is a bitmask with the requested number of free bits set to 1. If there are not enough free bits left to satisfy the request, stop with an error. @enddesc @@*/ CCTK_INT8 SpaceMask_get_free_bits(int nbits) { CCTK_INT8 used_bits; CCTK_INT8 new_bits; int i; int j; int n; used_bits = 0; if (spacemask_registry != NULL) { for (i=0; intypes; ++i) used_bits |= spacemask_registry->type_list[i]->bitmask; } n=1; new_bits = 0; j = 0; for (i=0; iname = name; new_state->bitmask = state_mask; return new_state; } /*@@ @routine SpaceMask_setup_new_type @author Denis Pollney @date 15 October 2002 @desc Allocate a new SpaceMask_Type. This involves allocating a set of bits within the mask to the new type, and creating appropriate bitmasks (using the allocated bits) for each of the requested states. @enddesc @@*/ SpaceMask_Type* SpaceMask_setup_new_type(CCTK_INT8 new_bits, char* type_name, int nstates, char** state_list, CCTK_INT8* state_mask) { SpaceMask_Type* new_type; int j; new_type = (SpaceMask_Type*) malloc (sizeof(SpaceMask_Type)); new_type->bitmask = new_bits; new_type->nstates = nstates; new_type->name = type_name; new_type->state_list = (SpaceMask_State**) malloc (nstates*sizeof(SpaceMask_State*)); for (j=0; jstate_list[j] = SpaceMask_setup_new_state(state_mask[j], state_list[j]); return new_type; } /*@@ @routine SpaceMask_append_type_to_registry @author Denis Pollney @date 15 October 2002 @desc Adds a new type to the spacemask_registry. @enddesc @@*/ void SpaceMask_append_type_to_registry(SpaceMask_Type* new_type) { SpaceMask_Type** new_type_list; int ntypes; int i; if (spacemask_registry == NULL) { spacemask_registry = (SpaceMask_Registry*) malloc (sizeof(SpaceMask_Registry)); ntypes = 1; new_type_list = (SpaceMask_Type**) malloc (sizeof(SpaceMask_Type*)); new_type_list[0] = new_type; } else { ntypes = spacemask_registry->ntypes + 1; new_type_list = (SpaceMask_Type**) malloc (ntypes*sizeof(SpaceMask_Type*)); for (i=0; itype_list[i]; new_type_list[ntypes-1] = new_type; free(spacemask_registry->type_list); } spacemask_registry->ntypes = ntypes; spacemask_registry->type_list = new_type_list; } /*@@ @routine SpaceMask_RegisterType @author Denis Pollney @date 15 October 2002 @desc Allocates a set of bits of the SpaceMask to represent a set of states of the named type. @enddesc @@*/ int SpaceMask_RegisterType(char* type_name, int nstates, char** state_list) { SpaceMask_Type* new_type; CCTK_INT8 new_bits; CCTK_INT8* state_mask; int bit_nbr; bit_nbr = SpaceMask_get_bit_nbr(nstates); new_bits = SpaceMask_get_free_bits(bit_nbr); state_mask = SpaceMask_determine_state_mask(new_bits, nstates); new_type = SpaceMask_setup_new_type(new_bits, type_name, nstates, state_list, state_mask); SpaceMask_append_type_to_registry (new_type); return 0; } /*@@ @routine SpaceMask_AppendStatesToType @author Denis Pollney @date 15 October 2002 @desc Adds a new set of possible states to an already existing type. If required, new bits of the mask are allocated to the given state. If bits are not available for this, then an error is returned. @enddesc @@*/ int SpaceMask_AppendStatesToType(char* type_name, int nstates, char** state_list) { CCTK_INT8 new_bits; CCTK_INT8 allocated_bits; CCTK_INT8* state_mask; SpaceMask_Type* old_type; SpaceMask_Type* new_type; char** new_state_list; int i; int j; int old_type_idx; int new_bit_nbr; int total_nstates; old_type = NULL; for (i=0; intypes; ++i) { if (!strcmp(spacemask_registry->type_list[i]->name, type_name)) { old_type = spacemask_registry->type_list[i]; old_type_idx = i; } } if (old_type == NULL) { CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING, "Mask type \"%s\" has not been registered", type_name); return -1; } total_nstates = old_type->nstates + nstates; new_bit_nbr = SpaceMask_get_bit_nbr(total_nstates) - SpaceMask_get_bit_nbr(old_type->nstates); new_bits = SpaceMask_get_free_bits(new_bit_nbr); allocated_bits = old_type->bitmask | new_bits; state_mask = SpaceMask_determine_state_mask(allocated_bits, total_nstates); new_state_list = (char**) malloc (total_nstates*sizeof(char*)); i = 0; for (j=0; jnstates; ++j, ++i) new_state_list[i] = old_type->state_list[j]->name; for (j=0; jtype_list[old_type_idx] = new_type; return 0; } /*@@ @routine SpaceMask_GetTypeBits @author Denis Pollney @date 15 October 2002 @desc Returns the bitmask corresponding to the given type. Bits which are allocated to the given type are set to 1, all other bits are 0. @enddesc @@*/ CCTK_INT8 SpaceMask_GetTypeBits(char* type_name) { int i; for (i=0; intypes; ++i) { if (!strcmp(spacemask_registry->type_list[i]->name, type_name)) return spacemask_registry->type_list[i]->bitmask; } CCTK_VInfo (CCTK_THORNSTRING, "Type \"%s\" has not been registered.\n", type_name); return 0; } /*@@ @routine SpaceMask_GetStateBits @author Denis Pollney @date 15 October 2002 @desc Returns the bitmask corresponding to the given state. @enddesc @@*/ CCTK_INT8 SpaceMask_GetStateBits(char* type_name, char* state_name) { SpaceMask_Type* type; int i, j; for (i=0; intypes; ++i) { if (!strcmp(spacemask_registry->type_list[i]->name, type_name)) { type = spacemask_registry->type_list[i]; for (j=0; jnstates; ++j) { if (!strcmp(type->state_list[j]->name, state_name)) return type->state_list[j]->bitmask; } } } CCTK_VInfo (CCTK_THORNSTRING, "Requested state \"%s\" could not be found in type \"%s\"\n", state_name, type_name); return 0; } /*@@ @routine SpaceMask_SetState @author Denis Pollney @date 15 October 2002 @desc Sets the mask at a point to the given state. @enddesc @@*/ void SpaceMask_SetState(CCTK_INT8* mask, int point, char* type_name, char* state) { CCTK_INT8 type_bits; CCTK_INT8 state_bits; type_bits = SpaceMask_GetTypeBits(type_name); state_bits = SpaceMask_GetStateBits(type_name, state); SpaceMask_SetStateBits(mask, point, type_bits, state_bits); } /*@@ @routine SpaceMask_CheckState @author Denis Pollney @date 15 October 2002 @desc Checks that the mask at a point has the given state, in which case return 1, otherwise return 0. @enddesc @@*/ int SpaceMask_CheckState(CCTK_INT8* mask, int point, char* type_name, char* state) { CCTK_INT8 type_bits; CCTK_INT8 state_bits; type_bits = SpaceMask_GetTypeBits(type_name); state_bits = SpaceMask_GetStateBits(type_name, state); return SpaceMask_CheckStateBits(mask, point, type_bits, state_bits); } /******************************************************************** ********************* Fortran Wrappers *************************** ********************************************************************/ /* How do you pass the char** state list from fortran??? void CCTK_FCALL CCTK_FNAME(SpaceMask_RegisterType)(int* ierr, char* type_name, int* nstates, char** state_list) { *ierr = SpaceMask_RegisterType(type_name, *nstates, state_list); } */ void CCTK_FCALL CCTK_FNAME(SpaceMask_GetTypeBits)(CCTK_INT8* type_bits, ONE_FORTSTRING_ARG) { ONE_FORTSTRING_CREATE(type_name) *type_bits = SpaceMask_GetTypeBits(type_name); free(type_name); } void CCTK_FCALL CCTK_FNAME(SpaceMask_GetStateBits)(CCTK_INT8* state_bits, TWO_FORTSTRING_ARG) { TWO_FORTSTRING_CREATE(type_name, state_name) *state_bits = SpaceMask_GetStateBits(type_name, state_name); } void CCTK_FCALL CCTK_FNAME(SpaceMask_SetState)(CCTK_INT8* mask, CCTK_INT* point, TWO_FORTSTRING_ARG) { TWO_FORTSTRING_CREATE(type_name, state) SpaceMask_SetState(mask, *point, type_name, state); } void CCTK_FCALL CCTK_FNAME(SpaceMask_CheckState)(int* retval, CCTK_INT8* mask, CCTK_INT* point, TWO_FORTSTRING_ARG) { TWO_FORTSTRING_CREATE(type_name, state) *retval = SpaceMask_CheckState(mask, *point, type_name, state); }