* 1 greater. */
int basic::compare(const basic & other) const
{
+#ifdef GINAC_COMPARE_STATISTICS
+ compare_statistics.total_basic_compares++;
+#endif
const unsigned hash_this = gethash();
const unsigned hash_other = other.gethash();
if (hash_this<hash_other) return -1;
if (hash_this>hash_other) return 1;
+#ifdef GINAC_COMPARE_STATISTICS
+ compare_statistics.compare_same_hashvalue++;
+#endif
const unsigned typeid_this = tinfo();
const unsigned typeid_other = other.tinfo();
// std::cout << std::endl;
// }
// return cmpval;
+#ifdef GINAC_COMPARE_STATISTICS
+ compare_statistics.compare_same_type++;
+#endif
return compare_same_type(other);
} else {
// std::cout << "hash collision, different types: "
* @see is_equal_same_type */
bool basic::is_equal(const basic & other) const
{
+#ifdef GINAC_COMPARE_STATISTICS
+ compare_statistics.total_basic_is_equals++;
+#endif
if (this->gethash()!=other.gethash())
return false;
+#ifdef GINAC_COMPARE_STATISTICS
+ compare_statistics.is_equal_same_hashvalue++;
+#endif
if (this->tinfo()!=other.tinfo())
return false;
GINAC_ASSERT(typeid(*this)==typeid(other));
+#ifdef GINAC_COMPARE_STATISTICS
+ compare_statistics.is_equal_same_type++;
+#endif
return is_equal_same_type(other);
}
int max_recursion_level = 1024;
+
+#ifdef GINAC_COMPARE_STATISTICS
+compare_statistics_t::~compare_statistics_t()
+{
+ std::clog << "ex::compare() called " << total_compares << " times" << std::endl;
+ std::clog << "nontrivial compares: " << nontrivial_compares << " times" << std::endl;
+ std::clog << "basic::compare() called " << total_basic_compares << " times" << std::endl;
+ std::clog << "same hashvalue in compare(): " << compare_same_hashvalue << " times" << std::endl;
+ std::clog << "compare_same_type() called " << compare_same_type << " times" << std::endl;
+ std::clog << std::endl;
+ std::clog << "ex::is_equal() called " << total_is_equals << " times" << std::endl;
+ std::clog << "nontrivial is_equals: " << nontrivial_is_equals << " times" << std::endl;
+ std::clog << "basic::is_equal() called " << total_basic_is_equals << " times" << std::endl;
+ std::clog << "same hashvalue in is_equal(): " << is_equal_same_hashvalue << " times" << std::endl;
+ std::clog << "is_equal_same_type() called " << is_equal_same_type << " times" << std::endl;
+ std::clog << std::endl;
+ std::clog << "basic::gethash() called " << total_gethash << " times" << std::endl;
+ std::clog << "used cached hashvalue " << gethash_cached << " times" << std::endl;
+}
+
+compare_statistics_t compare_statistics;
+#endif
+
} // namespace GiNaC
typedef std::map<ex, ex, ex_is_less> exmap;
+// Define this to enable some statistical output for comparisons and hashing
+#undef GINAC_COMPARE_STATISTICS
+
+#ifdef GINAC_COMPARE_STATISTICS
+class compare_statistics_t {
+public:
+ compare_statistics_t()
+ : total_compares(0), nontrivial_compares(0), total_basic_compares(0), compare_same_hashvalue(0), compare_same_type(0),
+ total_is_equals(0), nontrivial_is_equals(0), total_basic_is_equals(0), is_equal_same_hashvalue(0), is_equal_same_type(0),
+ total_gethash(0), gethash_cached(0) {}
+ ~compare_statistics_t();
+
+ unsigned long total_compares;
+ unsigned long nontrivial_compares;
+ unsigned long total_basic_compares;
+ unsigned long compare_same_hashvalue;
+ unsigned long compare_same_type;
+
+ unsigned long total_is_equals;
+ unsigned long nontrivial_is_equals;
+ unsigned long total_basic_is_equals;
+ unsigned long is_equal_same_hashvalue;
+ unsigned long is_equal_same_type;
+
+ unsigned long total_gethash;
+ unsigned long gethash_cached;
+};
+
+extern compare_statistics_t compare_statistics;
+#endif
+
+
/** Function object for map(). */
struct map_function {
typedef const ex & argument_type;
int compare(const basic & other) const;
bool is_equal(const basic & other) const;
const basic & hold() const;
- unsigned gethash() const { if (flags & status_flags::hash_calculated) return hashvalue; else return calchash(); }
+
+ unsigned gethash() const
+ {
+#ifdef GINAC_COMPARE_STATISTICS
+ compare_statistics.total_gethash++;
+#endif
+ if (flags & status_flags::hash_calculated) {
+#ifdef GINAC_COMPARE_STATISTICS
+ compare_statistics.gethash_cached++;
+#endif
+ return hashvalue;
+ } else {
+ return calchash();
+ }
+ }
+
unsigned tinfo() const {return tinfo_key;}
/** Set some status_flags. */
inline
int ex::compare(const ex & other) const
{
+#ifdef GINAC_COMPARE_STATISTICS
+ compare_statistics.total_compares++;
+#endif
if (bp == other.bp) // trivial case: both expressions point to same basic
return 0;
+#ifdef GINAC_COMPARE_STATISTICS
+ compare_statistics.nontrivial_compares++;
+#endif
const int cmpval = bp->compare(*other.bp);
+#if 1
if (cmpval == 0) {
// Expressions point to different, but equal, trees: conserve
// memory and make subsequent compare() operations faster by
- // making both expression point to the same tree.
+ // making both expressions point to the same tree.
share(other);
}
+#endif
return cmpval;
}
inline
bool ex::is_equal(const ex & other) const
{
+#ifdef GINAC_COMPARE_STATISTICS
+ compare_statistics.total_is_equals++;
+#endif
if (bp == other.bp) // trivial case: both expressions point to same basic
return true;
- return bp->is_equal(*other.bp);
+#ifdef GINAC_COMPARE_STATISTICS
+ compare_statistics.nontrivial_is_equals++;
+#endif
+ const bool equal = bp->is_equal(*other.bp);
+#if 0
+ if (equal) {
+ // Expressions point to different, but equal, trees: conserve
+ // memory and make subsequent compare() operations faster by
+ // making both expressions point to the same tree.
+ share(other);
+ }
+#endif
+ return equal;
}