C++ arcsin和arccos通常是如何实现的?

C++ arcsin和arccos通常是如何实现的?,c++,performance,assembly,x86,trigonometry,C++,Performance,Assembly,X86,Trigonometry,我正在阅读Agner的x86和x87汇编代码列表,注意到Arcin或arccos没有操作代码,只有arctan。所以我已经用Google和所有的结果使用ATAN和SqRT实现了这意味着ACOS和ASIN应该比ATAN慢得多,因为你需要一个额外的Sqt,但是我在C++中写了一个简单的测试程序,ACOS和asin都比ATAN:快。 #include <chrono> #include <cmath> #include <iostream> class timer

我正在阅读Agner的x86和x87汇编代码列表,注意到Arcin或arccos没有操作代码,只有arctan。所以我已经用Google和所有的结果使用ATAN和SqRT实现了这意味着ACOS和ASIN应该比ATAN慢得多,因为你需要一个额外的Sqt,但是我在C++中写了一个简单的测试程序,ACOS和asin都比ATAN:

快。
#include <chrono>
#include <cmath>
#include <iostream>

class timer {
    private:
        decltype(std::chrono::high_resolution_clock::now()) begin, end;

    public:
        void
        start() {
            begin = std::chrono::high_resolution_clock::now();
        }

        void
        stop() {
            end = std::chrono::high_resolution_clock::now();
        }

        template<typename T>
        auto
        duration() const {
            return std::chrono::duration_cast<T>(end - begin).count();
        }

        auto
        nanoseconds() const {
            return duration<std::chrono::nanoseconds>();
        }

        void
        printNS(char const* str) const {
            std::cout << str << ": " << nanoseconds() << std::endl;
        }
};

int
main(int argc, char**) {
    timer timer;

    double p1 = 0 + 0.000000001;
    double acc1{1};

    timer.start();
    //less than 8 seconds
    for(int i{0}; 200000000 > i; ++i) {
        acc1 += std::acos(i * p1);
    }
    timer.stop();
    timer.printNS("acos");

    timer.start();
    //less than 8 seconds
    for(int i{0}; 200000000 > i; ++i) {
        acc1 += std::asin(i * p1);
    }
    timer.stop();
    timer.printNS("asin");

    timer.start();
    //more than 12 seconds
    for(int i{0}; 200000000 > i; ++i) {
        acc1 += std::atan(i * p1);
    }
    timer.stop();
    timer.printNS("atan");

    timer.start();
    //almost 20 seconds
    for(int i{0}; 200000000 > i; ++i) {
        acc1 += std::atan2(i * p1, i * p1);
    }
    timer.stop();
    timer.printNS("atan");

    std::cout << acc1 << '\n';
}
#包括
#包括
#包括
班级计时器{
私人:
decltype(std::chrono::high_resolution_clock::now())开始,结束;
公众:
无效的
开始(){
begin=std::chrono::高分辨率时钟::现在();
}
无效的
停止(){
end=std::chrono::高分辨率时钟::现在();
}
模板
汽车
持续时间()常数{
返回std::chrono::duration_cast(end-begin).count();
}
汽车
纳秒()常数{
返回持续时间();
}
无效的
printNS(字符常量*str)常量{
标准::cout i;++i){
acc1+=std::atan2(i*p1,i*p1);
}
timer.stop();
timer.printNS(“atan”);

std::cout现代数学库不使用x87指令,因为它们比直接实现慢。也就是说,在现代处理器上,
fsqrt
非常快,只有4个周期,所以这并不重要。@fuz:
fsqrt
不是“复杂”的微代码x87指令。它是“基本”指令之一与div/mul/add/sub一起执行的操作,甚至SSE/AVX都实现了(
sqrtsd
),这可能需要有一个的副本。如果你想看到asm,你实际上是微边界的,很明显,通过调试器单步进入其中一个函数调用。你没有告诉用户你正在使用什么操作系统、编译器或CPU微体系结构。不同的操作系统有不同的复杂函数的数学库实现。我是v因为这个问题确实需要操作系统、精确的CPU、编译器、所用的库等,所以我们不打算把这个问题作为离题题来结束。这个问题可能是重复的,但它肯定不是上面链接的三个问题中的任何一个的重复,它们都不涉及反触发函数。而且几乎所有链接问题的答案都是错误的——不是实际的生产C++执行与原泰勒级数的正弦和余弦,例如,尽管第二个问题的答案大部分是。现代数学库不使用X87指令,因为它们比直接实现慢,也就是说,<代码> FQRT < /代码>在现代处理器上只有4个周期,所以它非常快,所以没什么大不了的。@fuz:
fsqrt
不是一条“复杂”的微代码x87指令。它是与div/mul/add/sub一起的“基本”操作之一,甚至SSE/AVX都实现了(
sqrtsd
),这可能需要有一个的副本。如果你想看到asm,你实际上是微边界的,很明显,通过调试器单步进入其中一个函数调用。你没有告诉用户你正在使用什么操作系统、编译器或CPU微体系结构。不同的操作系统有不同的复杂函数的数学库实现。我是v因为这个问题确实需要操作系统、精确的CPU、编译器、所用的库等,所以我们不打算把这个问题作为离题题来结束。这个问题可能是重复的,但它肯定不是上面链接的三个问题中的任何一个的重复,它们都不涉及反触发函数。而且几乎所有链接问题的答案都是错误的——不是实际生产C++执行与正弦泰勒级数的正弦和余弦,例如,尽管第二个问题的答案最多。