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