From 7ac8df211cdc2ea1ddc6bfa658c9c7ca1f583741 Mon Sep 17 00:00:00 2001
From: "Vladimir V. Kisil" <V.Kisilv@leeds.ac.uk>
Date: Fri, 4 Jun 2021 09:20:48 +0100
Subject: [PATCH] Smarter conversion of a relational to Boolean

If a relational contains symbolic entries we look to ex::info
to decide either it can be converted to true value.


Signed-off-by: Vladimir V. Kisil <V.Kisilv@leeds.ac.uk>
---
 ginac/relational.cpp | 55 +++++++++++++++++++++++++++++---------------
 1 file changed, 36 insertions(+), 19 deletions(-)

diff --git a/ginac/relational.cpp b/ginac/relational.cpp
index 1b7e07fd..892d2e91 100644
--- a/ginac/relational.cpp
+++ b/ginac/relational.cpp
@@ -309,25 +309,42 @@ relational::safe_bool relational::make_safe_bool(bool cond) const
 relational::operator relational::safe_bool() const
 {
 	const ex df = lh-rh;
-	if (!is_exactly_a<numeric>(df))
-		// cannot decide on non-numerical results
-		return o==not_equal ? make_safe_bool(true) : make_safe_bool(false);
-
-	switch (o) {
-		case equal:
-			return make_safe_bool(ex_to<numeric>(df).is_zero());
-		case not_equal:
-			return make_safe_bool(!ex_to<numeric>(df).is_zero());
-		case less:
-			return make_safe_bool(ex_to<numeric>(df)<(*_num0_p));
-		case less_or_equal:
-			return make_safe_bool(ex_to<numeric>(df)<=(*_num0_p));
-		case greater:
-			return make_safe_bool(ex_to<numeric>(df)>(*_num0_p));
-		case greater_or_equal:
-			return make_safe_bool(ex_to<numeric>(df)>=(*_num0_p));
-		default:
-			throw(std::logic_error("invalid relational operator"));
+	// We treat numeric and symbolic expression differently
+	if (is_exactly_a<numeric>(df)) {
+		switch (o) {
+			case equal:
+				return make_safe_bool(ex_to<numeric>(df).is_zero());
+			case not_equal:
+				return make_safe_bool(!ex_to<numeric>(df).is_zero());
+			case less:
+				return make_safe_bool(ex_to<numeric>(df)<(*_num0_p));
+			case less_or_equal:
+				return make_safe_bool(ex_to<numeric>(df)<=(*_num0_p));
+			case greater:
+				return make_safe_bool(ex_to<numeric>(df)>(*_num0_p));
+			case greater_or_equal:
+				return make_safe_bool(ex_to<numeric>(df)>=(*_num0_p));
+			default:
+				throw(std::logic_error("invalid relational operator"));
+		}
+	} else {
+		// The conversion for symbolic expressions is based on the info flags
+		switch (o) {
+			case equal:
+				return make_safe_bool(df.is_zero());
+			case not_equal:
+				return make_safe_bool(! df.is_zero());
+			case less:
+				return make_safe_bool(df.info(info_flags::negative));
+			case less_or_equal:
+				return make_safe_bool((-df).info(info_flags::nonnegative));
+			case greater:
+				return make_safe_bool(df.info(info_flags::positive));
+			case greater_or_equal:
+				return make_safe_bool(df.info(info_flags::nonnegative));
+			default:
+				throw(std::logic_error("invalid relational operator"));
+		}
 	}
 }
 
-- 
2.30.2

