Subversion Repositories programming

Rev

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