Skip to content
Permalink
5002e16e6e
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
298 lines (244 sloc) 9.15 KB
#pragma message("touching: "__FILE__)
#include "common.h"
#define MAXSEG 5
#define DYNARR_TYPE int
#define TYPED_NAME(name) TOKEN_PASTE(DYNARR_TYPE, name)
/* Assuming MAXSEG is defined.
Size of each block of the dynamic array.
Must be a positive integer.*/
/* Assuming DYNARR_TYPE is defined.
The data type of the array.
Must be a valid one-word type without space, *, etc. (use typedef if necessary)
*/
#ifndef MAXSEG
#pragma message("MAXSEG must be defined before including " __FILE__)
#elif MAXSEG <= 0
#pragma message("MAXSEG has non positive value: " MAXSEG)
#elif !defined(DYNARR_TYPE)
#pragma message("DYNARR_TYPE must be defined before including " __FILE__)
#else
// everything is fine
#include "dynarr_freenodelist.h"
/* The segment structure. These are the nodes of the linked list */
typedef struct {
DYNARR_TYPE data;
int index; // my position
int nextIndex; // next node's position
}TYPED_NAME(Sseg);
const TYPED_NAME(Sseg) EMPTY_SSEG;
/* The dynamic array data structure */
typedef struct{
TYPED_NAME(Sseg)* pSegArr;
//real_t* pSegNextArr;
int iInsertPos;
/////////////////// Free nodes list ////////////////
struct FreeSegNode *pFreeSegList, *pFreeSegInvalidList;
int iSizeOfFreeSegList;
struct FreeSegNode* pTempFreeNode1, *pTempFreeNode2;
////////////// temporaries //////////////
int iTempIndex1, iTempIndex2;
TYPED_NAME(Sseg) tempSeg1;
const TYPED_NAME(Sseg) emptySeg;
//////////// Segment banks ////////////
TYPED_NAME(Sseg)** pSegBanksArr;
int* pSegBankSizeArr;
int* pSegBankIndexLimitArr;
int NumSegBanks;
int NumSegBanks;
int MaxSegBanks;
int SegBankAllocViolation;
}TYPED_NAME(DynArr);
// dynarr variable name; contains all state variables
#define DYNARR_VARS TOKEN_PASTE(TYPED_NAME(DynArr), Vars)
/* Shortcuts to important variables */
#define SEG_ARR DYNARR_VARS.pSegArr
#define SEG_INSERT_POS DYNARR_VARS.iInsertPos
#define FREESEG_LIST DYNARR_VARS.pFreeSegList
#define FREESEG_INVALID_LIST DYNARR_VARS.pFreeSegInvalidList
#define FREESEG_LIST_SIZE DYNARR_VARS.iSizeOfFreeSegList
#define TEMP_FREESEGNODE_1 DYNARR_VARS.pTempFreeNode1
#define TEMP_FREESEGNODE_2 DYNARR_VARS.pTempFreeNode2
#define TEMP_INDEX_1 DYNARR_VARS.iTempIndex1
#define TEMP_INDEX_2 DYNARR_VARS.iTempIndex2
#define TEMP_SEG_1 DYNARR_VARS.iTempIndex1
#define NULL_SEG DYNARR_VARS.emptySeg
#define SEG_BANK_ALLOC_VIOLATION DYNARR_VARS.SegBankAllocViolation
// maximum number of segment banks
// this should be a very big number
// this number should never be reached
#define MAX_SEG_BANKS DYNARR_VARS.MaxSegBanks
// array containing size (# of segments) of each segment bank
#define SEG_BANK_SIZE_ARR DYNARR_VARS.pSegBankSizeArr
// array containing last valid index of each segment bank
#define SEG_BANK_INDEX_LIMIT_ARR DYNARR_VARS.pSegBankIndexLimitArr
// Number of active segment banks
#define NUM_SEG_BANKS DYNARR_VARS.NumSegBanks
#define CURRENT_SEG_BANK (NUM_SEG_BANKS - 1)
// actual segment banks
#define SEG_BANKS_ARR DYNARR_VARS.pSegBanksArr
// declarations
// swap two integers, or pointers, without using temporary storage
__inline void int_swap(unsigned int *var1, unsigned int *var2) {
(*var1) = (*var1) ^ (*var2);
(*var2) = (*var1) ^ (*var2);
(*var1) = (*var1) ^ (*var2);
}
// external definitions for allocating/resizing blocks
extern int seg_bank_alloc_next();
extern int seg_bank_increase_max();
#define EMPTY_INDEX 0
#define EMPTY_BYTE 0
#define NULL_SEG TYPED_NAME(DynArr).emptySeg
#define SEG_INSERT_POS_BEGIN 1
// Node blocks
#if _REGION_
// coordinates in the 2-D segment allocation
#define BANK_INDEX_FROM_SEG_INDEX(index) \
( ((unsigned int)(index)) >> LOG_MAXSEG )
#define BANK_FROM_SEG_INDEX(index) SEG_BANKS_ARR[BANK_INDEX_FROM_SEG_INDEX(index)]
#define SLOT_FROM_SEG_INDEX(index) (((unsigned int)(index)) & MAXSEG_REMAINDER_BITMASK)
// pointer to the segment
#define PTR_SEG_FROM_INDEX(index) \
(BANK_FROM_SEG_INDEX(index) + NUM_SEG_MEMBERS_IN_ARR * SLOT_FROM_SEG_INDEX(index) )
#endif
/* Accessor methods */
#define SEG_ARR_GET_SEG(segIndex) \
( (segIndex) != EMPTY_INDEX && \
(segIndex) >= 0 && \
(segIndex) < iInsertPos )\
? ( (tempSeg1).index = (segIndex),\
tempSeg1.nextIndex = \
(int) (SEG_ARR_SEG_NEXT_INDEX(tempSeg1)),\
tempSeg1.c = SEG_ARR_SEG_C(tempSeg1), \
tempSeg1.v = SEG_ARR_SEG_V(tempSeg1), \
tempSeg1.prev = NULL, \
tempSeg1)\
: NULL_SEG
// Region: seg banks use/create/init/cleanup
#ifdef _REGION_
#define SEG_BANKS_CREATE() \
/* NumSegBanks must be initialized at once, because it may be needed by GPU */ \
NUM_SEG_BANKS = 1; /* Default value */ \
MAX_SEG_BANKS = 1; /* Default value */ \
SEG_BANK_ALLOC_VIOLATION = 0; \
/* SEG_BANKS_INIT() must be called after/at the end of SEG_ARR_INIT() */
#define SEG_BANKS_INIT() \
/* In test mode, do not initalize MaxSegBanks here so that
it can be initialized by other code before calling SEG_BANKS_INIT() */ \
if (!TestEnabled) MaxSegBanks = 1; \
SEG_BANKS_ARR = (real_t**)malloc(MaxSegBanks * sizeof(real_t*)); \
memset(SEG_BANKS_ARR, 0, MaxSegBanks * sizeof(real_t*)); \
SEG_BANK_SIZE_ARR = (int*)malloc(MaxSegBanks * sizeof(int)); \
memset(SEG_BANK_SIZE_ARR, 0, MaxSegBanks * sizeof(int)); \
SEG_BANK_INDEX_LIMIT_ARR = (int*)malloc(MaxSegBanks * sizeof(int)); \
memset(SEG_BANK_INDEX_LIMIT_ARR, 0, MaxSegBanks * sizeof(int)); \
SEG_BANKS_ARR[0] = pSegArr + SEG_ARR_SEG_CONTENTS_OFFSET; \
SEG_BANK_SIZE_ARR[0] = MAXSEG; \
SEG_BANK_INDEX_LIMIT_ARR[0] = MAXSEG - 1; \
NumSegBanks = 1; /* one segment bank is already created */ \
SegBankAllocViolation = 0; \
#define SEG_BANKS_CLEANUP() \
for(iTempIndex1 = 1; iTempIndex1 < NUM_SEG_BANKS; iTempIndex1++){ \
FREE_SAFE(SEG_BANKS_ARR[iTempIndex1]); \
} \
FREE_SAFE(SEG_BANKS_ARR); \
FREE_SAFE(SEG_BANK_SIZE_ARR); \
FREE_SAFE(SEG_BANK_INDEX_LIMIT_ARR); \
SegBankAllocViolation = 0; \
#endif
/* DynArr methods*/
#define SEG_ARR_USE() \
extern TYPED_NAME(DynArr) DYNARR_VARS;
#define SEG_ARR_CREATE() \
TYPED_NAME(DynArr) DYNARR_VARS;\
SEG_ARR = NULL; \
SEG_INSERT_POS = SEG_INSERT_POS_BEGIN; \
FREESEG_LIST = NULL, FREESEG_INVALID_LIST = NULL; \
FREESEG_LIST_SIZE = 0; \
TEMP_FREESEGNODE_1 = NULL, TEMP_FREESEGNODE_2 = NULL; \
TEMP_INDEX_1 = 0, TEMP_INDEX_2 = 0;\
/* initialize struct types later */\
SEG_BANKS_CREATE(); \
#define SEG_ARR_INIT() \
printf("maxseg: %d, offsets... fs:%d ls:%d c:%d v:%d n:%d num_seg_arr_items:%d\n", \
MAXSEG, \
SEG_ARR_FIRSTSEG_OFFSET, \
SEG_ARR_LASTSEG_OFFSET, \
SEG_ARR_C_OFFSET, \
SEG_ARR_V_OFFSET, \
SEG_ARR_NEXT_OFFSET, \
NUM_SEG_ARR_ITEMS \
); \
/*MaxSeg should be already assigned */ \
assert(MaxSeg > 0 ); \
LogMaxSeg = (unsigned int) (log(MaxSeg+0.0f)/log(2.0f)); \
MaxSegRemainderBitMask = (unsigned int) (MaxSeg - 1); \
pSegArr = (real_t*) malloc(sizeof(real_t) * NUM_SEG_ARR_ITEMS); \
assert(pSegArr != NULL ); \
/* seg indexes: first-seg, last-seg */ \
pFirstSegIndexForPipe = (real_t*)(pSegArr + SEG_ARR_FIRSTSEG_OFFSET); \
pLastSegIndexForPipe = (real_t*)(pSegArr + SEG_ARR_LASTSEG_OFFSET); \
/* seg contents: c,v,next */ \
pSegCArr = (real_t*)(pSegArr + SEG_ARR_C_OFFSET); \
pSegVArr = (real_t*)(pSegArr + SEG_ARR_V_OFFSET); \
pSegNextArr = (real_t*)(pSegArr + SEG_ARR_NEXT_OFFSET); \
/* seg-arr management */ \
iInsertPos = SEG_INSERT_POS_BEGIN; \
pFreeSegList = NULL;\
pFreeSegInvalidList = NULL; \
memset(pSegArr, 0, sizeof(real_t) * NUM_SEG_ARR_ITEMS ); \
/* multiple segment banks */ \
SEG_BANKS_INIT(); \
//
// allocated arrays remain to be used by later timesteps
//
#define SEG_ARR_CLEANUP() \
FREE_SAFE( pSegArr ); \
_SEG_ARR_FREE_LIST_CLEANUP(); \
pSegCArr = pSegVArr = pSegNextArr = NULL; \
iInsertPos = SEG_INSERT_POS_BEGIN; \
pFirstSegIndexForPipe = NULL; \
pLastSegIndexForPipe = NULL; \
/* multiple segment banks */ \
SEG_BANKS_CLEANUP(); \
#define SEG_ARR_EXISTS() ( pSegArr != NULL )
#define SEG_ARR_SIZE NUM_SEG_ARR_ITEMS
// allocation/free
#define SEG_EPANET_FREE_SET(value_seg) \
( _SEG_ARR_FREE_LIST_ADD((value_seg)), \
TOTALSEGS_DECR(), \
SEG_ARR_SEG_NEXT_INDEX(value_seg) = (real_t) EMPTY_INDEX, \
(value_seg).index = (value_seg).nextIndex = EMPTY_INDEX \
)
#define SEG_EPANET_FREE_GET(value_seg) (\
_SEG_ARR_FREE_LIST_GRAB_INDEX((value_seg)), \
(SEG_EPANET_NOT_NULL(value_seg) ? TOTALSEGS_INCR() : 0), \
(value_seg) \
)
// should return NULL_SEG if alloc fails
#define SEG_EPANET_ALLOC(value_seg) (\
(SegBankAllocViolation) \
? ((value_seg).index = (value_seg).nextIndex = EMPTY_INDEX, (value_seg) ) \
: ( \
(value_seg).index = iInsertPos, \
(value_seg).nextIndex = EMPTY_INDEX, \
TOTALSEGS_INCR(), \
(iInsertPos >= SEG_BANK_INDEX_LIMIT_ARR[NUM_SEG_BANKS-1]) \
? /* last index filled. allocate more banks. */ \
seg_bank_alloc_next() \
? /* ok */ (void) 0 \
: /* further alloc not possible */ (\
SegBankAllocViolation = 1, \
printf("\nFatal error: No more segment allocation possible." \
"\n\tSegment index: %d, Last possible index: %d " \
"NumSegBanks: %d, MaxSegBanks: %d " \
"\n\tFile: %s\n\tLine: %d\n", \
iInsertPos, SEG_BANK_INDEX_LIMIT_ARR[CURRENT_SEG_BANK], \
NUM_SEG_BANKS, MAX_SEG_BANKS, \
__FILE__, __LINE__) \
) \
: /* last index not filled */ iInsertPos++, \
(value_seg)\
) \
) \
#endif