Files
2026-08-30 01:48:03 +08:00

223 lines
9.7 KiB
C

#include "c_Matrix.h"
#include "c_Test.h"
typedef struct {
float x_scale;
float y_scale;
} TransformNode_t;
TEST_CASE(test_generic_flattened_matrix_flow) {
c_Matrix_t mat;
// 初始化一个 2行 3列 专门存储 TransformNode_t 变换的矩阵
ASSERT_INT_EQ(C_ERR_OK, c_Matrix_Init(&mat, 2, 3, sizeof(TransformNode_t), NULL));
ASSERT_INT_EQ(2, c_Matrix_Rows(&mat));
ASSERT_INT_EQ(3, c_Matrix_Cols(&mat));
ASSERT_PTR_NOT_NULL(mat.data);
TransformNode_t t_origin = { .x_scale = 1.0f, .y_scale = 1.0f };
TransformNode_t t_custom = { .x_scale = 5.5f, .y_scale = 9.9f };
// 1. 全局先刷入原始一阶数据
ASSERT_INT_EQ(C_ERR_OK, c_Matrix_Fill(&mat, &t_origin));
// 2. 在 (1行, 2列) 定点写入定制数据
ASSERT_INT_EQ(C_ERR_OK, c_Matrix_Write(&mat, 1, 2, &t_custom));
// 防御防御:拦截一切非法非法越界读写
ASSERT_INT_EQ(C_ERR_PARAM, c_Matrix_Write(&mat, 2, 0, &t_custom)); // 2行已越界
// 3. 验证定点读取与强值复制隔离 (Read / Get)
TransformNode_t read_res;
ASSERT_INT_EQ(C_ERR_OK, c_Matrix_Read(&mat, 1, 2, &read_res));
ASSERT_DOUBLE_EQ_MSG(5.5f, read_res.x_scale, "Float accuracy inside matrix");
// 修改外部变量,内部绝对不可受到交叉污染
t_custom.x_scale = 0.1f;
TransformNode_t* peeked = (TransformNode_t*)c_Matrix_Get(&mat, 1, 2);
ASSERT_PTR_NOT_NULL(peeked);
ASSERT_DOUBLE_EQ_MSG(5.5f, peeked->x_scale, "Verify deep value copy shield");
// 4. 【严苛物理断言】:验证一维行优先扁平存储的连续性
// 在 (1行, 2列) 上的扁平一维映射偏移:Index = 1 * 3 + 2 = 5
// 也就是说,它的物理物理实际物理首地址必须与矩阵的 data 首地址完美偏移 5 个结构体步长
void* expected_address = (void*)((char*)mat.data + (5 * sizeof(TransformNode_t)));
ASSERT_TRUE((void*)peeked == expected_address);
// 5. 验证高级整行高速抓取复制功能 (CopyRow)
// 我们抓取第 1 行的整行快照(包含 3 个 TransformNode_t 元素)
TransformNode_t row_dump_buffer[3];
ASSERT_INT_EQ(C_ERR_OK, c_Matrix_CopyRow(&mat, 1, row_dump_buffer));
// 验证这一行里抓取出来的最后一项是不是之前写入的定制变换
ASSERT_DOUBLE_EQ_MSG(5.5f, row_dump_buffer[2].x_scale, "Row block transmission verification");
c_Matrix_Destroy(&mat);
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
// ==================================================================================================================
// 具体类型:Double 矩阵专属算子族实现
// ==================================================================================================================
static void double_add_op(void* out, const void* a, const void* b, void* ud) {
(void)ud; *(double*)out = *(const double*)a + *(const double*)b;
}
static void double_sub_op(void* out, const void* a, const void* b, void* ud) {
(void)ud; *(double*)out = *(const double*)a - *(const double*)b;
}
static void double_mul_op(void* out, const void* a, const void* b, void* ud) {
(void)ud; *(double*)out = *(const double*)a * *(const double*)b;
}
static void double_div_op(void* out, const void* a, const void* b, void* ud) {
(void)ud; *(double*)out = *(const double*)a / *(const double*)b;
}
static void double_neg_op(void* out, const void* in, void* ud) {
(void)ud; *(double*)out = -(*(const double*)in);
}
// ==================================================================================================================
// 单元测试用例
// ==================================================================================================================
TEST_CASE(test_matrix_generic_math_computations) {
c_Matrix_t A, B, C;
// 初始化三个 2x2 的 double 矩阵
ASSERT_INT_EQ(C_ERR_OK, c_Matrix_Init(&A, 2, 2, sizeof(double), NULL));
ASSERT_INT_EQ(C_ERR_OK, c_Matrix_Init(&B, 2, 2, sizeof(double), NULL));
ASSERT_INT_EQ(C_ERR_OK, c_Matrix_Init(&C, 2, 2, sizeof(double), NULL));
// 填充 A 矩阵数据: [2.0, 4.0]
// [6.0, 8.0]
double v_a[2][2] = {{2.0, 4.0}, {6.0, 8.0}};
c_Matrix_Write(&A, 0, 0, &v_a[0][0]); c_Matrix_Write(&A, 0, 1, &v_a[0][1]);
c_Matrix_Write(&A, 1, 0, &v_a[1][0]); c_Matrix_Write(&A, 1, 1, &v_a[1][1]);
// 填充 B 矩阵数据: [1.0, 2.0]
// [3.0, 4.0]
double v_b[2][2] = {{1.0, 2.0}, {3.0, 4.0}};
c_Matrix_Write(&B, 0, 0, &v_b[0][0]); c_Matrix_Write(&B, 0, 1, &v_b[0][1]);
c_Matrix_Write(&B, 1, 0, &v_b[1][0]); c_Matrix_Write(&B, 1, 1, &v_b[1][1]);
// -------------------------------------------------------------------------
// 1. 测试 Element-wise 逐元素矩阵加法
// -------------------------------------------------------------------------
ASSERT_INT_EQ(C_ERR_OK, c_Matrix_Add(&C, &A, &B, double_add_op, NULL));
// 结果 C 应为: [3.0, 6.0]
// [9.0, 12.0]
ASSERT_DOUBLE_EQ_MSG(3.0, *(double*)c_Matrix_Get(&C, 0, 0), "Matrix Add Cell (0,0)");
ASSERT_DOUBLE_EQ_MSG(12.0, *(double*)c_Matrix_Get(&C, 1, 1), "Matrix Add Cell (1,1)");
// -------------------------------------------------------------------------
// 2. 测试 标量乘法 (Scalar Multiplication)
// -------------------------------------------------------------------------
double factor = 2.0;
ASSERT_INT_EQ(C_ERR_OK, c_Matrix_MulScalar(&C, &A, &factor, double_mul_op, NULL));
// 结果 C 应为 A 的每个元素乘以 2: [4.0, 8.0]
// [12.0, 16.0]
ASSERT_DOUBLE_EQ_MSG(4.0, *(double*)c_Matrix_Get(&C, 0, 0), "Matrix Scalar Mul Cell (0,0)");
ASSERT_DOUBLE_EQ_MSG(16.0, *(double*)c_Matrix_Get(&C, 1, 1), "Matrix Scalar Mul Cell (1,1)");
// -------------------------------------------------------------------------
// 3. 测试 线性代数标准矩阵乘法 (Matrix Multiplication)
// -------------------------------------------------------------------------
// 计算 C = A * B
// [2.0, 4.0] [1.0, 2.0] [(2*1 + 4*3), (2*2 + 4*4)] [14.0, 20.0]
// [6.0, 8.0] * [3.0, 4.0] = [(6*1 + 8*3), (6*2 + 8*4)] = [30.0, 44.0]
ASSERT_INT_EQ(C_ERR_OK, c_Matrix_Mul(&C, &A, &B, double_mul_op, double_add_op, NULL));
ASSERT_DOUBLE_EQ_MSG(14.0, *(double*)c_Matrix_Get(&C, 0, 0), "Matrix Mul Cell (0,0)");
ASSERT_DOUBLE_EQ_MSG(20.0, *(double*)c_Matrix_Get(&C, 0, 1), "Matrix Mul Cell (0,1)");
ASSERT_DOUBLE_EQ_MSG(30.0, *(double*)c_Matrix_Get(&C, 1, 0), "Matrix Mul Cell (1,0)");
ASSERT_DOUBLE_EQ_MSG(44.0, *(double*)c_Matrix_Get(&C, 1, 1), "Matrix Mul Cell (1,1)");
// 4. 清理闭环
c_Matrix_Destroy(&A);
c_Matrix_Destroy(&B);
c_Matrix_Destroy(&C);
}
TEST_CASE(test_matrix_transpose_and_determinant_closure) {
c_Matrix_t A, A_T;
// -------------------------------------------------------------------------
// 1. 验证矩阵转置 (Transpose)
// -------------------------------------------------------------------------
// 建立一个 2行 3列 的非方阵 A
ASSERT_INT_EQ(C_ERR_OK, c_Matrix_Init(&A, 2, 3, sizeof(double), NULL));
ASSERT_INT_EQ(C_ERR_OK, c_Matrix_Init(&A_T, 3, 2, sizeof(double), NULL)); // 转置后为 3x2
// 填充 A 为: [1.0, 2.0, 3.0]
// [4.0, 5.0, 6.0]
double val = 1.0;
for(c_size_t r=0; r<2; r++) {
for(c_size_t c=0; c<3; c++) {
c_Matrix_Write(&A, r, c, &val);
val += 1.0;
}
}
ASSERT_INT_EQ(C_ERR_OK, c_Matrix_Transpose(&A_T, &A));
// 校验转置后的几何单元: A_T 应为 [1.0, 4.0]
// [2.0, 5.0]
// [3.0, 6.0]
ASSERT_DOUBLE_EQ_MSG(1.0, *(double*)c_Matrix_Get(&A_T, 0, 0), "Transpose Cell (0,0)");
ASSERT_DOUBLE_EQ_MSG(4.0, *(double*)c_Matrix_Get(&A_T, 0, 1), "Transpose Cell (0,1)");
ASSERT_DOUBLE_EQ_MSG(5.0, *(double*)c_Matrix_Get(&A_T, 1, 1), "Transpose Cell (1,1)");
ASSERT_DOUBLE_EQ_MSG(6.0, *(double*)c_Matrix_Get(&A_T, 2, 1), "Transpose Cell (2,1)");
c_Matrix_Destroy(&A);
c_Matrix_Destroy(&A_T);
// -------------------------------------------------------------------------
// 2. 验证矩阵行列式求解 (Determinant)
// -------------------------------------------------------------------------
c_Matrix_t M;
// 建立一个 3x3 的标准双精度方阵 M
ASSERT_INT_EQ(C_ERR_OK, c_Matrix_Init(&M, 3, 3, sizeof(double), NULL));
// 填充方阵数据: [1.0, 2.0, 3.0]
// [0.0, 4.0, 5.0]
// [1.0, 0.0, 6.0]
// 理论行列式解算: 1*(4*6 - 5*0) - 2*(0*6 - 5*1) + 3*(0*0 - 4*1)
// = 1*(24) - 2*(-5) + 3*(-4) = 24 + 10 - 12 = 22.0
double m_data[3][3] = {
{1.0, 2.0, 3.0},
{0.0, 4.0, 5.0},
{1.0, 0.0, 6.0}
};
for(int i=0; i<3; i++) {
for(int j=0; j<3; j++) {
c_Matrix_Write(&M, i, j, &m_data[i][j]);
}
}
double final_det = 0.0;
c_err_t det_err = c_Matrix_Determinant(&M, &final_det,
double_add_op, double_sub_op,
double_mul_op, double_neg_op, NULL);
ASSERT_INT_EQ(C_ERR_OK, det_err);
ASSERT_DOUBLE_EQ_MSG(22.0, final_det, "Laplace Expansion Determinant Validation");
c_Matrix_Destroy(&M);
}
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
int main(void) {
TEST_START(C_Matrix_RowMajor_Layout_Tests);
RUN_TEST(test_generic_flattened_matrix_flow);
RUN_TEST(test_matrix_generic_math_computations);
RUN_TEST(test_matrix_transpose_and_determinant_closure);
TEST_REPORT();
RETURN_TEST_STATUS;
}