]> www.ginac.de Git - ginac.git/blobdiff - ginac/relational.cpp
Finalize 1.8.1 release.
[ginac.git] / ginac / relational.cpp
index 92b54318392afd8ea89120522a0345ba6dc2f5b5..599a26352de202f949eddd9e8aac1fdee0cc6289 100644 (file)
@@ -3,7 +3,7 @@
  *  Implementation of relations between expressions */
 
 /*
- *  GiNaC Copyright (C) 1999-2019 Johannes Gutenberg University Mainz, Germany
+ *  GiNaC Copyright (C) 1999-2021 Johannes Gutenberg University Mainz, Germany
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -308,27 +308,51 @@ relational::safe_bool relational::make_safe_bool(bool cond) const
  *  unequal or undecidable). */
 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"));
+       const ex df = lh-rh;  // like ::canonical() method
+       // 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"));
+               }
        }
 }
 
+/** Returns an equivalent relational with zero right-hand side.
+ */
+ex relational::canonical() const
+{
+       return relational(lh-rh, _ex0, o);
+}
+
 } // namespace GiNaC