-void expairseq::construct_from_2_ex_via_exvector(ex const & lh, ex const & rh)
-{
- exvector v;
- v.reserve(2);
- v.push_back(lh);
- v.push_back(rh);
- construct_from_exvector(v);
-#ifdef EXPAIRSEQ_USE_HASHTAB
- GINAC_ASSERT((hashtabsize==0)||(hashtabsize>=minhashtabsize));
- GINAC_ASSERT(hashtabsize==calc_hashtabsize(seq.size()));
-#endif // def EXPAIRSEQ_USE_HASHTAB
-}
-
-void expairseq::construct_from_2_ex(ex const & lh, ex const & rh)
-{
- if (lh.bp->tinfo()==tinfo()) {
- if (rh.bp->tinfo()==tinfo()) {
-#ifdef EXPAIRSEQ_USE_HASHTAB
- unsigned totalsize=ex_to_expairseq(lh).seq.size()+
- ex_to_expairseq(rh).seq.size();
- if (calc_hashtabsize(totalsize)!=0) {
- construct_from_2_ex_via_exvector(lh,rh);
- } else {
-#endif // def EXPAIRSEQ_USE_HASHTAB
- construct_from_2_expairseq(ex_to_expairseq(lh),
- ex_to_expairseq(rh));
-#ifdef EXPAIRSEQ_USE_HASHTAB
- }
-#endif // def EXPAIRSEQ_USE_HASHTAB
- return;
- } else {
-#ifdef EXPAIRSEQ_USE_HASHTAB
- unsigned totalsize=ex_to_expairseq(lh).seq.size()+1;
- if (calc_hashtabsize(totalsize)!=0) {
- construct_from_2_ex_via_exvector(lh,rh);
- } else {
-#endif // def EXPAIRSEQ_USE_HASHTAB
- construct_from_expairseq_ex(ex_to_expairseq(lh),rh);
-#ifdef EXPAIRSEQ_USE_HASHTAB
- }
-#endif // def EXPAIRSEQ_USE_HASHTAB
- return;
- }
- } else if (rh.bp->tinfo()==tinfo()) {
-#ifdef EXPAIRSEQ_USE_HASHTAB
- unsigned totalsize=ex_to_expairseq(rh).seq.size()+1;
- if (calc_hashtabsize(totalsize)!=0) {
- construct_from_2_ex_via_exvector(lh,rh);
- } else {
-#endif // def EXPAIRSEQ_USE_HASHTAB
- construct_from_expairseq_ex(ex_to_expairseq(rh),lh);
-#ifdef EXPAIRSEQ_USE_HASHTAB
- }
-#endif // def EXPAIRSEQ_USE_HASHTAB
- return;
- }
-
-#ifdef EXPAIRSEQ_USE_HASHTAB
- if (calc_hashtabsize(2)!=0) {
- construct_from_2_ex_via_exvector(lh,rh);
- return;
- }
- hashtabsize=0;
-#endif // def EXPAIRSEQ_USE_HASHTAB
-
- if (is_ex_exactly_of_type(lh,numeric)) {
- if (is_ex_exactly_of_type(rh,numeric)) {
- combine_overall_coeff(lh);
- combine_overall_coeff(rh);
- } else {
- combine_overall_coeff(lh);
- seq.push_back(split_ex_to_pair(rh));
- }
- } else {
- if (is_ex_exactly_of_type(rh,numeric)) {
- combine_overall_coeff(rh);
- seq.push_back(split_ex_to_pair(lh));
- } else {
- expair p1=split_ex_to_pair(lh);
- expair p2=split_ex_to_pair(rh);
-
- int cmpval=p1.rest.compare(p2.rest);
- if (cmpval==0) {
- p1.coeff=ex_to_numeric(p1.coeff).add_dyn(ex_to_numeric(p2.coeff));
- if (!ex_to_numeric(p1.coeff).is_zero()) {
- // no further processing is necessary, since this
- // one element will usually be recombined in eval()
- seq.push_back(p1);
- }
- } else {
- seq.reserve(2);
- if (cmpval<0) {
- seq.push_back(p1);
- seq.push_back(p2);
- } else {
- seq.push_back(p2);
- seq.push_back(p1);
- }
- }
- }
- }
-}
-
-void expairseq::construct_from_2_expairseq(expairseq const & s1,
- expairseq const & s2)
-{
- combine_overall_coeff(s1.overall_coeff);
- combine_overall_coeff(s2.overall_coeff);
-
- epvector::const_iterator first1=s1.seq.begin();
- epvector::const_iterator last1=s1.seq.end();
- epvector::const_iterator first2=s2.seq.begin();
- epvector::const_iterator last2=s2.seq.end();
-
- seq.reserve(s1.seq.size()+s2.seq.size());
-
- bool needs_further_processing=false;
-
- while (first1!=last1 && first2!=last2) {
- int cmpval=(*first1).rest.compare((*first2).rest);
- if (cmpval==0) {
- // combine terms
- numeric const & newcoeff=ex_to_numeric((*first1).coeff).
- add(ex_to_numeric((*first2).coeff));
- if (!newcoeff.is_zero()) {
- seq.push_back(expair((*first1).rest,newcoeff));
- if (expair_needs_further_processing(seq.end()-1)) {
- needs_further_processing = true;
- }
- }
- ++first1;
- ++first2;
- } else if (cmpval<0) {
- seq.push_back(*first1);
- ++first1;
- } else {
- seq.push_back(*first2);
- ++first2;
- }
- }
-
- while (first1!=last1) {
- seq.push_back(*first1);
- ++first1;
- }
- while (first2!=last2) {
- seq.push_back(*first2);
- ++first2;
- }
-
- if (needs_further_processing) {
- epvector v=seq;
- seq.clear();
- construct_from_epvector(v);
- }
-}
-
-void expairseq::construct_from_expairseq_ex(expairseq const & s,
- ex const & e)
-{
- combine_overall_coeff(s.overall_coeff);
- if (is_ex_exactly_of_type(e,numeric)) {
- combine_overall_coeff(e);
- seq=s.seq;
- return;
- }
-
- epvector::const_iterator first=s.seq.begin();
- epvector::const_iterator last=s.seq.end();
- expair p=split_ex_to_pair(e);
-
- seq.reserve(s.seq.size()+1);
- bool p_pushed=0;
-
- bool needs_further_processing=false;
-
- // merge p into s.seq
- while (first!=last) {
- int cmpval=(*first).rest.compare(p.rest);
- if (cmpval==0) {
- // combine terms
- numeric const & newcoeff=ex_to_numeric((*first).coeff).
- add(ex_to_numeric(p.coeff));
- if (!newcoeff.is_zero()) {
- seq.push_back(expair((*first).rest,newcoeff));
- if (expair_needs_further_processing(seq.end()-1)) {
- needs_further_processing = true;
- }
- }
- ++first;
- p_pushed=1;
- break;
- } else if (cmpval<0) {
- seq.push_back(*first);
- ++first;
- } else {
- seq.push_back(p);
- p_pushed=1;
- break;
- }
- }
-
- if (p_pushed) {
- // while loop exited because p was pushed, now push rest of s.seq
- while (first!=last) {
- seq.push_back(*first);
- ++first;
- }
- } else {
- // while loop exited because s.seq was pushed, now push p
- seq.push_back(p);
- }
-
- if (needs_further_processing) {
- epvector v=seq;
- seq.clear();
- construct_from_epvector(v);
- }
-}
-
-void expairseq::construct_from_exvector(exvector const & v)
-{
- // simplifications: +(a,+(b,c),d) -> +(a,b,c,d) (associativity)
- // +(d,b,c,a) -> +(a,b,c,d) (canonicalization)
- // +(...,x,*(x,c1),*(x,c2)) -> +(...,*(x,1+c1+c2)) (c1, c2 numeric())
- // (same for (+,*) -> (*,^)
-
- make_flat(v);
-#ifdef EXPAIRSEQ_USE_HASHTAB
- combine_same_terms();
+void expairseq::construct_from_2_ex_via_exvector(const ex &lh, const ex &rh)
+{
+ exvector v;
+ v.reserve(2);
+ v.push_back(lh);
+ v.push_back(rh);
+ construct_from_exvector(v);
+#if EXPAIRSEQ_USE_HASHTAB
+ GINAC_ASSERT((hashtabsize==0)||(hashtabsize>=minhashtabsize));
+ GINAC_ASSERT(hashtabsize==calc_hashtabsize(seq.size()));
+#endif // EXPAIRSEQ_USE_HASHTAB
+}
+
+void expairseq::construct_from_2_ex(const ex &lh, const ex &rh)
+{
+ if (ex_to<basic>(lh).tinfo()==this->tinfo()) {
+ if (ex_to<basic>(rh).tinfo()==this->tinfo()) {
+#if EXPAIRSEQ_USE_HASHTAB
+ unsigned totalsize = ex_to<expairseq>(lh).seq.size() +
+ ex_to<expairseq>(rh).seq.size();
+ if (calc_hashtabsize(totalsize)!=0) {
+ construct_from_2_ex_via_exvector(lh,rh);
+ } else {
+#endif // EXPAIRSEQ_USE_HASHTAB
+ if(is_a<mul>(lh))
+ {
+ ex newrh=rename_dummy_indices_uniquely(lh, rh);
+ construct_from_2_expairseq(ex_to<expairseq>(lh),
+ ex_to<expairseq>(newrh));
+ }
+ else
+ construct_from_2_expairseq(ex_to<expairseq>(lh),
+ ex_to<expairseq>(rh));
+#if EXPAIRSEQ_USE_HASHTAB
+ }
+#endif // EXPAIRSEQ_USE_HASHTAB
+ return;
+ } else {
+#if EXPAIRSEQ_USE_HASHTAB
+ unsigned totalsize = ex_to<expairseq>(lh).seq.size()+1;
+ if (calc_hashtabsize(totalsize)!=0) {
+ construct_from_2_ex_via_exvector(lh, rh);
+ } else {
+#endif // EXPAIRSEQ_USE_HASHTAB
+ construct_from_expairseq_ex(ex_to<expairseq>(lh), rh);
+#if EXPAIRSEQ_USE_HASHTAB
+ }
+#endif // EXPAIRSEQ_USE_HASHTAB
+ return;
+ }
+ } else if (ex_to<basic>(rh).tinfo()==this->tinfo()) {
+#if EXPAIRSEQ_USE_HASHTAB
+ unsigned totalsize=ex_to<expairseq>(rh).seq.size()+1;
+ if (calc_hashtabsize(totalsize)!=0) {
+ construct_from_2_ex_via_exvector(lh,rh);
+ } else {
+#endif // EXPAIRSEQ_USE_HASHTAB
+ construct_from_expairseq_ex(ex_to<expairseq>(rh),lh);
+#if EXPAIRSEQ_USE_HASHTAB
+ }
+#endif // EXPAIRSEQ_USE_HASHTAB
+ return;
+ }
+
+#if EXPAIRSEQ_USE_HASHTAB
+ if (calc_hashtabsize(2)!=0) {
+ construct_from_2_ex_via_exvector(lh,rh);
+ return;
+ }
+ hashtabsize = 0;
+#endif // EXPAIRSEQ_USE_HASHTAB
+
+ if (is_exactly_a<numeric>(lh)) {
+ if (is_exactly_a<numeric>(rh)) {
+ combine_overall_coeff(lh);
+ combine_overall_coeff(rh);
+ } else {
+ combine_overall_coeff(lh);
+ seq.push_back(split_ex_to_pair(rh));
+ }
+ } else {
+ if (is_exactly_a<numeric>(rh)) {
+ combine_overall_coeff(rh);
+ seq.push_back(split_ex_to_pair(lh));
+ } else {
+ expair p1 = split_ex_to_pair(lh);
+ expair p2 = split_ex_to_pair(rh);
+
+ int cmpval = p1.rest.compare(p2.rest);
+ if (cmpval==0) {
+ p1.coeff = ex_to<numeric>(p1.coeff).add_dyn(ex_to<numeric>(p2.coeff));
+ if (!ex_to<numeric>(p1.coeff).is_zero()) {
+ // no further processing is necessary, since this
+ // one element will usually be recombined in eval()
+ seq.push_back(p1);
+ }
+ } else {
+ seq.reserve(2);
+ if (cmpval<0) {
+ seq.push_back(p1);
+ seq.push_back(p2);
+ } else {
+ seq.push_back(p2);
+ seq.push_back(p1);
+ }
+ }
+ }
+ }
+}
+
+void expairseq::construct_from_2_expairseq(const expairseq &s1,
+ const expairseq &s2)
+{
+ combine_overall_coeff(s1.overall_coeff);
+ combine_overall_coeff(s2.overall_coeff);
+
+ epvector::const_iterator first1 = s1.seq.begin();
+ epvector::const_iterator last1 = s1.seq.end();
+ epvector::const_iterator first2 = s2.seq.begin();
+ epvector::const_iterator last2 = s2.seq.end();
+
+ seq.reserve(s1.seq.size()+s2.seq.size());
+
+ bool needs_further_processing=false;
+
+ while (first1!=last1 && first2!=last2) {
+ int cmpval = (*first1).rest.compare((*first2).rest);
+
+ if (cmpval==0) {
+ // combine terms
+ const numeric &newcoeff = ex_to<numeric>(first1->coeff).
+ add(ex_to<numeric>(first2->coeff));
+ if (!newcoeff.is_zero()) {
+ seq.push_back(expair(first1->rest,newcoeff));
+ if (expair_needs_further_processing(seq.end()-1)) {
+ needs_further_processing = true;
+ }
+ }
+ ++first1;
+ ++first2;
+ } else if (cmpval<0) {
+ seq.push_back(*first1);
+ ++first1;
+ } else {
+ seq.push_back(*first2);
+ ++first2;
+ }
+ }
+
+ while (first1!=last1) {
+ seq.push_back(*first1);
+ ++first1;
+ }
+ while (first2!=last2) {
+ seq.push_back(*first2);
+ ++first2;
+ }
+
+ if (needs_further_processing) {
+ epvector v = seq;
+ seq.clear();
+ construct_from_epvector(v);
+ }
+}
+
+void expairseq::construct_from_expairseq_ex(const expairseq &s,
+ const ex &e)
+{
+ combine_overall_coeff(s.overall_coeff);
+ if (is_exactly_a<numeric>(e)) {
+ combine_overall_coeff(e);
+ seq = s.seq;
+ return;
+ }
+
+ epvector::const_iterator first = s.seq.begin();
+ epvector::const_iterator last = s.seq.end();
+ expair p = split_ex_to_pair(e);
+
+ seq.reserve(s.seq.size()+1);
+ bool p_pushed = false;
+
+ bool needs_further_processing=false;
+
+ // merge p into s.seq
+ while (first!=last) {
+ int cmpval = (*first).rest.compare(p.rest);
+ if (cmpval==0) {
+ // combine terms
+ const numeric &newcoeff = ex_to<numeric>(first->coeff).
+ add(ex_to<numeric>(p.coeff));
+ if (!newcoeff.is_zero()) {
+ seq.push_back(expair(first->rest,newcoeff));
+ if (expair_needs_further_processing(seq.end()-1))
+ needs_further_processing = true;
+ }
+ ++first;
+ p_pushed = true;
+ break;
+ } else if (cmpval<0) {
+ seq.push_back(*first);
+ ++first;
+ } else {
+ seq.push_back(p);
+ p_pushed = true;
+ break;
+ }
+ }
+
+ if (p_pushed) {
+ // while loop exited because p was pushed, now push rest of s.seq
+ while (first!=last) {
+ seq.push_back(*first);
+ ++first;
+ }
+ } else {
+ // while loop exited because s.seq was pushed, now push p
+ seq.push_back(p);
+ }
+
+ if (needs_further_processing) {
+ epvector v = seq;
+ seq.clear();
+ construct_from_epvector(v);
+ }
+}
+
+void expairseq::construct_from_exvector(const exvector &v)
+{
+ // simplifications: +(a,+(b,c),d) -> +(a,b,c,d) (associativity)
+ // +(d,b,c,a) -> +(a,b,c,d) (canonicalization)
+ // +(...,x,*(x,c1),*(x,c2)) -> +(...,*(x,1+c1+c2)) (c1, c2 numeric())
+ // (same for (+,*) -> (*,^)
+
+ make_flat(v);
+#if EXPAIRSEQ_USE_HASHTAB
+ combine_same_terms();