Subversion Repositories programming

Rev

Rev 170 | Rev 173 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
168 ira 1
/* Copyright: Ira W. Snyder
2
 * Start Date: 2005-11-28
170 ira 3
 * End Date: 2005-11-29
168 ira 4
 * License: Public Domain
5
 *
6
 * Changelog Follows:
7
 * 2005-11-28
8
 * - Implement eval_euler() and eval_trapezoid().
9
 *
10
 * 2005-11-29
169 ira 11
 * - Implement eval_romberg() and eval_simpson().
168 ira 12
 *
13
 */
14
 
15
#include <cmath>
16
#include <cstdio>
17
using namespace std;
18
 
169 ira 19
/**
20
 * The function given in the Project #5 Handout.
21
 * This is 1 + x^28
22
 *
23
 * @param x the point at which to evaluate the function
24
 */
25
float func (float x)
168 ira 26
{
27
    return 1.0 + pow (x, 28);
28
}
29
 
169 ira 30
/**
31
 * Evaluate the integral of the function given, over the interval given,
32
 * using the Euler method.
33
 *
34
 * @param a the lower bound of the integral
35
 * @param b the upper bound of the integral
36
 * @param n the number of intervals to use
37
 * @param f the function to evaluate
38
 */
39
float eval_euler (const float a, const float b, const int n, float(*f)(float))
168 ira 40
{
41
    const float h = (b - a) / n;
42
    float answer = 0.0, xi = 0.0;
43
    int i = 0;
44
 
45
    for (i=0; i<=n; i++)
46
    {
47
        xi = a + (i * h);
48
        answer += f(xi);
49
    }
50
 
51
    return h * answer;
52
}
53
 
169 ira 54
/**
55
 * Evaluate the integral of the function given, over the interval given,
56
 * using the trapezoid method.
57
 *
58
 * @param a the lower bound of the integral
59
 * @param b the upper bound of the integral
60
 * @param n the number of intervals to use
61
 * @param f the function to evaluate
62
 */
63
float eval_trapezoid (const float a, const float b, const int n, float(*f)(float))
168 ira 64
{
65
    const float h = (b - a) / n;
66
    float answer = 0.0, xi_last = 0.0, xi_now = 0.0;
67
    int i = 0;
68
 
69
    xi_last = a + (i * h); // i = 0 here
70
 
71
    for (i=1; i<=n; i++)
72
    {
73
        xi_now = a + (i * h);
74
        answer += (f (xi_last) + f (xi_now) * (xi_now - xi_last));
75
        xi_last = xi_now; // shift xi's
76
    }
77
 
78
    return answer;
79
}
80
 
169 ira 81
/**
82
 * Evaluate the integral of the function given, over the interval given,
83
 * using the Romberg method.
84
 *
85
 * This is directly based on the pseudocode on Pg 223-224 of the textbook.
86
 *
87
 * @param a the lower bound of the integral
88
 * @param b the upper bound of the integral
89
 * @param n the number of intervals to use
90
 * @param f the function to evaluate
91
 */
92
float eval_romberg (const float a, const float b, const int n, float(*f)(float))
168 ira 93
{
94
    float R[n+1][n+1];
95
    int i, j, k;
96
    float h, sum;
97
 
171 ira 98
    /* Check for values that make us run wild, and refuse to run */
99
    if (n > 25)
100
    {
101
        printf ("Cowardly refusing to run... You shouldn't need to use a\n"
102
                "value of n > 25. Remember, the inner loop runs (2^n) - 1.\n");
103
        return 0.0;
104
    }
105
 
168 ira 106
    h = b - a;
107
    R[0][0] = (h/2.0) * (f(a) + f(b));
108
 
109
    for (i=1; i<=n; i++)
110
    {
111
        h = h/2.0;
112
        sum = 0.0;
113
 
114
        for (k=1; k<=(pow(2.0, i) - 1); k+=2)
115
            sum = sum + f(a + k * h);
116
 
117
        R[i][0] = (1.0/2.0) * R[i-1][0] + sum * h;
118
 
119
        for (j=1; j<=i; j++)
120
            R[i][j] = R[i][j-1] + (R[i][j-1] - R[i-1][j-1]) / (pow(4.0, j) - 1);
121
    }
122
 
123
    return R[n][n];
124
}
125
 
169 ira 126
/**
127
 * Evaluate the integral of the function given, over the interval given,
128
 * using the Simpson method.
129
 *
130
 * This is derived from the formula on Pg 237-238
131
 *
132
 * @param a the lower bound of the integral
133
 * @param b the upper bound of the integral
134
 * @param n the number of intervals to use
135
 * @param f the function to evaluate
136
 */
137
float eval_simpson (const float a, const float b, const int n, float(*f)(float))
168 ira 138
{
169 ira 139
    const float h = (b - a) / n;
140
    float sum1=0.0, sum2=0.0;
141
    int i;
168 ira 142
 
169 ira 143
    /* Get the first sum in the formula on Pg 238 */
144
    for (i=1, sum1=0.0; i<=n/2; i++)
145
        sum1 += f (a + (2 * i - 1) * h);
146
 
147
    sum1 *= 4;
148
 
149
    /* Get the second sum in the formula on Pg 238 */
150
    for (i=1, sum2=0.0; i<=(n-2)/2; i++)
151
        sum2 += f (a + 2 * i * h);
152
 
153
    sum2 *= 2;
154
 
155
    /* Add it all together, and return it */
156
    return (h / 3.0) * ((f(a) + f(b)) + sum1 + sum2);
168 ira 157
}
158
 
159
int main (void)
160
{
169 ira 161
    const float a = 0.0;
162
    const float b = 3.0;
170 ira 163
    const float real = 3.0 + (pow(3.0, 29.0) / 29.0);
164
    float h, comp, abs, rel;
165
    int i, n;
169 ira 166
 
170 ira 167
    /* Euler Method Header */
168
    printf ("Euler's Method\n");
171 ira 169
    printf ("i       h               Computed        Abs Error       Rel Error\n");
170 ira 170
    printf ("====================================================================\n");
171 ira 171
 
170 ira 172
    /* Euler Method Table */
171 ira 173
    for (i=1; i<=25; i++)
170 ira 174
    {
171 ira 175
        h = pow(2.0, -i);
176
        n = (int)((b - a) / h);
170 ira 177
        comp = eval_euler (a, b, n, &func);
178
        abs = fabs(real - comp);
179
        rel = fabs(real - comp) / fabs(real);
180
 
171 ira 181
        printf ("%.2d\t%e\t%e\t%e\t%e\n", i, h, comp, abs, rel);
170 ira 182
    }
183
 
184
    /* Trapezoid Method Header */
185
    printf ("\n\nTrapezoid Method\n");
171 ira 186
    printf ("i       h               Computed        Abs Error       Rel Error\n");
170 ira 187
    printf ("====================================================================\n");
171 ira 188
 
170 ira 189
    /* Trapezoid Method Table */
171 ira 190
    for (i=1; i<=25; i++)
170 ira 191
    {
171 ira 192
        h = pow(2.0, -i);
193
        n = (int)((b - a) / h);
170 ira 194
        comp = eval_trapezoid (a, b, n, &func);
195
        abs = fabs(real - comp);
196
        rel = fabs(real - comp) / fabs(real);
197
 
171 ira 198
        printf ("%.2d\t%e\t%e\t%e\t%e\n", i, h, comp, abs, rel);
170 ira 199
    }
200
 
201
    /* Romberg Method Header */
202
    printf ("\n\nRomberg's Method\n");
171 ira 203
    printf ("i       h               Computed        Abs Error       Rel Error\n");
170 ira 204
    printf ("====================================================================\n");
171 ira 205
 
206
    /* Romberg Method Table
207
     *
208
     * NOTE: Don't go higher than 3 for this one, since the Romberg method's inner
209
     *       loop runs (2^24) - 1 = 16777216 times at i=3 and
210
     *       (2^48) - 1 = 2.81474 * 10^14 times at i = 4.
211
     */
212
    for (i=1; i<=3; i++)
170 ira 213
    {
171 ira 214
        h = pow(2.0, -i);
215
        n = (int)((b - a) / h);
170 ira 216
        comp = eval_romberg (a, b, n, &func);
217
        abs = fabs(real - comp);
218
        rel = fabs(real - comp) / fabs(real);
219
 
171 ira 220
        printf ("%.2d\t%e\t%e\t%e\t%e\n", i, h, comp, abs, rel);
170 ira 221
    }
222
 
223
    /* Simpson Method Header */
224
    printf ("\n\nSimpson's Method\n");
171 ira 225
    printf ("i       h               Computed        Abs Error       Rel Error\n");
170 ira 226
    printf ("====================================================================\n");
171 ira 227
 
170 ira 228
    /* Simpson Method Table */
171 ira 229
    for (i=1; i<=25; i++)
170 ira 230
    {
171 ira 231
        h = pow(2.0, -i);
232
        n = (int)((b - a) / h);
170 ira 233
        comp = eval_simpson (a, b, n, &func);
234
        abs = fabs(real - comp);
235
        rel = fabs(real - comp) / fabs(real);
236
 
171 ira 237
        printf ("%.2d\t%e\t%e\t%e\t%e\n", i, h, comp, abs, rel);
170 ira 238
    }
239
 
168 ira 240
    return 0;
241
}
242