/* $Id: pi.cpp 1136 2006-09-06 08:05:31Z olau $ */

/* Copyright (C) 2006 Oliver Lau <ola@ctmagazin.de>, Heise Zeitschriften Verlag */

#include <stdlib.h>
#include <stdio.h>

#include "tbb/task_scheduler_init.h"
#include "tbb/blocked_range.h"
#include "tbb/parallel_reduce.h"
#include "tbb/tick_count.h"

using namespace tbb;

#define PI                   (3.14159265358979323846264338327950288419716939937510)
#define DEFAULT_ITERATIONS   (100000000)


class Summarizer {
private:
  double m_w;
  double m_sum;
public:
  Summarizer(size_t iterations) : m_sum(0.0), m_w(1.0/iterations) { }
  Summarizer(Summarizer& other, split) : m_sum(0.0), m_w(other.m_w) { }
  void operator() (const blocked_range<size_t>& r)
  {
    for (size_t i = r.begin(); i != r.end(); ++i) {
      double x = m_w * ((double) i - 0.5);
      m_sum += 4 / (1 + x * x);
    }
  }
  void join(const Summarizer& other) { m_sum += other.m_sum; }
  double sum(void) { return m_sum; }
};


int main(int argc, char *argv[])
{
  task_scheduler_init init;

  const size_t iterations = DEFAULT_ITERATIONS;
  const size_t blockSize = iterations/100;

  tick_count t0 = tick_count::now();

  Summarizer summarizer(iterations);
  parallel_reduce(blocked_range<size_t>(1, iterations+1, blockSize), summarizer);
  double pi = 1.0 / (double) iterations * summarizer.sum();

  tick_count t1 = tick_count::now();

  printf("pi = %.14lf (Fehler: %.14lf)\n", pi, pi - PI);
  printf("Ausfuehrungsdauer: %lg ms\n\n", 1000 * (t1 - t0).seconds());
  return 0;
}
