Приведенный ниже код вычисляет числа Фибоначчи по экспоненциально медленному алгоритму:
#include <cstdlib>
#include <iostream>
#define DEBUG(var) { std::cout << #var << ": " << (var) << std::endl; }
constexpr auto fib(const size_t n) -> long long
{
return n < 2 ? 1: fib(n - 1) + fib(n - 2);
}
int main(int argc, char *argv[])
{
const long long fib91 = fib(91);
DEBUG( fib91 );
DEBUG( fib(45) );
return EXIT_SUCCESS;
}
И я вычисляю 45-й номер Фибоначчи во время выполнения, а 91-й - во время компиляции.
Интересным фактом является то, что GCC 4.9 компилирует код и вычисляет fib91
за долю секунды, но требуется время, чтобы выплюнуть fib(45)
.
Мой вопрос: если GCC достаточно умен, чтобы оптимизировать вычисление fib(91)
и не принимать экспоненциально медленный путь, что мешает ему сделать то же самое для fib(45)
?
Означает ли это, что GCC создает две скомпилированные версии функции fib
, где один является быстрым, а другой экспоненциально медленным?
Вопрос заключается не в том, как компилятор оптимизирует вычисление fib(91)
(да, он использует своего рода memoization), но если он знает, как оптимизировать функцию fib
, почему она не делает то же самое для fib(45)
? И есть ли две отдельные компиляции функции fib
? Один медленный, а другой быстрый?