summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lab04/README.md6
-rw-r--r--lab04/polynomial.h46
-rw-r--r--lab04/ui.c76
3 files changed, 119 insertions, 9 deletions
diff --git a/lab04/README.md b/lab04/README.md
index b5dd0a5..b771dba 100644
--- a/lab04/README.md
+++ b/lab04/README.md
@@ -6,10 +6,10 @@
- 线性表的添加、插入、删除、修改、查找和遍历;
- 向量加法、减法和夹角余弦计算;
-- 顺序表多项式的加减、乘法和求导;
-- 链表多项式的加减、乘法和求导;
+- 顺序表多项式的加减、乘法、求导和积分;
+- 链表多项式的加减、乘法、求导和积分;
- 四则运算表达式求值;
-- 实矩阵加减乘、转置、行列式和特征值计算(特征值可为复数)。
+- 实矩阵加减乘、转置、行列式、求逆和特征值计算(特征值可为复数)。
底层实现使用自定义的 `vec` 动态数组和循环双向链表。
diff --git a/lab04/polynomial.h b/lab04/polynomial.h
index a270211..6641e36 100644
--- a/lab04/polynomial.h
+++ b/lab04/polynomial.h
@@ -749,6 +749,52 @@ static inline bool poly_list_derivative(struct poly_list *dst,
return true;
}
+/* Indefinite integral with the constant term set to zero. */
+static inline bool poly_vec_integral(struct poly_vec *dst,
+ const struct poly_vec *src)
+{
+ struct poly_vec tmp;
+ poly_vec_init(&tmp);
+
+ for (size_t i = 0; i < src->terms.size; ++i) {
+ const struct poly_term *term =
+ vec_at_const(&src->terms, i);
+ if (term->exp == UINT_MAX ||
+ !poly_vec_add_term(&tmp, term->coef / (term->exp + 1.0),
+ term->exp + 1)) {
+ poly_vec_destroy(&tmp);
+ return false;
+ }
+ }
+
+ __poly_vec_replace(dst, &tmp);
+ return true;
+}
+
+static inline bool poly_list_integral(struct poly_list *dst,
+ const struct poly_list *src)
+{
+ struct poly_list tmp;
+ poly_list_init(&tmp);
+
+ const struct list_head *pos = src->head.next;
+ while (pos != &src->head) {
+ const struct poly_node *node =
+ list_entry(pos, struct poly_node, link);
+ if (node->term.exp == UINT_MAX ||
+ !poly_list_add_term(&tmp,
+ node->term.coef / (node->term.exp + 1.0),
+ node->term.exp + 1)) {
+ poly_list_destroy(&tmp);
+ return false;
+ }
+ pos = pos->next;
+ }
+
+ __poly_list_replace(dst, &tmp);
+ return true;
+}
+
/*
* ============================================================
diff --git a/lab04/ui.c b/lab04/ui.c
index 7c36bd7..5b6329e 100644
--- a/lab04/ui.c
+++ b/lab04/ui.c
@@ -1013,6 +1013,7 @@ static void ui_draw_matrix(const struct ui_state *state, size_t selected)
"转置矩阵",
"计算行列式",
"计算特征值",
+ "计算逆矩阵",
};
tui_clear();
@@ -1134,7 +1135,8 @@ static void ui_matrix_binary(struct ui_state *state, char operation)
static void ui_matrix_unary(struct ui_state *state, int choice)
{
const char *title = choice == 5 ? "转置矩阵" :
- choice == 6 ? "计算行列式" : "计算特征值";
+ choice == 6 ? "计算行列式" :
+ choice == 7 ? "计算特征值" : "计算逆矩阵";
size_t selected;
if (!ui_read_size_value(title, "选择矩阵:1 = A,2 = B", &selected, state)) {
return;
@@ -1149,7 +1151,7 @@ static void ui_matrix_unary(struct ui_state *state, int choice)
return;
}
if (choice != 5 && matrix->rows != matrix->cols) {
- ui_set_status(state, "错误:行列式和特征值计算要求方阵");
+ ui_set_status(state, "错误:行列式、特征值和求逆要求方阵");
return;
}
bool success;
@@ -1163,14 +1165,19 @@ static void ui_matrix_unary(struct ui_state *state, int choice)
success = matrix_det(matrix, &state->matrix_determinant);
kind = UI_MATRIX_RESULT_DETERMINANT;
break;
- default:
+ case 7:
success = matrix_eigenvalues(matrix, &state->matrix_eigenvalues);
kind = UI_MATRIX_RESULT_EIGENVALUES;
break;
+ default:
+ success = matrix_inverse(&state->matrix_result, matrix);
+ kind = UI_MATRIX_RESULT_VALUE;
+ break;
}
if (!success) {
ui_set_status(state, choice == 7 ?
"错误:特征值计算失败(内存不足或迭代未收敛)" :
+ choice == 8 ? "错误:矩阵不可逆或内存分配失败" :
"错误:结果尺寸过大或内存分配失败");
return;
}
@@ -1191,6 +1198,7 @@ static void ui_matrix_action(struct ui_state *state, int choice)
case 5:
case 6:
case 7: ui_matrix_unary(state, choice); break;
+ case 8: ui_matrix_unary(state, choice); break;
}
}
@@ -1199,7 +1207,7 @@ static void ui_matrix_page(struct ui_state *state)
size_t selected = 0;
for (;;) {
ui_draw_matrix(state, selected);
- int choice = ui_menu_input(&selected, 8);
+ int choice = ui_menu_input(&selected, 9);
if (choice == -1) return;
if (choice >= 0) ui_matrix_action(state, choice);
}
@@ -1214,6 +1222,7 @@ static void ui_draw_poly_vec(const struct ui_state *state, size_t selected)
"A - B",
"A × B",
"多项式求导",
+ "多项式积分",
"查看存储结构",
};
@@ -1320,6 +1329,30 @@ static void ui_poly_vec_derivative(struct ui_state *state)
ui_set_status(state, "已完成多项式求导");
}
+static void ui_poly_vec_integral(struct ui_state *state)
+{
+ char input[128];
+ unsigned int which;
+ const struct poly_vec *source;
+
+ if (!ui_prompt_inline("多项式积分", "选择多项式(1=A,2=B):",
+ input, sizeof(input))) {
+ ui_set_status(state, "已取消");
+ return;
+ }
+ if (!ui_parse_unsigned(input, &which) || (which != 1 && which != 2)) {
+ ui_set_status(state, "错误:多项式选择无效");
+ return;
+ }
+ source = which == 1 ? &state->poly_vec_a : &state->poly_vec_b;
+ if (!poly_vec_integral(&state->poly_vec_result, source)) {
+ ui_set_status(state, "错误:多项式积分失败,指数可能超出范围");
+ return;
+ }
+ state->poly_vec_result_valid = true;
+ ui_set_status(state, "已完成多项式积分(积分常数为 0)");
+}
+
static void ui_poly_vec_storage(const struct ui_state *state)
{
tui_clear();
@@ -1367,6 +1400,9 @@ static void ui_poly_vec_action(struct ui_state *state, int choice)
ui_poly_vec_derivative(state);
break;
case 6:
+ ui_poly_vec_integral(state);
+ break;
+ case 7:
ui_poly_vec_storage(state);
break;
default:
@@ -1380,7 +1416,7 @@ static void ui_poly_vec_page(struct ui_state *state)
for (;;) {
ui_draw_poly_vec(state, selected);
- int choice = ui_menu_input(&selected, 7);
+ int choice = ui_menu_input(&selected, 8);
if (choice == -1) {
return;
}
@@ -1399,6 +1435,7 @@ static void ui_draw_poly_list(const struct ui_state *state, size_t selected)
"A - B",
"A × B",
"多项式求导",
+ "多项式积分",
"查看链表结构",
};
@@ -1505,6 +1542,30 @@ static void ui_poly_list_derivative(struct ui_state *state)
ui_set_status(state, "已完成多项式求导");
}
+static void ui_poly_list_integral(struct ui_state *state)
+{
+ char input[128];
+ unsigned int which;
+ const struct poly_list *source;
+
+ if (!ui_prompt_inline("多项式积分", "选择多项式(1=A,2=B):",
+ input, sizeof(input))) {
+ ui_set_status(state, "已取消");
+ return;
+ }
+ if (!ui_parse_unsigned(input, &which) || (which != 1 && which != 2)) {
+ ui_set_status(state, "错误:多项式选择无效");
+ return;
+ }
+ source = which == 1 ? &state->poly_list_a : &state->poly_list_b;
+ if (!poly_list_integral(&state->poly_list_result, source)) {
+ ui_set_status(state, "错误:多项式积分失败,指数可能超出范围");
+ return;
+ }
+ state->poly_list_result_valid = true;
+ ui_set_status(state, "已完成多项式积分(积分常数为 0)");
+}
+
static void ui_poly_list_storage(const struct ui_state *state)
{
tui_clear();
@@ -1551,6 +1612,9 @@ static void ui_poly_list_action(struct ui_state *state, int choice)
ui_poly_list_derivative(state);
break;
case 6:
+ ui_poly_list_integral(state);
+ break;
+ case 7:
ui_poly_list_storage(state);
break;
default:
@@ -1564,7 +1628,7 @@ static void ui_poly_list_page(struct ui_state *state)
for (;;) {
ui_draw_poly_list(state, selected);
- int choice = ui_menu_input(&selected, 7);
+ int choice = ui_menu_input(&selected, 8);
if (choice == -1) {
return;
}