00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef DJC_COROPA_LIBALGEBRA_TENSORBASISH_SEEN
00019 #define DJC_COROPA_LIBALGEBRA_TENSORBASISH_SEEN
00020
00021
00022 #include "_tensor_basis.h"
00023 #include "constpower.h"
00024 #include "basis_traits.h"
00025
00027
00051 template<typename SCA, DEG n_letters, DEG max_degree>
00052 class tensor_basis
00053 {
00054 public:
00056 typedef _tensor_basis<n_letters, max_degree> KEY;
00058 const KEY empty_key;
00060 typedef std::map<KEY, SCA> MAP;
00061 private:
00063 DEG _size;
00064 public:
00066
00069 tensor_basis(void)
00070 : _size ((ConstPower < n_letters, max_degree + 1 > ::ans - 1) / (n_letters - 1)) {}
00071 public:
00073 inline KEY keyofletter(LET letter) const
00074 {
00075 return KEY(letter);
00076 }
00078 inline bool letter(const KEY& k) const
00079 {
00080 return k.size() == 1;
00081 }
00083 inline LET getletter(const KEY& k) const
00084 {
00085 return k.FirstLetter();
00086 }
00088 inline KEY lparent(const KEY& k) const
00089 {
00090 return k.lparent();
00091 }
00093 inline KEY rparent(const KEY& k) const
00094 {
00095 return k.rparent();
00096 }
00098 inline DEG degree(const KEY& k) const
00099 {
00100 return k.size();
00101 }
00103 inline DEG size(void) const
00104 {
00105 return _size;
00106 }
00108 inline KEY begin(void) const
00109 {
00110 return empty_key;
00111 }
00113 inline KEY end(void) const
00114 {
00115 KEY result;
00116 result.push_back(0);
00117 return result;
00118 }
00120 inline KEY nextkey(const KEY& k) const
00121 {
00122 KEY::size_type i;
00123 for (i = k.size() - 1; i >= 0; --i)
00124 if (k[i] < n_letters)
00125 {
00126 KEY result(k);
00127 result[i] += 1;
00128 return result;
00129 }
00130 return end();
00131 }
00133 std::string key2string(const KEY& k) const
00134 {
00135 std::ostringstream oss;
00136
00137 if (k.size() > 0)
00138 {
00139 oss << k.FirstLetter();
00140 KEY kk = k.rparent();
00141 for (unsigned i = 1; i < k.size(); ++i)
00142 {
00143 oss << "," << kk.FirstLetter();
00144 kk = kk.rparent();
00145 }
00146 }
00147 return oss.str();
00148 }
00149 };
00150
00152
00163 template<typename SCA, typename RAT, DEG n_letters, DEG max_degree>
00164 class free_tensor_basis : public tensor_basis<SCA, n_letters, max_degree>,
00165 public basis_traits<With_Degree, n_letters, max_degree>
00166 {
00167 public:
00169 typedef tensor_basis<SCA, n_letters, max_degree> TBASIS;
00171 typedef RAT RATIONAL;
00173 typedef free_tensor<SCA, RAT, n_letters, max_degree> TENSOR;
00174 public:
00176 free_tensor_basis(void) {}
00177 public:
00179
00185 static inline TENSOR prod(const KEY& k1, const KEY& k2)
00186 {
00187 static SCA one(+1);
00188 TENSOR result;
00189 if ((max_degree == 0) || (k1.size() + k2.size() <= max_degree))
00190 {
00191 KEY concat = k1 * k2;
00192 result[concat] = one;
00193 }
00194 return result;
00195 }
00197 inline friend
00198 std::ostream& operator<<(std::ostream& os, const std::pair<free_tensor_basis*, KEY>& t)
00199 {
00200 return os << (t.first)->key2string(t.second);
00201 }
00202 };
00203
00205
00216 template<typename SCA, typename RAT, DEG n_letters, DEG max_degree>
00217 class shuffle_tensor_basis : public tensor_basis<SCA, n_letters, max_degree>,
00218 public basis_traits<With_Degree, n_letters, max_degree>
00219 {
00220 public:
00222 typedef tensor_basis<SCA, n_letters, max_degree> TBASIS;
00224 typedef typename TBASIS::KEY KEY;
00226 typedef typename TBASIS::MAP MAP;
00228 typedef RAT RATIONAL;
00230 typedef shuffle_tensor<SCA, RAT, n_letters, max_degree> TENSOR;
00231 public:
00233 shuffle_tensor_basis(void) {}
00234 public:
00236
00243 inline const TENSOR& prod(const KEY& k1, const KEY& k2) const
00244 {
00245 static boost::recursive_mutex table_access;
00246
00247 boost::lock_guard<boost::recursive_mutex> lock(table_access);
00248
00249 typedef std::map<std::pair<KEY, KEY>, TENSOR> TABLE_T;
00250 static TABLE_T table;
00251 typename TABLE_T::iterator it;
00252 std::pair<KEY, KEY> p(std::min(k1, k2), std::max(k1, k2));
00253 it = table.find(p);
00254 if (it == table.end())
00255 return table[p] = _prod(k1, k2);
00256 else
00257 return it->second;
00258 }
00260 inline friend
00261 std::ostream& operator<<(std::ostream& os, const std::pair<shuffle_tensor_basis*, KEY>& t)
00262 {
00263 return os << (t.first)->key2string(t.second);
00264 }
00265 private:
00266
00267 inline void tensor_add_mul(const TENSOR& a, const TENSOR& b, TENSOR& ans) const
00268 {
00269 sparse_vector<typename free_tensor_basis<SCA, RAT, n_letters, max_degree>,MAP>
00270 ::const_iterator i, j;
00271 for (i = a.begin(); i != a.end(); ++i)
00272 for (j = b.begin(); j != b.end(); ++j)
00273 ans.add_scal_prod(free_tensor_prod(i->first, j->first),
00274 i->second * j->second);
00275 }
00277
00283 static inline TENSOR free_tensor_prod(const KEY& k1, const KEY& k2)
00284 {
00285 static SCA one(+1);
00286 TENSOR result;
00287 if ((max_degree == 0) || (k1.size() + k2.size() <= max_degree))
00288 {
00289 KEY concat = k1 * k2;
00290 result[concat] = one;
00291 }
00292 return result;
00293 }
00294
00296 inline TENSOR _prod(const KEY& k1, const KEY& k2) const
00297 {
00298 TENSOR result;
00299 unsigned i, j;
00300 static SCA one(+1);
00301
00302 if ((max_degree == 0) || (k1.size() + k2.size() <= max_degree))
00303
00304 {
00305 if (k1.size() == 0)
00306 {
00307 result[k2] = one;
00308 return result;
00309 }
00310 if (k2.size() == 0)
00311 {
00312 result[k1] = one;
00313 return result;
00314 }
00315
00316 tensor_add_mul((TENSOR)k1.lparent(), prod(k1.rparent(), k2), result);
00317 tensor_add_mul((TENSOR)k2.lparent(), prod(k1, k2.rparent()), result);
00318 }
00319 return result;
00320 }
00321 };
00322
00323
00324
00325
00326 #endif // DJC_COROPA_LIBALGEBRA_TENSORBASISH_SEEN
00327
00328