summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lab04/tests/test.c306
1 files changed, 305 insertions, 1 deletions
diff --git a/lab04/tests/test.c b/lab04/tests/test.c
index 870d717..b40e7b3 100644
--- a/lab04/tests/test.c
+++ b/lab04/tests/test.c
@@ -117,7 +117,8 @@ static bool test_vec_resize_capacity_and_swap(void)
vec_swap(&vector, &other);
CHECK(*(int *)vec_front(&vector) == 22);
CHECK(*(int *)vec_front(&other) == 11);
- CHECK(!vec_reserve(&vector, SIZE_MAX));
+ volatile size_t impossible_capacity = SIZE_MAX;
+ CHECK(!vec_reserve(&vector, impossible_capacity));
vec_destroy(&vector);
vec_destroy(&other);
@@ -356,6 +357,254 @@ static bool test_poly_list_arithmetic_and_alias(void)
return true;
}
+static bool test_polynomial_integral(void)
+{
+ struct poly_vec vector, vector_result;
+ struct poly_list list, list_result;
+ poly_vec_init(&vector);
+ poly_vec_init(&vector_result);
+ poly_list_init(&list);
+ poly_list_init(&list_result);
+
+ CHECK(poly_vec_add_term(&vector, 6.0, 3));
+ CHECK(poly_vec_add_term(&vector, -4.0, 1));
+ CHECK(poly_vec_add_term(&vector, 2.0, 0));
+ CHECK(poly_vec_integral(&vector_result, &vector));
+ CHECK(vector_result.terms.size == 3);
+ CHECK(poly_vec_get_term(&vector_result, 4, &(double){ 0.0 }));
+ CHECK(poly_vec_at_const(&vector_result, 0)->coef == 1.5);
+ CHECK(poly_vec_at_const(&vector_result, 1)->coef == -2.0);
+ CHECK(poly_vec_at_const(&vector_result, 2)->coef == 2.0);
+ CHECK(poly_vec_integral(&vector_result, &vector_result));
+ CHECK(poly_vec_at_const(&vector_result, 0)->exp == 5);
+ CHECK(poly_vec_at_const(&vector_result, 0)->coef == 0.3);
+ CHECK(poly_vec_at_const(&vector_result, 1)->exp == 3);
+ CHECK(poly_vec_at_const(&vector_result, 1)->coef == -2.0 / 3.0);
+ CHECK(poly_vec_at_const(&vector_result, 2)->exp == 2);
+ CHECK(poly_vec_at_const(&vector_result, 2)->coef == 1.0);
+
+ CHECK(poly_list_add_term(&list, 6.0, 3));
+ CHECK(poly_list_add_term(&list, -4.0, 1));
+ CHECK(poly_list_add_term(&list, 2.0, 0));
+ CHECK(poly_list_integral(&list_result, &list));
+ double coefficient;
+ CHECK(poly_list_get_term(&list_result, 4, &coefficient));
+ CHECK(coefficient == 1.5);
+ CHECK(poly_list_get_term(&list_result, 2, &coefficient));
+ CHECK(coefficient == -2.0);
+ CHECK(poly_list_get_term(&list_result, 1, &coefficient));
+ CHECK(coefficient == 2.0);
+ CHECK(poly_list_integral(&list_result, &list_result));
+ CHECK(poly_list_get_term(&list_result, 5, &coefficient));
+ CHECK(coefficient == 0.3);
+ CHECK(poly_list_get_term(&list_result, 3, &coefficient));
+ CHECK(coefficient == -2.0 / 3.0);
+ CHECK(poly_list_get_term(&list_result, 2, &coefficient));
+ CHECK(coefficient == 1.0);
+
+ CHECK(poly_vec_set_term(&vector_result, 9.0, 0));
+ CHECK(poly_vec_set_term(&vector, 1.0, UINT_MAX));
+ CHECK(!poly_vec_integral(&vector_result, &vector));
+ CHECK(poly_vec_get_term(&vector_result, 0, &coefficient));
+ CHECK(coefficient == 9.0);
+ CHECK(poly_list_set_term(&list_result, 9.0, 0));
+ CHECK(poly_list_set_term(&list, 1.0, UINT_MAX));
+ CHECK(!poly_list_integral(&list_result, &list));
+ CHECK(poly_list_get_term(&list_result, 0, &coefficient));
+ CHECK(coefficient == 9.0);
+
+ poly_vec_destroy(&vector);
+ poly_vec_destroy(&vector_result);
+ poly_list_destroy(&list);
+ poly_list_destroy(&list_result);
+ return true;
+}
+
+static bool test_polynomial_integral_edges(void)
+{
+ struct poly_vec vector, vector_result;
+ struct poly_list list, list_result;
+ poly_vec_init(&vector);
+ poly_vec_init(&vector_result);
+ poly_list_init(&list);
+ poly_list_init(&list_result);
+
+ CHECK(poly_vec_add_term(&vector_result, 9.0, 0));
+ CHECK(poly_vec_integral(&vector_result, &vector));
+ CHECK(poly_vec_empty(&vector_result));
+ CHECK(poly_list_add_term(&list_result, 9.0, 0));
+ CHECK(poly_list_integral(&list_result, &list));
+ CHECK(poly_list_empty(&list_result));
+
+ CHECK(poly_vec_add_term(&vector, 7.0, 0));
+ CHECK(poly_vec_integral(&vector_result, &vector));
+ CHECK(vector_result.terms.size == 1);
+ CHECK(poly_vec_at_const(&vector_result, 0)->coef == 7.0);
+ CHECK(poly_vec_at_const(&vector_result, 0)->exp == 1);
+ CHECK(poly_list_add_term(&list, 7.0, 0));
+ CHECK(poly_list_integral(&list_result, &list));
+ double coefficient;
+ CHECK(poly_list_get_term(&list_result, 1, &coefficient));
+ CHECK(coefficient == 7.0);
+
+ CHECK(poly_vec_set_term(&vector, 1.0, 2));
+ CHECK(poly_vec_integral(&vector_result, &vector));
+ CHECK(fabs(poly_vec_at_const(&vector_result, 0)->coef - 1.0 / 3.0) < 1e-15);
+ CHECK(poly_vec_at_const(&vector_result, 0)->exp == 3);
+ CHECK(poly_vec_get_term(&vector, 2, &coefficient));
+ CHECK(coefficient == 1.0);
+ CHECK(poly_list_set_term(&list, 1.0, 2));
+ CHECK(poly_list_integral(&list_result, &list));
+ CHECK(poly_list_get_term(&list_result, 3, &coefficient));
+ CHECK(fabs(coefficient - 1.0 / 3.0) < 1e-15);
+ CHECK(poly_list_get_term(&list, 2, &coefficient));
+ CHECK(coefficient == 1.0);
+
+ CHECK(poly_vec_set_term(&vector_result, 8.0, 2));
+ CHECK(poly_vec_set_term(&vector_result, 9.0, 0));
+ CHECK(poly_vec_set_term(&vector, 1.0, UINT_MAX));
+ CHECK(!poly_vec_integral(&vector_result, &vector));
+ CHECK(poly_vec_get_term(&vector_result, 2, &coefficient));
+ CHECK(coefficient == 8.0);
+ CHECK(poly_vec_get_term(&vector_result, 0, &coefficient));
+ CHECK(coefficient == 9.0);
+
+ CHECK(poly_list_set_term(&list_result, 8.0, 2));
+ CHECK(poly_list_set_term(&list_result, 9.0, 0));
+ CHECK(poly_list_set_term(&list, 1.0, UINT_MAX));
+ CHECK(!poly_list_integral(&list_result, &list));
+ CHECK(poly_list_get_term(&list_result, 2, &coefficient));
+ CHECK(coefficient == 8.0);
+ CHECK(poly_list_get_term(&list_result, 0, &coefficient));
+ CHECK(coefficient == 9.0);
+
+ poly_vec_destroy(&vector);
+ poly_vec_destroy(&vector_result);
+ poly_list_destroy(&list);
+ poly_list_destroy(&list_result);
+ return true;
+}
+
+static bool test_vec_mutation_edges(void)
+{
+ struct vec vector;
+ vec_init(&vector, int);
+ int values[] = { 1, 2, 3 };
+ CHECK(vec_append(&vector, values, 3));
+
+ int *slot = vec_emplace_as(&vector, int, 1);
+ CHECK(slot != NULL);
+ *slot = 9;
+ slot = vec_emplace_back_as(&vector, int);
+ CHECK(slot != NULL);
+ *slot = 4;
+ int popped;
+ CHECK(vec_pop_back_copy(&vector, &popped));
+ CHECK(popped == 4);
+ CHECK(vec_erase_range(&vector, 1, 3) == (int *)vector.data + 1);
+ CHECK(vector.size == 2);
+ CHECK(*(int *)vec_at(&vector, 0) == 1);
+ CHECK(*(int *)vec_at(&vector, 1) == 3);
+ CHECK(vec_erase_range(&vector, 2, 1) == NULL);
+ vec_swap_erase(&vector, 0);
+ CHECK(vector.size == 1 && *(int *)vec_front(&vector) == 3);
+
+ vec_clear(&vector);
+ CHECK(vec_empty(&vector));
+ CHECK(vec_append(&vector, values, 3));
+ CHECK(vec_push_back(&vector, vec_at(&vector, 1)));
+ CHECK(vector.size == 4 && *(int *)vec_back(&vector) == 2);
+ CHECK(vec_assign_n(&vector, 3, vec_at(&vector, 1)));
+ CHECK(vector.size == 3);
+ for (size_t i = 0; i < vector.size; ++i) {
+ CHECK(*(int *)vec_at(&vector, i) == 2);
+ }
+ vec_destroy(&vector);
+ return true;
+}
+
+static bool test_list_replace_and_move(void)
+{
+ LIST_HEAD(head);
+ struct list_test_item first = { .value = 1 };
+ struct list_test_item second = { .value = 2 };
+ struct list_test_item third = { .value = 3 };
+ struct list_test_item replacement = { .value = 4 };
+ INIT_LIST_HEAD(&first.link);
+ INIT_LIST_HEAD(&second.link);
+ INIT_LIST_HEAD(&third.link);
+ INIT_LIST_HEAD(&replacement.link);
+ list_add_tail(&first.link, &head);
+ list_add_tail(&second.link, &head);
+ list_add_tail(&third.link, &head);
+
+ list_replace_init(&second.link, &replacement.link);
+ CHECK(list_entry(head.next, struct list_test_item, link)->value == 1);
+ CHECK(list_entry(head.next->next, struct list_test_item, link)->value == 4);
+ CHECK(second.link.next == &second.link && second.link.prev == &second.link);
+ list_move(&third.link, &head);
+ CHECK(list_entry(head.next, struct list_test_item, link)->value == 3);
+ list_move_tail(&first.link, &head);
+ CHECK(list_entry(head.prev, struct list_test_item, link)->value == 1);
+ CHECK(list_is_first(&third.link, &head));
+ CHECK(list_is_last(&first.link, &head));
+ list_del(&replacement.link);
+ CHECK(head.next->next == &first.link);
+ list_del(&third.link);
+ list_del(&first.link);
+ CHECK(list_empty(&head));
+ return true;
+}
+
+static bool test_polynomial_copy_and_derivative_edges(void)
+{
+ struct poly_vec vector, vector_copy, derivative;
+ struct poly_list list, list_copy, list_derivative;
+ poly_vec_init(&vector);
+ poly_vec_init(&vector_copy);
+ poly_vec_init(&derivative);
+ poly_list_init(&list);
+ poly_list_init(&list_copy);
+ poly_list_init(&list_derivative);
+ CHECK(poly_vec_add_term(&vector, 3.0, 2));
+ CHECK(poly_vec_add_term(&vector, 2.0, 1));
+ CHECK(poly_vec_add_term(&vector, 1.0, 0));
+ CHECK(poly_vec_copy(&vector_copy, &vector));
+ CHECK(poly_vec_equal(&vector, &vector_copy, 0.0));
+ CHECK(poly_vec_derivative(&derivative, &vector, 0));
+ CHECK(poly_vec_equal(&derivative, &vector, 0.0));
+ CHECK(poly_vec_derivative(&derivative, &vector, 1));
+ CHECK(derivative.terms.size == 2);
+ CHECK(poly_vec_at_const(&derivative, 0)->exp == 1);
+ CHECK(poly_vec_at_const(&derivative, 0)->coef == 6.0);
+ CHECK(poly_vec_at_const(&derivative, 1)->exp == 0);
+ CHECK(poly_vec_at_const(&derivative, 1)->coef == 2.0);
+ CHECK(poly_vec_derivative(&derivative, &vector, 3));
+ CHECK(poly_vec_empty(&derivative));
+
+ CHECK(poly_list_from_vec(&list, &vector));
+ CHECK(poly_list_copy(&list_copy, &list));
+ CHECK(poly_list_equal(&list, &list_copy, 0.0));
+ CHECK(poly_list_derivative(&list_derivative, &list, 0));
+ CHECK(poly_list_equal(&list_derivative, &list, 0.0));
+ CHECK(poly_list_derivative(&list_derivative, &list, 1));
+ double coefficient;
+ CHECK(poly_list_get_term(&list_derivative, 1, &coefficient));
+ CHECK(coefficient == 6.0);
+ CHECK(poly_list_get_term(&list_derivative, 0, &coefficient));
+ CHECK(coefficient == 2.0);
+ CHECK(poly_list_derivative(&list_derivative, &list, 3));
+ CHECK(poly_list_empty(&list_derivative));
+
+ poly_vec_destroy(&vector);
+ poly_vec_destroy(&vector_copy);
+ poly_vec_destroy(&derivative);
+ poly_list_destroy(&list);
+ poly_list_destroy(&list_copy);
+ poly_list_destroy(&list_derivative);
+ return true;
+}
+
static bool test_expression_nested_precedence_and_variables(void)
{
struct expression_context context;
@@ -967,6 +1216,54 @@ static bool test_matrix_eigenvalues(void)
return true;
}
+static bool test_matrix_inverse(void)
+{
+ struct matrix matrix, inverse, product;
+ matrix_init(&matrix);
+ matrix_init(&inverse);
+ matrix_init(&product);
+
+ double data[] = { 4, 7, 2, 6 };
+ double expected[] = { 0.6, -0.7, -0.2, 0.4 };
+ double identity[] = { 1, 0, 0, 1 };
+ CHECK(matrix_assign(&matrix, 2, 2, data));
+ CHECK(matrix_inverse(&inverse, &matrix));
+ for (size_t i = 0; i < 4; ++i) {
+ CHECK(fabs(((double *)inverse.elements.data)[i] - expected[i]) < 1e-12);
+ }
+ CHECK(matrix_mul(&product, &matrix, &inverse));
+ for (size_t i = 0; i < 4; ++i) {
+ CHECK(fabs(((double *)product.elements.data)[i] - identity[i]) < 1e-12);
+ }
+ CHECK(matrix_inverse(&matrix, &matrix));
+ for (size_t i = 0; i < 4; ++i) {
+ CHECK(fabs(((double *)matrix.elements.data)[i] - expected[i]) < 1e-12);
+ }
+
+ double three_by_three[] = { 1, 2, 3, 0, 1, 4, 5, 6, 0 };
+ double three_inverse[] = { -24, 18, 5, 20, -15, -4, -5, 4, 1 };
+ CHECK(matrix_assign(&matrix, 3, 3, three_by_three));
+ CHECK(matrix_inverse(&inverse, &matrix));
+ for (size_t i = 0; i < 9; ++i) {
+ CHECK(fabs(((double *)inverse.elements.data)[i] - three_inverse[i]) < 1e-12);
+ }
+
+ double singular[] = { 1, 2, 2, 4 };
+ double retained[] = { 31, 32, 33, 34 };
+ CHECK(matrix_assign(&matrix, 2, 2, singular));
+ CHECK(matrix_assign(&inverse, 2, 2, retained));
+ CHECK(!matrix_inverse(&inverse, &matrix));
+ CHECK(memcmp(inverse.elements.data, retained, sizeof(retained)) == 0);
+ CHECK(matrix_assign(&matrix, 2, 3, three_by_three));
+ CHECK(!matrix_inverse(&inverse, &matrix));
+ CHECK(memcmp(inverse.elements.data, retained, sizeof(retained)) == 0);
+
+ matrix_destroy(&matrix);
+ matrix_destroy(&inverse);
+ matrix_destroy(&product);
+ return true;
+}
+
static bool test_matrix_error_outputs(void)
{
struct matrix a, b, output, empty;
@@ -1062,7 +1359,14 @@ int main(void)
{ "matrix transpose", test_matrix_transpose },
{ "matrix determinant", test_matrix_determinant },
{ "matrix eigenvalues", test_matrix_eigenvalues },
+ { "matrix inverse", test_matrix_inverse },
{ "matrix error outputs", test_matrix_error_outputs },
+ { "polynomial integral", test_polynomial_integral },
+ { "polynomial integral edge cases", test_polynomial_integral_edges },
+ { "vec mutation edges", test_vec_mutation_edges },
+ { "list replace and move", test_list_replace_and_move },
+ { "polynomial copy and derivative edges",
+ test_polynomial_copy_and_derivative_edges },
};
size_t failures = 0;