add conv for hw2 and complement main.c
This commit is contained in:
244
hws/hw2/convergence.c
Normal file
244
hws/hw2/convergence.c
Normal file
@@ -0,0 +1,244 @@
|
|||||||
|
#include "convergence.h"
|
||||||
|
#define JMAX 80
|
||||||
|
|
||||||
|
ConvergenceData rtbis_with_conv(float (*func)(float), float x1, float x2, float xacc) {
|
||||||
|
void nrerror(char error_text[]);
|
||||||
|
|
||||||
|
ConvergenceData data;
|
||||||
|
data.size = 0;
|
||||||
|
|
||||||
|
int j;
|
||||||
|
float dx, f, fmid, xmid, rtb;
|
||||||
|
|
||||||
|
f = (*func)(x1);
|
||||||
|
fmid = (*func)(x2);
|
||||||
|
if (f * fmid >= 0.0) nrerror("Root must be bracketed for bisection in rtbis");
|
||||||
|
rtb = f < 0.0 ? (dx = x2 - x1, x1) : (dx = x1 - x2, x2);
|
||||||
|
for (j = 1; j <= JMAX; j++) {
|
||||||
|
fmid = (*func)(xmid = rtb + (dx *= 0.5));
|
||||||
|
if (fmid <= 0.0) rtb = xmid;
|
||||||
|
data.data[data.size++] = rtb;
|
||||||
|
if (fabs(dx) < xacc || fmid == 0.0) {
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
nrerror("Too many bisections in rtbis");
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConvergenceData rtflsp_with_conv(float (*func)(float), float x1, float x2, float xacc) {
|
||||||
|
void nrerror(char error_text[]);
|
||||||
|
|
||||||
|
ConvergenceData data;
|
||||||
|
data.size = 0;
|
||||||
|
|
||||||
|
int j;
|
||||||
|
float fl, fh, xl, xh, swap, dx, del, f, rtf;
|
||||||
|
|
||||||
|
fl = (*func)(x1);
|
||||||
|
fh = (*func)(x2);
|
||||||
|
if (fl * fh > 0.0) nrerror("Root must be bracketed in rtflsp");
|
||||||
|
if (fl < 0.0) {
|
||||||
|
xl = x1;
|
||||||
|
xh = x2;
|
||||||
|
} else {
|
||||||
|
xl = x2;
|
||||||
|
xh = x1;
|
||||||
|
swap = fl;
|
||||||
|
fl = fh;
|
||||||
|
fh = swap;
|
||||||
|
}
|
||||||
|
dx = xh - xl;
|
||||||
|
for (j = 1; j <= JMAX; j++) {
|
||||||
|
rtf = xl + dx * fl / (fl - fh);
|
||||||
|
f = (*func)(rtf);
|
||||||
|
if (f < 0.0) {
|
||||||
|
del = xl - rtf;
|
||||||
|
xl = rtf;
|
||||||
|
fl = f;
|
||||||
|
} else {
|
||||||
|
del = xh - rtf;
|
||||||
|
xh = rtf;
|
||||||
|
fh = f;
|
||||||
|
}
|
||||||
|
dx = xh - xl;
|
||||||
|
data.data[data.size++] = rtf;
|
||||||
|
if (fabs(del) < xacc || f == 0.0) return data;
|
||||||
|
}
|
||||||
|
nrerror("Maximum number of iterations exceeded in rtflsp");
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConvergenceData rtsec_with_conv(float (*func)(float), float x1, float x2, float xacc) {
|
||||||
|
void nrerror(char error_text[]);
|
||||||
|
|
||||||
|
ConvergenceData data;
|
||||||
|
data.size = 0;
|
||||||
|
|
||||||
|
int j;
|
||||||
|
float fl, f, dx, swap, xl, rts;
|
||||||
|
|
||||||
|
fl = (*func)(x1);
|
||||||
|
f = (*func)(x2);
|
||||||
|
if (fabs(fl) < fabs(f)) {
|
||||||
|
rts = x1;
|
||||||
|
xl = x2;
|
||||||
|
swap = fl;
|
||||||
|
fl = f;
|
||||||
|
f = swap;
|
||||||
|
} else {
|
||||||
|
xl = x1;
|
||||||
|
rts = x2;
|
||||||
|
}
|
||||||
|
for (j = 1; j <= JMAX; j++) {
|
||||||
|
dx = (xl - rts) * f / (f - fl);
|
||||||
|
xl = rts;
|
||||||
|
fl = f;
|
||||||
|
rts += dx;
|
||||||
|
f = (*func)(rts);
|
||||||
|
data.data[data.size++] = rts;
|
||||||
|
if (fabs(dx) < xacc || f == 0.0) return data;
|
||||||
|
}
|
||||||
|
nrerror("Maximum number of iterations exceeded in rtsec");
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConvergenceData rtnewt_with_conv(void (*funcd)(float, float *, float *), float x1, float x2,
|
||||||
|
float xacc) {
|
||||||
|
void nrerror(char error_text[]);
|
||||||
|
|
||||||
|
ConvergenceData data;
|
||||||
|
data.size = 0;
|
||||||
|
|
||||||
|
int j;
|
||||||
|
float df, dx, f, rtn;
|
||||||
|
|
||||||
|
rtn = 0.5 * (x1 + x2);
|
||||||
|
for (j = 1; j <= JMAX; j++) {
|
||||||
|
(*funcd)(rtn, &f, &df);
|
||||||
|
dx = f / df;
|
||||||
|
rtn -= dx;
|
||||||
|
if ((x1 - rtn) * (rtn - x2) < 0.0)
|
||||||
|
nrerror("Jumped out of brackets in rtnewt");
|
||||||
|
|
||||||
|
data.data[data.size++] = rtn;
|
||||||
|
if (fabs(dx) < xacc) return data;
|
||||||
|
}
|
||||||
|
nrerror("Maximum number of iterations exceeded in rtnewt");
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConvergenceData rtsafe_with_conv(void (*funcd)(float, float *, float *), float x1, float x2,
|
||||||
|
float xacc) {
|
||||||
|
void nrerror(char error_text[]);
|
||||||
|
|
||||||
|
ConvergenceData data;
|
||||||
|
data.size = 0;
|
||||||
|
|
||||||
|
int j;
|
||||||
|
float df, dx, dxold, f, fh, fl;
|
||||||
|
float temp, xh, xl, rts;
|
||||||
|
|
||||||
|
(*funcd)(x1, &fl, &df);
|
||||||
|
(*funcd)(x2, &fh, &df);
|
||||||
|
if ((fl > 0.0 && fh > 0.0) || (fl < 0.0 && fh < 0.0))
|
||||||
|
nrerror("Root must be bracketed in rtsafe");
|
||||||
|
if (fl == 0.0) {
|
||||||
|
data.data[data.size++] = x1;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
if (fh == 0.0) {
|
||||||
|
data.data[data.size++] = x2;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
if (fl < 0.0) {
|
||||||
|
xl = x1;
|
||||||
|
xh = x2;
|
||||||
|
} else {
|
||||||
|
xh = x1;
|
||||||
|
xl = x2;
|
||||||
|
}
|
||||||
|
rts = 0.5 * (x1 + x2);
|
||||||
|
dxold = fabs(x2 - x1);
|
||||||
|
dx = dxold;
|
||||||
|
(*funcd)(rts, &f, &df);
|
||||||
|
for (j = 1; j <= JMAX; j++) {
|
||||||
|
if ((((rts - xh) * df - f) * ((rts - xl) * df - f) > 0.0) || (fabs(2.0 * f) > fabs(dxold * df))) {
|
||||||
|
dxold = dx;
|
||||||
|
dx = 0.5 * (xh - xl);
|
||||||
|
rts = xl + dx;
|
||||||
|
data.data[data.size++] = rts;
|
||||||
|
|
||||||
|
if (xl == rts) return data;
|
||||||
|
} else {
|
||||||
|
dxold = dx;
|
||||||
|
dx = f / df;
|
||||||
|
temp = rts;
|
||||||
|
rts -= dx;
|
||||||
|
data.data[data.size++] = rts;
|
||||||
|
|
||||||
|
if (temp == rts) return data;
|
||||||
|
}
|
||||||
|
if (fabs(dx) < xacc) return data;
|
||||||
|
(*funcd)(rts, &f, &df);
|
||||||
|
if (f < 0.0)
|
||||||
|
xl = rts;
|
||||||
|
else
|
||||||
|
xh = rts;
|
||||||
|
}
|
||||||
|
nrerror("Maximum number of iterations exceeded in rtsafe");
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConvergenceData rtmuller_with_conv(float (*func)(float), float x1, float x2, float xacc) {
|
||||||
|
void nrerror(char error_text[]);
|
||||||
|
int j;
|
||||||
|
float fh, fl, fm, fnew, s, xl, r, x3, x0, x_prev, x_curr, x_next;
|
||||||
|
float d0, d1, d2, a, b, c;
|
||||||
|
|
||||||
|
ConvergenceData data;
|
||||||
|
data.size = 0;
|
||||||
|
|
||||||
|
x0 = x1;
|
||||||
|
x_prev = x2;
|
||||||
|
x_curr = (x0 + x_prev) / 2.0;
|
||||||
|
|
||||||
|
if (x_prev == x_curr) x_curr += xacc;
|
||||||
|
if (x0 == x_curr) x0 -= xacc;
|
||||||
|
|
||||||
|
for (j = 1; j <= 200; j++) {
|
||||||
|
d0 = func(x0);
|
||||||
|
d1 = func(x_prev);
|
||||||
|
d2 = func(x_curr);
|
||||||
|
|
||||||
|
float h1 = x_prev - x0;
|
||||||
|
float h2 = x_curr - x_prev;
|
||||||
|
float delta1 = (d1 - d0) / h1;
|
||||||
|
float delta2 = (d2 - d1) / h2;
|
||||||
|
a = (delta2 - delta1) / (h2 + h1);
|
||||||
|
b = a * h2 + delta2;
|
||||||
|
c = d2;
|
||||||
|
|
||||||
|
float disc = b * b - 4 * a * c;
|
||||||
|
if (disc < 0) nrerror("MullerMethodError: Complex roots encountered");
|
||||||
|
|
||||||
|
float denom1 = b + sqrt(disc);
|
||||||
|
float denom2 = b - sqrt(disc);
|
||||||
|
|
||||||
|
if (fabs(denom1) < fabs(denom2)) {
|
||||||
|
x_next = x_curr - (2 * c) / denom2;
|
||||||
|
} else {
|
||||||
|
x_next = x_curr - (2 * c) / denom1;
|
||||||
|
}
|
||||||
|
data.data[data.size++] = x_next;
|
||||||
|
if (fabs(x_next - x_curr) < xacc) return data;
|
||||||
|
|
||||||
|
x0 = x_prev;
|
||||||
|
x_prev = x_curr;
|
||||||
|
x_curr = x_next;
|
||||||
|
}
|
||||||
|
nrerror("MullerMethodError: Too many iterations");
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef JMAX
|
||||||
16
hws/hw2/convergence.h
Normal file
16
hws/hw2/convergence.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "nr.h"
|
||||||
|
#include "nrutil.h"
|
||||||
|
|
||||||
|
typedef struct ConvergenceData {
|
||||||
|
int size;
|
||||||
|
float data[200];
|
||||||
|
} ConvergenceData;
|
||||||
|
|
||||||
|
ConvergenceData rtbis_with_conv(float (*func)(float), float x1, float x2, float xacc);
|
||||||
|
ConvergenceData rtflsp_with_conv(float (*func)(float), float x1, float x2, float xacc);
|
||||||
|
ConvergenceData rtsec_with_conv(float (*func)(float), float x1, float x2, float xacc);
|
||||||
|
ConvergenceData rtnewt_with_conv(void (*funcd)(float, float *, float *), float x1, float x2, float xacc);
|
||||||
|
ConvergenceData rtsafe_with_conv(void (*funcd)(float, float *, float *), float x1, float x2, float xacc);
|
||||||
|
ConvergenceData rtmuller_with_conv(float (*func)(float), float x1, float x2, float xacc);
|
||||||
141
hws/hw2/main.c
141
hws/hw2/main.c
@@ -2,6 +2,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "convergence.h"
|
||||||
#include "muller.h"
|
#include "muller.h"
|
||||||
#include "nr.h"
|
#include "nr.h"
|
||||||
|
|
||||||
@@ -28,6 +29,10 @@ int main() {
|
|||||||
1. using zbrak, find all possible intervals with roots.
|
1. using zbrak, find all possible intervals with roots.
|
||||||
2. and use routines and enumerate all roots.
|
2. and use routines and enumerate all roots.
|
||||||
*/
|
*/
|
||||||
|
printf("===============================\n");
|
||||||
|
printf("A report of root-finding\n");
|
||||||
|
printf("student name: Hajin Ju, id: 2024062806\n");
|
||||||
|
printf("--------------------------------\n");
|
||||||
printf("=== A Program that find bessj0 roots in [1, 10] ===\n");
|
printf("=== A Program that find bessj0 roots in [1, 10] ===\n");
|
||||||
printf("--------------------------------\n");
|
printf("--------------------------------\n");
|
||||||
float a = 1.0, b = 10.0;
|
float a = 1.0, b = 10.0;
|
||||||
@@ -41,10 +46,6 @@ int main() {
|
|||||||
int i;
|
int i;
|
||||||
zbrak(bessj0, a, b, n, xb1, xb2, &nb);
|
zbrak(bessj0, a, b, n, xb1, xb2, &nb);
|
||||||
|
|
||||||
/* for (i = 1; i <= nb; i++) {
|
|
||||||
printf("[%f, %f]\n", xb1[i], xb2[i]);
|
|
||||||
} */
|
|
||||||
|
|
||||||
float *roots_bisect = calloc(sizeof(float), nb);
|
float *roots_bisect = calloc(sizeof(float), nb);
|
||||||
float *roots_linter = calloc(sizeof(float), nb);
|
float *roots_linter = calloc(sizeof(float), nb);
|
||||||
float *roots_secant = calloc(sizeof(float), nb);
|
float *roots_secant = calloc(sizeof(float), nb);
|
||||||
@@ -128,7 +129,8 @@ int main() {
|
|||||||
roots_interesting[i] = rtsafe(test_funcd, l, r, xacc);
|
roots_interesting[i] = rtsafe(test_funcd, l, r, xacc);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("I want to find roots of `x * sin(x) - 1`\n");
|
printf("I want to find roots of `x * sin(x) - 1`\nwhere x in [%.02f, %.02f]\n", a, b);
|
||||||
|
printf("-------------------------------\n");
|
||||||
printf("roots: ");
|
printf("roots: ");
|
||||||
for (i = 0; i < nb; i++) {
|
for (i = 0; i < nb; i++) {
|
||||||
printf("%f ", roots_interesting[i]);
|
printf("%f ", roots_interesting[i]);
|
||||||
@@ -139,5 +141,134 @@ int main() {
|
|||||||
free(xb2);
|
free(xb2);
|
||||||
free(roots_interesting);
|
free(roots_interesting);
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("=== Discuss the convergence speed ===\n");
|
||||||
|
printf("--------------------------------\n");
|
||||||
|
|
||||||
|
a = 2.0f;
|
||||||
|
b = 3.0f;
|
||||||
|
printf("Find a root of bessj0(x) where x in [%.02f, %.02f].\n", a, b);
|
||||||
|
printf("We want to get convergence speed(iteration count).\n");
|
||||||
|
printf("-------------------------------\n");
|
||||||
|
|
||||||
|
ConvergenceData conv_bisect = rtbis_with_conv(bessj0, a, b, xacc);
|
||||||
|
ConvergenceData conv_flsp = rtflsp_with_conv(bessj0, a, b, xacc);
|
||||||
|
ConvergenceData conv_secant = rtsec_with_conv(bessj0, a, b, xacc);
|
||||||
|
ConvergenceData conv_newt = rtnewt_with_conv(dbessj0, a, b, xacc);
|
||||||
|
ConvergenceData conv_newtsafe = rtsafe_with_conv(dbessj0, a, b, xacc);
|
||||||
|
ConvergenceData conv_muller = rtmuller_with_conv(bessj0, a, b, xacc);
|
||||||
|
|
||||||
|
printf("Convergence History(where root ~ 2.404825):\n");
|
||||||
|
|
||||||
|
printf("bisect iteration count: %d\n", conv_bisect.size);
|
||||||
|
printf("bisect iteration history: ");
|
||||||
|
for (i = 0; i < conv_bisect.size; i++) {
|
||||||
|
printf("%f ", conv_bisect.data[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("lin-interpoalation iteration count: %d\n", conv_flsp.size);
|
||||||
|
printf("lin-interpoalation iteration history: ");
|
||||||
|
for (i = 0; i < conv_flsp.size; i++) {
|
||||||
|
printf("%f ", conv_flsp.data[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("secant iteration count: %d\n", conv_secant.size);
|
||||||
|
printf("secant iteration history: ");
|
||||||
|
for (i = 0; i < conv_secant.size; i++) {
|
||||||
|
printf("%f ", conv_secant.data[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("newton-raphson iteration count: %d\n", conv_newt.size);
|
||||||
|
printf("newton-raphson iteration history: ");
|
||||||
|
for (i = 0; i < conv_newt.size; i++) {
|
||||||
|
printf("%f ", conv_newt.data[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("newton with bracketing iteration count: %d\n", conv_newtsafe.size);
|
||||||
|
printf("newton with bracketing iteration history: ");
|
||||||
|
for (i = 0; i < conv_newtsafe.size; i++) {
|
||||||
|
printf("%f ", conv_newtsafe.data[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("muller method iteration count: %d\n", conv_muller.size);
|
||||||
|
printf("muller method iteration history: ");
|
||||||
|
for (i = 0; i < conv_muller.size; i++) {
|
||||||
|
printf("%f ", conv_muller.data[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("-------------------------------\n");
|
||||||
|
printf("Convergence Error\n");
|
||||||
|
float res;
|
||||||
|
|
||||||
|
printf("bisect convergence error: ");
|
||||||
|
res = conv_bisect.data[conv_bisect.size - 1];
|
||||||
|
for (i =0;i < conv_bisect.size; i++) {
|
||||||
|
printf("%f ", fabs(conv_bisect.data[i] - res) / res);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("flsp convergence error: ");
|
||||||
|
res = conv_flsp.data[conv_flsp.size - 1];
|
||||||
|
for (i =0;i < conv_flsp.size; i++) {
|
||||||
|
printf("%f ", fabs(conv_flsp.data[i] - res) / res);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("secant convergence error: ");
|
||||||
|
res = conv_secant.data[conv_secant.size - 1];
|
||||||
|
for (i =0;i < conv_secant.size; i++) {
|
||||||
|
printf("%f ", fabs(conv_secant.data[i] - res) / res);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("newton-raphson convergence error: ");
|
||||||
|
res = conv_newt.data[conv_newt.size - 1];
|
||||||
|
for (i =0;i < conv_newt.size; i++) {
|
||||||
|
printf("%f ", fabs(conv_newt.data[i] - res) / res);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("newton with bracketing convergence error: ");
|
||||||
|
res = conv_newtsafe.data[conv_newtsafe.size - 1];
|
||||||
|
for (i =0;i < conv_newtsafe.size; i++) {
|
||||||
|
printf("%f ", fabs(conv_newtsafe.data[i] - res) / res);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("muller method convergence error: ");
|
||||||
|
res = conv_muller.data[conv_muller.size - 1];
|
||||||
|
for (i =0;i < conv_muller.size; i++) {
|
||||||
|
printf("%f ", fabs(conv_muller.data[i] - res) / res);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("-------------------------------\n");
|
||||||
|
|
||||||
|
printf("Convergence Iteration Counts Table:\n");
|
||||||
|
printf("--------------------------------------------------------------\n");
|
||||||
|
printf("| Method | Iter |\n");
|
||||||
|
printf("--------------------------------------------------------------\n");
|
||||||
|
printf("| Bisection | %-04d |\n", conv_bisect.size);
|
||||||
|
printf("| Linear Interpolation | %-04d |\n", conv_flsp.size);
|
||||||
|
printf("| Secant | %-04d |\n", conv_secant.size);
|
||||||
|
printf("| Newton-Raphson | %-04d |\n", conv_newt.size);
|
||||||
|
printf("| Newton with Bracketing | %-04d |\n", conv_newtsafe.size);
|
||||||
|
printf("| Muller | %-04d |\n", conv_muller.size);
|
||||||
|
printf("--------------------------------------------------------------\n");
|
||||||
|
|
||||||
|
printf("As a result, In order of performance(faster convergence speed),\n");
|
||||||
|
printf("Newton-Raphson, Newton with Bracketing, Muller, Secant, Linear Interpolation, Bisection\n");
|
||||||
|
|
||||||
|
printf("-------------------------------\n");
|
||||||
|
|
||||||
|
printf("===============================\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ float rtmuller(float (*func)(float), float x1, float x2, float xacc) {
|
|||||||
c = d2;
|
c = d2;
|
||||||
|
|
||||||
float disc = b * b - 4 * a * c;
|
float disc = b * b - 4 * a * c;
|
||||||
if (disc < 0) nrerror("Muller's method: complex roots encountered");
|
if (disc < 0) nrerror("MullerMethodError: complex roots encountered");
|
||||||
|
|
||||||
float denom1 = b + sqrt(disc);
|
float denom1 = b + sqrt(disc);
|
||||||
float denom2 = b - sqrt(disc);
|
float denom2 = b - sqrt(disc);
|
||||||
@@ -46,6 +46,6 @@ float rtmuller(float (*func)(float), float x1, float x2, float xacc) {
|
|||||||
x_prev = x_curr;
|
x_prev = x_curr;
|
||||||
x_curr = x_next;
|
x_curr = x_next;
|
||||||
}
|
}
|
||||||
nrerror("Too many iterations in rtmuller");
|
nrerror("MullerMethodError: too many iterations");
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user