/* Calculate Pi according to various methods */

#include <stdio.h>
#include <math.h>

/* Calculate PI according to: pi = sqrt(6 * sum(1/n^2)) */
double pi1(int num)
{
  double sum = 0.0;
  int i;
  for (i = 1; i <= num; i++)
    sum += 1.0 / (i * i);
  return sqrt(sum * 6.0);
}

/* Calculate PI according to: pi = 4 * (1 - 1/3 + 1/5 - 1/7 + 1/9 ... */
double pi2(double epsilon)
{
  double sum = 0.0;
  double expr;
  int i = 0;
  do {
    double sign = (i % 2 == 0) ? 1.0 : -1.0;
    expr = 1.0 / (2.0 * i + 1);
    sum += sign * expr;
    i++;
  } while(expr > epsilon);
  return sum * 4.0;
}

/* Calculate PI: pi = 2 * (1 + (1/3) + (1/3 * 2/5) + (1/3 + 2/5 * 3/7) + ... */
double pi3(double epsilon)
{
  int i, j;
  double expr = 1.0;
  double sum = 0.0;
  for (i = 1; expr >= epsilon; i++) {
    sum += expr;    
    expr = expr * i / (2 * i + 1);
  }
  return sum * 2.0;
}

int main()
{
  int rc, num, opt;
  double epsilon, pi;
  printf("Enter an option (1, 2, or 3): ");
  rc = scanf("%d", &opt);
  if (rc != 1) {
    printf("ERROR: cannot read option!\n");
    return -1;
  }
  switch(opt) {
   case 1:
    printf("Enter the number of items: ");
    rc = scanf("%d", &num);
    if (rc != 1) {
      printf("ERROR: cannot read the number!\n");
      return -1;
    }
    pi = pi1(num);
    break;
    
   case 2:
    printf("Enter the approximation value: ");
    rc = scanf("%lf", &epsilon);
    if (rc != 1) {
      printf("ERROR: cannot read the value!\n");
      return -1;
    }
    if (epsilon <= 0) {
      printf("ERROR: invalid epsilon (%f)!\n", epsilon);
      return -1.0;
    }
    pi = pi2(epsilon);
    break;
    
   case 3:
    printf("Enter the approximation value: ");
    rc = scanf("%lf", &epsilon);
    if (rc != 1) {
      printf("ERROR: cannot read the value!\n");
      return -1;
    }
    if (epsilon <= 0) {
      printf("ERROR: invalid epsilon (%f)!\n", epsilon);
      return -1.0;
    }
    pi = pi3(epsilon);
    break;

   default:
    printf("Error: invalid option (%d)\n");
    return -1;
  }
  printf("Pi = %lf\n", pi);
  return 0;
}
