diff --git a/qpms/indexing.h b/qpms/indexing.h index f32679e..59e90eb 100644 --- a/qpms/indexing.h +++ b/qpms/indexing.h @@ -6,6 +6,7 @@ #include "qpms_types.h" #include +#include "optim.h" @@ -72,8 +73,8 @@ static inline qpms_errno_t qpms_uvswfi2tmn(qpms_uvswfi_t u, qpms_y_sc_t y_sc = u / 4; qpms_y2mn_sc_p(y_sc, m, n); // Test validity - if (*t == 3) return QPMS_ERROR; // VSWF type code invalid, TODO WARN - if (*t && !y_sc) return QPMS_ERROR; // l == 0 for transversal wave, TODO WARN + if (QPMS_UNLIKELY(*t == 3)) return QPMS_ERROR; // VSWF type code invalid, TODO WARN + if (QPMS_UNLIKELY(*t && !y_sc)) return QPMS_ERROR; // l == 0 for transversal wave, TODO WARN return QPMS_SUCCESS; } @@ -83,8 +84,8 @@ static inline qpms_errno_t qpms_uvswfi2ty(qpms_uvswfi_t u, qpms_vswf_type_t *t, qpms_y_t *y) { *t = u & 3; *y = u / 4 - 1; - if (*t == 0 || *t == 3) return QPMS_ERROR; - if (*y < 0) return QPMS_ERROR; + if (QPMS_UNLIKELY(*t == 0 || *t == 3)) return QPMS_ERROR; + if (QPMS_UNLIKELY(*y < 0)) return QPMS_ERROR; return QPMS_SUCCESS; } @@ -96,8 +97,8 @@ static inline qpms_errno_t qpms_uvswfi2ty_l(qpms_uvswfi_t u, qpms_vswf_type_t *t, qpms_y_t *y) { *t = u & 3; *y = u / 4 - 1; - if (*t == 3) return QPMS_ERROR; - if (*y < 0) return QPMS_ERROR; + if (QPMS_UNLIKELY(*t == 3)) return QPMS_ERROR; + if (QPMS_UNLIKELY(*y < 0)) return QPMS_ERROR; return QPMS_SUCCESS; } diff --git a/qpms/normalisation.h b/qpms/normalisation.h index 5ab7099..f84f546 100644 --- a/qpms/normalisation.h +++ b/qpms/normalisation.h @@ -11,11 +11,12 @@ #include #include #include "indexing.h" +#include "optim.h" /// Returns the (real positive) common norm factor of a given normalisation compared to the reference convention. /** Does NOT perform the inversion if QPMS_NORMALISATION_INVERSE is set. */ static inline double qpms_normalisation_normfactor(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m) { - switch (norm & QPMS_NORMALISATION_NORM_BITS) { + switch (QPMS_EXPECT(norm & QPMS_NORMALISATION_NORM_BITS, norm & QPMS_NORMALISATION_DEFAULT)) { case QPMS_NORMALISATION_NORM_POWER: return 1; case QPMS_NORMALISATION_NORM_SPHARM: @@ -37,9 +38,9 @@ static inline double qpms_normalisation_normfactor(qpms_normalisation_t norm, qp */ static inline complex double qpms_normalisation_factor_M_noCS(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m) { complex double fac = qpms_normalisation_normfactor(norm, l, m); - if (norm & QPMS_NORMALISATION_M_MINUS) fac *= -1; - if (norm & QPMS_NORMALISATION_M_I) fac *= I; - if (norm & QPMS_NORMALISATION_INVERSE) fac = 1/fac; + if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_M_MINUS)) fac *= -1; + if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_M_I)) fac *= I; + if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_INVERSE)) fac = 1/fac; return fac; } @@ -63,9 +64,9 @@ static inline complex double qpms_normalisation_factor_M(qpms_normalisation_t no */ static inline complex double qpms_normalisation_factor_N_noCS(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m) { complex double fac = qpms_normalisation_normfactor(norm, l, m); - if (norm & QPMS_NORMALISATION_N_MINUS) fac *= -1; - if (norm & QPMS_NORMALISATION_N_I) fac *= I; - if (norm & QPMS_NORMALISATION_INVERSE) fac = 1/fac; + if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_N_MINUS)) fac *= -1; + if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_N_I)) fac *= I; + if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_INVERSE)) fac = 1/fac; return fac; } @@ -96,9 +97,9 @@ static inline complex double qpms_normalisation_factor_N_M(qpms_normalisation_t */ static inline complex double qpms_normalisation_factor_L_noCS(qpms_normalisation_t norm, qpms_l_t l, qpms_m_t m) { complex double fac = qpms_normalisation_normfactor(norm, l, m); - if (norm & QPMS_NORMALISATION_L_MINUS) fac *= -1; - if (norm & QPMS_NORMALISATION_L_I) fac *= I; - if (norm & QPMS_NORMALISATION_INVERSE) fac = 1/fac; + if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_L_MINUS)) fac *= -1; + if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_L_I)) fac *= I; + if (QPMS_UNLIKELY(norm & QPMS_NORMALISATION_INVERSE)) fac = 1/fac; return fac; } @@ -156,7 +157,8 @@ static inline qpms_normalisation_t qpms_normalisation_dual(qpms_normalisation_t * \f] */ static inline complex double qpms_spharm_azimuthal_part(qpms_normalisation_t norm, qpms_m_t m, double phi) { - switch(norm & (QPMS_NORMALISATION_REVERSE_AZIMUTHAL_PHASE | QPMS_NORMALISATION_SPHARM_REAL)) { + switch(QPMS_EXPECT(norm, QPMS_NORMALISATION_DEFAULT) + & (QPMS_NORMALISATION_REVERSE_AZIMUTHAL_PHASE | QPMS_NORMALISATION_SPHARM_REAL)) { case 0: return cexp(I*m*phi); case QPMS_NORMALISATION_REVERSE_AZIMUTHAL_PHASE: @@ -194,7 +196,8 @@ static inline complex double qpms_spharm_azimuthal_part(qpms_normalisation_t nor */ static inline complex double qpms_spharm_azimuthal_part_derivative_div_m(qpms_normalisation_t norm, qpms_m_t m, double phi) { if(m==0) return 0; - switch(norm & (QPMS_NORMALISATION_REVERSE_AZIMUTHAL_PHASE | QPMS_NORMALISATION_SPHARM_REAL)) { + switch(QPMS_EXPECT(norm, QPMS_NORMALISATION_DEFAULT) + & (QPMS_NORMALISATION_REVERSE_AZIMUTHAL_PHASE | QPMS_NORMALISATION_SPHARM_REAL)) { case 0: return I*cexp(I*m*phi); case QPMS_NORMALISATION_REVERSE_AZIMUTHAL_PHASE: diff --git a/qpms/optim.h b/qpms/optim.h new file mode 100644 index 0000000..44e14c8 --- /dev/null +++ b/qpms/optim.h @@ -0,0 +1,22 @@ +/** \file optim.h + * \brief Macros for compiler optimisation. + */ +#ifndef QPMS_OPTIM_H +#define QPMS_OPTIM_H + + +#if ((defined __GNUC__) || (defined __clang__)) && !(defined QPMS_NO_BUILTIN_EXPECT) +/// Wrapper over gcc's and clang's __builtin_expect. +/** If expands to __builtin_expect if gcc or clang are used, + * else expands only to the first argument. + */ +#define QPMS_EXPECT(exp, c) __builtin_expect(exp, c) +#define QPMS_LIKELY(x) __builtin_expect(!!(x), 1) +#define QPMS_UNLIKELY(x) __builtin_expect(!!(x), 0) +#else +#define QPMS_LIKELY(x) (x) +#define QPMS_UNLIKELY(x) +#define QPMS_EXPECT(exp,c) (exp) +#endif + +#endif // OPTIM_H