This document is a part of a larger collection of macros. For introductory remarks, see the first part (General Purpose Macros).
For a review of macro-syntax rules and related tips and tricks, see Writing Macros.
Basic Relations
Code:
#define mIsEQ(a,b) ((a)==(b))
#define mIsLT(a,b) ((a)<(b))
#define mIsLE(a,b) ((a)<=(b))
#define mIsGT(a,b) ((a)>(b))
#define mIsGE(a,b) ((a)>=(b))
#define mCompare(a,b) (mIsEQ(a,b) ? 0 : (mIsLT(a,b) ? -1 : 1))
Arguments:
a and b must be of a type which is compatible with relational operators.
These macros provide enhanced-readability for basic comparisons between objects of any type for which the relational operators have been defined.
Sorting
Code:
#define mSort(lvA,lvB,lvAux)
{if (mIsLT(lvB,lvA)) mSwap(lvA,lvB,lvAux);}
#define mSort2(lvA,lvB,lvAux) mSort(lvA,lvB,lvAux)
#define mSort3(lvA,lvB,lvC,lvAux) \
{mSort(lvB,lvC,lvAux);mSort(lvA,lvB,lvAux);mSort(lvB,lvC,lvAux);}
#define mSort4(lvA,lvB,lvC,lvD,lvAux) \
{mSort3(lvA,lvB,lvC,lvAux); \
if (mIsLT(lvD,lvA)) mRotate4(lvA,lvB,lvC,lvD,lvAux); \
else if (mIsLT(lvD,lvB)) mRotate3(lvB,lvC,lvD,lvAux); \
else if (mIsLT(lvD,lvC)) mRotate2(lvC,lvD,lvAux);}
#define mSort5(lvA,lvB,lvC,lvD,lvE,lvAux) \
{mSort4(lvA,lvB,lvC,lvD,lvAux); \
if (mIsLT(lvE,lvA)) mRotate5(lvA,lvB,lvC,lvD,lvE,lvAux); \
else if (mIsLT(lvE,lvB)) mRotate4(lvB,lvC,lvD,lvE,lvAux); \
else if (mIsLT(lvE,lvC)) mRotate3(lvC,lvD,lvE,lvAux); \
else if (mIsLT(lvE,lvD)) mRotate2(lvD,lvE,lvAux);}
#define mSort6(lvA,lvB,lvC,lvD,lvE,lvF,lvAux) \
{mSort5(lvA,lvB,lvC,lvD,lvE,lvAux); \
if (mIsLT(lvF,lvA)) mRotate6(lvA,lvB,lvC,lvD,lvE,LvF,lvAux); \
else if (mIsLT(lvF,lvB)) mRotate5(lvB,lvC,lvD,lvE,lvFlvAux); \
else if (mIsLT(lvF,lvC)) mRotate4(lvC,lvD,lvE,lvF,lvAux); \
else if (mIsLT(lvF,lvD)) mRotate3(lvD,lvE,lvF,lvAux); \
else if (mIsLT(lvF,lvE)) mRotate2(lvE,lvF,lvAux);}
Arguments:
lvA through lvF are the objects to be sorted.
lvAux is an auxiliary object.
Ideally, all the arguments (including lvAux) should be of the same type.
They must be assignable, lvalue entities which admit the relational operator <
The return values of these macros (as well as the exit values of lvAux) are dynamically dependent on the contents of the sorted entities. Consequently, the macros should not be used as constituent parts of expressions.
Comparisons with zero
Code:
#define mIsNegative(s) (mIsLT(s,0))
#define mIsNonPositive(s) (mIsLE(s,0))
#define mIsPositive(s) (mIsGT(s,0))
#define mIsNonNegative(s) (mIsGE(s,0))
Arguments:
s is any argument of a type for which relational comparisons to zero are defined and make sense.
These macros provide enhanced-readability shorthand for sign-related properties.
Sign Functions
Code:
#define mSign(x) (mIsNegative(x)?-1:1)
#define mSignsAgree(x,y) (mIsNegative(x)? (mIsNegative(y)?1:0):(mIsNegative(y)?0:1))
#define mSignsDiffer(x,y) (mIsNegative(x)? (mIsNegative(y)?0:1):(mIsNegative(y)?1:0))
#define mAbs(x) (mIsNegative(x)?-(x):(x))
#define mMinusAbs(x) (mIsNegative(x)?(x):-(x))
#define mMultiplyBySign(x,s) (mIsNegative(s)?-(x):(x))
#define mAttachSign(x,s)
(mIsNegative(s)?mMinusAbs(x):mAbs(x))
Arguments:
x, y and s are arguments of any types for which comparisons with zero are defined and make sense.