Is relational::is_equal patch needed?
Pearu Peterson
pearu at cens.ioc.ee
Wed Nov 21 18:45:57 CET 2001
On Wed, 21 Nov 2001, Richard B. Kreckel wrote:
> Can you send a patch? I am planning to put out 1.0.1 tomorrow.
You can find patches attached. Features include
(a<b).is_equal(b>a) -> true
(a==b).is_equal(b==a) -> true
etc.
Note that I had to introduce also
relational::calchash
such that
hash(a < b) == hash(b > a)
hash(a == b) == hash(b == a)
etc.
in order to relational::is_equal_same_type will acctually called on
(a<b).is_equal(b>a)
Earlier a<b and b>a had different hash values and basic::is_equal used to
return false on such cases.
I run also `make check' to ensure that I didn't broke anything. All
tests passed fine.
Regards,
Pearu
-------------- next part --------------
--- relational.h.orig Wed Nov 21 14:35:32 2001
+++ relational.h Wed Nov 21 17:13:57 2001
@@ -63,6 +63,8 @@
bool match_same_type(const basic & other) const;
unsigned return_type(void) const;
unsigned return_type_tinfo(void) const;
+ bool is_equal_same_type(const basic & other) const;
+ unsigned calchash(void) const;
// new virtual functions which can be overridden by derived classes
public:
-------------- next part --------------
--- relational.cpp.orig Wed Nov 21 14:29:35 2001
+++ relational.cpp Wed Nov 21 18:09:23 2001
@@ -229,6 +229,70 @@
return rh;
}
+unsigned relational::calchash(void) const
+{
+ unsigned v = golden_ratio_hash(tinfo());
+ unsigned lhash = lh.gethash();
+ unsigned rhash = rh.gethash();
+
+ v = rotate_left_31(v);
+ switch(o) {
+ case equal: ;
+ case not_equal:
+ if (lhash>rhash) { v ^= lhash; lhash = rhash; }
+ else v ^= rhash;
+ break;
+ case less: ;
+ case less_or_equal:
+ v ^= rhash;
+ break;
+ case greater: ;
+ case greater_or_equal:
+ v ^= lhash; lhash = rhash;
+ break;
+ }
+ v = rotate_left_31(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);
+ hashvalue = v;
+ }
+
+ return v;
+}
+
+bool relational::is_equal_same_type(const basic & other) const
+{
+ GINAC_ASSERT(is_a<relational>(other));
+ relational const &oth = static_cast<const relational &>(other);
+ if (o == oth.o && lh.is_equal(oth.lh) && rh.is_equal(oth.rh))
+ return true;
+ switch (o) {
+ case equal: ;
+ case not_equal:
+ if (oth.o!=o) return false;
+ break;
+ case less:
+ if (oth.o!=greater) return false;
+ break;
+ case less_or_equal:
+ if (oth.o!=greater_or_equal) return false;
+ break;
+ case greater:
+ if (oth.o!=less) return false;
+ break;
+ case greater_or_equal:
+ if (oth.o!=less_or_equal) return false;
+ break;
+ }
+ return lh.is_equal(oth.rh) && rh.is_equal(oth.lh);
+}
+
//////////
// non-virtual functions in this class
//////////
More information about the GiNaC-devel
mailing list