定义一个宏,仅在指数为整数的情况下定义 pow 函数

0 c++ macros optimization preprocessor pow

对我的 C++ 代码进行分析后,发现该pow函数被大量使用。

我的一些pow函数有一个整数指数和另一个非整数指数。我只对整数指数感兴趣。

为了提高性能,我正在寻找一种定义宏的方法,如下所示:

#define pow(x,n) ({\
    double product;\
    if (typeid(n).name() == "i") {\
    for(int i = 0; i < n-1; i++)\
        product *= x;}\
    else\
    product = pow(x,n);\
    product;\
})
Run Code Online (Sandbox Code Playgroud)

但我没有得到关于运行时间的预期收益。我认为这是由于else我的宏中我称之为经典pow函数的部分所致。

如何在预处理期间“写入”宏之前提前确定指数类型?

理想情况下,我希望仅在指数是整数时应用此宏,但似乎我的尝试不相关。

根据您的建议,我尝试了三种选择:

第一个选项:只需添加重载内联函数,其基数为integeror double

// First option
inline int pow(int x, int n){
    // using simple mechanism for repeated multiplication
    int product = 1;
    for(int i = 0; i < n; i++){
        product *= x;
    }
    return product;
}

inline int pow(double x, int n){
    // using simple mechanism for repeated multiplication
    double product = 1;
    for(int i = 0; i < n; i++){
        product *= x;
    }
    return product;
}
Run Code Online (Sandbox Code Playgroud)

结果:运行时间 = 1 分 08 秒

my_pow第二个选项:定义一​​个宏,如果指数n不是整数,则通过内联函数调用:

// Second option
inline double my_pow(double x, double n){
    return pow(x,n);
}

#define pow(x,n) ({\
    double product = 1;\
    if (typeid(n) == typeid(int)) {\
    for(int i = 0; i < n; i++)\
        product *= x;}\
    else product = my_pow(x,n);\
    product;\
})
Run Code Online (Sandbox Code Playgroud)

结果:运行时间 = 51.86 秒

第三个选项:在回答中给出的建议template<typename type_t>

template<typename type_t>
inline double pow(const double x, type_t n)
{
    // This is compile time checking of types.
    // Don't use the RTTI thing you are trying to do
    //if constexpr (is_floating_point_v<type_t>)
    if (typeid(n) != typeid(int))
    {
        return pow(x, n);
    }
    else
    {
        double value = 1;
        for (type_t i = 0; i < n; ++i) value *= x;
        return value;
    }
}
Run Code Online (Sandbox Code Playgroud)

结果:运行时间 = 52.84 秒

pow因此,最后,从这些第一个测试中,最好的选择是第二个,其中我将宏与调用函数的一般情况(整数和浮点指数)的函数结合使用。

是否有更有效的解决方案或者第二个选项是最好的?

P K*_*mer 14

如果您只需要在浮点类型之间切换,则可以使用模板而不是宏。

#include <cassert>
#include <cmath>
#include <type_traits>

namespace my_math
{
    template<typename type_t>
    inline double pow(const double x, type_t n)
    {
        // this is compile time checking of types
        // don't use the rtti thing you are trying to do 
        if constexpr (std::is_floating_point_v<type_t>)
        {
            return std::pow(x, n);
        }
        else
        {
            double value = 1;
            for (type_t i = 0; i < n; ++i) value *= x;
            return value;
        }
    };

}

int main()
{
    assert(my_math::pow(2, 0) == 1);
    assert(my_math::pow(2.0, 1) == 2.0);
    assert(my_math::pow(3.0, 2.0) == 9.0);
    assert(my_math::pow(4.0f, 3.0f) == 64.0f);

   return 0;
}
Run Code Online (Sandbox Code Playgroud)