// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// Title:   src_TheromChronometry()
// Author:  F2.1 Geophysical Parametrisation/Regionalisation, LIAG - Institute 
// for Applied Geophysics (Hannover, Germany)
// Contact: sebastian.kreutzer@uni-heidelberg.de
// Version: 0.1.0 [2025-06-04]
// Usage:   use with IsothermalHolding.R
// Code and model structure from OpenAI ChatGPT, 2025-06
// +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

// link to Rcpp
#include <Rcpp.h>
using namespace Rcpp;

// Helper function: Simpson's rule for 1D definite integration
double integrate_simpson(std::function<double(double)> f, double a, double b, int n) {
  if (n % 2 == 1) n++;
  double h = (b - a) / n;
  double s = f(a) + f(b);

  for (int i = 1; i < n; i += 2)
    s += 4 * f(a + i * h);

  for (int i = 2; i < n; i += 2)
    s += 2 * f(a + i * h);

  return s * h / 3.0;
}

// [[Rcpp::export]]
NumericVector f_BTS_cpp_part(
    NumericVector x,
    double A,
    double Eu,
    double s10,
    double Et,
    double kB,
    double T_K,
    double DeltaE,
    double rhop
) {
  int nx = x.size();
  NumericVector out(nx);

  // precompute constant part of the outer term
  double log_factor = std::log(1.8 * 3e15);
  double s = std::pow(10.0, s10);

  for (int i = 0; i < nx; ++i) {
    double t = x[i];

    // precompute outside the integral for this t
    double kars = std::exp(-rhop * std::pow(log_factor + std::log(250.0 + t), 3.0));

    // define integrand as a lambda
    std::function<double(double)> integrand = [&](double Eb) { // # nocov
      double exp1 = std::exp(-Eb / Eu);
      double exp2 = std::exp(-s * t * std::exp(-(Et - Eb) / (kB * T_K)));
      return A * exp1 * exp2;
    };

    double integral = integrate_simpson(integrand, 0.0, DeltaE, 100);

    out[i] = kars * integral;
  }
  return out;
}
