
#include <stdio.h>
#include <math.h>

// Define the ODE function: dy/dx = 3y - 12y^2
double f(double x, double y) {
    return 3 * y - 12 * y * y;
}

// Runge-Kutta 4th order method to generate initial values
void runge_kutta_4(double (*f)(double, double), double y0, double x0, double xf, double h, double *x_values, double *y_values, int n) {
    double x = x0;
    double y = y0;
    for (int i = 0; i < n; i++) {
        x_values[i] = x;
        y_values[i] = y;

        double k1 = h * f(x, y);
        double k2 = h * f(x + 0.5 * h, y + 0.5 * k1);
        double k3 = h * f(x + 0.5 * h, y + 0.5 * k2);
        double k4 = h * f(x + h, y + k3);

        y = y + (1.0 / 6.0) * (k1 + 2 * k2 + 2 * k3 + k4);
        x = x + h;
    }
}

// Adams-Bashforth 2-step method for prediction
void adams_bashforth_2(double (*f)(double, double), double *x_values, double *y_values, double h, int n) {
    for (int i = 2; i < n; i++) {
        double f1 = f(x_values[i-1], y_values[i-1]);
        double f2 = f(x_values[i-2], y_values[i-2]);

        y_values[i] = y_values[i-1] + (h / 2) * (3 * f1 - f2);
    }
}

int main() {
    // Initial conditions
    double y0 = 0.2;   // initial value of y
    double x0 = 0;     // initial value of x
    double xf = 2.0;   // final value of x
    double h = 0.1;    // step size
    int n = (int)((xf - x0) / h) + 1;  // number of steps

    // Arrays to store x and y values
    double x_values[n], y_values[n];

    // Step 1: Use Runge-Kutta to generate initial values
    runge_kutta_4(f, y0, x0, xf, h, x_values, y_values, n);

    // Step 2: Apply Adams-Bashforth 2-step method to predict further values
    adams_bashforth_2(f, x_values, y_values, h, n);

    // Print the results (x, y)
    printf("x\t\ty\n");
    for (int i = 0; i < n; i++) {
        printf("%.2f\t%.6f\n", x_values[i], y_values[i]);
    }

    return 0;
}
