/* * CS5600 University of Utah * Charles McGarvey * mcgarvey@eng.utah.edu */ #ifndef _COMMON_H_ #define _COMMON_H_ #include #include #include #include #include #include #include "config.h" /* * Define a keyword for use while defining small and fast functions. */ #if EXTRA_INLINE #define INLINE_MAYBE static inline #else #define INLINE_MAYBE static #endif /* * Define a type for scalar values, either float or double. */ #if DOUBLE_FLOAT typedef double scal_t; #define SCALAR_SIZE 8 #define S(K) K #define scal_floor floor #define scal_ceil ceil #define scal_min fmin #define scal_max fmax #define scal_abs fabs #define scal_pow pow #define scal_sqrt sqrt #define scal_sin sin #define scal_cos cos #define scal_tan tan #define scal_asin asin #define scal_acos acos #define scal_atan atan #else typedef float scal_t; #define SCALAR_SIZE 4 #define S(K) K##f #define scal_floor floorf #define scal_ceil ceilf #define scal_min fminf #define scal_max fmaxf #define scal_abs fabsf #define scal_pow powf #define scal_sqrt sqrtf #define scal_sin sinf #define scal_cos cosf #define scal_tan tanf #define scal_asin asinf #define scal_acos acosf #define scal_atan atanf #endif #define scal_min2(A,B,C) scal_min(scal_min(A,B),C) #define scal_max2(A,B,C) scal_max(scal_max(A,B),C) #define SCAL_EPSILON (S(0.000001)) /* * Check if two scalars are mostly equal, given a margin of error. */ INLINE_MAYBE bool scal_isequal2(scal_t a, scal_t b, scal_t e) { return scal_abs(a -b) < e; } /* * Check if two scalars are mostly equal. */ INLINE_MAYBE bool scal_isequal(scal_t a, scal_t b) { return scal_isequal2(a, b, SCAL_EPSILON); } /* * Clamp a scalar between two values. */ INLINE_MAYBE scal_t scal_clamp(scal_t s, scal_t min, scal_t max) { if (s < min) { return min; } if (max < s) { return max; } return s; } /* * Define min and max functions for integers. */ INLINE_MAYBE int imin(int a, int b) { return a < b ? a : b; } INLINE_MAYBE int imax(int a, int b) { return a < b ? b : a; } /* * Define some macros for packing and unpacking bytes to and from larger ints. */ #define PACK(W,N,B) (((B) << (8 * (N))) | ((W) & ~(0xff << (8 * (N))))) #define UNPACK(W,N) ((uint8_t)((W) >> (8 * (N))) & 0xff) /* * Try to execute a statement and print a status message. If the statement * resolves to 0, it is considered to have succeeded; any other evaluation is * an error condition and an abort(3) occurs. * return. */ #if VERBOSITY >= 1 #define TRY_DO(L, K, ARGS...) \ printf("* " L "... ", ##ARGS); \ fflush(stdout); \ if ((K) == 0) printf("done!\n"); \ else abort() #else #define TRY_DO(L, K, ARGS...) \ if ((K) != 0) abort() #endif /* * Declare a type of destructor functions. */ typedef void (*dtor_t)(void*); #define DTOR(A) (dtor_t)(A) /* * Allocate a block of memory of a certain size. This follows the semantics * of malloc(3), except it will never return NULL and will abort(3) if the * memory could not be allocated. */ void* mem_alloc(size_t size); /* * Change the size of a block of memory. This follows the semantics of * realloc(3), except it will never return NULL and will abort(3) if the * memory could not be allocated. */ void* mem_realloc(void* mem, size_t size); /* * Deallocate a block of memory previously allocated by mem_alloc or malloc(3) * and friends. This is essentially just a call to free(3). */ void mem_free(void* mem); /* * Set a function to call if either mem_alloc or mem_realloc fails, or NULL if * no callback should be called. The callback takes the same arguments as * realloc(3) and may try to fulfill the request. The return value of the * callback function will be returned from the allocation function and must be * a valid pointer to an allocated block of memory. The callback function * should not call mem_alloc or mem_realloc and must not return if a block of * memory could not be allocated. */ void mem_set_fn(void* (*fn)(void*, size_t)); /* * Get the number of blocks currently allocated with either mem_alloc or * mem_realloc. This number should be zero at the end of a process running * this program. */ int mem_blocks(); /* * Duplicate a string; like the non-standard strdup(3) but uses mem_alloc. * The result needs to be freed with mem_free. */ INLINE_MAYBE char* mem_strdup(const char* str) { size_t size = strlen(str) + 1; return (char*)memcpy(mem_alloc(size), str, size); } /* * Get an allocated string made up of two strings concatenated together. * The result needs to be freed with mem_free. */ INLINE_MAYBE char* mem_strcat(const char* str1, const char* str2) { size_t size1 = strlen(str1); size_t size2 = strlen(str2); char* str = (char*)mem_alloc(size1 + size2 + 1); memcpy(str + size1, str2, size2 + 1); return memcpy(str, str1, size1); } /* * Cut a string short at the last matching character. The string will be * modified if the character was matched. Either way, str is returned. */ INLINE_MAYBE char* strcut(char* str, int c) { char* ptr = strrchr(str, c); if (ptr != NULL) { *ptr = '\0'; } return str; } /* * Trim white space off of the right side of a string. */ void rtrim(char *str); /* * Trim white space off of the left side of a string. */ void ltrim(char *str); /* * Trim white space off of both sides of a string. */ INLINE_MAYBE void trim(char *str) { rtrim(str); ltrim(str); } /* * Initialize the timer. */ void timer_start(); /* * Stop the timer and return how many microseconds passed after * initialization. */ long timer_stop(); #endif // _COMMON_H_