#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; }