#ifndef __ETK_DIFF_H__
#define __ETK_DIFF_H__
#include "etk_utils.h"
#include <stdint.h>

#ifdef __cplusplus
extern "C"
{
#endif

/**
 * @brief Compute first derivative (dy) with uniform spacing h
 * 
 * This function calculates the first derivative of a function represented by discrete
 * values y[0..n-1] with uniform spacing h between points. The function uses different
 * approximation methods for endpoints and interior points to achieve O(h^2) accuracy.
 * 
 * @param y Input array of function values, must have at least 2 elements
 * @param n Number of elements in array y
 * @param h Uniform spacing between points, must be non-zero and finite. The unit of h
 *          should match the unit of your data's x-axis (e.g., seconds for time-based data).
 *          The derivative unit will be "y-unit per h-unit".
 * @param dy Output array for first derivative values, must have same size as y
 * @return true if calculation was successful, false if parameters were invalid or results contained NaN/infinity
 */
bool etk_diff1(const double *y, uint32_t n, double h, double *dy);

/**
 * @brief Compute second derivative (d2y) with uniform spacing h
 * 
 * This function calculates the second derivative of a function represented by discrete
 * values y[0..n-1] with uniform spacing h between points. The function uses different
 * approximation methods for endpoints and interior points to achieve O(h^2) accuracy.
 * 
 * @param y Input array of function values, must have at least 3 elements
 * @param n Number of elements in array y
 * @param h Uniform spacing between points, must be non-zero and finite. The unit of h
 *          should match the unit of your data's x-axis (e.g., seconds for time-based data).
 *          The derivative unit will be "y-unit per h-unit".
 * @param d2y Output array for second derivative values, must have same size as y
 * @return true if calculation was successful, false if parameters were invalid or results contained NaN/infinity
 */
bool etk_diff2(const double *y, uint32_t n, double h, double *d2y);

/**
 * @brief Compute both first and second derivatives in one pass
 * 
 * This function calculates both the first and second derivatives of a function
 * represented by discrete values. Computing both derivatives in one function
 * can be slightly more efficient due to better cache utilization.
 * 
 * @param y Input array of function values, must have at least 2 elements
 * @param n Number of elements in array y
 * @param h Uniform spacing between points, must be non-zero and finite. The unit of h
 *          should match the unit of your data's x-axis (e.g., seconds for time-based data).
 *          The derivative unit will be "y-unit per h-unit".
 * @param dy Output array for first derivative values, can be NULL if not needed
 * @param d2y Output array for second derivative values, can be NULL if not needed
 * @return true if calculation was successful, false if parameters were invalid or results contained NaN/infinity
 */
bool etk_diff12(const double *y, uint32_t n, double h, double *dy, double *d2y);

#ifdef __cplusplus
}
#endif

#endif
