This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[jit] Support floating-point division; add test-quadratic.c
- From: David Malcolm <dmalcolm at redhat dot com>
- To: jit at gcc dot gnu dot org, gcc-patches at gcc dot gnu dot org
- Cc: David Malcolm <dmalcolm at redhat dot com>
- Date: Fri, 24 Jan 2014 15:15:39 -0500
- Subject: [jit] Support floating-point division; add test-quadratic.c
- Authentication-results: sourceware.org; auth=none
Committed to branch dmalcolm/jit:
Add testcase test-quadratic.c, written to achieve test coverage of
gcc_jit_rvalue_access_field - with this commit, the test suite has at
least one call to every public symbol in the API.
In the process, I found that GCC_JIT_BINARY_OP_DIVIDE on
floating-point types would lead to a crash when expanding gimple to RTL,
since the use of TRUNC_DIV_EXPR requires integer args. (Violating this
assumption led to a crash when the division by 2 was turned into a shift,
which the RTL expander assumes is on an integer).
Hence we update GCC_JIT_BINARY_OP_DIVIDE to internally pick either
RDIV_EXPR (floating point division) or TRUNC_DIV_EXPR (truncation towards
zero) based on the result-type of the binary op (my intent being to be
least-surprising to a C programmer).
gcc/jit/
* libgccjit.h (enum gcc_jit_binary_op): We will use the result
type to determine if GCC_JIT_BINARY_OP_DIVIDE should
truncate towards zero, or be floating-point division.
* internal-api.c (gcc::jit::context::new_binary_op): Likewise.
gcc/testsuite/
* jit.dg/test-quadratic.c: New test case, written to achieve test
coverage of gcc_jit_rvalue_access_field, but also exercising
division of doubles.
* jit.dg/test-combination.c: Add test-quadratic.c
* jit.dg/test-expressions.c: Add TODOs.
---
gcc/jit/ChangeLog.jit | 8 +
gcc/jit/internal-api.c | 8 +-
gcc/jit/libgccjit.h | 12 +-
gcc/testsuite/ChangeLog.jit | 10 +
gcc/testsuite/jit.dg/test-combination.c | 7 +
gcc/testsuite/jit.dg/test-expressions.c | 3 +
gcc/testsuite/jit.dg/test-quadratic.c | 488 ++++++++++++++++++++++++++++++++
7 files changed, 532 insertions(+), 4 deletions(-)
create mode 100644 gcc/testsuite/jit.dg/test-quadratic.c
diff --git a/gcc/jit/ChangeLog.jit b/gcc/jit/ChangeLog.jit
index cdf9ddb..f13d0c5 100644
--- a/gcc/jit/ChangeLog.jit
+++ b/gcc/jit/ChangeLog.jit
@@ -1,5 +1,13 @@
2014-01-24 David Malcolm <dmalcolm@redhat.com>
+ * libgccjit.h (enum gcc_jit_binary_op): We will use the result
+ type to determine if GCC_JIT_BINARY_OP_DIVIDE should
+ truncate towards zero, or be floating-point division.
+
+ * internal-api.c (gcc::jit::context::new_binary_op): Likewise.
+
+2014-01-24 David Malcolm <dmalcolm@redhat.com>
+
* internal-api.h (gcc::jit::context::get_str_option): New access
method.
(gcc::jit::context::get_int_option): Likewise.
diff --git a/gcc/jit/internal-api.c b/gcc/jit/internal-api.c
index 32af625..f95c09f 100644
--- a/gcc/jit/internal-api.c
+++ b/gcc/jit/internal-api.c
@@ -479,9 +479,13 @@ new_binary_op (location *loc,
break;
case GCC_JIT_BINARY_OP_DIVIDE:
- inner_op = TRUNC_DIV_EXPR;
+ if (FLOAT_TYPE_P (result_type->as_tree ()))
+ /* Floating-point division: */
+ inner_op = RDIV_EXPR;
+ else
+ /* Truncating to zero: */
+ inner_op = TRUNC_DIV_EXPR;
break;
- /* do we want separate floor divide vs frac divide? */
case GCC_JIT_BINARY_OP_MODULO:
inner_op = TRUNC_MOD_EXPR;
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index baf1541..dd287e8 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -497,9 +497,17 @@ enum gcc_jit_binary_op
/* Quotient of division of arithmetic values; analogous to:
(EXPR_A) / (EXPR_B)
- in C. */
+ in C.
+ The result type affects the kind of division: if the result type is
+ integer-based, then the result is truncated towards zero, whereas
+ a floating-point result type indicates floating-point division. */
GCC_JIT_BINARY_OP_DIVIDE,
- /* do we want separate floor divide vs frac divide? */
+
+ /* Quotient of division of floating-point values, without rounding;
+ analogous to:
+ (EXPR_A) / (EXPR_B)
+ in C. */
+ GCC_JIT_BINARY_OP_FLOATING_DIVIDE,
/* Remainder of division of arithmetic values; analogous to:
(EXPR_A) / (EXPR_B)
diff --git a/gcc/testsuite/ChangeLog.jit b/gcc/testsuite/ChangeLog.jit
index 5cd4a63..02e73c7 100644
--- a/gcc/testsuite/ChangeLog.jit
+++ b/gcc/testsuite/ChangeLog.jit
@@ -1,5 +1,15 @@
2014-01-23 David Malcolm <dmalcolm@redhat.com>
+ * jit.dg/test-quadratic.c: New test case, written to achieve test
+ coverage of gcc_jit_rvalue_access_field, but also exercising
+ division of doubles.
+
+ * jit.dg/test-combination.c: Add test-quadratic.c
+
+ * jit.dg/test-expressions.c: Add TODOs.
+
+2014-01-23 David Malcolm <dmalcolm@redhat.com>
+
* jit.dg/test-reading-struct.c: New test, to provide test coverage
of gcc_jit_type_get_const and gcc_jit_lvalue_access_field, in the
process uncovering bugs in how locals were handled.
diff --git a/gcc/testsuite/jit.dg/test-combination.c b/gcc/testsuite/jit.dg/test-combination.c
index 6a2372f..562f031 100644
--- a/gcc/testsuite/jit.dg/test-combination.c
+++ b/gcc/testsuite/jit.dg/test-combination.c
@@ -59,6 +59,13 @@
#undef code_making_callback
#undef verify_code
+/* test-quadratic.c */
+#define code_making_callback code_making_callback_quadratic
+#define verify_code verify_code_quadratic
+#include "test-quadratic.c"
+#undef code_making_callback
+#undef verify_code
+
/* test-reading-struct.c */
#define code_making_callback code_making_callback_reading_struct
#define verify_code verify_code_reading_struct
diff --git a/gcc/testsuite/jit.dg/test-expressions.c b/gcc/testsuite/jit.dg/test-expressions.c
index c270082..b224347 100644
--- a/gcc/testsuite/jit.dg/test-expressions.c
+++ b/gcc/testsuite/jit.dg/test-expressions.c
@@ -158,6 +158,7 @@ make_tests_of_binary_ops (gcc_jit_context *ctxt)
int_type,
GCC_JIT_BINARY_OP_DIVIDE,
"test_BINARY_OP_DIVIDE_on_int");
+ /* TODO: test for DIVIDE on float or double */
make_test_of_binary_op (ctxt,
int_type,
GCC_JIT_BINARY_OP_MODULO,
@@ -226,6 +227,8 @@ verify_binary_ops (gcc_jit_result *result)
CHECK_VALUE (test_BINARY_OP_DIVIDE_on_int (-1, -4), (-1 / -4));
CHECK_VALUE (test_BINARY_OP_DIVIDE_on_int (60, 5), 12);
+ /* TODO: test for DIVIDE on float or double */
+
test_fn test_BINARY_OP_MODULO_on_int =
(test_fn)gcc_jit_result_get_code (result,
"test_BINARY_OP_MODULO_on_int");
diff --git a/gcc/testsuite/jit.dg/test-quadratic.c b/gcc/testsuite/jit.dg/test-quadratic.c
new file mode 100644
index 0000000..7b154fe
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-quadratic.c
@@ -0,0 +1,488 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+struct quadratic
+{
+ double a;
+ double b;
+ double c;
+ double discriminant;
+};
+
+/* Let's try to inject the equivalent of:
+
+ extern double sqrt (double);
+
+ void
+ calc_discriminant (struct quadratic *q)
+ {
+ // (b^2 - 4ac)
+ q->discriminant = (q->b * q->b) - (4 * q->a * q->c);
+ }
+
+ int
+ test_quadratic (double a, double b, double c, double *r1, double *r2)
+ {
+ struct quadratic q;
+ q.a = a;
+ q.b = b;
+ q.c = c;
+ calc_discriminant (&q);
+ if (q.discriminant > 0)
+ {
+ double s = sqrt (q.discriminant);
+ *r1 = (-b + s) / (2 * a);
+ *r2 = (-b - s) / (2 * a);
+ return 2;
+ }
+ else if (q.discriminant == 0)
+ {
+ *r1 = -b / (2 * a);
+ return 1;
+ }
+ else return 0;
+ }
+*/
+
+struct quadratic_test
+{
+ gcc_jit_context *ctxt;
+
+ /* "double" and "(double *)". */
+ gcc_jit_type *numeric_type;
+ gcc_jit_type *numeric_type_ptr;
+
+ /* The value (double)0. */
+ gcc_jit_rvalue *zero;
+
+ gcc_jit_type *int_type;
+
+ /* "struct quadratic" */
+ gcc_jit_type *quadratic;
+ gcc_jit_field *a;
+ gcc_jit_field *b;
+ gcc_jit_field *c;
+ gcc_jit_field *discriminant;
+
+ /* "(struct quadratic *)" */
+ gcc_jit_type *quadratic_ptr;
+
+ gcc_jit_function *calc_discriminant;
+
+ gcc_jit_function *sqrt;
+
+};
+
+static void
+make_types (struct quadratic_test *testcase)
+{
+ testcase->numeric_type =
+ gcc_jit_context_get_type (testcase->ctxt, GCC_JIT_TYPE_DOUBLE);
+ testcase->numeric_type_ptr =
+ gcc_jit_type_get_pointer (testcase->numeric_type);
+ testcase->zero =
+ gcc_jit_context_zero (testcase->ctxt, testcase->numeric_type);
+
+ testcase->int_type =
+ gcc_jit_context_get_type (testcase->ctxt, GCC_JIT_TYPE_INT);
+
+ testcase->a =
+ gcc_jit_context_new_field (testcase->ctxt,
+ NULL,
+ testcase->numeric_type,
+ "a");
+ testcase->b =
+ gcc_jit_context_new_field (testcase->ctxt,
+ NULL,
+ testcase->numeric_type,
+ "b");
+ testcase->c =
+ gcc_jit_context_new_field (testcase->ctxt,
+ NULL,
+ testcase->numeric_type,
+ "c");
+ testcase->discriminant =
+ gcc_jit_context_new_field (testcase->ctxt,
+ NULL,
+ testcase->numeric_type,
+ "discriminant");
+ gcc_jit_field *fields[] = {testcase->a,
+ testcase->b,
+ testcase->c,
+ testcase->discriminant};
+ testcase->quadratic =
+ gcc_jit_context_new_struct_type (testcase->ctxt, NULL,
+ "quadratic", 4, fields);
+ testcase->quadratic_ptr = gcc_jit_type_get_pointer (testcase->quadratic);
+}
+
+static void
+make_sqrt (struct quadratic_test *testcase)
+{
+ gcc_jit_param *param_x =
+ gcc_jit_context_new_param (testcase->ctxt, NULL,
+ testcase->numeric_type, "x");
+ testcase->sqrt =
+ gcc_jit_context_new_function (testcase->ctxt, NULL,
+ GCC_JIT_FUNCTION_IMPORTED,
+ testcase->numeric_type,
+ "sqrt",
+ 1, ¶m_x,
+ 0);
+}
+
+static void
+make_calc_discriminant (struct quadratic_test *testcase)
+{
+ /* Build "calc_discriminant". */
+ gcc_jit_param *param_q =
+ gcc_jit_context_new_param (testcase->ctxt, NULL,
+ testcase->quadratic_ptr, "q");
+ testcase->calc_discriminant =
+ gcc_jit_context_new_function (testcase->ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ testcase->numeric_type,
+ "calc_discriminant",
+ 1, ¶m_q,
+ 0);
+ gcc_jit_function_add_comment (
+ testcase->calc_discriminant, NULL,
+ "(b^2 - 4ac)");
+
+ gcc_jit_rvalue *q_a =
+ gcc_jit_lvalue_as_rvalue (
+ gcc_jit_rvalue_dereference_field (
+ gcc_jit_param_as_rvalue (param_q),
+ NULL, "a"));
+ gcc_jit_rvalue *q_b =
+ gcc_jit_lvalue_as_rvalue (
+ gcc_jit_rvalue_dereference_field (
+ gcc_jit_param_as_rvalue (param_q),
+ NULL, "b"));
+ gcc_jit_rvalue *q_c =
+ gcc_jit_lvalue_as_rvalue (
+ gcc_jit_rvalue_dereference_field (
+ gcc_jit_param_as_rvalue (param_q),
+ NULL, "c"));
+
+ gcc_jit_function_add_assignment (
+ testcase->calc_discriminant, NULL,
+
+ /* q->discriminant =... */
+ gcc_jit_rvalue_dereference_field (
+ gcc_jit_param_as_rvalue (param_q),
+ NULL,
+ "discriminant"),
+
+ /* (q->b * q->b) - (4 * q->a * q->c) */
+ gcc_jit_context_new_binary_op (
+ testcase->ctxt, NULL,
+ GCC_JIT_BINARY_OP_MINUS,
+ testcase->numeric_type,
+
+ /* (q->b * q->b) */
+ gcc_jit_context_new_binary_op (
+ testcase->ctxt, NULL,
+ GCC_JIT_BINARY_OP_MULT,
+ testcase->numeric_type,
+ q_b, q_b),
+
+ /* (4 * (q->a * q->c)) */
+ gcc_jit_context_new_binary_op (
+ testcase->ctxt, NULL,
+ GCC_JIT_BINARY_OP_MULT,
+ testcase->numeric_type,
+ /* 4.0 */
+ gcc_jit_context_new_rvalue_from_int (
+ testcase->ctxt,
+ testcase->numeric_type,
+ 4),
+ /* (q->a * q->c) */
+ gcc_jit_context_new_binary_op (
+ testcase->ctxt, NULL,
+ GCC_JIT_BINARY_OP_MULT,
+ testcase->numeric_type,
+ q_a, q_c)))); /* end of gcc_jit_function_add_assignment call. */
+}
+
+static void
+make_test_quadratic (struct quadratic_test *testcase)
+{
+ gcc_jit_param *a =
+ gcc_jit_context_new_param (testcase->ctxt, NULL,
+ testcase->numeric_type, "a");
+ gcc_jit_param *b =
+ gcc_jit_context_new_param (testcase->ctxt, NULL,
+ testcase->numeric_type, "b");
+ gcc_jit_param *c =
+ gcc_jit_context_new_param (testcase->ctxt, NULL,
+ testcase->numeric_type, "c");
+ gcc_jit_param *r1 =
+ gcc_jit_context_new_param (testcase->ctxt, NULL,
+ testcase->numeric_type_ptr, "r1");
+ gcc_jit_param *r2 =
+ gcc_jit_context_new_param (testcase->ctxt, NULL,
+ testcase->numeric_type_ptr, "r2");
+ gcc_jit_param *params[] = {a, b, c, r1, r2};
+ gcc_jit_function *test_quadratic =
+ gcc_jit_context_new_function (testcase->ctxt, NULL,
+ GCC_JIT_FUNCTION_EXPORTED,
+ testcase->int_type,
+ "test_quadratic",
+ 5, params,
+ 0);
+
+ /* struct quadratic q; */
+ gcc_jit_lvalue *q =
+ gcc_jit_function_new_local (
+ test_quadratic, NULL,
+ testcase->quadratic,
+ "q");
+ /* q.a = a; */
+ gcc_jit_function_add_assignment (
+ test_quadratic, NULL,
+ gcc_jit_lvalue_access_field (q, NULL, "a"),
+ gcc_jit_param_as_rvalue (a));
+ /* q.b = b; */
+ gcc_jit_function_add_assignment (
+ test_quadratic, NULL,
+ gcc_jit_lvalue_access_field (q, NULL, "b"),
+ gcc_jit_param_as_rvalue (b));
+ /* q.c = c; */
+ gcc_jit_function_add_assignment (
+ test_quadratic, NULL,
+ gcc_jit_lvalue_access_field (q, NULL, "c"),
+ gcc_jit_param_as_rvalue (c));
+ /* calc_discriminant (&q); */
+ gcc_jit_rvalue *address_of_q = gcc_jit_lvalue_get_address (q, NULL);
+ gcc_jit_function_add_eval (
+ test_quadratic, NULL,
+ gcc_jit_context_new_call (
+ testcase->ctxt, NULL,
+ testcase->calc_discriminant,
+ 1, &address_of_q));
+
+ gcc_jit_label *on_positive_discriminant
+ = gcc_jit_function_new_forward_label (test_quadratic,
+ "positive_discriminant");
+
+ gcc_jit_label *on_nonpositive_discriminant
+ = gcc_jit_function_new_forward_label (test_quadratic,
+ "nonpositive_discriminant");
+
+ gcc_jit_label *on_zero_discriminant
+ = gcc_jit_function_new_forward_label (test_quadratic,
+ "zero_discriminant");
+
+ gcc_jit_label *on_negative_discriminant
+ = gcc_jit_function_new_forward_label (test_quadratic,
+ "negative_discriminant");
+
+ gcc_jit_function_add_comment (
+ test_quadratic, NULL,
+ "if (q.discriminant > 0)");
+ gcc_jit_function_add_conditional (
+ test_quadratic, NULL,
+ gcc_jit_context_new_comparison (
+ testcase->ctxt, NULL,
+ GCC_JIT_COMPARISON_GT,
+ gcc_jit_rvalue_access_field (
+ gcc_jit_lvalue_as_rvalue (q),
+ NULL,
+ "discriminant"),
+ testcase->zero),
+ on_positive_discriminant,
+ on_nonpositive_discriminant);
+
+ gcc_jit_function_place_forward_label (
+ test_quadratic, NULL,
+ on_positive_discriminant);
+ /* double s = sqrt (q.discriminant); */
+ gcc_jit_lvalue *s = gcc_jit_function_new_local (
+ test_quadratic, NULL,
+ testcase->numeric_type,
+ "s");
+ gcc_jit_rvalue *discriminant_of_q =
+ gcc_jit_rvalue_access_field (gcc_jit_lvalue_as_rvalue (q),
+ NULL,
+ "discriminant");
+ gcc_jit_function_add_assignment (
+ test_quadratic, NULL,
+ s,
+ gcc_jit_context_new_call (
+ testcase->ctxt, NULL,
+ testcase->sqrt,
+ 1, &discriminant_of_q));
+
+ gcc_jit_rvalue *minus_b =
+ gcc_jit_context_new_unary_op (
+ testcase->ctxt, NULL,
+ GCC_JIT_UNARY_OP_MINUS,
+ testcase->numeric_type,
+ gcc_jit_param_as_rvalue (b));
+ gcc_jit_rvalue *two_a =
+ gcc_jit_context_new_binary_op (
+ testcase->ctxt, NULL,
+ GCC_JIT_BINARY_OP_MULT,
+ testcase->numeric_type,
+ gcc_jit_context_new_rvalue_from_int (
+ testcase->ctxt,
+ testcase->numeric_type,
+ 2),
+ gcc_jit_param_as_rvalue (a));
+
+ gcc_jit_function_add_comment (
+ test_quadratic, NULL,
+ "*r1 = (-b + s) / (2 * a);");
+ gcc_jit_function_add_assignment (
+ test_quadratic, NULL,
+
+ /* "*r1 = ..." */
+ gcc_jit_rvalue_dereference (
+ gcc_jit_param_as_rvalue (r1), NULL),
+
+ /* (-b + s) / (2 * a) */
+ gcc_jit_context_new_binary_op (
+ testcase->ctxt, NULL,
+ GCC_JIT_BINARY_OP_DIVIDE,
+ testcase->numeric_type,
+ gcc_jit_context_new_binary_op (
+ testcase->ctxt, NULL,
+ GCC_JIT_BINARY_OP_PLUS,
+ testcase->numeric_type,
+ minus_b,
+ gcc_jit_lvalue_as_rvalue (s)),
+ two_a));
+
+ gcc_jit_function_add_comment (
+ test_quadratic, NULL,
+ "*r2 = (-b - s) / (2 * a)");
+ gcc_jit_function_add_assignment (
+ test_quadratic, NULL,
+
+ /* "*r2 = ..." */
+ gcc_jit_rvalue_dereference (
+ gcc_jit_param_as_rvalue (r2), NULL),
+
+ /* (-b - s) / (2 * a) */
+ gcc_jit_context_new_binary_op (
+ testcase->ctxt, NULL,
+ GCC_JIT_BINARY_OP_DIVIDE,
+ testcase->numeric_type,
+ gcc_jit_context_new_binary_op (
+ testcase->ctxt, NULL,
+ GCC_JIT_BINARY_OP_MINUS,
+ testcase->numeric_type,
+ minus_b,
+ gcc_jit_lvalue_as_rvalue (s)),
+ two_a));
+
+ /* "return 2;" */
+ gcc_jit_function_add_return (
+ test_quadratic, NULL,
+ gcc_jit_context_new_rvalue_from_int (
+ testcase->ctxt,
+ testcase->int_type,
+ 2));
+
+ /* "else if (q.discriminant == 0)" */
+ gcc_jit_function_place_forward_label (
+ test_quadratic, NULL,
+ on_nonpositive_discriminant);
+ gcc_jit_function_add_comment (
+ test_quadratic, NULL,
+ "else if (q.discriminant == 0)");
+ gcc_jit_function_add_conditional (
+ test_quadratic, NULL,
+ gcc_jit_context_new_comparison (
+ testcase->ctxt, NULL,
+ GCC_JIT_COMPARISON_EQ,
+ gcc_jit_rvalue_access_field (
+ gcc_jit_lvalue_as_rvalue (q),
+ NULL,
+ "discriminant"),
+ testcase->zero),
+ on_zero_discriminant,
+ on_negative_discriminant);
+
+ /* if (q.discriminant == 0) */
+ gcc_jit_function_place_forward_label (
+ test_quadratic, NULL,
+ on_zero_discriminant);
+
+ gcc_jit_function_add_comment (
+ test_quadratic, NULL,
+ "*r1 = -b / (2 * a);");
+ gcc_jit_function_add_assignment (
+ test_quadratic, NULL,
+
+ /* "*r1 = ..." */
+ gcc_jit_rvalue_dereference (
+ gcc_jit_param_as_rvalue (r1), NULL),
+
+ /* -b / (2 * a) */
+ gcc_jit_context_new_binary_op (
+ testcase->ctxt, NULL,
+ GCC_JIT_BINARY_OP_DIVIDE,
+ testcase->numeric_type,
+ minus_b,
+ two_a));
+
+ /* "return 1;" */
+ gcc_jit_function_add_return (
+ test_quadratic, NULL,
+ gcc_jit_context_one (testcase->ctxt, testcase->int_type));
+
+ /* else return 0; */
+ gcc_jit_function_place_forward_label (
+ test_quadratic, NULL,
+ on_negative_discriminant);
+ gcc_jit_function_add_return (
+ test_quadratic, NULL,
+ gcc_jit_context_zero (testcase->ctxt, testcase->int_type));
+}
+
+int
+code_making_callback (gcc_jit_context *ctxt, void *user_data)
+{
+ struct quadratic_test testcase;
+ memset (&testcase, 0, sizeof (testcase));
+ testcase.ctxt = ctxt;
+ make_types (&testcase);
+ make_sqrt (&testcase);
+ make_calc_discriminant (&testcase);
+ make_test_quadratic (&testcase);
+ return 0;
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ typedef int (*fn_type) (double a, double b, double c,
+ double *r1, double *r2);
+
+ CHECK_NON_NULL (result);
+
+ fn_type test_quadratic =
+ (fn_type)gcc_jit_result_get_code (result, "test_quadratic");
+ CHECK_NON_NULL (test_quadratic);
+
+ /* Verify that the code correctly solves quadratic equations. */
+ double r1, r2;
+
+ /* This one has two solutions: */
+ CHECK_VALUE (test_quadratic (1, 3, -4, &r1, &r2), 2);
+ CHECK_VALUE (r1, 1);
+ CHECK_VALUE (r2, -4);
+
+ /* This one has one solution: */
+ CHECK_VALUE (test_quadratic (4, 4, 1, &r1, &r2), 1);
+ CHECK_VALUE (r1, -0.5);
+
+ /* This one has no real solutions: */
+ CHECK_VALUE (test_quadratic (4, 1, 1, &r1, &r2), 0);
+}
--
1.7.11.7