Rev 147 | Blame | Compare with Previous | Last modification | View Log | RSS feed
/* Ira Snyder
* Project #2
* Due 2005-10-28
*/
/* Copyright: Ira W. Snyder
* Start Date: 2005-10-23
* End Date: 2005-10-27
* License: Public Domain
*/
#include <iostream>
#include <iomanip>
#include <cmath>
#include <cstdio>
using namespace std;
// Global Variables
enum {IDX0, IDX1, IDX5, IDX10, IDX15, IDX19, IDX20}; // Constants' Indices
float x1_const[7] = { 1.266065978, 5.651591040E-01, 2.714631560E-04,
2.752948040E-10, 2.370463051E-17, 1.587678369E-23,
3.966835986E-25 };
float x2_const[7] = { 2.279585302, 1.590636855, 9.825679323E-03,
3.016963879E-07, 8.139432531E-13, 8.641603385E-18,
4.310560576E-19 };
float x5_const[7] = { 2.723987182E+01, 2.433564214E+01, 2.157974547,
4.580044419E-03, 1.047977675E-6 , 4.078415017E-10,
5.024239358E-11 };
// Global Defines
#define ARRAY_SIZE 21
// Function Prototypes
float *Bessel_BottomUp (int n, float x, float *constants);
float *Bessel_TopDown (int n, float x, float *constants);
void print_table_bottomup (float x);
void print_table_topdown (float x);
void print_equals (int num);
/* Find the Bessel Function.
* Algorithm: I[n+1](x) = I[n-1](x) - (2*n/x) * I[n](x)
* Which is equvalent to: I[n](x) = I[n-2](x) - (2 * (n-1)/x) * I[n-1](x)
* by simple substitution.
*
* This is the recurrence relation for PART #1.
*
* Return values:
* this returns an array of values, in the form:
* array[0] = calculated value
* array[1] = part before the subtraction: I[n-2](x)
* array[2] = part after the subtraction: (2(n-1)/x) * I[n-1](x)
*/
float *Bessel_BottomUp (int n, float x, float *constants)
{
int i = 0;
float *answer = new float[3];
float *storage = new float[ARRAY_SIZE];
// Prime the array
storage[0] = constants[IDX0];
storage[1] = constants[IDX1];
// Calculate each value in turn
for (i=2; i<=n; i++)
{
storage[i] = storage[i-2] - (2.0 * (i-1) / x) * storage[i-1];
#ifdef DEBUG
// This will print out some useful information to find out why this
// is going right or wrong in it's calculation.
printf ("storage[%d] = %e - %e * %e = %e - %e = %e\n", i, storage[i-2],
(2.0 * (i-1) / x), storage[i-1],
storage[i-2], (2.0 * (i-1) / x) * storage[i-1], storage[i]);
#endif
}
// Store the answer, delete the memory
answer[0] = storage[n];
answer[1] = storage[n-2];
answer[2] = (2.0 * (n-1) / x) * storage[n-1];
delete[] storage;
// Return the result
return answer;
}
/* Find the Bessel Function, from the Top -> Down.
* Algorithm: I[n-1](x) = (2*n/x)*I[n](x) + I[n+1](x)
* Which is equivalent to: I[n](x) = (2 * (n+1) / x) * I[n+1](x) + I[n+2](x)
* by simple substitution.
*
* This is the recurrence relation for PART #2.
*
* Return values:
* this returns an array of values in the form:
* array[0] = calculated value
* array[1] = part before the addition: I[n+2](x)
* array[2] = part after the addition: (2(n+1)/x) * I[n+1](x)
*/
float *Bessel_TopDown (int n, float x, float *constants)
{
int i = 18;
float *answer = new float[3];
float *storage = new float[ARRAY_SIZE];
// Prime the array
storage[20] = constants[IDX20];
storage[19] = constants[IDX19];
// Calculate each value in turn
for (i=18; i>=n; i--)
{
storage[i] = (2.0 * (i+1) / x) * storage[i+1] + storage[i+2];
#ifdef DEBUG
// This will print out some useful information to find out why this
// is going right or wrong in it's calculation.
printf ("storage[%d] = %e * %e + %e = %e + %e = %e\n", i,
(2.0 * (i+1) / x), storage[i+1], storage[i+2],
(2.0 * (i+1) / x) * storage[i+1], storage[i+2], storage[i]);
#endif
}
// Store the answer, free the memory
answer[0] = storage[n];
answer[1] = storage[n+2];
answer[2] = (2.0 * (n+1) / x) * storage[n+1];
delete[] storage;
// Return the result
return answer;
}
/* Print a table of the Bessel function (for PART #2)
* for the given value of x */
void print_table_bottomup (float x)
{
int n, tblwidth = 6+16+16+16+16+16+20;
float true_val, calc_val, abs_err, rel_err, part1, part2;
float *constants, *answer;
// Find the right constants to use for the x value we're using.
if (x == 1.0) constants = x1_const;
if (x == 2.0) constants = x2_const;
if (x == 5.0) constants = x5_const;
// Reset the output flags
cout << resetiosflags (ios_base::scientific | ios_base::showpoint);
// A line of equal signs
print_equals (tblwidth);
// Print the x value we're using
cout << "Using x = " << x
<< " and working Bottom-up (PART #1)" << endl;
// A line of equal signs
print_equals (tblwidth);
// Set the output flags we're using
cout << setiosflags (ios_base::scientific | ios_base::showpoint);
// Print the table header
cout << setw(6) << "n Val."
<< setw(16) << "TRUE VAL"
<< setw(16) << "COMPUTED"
<< setw(16) << "ABS ERROR"
<< setw(16) << "REL ERROR"
<< setw(16) << "I[n-2](x)"
<< setw(20) << "(2(n-1)/x)I[n-1](x)"
<< endl;
// A line of equal signs
print_equals (tblwidth);
// Run once for n = 5,10,15,20
for (n=5; n<=20; n+=5)
{
// Choose the true values
switch (n)
{
case 5: true_val = constants[IDX5]; break;
case 10: true_val = constants[IDX10]; break;
case 15: true_val = constants[IDX15]; break;
case 20: true_val = constants[IDX20]; break;
}
// Get all of the pieces to print
answer = Bessel_BottomUp(n, x, constants);
calc_val = answer[0];
abs_err = abs (true_val - calc_val);
rel_err = abs_err / abs (true_val);
part1 = answer[1];
part2 = answer[2];
delete[] answer;
// Print a table line
cout << setw(6) << n
<< setw(16) << true_val
<< setw(16) << calc_val
<< setw(16) << abs_err
<< setw(16) << rel_err
<< setw(16) << part1
<< setw(20) << part2
<< endl;
}
cout << endl;
}
/* Print a table of the Bessel function (for PART #2)
* for the given value of x */
void print_table_topdown (float x)
{
int n, tblwidth = 6+16+16+16+16+16+20;
float true_val, calc_val, abs_err, rel_err, part1, part2;
float *constants, *answer;
bool done = false;
// Choose the correct constants for the value of x we're using
if (x == 1.0) constants = x1_const;
if (x == 2.0) constants = x2_const;
if (x == 5.0) constants = x5_const;
// Reset the output flags
cout << resetiosflags (ios_base::scientific | ios_base::showpoint);
// A line of equal signs
print_equals (tblwidth);
// Print the x value we're using
cout << "Using x = " << x
<< " and working Top-down (PART #2)" << endl;
// A line of equal signs
print_equals (tblwidth);
// Set the output flags we're using
cout << setiosflags (ios_base::scientific | ios_base::showpoint);
// Print the table header
cout << setw(6) << "n Val."
<< setw(16) << "TRUE VAL"
<< setw(16) << "COMPUTED"
<< setw(16) << "ABS ERROR"
<< setw(16) << "REL ERROR"
<< setw(16) << "I[n+2](x)"
<< setw(20) << "(2(n+1)/x)I[n+1](x)"
<< endl;
// A line of equal signs
print_equals (tblwidth);
n = 0;
// Run once for n = 0,1,5,10,15
while (!done)
{
// Choose the correct true values of the function
switch (n)
{
case 0: true_val = constants[IDX0]; break;
case 1: true_val = constants[IDX1]; break;
case 5: true_val = constants[IDX5]; break;
case 10: true_val = constants[IDX10]; break;
case 15: true_val = constants[IDX15]; break;
}
// Get all of the values to be printed
answer = Bessel_TopDown(n, x, constants);
calc_val = answer[0];
abs_err = abs (true_val - calc_val);
rel_err = abs_err / abs (true_val);
part1 = answer[1];
part2 = answer[2];
delete[] answer;
// Print a line in the table
cout << setw(6) << n
<< setw(16) << true_val
<< setw(16) << calc_val
<< setw(16) << abs_err
<< setw(16) << rel_err
<< setw(16) << part1
<< setw(20) << part2
<< endl;
switch (n) // Set n for the next loop
{
case 0: n = 1; break;
case 1: n = 5; break;
case 5: n = 10; break;
case 10: n = 15; break;
case 15: done = true; break;
}
}
cout << endl;
}
/* Print a line of equal signs on the screen */
void print_equals (int num)
{
int i;
for (i=0; i<num; i++)
cout << "=";
cout << endl;
}
int main (void)
{
#ifdef DEBUG
// Print out lots of good information to find out why these functions are
// going right or wrong.
float *answer;
cout << "Bottom-up" << endl << endl;
answer = Bessel_BottomUp(20, 1.0, x1_const);
cout << endl << endl << "Top-down" << endl << endl;
answer = Bessel_TopDown (0, 1.0, x1_const);
#else
// Print the first line of output as my name
cout << "Name: Ira Snyder" << endl << endl;
// Print all of the tables we need
print_table_bottomup (1.0);
print_table_bottomup (2.0);
print_table_bottomup (5.0);
print_table_topdown (1.0);
print_table_topdown (2.0);
print_table_topdown (5.0);
#endif
return 0;
}