#ifndef INCLUDED_C_LINEARREGRESSION_H #define INCLUDED_C_LINEARREGRESSION_H #ifndef INCLUDED_C_BASE_H #include #endif /*INCLUDED_C_BASE_H*/ /* ------------------------------------------------------------------------------------------------------------------ */ /* */ // Linear Regression Model Context Structure typedef struct { double slope; // Slope coefficient (Beta) double intercept; // Y-Intercept coefficient (Alpha) c_bool_t is_trained;// State flag tracking model training status } c_LinearRegression_t; /* ------------------------------------------------------------------------------------------------------------------ */ /* */ /** * Initialize the Linear Regression Model context block. */ C_STATIC_FORCE_INLINE c_err_t c_LinearRegression_Init(c_LinearRegression_t* model) { if (model == NULL) return C_ERR_PARAM; model->slope = 0.0; model->intercept = 0.0; model->is_trained = C_FALSE; return C_ERR_OK; } /** * Train the model using Ordinary Least Squares (OLS) linear derivation math. * Time Complexity: O(N) | Auxiliary Space: O(1) in-place * @param model Pointer to the linear regression model context instance. * @param x Contiguous array tracking independent variable observations. * @param y Contiguous array tracking dependent variable target features. * @param num Total number of data points inside the training array sets. * @return C_ERR_OK if successful, C_ERR_PARAM for NULL targets, * or C_ERR_INVALID if variance evaluates to zero (vertical line slope anomaly). */ C_STATIC_FORCE_INLINE c_err_t c_LinearRegression_Fit(c_LinearRegression_t* model, const double* x, const double* y, c_size_t num) { if (model == NULL || x == NULL || y == NULL) return C_ERR_PARAM; if (num < 2) return C_ERR_PARAM; // Mandate at least two distinct points to draw a trend line double sum_x = 0.0; double sum_y = 0.0; // Step 1: Calculate the arithmetic mean values for features X and Y for (c_size_t i = 0; i < num; i++) { sum_x += x[i]; sum_y += y[i]; } double mean_x = sum_x / (double)num; double mean_y = sum_y / (double)num; double num_covariance = 0.0; double den_variance = 0.0; // Step 2: Accumulate sample covariance and independent feature variance maps for (c_size_t i = 0; i < num; i++) { double diff_x = x[i] - mean_x; num_covariance += diff_x * (y[i] - mean_y); den_variance += diff_x * diff_x; } // Step 3: Guard against division-by-zero on perfectly vertical data layouts if (den_variance == 0.0) { model->is_trained = C_FALSE; return C_ERR_INVALID; } // Step 4: Map final slope and intercept boundary coefficients model->slope = num_covariance / den_variance; model->intercept = mean_y - (model->slope * mean_x); model->is_trained = C_TRUE; return C_ERR_OK; } /** * Inference Lookahead: Predict the output target value for a specific input feature. * @param model Pointer to the constant trained model instance. * @param x The input independent scalar variable point. * @param out_val Pointer to the destination variable where the predicted Y value is written. * @return C_ERR_OK if successful, or C_ERR_INVALID if the model is untrained. */ C_STATIC_FORCE_INLINE c_err_t c_LinearRegression_Predict(const c_LinearRegression_t* model, double x, double* out_val) { if (model == NULL || out_val == NULL) return C_ERR_PARAM; if (!model->is_trained) return C_ERR_INVALID; // Execute standard linear function lookup: y = alpha + beta * x *out_val = model->intercept + (model->slope * x); return C_ERR_OK; } #endif /*INCLUDED_C_LINEARREGRESSION_H*/