X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Frelational.cpp;h=05fe56e8b0103b8348ad6d7d418c8a17b11d0d7d;hp=158c41617fc812f0bb7dab4529b86ed1857d0362;hb=08aeba6a42b4147d495237eebe101cfe36f44989;hpb=e7cc6a764ff67b5885d6633385fac23ccc1dc9a7 diff --git a/ginac/relational.cpp b/ginac/relational.cpp index 158c4161..05fe56e8 100644 --- a/ginac/relational.cpp +++ b/ginac/relational.cpp @@ -3,7 +3,7 @@ * Implementation of relations between expressions */ /* - * GiNaC Copyright (C) 1999-2002 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2003 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 @@ -24,33 +24,26 @@ #include #include "relational.h" +#include "operators.h" #include "numeric.h" -#include "print.h" #include "archive.h" #include "utils.h" namespace GiNaC { -GINAC_IMPLEMENT_REGISTERED_CLASS(relational, basic) +GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(relational, basic, + print_func(&relational::do_print). + print_func(&basic::do_print_tree). + print_func(&relational::do_print_python_repr)) ////////// -// default ctor, dtor, copy ctor, assignment operator and helpers +// default constructor ////////// relational::relational() : basic(TINFO_relational) {} -void relational::copy(const relational & other) -{ - basic::copy(other); - lh=other.lh; - rh=other.rh; - o=other.o; -} - -DEFAULT_DESTROY(relational) - ////////// -// other ctors +// other constructors ////////// // public @@ -61,7 +54,7 @@ relational::relational(const ex & lhs, const ex & rhs, operators oper) : basic(T // archiving ////////// -relational::relational(const archive_node &n, const lst &sym_lst) : inherited(n, sym_lst) +relational::relational(const archive_node &n, lst &sym_lst) : inherited(n, sym_lst) { unsigned int opi; if (!(n.find_unsigned("op", opi))) @@ -87,57 +80,55 @@ DEFAULT_UNARCHIVE(relational) // public -void relational::print(const print_context & c, unsigned level) const +static void print_operator(const print_context & c, relational::operators o) { - if (is_a(c)) { - - inherited::print(c, level); - - } else { - - if (is_a(c)) { - c.s << class_name() << '('; - lh.print(c); - c.s << ','; - rh.print(c); - c.s << ",'"; - } else { - if (precedence() <= level) - c.s << "("; - lh.print(c, precedence()); - } - switch (o) { - case equal: - c.s << "=="; - break; - case not_equal: - c.s << "!="; - break; - case less: - c.s << "<"; - break; - case less_or_equal: - c.s << "<="; - break; - case greater: - c.s << ">"; - break; - case greater_or_equal: - c.s << ">="; - break; - default: - c.s << "(INVALID RELATIONAL OPERATOR)"; - } - if (is_a(c)) - c.s << "')"; - else { - rh.print(c, precedence()); - if (precedence() <= level) - c.s << ")"; - } + switch (o) { + case relational::equal: + c.s << "=="; + break; + case relational::not_equal: + c.s << "!="; + break; + case relational::less: + c.s << "<"; + break; + case relational::less_or_equal: + c.s << "<="; + break; + case relational::greater: + c.s << ">"; + break; + case relational::greater_or_equal: + c.s << ">="; + break; + default: + c.s << "(INVALID RELATIONAL OPERATOR)"; + break; } } +void relational::do_print(const print_context & c, unsigned level) const +{ + if (precedence() <= level) + c.s << "("; + lh.print(c, precedence()); + print_operator(c, o); + rh.print(c, precedence()); + if (precedence() <= level) + c.s << ")"; +} + +void relational::do_print_python_repr(const print_python_repr & c, unsigned level) const +{ + c.s << class_name() << '('; + lh.print(c); + c.s << ','; + rh.print(c); + c.s << ",'"; + print_operator(c, o); + c.s << "')"; +} + bool relational::info(unsigned inf) const { switch (inf) { @@ -159,19 +150,23 @@ bool relational::info(unsigned inf) const return 0; } -unsigned relational::nops() const +size_t relational::nops() const { return 2; } -ex & relational::let_op(int i) +ex relational::op(size_t i) const { - GINAC_ASSERT(i>=0); GINAC_ASSERT(i<2); return i==0 ? lh : rh; } +ex relational::map(map_function & f) const +{ + return (new relational(f(lh), f(rh), o))->setflag(status_flags::dynallocated); +} + ex relational::eval(int level) const { if (level==1) @@ -183,9 +178,20 @@ ex relational::eval(int level) const return (new relational(lh.eval(level-1),rh.eval(level-1),o))->setflag(status_flags::dynallocated | status_flags::evaluated); } -ex relational::simplify_ncmul(const exvector & v) const +ex relational::subs(const exmap & m, unsigned options) const +{ + const ex & subsed_lh = lh.subs(m, options); + const ex & subsed_rh = rh.subs(m, options); + + if (!are_ex_trivially_equal(lh, subsed_lh) || !are_ex_trivially_equal(rh, subsed_rh)) + return relational(subsed_lh, subsed_rh, o).subs_one_level(m, options); + else + return subs_one_level(m, options); +} + +ex relational::eval_ncmul(const exvector & v) const { - return lh.simplify_ncmul(v); + return lh.eval_ncmul(v); } // protected @@ -231,25 +237,25 @@ bool relational::match_same_type(const basic & other) const return o == oth.o; } -unsigned relational::return_type(void) const +unsigned relational::return_type() const { GINAC_ASSERT(lh.return_type()==rh.return_type()); return lh.return_type(); } -unsigned relational::return_type_tinfo(void) const +unsigned relational::return_type_tinfo() const { GINAC_ASSERT(lh.return_type_tinfo()==rh.return_type_tinfo()); return lh.return_type_tinfo(); } -unsigned relational::calchash(void) const +unsigned relational::calchash() const { unsigned v = golden_ratio_hash(tinfo()); unsigned lhash = lh.gethash(); unsigned rhash = rh.gethash(); - v = rotate_left_31(v); + v = rotate_left(v); switch(o) { case equal: case not_equal: @@ -270,12 +276,9 @@ unsigned relational::calchash(void) const lhash = rhash; break; } - v = rotate_left_31(v); + v = rotate_left(v); v ^= lhash; - // mask out numeric hashes: - v &= 0x7FFFFFFFU; - // store calculated hash value only if object is already evaluated if (flags & status_flags::evaluated) { setflag(status_flags::hash_calculated); @@ -290,13 +293,13 @@ unsigned relational::calchash(void) const ////////// /** Left hand side of relational. */ -ex relational::lhs(void) const +ex relational::lhs() const { return lh; } /** Right hand side of relational. */ -ex relational::rhs(void) const +ex relational::rhs() const { return rh; } @@ -305,31 +308,36 @@ ex relational::rhs(void) const // non-virtual functions in this class ////////// -/** Cast the relational into a boolean, mainly for evaluation within an +relational::safe_bool relational::make_safe_bool(bool cond) const +{ + return cond? &safe_bool_helper::nonnull : 0; +} + +/** Cast the relational into a boolean, mainly for evaluation within an * if-statement. Note that (a=b) == true in * the general symbolic case. A false result means the comparison is either * false or undecidable (except of course for !=, where true means either * unequal or undecidable). */ -relational::operator bool() const +relational::operator relational::safe_bool() const { const ex df = lh-rh; - if (!is_ex_exactly_of_type(df,numeric)) + if (!is_exactly_a(df)) // cannot decide on non-numerical results - return o==not_equal ? true : false; - + return o==not_equal ? make_safe_bool(true) : make_safe_bool(false); + switch (o) { case equal: - return ex_to(df).is_zero(); + return make_safe_bool(ex_to(df).is_zero()); case not_equal: - return !ex_to(df).is_zero(); + return make_safe_bool(!ex_to(df).is_zero()); case less: - return ex_to(df)<_num0; + return make_safe_bool(ex_to(df)<_num0); case less_or_equal: - return ex_to(df)<=_num0; + return make_safe_bool(ex_to(df)<=_num0); case greater: - return ex_to(df)>_num0; + return make_safe_bool(ex_to(df)>_num0); case greater_or_equal: - return ex_to(df)>=_num0; + return make_safe_bool(ex_to(df)>=_num0); default: throw(std::logic_error("invalid relational operator")); }