#pragma once

#include <cstddef>

namespace fn::ds {

// Binning 2D puro CPU. samples_x[i], samples_y[i] son los pares (x, y) a
// binnear. nx*ny celdas en row-major (idx = row * nx + col), donde row
// crece con y. Samples fuera del rango se descartan.
//
// out_counts[nx*ny] se llena con conteos uint32. (No se hace clear interno —
// el caller decide si acumular sobre llamadas previas o no.)
void samples_to_grid_2d_counts(const double* samples_x,
                               const double* samples_y,
                               std::size_t n,
                               double xmin, double xmax,
                               double ymin, double ymax,
                               int nx, int ny,
                               unsigned int* out_counts);

// Variante que normaliza los counts a float[0,1] sobre el max (densidad
// relativa). Adecuado para alimentar heatmap_cpp_viz / contour_cpp_viz / surface_plot_3d.
// Si todos los counts son 0 se llena out_density con 0.
void samples_to_grid_2d_density(const double* samples_x,
                                const double* samples_y,
                                std::size_t n,
                                double xmin, double xmax,
                                double ymin, double ymax,
                                int nx, int ny,
                                float* out_density);

// Helper: convierte counts uint -> density float in-place sobre out.
// max_count se calcula y se normaliza out[i] = counts[i]/max_count.
void counts_to_density(const unsigned int* counts, int nx, int ny,
                       float* out_density);

} // namespace fn::ds
