methods.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #define _CRT_SECURE_NO_WARNINGS
  2. #include <stdlib.h>
  3. #include <stdio.h>
  4. #include <math.h>
  5. #include "header.h"
  6. double integrate_left_rects(double(*f)(double), double prev_S, long int N, double a, double b, int* f_counter) {
  7. double S;
  8. long double H = (long double)(b - a) / N;
  9. S = 0;
  10. for (int i = 2;i <= N;i += 2) {
  11. S += f(a + (i - 1) * H, f_counter);
  12. }
  13. return H * S + (0.5) * prev_S;
  14. }
  15. void runge_left_rects(double eps, double(*f)(double), double a, double b,int* f_counter) {
  16. double S, S2 = 0;
  17. long int N = 1;
  18. S2 = (b - a) * f(0,f_counter);
  19. do {
  20. S = S2;
  21. N *= 2;
  22. S2 = integrate_left_rects(f, S, N, a, b, f_counter);
  23. } while (fabs(S2 - S) > eps);
  24. return S2;
  25. }
  26. double polyval(double* coeffs, double x, int n) {
  27. double ans = 0;
  28. for (int i = 0;i < n + 1;i++) {
  29. ans += coeffs[i] * pow(x, n - i);
  30. }
  31. return ans;
  32. }
  33. double* polyder(double* coeffs, int n) {
  34. double* der = malloc(sizeof(double) * (n));
  35. for (int i = 0;i < n;i++) {
  36. der[i] = coeffs[i] * (n - i);
  37. }
  38. return der;
  39. }
  40. double newton_solve(double* coeffs, int n, double a, double b) {
  41. double x_next = b, x_prev = b;
  42. double* der = polyder(coeffs, n);
  43. do {
  44. x_prev = x_next;
  45. x_next = x_prev - polyval(coeffs, x_prev, n) / polyval(der, x_prev, n - 1);
  46. } while (fabs(x_next - x_prev) >= 10e-10);
  47. free(der);
  48. return x_next;
  49. }
  50. double* solve_poly(double* coeffs, int n, double a, double b) {
  51. double* xx = calloc(n, sizeof(double));
  52. int c = 0;
  53. double x1 = a, x2 = a;
  54. while (x1 < b) {
  55. while (x2 < x1) {
  56. if (polyval(coeffs, x1, n) * polyval(coeffs, x2, n) < 0) {
  57. xx[c] = newton_solve(coeffs, n, x2, x1);
  58. c++;
  59. x1 = x2;
  60. x2 += (b - a) / 10000;
  61. break;
  62. }
  63. x2 += (b - a) / 10000;
  64. }
  65. x1 += (b - a) / 10000;
  66. }
  67. return xx;
  68. }
  69. double** table_xx() {
  70. double** ret = malloc(sizeof(double*) * 4);
  71. for (int n = 2;n <= 5;n++) {
  72. double* coeffs = malloc(sizeof(double) * (n + 1));
  73. double* sk = malloc(sizeof(double) * (n + 1));
  74. if (coeffs == NULL || sk == NULL) {
  75. exit(16);
  76. }
  77. coeffs[0] = 1;
  78. double A = 2.0 / n;
  79. for (int i = 1;i < (n + 1);i++) {
  80. sk[i] = (1.0 / (i + 1) - pow(-1, i + 1) / (i + 1)) / A;
  81. coeffs[i] = sk[i];
  82. for (int j = 1;j < i;j++) {
  83. coeffs[i] += coeffs[j] * sk[i - j];
  84. }
  85. coeffs[i] *= -1.0 / i;
  86. }
  87. ret[n - 2] = solve_poly(coeffs, n, -1, 1);
  88. free(sk);
  89. free(coeffs);
  90. }
  91. return ret;
  92. }
  93. double chebyshev_method(double(*f)(double), double a1, double b1, int n, double** xx_tab, int* f_counter) {
  94. double s = 0, a, b, ans;
  95. a = a1;
  96. b = b1;
  97. double* xx = xx_tab[n - 2];
  98. double A = 2.0 / n;
  99. ans = 0;
  100. for (int k = 0;k < n;k++) {
  101. ans += f((a + b) / 2 + ((b - a) / 2) * xx[k], f_counter);
  102. }
  103. s = ((b - a) / 2) * ans * A;
  104. return s;
  105. }
  106. double adaptive_div(double(*f)(double), double** xx_tab, double a, double b, int n, double eps, double S_n, double S_n_plus_1, int* N, int* f_counter) {
  107. if (fabs(S_n_plus_1 - S_n) < eps / (*N)) {
  108. return S_n;
  109. }
  110. else {
  111. double S_n_plus_1_r = chebyshev_method(f, a, (a + b) / 2, n + 1, xx_tab, f_counter);
  112. double S_n_r = chebyshev_method(f, a, (a + b) / 2, n, xx_tab, f_counter);
  113. double S_n_plus_1_l = chebyshev_method(f, (a + b) / 2, b, n + 1, xx_tab, f_counter);
  114. double S_n_l = chebyshev_method(f, (a + b) / 2, b, n, xx_tab, f_counter);
  115. *N += 1;
  116. return (adaptive_div(f, xx_tab, a, (a + b) / 2, n, eps, S_n_l, S_n_plus_1_l,N, f_counter) + adaptive_div(f, xx_tab, (a + b) / 2, b, n, eps, S_n_r, S_n_plus_1_r, N, f_counter));
  117. }
  118. }
  119. double cheb_approx(double(*f)(double), double a, double b, int n, double eps,int* f_counter) {
  120. double** xx_table = table_xx(a, b);
  121. int N = 1;
  122. return adaptive_div(f, xx_table, a, b, n, eps, 100, 1,&N, f_counter);
  123. }
  124. double* counters(double(*f)(double), double a, double b, double eps) {
  125. int counter_recs = 0,counter_cheb = 0;
  126. cheb_approx(f, a, b, 3, eps, &counter_cheb);
  127. runge_left_rects(eps, f, a, b, &counter_recs);
  128. printf("eps = %e, counter_recs = %d, counter_cheb = %d\n",eps, counter_recs, counter_cheb);
  129. int* counter = malloc(sizeof(int) * 2);
  130. counter[0] = counter_recs;
  131. counter[1] = counter_cheb;
  132. return counter;
  133. }