#include "../include/helpers.hpp"

double f(double x){
    return 100*exp(-10*x);
}

std::vector<double> get_x(int N){
    std::vector<double> x;
    for (int i = 0; i <= N; i++) {
        x.push_back(i * (1.0 / N));
    }
    return x;
}

std::vector<double> get_g(const std::vector<double>& x){
    std::vector<double> g;
    double delta_x = x[1] - x[0];
    for (int i = 1; i < x.size() - 1; i++) {
        double x_i = x[i];
        g.push_back(delta_x * delta_x * f(x_i));
    }
    return g;
}

std::vector<double> analytical_solution(const std::vector<double>& x){
    std::vector<double> u;
    for(int i = 0; i < x.size(); i++){
        double x_i = x.at(i);
        double u_i = 1.0 - (1.0 - exp(-10.0))*x_i - exp(-10.0*x_i);
        u.push_back(u_i);
    }
    return u;
}

double relative_error(const std::vector<double>& v, const std::vector<double>& u){
    if (v.size() != u.size()) {
        std::cerr << "Error: Vectors must be of the same size." << std::endl << "Found sizes: " << v.size() << " and " << u.size() << std::endl;
        return -1.0;
    }
    const double eps = 1e-14;
    double max_rel_error = 0.0;
    for(int i = 0; i < v.size(); i++){
        if (fabs(u[i]) > eps) { // Avoid division by zero
            double rel_error = fabs((v[i] - u[i]) / u[i]);
            if (rel_error > max_rel_error) {
                max_rel_error = rel_error;
            }
        }
    }
    return max_rel_error;
}

void debug_print(const std::vector<double>& v, const std::string& name){
    for (int i = 0; i < v.size(); i++){
        std::cout << name << "[" << i << "] = " << v[i] << std::endl;
    }
}