]> www.ginac.de Git - ginac.git/commitdiff
* Globalize the hash-value-space.
authorRichard Kreckel <Richard.Kreckel@uni-mainz.de>
Tue, 30 Apr 2002 23:42:41 +0000 (23:42 +0000)
committerRichard Kreckel <Richard.Kreckel@uni-mainz.de>
Tue, 30 Apr 2002 23:42:41 +0000 (23:42 +0000)
14 files changed:
ginac/add.cpp
ginac/add.h
ginac/basic.cpp
ginac/constant.cpp
ginac/expairseq.cpp
ginac/function.pl
ginac/matrix.cpp
ginac/mul.cpp
ginac/mul.h
ginac/numeric.cpp
ginac/numeric.h
ginac/relational.cpp
ginac/symbol.cpp
ginac/utils.h

index e6fb727ec5dd032af2e95caa5f55d2eeef69a614..bde5b2b71b2a96060fd278a888baf1dfc9b3dab5 100644 (file)
@@ -420,11 +420,6 @@ int add::compare_same_type(const basic & other) const
        return inherited::compare_same_type(other);
 }
 
-bool add::is_equal_same_type(const basic & other) const
-{
-       return inherited::is_equal_same_type(other);
-}
-
 unsigned add::return_type(void) const
 {
        if (seq.empty())
index 9288891921a9643cba026295eebc1f3706e37442..032267e67bbf79ee821e58084fe5927b2e1dec20 100644 (file)
@@ -62,7 +62,6 @@ public:
        ex simplify_ncmul(const exvector & v) const;
 protected:
        ex derivative(const symbol & s) const;
-       bool is_equal_same_type(const basic & other) const;
        unsigned return_type(void) const;
        unsigned return_type_tinfo(void) const;
        ex thisexpairseq(const epvector & v, const ex & oc) const;
index d4f06fe8017ff0668803f75d5293fa54a187062f..1b8109267179fabd87ec44ed23c7661d5dc5703b 100644 (file)
@@ -639,13 +639,10 @@ unsigned basic::calchash(void) const
 {
        unsigned v = golden_ratio_hash(tinfo());
        for (unsigned i=0; i<nops(); i++) {
-               v = rotate_left_31(v);
+               v = rotate_left(v);
                v ^= (const_cast<basic *>(this))->op(i).gethash();
        }
-       
-       // 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);
@@ -707,7 +704,9 @@ ex basic::subs(const ex & e, bool no_pattern) const
        return subs(ls, lr, no_pattern);
 }
 
-/** Compare objects to establish canonical ordering.
+extern "C" { int putchar(int c); }  // FIXME: removeme
+
+/** Compare objects syntactically to establish canonical ordering.
  *  All compare functions return: -1 for *this less than other, 0 equal,
  *  1 greater. */
 int basic::compare(const basic & other) const
@@ -722,7 +721,7 @@ int basic::compare(const basic & other) const
        if (typeid_this==typeid_other) {
                GINAC_ASSERT(typeid(*this)==typeid(other));
 //             int cmpval = compare_same_type(other);
-//             if ((cmpval!=0) && (hash_this<0x80000000U)) {
+//             if (cmpval!=0) {
 //                     std::cout << "hash collision, same type: " 
 //                               << *this << " and " << other << std::endl;
 //                     this->print(print_tree(std::cout));
@@ -733,17 +732,17 @@ int basic::compare(const basic & other) const
 //             return cmpval;
                return compare_same_type(other);
        } else {
-//                     std::cout << "hash collision, different types: " 
-//                               << *this << " and " << other << std::endl;
-//                     this->print(print_tree(std::cout));
-//                     std::cout << " and ";
-//                     other.print(print_tree(std::cout));
-//                     std::cout << std::endl;
+//             std::cout << "hash collision, different types: " 
+//                       << *this << " and " << other << std::endl;
+//             this->print(print_tree(std::cout));
+//             std::cout << " and ";
+//             other.print(print_tree(std::cout));
+//             std::cout << std::endl;
                return (typeid_this<typeid_other ? -1 : 1);
        }
 }
 
-/** Test for equality.
+/** Test for syntactic equality.
  *  This is only a quick test, meaning objects should be in the same domain.
  *  You might have to .expand(), .normal() objects first, depending on the
  *  domain of your computation, to get a more reliable answer.
index 5ba8475108af93ef8ccf90ff4fc5afb4fb747fc3..092c933cdc5c56e318dd2b986e3d5b8090854a8f 100644 (file)
@@ -187,11 +187,9 @@ bool constant::is_equal_same_type(const basic & other) const
 unsigned constant::calchash(void) const
 {
        hashvalue = golden_ratio_hash(tinfo() ^ serial);
-       // mask out numeric hashes:
-       hashvalue &= 0x7FFFFFFFU;
-       
+
        setflag(status_flags::hash_calculated);
-       
+
        return hashvalue;
 }
 
index 4257c3c7dd7e108ded8c7b9e9da08d205c44421b..44bc87ef2ec4132fd80f7a444f05ddb1b33e2a4a 100644 (file)
@@ -555,15 +555,14 @@ unsigned expairseq::calchash(void) const
                v ^= i->rest.gethash();
 #if !EXPAIRSEQ_USE_HASHTAB
                // rotation spoils commutativity!
-               v = rotate_left_31(v);
+               v = rotate_left(v);
                v ^= i->coeff.gethash();
 #endif // !EXPAIRSEQ_USE_HASHTAB
                ++i;
        }
-       
+
        v ^= overall_coeff.gethash();
-       v &= 0x7FFFFFFFU;
-       
+
        // store calculated hash value only if object is already evaluated
        if (flags &status_flags::evaluated) {
                setflag(status_flags::hash_calculated);
@@ -1122,7 +1121,7 @@ unsigned expairseq::calc_hashtabsize(unsigned sz) const
        size = nearest_power_of_2/hashtabfactor;
        if (size<minhashtabsize)
                return 0;
-       GINAC_ASSERT(hashtabsize<=0x8000000U); // really max size due to 31 bit hashing
+
        // hashtabsize must be a power of 2
        GINAC_ASSERT((1U << log2(size))==size);
        return size;
@@ -1131,16 +1130,14 @@ unsigned expairseq::calc_hashtabsize(unsigned sz) const
 unsigned expairseq::calc_hashindex(const ex &e) const
 {
        // calculate hashindex
-       unsigned hash = e.gethash();
        unsigned hashindex;
-       if (is_a_numeric_hash(hash)) {
+       if (is_a<numeric>(e)) {
                hashindex = hashmask;
        } else {
-               hashindex = hash &hashmask;
+               hashindex = e.gethash() & hashmask;
                // last hashtab entry is reserved for numerics
                if (hashindex==hashmask) hashindex = 0;
        }
-       GINAC_ASSERT(hashindex>=0);
        GINAC_ASSERT((hashindex<hashtabsize)||(hashtabsize==0));
        return hashindex;
 }
index 2fdeaaa4937c6e054dd1ed3739f073e754401d3d..bbadf37930d79fb067ff74ea295501cc1355769c 100755 (executable)
@@ -803,10 +803,10 @@ unsigned function::calchash(void) const
 {
        unsigned v = golden_ratio_hash(golden_ratio_hash(tinfo()) ^ serial);
        for (unsigned i=0; i<nops(); i++) {
-               v = rotate_left_31(v);
+               v = rotate_left(v);
                v ^= this->op(i).gethash();
        }
-       v &= 0x7FFFFFFFU;
+
        if (flags & status_flags::evaluated) {
                setflag(status_flags::hash_calculated);
                hashvalue = v;
index 5a68f132bafcefeac240e399680a695e6ba4bea9..7421e149435108893afb5f0bd62a262837a64044 100644 (file)
@@ -1288,7 +1288,7 @@ int matrix::fraction_free_elimination(const bool det)
        //
        // Bareiss (fraction-free) elimination in addition divides that element
        // by m[k-1](k-1,k-1) for k>1, where it can be shown by means of the
-       // Sylvester determinant that this really divides m[k+1](r,c).
+       // Sylvester identity that this really divides m[k+1](r,c).
        //
        // We also allow rational functions where the original prove still holds.
        // However, we must care for numerator and denominator separately and
index cc7d41aec2fcb4de1ec4ebb6647714fa2022161c..8127c3165f6a929e33125fca4f11e8cbfb75a225 100644 (file)
@@ -507,11 +507,6 @@ int mul::compare_same_type(const basic & other) const
        return inherited::compare_same_type(other);
 }
 
-bool mul::is_equal_same_type(const basic & other) const
-{
-       return inherited::is_equal_same_type(other);
-}
-
 unsigned mul::return_type(void) const
 {
        if (seq.empty()) {
@@ -590,7 +585,7 @@ expair mul::combine_ex_with_coeff_to_pair(const ex & e,
        // expression like (4^(1/3))^(3/2)
        if (are_ex_trivially_equal(c,_ex1))
                return split_ex_to_pair(e);
-       
+
        return split_ex_to_pair(power(e,c));
 }
        
@@ -603,7 +598,7 @@ expair mul::combine_pair_with_coeff_to_pair(const expair & p,
        // expression like (4^(1/3))^(3/2)
        if (are_ex_trivially_equal(c,_ex1))
                return p;
-       
+
        return split_ex_to_pair(power(recombine_pair_to_ex(p),c));
 }
        
@@ -612,25 +607,25 @@ ex mul::recombine_pair_to_ex(const expair & p) const
        if (ex_to<numeric>(p.coeff).is_equal(_num1)) 
                return p.rest;
        else
-               return power(p.rest,p.coeff);
+               return (new power(p.rest,p.coeff))->setflag(status_flags::dynallocated);
 }
 
 bool mul::expair_needs_further_processing(epp it)
 {
-       if (is_exactly_a<mul>((*it).rest) &&
-               ex_to<numeric>((*it).coeff).is_integer()) {
+       if (is_exactly_a<mul>(it->rest) &&
+               ex_to<numeric>(it->coeff).is_integer()) {
                // combined pair is product with integer power -> expand it
                *it = split_ex_to_pair(recombine_pair_to_ex(*it));
                return true;
        }
-       if (is_exactly_a<numeric>((*it).rest)) {
-               expair ep=split_ex_to_pair(recombine_pair_to_ex(*it));
+       if (is_exactly_a<numeric>(it->rest)) {
+               expair ep = split_ex_to_pair(recombine_pair_to_ex(*it));
                if (!ep.is_equal(*it)) {
                        // combined pair is a numeric power which can be simplified
                        *it = ep;
                        return true;
                }
-               if (ex_to<numeric>((*it).coeff).is_equal(_num1)) {
+               if (it->coeff.is_equal(_ex1)) {
                        // combined pair has coeff 1 and must be moved to the end
                        return true;
                }
index 65a291b7993a2b0216c0791541e117333cb705c0..f2862dcb5c6f46a0f5508cb141786de46b43d5fc 100644 (file)
@@ -65,7 +65,6 @@ public:
        ex simplify_ncmul(const exvector & v) const;
 protected:
        ex derivative(const symbol & s) const;
-       bool is_equal_same_type(const basic & other) const;
        unsigned return_type(void) const;
        unsigned return_type_tinfo(void) const;
        ex thisexpairseq(const epvector & v, const ex & oc) const;
index 1d9c78ba2687190f2e6cdf26c22ff4619ba7a1eb..7bdca3447cb17daa1621e3c0111b1d99e606f4ec 100644 (file)
@@ -584,7 +584,7 @@ unsigned numeric::calchash(void) const
        // equivalence relation on numbers).  As a consequence, 3 and 3.0 share
        // the same hashvalue.  That shouldn't really matter, though.
        setflag(status_flags::hash_calculated);
-       hashvalue = golden_ratio_hash(cln::equal_hashcode(cln::the<cln::cl_N>(value))) | 0x80000000U;
+       hashvalue = golden_ratio_hash(cln::equal_hashcode(cln::the<cln::cl_N>(value)));
        return hashvalue;
 }
 
index 3c7dba2c37aee6b178a978bd5088bed3b104aa7a..2d6d2959b5540a66917c76f0b162fee9abf49a96 100644 (file)
@@ -170,9 +170,6 @@ protected:
 extern const numeric I;
 extern _numeric_digits Digits;
 
-// deprecated macro, for internal use only
-#define is_a_numeric_hash(x) ((x)&0x80000000U)
-
 // global functions
 
 const numeric exp(const numeric &x);
index 4f4dc9ff9732b878f0d24fed98b02fd21216eba3..9ff452bec32e842846173757b0ccd9304c45c4b0 100644 (file)
@@ -249,7 +249,7 @@ unsigned relational::calchash(void) const
        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 +270,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);
index dae17b34a31c8488c6d888a2ff4c43493c625985..e393e95d2fd5f82034bc95069ef53c0e9c1244b7 100644 (file)
@@ -223,10 +223,7 @@ bool symbol::is_equal_same_type(const basic & other) const
 
 unsigned symbol::calchash(void) const
 {
-       // this is where the schoolbook method
-       // (golden_ratio_hash(tinfo()) ^ serial)
-       // is not good enough yet...
-       hashvalue = golden_ratio_hash(golden_ratio_hash(tinfo()) ^ serial);
+       hashvalue = golden_ratio_hash(tinfo() ^ serial);
        setflag(status_flags::hash_calculated);
        return hashvalue;
 }
index a161ee2bdf02390d4e406684d39f49be9435daae..392efd40b70776437144e5cb8ec1b6983171216b 100644 (file)
@@ -65,46 +65,37 @@ inline int compare_pointers(const void * a, const void * b)
        return 0;
 }
 
-/** Rotate lower 31 bits of unsigned value by one bit to the left
- *  (upper bit gets cleared). */
-inline unsigned rotate_left_31(unsigned n)
+/** Rotate bits of unsigned value by one bit to the left. */
+inline unsigned rotate_left(unsigned n)
 {
-       // clear highest bit and shift 1 bit to the left
-       n = (n & 0x7FFFFFFFU) << 1;
-       
-       // overflow? clear highest bit and set lowest bit
        if (n & 0x80000000U)
-               n = (n & 0x7FFFFFFFU) | 0x00000001U;
-       
-       GINAC_ASSERT(n<0x80000000U);
-       
+               n = n << 1 | 0x00000001U;
+       else
+               n = n << 1;
        return n;
 }
 
-/** Golden ratio hash function for the 31 least significant bits. */
+/** Truncated multiplication with golden ratio, for computing hash values. */
 inline unsigned golden_ratio_hash(unsigned n)
 {
        // This function requires arithmetic with at least 64 significant bits
 #if SIZEOF_LONG >= 8
        // So 'long' has 64 bits.  Excellent!  We prefer it because it might be
        // more efficient than 'long long'.
-       unsigned long l = n * 0x4f1bbcddL;
-       return (l & 0x7fffffffU) ^ (l >> 32);
+       unsigned long l = n * 0x4f1bbcddUL;
+       return (unsigned)l;
 #elif SIZEOF_LONG_LONG >= 8
        // This requires 'long long' (or an equivalent 64 bit type)---which is,
        // unfortunately, not ANSI-C++-compliant.
        // (Yet C99 demands it, which is reason for hope.)
-       unsigned long long l = n * 0x4f1bbcddL;
-       return (l & 0x7fffffffU) ^ (l >> 32);
-#elif SIZEOF_LONG_DOUBLE > 8
-       // If 'long double' is bigger than 64 bits, we assume that the mantissa
-       // has at least 64 bits. This is not guaranteed but it's a good guess.
-       // Unfortunately, it may lead to horribly slow code.
-       const static long double golden_ratio = .618033988749894848204586834370;
-       long double m = golden_ratio * n;
-       return unsigned((m - int(m)) * 0x80000000);
+       unsigned long long l = n * 0x4f1bbcddULL;
+       return (unsigned)l;
 #else
-#error "No 64 bit data type. You lose."
+       // Do the multiplication manually by splitting n up into the lower and
+       // upper two bytes.
+       const unsigned n0 = (n & 0x0000ffffU);
+       const unsigned n1 = (n & 0xffff0000U) >> 16;
+       return (n0 * 0x0000bcddU) + ((n1 * 0x0000bcddU + n0 * 0x00004f1bU) << 16);
 #endif
 }