//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // PPPPP H H EEEEE N N GGGGG L EEEEE III + // P P H H E NN N G L E I + // PPPPP HHHHH EEEEE N N N G GG L EEEEE I + // P H H E N N N G G L E I + // P H H EEEEE N N GGGGG LLLLL EEEEE III + //------------------------------------------------------------------------+ // Platform for Hybrid Engineering Simulation of Flows + // China Aerodynamics Research and Development Center + // (C) Copyright, Since 2010 + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //! @file PHOps.h //! @brief Explain this file briefly. //! @author He Xin. namespace PHSPACE { template struct autopromote_trait { typedef T T_numtype; }; template struct promote2 { typedef T1 T_promote; }; template struct promote2 { typedef T2 T_promote; }; /* * This compiler supports partial specialization, so type promotion * can be done the elegant way. This implementation is after ideas * by Jean-Louis Leroy. */ template struct precision_trait { static const int precisionRank = 0; static const bool knowPrecisionRank = false; }; template struct promote_trait { //! Handle promotion of small integers to int/unsigned int. typedef typename autopromote_trait::T_numtype T1; typedef typename autopromote_trait::T_numtype T2; //! True if T1 is higher ranked. static const bool T1IsBetter = precision_trait::precisionRank > precision_trait::precisionRank; //! True if we know ranks for both T1 and T2. static const bool knowBothRanks = precision_trait::knowPrecisionRank && precision_trait::knowPrecisionRank; //! True if we know T1 but not T2. static const bool knowT1butNotT2 = precision_trait::knowPrecisionRank && !precision_trait::knowPrecisionRank; //! True if we know T2 but not T1. static const bool knowT2butNotT1 = precision_trait::knowPrecisionRank && !precision_trait::knowPrecisionRank; //! True if T1 is bigger than T2. static const bool T1IsLarger = sizeof(T1) >= sizeof(T2); //! We know T1 but not T2: false. //! We know T2 but not T1: true. //! Otherwise, if T1 is bigger than T2: true. //! static const bool. //defaultPromotion = knowT1butNotT2 ? false : (knowT2butNotT1 ? true : T1IsLarger); //! If we have both ranks, then use them. //! If we have only one rank, then use the unknown type. //! If we have neither rank, then promote to the larger type. static const bool promoteToT1 = knowBothRanks ? T1IsBetter : (knowT1butNotT2 ? false : (knowT2butNotT1 ? true : T1IsLarger)); typedef typename promote2::T_promote T_promote; }; //#define PH_PROMOTE(A,B) A #define PH_PROMOTE(A, B) typename promote_trait::T_promote #define PH_DEFINE_UNARY_OP(name, op) \ template \ struct name \ { \ typedef T_numtype1 T_numtype; \ \ static inline T_numtype \ apply(T_numtype1 a) \ { \ return op a; \ } \ \ }; #define PH_DEFINE_BINARY_OPERATION(name, op) \ template \ struct name \ { \ typedef PH_PROMOTE(T_numtype1, T_numtype2) T_numtype; \ \ static inline T_numtype \ apply(T_numtype1 a, T_numtype2 b) \ { \ return a op b; \ } \ \ }; #define PH_DEFINE_BINARY_FUNCTION(name, functor) \ template \ struct name \ { \ typedef PH_PROMOTE(T_numtype1, T_numtype2) T_numtype; \ \ static inline T_numtype \ apply(T_numtype1 a, T_numtype2 b) \ { \ return functor(a, b); \ } \ \ }; PH_DEFINE_UNARY_OP(UnaryPlus , +) PH_DEFINE_UNARY_OP(UnaryMinus, -) PH_DEFINE_BINARY_OPERATION(Add , +) PH_DEFINE_BINARY_OPERATION(Subtract, -) PH_DEFINE_BINARY_OPERATION(Multiply, *) PH_DEFINE_BINARY_OPERATION(Divide , /) }