Last active
March 22, 2017 07:38
-
-
Save bojanpotocnik/8007bae05ad8d16b8a875457708d159c to your computer and use it in GitHub Desktop.
Various C utility macros
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* compiler_utils.h | |
* | |
* Created: 2016, 2017 | |
* Author: Bojan Potocnik | |
* [email protected] | |
*/ | |
#ifndef COMPILER_UTILS_H__ | |
#define COMPILER_UTILS_H__ | |
#include <stddef.h> /*< size_t */ | |
#include <float.h> /*< FLT_EPSILON */ | |
#ifndef min | |
__attribute__((__const__, __unused__, __weak__)) | |
static inline int min(const int a, const int b) { | |
return (a < b ? a : b); | |
} | |
#endif /* min */ | |
#ifndef max | |
__attribute__((__const__, __unused__, __weak__)) | |
static inline int max(const int a, const int b) { | |
return (a > b ? a : b); | |
} | |
#endif /* max */ | |
#ifndef MIN | |
#define MIN(a, b) (a < b ? a : b) | |
#endif | |
#ifndef MAX | |
#define MAX(a, b) (a < b ? b : a) | |
#endif | |
#if defined(__CC_ARM) | |
/* Always set to 1 for the ARM compiler, even when you specify the --thumb option. | |
* Note: This macro is also defined if you invoke the ARM compiler using armcpp, tcc, and tcpp. */ | |
#define WEAK __weak | |
#define STR(x) x | |
#define ATTR_ISR __attribute__((__used__)) | |
#elif defined(__GNUC__) | |
/* These macros are defined by all GNU compilers that use the C preprocessor: C, C++, Objective-C and Fortran. | |
* Even when using ARM compiler, defined when the --gnu option is specified. | |
* It is an integer that shows the current major version of the GNU mode being used. */ | |
#define WEAK __attribute__((__weak__)) | |
/** | |
* @brief Print integer value of preprocessor macro (or it's name if value is not defined). | |
* GCC double expansion trick is used for stringifying the integer value. | |
* | |
* @param Preprocessor definition of integer value. | |
* @return Stringified representation of integer value. | |
*/ | |
#define STR(x) _STR(x) | |
#define _STR(x) #x | |
#define ATTR_ISR __attribute__((__interrupt_handler__, __used__)) | |
#endif | |
/** | |
* @brief Check if integer value is a power of 2. | |
* | |
* @param N An integer value to be checked. | |
* | |
* @return True if integer is a power of two. | |
*/ | |
#define IS_POWER_OF_2(N) (((N) & ((N) - 1)) == 0) | |
/** | |
* @brief Calculate power of 2 (2 to the power of n). | |
* | |
* @param N A power (potency). | |
* | |
* @return Two to the power of n (2^n). | |
*/ | |
#define POW_2(N) (1 << (N)) | |
/** | |
* @brief Round a number (+0.5 = 1, -0.5 = -1). Cast to integer type is mandatory to achieve desired result. | |
* | |
* @param N The number to be rounded. | |
* | |
* @return Rounded number. Cast to integer type is mandatory to achieve desired result. | |
*/ | |
#define ROUND(N) ( ((N) >= 0) ? (N) + 0.5f : (N) - 0.5f ) | |
/** | |
* @brief Rounds up a positive number. Cast to integer type is mandatory to achieve desired result. | |
* | |
* @param N A positive number to be rounded. | |
* | |
* @return Up-rounded number. Cast to integer type is mandatory to achieve desired result. | |
*/ | |
#define ROUND_UP_POS(N) ( ((float) (N)) + (1.0f - FLT_EPSILON) ) | |
/** | |
* @brief Rounds up a negative number. Cast to integer type is mandatory to achieve desired result. | |
* | |
* @param N A negative number to be rounded. | |
* | |
* @return Up-rounded number. Cast to integer type is mandatory to achieve desired result. | |
*/ | |
#define ROUND_UP_NEG(N) (N) | |
/** | |
* @brief Rounds down a positive number. Cast to integer type is mandatory to achieve desired result. | |
* | |
* @param N A positive number to be rounded. | |
* | |
* @return Down-rounded number. Cast to integer type is mandatory to achieve desired result. | |
*/ | |
#define ROUND_DOWN_POS(N) (N) | |
/** | |
* @brief Rounds down a negative number. Cast to integer type is mandatory to achieve desired result. | |
* | |
* @param N A negative number to be rounded. | |
* | |
* @return Down-rounded number. Cast to integer type is mandatory to achieve desired result. | |
*/ | |
#define ROUND_DOWN_NEG(N) ( ((float) (N)) - (1.0 - FLT_EPSILON) ) | |
/** | |
* @brief Rounds a number up. Cast to integer type is mandatory to achieve desired result. | |
* | |
* @param N A number to be rounded. | |
* | |
* @return Up-rounded number. Cast to integer type is mandatory to achieve desired result. | |
*/ | |
#define ROUND_UP(N) ( ((N) >= 0) ? ROUND_UP_POS(N) : ROUND_UP_NEG(N) ) | |
/** | |
* @brief Rounds a number down. Cast to integer type is mandatory to achieve desired result. | |
* | |
* @param N A number to be rounded. | |
* | |
* @return Down-rounded number. Cast to integer type is mandatory to achieve desired result. | |
*/ | |
#define ROUND_DOWN(N) ( ((N) >= 0) ? ROUND_DOWN_POS(N) : ROUND_DOWN_NEG(N) ) | |
/** | |
* @brief Rounds a number towards 0. Cast to integer type is mandatory to achieve desired result. | |
* | |
* @param N A number to be rounded. | |
* | |
* @return Rounded number. Cast to integer type is mandatory to achieve desired result. | |
*/ | |
#define ROUND_TOWARDS_0(N) ( ((N) >= 0) ? ROUND_DOWN_POS(N) : ROUND_UP_NEG(N) ) | |
/** | |
* @brief Rounds a number away from 0. Cast to integer type is mandatory to achieve desired result. | |
* | |
* @param N A number to be rounded. | |
* | |
* @return Rounded number. Cast to integer type is mandatory to achieve desired result. | |
*/ | |
#define ROUND_AWAY_FROM_0(N) (((N) >= 0) ? ROUND_UP_POS(N) : ROUND_DOWN_NEG(N)) | |
#if 0 | |
// TODO | |
/** | |
* @brief Rounds a positive number up to the nearest multiple of significance. | |
* | |
* @param N A positive number to be rounded. | |
* @param s The multiple to which the number is to be rounded. | |
* | |
* @return Up-rounded number (the smallest possible z which satisfies: z * y >= x). | |
*/ | |
#define CEILING(N, S) (((x) + (s) - 1) / (s)) | |
/** | |
* @brief Rounds a positive number up to the nearest multiple of significance. | |
* | |
* @param x A positive number to be rounded. | |
* @param s The multiple to which the number is to be rounded. | |
* | |
* @return Up-rounded number (the smallest possible z which satisfies: z * y >= x). | |
*/ | |
#define ROUND_UPfff(N, S) ((((N) + (S) - 1) / (S)) * (S)) | |
#endif | |
/** | |
* @brief Generates compiler error if condition is 0 or false. | |
* | |
* Original version generates compiler error if condition is not exactly 0. | |
* ((void)sizeof(char[1 - 2*!!(condition)])) | |
*/ | |
#define ASSERT_BUG(condition, description) ((void)sizeof(char[1 - 2*!!((unsigned char) !(condition))])) | |
/** | |
* @brief Generates compiler error if condition is 0 or false. | |
*/ | |
#define ASSERT_BUG_FUNCTION(condition, description) \ | |
static inline __attribute__((__unused__, __always_inline__)) \ | |
void __compiler_assert_##__FILE__##__LINE__(void) { \ | |
ASSERT_BUG(condition, description); \ | |
} | |
/** | |
* @brief Get length of the array. | |
* | |
* Taken from Google Chromium's codebase. | |
* This version improves on the array[0] or *array version by using 0[array], which is equivalent | |
* to array[0] on plain arrays, but will fail to compile if array happens to be a C++ type that | |
* overloads operator[](). | |
* Also, if a pointer is mistakenly passed as the argument, the compiler will complain in some | |
* cases - specifically if the pointer's size isn't evenly divisible by the size of the object | |
* the pointer points to. In that situation a divide-by-zero will cause the compiler to error out. | |
* The division causes a divide-by-zero operation (that should be caught at compile time since | |
* it's a compile-time constant expression) for many (but not all) situations where a pointer is | |
* passed as the array parameter. | |
* | |
* @return Count of the array elements. | |
*/ | |
#define COUNT_OF(array) ((sizeof(array) / sizeof(0[array])) / ((size_t)(!(sizeof(array) % sizeof(0[array]))))) | |
/** | |
* @brief Get size (in bytes) of the member of the structure. | |
* | |
* The operand of sizeof is not evaluated, so there is no issue with dereferencing the null | |
* pointer (because it isn't actually dereferenced). | |
* | |
* @return sizeof() of the member of the structre. | |
*/ | |
#define sizeof_member(type, member) sizeof(((type *)0)->member) | |
// TODO: | |
#define ABS(x) ((x) < 0 ? -(x) : (x)) | |
#endif /* COMPILER_UTILS_H__ */ | |
/* [] END OF FILE */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment