diff --git a/spikes/ieee_floating_point/float.c b/spikes/ieee_floating_point/float.c index d91de74da2bbd0c1e9a3f947c6a760b12abf3fa5..7b26c9b29539bee05173a64e42b2023ceab2f13a 100644 --- a/spikes/ieee_floating_point/float.c +++ b/spikes/ieee_floating_point/float.c @@ -59,7 +59,7 @@ int main(int argc, char* argv[]) { } //who doesn't love fun facts? - printf("\nFirst of all, here are some fun facts on how your machine handles floating point numbers!\nMax value of floats: %f\nMin value of positive floats: %f\nRounding method: %s\nMantissa precision: %i bits\n", FLT_MAX, FLT_MIN, floatRound, FLT_MANT_DIG); + printf("\nFirst of all, here are some fun facts on how your machine handles floating point numbers!\nMax value of floats: %.10e\nMin value of positive floats: %.10e\nRounding method: %s\nMantissa precision: %i bits\n", FLT_MAX, FLT_MIN, floatRound, FLT_MANT_DIG); printf("\nYour input number as a float: %f\nRounding error: %lf\n", number, roundError); diff --git a/src/compute.c b/src/compute.c index ccab99e31176970da95deb617f529879feae7ebb..0cd7d8d530052d8f569f0b4dd833d289b9fa4cb7 100644 --- a/src/compute.c +++ b/src/compute.c @@ -15,19 +15,10 @@ /** * Creates computation struct. */ -COMPUTATION_STRUCT *computation_struct_new(float original_x) { +COMPUTATION_STRUCT *computation_struct_new(double original_x) { COMPUTATION_STRUCT *computation_struct = calloc_or_quit(1, sizeof(COMPUTATION_STRUCT)); computation_struct->x = original_x; - // Determines if rounding error was detected while calculating x_plus. - if (fetestexcept(FE_INEXACT) && FE_INEXACT) { - computation_struct->rounding_error = 1; - computation_struct->rounding_error_display = "Yes\0"; - } else { - computation_struct->rounding_error = 0; - computation_struct->rounding_error_display = "No\0"; - } - // Check if x is imaginary. If so, set as "Imaginary". Else, convert float to string. if (isnan(computation_struct->x)) { computation_struct->string_needs_free = 0; @@ -35,14 +26,11 @@ COMPUTATION_STRUCT *computation_struct_new(float original_x) { } else { computation_struct->string_needs_free = 1; computation_struct->x_as_string = calloc_or_quit(MAX_ANSWER_LENGTH, sizeof(char*)); - sprintf(computation_struct->x_as_string, "%f", computation_struct->x); + sprintf(computation_struct->x_as_string, "%.10E", computation_struct->x); } - // Remove any possible lingering floating point exceptions. - feclearexcept(FE_ALL_EXCEPT); - // Print out struct values. - // printf("x: %f\nx Rounding Error: %d\n\n", computation_struct->x, computation_struct->rounding_error); + // printf("x: %f\n", computation_struct->x); return computation_struct; } @@ -58,56 +46,44 @@ void computation_struct_free(COMPUTATION_STRUCT *computation_struct) { free(computation_struct); } +int calculate_roots(double a, double b, double c, COMPUTATION_STRUCT **root1, COMPUTATION_STRUCT **root2) { + double r1 = NAN; + double r2 = NAN; + double rooted = NAN; + int inexact = 0; -/** - * Calculate x plus. - */ -COMPUTATION_STRUCT *calculate_x_plus(float a, float b, float c) { - float x_plus = 0; - double determinant = 0; - double rooted = 0; - COMPUTATION_STRUCT *x_plus_struct; - - // printf("Calculating (%f + (%f^2 - 4*%f*%f)^(1/2))/(2*%f)\n", (-1*b), b, a, c, a); - - // Removes any possible lingering floating point exceptions. + // Remove any possible lingering floating point exceptions. feclearexcept(FE_ALL_EXCEPT); - // Determines the value of x_plus using the quadratic formula - determinant = (b * b) - (4 * a * c); + double determinant = (b * b) - 4 * a * c; + if (my_sqrt(determinant, &rooted) != 0) { - // TODO: Should this function return an error code? code_error_quit("Invalid parameters"); } - x_plus = (((-1 * b) + rooted) / (2 * a)); - x_plus_struct = computation_struct_new(x_plus); - return x_plus_struct; -} - - -/** - * Calculate x minus. - */ -COMPUTATION_STRUCT *calculate_x_minus(float a, float b, float c) { - float x_minus; - double determinant = 0; - double rooted = 0; - COMPUTATION_STRUCT *x_minus_struct; + // See Page 7 of "What Every Computer Scientist Should Know About Floating-Point Arithmetic" + // For Quadratic Equation that limits precision loss. + if (b < 0) { + r1 = (-b + rooted) / (2 * a); + r2 = c / (a * r1); + } else if (b > 0) { + r1 = (-b - rooted) / (2 * a); + r2 = c / (a * r1); + } else { + if (my_sqrt(c / a, &r1) != 0) { + code_error_quit("Invalid parameters"); + } + r2 = -r1; + } - // printf("Calculating (%f - (%f^2 - 4*%f*%f)^(1/2)/(2*%f)))\n", (-1*b), b, a, c, a); + if (fetestexcept(FE_INEXACT) && FE_INEXACT) { + inexact = 1; + } - // Removes any possible lingering floating point exceptions. - feclearexcept(FE_ALL_EXCEPT); + //printf("Roots: %.10E, %.10E\n", r1, r2); - // Determines the value of x_plus using the quadratic formula - determinant = (b * b) - (4 * a * c); - if (my_sqrt(determinant, &rooted) != 0) { - // TODO: Should this function return an error code? - code_error_quit("Invalid parameters"); - } - x_minus = (((-1 * b) - rooted) / (2 * a)); - x_minus_struct = computation_struct_new(x_minus); + *root1 = computation_struct_new(r1); + *root2 = computation_struct_new(r2); - return x_minus_struct; + return inexact; } diff --git a/src/compute.h b/src/compute.h index bbed7cff5a660fe78c618944dbe28f809ae175a7..30c2f1c3d3305f4559e77dfde2d62a2d05224977 100644 --- a/src/compute.h +++ b/src/compute.h @@ -13,18 +13,15 @@ // Struct typedef declaration. typedef struct { int string_needs_free; // Bool to hold if x_as_string needs a free() or not. - int rounding_error; // Bool to hold if rounding error was detected. - float x; // Computated value, unmodified. + double x; // Computated value, unmodified. char *x_as_string; // Answer may not always be a number. Use this for safe printing. - char *rounding_error_display; // Print display for rounding error. } COMPUTATION_STRUCT; // Function Prototypes. -COMPUTATION_STRUCT *computation_struct_new(float original_x); +COMPUTATION_STRUCT *computation_struct_new(double original_x); void computation_struct_free(COMPUTATION_STRUCT *computation_struct); -COMPUTATION_STRUCT *calculate_x_plus(float a, float b, float c); -COMPUTATION_STRUCT *calculate_x_minus(float a, float b, float c); +int calculate_roots(double a, double b, double c, COMPUTATION_STRUCT **root1, COMPUTATION_STRUCT **root2); #endif // _QUAD_SOLVER_COMPUTE_H diff --git a/src/main.c b/src/main.c index 24f867203226778f32dc45cca20ff7d21a7d4507..ce43aef6001aec5d8a40b4a0f8939c8324def4bb 100644 --- a/src/main.c +++ b/src/main.c @@ -17,6 +17,8 @@ // Import headers. +#include <float.h> +#include <math.h> #include "argparse.h" #include "compute.h" #include "helper.h" @@ -34,6 +36,7 @@ char parse_doubles(const char *string, double *a, double *b, double *c); * Initializes and runs program. */ int main(int argc, char* argv[]) { + int exit_code = 1; printf("\n"); ARGPARSE *argparse = argparse_new( @@ -88,7 +91,7 @@ int main(int argc, char* argv[]) { } free(input_string); } - printf("Received floats:\nA: %f\nB: %f\nC: %f\n", a, b, c); + printf("Received floats:\nA: %.10E\nB: %.10E\nC: %.10E\n", a, b, c); // Check for valid args. if (a == 0) { @@ -96,15 +99,36 @@ int main(int argc, char* argv[]) { printf("Recieved %fx^2 + %fx + %f. Invalid equation, A can't be zero.\n", a, b, c); printf("Note that non-integer values are parsed as \"0\".\n"); printf("Please try again.\n"); + // a, b, c > 0 or NAN + } else if ((a > 0 && (a < FLT_MIN || a > FLT_MAX)) || isnan(a)) { + printf("The first value is not within the exclusive range %.10e - %.10e\n", FLT_MIN, FLT_MAX); + printf("Please try again.\n"); + } else if ((b > 0 && (b < FLT_MIN || b > FLT_MAX)) || isnan(b)) { + printf("The second value is not within the exclusive range %.10e - %.10e\n", FLT_MIN, FLT_MAX); + printf("Please try again.\n"); + } else if ((c > 0 && (c < FLT_MIN || c > FLT_MAX)) || isnan(c)) { + printf("The last value is not within the exclusive range %.10e - %.10e\n", FLT_MIN, FLT_MAX); + printf("Please try again.\n"); + // a, b, c < 0 + } else if (a < 0 && (a < -FLT_MAX || a > -FLT_MIN)) { + printf("The first value is not within the exclusive range %.10e - %.10e\n", -FLT_MAX, -FLT_MIN); + printf("Please try again.\n"); + } else if (b < 0 && (b < -FLT_MAX || b > -FLT_MIN)) { + printf("The second value is not within the exclusive range %.10e - %.10e\n", -FLT_MAX, -FLT_MIN); + printf("Please try again.\n"); + } else if (c < 0 && (c < -FLT_MAX || c > -FLT_MIN)) { + printf("The last value is not within the exclusive range %.10e - %.10e\n", -FLT_MAX, -FLT_MIN); + printf("Please try again.\n"); } else { - // At least one of a, b, or c is non-zero. Execute solver. + // Values are valid. Execute solver. run_quad_solver(a, b, c); + exit_code = 0; } } argparse_free(argparse); - exit_program(0); + exit_program(exit_code); } @@ -112,20 +136,24 @@ int main(int argc, char* argv[]) { * Runs the quad solver equation and outputs results. */ void run_quad_solver(double a, double b, double c) { - COMPUTATION_STRUCT *x_plus_struct; - COMPUTATION_STRUCT *x_minus_struct; + printf("Calculating %.01Ex^2 + %.01Ex + %.01E = 0.\n", a, b, c); - printf("Calculating %fx^2 + %fx + %f.\n", a, b, c); + COMPUTATION_STRUCT *root1; + COMPUTATION_STRUCT *root2; + int inexact = 0; - x_plus_struct = calculate_x_plus(a, b, c); - x_minus_struct = calculate_x_minus(a, b, c); + inexact = calculate_roots(a, b, c, &root1, &root2); - printf("Results:\n\tX1: %s\n\tPossible rounding error: %s\n\n\tX2: %s\n\tPossible rounding error: %s\n", - x_plus_struct->x_as_string, x_plus_struct->rounding_error_display, - x_minus_struct->x_as_string, x_minus_struct->rounding_error_display); + char *round_error = "No"; + if (inexact) { + round_error = "Yes"; + } + + printf("Results:\n\tr1: %s\n\n\tr2: %s\n\n\tInexact: %s\n", + root1->x_as_string, root2->x_as_string, round_error); - computation_struct_free(x_plus_struct); - computation_struct_free(x_minus_struct); + computation_struct_free(root1); + computation_struct_free(root2); } @@ -135,6 +163,12 @@ void run_quad_solver(double a, double b, double c) { * Returns 0 if no error, 1 if error. */ char parse_doubles(const char *string, double *a, double *b, double *c) { + + if (sscanf(string, "%lf %lf %lf", a, b, c) != 3) { + return 1; + } + + return 0; char *token = calloc_or_quit(MAX_ANSWER_LENGTH+1, 1); char x = '\0'; size_t i = 0; diff --git a/tests/integration_tests/Makefile b/tests/integration_tests/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..a11b96b571f5531607003e8a3f2401400bb0a3f6 --- /dev/null +++ b/tests/integration_tests/Makefile @@ -0,0 +1,16 @@ +SRC_DIR = ../../src + +.PHONY: default all clean test_int_all quad_solver + +default: test_int_all +all: default + +# This will always run make in src +quad_solver: + cd $(SRC_DIR); make + +test_int_all: quad_solver + ./test_ranges.sh $(SRC_DIR) + +clean: + rm *.temp diff --git a/tests/integration_tests/test_ranges.sh b/tests/integration_tests/test_ranges.sh new file mode 100755 index 0000000000000000000000000000000000000000..f9445f1b0c53c53aaf9238e5eaa2f6c8d512be68 --- /dev/null +++ b/tests/integration_tests/test_ranges.sh @@ -0,0 +1,52 @@ +#!/bin/bash +POS_FLT_MIN="1.1754943509e-38" +POS_FLT_MIN_LESS="1.1754943507e-38" +POS_FLT_MAX="3.4028234663e+38" +POS_FLT_MAX_MORE="3.4028234664e+38" +SRC_DIR="$1" + +# Test Minimum values are allowed +$SRC_DIR/quad_solver -n $POS_FLT_MIN 1 1 > /dev/null +OUT_A=$? +$SRC_DIR/quad_solver -n 1 $POS_FLT_MIN 1 > /dev/null +OUT_B=$? +$SRC_DIR/quad_solver -n 1 1 $POS_FLT_MIN > /dev/null +OUT_C=$? +if [ $OUT_A != 0 ] || [ $OUT_B != 0 ] || [ $OUT_C != 0 ]; then + echo "Quad Solver should allow values equal to $POS_FLT_MIN" + echo "A: $OUT_A B: $OUT_B C: $OUT_C" +fi + +# Test less than Minimum values are NOT allowed +$SRC_DIR/quad_solver -n $POS_FLT_MIN_LESS 1 1 > /dev/null +OUT_A=$? +$SRC_DIR/quad_solver -n 1 $POS_FLT_MIN_LESS 1 > /dev/null +OUT_B=$? +$SRC_DIR/quad_solver -n 1 1 $POS_FLT_MIN_LESS > /dev/null +OUT_C=$? +if [ $OUT_A == 0 ] || [ $OUT_B == 0 ] || [ $OUT_C == 0 ]; then + echo "Quad Solver should not allow values less than $POS_FLT_MIN" +fi + +# Test Maximum values are allowed +$SRC_DIR/quad_solver -n $POS_FLT_MAX 1 1 > /dev/null +OUT_A=$? +$SRC_DIR/quad_solver -n 1 $POS_FLT_MAX 1 > /dev/null +OUT_B=$? +$SRC_DIR/quad_solver -n 1 1 $POS_FLT_MAX > /dev/null +OUT_C=$? +if [ $OUT_A != 0 ] || [ $OUT_B != 0 ] || [ $OUT_C != 0 ]; then + echo "Quad Solver should allow values equal to $POS_FLT_MAX" + echo "A: $OUT_A B: $OUT_B C: $OUT_C" +fi + +# Test more than Maximum values are NOT allowed +$SRC_DIR/quad_solver -n $POS_FLT_MAX_MORE 1 1 > /dev/null +OUT_A=$? +$SRC_DIR/quad_solver -n 1 $POS_FLT_MAX_MORE 1 > /dev/null +OUT_B=$? +$SRC_DIR/quad_solver -n 1 1 $POS_FLT_MAX_MORE > /dev/null +OUT_C=$? +if [ $OUT_A == 0 ] || [ $OUT_B == 0 ] || [ $OUT_C == 0 ]; then + echo "Quad Solver should not allow values more than $POS_FLT_MAX" +fi diff --git a/tests/unit_tests.c b/tests/unit_tests.c index 9f28cc4d66a580ddd2ed382da42db2cc9e6f02a9..e5bbe03c85da768122c7af5081894701c5fbc479 100644 --- a/tests/unit_tests.c +++ b/tests/unit_tests.c @@ -21,8 +21,6 @@ // Method Declaration. void test_argparse(); void test_computation_struct(); -void test_x_plus_computation(); -void test_x_minus_computation(); /** @@ -53,9 +51,7 @@ int main(int argc, char* argv[]) { // Now add tests to given suite. if ((CU_add_test(test_suite, "test_argparse", test_argparse) == NULL) || - (CU_add_test(test_suite, "test_computation_struct", test_computation_struct) == NULL) || - (CU_add_test(test_suite, "test_x_plus_computation", test_x_plus_computation) == NULL) || - (CU_add_test(test_suite, "test_x_minus_computation", test_x_minus_computation) == NULL)) { + (CU_add_test(test_suite, "test_computation_struct", test_computation_struct) == NULL)) { CU_cleanup_registry(); return CU_get_error(); @@ -94,184 +90,80 @@ void test_argparse(void) { * Tests that the computation struct will create and free properly. */ void test_computation_struct(void) { - float a_float; double a_double; COMPUTATION_STRUCT *a_struct; printf("\n"); // Test with value "0". - feclearexcept(FE_ALL_EXCEPT); // Removes possible lingering floating point exceptions. - a_float = 0; - a_struct = computation_struct_new(a_float); + a_double = 0; + a_struct = computation_struct_new(a_double); CU_ASSERT_PTR_NOT_NULL(a_struct); - CU_ASSERT_DOUBLE_EQUAL(a_struct->x, a_float, 0.000001); - CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "0.000000"); + CU_ASSERT_DOUBLE_EQUAL(a_struct->x, a_double, 0.000001); + CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "0.0000000000E+00"); CU_ASSERT_EQUAL(a_struct->string_needs_free, 1); - CU_ASSERT_EQUAL(a_struct->rounding_error, 0); computation_struct_free(a_struct); // Test with value "1". - feclearexcept(FE_ALL_EXCEPT); // Removes possible lingering floating point exceptions. - a_float = 1; - a_struct = computation_struct_new(a_float); + a_double = 1; + a_struct = computation_struct_new(a_double); CU_ASSERT_PTR_NOT_NULL(a_struct); - CU_ASSERT_DOUBLE_EQUAL(a_struct->x, a_float, 0.000001); - CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "1.000000"); + CU_ASSERT_DOUBLE_EQUAL(a_struct->x, a_double, 0.000001); + CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "1.0000000000E+00"); CU_ASSERT_EQUAL(a_struct->string_needs_free, 1); - CU_ASSERT_EQUAL(a_struct->rounding_error, 0); computation_struct_free(a_struct); // Test with value "-1". - feclearexcept(FE_ALL_EXCEPT); // Removes possible lingering floating point exceptions. - a_float = -1; - a_struct = computation_struct_new(a_float); + a_double = -1; + a_struct = computation_struct_new(a_double); CU_ASSERT_PTR_NOT_NULL(a_struct); - CU_ASSERT_DOUBLE_EQUAL(a_struct->x, a_float, 0.000001); - CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "-1.000000"); + CU_ASSERT_DOUBLE_EQUAL(a_struct->x, a_double, 0.000001); + CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "-1.0000000000E+00"); CU_ASSERT_EQUAL(a_struct->string_needs_free, 1); - CU_ASSERT_EQUAL(a_struct->rounding_error, 0); computation_struct_free(a_struct); // Test with value "5.55". - feclearexcept(FE_ALL_EXCEPT); // Removes possible lingering floating point exceptions. - a_float = 5.55; - a_struct = computation_struct_new(a_float); + a_double = 5.55; + a_struct = computation_struct_new(a_double); CU_ASSERT_PTR_NOT_NULL(a_struct); - CU_ASSERT_DOUBLE_EQUAL(a_struct->x, a_float, 0.000001); - CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "5.550000"); + CU_ASSERT_DOUBLE_EQUAL(a_struct->x, a_double, 0.000001); + CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "5.5500000000E+00"); CU_ASSERT_EQUAL(a_struct->string_needs_free, 1); - CU_ASSERT_EQUAL(a_struct->rounding_error, 0); computation_struct_free(a_struct); // Test with value "-5.55". - feclearexcept(FE_ALL_EXCEPT); // Removes possible lingering floating point exceptions. - a_float = -5.55; - a_struct = computation_struct_new(a_float); + a_double = -5.55; + a_struct = computation_struct_new(a_double); CU_ASSERT_PTR_NOT_NULL(a_struct); - CU_ASSERT_DOUBLE_EQUAL(a_struct->x, a_float, 0.000001); - CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "-5.550000"); + CU_ASSERT_DOUBLE_EQUAL(a_struct->x, a_double, 0.000001); + CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "-5.5500000000E+00"); CU_ASSERT_EQUAL(a_struct->string_needs_free, 1); - CU_ASSERT_EQUAL(a_struct->rounding_error, 0); computation_struct_free(a_struct); // Test with value "Infinity". - feclearexcept(FE_ALL_EXCEPT); // Removes possible lingering floating point exceptions. - a_float = INFINITY; - a_struct = computation_struct_new(a_float); + a_double = INFINITY; + a_struct = computation_struct_new(a_double); CU_ASSERT_PTR_NOT_NULL(a_struct); CU_ASSERT_TRUE(isinf(a_struct->x)); - CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "inf"); + CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "INF"); CU_ASSERT_EQUAL(a_struct->string_needs_free, 1); - CU_ASSERT_EQUAL(a_struct->rounding_error, 0); computation_struct_free(a_struct); // Test with value "-Infinity". - feclearexcept(FE_ALL_EXCEPT); // Removes possible lingering floating point exceptions. - a_float = -INFINITY; - a_struct = computation_struct_new(a_float); + a_double = -INFINITY; + a_struct = computation_struct_new(a_double); CU_ASSERT_PTR_NOT_NULL(a_struct); CU_ASSERT_TRUE(isinf(a_struct->x)); - CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "-inf"); + CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "-INF"); CU_ASSERT_EQUAL(a_struct->string_needs_free, 1); - CU_ASSERT_EQUAL(a_struct->rounding_error, 0); computation_struct_free(a_struct); // Test with value "NaN". - feclearexcept(FE_ALL_EXCEPT); // Removes possible lingering floating point exceptions. - a_float = NAN; - a_struct = computation_struct_new(a_float); + a_double = NAN; + a_struct = computation_struct_new(a_double); CU_ASSERT_PTR_NOT_NULL(a_struct); CU_ASSERT_TRUE(isnan(a_struct->x)); CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "Imaginary"); CU_ASSERT_EQUAL(a_struct->string_needs_free, 0); - CU_ASSERT_EQUAL(a_struct->rounding_error, 0); computation_struct_free(a_struct); - - // Test with value "1.23456789876543210". Should round. - feclearexcept(FE_ALL_EXCEPT); // Removes possible lingering floating point exceptions. - a_double = 1.23456789876543210; - a_float = (float) a_double; - a_struct = computation_struct_new(a_float); - CU_ASSERT_PTR_NOT_NULL(a_struct); - CU_ASSERT_DOUBLE_EQUAL(a_struct->x, a_float, 0.000001); - CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "1.234568"); - CU_ASSERT_EQUAL(a_struct->string_needs_free, 1); - CU_ASSERT_EQUAL(a_struct->rounding_error, 1); - computation_struct_free(a_struct); -} - - -/** - * Tests that the computation struct will create and free properly. - * Note: Only valid input should make it to this method. Thus don't test with bad a/b/c values. - */ -void test_x_plus_computation(void) { - COMPUTATION_STRUCT *a_struct; - - printf("\n"); - - // a=2, b=3, c=1. - a_struct = calculate_x_plus(2, 3, 1); - CU_ASSERT_DOUBLE_EQUAL(-0.5, a_struct->x, 0.01); - computation_struct_free(a_struct); - - // a=-4, b=-7, c=-3. - a_struct = calculate_x_plus(-4, -7, -3); - CU_ASSERT_DOUBLE_EQUAL(-1, a_struct->x, 0.1); - computation_struct_free(a_struct); - - // a=1.5788, b=14.0789, c=3.212. - a_struct = calculate_x_plus(1.5788, 14.0789, 3.212); - CU_ASSERT_DOUBLE_EQUAL(-0.234298, a_struct->x, 0.000001); - computation_struct_free(a_struct); - - // a=-6.54, b=59, c=2.7. - a_struct = calculate_x_plus(-6.54, 59, 2.7); - CU_ASSERT_DOUBLE_EQUAL(-0.045532, a_struct->x, 0.000001); - computation_struct_free(a_struct); - - // a=1, b=1, c=1. - a_struct = calculate_x_plus(1, 1, 1); - CU_ASSERT_TRUE(isnan(a_struct->x)); - CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "Imaginary"); - computation_struct_free(a_struct); -} - - -/** - * Tests that the computation struct will create and free properly. - * Note: Only valid input should make it to this method. Thus don't test with bad a/b/c values. - */ -void test_x_minus_computation(void) { - COMPUTATION_STRUCT *a_struct; - - printf("\n"); - - // a=2, b=3, c=1. - a_struct = calculate_x_minus(2, 3, 1); - CU_ASSERT_DOUBLE_EQUAL(-1, a_struct->x, 0.1); - computation_struct_free(a_struct); - - // a=-4, b=-7, c=-3. - a_struct = calculate_x_minus(-4, -7, -3); - CU_ASSERT_DOUBLE_EQUAL(-0.75, a_struct->x, 0.001); - computation_struct_free(a_struct); - - // a=1.5788, b=14.0789, c=3.212. - a_struct = calculate_x_minus(1.5788, 14.0789, 3.212); - CU_ASSERT_DOUBLE_EQUAL(-8.683170, a_struct->x, 0.000001); - computation_struct_free(a_struct); - - // a=-6.54, b=59, c=2.7. - a_struct = calculate_x_minus(-6.54, 59, 2.7); - CU_ASSERT_DOUBLE_EQUAL(9.066939, a_struct->x, 0.000001); - computation_struct_free(a_struct); - - // a=1, b=1, c=1. - a_struct = calculate_x_minus(1, 1, 1); - CU_ASSERT_TRUE(isnan(a_struct->x)); - CU_ASSERT_STRING_EQUAL(a_struct->x_as_string, "Imaginary"); - computation_struct_free(a_struct); - }