| 148 |
ira |
1 |
/* Ira Snyder
|
|
|
2 |
* Project #2
|
|
|
3 |
* Due 2005-10-28
|
|
|
4 |
*/
|
|
|
5 |
|
|
|
6 |
/* Copyright: Ira W. Snyder
|
|
|
7 |
* Start Date: 2005-10-23
|
|
|
8 |
* End Date: 2005-10-27
|
|
|
9 |
* License: Public Domain
|
|
|
10 |
*/
|
|
|
11 |
|
| 144 |
ira |
12 |
#include <iostream>
|
|
|
13 |
#include <iomanip>
|
|
|
14 |
#include <cmath>
|
| 148 |
ira |
15 |
#include <cstdio>
|
| 144 |
ira |
16 |
using namespace std;
|
|
|
17 |
|
| 147 |
ira |
18 |
// Global Variables
|
|
|
19 |
enum {IDX0, IDX1, IDX5, IDX10, IDX15, IDX19, IDX20}; // Constants' Indices
|
| 144 |
ira |
20 |
|
|
|
21 |
float x1_const[7] = { 1.266065978, 5.651591040E-01, 2.714631560E-04,
|
|
|
22 |
2.752948040E-10, 2.370463051E-17, 1.587678369E-23,
|
|
|
23 |
3.966835986E-25 };
|
|
|
24 |
|
|
|
25 |
float x2_const[7] = { 2.279585302, 1.590636855, 9.825679323E-03,
|
|
|
26 |
3.016963879E-07, 8.139432531E-13, 8.641603385E-18,
|
|
|
27 |
4.310560576E-19 };
|
|
|
28 |
|
|
|
29 |
float x5_const[7] = { 2.723987182E+01, 2.433564214E+01, 2.157974547,
|
|
|
30 |
4.580044419E-03, 1.047977675E-6 , 4.078415017E-10,
|
|
|
31 |
5.024239358E-11 };
|
|
|
32 |
|
| 147 |
ira |
33 |
// Global Defines
|
|
|
34 |
#define ARRAY_SIZE 21
|
|
|
35 |
|
|
|
36 |
// Function Prototypes
|
| 148 |
ira |
37 |
float *Bessel_BottomUp (int n, float x, float *constants);
|
|
|
38 |
float *Bessel_TopDown (int n, float x, float *constants);
|
| 147 |
ira |
39 |
void print_table_bottomup (float x);
|
|
|
40 |
void print_table_topdown (float x);
|
|
|
41 |
void print_equals (int num);
|
|
|
42 |
|
| 144 |
ira |
43 |
/* Find the Bessel Function.
|
|
|
44 |
* Algorithm: I[n+1](x) = I[n-1](x) - (2*n/x) * I[n](x)
|
|
|
45 |
* Which is equvalent to: I[n](x) = I[n-2](x) - (2 * (n-1)/x) * I[n-1](x)
|
|
|
46 |
* by simple substitution.
|
|
|
47 |
*
|
|
|
48 |
* This is the recurrence relation for PART #1.
|
| 148 |
ira |
49 |
*
|
|
|
50 |
* Return values:
|
|
|
51 |
* this returns an array of values, in the form:
|
|
|
52 |
* array[0] = calculated value
|
|
|
53 |
* array[1] = part before the subtraction: I[n-2](x)
|
|
|
54 |
* array[2] = part after the subtraction: (2(n-1)/x) * I[n-1](x)
|
| 144 |
ira |
55 |
*/
|
| 148 |
ira |
56 |
float *Bessel_BottomUp (int n, float x, float *constants)
|
| 144 |
ira |
57 |
{
|
|
|
58 |
int i = 0;
|
| 148 |
ira |
59 |
float *answer = new float[3];
|
| 144 |
ira |
60 |
float *storage = new float[ARRAY_SIZE];
|
|
|
61 |
|
|
|
62 |
// Prime the array
|
| 145 |
ira |
63 |
storage[0] = constants[IDX0];
|
|
|
64 |
storage[1] = constants[IDX1];
|
| 144 |
ira |
65 |
|
|
|
66 |
// Calculate each value in turn
|
| 147 |
ira |
67 |
for (i=2; i<=n; i++)
|
| 148 |
ira |
68 |
{
|
|
|
69 |
storage[i] = storage[i-2] - (2.0 * (i-1) / x) * storage[i-1];
|
|
|
70 |
#ifdef DEBUG
|
|
|
71 |
// This will print out some useful information to find out why this
|
|
|
72 |
// is going right or wrong in it's calculation.
|
|
|
73 |
printf ("storage[%d] = %e - %e * %e = %e - %e = %e\n", i, storage[i-2],
|
|
|
74 |
(2.0 * (i-1) / x), storage[i-1],
|
|
|
75 |
storage[i-2], (2.0 * (i-1) / x) * storage[i-1], storage[i]);
|
|
|
76 |
#endif
|
|
|
77 |
}
|
| 144 |
ira |
78 |
|
|
|
79 |
// Store the answer, delete the memory
|
| 148 |
ira |
80 |
answer[0] = storage[n];
|
|
|
81 |
answer[1] = storage[n-2];
|
|
|
82 |
answer[2] = (2.0 * (n-1) / x) * storage[n-1];
|
| 144 |
ira |
83 |
delete[] storage;
|
|
|
84 |
|
|
|
85 |
// Return the result
|
|
|
86 |
return answer;
|
|
|
87 |
}
|
|
|
88 |
|
|
|
89 |
/* Find the Bessel Function, from the Top -> Down.
|
|
|
90 |
* Algorithm: I[n-1](x) = (2*n/x)*I[n](x) + I[n+1](x)
|
|
|
91 |
* Which is equivalent to: I[n](x) = (2 * (n+1) / x) * I[n+1](x) + I[n+2](x)
|
|
|
92 |
* by simple substitution.
|
|
|
93 |
*
|
|
|
94 |
* This is the recurrence relation for PART #2.
|
| 148 |
ira |
95 |
*
|
|
|
96 |
* Return values:
|
|
|
97 |
* this returns an array of values in the form:
|
|
|
98 |
* array[0] = calculated value
|
|
|
99 |
* array[1] = part before the addition: I[n+2](x)
|
|
|
100 |
* array[2] = part after the addition: (2(n+1)/x) * I[n+1](x)
|
| 144 |
ira |
101 |
*/
|
| 148 |
ira |
102 |
float *Bessel_TopDown (int n, float x, float *constants)
|
| 144 |
ira |
103 |
{
|
|
|
104 |
int i = 18;
|
| 148 |
ira |
105 |
float *answer = new float[3];
|
| 144 |
ira |
106 |
float *storage = new float[ARRAY_SIZE];
|
|
|
107 |
|
|
|
108 |
// Prime the array
|
| 145 |
ira |
109 |
storage[20] = constants[IDX20];
|
|
|
110 |
storage[19] = constants[IDX19];
|
| 144 |
ira |
111 |
|
|
|
112 |
// Calculate each value in turn
|
| 147 |
ira |
113 |
for (i=18; i>=n; i--)
|
| 148 |
ira |
114 |
{
|
|
|
115 |
storage[i] = (2.0 * (i+1) / x) * storage[i+1] + storage[i+2];
|
|
|
116 |
#ifdef DEBUG
|
|
|
117 |
// This will print out some useful information to find out why this
|
|
|
118 |
// is going right or wrong in it's calculation.
|
|
|
119 |
printf ("storage[%d] = %e * %e + %e = %e + %e = %e\n", i,
|
|
|
120 |
(2.0 * (i+1) / x), storage[i+1], storage[i+2],
|
|
|
121 |
(2.0 * (i+1) / x) * storage[i+1], storage[i+2], storage[i]);
|
|
|
122 |
#endif
|
|
|
123 |
}
|
| 144 |
ira |
124 |
|
|
|
125 |
// Store the answer, free the memory
|
| 148 |
ira |
126 |
answer[0] = storage[n];
|
|
|
127 |
answer[1] = storage[n+2];
|
|
|
128 |
answer[2] = (2.0 * (n+1) / x) * storage[n+1];
|
| 144 |
ira |
129 |
delete[] storage;
|
|
|
130 |
|
|
|
131 |
// Return the result
|
|
|
132 |
return answer;
|
|
|
133 |
}
|
|
|
134 |
|
| 148 |
ira |
135 |
/* Print a table of the Bessel function (for PART #2)
|
|
|
136 |
* for the given value of x */
|
| 147 |
ira |
137 |
void print_table_bottomup (float x)
|
| 144 |
ira |
138 |
{
|
| 147 |
ira |
139 |
int n, tblwidth = 6+16+16+16+16+16+20;
|
|
|
140 |
float true_val, calc_val, abs_err, rel_err, part1, part2;
|
| 148 |
ira |
141 |
float *constants, *answer;
|
| 144 |
ira |
142 |
|
| 148 |
ira |
143 |
// Find the right constants to use for the x value we're using.
|
| 145 |
ira |
144 |
if (x == 1.0) constants = x1_const;
|
|
|
145 |
if (x == 2.0) constants = x2_const;
|
|
|
146 |
if (x == 5.0) constants = x5_const;
|
| 144 |
ira |
147 |
|
| 147 |
ira |
148 |
// Reset the output flags
|
|
|
149 |
cout << resetiosflags (ios_base::scientific | ios_base::showpoint);
|
| 144 |
ira |
150 |
|
| 145 |
ira |
151 |
// A line of equal signs
|
| 147 |
ira |
152 |
print_equals (tblwidth);
|
| 145 |
ira |
153 |
|
|
|
154 |
// Print the x value we're using
|
| 147 |
ira |
155 |
cout << "Using x = " << x
|
| 148 |
ira |
156 |
<< " and working Bottom-up (PART #1)" << endl;
|
|
|
157 |
// A line of equal signs
|
|
|
158 |
print_equals (tblwidth);
|
| 145 |
ira |
159 |
|
| 147 |
ira |
160 |
// Set the output flags we're using
|
|
|
161 |
cout << setiosflags (ios_base::scientific | ios_base::showpoint);
|
|
|
162 |
|
| 144 |
ira |
163 |
// Print the table header
|
| 147 |
ira |
164 |
cout << setw(6) << "n Val."
|
|
|
165 |
<< setw(16) << "TRUE VAL"
|
|
|
166 |
<< setw(16) << "COMPUTED"
|
|
|
167 |
<< setw(16) << "ABS ERROR"
|
|
|
168 |
<< setw(16) << "REL ERROR"
|
|
|
169 |
<< setw(16) << "I[n-2](x)"
|
|
|
170 |
<< setw(20) << "(2(n-1)/x)I[n-1](x)"
|
| 144 |
ira |
171 |
<< endl;
|
|
|
172 |
|
|
|
173 |
// A line of equal signs
|
| 147 |
ira |
174 |
print_equals (tblwidth);
|
| 144 |
ira |
175 |
|
| 145 |
ira |
176 |
// Run once for n = 5,10,15,20
|
|
|
177 |
for (n=5; n<=20; n+=5)
|
|
|
178 |
{
|
| 148 |
ira |
179 |
// Choose the true values
|
|
|
180 |
switch (n)
|
|
|
181 |
{
|
|
|
182 |
case 5: true_val = constants[IDX5]; break;
|
|
|
183 |
case 10: true_val = constants[IDX10]; break;
|
|
|
184 |
case 15: true_val = constants[IDX15]; break;
|
|
|
185 |
case 20: true_val = constants[IDX20]; break;
|
|
|
186 |
}
|
| 144 |
ira |
187 |
|
| 148 |
ira |
188 |
// Get all of the pieces to print
|
|
|
189 |
answer = Bessel_BottomUp(n, x, constants);
|
|
|
190 |
calc_val = answer[0];
|
| 145 |
ira |
191 |
abs_err = abs (true_val - calc_val);
|
|
|
192 |
rel_err = abs_err / abs (true_val);
|
| 148 |
ira |
193 |
part1 = answer[1];
|
|
|
194 |
part2 = answer[2];
|
|
|
195 |
delete[] answer;
|
| 144 |
ira |
196 |
|
| 148 |
ira |
197 |
// Print a table line
|
| 147 |
ira |
198 |
cout << setw(6) << n
|
|
|
199 |
<< setw(16) << true_val
|
|
|
200 |
<< setw(16) << calc_val
|
|
|
201 |
<< setw(16) << abs_err
|
|
|
202 |
<< setw(16) << rel_err
|
|
|
203 |
<< setw(16) << part1
|
|
|
204 |
<< setw(20) << part2
|
| 145 |
ira |
205 |
<< endl;
|
|
|
206 |
}
|
| 146 |
ira |
207 |
|
|
|
208 |
cout << endl;
|
| 144 |
ira |
209 |
}
|
|
|
210 |
|
| 148 |
ira |
211 |
/* Print a table of the Bessel function (for PART #2)
|
|
|
212 |
* for the given value of x */
|
| 147 |
ira |
213 |
void print_table_topdown (float x)
|
|
|
214 |
{
|
|
|
215 |
int n, tblwidth = 6+16+16+16+16+16+20;
|
|
|
216 |
float true_val, calc_val, abs_err, rel_err, part1, part2;
|
| 148 |
ira |
217 |
float *constants, *answer;
|
| 147 |
ira |
218 |
bool done = false;
|
|
|
219 |
|
| 148 |
ira |
220 |
// Choose the correct constants for the value of x we're using
|
| 147 |
ira |
221 |
if (x == 1.0) constants = x1_const;
|
|
|
222 |
if (x == 2.0) constants = x2_const;
|
|
|
223 |
if (x == 5.0) constants = x5_const;
|
|
|
224 |
|
|
|
225 |
// Reset the output flags
|
|
|
226 |
cout << resetiosflags (ios_base::scientific | ios_base::showpoint);
|
|
|
227 |
|
|
|
228 |
// A line of equal signs
|
|
|
229 |
print_equals (tblwidth);
|
|
|
230 |
|
|
|
231 |
// Print the x value we're using
|
|
|
232 |
cout << "Using x = " << x
|
| 148 |
ira |
233 |
<< " and working Top-down (PART #2)" << endl;
|
|
|
234 |
// A line of equal signs
|
|
|
235 |
print_equals (tblwidth);
|
| 147 |
ira |
236 |
|
|
|
237 |
// Set the output flags we're using
|
|
|
238 |
cout << setiosflags (ios_base::scientific | ios_base::showpoint);
|
|
|
239 |
|
|
|
240 |
// Print the table header
|
|
|
241 |
cout << setw(6) << "n Val."
|
|
|
242 |
<< setw(16) << "TRUE VAL"
|
|
|
243 |
<< setw(16) << "COMPUTED"
|
|
|
244 |
<< setw(16) << "ABS ERROR"
|
|
|
245 |
<< setw(16) << "REL ERROR"
|
|
|
246 |
<< setw(16) << "I[n+2](x)"
|
|
|
247 |
<< setw(20) << "(2(n+1)/x)I[n+1](x)"
|
|
|
248 |
<< endl;
|
|
|
249 |
|
|
|
250 |
// A line of equal signs
|
|
|
251 |
print_equals (tblwidth);
|
|
|
252 |
|
|
|
253 |
n = 0;
|
|
|
254 |
// Run once for n = 0,1,5,10,15
|
|
|
255 |
while (!done)
|
|
|
256 |
{
|
| 148 |
ira |
257 |
// Choose the correct true values of the function
|
| 147 |
ira |
258 |
switch (n)
|
|
|
259 |
{
|
|
|
260 |
case 0: true_val = constants[IDX0]; break;
|
|
|
261 |
case 1: true_val = constants[IDX1]; break;
|
|
|
262 |
case 5: true_val = constants[IDX5]; break;
|
|
|
263 |
case 10: true_val = constants[IDX10]; break;
|
|
|
264 |
case 15: true_val = constants[IDX15]; break;
|
|
|
265 |
}
|
|
|
266 |
|
| 148 |
ira |
267 |
// Get all of the values to be printed
|
|
|
268 |
answer = Bessel_TopDown(n, x, constants);
|
|
|
269 |
calc_val = answer[0];
|
| 147 |
ira |
270 |
abs_err = abs (true_val - calc_val);
|
|
|
271 |
rel_err = abs_err / abs (true_val);
|
| 148 |
ira |
272 |
part1 = answer[1];
|
|
|
273 |
part2 = answer[2];
|
|
|
274 |
delete[] answer;
|
| 147 |
ira |
275 |
|
| 148 |
ira |
276 |
// Print a line in the table
|
| 147 |
ira |
277 |
cout << setw(6) << n
|
|
|
278 |
<< setw(16) << true_val
|
|
|
279 |
<< setw(16) << calc_val
|
|
|
280 |
<< setw(16) << abs_err
|
|
|
281 |
<< setw(16) << rel_err
|
|
|
282 |
<< setw(16) << part1
|
|
|
283 |
<< setw(20) << part2
|
|
|
284 |
<< endl;
|
|
|
285 |
|
|
|
286 |
switch (n) // Set n for the next loop
|
|
|
287 |
{
|
|
|
288 |
case 0: n = 1; break;
|
|
|
289 |
case 1: n = 5; break;
|
|
|
290 |
case 5: n = 10; break;
|
|
|
291 |
case 10: n = 15; break;
|
|
|
292 |
case 15: done = true; break;
|
|
|
293 |
}
|
|
|
294 |
}
|
|
|
295 |
|
|
|
296 |
cout << endl;
|
|
|
297 |
}
|
|
|
298 |
|
| 148 |
ira |
299 |
/* Print a line of equal signs on the screen */
|
| 147 |
ira |
300 |
void print_equals (int num)
|
|
|
301 |
{
|
|
|
302 |
int i;
|
|
|
303 |
|
|
|
304 |
for (i=0; i<num; i++)
|
|
|
305 |
cout << "=";
|
|
|
306 |
|
|
|
307 |
cout << endl;
|
|
|
308 |
}
|
|
|
309 |
|
| 144 |
ira |
310 |
int main (void)
|
|
|
311 |
{
|
| 148 |
ira |
312 |
#ifdef DEBUG
|
|
|
313 |
// Print out lots of good information to find out why these functions are
|
|
|
314 |
// going right or wrong.
|
|
|
315 |
float *answer;
|
|
|
316 |
cout << "Bottom-up" << endl << endl;
|
|
|
317 |
answer = Bessel_BottomUp(20, 1.0, x1_const);
|
|
|
318 |
cout << endl << endl << "Top-down" << endl << endl;
|
|
|
319 |
answer = Bessel_TopDown (0, 1.0, x1_const);
|
|
|
320 |
#else
|
|
|
321 |
// Print the first line of output as my name
|
|
|
322 |
cout << "Name: Ira Snyder" << endl << endl;
|
|
|
323 |
|
|
|
324 |
// Print all of the tables we need
|
| 147 |
ira |
325 |
print_table_bottomup (1.0);
|
|
|
326 |
print_table_bottomup (2.0);
|
|
|
327 |
print_table_bottomup (5.0);
|
|
|
328 |
print_table_topdown (1.0);
|
|
|
329 |
print_table_topdown (2.0);
|
|
|
330 |
print_table_topdown (5.0);
|
| 148 |
ira |
331 |
#endif
|
| 144 |
ira |
332 |
return 0;
|
|
|
333 |
}
|
|
|
334 |
|