
#include <QtCore/QCoreApplication>
#include <QtCore/QElapsedTimer>
#include <QtGui/QVector3D>
#include <iostream>
#include <sstream>
#define OP_LOOPS 1000000
#define RETRY_LOOPS 10

int main(int argc, char *argv[])
{
#ifdef _DEBUG
  std::cout << "DEBUG" << std::endl << std::endl;
#else
  std::cout << "RELEASE" << std::endl << std::endl;
#endif

  using Ints = std::list<int>;
  std::list<int> ints;
  for (unsigned int i = 0; i < OP_LOOPS; ++i) {
    ints.push_back(i);
  }

  std::cout << "Number of list elements: " << OP_LOOPS << std::endl << std::endl;

  struct Times {
    qint64 t0, t1, t2, t3, tx;
  };

  std::vector<Times> elapsedTimes;
  elapsedTimes.resize(RETRY_LOOPS);

  for (unsigned int r = 0; r < RETRY_LOOPS; ++r) {

    {
      QElapsedTimer timer;
      timer.start();

      for (Ints::iterator itr = ints.begin(); itr != ints.end(); itr++) {
        (*itr) -= 1;
      }

      qint64 elapsed = timer.elapsed();
      elapsedTimes[r].t0 = elapsed;
    }

    {
      QElapsedTimer timer;
      timer.start();

      for (Ints::iterator itr = ints.begin(); itr != ints.end(); ++itr) {
        (*itr) -= 1;
      }

      qint64 elapsed = timer.elapsed();
      elapsedTimes[r].t1 = elapsed;
    }

    {
      QElapsedTimer timer;
      timer.start();

      for (Ints::iterator itr = ints.begin(), end = ints.end(); itr != end; ++itr) {
        (*itr) -= 1;
      }

      qint64 elapsed = timer.elapsed();
      elapsedTimes[r].t2 = elapsed;
    }

    {
      QElapsedTimer timer;
      timer.start();

      for (int& i : ints) {
        i -= 1;
      }

      qint64 elapsed = timer.elapsed();
      elapsedTimes[r].t3 = elapsed;
    }

    {
      QElapsedTimer timer;
      timer.start();

      Ints::iterator itr = ints.begin();
      while (itr != ints.end()) {
        (*itr) -= 1;
        ++itr;
      }

      qint64 elapsed = timer.elapsed();
      elapsedTimes[r].tx = elapsed;
    }

    std::cout << ".";
  }

  std::cout << std::endl << std::endl << "times [ms]";
  std::cout << std::endl  << "for_loop_post_inc__:";
  float d = 0.0;
  for (unsigned int r = 0; r < RETRY_LOOPS; ++r) {
    d += (float)elapsedTimes[r].t0;
    std::cout << " " << elapsedTimes[r].t0;    
  }
  std::cout << " -> " << (d / (float)RETRY_LOOPS);

  d = 0.0;
  std::cout << std::endl << "for_loop_pre_inc_____:";
  for (unsigned int r = 0; r < RETRY_LOOPS; ++r) {
    d += (float)elapsedTimes[r].t1;
    std::cout << " " << elapsedTimes[r].t1;
  }
  std::cout << " -> " << (d / (float)RETRY_LOOPS);

  d = 0.0;
  std::cout << std::endl << "for_loop_pre_inc_cond:";
  for (unsigned int r = 0; r < RETRY_LOOPS; ++r) {
    d += (float)elapsedTimes[r].t2;
    std::cout << " " << elapsedTimes[r].t2;
  }
  std::cout << " -> " << (d / (float)RETRY_LOOPS);

  d = 0.0;
  std::cout << std::endl << "for_each_____________:";
  for (unsigned int r = 0; r < RETRY_LOOPS; ++r) {
    d += (float)elapsedTimes[r].t3;
    std::cout << " " << elapsedTimes[r].t3;
  }
  std::cout << " -> " << (d / (float)RETRY_LOOPS);

  d = 0.0;
  std::cout << std::endl << "while_loop___________:";
  for (unsigned int r = 0; r < RETRY_LOOPS; ++r) {
    d += (float)elapsedTimes[r].tx;
    std::cout << " " << elapsedTimes[r].tx;
  }
  std::cout << " -> " << (d / (float)RETRY_LOOPS);


  std::cout << std::endl << std::endl;

  return 0;
}
