From e1729843385fb095b542040bfd17d38683fe9a22 Mon Sep 17 00:00:00 2001 From: yenru0 Date: Fri, 26 Sep 2025 20:02:31 +0900 Subject: [PATCH] add conv for hw2 and complement main.c --- hws/hw2/convergence.c | 244 ++++++++++++++++++++++++++++++++++++++++++ hws/hw2/convergence.h | 16 +++ hws/hw2/main.c | 143 +++++++++++++++++++++++-- hws/hw2/muller.c | 4 +- 4 files changed, 399 insertions(+), 8 deletions(-) create mode 100644 hws/hw2/convergence.c create mode 100644 hws/hw2/convergence.h diff --git a/hws/hw2/convergence.c b/hws/hw2/convergence.c new file mode 100644 index 0000000..84de7d1 --- /dev/null +++ b/hws/hw2/convergence.c @@ -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 \ No newline at end of file diff --git a/hws/hw2/convergence.h b/hws/hw2/convergence.h new file mode 100644 index 0000000..b09ca0e --- /dev/null +++ b/hws/hw2/convergence.h @@ -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); diff --git a/hws/hw2/main.c b/hws/hw2/main.c index 992cdb3..b5e9542 100644 --- a/hws/hw2/main.c +++ b/hws/hw2/main.c @@ -2,6 +2,7 @@ #include #include +#include "convergence.h" #include "muller.h" #include "nr.h" @@ -28,6 +29,10 @@ int main() { 1. using zbrak, find all possible intervals with 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("--------------------------------\n"); float a = 1.0, b = 10.0; @@ -41,10 +46,6 @@ int main() { int i; 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_linter = calloc(sizeof(float), nb); float *roots_secant = calloc(sizeof(float), nb); @@ -117,7 +118,7 @@ int main() { xb1 = calloc(sizeof(float), n); xb2 = calloc(sizeof(float), n); nb = 0; - + zbrak(test_func, a, b, n, xb1, xb2, &nb); float *roots_interesting = calloc(sizeof(float), nb); @@ -128,7 +129,8 @@ int main() { 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: "); for (i = 0; i < nb; i++) { printf("%f ", roots_interesting[i]); @@ -139,5 +141,134 @@ int main() { free(xb2); 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; } \ No newline at end of file diff --git a/hws/hw2/muller.c b/hws/hw2/muller.c index 35f99f5..866320d 100644 --- a/hws/hw2/muller.c +++ b/hws/hw2/muller.c @@ -29,7 +29,7 @@ float rtmuller(float (*func)(float), float x1, float x2, float xacc) { c = d2; 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 denom2 = b - sqrt(disc); @@ -46,6 +46,6 @@ float rtmuller(float (*func)(float), float x1, float x2, float xacc) { x_prev = x_curr; x_curr = x_next; } - nrerror("Too many iterations in rtmuller"); + nrerror("MullerMethodError: too many iterations"); return 0.0; } \ No newline at end of file