#include <utility>
#include <cstdio>
#include <chrono>

#include "context_switcher/context_switcher.h"
using namespace context_switcher;
using namespace std;

const size_t NUM_RUNS = 1000;

// Memory for custom stack and continuation semantics
const size_t STACK_SIZE = 512 * 1;
const size_t NUM_STACKS = 64;
char custom_stacks[NUM_STACKS][STACK_SIZE];

int fib(int n) {
  if (n <= 1) {
    return 1;
  }

  int a, b;
  enter_context(custom_stacks[n], STACK_SIZE, [n, &a](continuation &&cont) {
    a = fib(n - 1);
    return std::move(cont);
  });
  enter_context(custom_stacks[n], STACK_SIZE, [n, &b](continuation &&cont) {
    b = fib(n - 2);
    return std::move(cont);
  });

  return a + b;
}

volatile int result;
int main() {
  auto start_time = chrono::steady_clock::now();
  for (unsigned int i = 0; i < NUM_RUNS; i++) {
    result = fib(18);
  }
  auto end_time = chrono::steady_clock::now();
  auto time = chrono::duration_cast<chrono::microseconds>(end_time - start_time).count();

  printf("%f", (float) time / NUM_RUNS);

  return 0;
}
