/* ++[ Machine Problem #1 ]++++++++++++++++++++++++++++++++++++++
   +								+
   + Zaczek, Mariusz						+
   + CS 223 - Monday 11:00am - 1:00 pm				+
   + 2/4/98							+
   + 								+
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */

#include <iostream.h>
#include <math.h>
#include <iomanip.h>

/* ++[  A  ]+++++++++++++++++++++++++++++++++++++++++++++++++++++
   + Function: allTheMeans                                      +
   +                                                            +
   +   Takes: --no values--                                     +
   +                                                            +
   +   Returns: --no values--                                   +
   +                                                            +
   +   Actions: Prompts user to input a series of values which  +
   +            are then used to calculate and display the      +
   +            the arithmetic, geometric and harmonic means of +
   +            these values.                                   +
   +								+
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */

void allTheMeans()
{
  /* Declare variables and in addition initialize sums & products */
  int numbers;           
  double sum = 0,            
         product = 1,        
         sum_inverses = 0,   
         first_value,        
         new_number,         
	 arithmetic_mean = sqrt(-1),    
         geometric_mean = sqrt(-1),
         harmonic_mean = sqrt(-1); 

  /* Prompt user to input the # of value that he plans on entering */
  cout << "How many numbers in the sequence? ";
  cin >> numbers;

  /* Check if user input zero or a negative value for the # of values */
  if (numbers > 0)
  {
    /* Prompt user to enter first number. And read it */
    cout << "Enter the first number in the sequence: ";
    cin >> first_value;

    /* Set the sums and products equal to initial values based on first
       number entered */
    sum += first_value;
    product *= first_value;
    sum_inverses += 1.0 / first_value;
         
    /* Loop asking each time for a new value and updating the sums and
       products */
    for (int i = 0; i < numbers - 1; ++i)
    {
      /* Prompt for next number */
      cout << "\nEnter the next number in the sequence: ";
      cin >> new_number;
 
      /* Update the sums and products */
      sum += new_number;
      product *= new_number;
      sum_inverses += 1.0 / new_number;
    }

    /* Calculate the arithmetic, geometric, and harmonic means */
    arithmetic_mean = sum / numbers ;
  
    geometric_mean = pow(product, 1.0 / numbers);
  
    harmonic_mean = numbers / sum_inverses ;

  }
  /* Test case for a negative input to # of values prompt */
  else if (numbers < 0)
  {  
    cout << "Invalid entry" << endl;     
    return;
  }
  
 /* Output to screen the value of the means set to a precision of two
     decimal places */
  cout << "\nThe arithmetic mean is "
       << setprecision(2)
       << setiosflags(ios::fixed | ios::showpoint)
       << arithmetic_mean
       << "\nThe geometric mean is "
       << geometric_mean
       << "\nThe harmonic mean is "
       << harmonic_mean
       << endl;
    
  return;
}

/* ++[  B  ]+++++++++++++++++++++++++++++++++++++++++++++++++++++
   + Function: pythagoreanNumbers                               +
   +                                                            +
   +   Takes: limit (type long)                                 +
   +                                                            +
   +   Returns: --no values--                                   +
   +                                                            +
   +   Actions: Loops through all the numbers between 1 and the +
   +            limit for the first for loop. Then inside this  +
   +            loop it uses another for loop to test all the   +
   +            numbers from 1 upto the i counter variable.     +
   +            Finally, this function calculate the square root+
   +            of (i^2 + j^2) and compares this value to the   +
   +            limit. The triple is only outputed if the       +
   +            square root value, assigned to variable test, is+
   +            both less than the limit and is equal to the    +
   +            integer value of the test value.		+
   +								+
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */

void pythagoreanNumbers(long limit)
{
  if (limit <= 0)
    cout << "ERROR: Invalid input. Limit must be positive integer"
         << endl;
  else
    /* Peform nested looping to run through all possible combinations
       of pythagorean triples */
    for (int i = 1; i <= limit; i++)
    {
      for (int j = 1; j <= i; j++)
      {
        double test;
        test=sqrt(i*i + j*j);
        
        /* Test if the sqrt. of the sum of the squares of the first
           two numbers is equal to the integer value of the 3rd
           and it is less than or equal to the limit */
	if ( (test <= limit) && (test == static_cast< int >(test)) )  
        cout << setiosflags( ios::left )
             << i << '\t'
             << j << '\t'
             << static_cast< int >(test) << endl;
      }
    }

return;
}

/* ++[  C  ]+++++++++++++++++++++++++++++++++++++++++++++++++++++
   + Function: chebyshevPolynomial                              +
   +                                                            +
   +   Takes: x (type double) number of which the polynomial    +
   +            value is desired.                               +
   +          n (type int) order of the polynomial              +
   +                                                            +
   +   Returns: The value of the Chebyshev Polynomial           +
   +                                                            +
   +   Actions: Using if statements, the function determines if +
   +            the base case of n==2 or n==1 has been reached  +
   +            yet. If not then the function recurses by       +
   +            calling itself.                                 +
   +								+
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
   
double chebyshevPolynomial(double x, int n)
{
  /* Test for base cases of polynomial */
  if ( n == 1 )
    return 1.0;
  else if ( n == 2 )
    return x;
  /* Perform recursive procedure for polynomial of order > 2 */
  else if ( n > 2 )
    return 2 * x * chebyshevPolynomial(x,n-1) -
	           chebyshevPolynomial(x,n-2);
  /* Test for negative order */
  else if ( n < 1 )
  { 
    cout << "Incorrect input: Enter positive number of order" << endl;
    return -1;
  } 
}


/* ++[  D  ]+++++++++++++++++++++++++++++++++++++++++++++++++++++
   + Function: fibonacci                                        +
   +                                                            +
   +   Takes: n (type long) number representing months          +
   +                                                            +
   +   Returns: The number of female rabbits after (n) months   +
   +                                                            +
   +   Actions: Loops iteratively using a for loop to determine +
   +            the fibonacci value of the variable ( n ).      +
   +								+
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */

long fibonacci(long n)
{
  /* Initialize base cases of f(0)=0 and f(1)=1 and intialize total
     of rabbits to zero */
  int fib_0 = 0,        
      fib_1 = 1,        
      rabbits = 0;      

  /* Output error and return -1 if # of month is less than 0 */
  if (n < 0)
  {
    cout << "Incorrect input: Enter a positive integer";
    return -1;
  }  
 
  /* Test to see if the requested fibonacci number is base case */
  if ( n == 0 )
    return fib_0;
  else if ( n == 1)
    return fib_1;

  /* Loop iteratively from 2 till n adding the previous two fibonacci
     numbers together and then reassigning new values to them (i.e. 
     updating the f(n-1) and f(n-2) fibonacci numbers */
  for (int i=2;i<=n;i++)
  {
    rabbits = (fib_0 + fib_1);
    fib_0 = fib_1;
    fib_1 = rabbits;
  }

  return rabbits;
}


/* ++[  E  ]+++++++++++++++++++++++++++++++++++++++++++++++++++++
   + Function: areaOfTriangle                                   +
   +                                                            +
   +   Takes: side1 (type double) side #1 of triangle           +
   +          side2 (type double) side #2 of triangle           +
   +	      side3 (type double) side #3 of triangle           +
   +                                                            +
   +   Returns: The area of the triangle described by the       +
   +            three sides.					+
   +                                                            +
   +   Actions: Determines if any side inputed is negative...if +
   +              is then an ERROR message is outputed and -1.0 +
   +              is returned. If the sum of any two sides is   +
   +              greater than the third side then the value of +
   +              the area is calculated using the area formula.+ 
   +								+
   ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */

double areaOfTriangle(double side1, double side2, double side3)
{
  /* Initialize s (half of perimeter of triangle */
  double s;       
            
  /* Test if any side entered was negative and give ERROR if it has */
  if ((side1 <= 0.0) || (side2 <= 0.0) || (side3 <= 0.0))
  {         
    cout << "ERROR: All sides must be positive in value!" << endl;
    return -1.0;
  }         

    s = (side1 + side2 + side3) / 2.0;
    return sqrt(s * (s - side1) * (s - side2) * (s - side3));
}

