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
1.3.9.1