#ifndef INCLUDED_C_VECTOR_H #define INCLUDED_C_VECTOR_H #ifndef INCLUDED_C_BASE_H #include #endif /*INCLUDED_C_BASE_H*/ /* ------------------------------------------------------------------------------------------------------------------ */ /* */ typedef struct { double* components; // Contiguous array block tracking dimension coefficients c_size_t dimensions; // Size of the coordinate dimension (N) } c_Vector_t; /* ------------------------------------------------------------------------------------------------------------------ */ /* */ c_err_t c_Vector_Init(c_Vector_t* vec, c_size_t dimensions); void c_Vector_Destroy(c_Vector_t* vec); /* ------------------------------------------------------------------------------------------------------------------ */ /* */ /** * Euclidean Vector Addition: res = v1 + v2 * Time Complexity: O(N) | Auxiliary Space: O(1) */ C_STATIC_FORCE_INLINE c_err_t c_Vector_Add(c_Vector_t* res, const c_Vector_t* v1, const c_Vector_t* v2) { if (res == NULL || v1 == NULL || v2 == NULL) return C_ERR_PARAM; if (v1->dimensions != v2->dimensions || v1->dimensions != res->dimensions) return C_ERR_FAIL; for (c_size_t i = 0; i < v1->dimensions; i++) { res->components[i] = v1->components[i] + v2->components[i]; } return C_ERR_OK; } C_STATIC_FORCE_INLINE c_err_t c_Vector_Sub(c_Vector_t* res, const c_Vector_t* v1, const c_Vector_t* v2) { if (res == NULL || v1 == NULL || v2 == NULL) return C_ERR_PARAM; if (v1->dimensions != v2->dimensions || v1->dimensions != res->dimensions) return C_ERR_FAIL; for (c_size_t i = 0; i < v1->dimensions; i++) { res->components[i] = v1->components[i] - v2->components[i]; } return C_ERR_OK; } /** * Dot Product (Scalar Product): v1 · v2 * Time Complexity: O(N) */ C_STATIC_FORCE_INLINE c_err_t c_Vector_DotProduct(const c_Vector_t* v1, const c_Vector_t* v2, double* out_scalar) { if (v1 == NULL || v2 == NULL || out_scalar == NULL) return C_ERR_PARAM; if (v1->dimensions != v2->dimensions) return C_ERR_FAIL; double dot = 0.0; for (c_size_t i = 0; i < v1->dimensions; i++) { dot += v1->components[i] * v2->components[i]; } *out_scalar = dot; return C_ERR_OK; } /** * Calculates the Euclidean Magnitude (L2 Norm / Length): ||v|| = sqrt(v · v) * Time Complexity: O(N) */ C_STATIC_FORCE_INLINE double c_Vector_Magnitude(const c_Vector_t* vec) { if (vec == NULL || vec->dimensions == 0) return 0.0; double sum_sq = 0.0; for (c_size_t i = 0; i < vec->dimensions; i++) { sum_sq += vec->components[i] * vec->components[i]; } return sqrt(sum_sq); } /** * Vector Normalization (Unit Vector Scaling): v_hat = v / ||v|| * Time Complexity: O(N) */ C_STATIC_FORCE_INLINE c_err_t c_Vector_Normalize(c_Vector_t* vec) { if (vec == NULL || vec->dimensions == 0) return C_ERR_PARAM; double mag = c_Vector_Magnitude(vec); if (mag == 0.0) return C_ERR_FAIL; // Prevent division-by-zero on zero-vectors for (c_size_t i = 0; i < vec->dimensions; i++) { vec->components[i] /= mag; } return C_ERR_OK; } /** * Vector Scalar Multiplication (In-place Scaling): v = alpha * v * Time Complexity: O(N) | Auxiliary Space: O(1) * @param vec Pointer to the Euclidean vector instance. * @param alpha The scalar scaling factor coefficient. * @return C_ERR_OK if successful, C_ERR_PARAM if vec or components are NULL. */ C_STATIC_FORCE_INLINE c_err_t c_Vector_Scale(c_Vector_t* vec, double alpha) { if (vec == NULL || vec->components == NULL) return C_ERR_PARAM; // Linear unrolled loops pass across N-dimensional coordinates for (c_size_t i = 0; i < vec->dimensions; i++) { vec->components[i] *= alpha; } return C_ERR_OK; } /** * Calculates the Euclidean Distance between two vectors: result = ||a - b|| * Time Complexity: O(N) | Auxiliary Space: O(1) in-place * @param a Pointer to the first vector instance. * @param b Pointer to the second vector instance. * @param result Pointer to the destination variable where the scalar distance is written. * @return C_ERR_OK if successful, C_ERR_PARAM for NULL targets, * or C_ERR_FAIL for unequal dimensions. */ C_STATIC_FORCE_INLINE c_err_t c_Vector_DistanceTo(const c_Vector_t* a, const c_Vector_t* b, double* result) { if (a == NULL || b == NULL || result == NULL) return C_ERR_PARAM; if (a->components == NULL || b->components == NULL) return C_ERR_PARAM; if (a->dimensions != b->dimensions) return C_ERR_FAIL; double sum_sq_diff = 0.0; // Linear unrolled coordinate passes tracking differences across N-dimensions for (c_size_t i = 0; i < a->dimensions; i++) { double diff = a->components[i] - b->components[i]; sum_sq_diff += diff * diff; } *result = sqrt(sum_sq_diff); return C_ERR_OK; } /** * Calculates the direction (unit vector) of a given vector: result = vector / ||vector|| * Time Complexity: O(N) | Auxiliary Space: O(1) in-place * @param result Pointer to the destination vector where the direction components are written. * @param vector Pointer to the source input vector. * @return C_ERR_OK if successful, C_ERR_PARAM for NULL targets, * or C_ERR_INVALID for unequal dimensions or zero-magnitude origin vectors. */ C_STATIC_FORCE_INLINE c_err_t c_Vector_Direction(c_Vector_t* result, const c_Vector_t* vector) { if (result == NULL || vector == NULL) return C_ERR_PARAM; if (result->components == NULL || vector->components == NULL) return C_ERR_PARAM; if (result->dimensions != vector->dimensions) return C_ERR_INVALID; // Step 1: Calculate the magnitude of the input vector (L2 Norm) double sum_sq = 0.0; for (c_size_t i = 0; i < vector->dimensions; i++) { double val = vector->components[i]; sum_sq += val * val; } double magnitude = sqrt(sum_sq); // Step 2: Prevent division-by-zero on origin vectors (magnitude == 0) if (magnitude == 0.0) return C_ERR_INVALID; // Step 3: Compute the unit vector direction components for (c_size_t i = 0; i < vector->dimensions; i++) { result->components[i] = vector->components[i] / magnitude; } return C_ERR_OK; } #endif /*INCLUDED_C_VECTOR_H*/