c ++ libstd同时计算sin和cos

时间:2014-06-20 13:14:48

标签: c++ math libstdc++ sin cos

在C库math.h中,有一个非常有效的sincos函数,因为它在接近sin()或{{{{}}的单个调用的时间内计算了正弦和余弦。 1}}而不是调用两者的总时间。

C ++标准库中是否有这样的功能?

4 个答案:

答案 0 :(得分:7)

  

c ++标准库中没有这样的功能吗?

不,不幸的是没有。

  

在C库math.h中,有一个sincos函数

在Linux上,它以GNU Extension的形式提供。它在C中也不是标准。

答案 1 :(得分:2)

分别使用sin和cos并启用优化。 C编译器非常擅长优化,他们可能会意识到你正在计算同一个变量的正弦和余弦。如果你想确定,你可以继续检查生成的程序集(对于gcc使用-S选项)并查看它生成了什么。

编译器可能会优化掉对sincos的任何调用,转而使用SSE intructions来计算它。我不确定SSE是否有sincos操作码,但即使分别计算它们也比调用编译器不会优化的任何sincos函数更快。

答案 2 :(得分:2)

虽然没有标准的C ++库函数,但是您可以快速定义模板函数:

template <class S>
std::pair<S,S> sincos(S arg) { return { std::sin(arg), std::cos(arg) }; }

然后,您可以使用以下命令在一行中(使用C ++ 17)获得结果:

auto [s, c] = sincos(arg);

如果您经常执行此操作,节省空间并具有自记录功能,这将非常方便,因此,我强烈建议您这样做。 如果您担心性能,请不要担心。使用优化进行编译时,它应产生与分别调用sin和cos完全相同的代码。您可以通过以下测试代码上的clang++ -std=c++17 -S -o - -c -O3 sincos.cpp确认是这种情况:

#include <cmath>
#include <utility>
#include <iostream>

template <class S>
std::pair<S,S> sincos(S arg) { return { std::sin(arg), std::cos(arg) }; }

void testPair(double a) {
    auto [s,c] = sincos(a);
    std::cout << s << ", " << c << '\n';
}

void testSeparate(double a) {
    double s = std::sin(a);
    double c = std::cos(a);
    std::cout << s << ", " << c << '\n';
}

在带有clang的MacOS上,两个测试函数都编译为完全相同的程序集(减去名称更改),该程序集调用___sincos_stret来执行组合计算(请参见https://stackoverflow.com/a/19017286/973580)。

答案 3 :(得分:0)

相反,你可以使用这个只使用 std::cos 和 std::sqrt 的函数(还没有实际测试过,它可能不起作用)

template <typename T>
constexpr inline static void sincos(const T &x, T* sin, T* cos) {
    (*cos) = std::cos(x);
    (*sin) = std::sqrt(static_cast<T>(1) - *cos**cos);
    if ((int)(x / M_PI) & 1) (*sin) = -(*sin);
}