Files
2026-08-10 01:21:15 +08:00

186 lines
6.2 KiB
C

#ifndef INCLUDED_C_VECTOR_H
#define INCLUDED_C_VECTOR_H
#ifndef INCLUDED_C_BASE_H
#include <c_Base.h>
#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*/