00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "kl.h"
00029
00030 #ifdef VERBOSE
00031 #include <iostream>
00032 #include <fstream>
00033 #include <ctime>
00034 #include <sstream>
00035 #include <string>
00036 #endif
00037
00038 #include <cassert>
00039 #include <map>
00040 #include <stack>
00041 #include <stdexcept>
00042
00043 #include "bitmap.h"
00044 #include "basic_io.h"
00045 #include "blocks.h"
00046 #include "error.h"
00047 #include "hashtable.h"
00048 #include "kl_error.h"
00049 #include "prettyprint.h"
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 namespace atlas {
00074
00075 namespace kl {
00076
00077
00078
00079
00080
00081
00082 class KLPolEntry : public KLPol
00083 {
00084 public:
00085
00086 KLPolEntry() : KLPol() {}
00087 KLPolEntry(const KLPol& p) : KLPol(p) {}
00088
00089
00090 typedef KLStore Pooltype;
00091 size_t hashCode(size_t modulus) const;
00092
00093
00094 bool operator!=(Pooltype::const_reference e) const;
00095
00096 };
00097
00098
00099 namespace helper {
00100
00101 using namespace kl;
00102
00103 size_t firstAscent(const descents::DescentStatus&,
00104 const descents::DescentStatus&, size_t);
00105
00106 size_t goodAscent(const descents::DescentStatus&,
00107 const descents::DescentStatus&, size_t);
00108
00109 class Thicket;
00110
00111
00112 typedef hashtable::HashTable<KLPolEntry,KLIndex> KLHashStore;
00113
00114 class Helper
00115 : public KLContext
00116 {
00117
00118 friend class Thicket;
00119
00120 KLHashStore d_hashtable;
00121
00122
00123
00124 size_t prim_size;
00125 size_t nr_of_prim_nulls;
00126
00127 public:
00128
00129
00130 Helper(const KLContext&);
00131
00132 ~Helper()
00133 {
00134 #ifdef VERBOSE
00135 std::cout << "\nNumber of primitive pairs stored: "
00136 << prim_size << ".\n";
00137 std::cout << "Number of unrecorded primitive pairs: "
00138 << nr_of_prim_nulls << '.' << std::endl;
00139 #endif
00140 }
00141
00142
00143
00144
00145
00146
00147 blocks::BlockEltPair cayley(size_t s, BlockElt y) const {
00148 return d_support->block().cayley(s,y);
00149 }
00150
00151
00152
00153
00154 BlockElt cross(size_t s, BlockElt y) const {
00155 return d_support->block().cross(s,y);
00156 }
00157
00158
00159
00160
00161
00162 const descents::DescentStatus& descent(BlockElt y) const {
00163 return d_support->block().descent(y);
00164 }
00165
00166
00167
00168
00169
00170 descents::DescentStatus::Value descentValue(size_t s, BlockElt y) const {
00171 return d_support->descentValue(s,y);
00172 }
00173
00174 size_t firstDirectRecursion(BlockElt y) const;
00175
00176 blocks::BlockEltPair inverseCayley(size_t s, BlockElt y) const {
00177 return d_support->block().inverseCayley(s,y);
00178 }
00179
00180
00181
00182
00183
00184
00185 using KLContext::klPol;
00186
00187 KLPolRef klPol(BlockElt x, BlockElt y, KLRow::const_iterator klv,
00188 klsupport::PrimitiveRow::const_iterator p_begin,
00189 klsupport::PrimitiveRow::const_iterator p_end) const;
00190
00191 inline bool ascentMu(BlockElt x, BlockElt y, size_t s) const;
00192
00193 inline MuCoeff goodDescentMu(BlockElt x, BlockElt y, size_t s) const;
00194
00195 MuCoeff lengthOneMu(BlockElt x, BlockElt y) const;
00196
00197
00198
00199
00200
00201 size_t orbit(BlockElt y) const {
00202 return d_support->block().x(y);
00203 }
00204
00205
00206
00207
00208 size_t dualOrbit(BlockElt y) const {
00209 return d_support->block().y(y);
00210 }
00211
00212 MuCoeff type2Mu(BlockElt x, BlockElt y) const;
00213
00214
00215 void completePacket(BlockElt y);
00216
00217 void directRecursion(BlockElt y, size_t s);
00218
00219 void fill();
00220
00221 void fillKLRow(BlockElt y);
00222
00223 void fillMuRow(BlockElt y);
00224
00225 void fillThickets(BlockElt y);
00226
00227 void muCorrection(std::vector<KLPol>& klv,
00228 const klsupport::PrimitiveRow& e,
00229 BlockElt y, size_t s);
00230
00231 void recursionRow(std::vector<KLPol> & klv,
00232 const klsupport::PrimitiveRow& e, BlockElt y, size_t s);
00233
00234 void writeRow(const std::vector<KLPol>& klv,
00235 const klsupport::PrimitiveRow& e, BlockElt y);
00236 };
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 class Thicket {
00279
00280 public:
00281
00282 struct Edge;
00283 typedef std::vector<Edge> EdgeList;
00284
00285 private:
00286
00287 typedef klsupport::PrimitiveRow::iterator PI;
00288 typedef KLRow::iterator KLI;
00289
00290
00291
00292
00293 std::vector<BlockElt> d_vertices;
00294
00295
00296
00297
00298 std::vector<EdgeList> d_edges;
00299
00300
00301
00302
00303 std::vector<BlockElt> d_xlist;
00304
00305
00306
00307
00308
00309
00310
00311 std::vector<klsupport::PrimitiveRow> d_extr;
00312
00313
00314
00315
00316
00317
00318
00319
00320 std::vector<klsupport::PrimitiveRow> d_prim;
00321 std::vector<KLRow> d_klr;
00322 std::vector<PI> d_firstPrim;
00323 std::vector<KLI> d_firstKL;
00324 Helper* d_helper;
00325
00326 public:
00327
00328
00329 Thicket() {}
00330
00331 Thicket(Helper&, BlockElt);
00332
00333 ~Thicket() {}
00334
00335
00336
00337
00338
00339
00340 BlockElt cross(size_t s, BlockElt y) const {
00341 return d_helper->cross(s,y);
00342 }
00343
00344
00345
00346
00347
00348 const descents::DescentStatus& descent(BlockElt y) const {
00349 return d_helper->descent(y);
00350 }
00351
00352
00353
00354
00355
00356
00357 descents::DescentStatus::Value descentValue(size_t s, BlockElt y) const {
00358 return d_helper->descentValue(s,y);
00359 }
00360
00361
00362
00363
00364 const EdgeList& edgeList(size_t j) const {
00365 return d_edges[j];
00366 }
00367
00368
00369
00370
00371 KLPolRef klPol(BlockElt x, size_t pos) const {
00372 return d_helper->klPol(x,d_vertices[pos],d_firstKL[pos],d_firstPrim[pos],
00373 d_prim[pos].end());
00374 }
00375
00376
00377
00378
00379
00380
00381
00382
00383 const klsupport::PrimitiveRow& primitiveRow(size_t j) const {
00384 return d_prim[j];
00385 }
00386
00387 size_t nonExtremal(BlockElt x) const;
00388
00389
00390
00391
00392 KLIndex one() const {
00393 return d_helper->d_one;
00394 }
00395
00396
00397
00398
00399 size_t rank() const {
00400 return d_helper->rank();
00401 }
00402
00403
00404
00405
00406 size_t size() const {
00407 return d_vertices.size();
00408 }
00409
00410
00411
00412
00413 const std::vector<BlockElt>& vertices() const {
00414 return d_vertices;
00415 }
00416
00417
00418
00419
00420 KLIndex zero() const {
00421 return d_helper->d_zero;
00422 }
00423
00424
00425 bool ascentCompute(BlockElt x, size_t pos);
00426
00427 void edgeCompute(BlockElt x, size_t pos, const Edge& e);
00428
00429 void fill();
00430
00431 void fillXList();
00432
00433 KLRow& klRow(BlockElt y) {
00434 return d_helper->d_kl[y];
00435 }
00436
00437 KLStore& store() {
00438 return d_helper->d_store;
00439 }
00440
00441 };
00442
00443
00444
00445
00446
00447 struct Thicket::Edge {
00448
00449
00450
00451
00452 size_t source;
00453
00454
00455
00456
00457 size_t y;
00458
00459
00460
00461
00462 size_t s;
00463
00464
00465
00466
00467
00468 std::vector<KLPol> recursion;
00469
00470 Edge() {}
00471 Edge(BlockElt x, BlockElt y, size_t s, const std::vector<KLPol>& r)
00472 :source(x), y(y), s(s), recursion(r) {}
00473 };
00474
00475 class ThicketIterator {
00476
00477 private:
00478 typedef Thicket::EdgeList EdgeList;
00479
00480 std::stack<size_t> d_stack;
00481 bitmap::BitMap d_done;
00482 EdgeList::const_iterator d_current;
00483 EdgeList::const_iterator d_currentEnd;
00484 size_t d_pos;
00485
00486 const Thicket* d_thicket;
00487
00488 public:
00489
00490
00491 ThicketIterator(const Thicket&, size_t);
00492
00493
00494 bool operator() () const {
00495 return not d_stack.empty();
00496 }
00497
00498 size_t operator* () const {
00499 return d_pos;
00500 }
00501
00502 const Thicket::Edge& edge() const {
00503 return *d_current;
00504 }
00505
00506
00507 ThicketIterator& operator++();
00508
00509 };
00510
00511 }
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 namespace kl {
00524 using namespace atlas::kl::helper;
00525
00526 KLContext::KLContext(klsupport::KLSupport& kls)
00527 :d_state(),
00528 d_support(&kls),
00529 d_prim(),
00530 d_kl(),
00531 d_mu(),
00532 d_store(2),
00533 d_zero(0),
00534 d_one(1)
00535 {
00536 d_store[d_zero]=Zero;
00537 d_store[d_one]=One;
00538 }
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 KLContext::KLContext(const KLContext& other)
00549 :d_state(other.d_state),
00550 d_support(other.d_support),
00551 d_prim(other.d_prim),
00552 d_kl(other.d_kl),
00553 d_mu(other.d_mu),
00554 d_store(other.d_store),
00555 d_zero(other.d_zero),
00556 d_one(other.d_one)
00557 {}
00558
00559
00560
00561
00562
00563
00564
00565
00566 KLContext& KLContext::operator= (const KLContext& other)
00567 {
00568
00569 if (&other != this) {
00570 this->~KLContext();
00571 new(this) KLContext(other);
00572 }
00573
00574 return *this;
00575 }
00576
00577 void KLContext::swap(KLContext& other)
00578 {
00579 d_state.swap(other.d_state);
00580
00581 std::swap(d_support,other.d_support);
00582
00583 d_prim.swap(other.d_prim);
00584
00585 d_kl.swap(other.d_kl);
00586 d_mu.swap(other.d_mu);
00587
00588 d_store.swap(other.d_store);
00589 std::swap(d_zero,other.d_zero);
00590 std::swap(d_one,other.d_one);
00591 }
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 KLPolRef KLContext::klPol(BlockElt x, BlockElt y) const
00609 {
00610 using namespace klsupport;
00611
00612 const PrimitiveRow& pr = d_prim[y];
00613 const KLRow& klr = d_kl[y];
00614
00615 x=d_support->primitivize(x,descentSet(y));
00616 if (x>y) return Zero;
00617 PrimitiveRow::const_iterator xptr = std::lower_bound(pr.begin(),pr.end(),x);
00618 if (xptr == pr.end() or *xptr != x)
00619 return Zero;
00620 return d_store[klr[xptr - pr.begin()]];
00621 }
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631 MuCoeff KLContext::mu(BlockElt x, BlockElt y) const
00632 {
00633 const MuRow& mr = d_mu[y];
00634
00635 std::vector<BlockElt>::const_iterator xloc=
00636 std::lower_bound(mr.first.begin(),mr.first.end(),x);
00637
00638 if (xloc==mr.first.end() or *xloc!=x)
00639 return 0;
00640
00641 return mr.second[xloc-mr.first.begin()];
00642 }
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654 void KLContext::makeExtremalRow(klsupport::PrimitiveRow& e, BlockElt y) const
00655 {
00656 using namespace bitmap;
00657
00658 BitMap b(size());
00659 size_t c = lengthLess(length(y));
00660
00661 b.fill(c);
00662 b.insert(y);
00663
00664
00665 d_support->extremalize(b,descentSet(y));
00666
00667
00668 e.reserve(e.size()+b.size());
00669 std::copy(b.begin(),b.end(),back_inserter(e));
00670
00671 }
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681 void KLContext::makePrimitiveRow(klsupport::PrimitiveRow& e, BlockElt y) const
00682 {
00683 using namespace bitmap;
00684
00685 BitMap b(size());
00686 size_t c = lengthLess(length(y));
00687
00688 b.fill(c);
00689 b.insert(y);
00690
00691
00692 d_support->primitivize(b,descentSet(y));
00693
00694 e.reserve(e.size()+b.size());
00695 std::copy(b.begin(),b.end(),back_inserter(e));
00696
00697 }
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708 void KLContext::fill()
00709 {
00710 #ifdef VERBOSE
00711 std::cerr << "computing kazhdan-lusztig polynomials ..." << std::endl;
00712 #endif
00713
00714 if (d_state.test(KLFilled))
00715 return;
00716
00717 try
00718 {
00719 Helper help(*this);
00720
00721 help.fill();
00722 swap(help);
00723
00724 d_state.set(KLFilled);
00725
00726 #ifdef VERBOSE
00727 std::cerr << "done" << std::endl;
00728 #endif
00729 }
00730 catch (std::bad_alloc) {
00731 std::cerr << "\n memory full, KL computation abondoned." << std::endl;
00732 throw error::MemoryOverflow();
00733 }
00734
00735 }
00736
00737 bitmap::BitMap KLContext::primMap (BlockElt y) const
00738 {
00739 bitmap::BitMap b(size());
00740
00741
00742 b.fill(lengthLess(length(y)));
00743 b.insert(y);
00744
00745
00746 d_support->primitivize(b,descentSet(y));
00747
00748
00749
00750
00751 bitmap::BitMap result (b.size());
00752
00753
00754 const klsupport::PrimitiveRow& row=d_prim[y];
00755
00756
00757
00758 size_t position=0;
00759 size_t j=0;
00760 for (bitmap::BitMap::iterator i=b.begin(); i(); ++position,++i)
00761 if (*i==row[j])
00762 {
00763 result.insert(position); ++j;
00764 if (j==row.size()) break;
00765 }
00766
00767 return result;
00768 }
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785 inline size_t KLPolEntry::hashCode(size_t modulus) const
00786 { const polynomials::Polynomial<KLCoeff>& P=*this;
00787 if (P.isZero()) return 0;
00788 polynomials::Degree i=P.degree();
00789 size_t h=P[i];
00790 while (i-->0) h= ((h<<21)+(h<<13)+(h<<8)+(h<<5)+h+P[i]) & (modulus-1);
00791 return h;
00792 }
00793
00794 bool KLPolEntry::operator!=(KLPolEntry::Pooltype::const_reference e) const
00795 {
00796 if (degree()!=e.degree()) return true;
00797 if (isZero()) return false;
00798 for (polynomials::Degree i=0; i<=degree(); ++i)
00799 if ((*this)[i]!=e[i]) return true;
00800 return false;
00801 }
00802
00803 }
00804
00805
00806
00807
00808
00809
00810
00811
00812 namespace kl {
00813 namespace helper {
00814
00815
00816
00817 Helper::Helper(const KLContext& kl)
00818 : KLContext(kl)
00819 , d_hashtable(d_store)
00820 , prim_size(0), nr_of_prim_nulls(0)
00821 {}
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832 size_t Helper::firstDirectRecursion(BlockElt y) const
00833 {
00834 using namespace descents;
00835
00836 const descents::DescentStatus& d = descent(y);
00837
00838 for (size_t s = 0; s < rank(); ++s) {
00839 DescentStatus::Value v = d[s];
00840 if (DescentStatus::isDirectRecursion(v))
00841 return s;
00842 }
00843
00844 return rank();
00845 }
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860 KLPolRef Helper::klPol(BlockElt x, BlockElt y,
00861 KLRow::const_iterator klv,
00862 klsupport::PrimitiveRow::const_iterator p_begin,
00863 klsupport::PrimitiveRow::const_iterator p_end) const
00864 {
00865 BlockElt xp = d_support->primitivize(x,descentSet(y));
00866
00867 if (xp>y) return Zero;
00868 klsupport::PrimitiveRow::const_iterator xptr =
00869 std::lower_bound(p_begin,p_end,xp);
00870 if (xptr == p_end or *xptr != xp) return Zero;
00871 return d_store[klv[xptr-p_begin]];
00872 }
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884 inline bool Helper::ascentMu(BlockElt x, BlockElt y, size_t s) const
00885 {
00886 using namespace blocks;
00887 using namespace descents;
00888
00889 switch (descentValue(s,x)) {
00890 case DescentStatus::ComplexAscent:
00891 return cross(s,x) == y;
00892 case DescentStatus::RealNonparity:
00893 return false;
00894 case DescentStatus::ImaginaryTypeI:
00895 return cayley(s,x).first == y;
00896 case DescentStatus::ImaginaryTypeII:
00897 {
00898 BlockEltPair x1 = cayley(s,x);
00899
00900 return x1.first == y or x1.second == y;
00901 }
00902 default:
00903 assert(false);
00904 return false;
00905 }
00906 }
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918
00919 inline MuCoeff Helper::goodDescentMu(BlockElt x, BlockElt y, size_t s) const
00920 {
00921 using namespace descents;
00922
00923 blocks::BlockElt y1;
00924
00925 if (descentValue(s,y) == DescentStatus::ComplexDescent)
00926 y1 = cross(s,y);
00927 else
00928 y1 = inverseCayley(s,y).first;
00929
00930 switch (descentValue(s,x))
00931 {
00932 case DescentStatus::ImaginaryCompact:
00933 return MuCoeff(0);
00934 case DescentStatus::ComplexDescent:
00935 return mu(cross(s,x),y1);
00936 case DescentStatus::RealTypeI:
00937 {
00938 blocks::BlockEltPair x1 = inverseCayley(s,x);
00939 return mu(x1.first,y1)+mu(x1.second,y1);
00940 }
00941 case DescentStatus::RealTypeII:
00942 return mu(inverseCayley(s,x).first,y1);
00943
00944 default:
00945 assert(false);
00946 return MuCoeff(0);
00947 }
00948 }
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964 MuCoeff Helper::lengthOneMu(BlockElt x, BlockElt y) const
00965 {
00966
00967 bitset::RankFlags ascents=descentSet(y); ascents.andnot(descentSet(x));
00968 if (ascents.any())
00969 return ascentMu(x,y,ascents.firstBit()) ? MuCoeff(1) : MuCoeff(0);
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980 KLPolRef p=klPol(x,y);
00981 return p.isZero() ? MuCoeff(0) : p[0];
00982
00983
00984
00985 }
00986
00987
00988
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005 MuCoeff Helper::type2Mu(BlockElt x, BlockElt y) const
01006 {
01007 using namespace descents;
01008
01009 std::map<BlockElt,size_t> rel;
01010 std::stack<BlockElt> toDo;
01011
01012 rel.insert(std::make_pair(y,rank()));
01013 toDo.push(y);
01014
01015 size_t s;
01016 BlockElt y1 = y;
01017 MuCoeff mu = 0;
01018
01019 while (not toDo.empty()) {
01020 y1 = toDo.top();
01021 toDo.pop();
01022 if (y1 < y) {
01023 mu = KLContext::mu(x,y1);
01024 goto unwind;
01025 }
01026 s = firstAscent(descent(x),descent(y1),rank());
01027 if (s != rank()) {
01028 mu = ascentMu(x,y1,s);
01029 goto unwind;
01030 }
01031 for (s = 0; s < rank(); ++s) {
01032 DescentStatus::Value v = descentValue(s,y1);
01033 if (not DescentStatus::isDescent(v))
01034 continue;
01035 if (DescentStatus::isDirectRecursion(v)) {
01036 mu = goodDescentMu(x,y1,s);
01037 goto unwind;
01038 }
01039
01040 if (v == DescentStatus::ImaginaryCompact)
01041 continue;
01042
01043 {
01044 BlockElt y2 = cross(s,y1);
01045 if (rel.insert(std::make_pair(y2,s)).second)
01046 toDo.push(y2);
01047 }
01048 }
01049 }
01050
01051 unwind:
01052 while (y1 != y) {
01053 std::map<BlockElt,size_t>::iterator i = rel.find(y1);
01054 s = i->second;
01055 y1 = cross(s,y1);
01056
01057 mu = goodDescentMu(x,y1,s) - mu;
01058 }
01059
01060 return mu;
01061 }
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078 void Helper::completePacket(BlockElt y)
01079 {
01080 using namespace descents;
01081 using namespace klsupport;
01082
01083 std::pair<blocks::BlockElt,blocks::BlockElt> packet = block().R_packet(y);
01084 assert (packet.first==y);
01085 std::stack<BlockElt> filled;
01086 std::set<BlockElt> empty;
01087
01088 for (BlockElt y1 = packet.first; y1<packet.second; ++y1) {
01089 if (d_kl[y1].size() != 0)
01090 filled.push(y1);
01091 else
01092 empty.insert(y1);
01093 }
01094
01095 while (not filled.empty()) {
01096
01097 BlockElt y1 = filled.top();
01098 filled.pop();
01099
01100 for (size_t s = 0; s < rank(); ++s) {
01101 if (descentValue(s,y1) != DescentStatus::RealTypeII)
01102 continue;
01103 BlockElt y2 = cross(s,y1);
01104 std::set<BlockElt>::iterator i = empty.find(y2);
01105 if (i != empty.end()) {
01106
01107 std::vector<KLPol> klv;
01108 PrimitiveRow e;
01109 makeExtremalRow(e,y2);
01110 recursionRow(klv,e,y2,s);
01111
01112 for (size_t j = 0; j < klv.size(); ++j) {
01113 BlockElt x = e[j];
01114 try {
01115 klv[j].safeSubtract(klPol(x,y1));
01116 }
01117 catch (error::NumericUnderflow& e){
01118 throw kl_error::KLError(x,y1,__LINE__,
01119 static_cast<const KLContext&>(*this));
01120 }
01121 }
01122
01123 writeRow(klv,e,y2);
01124
01125 empty.erase(i);
01126 filled.push(y2);
01127 }
01128 }
01129 }
01130
01131 if (not empty.empty())
01132 fillThickets(y);
01133
01134 }
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146 void Helper::directRecursion(BlockElt y, size_t s)
01147 {
01148 using namespace klsupport;
01149
01150 std::vector<KLPol> klv;
01151 PrimitiveRow e;
01152
01153
01154 makeExtremalRow(e,y);
01155 recursionRow(klv,e,y,s);
01156
01157
01158 writeRow(klv,e,y);
01159
01160 }
01161
01162
01163
01164
01165
01166 void Helper::fill()
01167 {
01168
01169 d_support->fill();
01170
01171
01172 d_prim.resize(d_support->size());
01173 d_kl.resize(d_support->size());
01174 d_mu.resize(d_support->size());
01175
01176
01177 size_t minLength = length(0);
01178 size_t maxLength = length(d_kl.size() - 1);
01179
01180
01181 for (BlockElt y = 0; y < lengthLess(minLength+1); ++y) {
01182 d_prim[y].push_back(y);
01183 ++prim_size;
01184
01185 d_kl[y].push_back(d_one);
01186
01187 }
01188
01189
01190 #ifdef VERBOSE
01191 std::time_t time0;
01192 std::time(&time0);
01193 std::time_t time;
01194
01195 std::ifstream statm("/proc/self/statm");
01196 #endif
01197
01198
01199 for (size_t l=minLength+1; l<=maxLength; ++l)
01200 {
01201 for (BlockElt y=lengthLess(l);
01202 y<lengthLess(l+1); ++y)
01203 {
01204 #ifdef VERBOSE
01205 std::cerr << y << "\r";
01206 #endif
01207 try
01208 {
01209 fillKLRow(y);
01210 }
01211 catch (kl_error::KLError& e)
01212 {
01213 e("error: negative coefficient in k-l construction");
01214 }
01215 fillMuRow(y);
01216 }
01217
01218
01219 #ifdef VERBOSE
01220 {
01221 size_t p_capacity
01222 =d_hashtable.capacity()*sizeof(KLIndex)
01223 + d_store.capacity()*sizeof(KLPol);
01224 for (size_t i=0; i<d_store.size(); ++i)
01225 p_capacity+= (d_store[i].degree()+1)*sizeof(KLCoeff);
01226
01227 std::time(&time);
01228 double deltaTime = difftime(time, time0);
01229 std::cerr << "t=" << std::setw(5) << deltaTime
01230 << "s. l=" << std::setw(3) << l
01231 << ", y=" << std::setw(6)
01232 << lengthLess(l+1)-1
01233 << ", polys:" << std::setw(11) << d_store.size()
01234 << ", pmem:" << std::setw(11) << p_capacity
01235 << ", mat:" << std::setw(11) << prim_size
01236 << std::endl;
01237
01238 unsigned int size, resident,share,text,lib,data;
01239 statm.seekg(0,std::ios_base::beg);
01240 statm >> size >> resident >> share >> text >> lib >> data;
01241 std::cerr << "Current data size " << data*4 << "kB (" << data*4096
01242 << "), resident " << resident*4 << "kB, total "
01243 << size*4 << "kB.\n";
01244 }
01245 #endif
01246 }
01247
01248 #ifdef VERBOSE
01249 std::time(&time);
01250 double deltaTime = difftime(time, time0);
01251 std::cerr << std::endl;
01252 std::cerr << "Total elapsed time = " << deltaTime << "s." << std::endl;
01253 std::cerr << d_store.size() << " polynomials, "
01254 << prim_size << " matrix entries."<< std::endl;
01255
01256 std::cerr << std::endl;
01257 #endif
01258
01259 }
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274 void Helper::fillKLRow(BlockElt y)
01275 {
01276 using namespace klsupport;
01277
01278 if (d_kl[y].size())
01279 return;
01280
01281 std::pair<blocks::BlockElt,blocks::BlockElt> packet = block().R_packet(y);
01282 assert (packet.first==y);
01283 bool done = true;
01284
01285
01286 for (BlockElt y1 = packet.first; y1<packet.second; ++y1) {
01287 size_t s = firstDirectRecursion(y1);
01288 if (s != rank()) {
01289 directRecursion(y1,s);
01290 } else
01291 done = false;
01292 }
01293
01294
01295 if (not done)
01296 completePacket(y);
01297
01298 }
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317 void Helper::fillMuRow(BlockElt y)
01318 {
01319 using namespace klsupport;
01320
01321 const PrimitiveRow& e = d_prim[y];
01322
01323 size_t ly = length(y);
01324 if (ly==0)
01325 return;
01326
01327 PrimitiveRow::const_iterator start= e.begin();
01328
01329 for (size_t lx=(ly-1)%2,d = (ly-1)/2; d>0; --d,lx+=2) {
01330
01331 PrimitiveRow::const_iterator stop =
01332 std::lower_bound(start,e.end(),lengthLess(lx+1));
01333 for (start= std::lower_bound(start,stop,lengthLess(lx));
01334 start<stop; ++start) {
01335 BlockElt x = *start;
01336 KLIndex klp = d_kl[y][start-e.begin()];
01337
01338 KLPolRef p=d_store[klp];
01339 if (p.degree()== d) {
01340 d_mu[y].first.push_back(x);
01341 d_mu[y].second.push_back(p[d]);
01342 }
01343 }
01344 }
01345
01346
01347 BlockElt x_begin = lengthLess(ly-1);
01348 BlockElt x_end = lengthLess(ly);
01349
01350 for (BlockElt x = x_begin; x < x_end; ++x) {
01351 MuCoeff mu = lengthOneMu(x,y);
01352 if (mu!=MuCoeff(0)) {
01353 d_mu[y].first.push_back(x);
01354 d_mu[y].second.push_back(mu);
01355 }
01356 }
01357
01358 }
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393 void Helper::fillThickets(BlockElt y)
01394 {
01395 using namespace descents;
01396 using namespace klsupport;
01397
01398 std::pair<blocks::BlockElt,blocks::BlockElt> packet = block().R_packet(y);
01399 assert (packet.first==y);
01400
01401 for (BlockElt y1 = packet.first; y1<packet.second; ++y1)
01402 if (d_kl[y1].size() == 0) {
01403 Thicket thicket(*this,y1);
01404 thicket.fill();
01405 }
01406
01407 }
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425 void Helper::muCorrection(std::vector<KLPol>& klv,
01426 const klsupport::PrimitiveRow& e,
01427 BlockElt y, size_t s)
01428 {
01429 using namespace descents;
01430 using namespace klsupport;
01431 using namespace polynomials;
01432
01433 BlockElt y1;
01434
01435 if (descentValue(s,y) == DescentStatus::ComplexDescent) {
01436 y1 = cross(s,y);
01437 } else {
01438 y1 = inverseCayley(s,y).first;
01439 }
01440
01441 const MuRow& mrow = d_mu[y1];
01442 size_t l_y = length(y);
01443
01444 for (size_t i = 0; i < mrow.first.size(); ++i) {
01445
01446 BlockElt z = mrow.first[i];
01447 size_t l_z = length(z);
01448
01449 DescentStatus::Value v = descentValue(s,z);
01450 if (not DescentStatus::isDescent(v))
01451 continue;
01452
01453 MuCoeff mu = mrow.second[i];
01454
01455 Degree d = (l_y-l_z)/2;
01456
01457 if (mu==MuCoeff(1))
01458
01459 for (size_t j = 0; j < e.size(); ++j) {
01460 BlockElt x = e[j];
01461 if (length(x) > l_z) break;
01462
01463 KLPolRef pol = klPol(x,z);
01464 try {
01465 klv[j].safeSubtract(pol,d);
01466 }
01467 catch (error::NumericUnderflow& e){
01468 throw kl_error::KLError(x,y,__LINE__,
01469 static_cast<const KLContext&>(*this));
01470 }
01471 }
01472
01473 else
01474
01475 for (size_t j = 0; j < e.size(); ++j) {
01476 BlockElt x = e[j];
01477 if (length(x) > l_z) break;
01478
01479 KLPolRef pol = klPol(x,z);
01480 try{
01481 klv[j].safeSubtract(pol,d,mu);
01482 }
01483 catch (error::NumericUnderflow& e){
01484 throw kl_error::KLError(x,y,__LINE__,
01485 static_cast<const KLContext&>(*this));
01486 }
01487 }
01488
01489 }
01490
01491 }
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511 void Helper::recursionRow(std::vector<KLPol>& klv,
01512 const klsupport::PrimitiveRow& e,
01513 BlockElt y,
01514 size_t s)
01515 {
01516 using namespace blocks;
01517 using namespace descents;
01518 using namespace klsupport;
01519
01520 BlockElt y1;
01521
01522 if (descentValue(s,y) == DescentStatus::ComplexDescent) {
01523 y1 = cross(s,y);
01524 } else {
01525 y1 = inverseCayley(s,y).first;
01526 }
01527
01528 klv.resize(e.size());
01529
01530 for (size_t j = 0; j < klv.size()-1; ++j) {
01531 BlockElt x = e[j];
01532 switch (descentValue(s,x)) {
01533 case DescentStatus::ImaginaryCompact: {
01534
01535 klv[j] = klPol(x,y1);
01536 klv[j].safeAdd(klv[j],1);
01537 }
01538 break;
01539 case DescentStatus::ComplexDescent: {
01540 BlockElt x1 = cross(s,x);
01541
01542 klv[j] = klPol(x1,y1);
01543 klv[j].safeAdd(klPol(x,y1),1);
01544 }
01545 break;
01546 case DescentStatus::RealTypeI: {
01547 BlockEltPair x1 = inverseCayley(s,x);
01548
01549 klv[j] = klPol(x1.first,y1);
01550 klv[j].safeAdd(klPol(x1.second,y1));
01551 klv[j].safeAdd(klPol(x,y1),1);
01552 try {
01553 klv[j].safeSubtract(klPol(x,y1));
01554 }
01555 catch (error::NumericUnderflow& e){
01556 throw kl_error::KLError(x,y,__LINE__,
01557 static_cast<const KLContext&>(*this));
01558 }
01559 }
01560 break;
01561 case DescentStatus::RealTypeII: {
01562 BlockElt x1 = inverseCayley(s,x).first;
01563
01564 klv[j] = klPol(x1,y1);
01565 klv[j].safeAdd(klPol(x,y1),1);
01566 try {
01567 klv[j].safeSubtract(klPol(cross(s,x),y1));
01568 }
01569 catch (error::NumericUnderflow& e){
01570 throw kl_error::KLError(x,y,__LINE__,
01571 static_cast<const KLContext&>(*this));
01572 }
01573 }
01574 break;
01575 default:
01576 assert(false);
01577 break;
01578 }
01579 }
01580
01581
01582 klv.back() = One;
01583
01584
01585 muCorrection(klv,e,y,s);
01586
01587 }
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604 void Helper::writeRow(const std::vector<KLPol>& klv,
01605 const klsupport::PrimitiveRow& er, BlockElt y)
01606 {
01607 using namespace blocks;
01608 using namespace klsupport;
01609
01610 PrimitiveRow pr;
01611 makePrimitiveRow(pr,y);
01612
01613 KLRow klr(pr.size());
01614 PrimitiveRow nzpr(pr.size());
01615 KLRow::iterator new_pol = klr.end();
01616 PrimitiveRow::iterator new_extr = nzpr.end();
01617 PrimitiveRow::iterator nzpr_end = nzpr.end();
01618
01619
01620 std::vector<size_t> stop(er.size()+1);
01621 stop[0] = 0;
01622
01623 for (size_t j = 0; j < er.size(); ++j) {
01624 size_t epos = std::lower_bound(pr.begin(),pr.end(),er[j]) - pr.begin() + 1;
01625 stop[j+1] = epos;
01626 }
01627
01628
01629 for (size_t j = er.size(); j;) {
01630 --j;
01631
01632 if (not klv[j].isZero()) {
01633 *--new_extr = er[j];
01634 *--new_pol = d_hashtable.match(klv[j]);
01635 }
01636
01637 for (size_t i = stop[j+1]-1; i > stop[j];) {
01638 --i;
01639 size_t s = firstAscent(descent(pr[i]),descent(y),rank());
01640 BlockEltPair x1 = cayley(s,pr[i]);
01641 KLPol pol = klPol(x1.first,y,new_pol,new_extr,nzpr_end);
01642 pol.safeAdd(klPol(x1.second,y,new_pol,new_extr,nzpr_end));
01643
01644 if (not pol.isZero()) {
01645 *--new_extr = pr[i];
01646 *--new_pol = d_hashtable.match(pol);
01647 }
01648 }
01649 }
01650
01651
01652 d_prim[y].reserve(klr.end() - new_pol);
01653 d_kl[y].reserve(klr.end() - new_pol);
01654
01655 copy(new_extr,nzpr.end(),back_inserter(d_prim[y]));
01656 copy(new_pol,klr.end(),back_inserter(d_kl[y]));
01657
01658 prim_size += nzpr.end()-new_extr;
01659 nr_of_prim_nulls += new_extr -nzpr.begin();
01660 }
01661
01662 }
01663 }
01664
01665
01666
01667
01668
01669
01670
01671 namespace kl {
01672 namespace helper {
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689 Thicket::Thicket(Helper& h, BlockElt y)
01690 :d_helper(&h)
01691 {
01692 using namespace descents;
01693
01694 typedef std::map<BlockElt,EdgeList> M;
01695 typedef M::iterator MI;
01696
01697 std::stack<BlockElt> toDo;
01698 M thicket;
01699
01700 toDo.push(y);
01701 thicket.insert(std::make_pair(y,EdgeList()));
01702
01703 while (not toDo.empty()) {
01704 BlockElt y1 = toDo.top();
01705 toDo.pop();
01706 EdgeList& e1 = thicket.find(y1)->second;
01707 for (size_t s = 0; s < rank(); ++s) {
01708 if (descentValue(s,y1) != DescentStatus::RealTypeII)
01709 continue;
01710 BlockElt y2 = cross(s,y1);
01711 std::pair<MI,bool> ins = thicket.insert(std::make_pair(y2,EdgeList()));
01712 if (ins.second) {
01713 EdgeList& e2 = ins.first->second;
01714 e1.push_back(Edge(y1,y2,s,std::vector<KLPol>()));
01715 e2.push_back(Edge(y2,y1,s,std::vector<KLPol>()));
01716 toDo.push(y2);
01717 }
01718 }
01719 }
01720
01721
01722
01723
01724 d_vertices.resize(thicket.size());
01725 d_edges.resize(thicket.size());
01726 size_t j = 0;
01727
01728 for (MI i = thicket.begin(); i != thicket.end(); ++i) {
01729 d_vertices[j] = i->first;
01730 d_edges[j].swap(i->second);
01731 ++j;
01732 }
01733
01734
01735
01736 for (size_t j = 0; j < d_edges.size(); ++j) {
01737 EdgeList& el = d_edges[j];
01738 for (size_t i = 0; i < el.size(); ++i) {
01739
01740 el[i].source = std::lower_bound(d_vertices.begin(),d_vertices.end(),
01741 el[i].source) - d_vertices.begin();
01742 el[i].y = std::lower_bound(d_vertices.begin(),d_vertices.end(),el[i].y)
01743 - d_vertices.begin();
01744 }
01745 }
01746
01747
01748 d_extr.resize(thicket.size());
01749
01750 for (size_t j = 0; j < d_extr.size(); ++j)
01751 d_helper->makeExtremalRow(d_extr[j],d_vertices[j]);
01752
01753
01754 d_prim.resize(thicket.size());
01755
01756 for (size_t j = 0; j < d_prim.size(); ++j)
01757 d_helper->makePrimitiveRow(d_prim[j],d_vertices[j]);
01758
01759
01760 for (size_t j = 0; j < size(); ++j) {
01761 EdgeList& el = d_edges[j];
01762 for (size_t i = 0; i < el.size(); ++i) {
01763 BlockElt y2 = d_vertices[el[i].y];
01764 d_helper->recursionRow(el[i].recursion,d_extr[el[i].y],y2,el[i].s);
01765 }
01766 }
01767
01768
01769 d_klr.resize(size());
01770 d_firstKL.resize(size());
01771 d_firstPrim.resize(size());
01772 }
01773
01774
01775
01776
01777
01778
01779
01780 size_t Thicket::nonExtremal(BlockElt x) const
01781 {
01782 for (size_t j = 0; j < d_vertices.size(); ++j) {
01783 BlockElt y = d_vertices[j];
01784 size_t s = firstAscent(descent(x),descent(y),rank());
01785 if (s != rank())
01786 return j;
01787 }
01788
01789 return size();
01790 }
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806 bool Thicket::ascentCompute(BlockElt x, size_t pos)
01807 {
01808 using namespace blocks;
01809
01810 BlockElt y = d_vertices[pos];
01811 size_t s = firstAscent(descent(x),descent(y),rank());
01812
01813 if (s == rank())
01814 return false;
01815
01816 BlockEltPair x1 = d_helper->cayley(s,x);
01817 KLPol pol = klPol(x1.first,pos);
01818 pol.safeAdd(klPol(x1.second,pos));
01819
01820 if (not pol.isZero()) {
01821 *--d_firstKL[pos] = d_helper->d_hashtable.match(pol);
01822 *--d_firstPrim[pos] = x;
01823 }
01824
01825 return true;
01826 }
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838
01839 void Thicket::edgeCompute(BlockElt x, size_t pos, const Edge& e)
01840 {
01841 using namespace klsupport;
01842
01843 const PrimitiveRow& er = d_extr[pos];
01844 size_t xpos = std::lower_bound(er.begin(),er.end(),x) - er.begin();
01845
01846 KLPol pol = e.recursion[xpos];
01847
01848 try {
01849 pol.safeSubtract(klPol(x,e.source));
01850 }
01851 catch (error::NumericUnderflow& err){
01852 throw kl_error::KLError(x,d_vertices[pos],__LINE__,
01853 static_cast<const KLContext&>(*d_helper));
01854 }
01855
01856 if (not pol.isZero()) {
01857 *--d_firstKL[pos] = d_helper->d_hashtable.match(pol);
01858 *--d_firstPrim[pos] = x;
01859 }
01860
01861 }
01862
01863
01864
01865
01866
01867
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879
01880
01881
01882
01883
01884
01885
01886
01887
01888 void Thicket::fill()
01889 {
01890 using namespace klsupport;
01891
01892 fillXList();
01893
01894
01895 for (size_t j = 0; j < size(); ++j) {
01896 const PrimitiveRow& pr = primitiveRow(j);
01897 d_klr[j].resize(pr.size());
01898 d_klr[j].back() = d_helper->d_one;
01899 d_firstPrim[j] = d_prim[j].end()-1;
01900 d_firstKL[j] = d_klr[j].end()-1;
01901 }
01902
01903
01904 for (size_t j = d_xlist.size(); j>0;) {
01905 --j;
01906 BlockElt x = d_xlist[j];
01907
01908 size_t iy = nonExtremal(x);
01909 if (iy == size())
01910 continue;
01911 for (ThicketIterator i(*this,iy); i(); ++i) {
01912 size_t pos = *i;
01913 const PrimitiveRow& pr = primitiveRow(pos);
01914 if (not std::binary_search(pr.begin(),pr.end(),x))
01915
01916 continue;
01917 if (ascentCompute(x,pos))
01918 continue;
01919
01920 edgeCompute(x,pos,i.edge());
01921 }
01922 }
01923
01924
01925
01926 for (size_t j = 0; j < size(); ++j) {
01927 BlockElt y = d_vertices[j];
01928
01929 d_helper->d_prim[y].reserve(d_prim[j].end() - d_firstPrim[j]);
01930 d_helper->d_kl[y].reserve(d_prim[j].end() - d_firstPrim[j]);
01931
01932 copy(d_firstPrim[j],d_prim[j].end(),back_inserter(d_helper->d_prim[y]));
01933 copy(d_firstKL[j],d_klr[j].end(),back_inserter(d_helper->d_kl[y]));
01934
01935 d_helper->prim_size += d_prim[j].end()-d_firstPrim[j];
01936 d_helper->nr_of_prim_nulls += d_firstPrim[j]-d_prim[j].begin();
01937 }
01938
01939 }
01940
01941
01942
01943
01944
01945
01946 void Thicket::fillXList()
01947 {
01948 using namespace klsupport;
01949
01950 std::set<BlockElt> xs;
01951
01952 for (size_t j = 0; j < size(); ++j) {
01953 const PrimitiveRow& p = primitiveRow(j);
01954 for (size_t i = 0; i < p.size()-1; ++i)
01955 xs.insert(p[i]);
01956 }
01957
01958 d_xlist.reserve(xs.size());
01959 copy(xs.begin(),xs.end(),std::back_inserter(d_xlist));
01960
01961 }
01962
01963 }
01964 }
01965
01966
01967
01968
01969
01970
01971
01972 namespace kl {
01973 namespace helper {
01974
01975 ThicketIterator::ThicketIterator(const Thicket& th, size_t j)
01976 : d_thicket(&th)
01977
01978 {
01979 d_stack.push(j);
01980 d_done.set_capacity(th.size());
01981 d_done.insert(j);
01982 d_current = th.edgeList(j).begin();
01983 d_currentEnd = th.edgeList(j).end();
01984 d_pos = j;
01985 }
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001 ThicketIterator& ThicketIterator::operator++ ()
02002 {
02003 for (; d_current != d_currentEnd; ++d_current) {
02004
02005 size_t j = d_current->y;
02006 if (not d_done.isMember(j)) {
02007 d_pos = j;
02008 d_stack.push(j);
02009 d_done.insert(j);
02010 return *this;
02011 }
02012 }
02013
02014
02015
02016 while (not d_stack.empty()) {
02017 size_t j = d_stack.top();
02018 d_stack.pop();
02019
02020
02021 d_current = d_thicket->edgeList(j).begin();
02022 d_currentEnd = d_thicket->edgeList(j).end();
02023
02024
02025 for (; d_current != d_currentEnd; ++d_current) {
02026 size_t i = d_current->y;
02027 if (not d_done.isMember(i)) {
02028 d_pos = i;
02029 d_stack.push(i);
02030 d_done.insert(i);
02031 return *this;
02032 }
02033 }
02034 }
02035
02036
02037 d_pos = d_thicket->size();
02038
02039 return *this;
02040 }
02041
02042 }
02043 }
02044
02045
02046
02047
02048
02049
02050
02051
02052 namespace kl {
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072 void wGraph(wgraph::WGraph& wg, const KLContext& klc)
02073 {
02074 using namespace bitset;
02075 using namespace graph;
02076 using namespace kl;
02077 using namespace wgraph;
02078
02079 wg.reset();
02080 wg.resize(klc.size());
02081
02082
02083 for (BlockElt y = 0; y < klc.size(); ++y)
02084 wg.descent(y) = klc.descentSet(y);
02085
02086
02087 for (BlockElt y = 0; y < klc.size(); ++y) {
02088 const RankFlags& d_y = wg.descent(y);
02089 const MuRow& mrow = klc.muRow(y);
02090 for (size_t j = 0; j < mrow.first.size(); ++j) {
02091 BlockElt x = mrow.first[j];
02092 const RankFlags& d_x = wg.descent(x);
02093 if (d_x == d_y)
02094 continue;
02095 MuCoeff mu = mrow.second[j];
02096 if (klc.length(y) - klc.length(x) > 1) {
02097 wg.edgeList(x).push_back(y);
02098 wg.coeffList(x).push_back(mu);
02099 continue;
02100 }
02101
02102 if (not d_y.contains(d_x)) {
02103 wg.edgeList(x).push_back(y);
02104 wg.coeffList(x).push_back(mu);
02105 }
02106 if (not d_x.contains(d_y)) {
02107 wg.edgeList(y).push_back(x);
02108 wg.coeffList(y).push_back(mu);
02109 }
02110 }
02111 }
02112
02113 }
02114
02115 }
02116
02117
02118
02119
02120
02121
02122
02123 namespace kl {
02124 namespace helper {
02125
02126
02127
02128
02129
02130
02131
02132
02133 size_t firstAscent(const descents::DescentStatus& d1,
02134 const descents::DescentStatus& d2, size_t rank)
02135 {
02136
02137 using namespace descents;
02138
02139 for (size_t s = 0; s < rank; ++s) {
02140 if ((DescentStatus::isDescent(d2[s])) and
02141 (not DescentStatus::isDescent(d1[s])))
02142 return s;
02143 }
02144
02145 return rank;
02146 }
02147
02148
02149
02150
02151
02152
02153
02154
02155 size_t goodAscent(const descents::DescentStatus& d1,
02156 const descents::DescentStatus& d2, size_t rank)
02157 {
02158 using namespace descents;
02159
02160 for (size_t s = 0; s < rank; ++s) {
02161 if ((not DescentStatus::isDescent(d2[s])) or
02162 (DescentStatus::isDescent(d1[s])))
02163 continue;
02164 if (d1[s] != DescentStatus::ImaginaryTypeII)
02165 return s;
02166 }
02167
02168 return rank;
02169 }
02170
02171 }
02172 }
02173 }