add conv for hw2 and complement main.c

This commit is contained in:
2025-09-26 20:02:31 +09:00
parent 40064d644b
commit e172984338
4 changed files with 399 additions and 8 deletions

244
hws/hw2/convergence.c Normal file
View 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
View 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);

View File

@@ -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);
@@ -117,7 +118,7 @@ int main() {
xb1 = calloc(sizeof(float), n); xb1 = calloc(sizeof(float), n);
xb2 = calloc(sizeof(float), n); xb2 = calloc(sizeof(float), n);
nb = 0; nb = 0;
zbrak(test_func, a, b, n, xb1, xb2, &nb); zbrak(test_func, a, b, n, xb1, xb2, &nb);
float *roots_interesting = calloc(sizeof(float), nb); float *roots_interesting = 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;
} }

View File

@@ -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;
} }