在C库math.h
中,有一个非常有效的sincos
函数,因为它在接近sin()
或{{{{}}的单个调用的时间内计算了正弦和余弦。 1}}而不是调用两者的总时间。
C ++标准库中是否有这样的功能?
答案 0 :(得分:7)
答案 1 :(得分:2)
分别使用sin和cos并启用优化。 C编译器非常擅长优化,他们可能会意识到你正在计算同一个变量的正弦和余弦。如果你想确定,你可以继续检查生成的程序集(对于gcc使用-S选项)并查看它生成了什么。
编译器可能会优化掉对sin
或cos
的任何调用,转而使用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);
}