#include <stdio.h>
#include <stdlib.h>
#include <math.h>
const double EPS1 = 1e-5;
const double EPS2 = 1e-5;
typedef struct Slice {
int n;
double *keys, *values;
} Slice;
double f(int k, double x) {
switch(k) {
case 0: return exp(x) + 2;
case 1: return -1/x;
case 2: return -2*(x + 1)/3;
default: return 0;
}
}
double fp(int k, double x) {
switch(k) {
case 0: return exp(x);
case 1: return 1/(x * x);
case 2: return -2*x/3;
default: return 0;
}
}
double rootChord(int f1, int f2, double l, double r, double lv, double rv) {
double m = (l * rv - r * lv) / (rv - lv);
if (fabs(m - l) < EPS1 || fabs(r - m) < EPS1) {
return m;
}
double mv = f(f1, m) - f(f2, m);
if ((lv < 0) != (mv < 0)) {
return rootChord(f1, f2, l, m, lv, mv);
} else {
return rootChord(f1, f2, m, r, mv, rv);
}
}
double rootTangent(int f1, int f2, double l, double r, double lv, double rv, double lp, double rp) {
//fprintf(stderr, "%.4lf, %.4lf\n", l, r);
//system("pause");
double m1 = l - lv / lp;
double m2 = r - rv / rp;
double m = (l < m1 && m1 < r) ? m1 : m2;
if (fabs(m - l) < EPS1 || fabs(r - m) < EPS1) {
return m;
}
double mv = f(f1, m) - f(f2, m);
double mp = fp(f1, m) - fp(f2, m);
if ((lv < 0) != (mv < 0)) {
return rootTangent(f1, f2, l, m, lv, mv, lp, mp);
} else {
return rootTangent(f1, f2, m, r, mv, rv, mp, rp);
}
}
double root(int f1, int f2, double l, double r) {
//fprintf(stderr, "Root: %.4lf, %.4lf\n", l, r);
double lv = f(f1, l) - f(f2, l);
double rv = f(f1, r) - f(f2, r);
double lp = fp(f1, l) - fp(f2, l);
double rp = fp(f1, r) - fp(f2, r);
//fprintf(stderr, "C\n");
double root1 = rootChord(f1, f2, l, r, lv, rv);
//fprintf(stderr, "T\n");
double root2 = rootTangent(f1, f2, l, r, lv, rv, lp, rp);
//fprintf(stderr, "OK\n");
return root1;
}
void expandArray(int fn, Slice *s) {
s->n *= 2;
s->keys = realloc(s->keys, (s->n + 1) * sizeof(double));
s->values = realloc(s->values, (s->n + 1) * sizeof(double));
for (int i = s->n; i >= 2; i -= 2) {
s->keys[i] = s->keys[i / 2];
s->values[i] = s->values[i / 2];
}
for (int i = 1; i < s->n; i += 2) {
s->keys[i] = (s->keys[i - 1] + s->keys[i + 1]) / 2.0;
s->values[i] = f(fn, s->keys[i]);
}
}
Slice newSlice(int fn, double l, double r) {
Slice res;
res.n = 1;
res.keys = malloc(2 * sizeof(double));
res.values = malloc(2 * sizeof(double));
res.keys[0] = l;
res.values[0] = f(fn, l);
res.keys[1] = r;
res.values[1] = f(fn, r);
expandArray(fn, &res);
return res;
}
double integrateArray(Slice s) {
double res = s.values[0] + s.values[s.n];
for (int i = 1; i < s.n; ++i) {
if (i % 2) {
res += 2 * s.values[i];
} else {
res += 4 * s.values[i];
}
}
res *= fabs(s.keys[0] - s.keys[s.n]) / (s.n * 3);
return res;
}
double integrate(int fn, double l, double r) {
Slice sl = newSlice(fn, l, r);
double prev, cur = integrateArray(sl);
do {
prev = cur;
expandArray(fn, &sl);
cur = integrateArray(sl);
} while (fabs(cur - prev) > EPS2);
return prev;
}
int main(void) {
double RANGES[3][2];
RANGES[0][0] = -3.0;
RANGES[0][1] = -1.0;
RANGES[1][0] = -5.0;
RANGES[1][1] = -3.0;
// fprintf(stderr, "To send: %.4lf, %.4lf\n", RANGES[1][0], RANGES[1][1]);
RANGES[2][0] = -1.0;
RANGES[2][1] = -0.1;
double cuts[3];
//fprintf(stderr, "---\n");
cuts[0] = root(1, 2, RANGES[0][0], RANGES[0][1]);
cuts[1] = root(0, 2, RANGES[1][0], RANGES[1][1]);
cuts[2] = root(0, 1, RANGES[2][0], RANGES[2][1]);
//fprintf(stderr, "---\n");
double ints[3];
ints[0] = integrate(0, cuts[1], cuts[2]);
ints[1] = integrate(1, cuts[0], cuts[2]);
ints[2] = integrate(2, cuts[0], cuts[1]);
//fprintf(stderr, "---\n");
double result;
if ((cuts[0] < cuts[1]) == (cuts[1] < cuts[2])) {
result = ints[1] - ints[0] - ints[2];
} else if ((cuts[0] < cuts[2]) == (cuts[2] < cuts[1])) {
result = ints[2] - ints[0] - ints[1];
} else {
result = ints[0] - ints[1] - ints[2];
}
//fprintf(stderr, "---\n");
printf("Result: %.4lf\n", fabs(result));
printf("Points: %.4lf %.4lf %.4lf\n", cuts[0], cuts[1], cuts[2]);
return 0;
}