Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

/home/r0/dav/atlas.dir/atlas3/sources/gkmod/klsupport.cpp

Go to the documentation of this file.
00001 /*!
00002 \file
00003 \brief Implementation for KLSupport.
00004 
00005   This module provides support code for the Kazhdan-Lusztig computation,
00006   mostly the management of the list of primitive pairs, and primitivization
00007   of arbitrary subsets of the block.
00008 */
00009 /*
00010   This is klsupport.cpp
00011 
00012   Copyright (C) 2004,2005 Fokko du Cloux
00013   part of the Atlas of Reductive Lie Groups
00014 
00015   See file main.cpp for full copyright notice
00016 */
00017 
00018 #include "klsupport.h"
00019 
00020 #include "blocks.h"
00021 #include "descents.h"
00022 
00023 /*
00024   After some hesitation, I think I _am_ going to assume that the block has
00025   been sorted by length and root datum involution, and then by R-packet.
00026   This does make the hard case in the recursion a lot simpler to handle:
00027   "thickets" of representations are in fact R-packets, so they will be
00028   consecutively numbered. [Fokko]
00029 */
00030 
00031 namespace atlas {
00032 
00033 namespace {
00034   using blocks::BlockElt;
00035 
00036   void fillLengthLess(std::vector<BlockElt>&, const blocks::Block&);
00037 
00038 } // namespace
00039 
00040 /*****************************************************************************
00041 
00042         Chapter I -- The KLSupport class
00043 
00044  *****************************************************************************/
00045 
00046 namespace klsupport {
00047 
00048 KLSupport::KLSupport(blocks::Block& b)
00049   :d_block(&b),
00050    d_rank(b.rank()),
00051    d_size(b.size())
00052 
00053 {}
00054 
00055 /******** copy, assignment and swap ******************************************/
00056 
00057 void KLSupport::swap(KLSupport& other)
00058 {
00059   d_state.swap(other.d_state);
00060 
00061   std::swap(d_block,other.d_block);
00062   std::swap(d_rank,other.d_rank);
00063   std::swap(d_size,other.d_size);
00064 
00065   d_descent.swap(other.d_descent);
00066   d_goodAscent.swap(other.d_goodAscent);
00067   d_downset.swap(other.d_downset);
00068   d_primset.swap(other.d_primset);
00069   d_lengthLess.swap(other.d_lengthLess);
00070 
00071 }
00072 
00073 /******** accessors **********************************************************/
00074 
00075 /*!
00076   \brief: Flags in b those block elements which are extremal w.r.t. the
00077   simple reflections in d.
00078 
00079   Preconditions: the capacity of b is the size(); d contains d_rank flags;
00080 
00081   Explanation: an element z in the block is extremal w.r.t. d, if all the
00082   descents in d are also descents for z. Since d_downset[s] flags the
00083   elements for which s is a descent, this amounts to requesting that z
00084   belong to the intersection of the downsets for the various descents in d.
00085 */
00086 
00087 void KLSupport::extremalize(bitmap::BitMap& b, const bitset::RankFlags& d)
00088   const
00089 {
00090   for (size_t s = 0; s < d_rank; ++s)
00091     if (d.test(s))
00092       b &= d_downset[s];
00093 }
00094 
00095 
00096 /*
00097   \brief Primitivizes b w.r.t. the values whose descent set is d, i.e.,
00098   throws out from b the non-primitive elements with respect to d
00099 
00100   Preconditions: the capacity of b is the size(); d contains d_rank flags;
00101 
00102   Explanation: an element z in the block is primitive w.r.t. d, if all the
00103   descents in d are either descents, or imaginary type II ascents for z. Since
00104   d_primset[s] flags the elements for which s is a descent or imaginary type
00105   II, this amounts to requesting that z belong to the intersection of the
00106   primsets for the various descents in d.
00107 */
00108 void KLSupport::primitivize(bitmap::BitMap& b, const bitset::RankFlags& d)
00109   const
00110 {
00111   for (size_t s = 0; s < d_rank; ++s)
00112     if (d.test(s))
00113       b &= d_primset[s];
00114 }
00115 
00116 
00117 /*!\brief
00118   Either replaces the block element |x| if possible with a primitive element
00119   for |d| above it, while returning that value, or returns |UndefBlock| if
00120   a real nonparity case is hit (leaving |x| at the block element in question).
00121 
00122   Explanation: a primitive element for |d| is one for which all elements in
00123   |d| are either descents or type II imaginary ascents. So if |x| is not
00124   primitive, it has an ascent in |d| that is either complex, imaginary type I
00125   or real nonparity. In the first two cases we replace |x| by the (unique)
00126   ascended element and continue; in the last case, we return |UndefBlock| (for
00127   K-L computations, this case implies that $P_{x,y}=0$; the value of
00128   |UndefBlock| is conveniently larger than any valid BlockElt |y|, so this
00129   case will be handled effortlessly together with triangularity).
00130 */
00131 BlockElt KLSupport::primitivize(BlockElt x, const bitset::RankFlags& d) const
00132 {
00133   using descents::DescentStatus;
00134 
00135   bitset::RankFlags a; // good ascents for x that are descents for y
00136 
00137   while ((a = goodAscentSet(x)&d).any())
00138   {
00139     size_t s = a.firstBit();
00140     DescentStatus::Value v = descentValue(s,x);
00141     if (v == DescentStatus::RealNonparity)
00142       return blocks::UndefBlock; // cop out
00143     x = v == DescentStatus::ComplexAscent // complex or imaginary type I ?
00144         ? d_block->cross(s,x)
00145         : d_block->cayley(s,x).first;
00146   }
00147   return x;
00148 }
00149 
00150 /******** manipulators *******************************************************/
00151 
00152 /*
00153   \brief Fills the lengthLess table, and the downsets
00154 */
00155 void KLSupport::fill()
00156 {
00157   using namespace bitmap;
00158 
00159   if (d_state.test(Filled)) // do nothing
00160     return;
00161 
00162   // fill lengthLess if necessary
00163   if (not d_state.test(LengthLessFilled))
00164   {
00165     fillLengthLess(d_lengthLess,block());
00166     d_state.set(LengthLessFilled);
00167   }
00168 
00169   // make the downsets
00170   fillDownsets();
00171 
00172   d_state.set(Filled);
00173 
00174 }
00175 
00176 
00177 /*
00178   \brief Fills in the downset, primset, descents and goodAscent bitmap/set
00179   vectors. Here downset and primset are vectors indexed by a simple reflection
00180   s, and giving a bitmap over all block elements, while descents and
00181   goodAscent are vectors indexed by a block element z and giving a bitset over
00182   all simple reflections.
00183 
00184   Explanation: here the predicate that s is a descent for z is taken in the
00185   weak sense that s belongs to the "tau-invariant" of z in b, in other
00186   words, it is a complex descent, real noncompact (type I or type II), or
00187   imaginary compact. The goodAscent bitset for z holds the ascents for z that
00188   are not imaginary type II. The primset bitmap for s records the block
00189   elements z for which s is not a goodAscent, in other words it is either
00190   a descent, or an imaginary type II ascent.
00191 
00192   Sets the DownsetsFilled bit in d_state if successful. Commit-or-rollback
00193   is guaranteed.
00194 */
00195 void KLSupport::fillDownsets()
00196 {
00197   using namespace bitmap;
00198   using namespace bitset;
00199   using namespace descents;
00200 
00201   if (d_state.test(DownsetsFilled))
00202     return;
00203 
00204   size_t size = d_block->size();
00205   std::vector<BitMap> downset(d_rank);
00206   std::vector<BitMap> primset(d_rank);
00207   std::vector<RankFlags> descents(size);
00208   std::vector<RankFlags> good_ascent(size);
00209 
00210   for (size_t s = 0; s < downset.size(); ++s) {
00211     downset[s].set_capacity(size);
00212     primset[s].set_capacity(size);
00213     for (BlockElt z = 0; z < size; ++z) {
00214       DescentStatus::Value v = descentValue(s,z);
00215       if (DescentStatus::isDescent(v)) {
00216         downset[s].insert(z);
00217         primset[s].insert(z);
00218         descents[z].set(s);
00219       } else { // ascents
00220         if (v == DescentStatus::ImaginaryTypeII)
00221           primset[s].insert(z);  // s is a "bad" ascent
00222         else
00223           good_ascent[z].set(s); // good ascent
00224       }
00225     }
00226   }
00227 
00228   // commit
00229   d_downset.swap(downset);
00230   d_primset.swap(primset);
00231   d_descent.swap(descents);
00232   d_goodAscent.swap(good_ascent);
00233   d_state.set(DownsetsFilled);
00234 
00235 }
00236 
00237 } // namespace klsupport
00238 
00239 /*****************************************************************************
00240 
00241         Chapter II -- Functions local to this module
00242 
00243  *****************************************************************************/
00244 
00245 namespace {
00246 
00247 /*
00248   \brief Makes ll into a vector of size max(lengths(b))+2 such that for
00249   0<=l<=max(lengths(b))+1, the element ll[l] is the first BlockElt of length
00250   at least l in b (or b.size() if there are none, as for l=max(lengths(b))+1)
00251   In other words, as a number ll[l] counts the elements in b of length < l.
00252 
00253   Precondition: b is sorted by length;
00254 */
00255 void fillLengthLess(std::vector<BlockElt>& ll, const blocks::Block& b)
00256 {
00257   ll.clear(); ll.resize(b.length(b.size()-1)+2);
00258 
00259   ll[0]=0; // no elements of length<0
00260   size_t l=0;
00261   for (blocks::BlockElt z=0; z<b.size(); ++z)
00262     while (b.length(z)>l)
00263       ll[++l]=z;  // invariant |l<=b.length(z)| after this statement
00264 
00265   // do not forget the last length!
00266   ll[l+1]=b.size(); // here l=b.length(b.size()-1)=max(lengths(b))
00267 }
00268 
00269 } // namsespace
00270 
00271 } // namespace atlas

Generated on Wed Mar 26 16:49:34 2008 for atlas by  doxygen 1.3.9.1