1#ifndef _GLUCAT_INDEX_SET_IMP_H
2#define _GLUCAT_INDEX_SET_IMP_H
46 template<const index_t LO, const index_t HI>
51 {
return "index_set"; }
54 template<const index_t LO, const index_t HI>
60 template<const index_t LO, const index_t HI>
67 template<const index_t LO, const index_t HI>
72 throw error_t(
"index_set(val,frm): cannot create: value gives an index set outside of frame");
75 const index_t skip = min_index > 0 ? 1 : 0;
77 *
this = folded_set.
unfold(frm);
81 template<const index_t LO, const index_t HI>
85 if (!prechecked && (range.first < LO || range.second > HI))
86 throw error_t(
"index_set(range): cannot create: range is too large");
87 const index_t begin_bit = (range.first < 0)
90 const index_t end_bit = (range.second < 0)
93 unsigned long mask = ( (end_bit == _GLUCAT_BITS_PER_ULONG)
95 : (1UL << end_bit)-1UL)
96 & ~((1UL << begin_bit)-1UL);
101 template<const index_t LO, const index_t HI>
105 std::istringstream ss(str);
108 throw error_t(
"index_set_t(str): could not parse string");
112 throw error_t(
"index_set_t(str): could not parse entire string");
116 template<const index_t LO, const index_t HI>
122 const auto* pthis =
static_cast<const bitset_t*
>(
this);
127 template<const index_t LO, const index_t HI>
133 const auto* pthis =
static_cast<const bitset_t*
>(
this);
134 return *pthis !=
static_cast<bitset_t>(rhs);
138 template<const index_t LO, const index_t HI>
143 {
return bitset_t::operator~(); }
146 template<const index_t LO, const index_t HI>
158 template<const index_t LO, const index_t HI>
171 template<const index_t LO, const index_t HI>
178 *pthis &=
static_cast<bitset_t>(rhs);
183 template<const index_t LO, const index_t HI>
196 template<const index_t LO, const index_t HI>
208 template<const index_t LO, const index_t HI>
216 using bitset_t =
typename index_set_t::bitset_t;
217 return static_cast<bitset_t
>(lhs) |
static_cast<bitset_t
>(rhs);
221 template<const index_t LO, const index_t HI>
229 template<const index_t LO, const index_t HI>
234 {
return this->test(idx); }
237 template<const index_t LO, const index_t HI>
245 ? bool(bitset_t::to_ulong() & (1UL << (idx - LO)))
247 ?
bool(bitset_t::to_ulong() & (1UL << (idx - LO - 1)))
252 template<const index_t LO, const index_t HI>
263 template<const index_t LO, const index_t HI>
270 bitset_t::set(idx-LO-1);
272 bitset_t::set(idx-LO);
277 template<const index_t LO, const index_t HI>
284 bitset_t::set(idx-LO-1, val);
286 bitset_t::set(idx-LO, val);
291 template<const index_t LO, const index_t HI>
302 template<const index_t LO, const index_t HI>
309 bitset_t::reset(idx-LO-1);
311 bitset_t::reset(idx-LO);
316 template<const index_t LO, const index_t HI>
327 template<const index_t LO, const index_t HI>
334 bitset_t::flip(idx-LO-1);
336 bitset_t::flip(idx-LO);
341 template<const index_t LO, const index_t HI>
347 unsigned long val = bitset_t::to_ulong();
361 template<const index_t LO, const index_t HI>
369 return neg_part.
count();
373 template<const index_t LO, const index_t HI>
379 const auto* pthis =
static_cast<const bitset_t*
>(
this);
381 return pos_part.
count();
384#if (_GLUCAT_BITS_PER_ULONG == 64)
386 template<const index_t LO, const index_t HI>
393 unsigned long val = bitset_t::to_ulong();
398 val -= val & (val-1);
405 if (val & 0xffffffff00000000ul)
407 if (val & 0xffff0000ffff0000ul)
409 if (val & 0xff00ff00ff00ff00ul)
412 if (val & 0xf0f0f0f0f0f0f0f0ul)
414 if (val & 0xccccccccccccccccul)
416 if (val & 0xaaaaaaaaaaaaaaaaul)
419 return idx + ((idx < -LO) ? LO : LO+1);
422#elif (_GLUCAT_BITS_PER_ULONG == 32)
424 template<const index_t LO, const index_t HI>
431 unsigned long val = bitset_t::to_ulong();
436 val -= val & (val-1);
442 if (val & 0xffff0000ul)
444 if (val & 0xff00ff00ul)
447 if (val & 0xf0f0f0f0ul)
449 if (val & 0xccccccccul)
451 if (val & 0xaaaaaaaaul)
454 return idx + ((idx < -LO) ? LO : LO+1);
459 template<const index_t LO, const index_t HI>
480#if (_GLUCAT_BITS_PER_ULONG == 64)
482 template<const index_t LO, const index_t HI>
489 auto val = bitset_t::to_ulong();
495 const auto nbits = HI - LO;
498 if (val & 0xffffffff00000000ul)
499 { val >>= 32; idx += 32; }
500 if (val & 0x00000000ffff0000ul)
501 { val >>= 16; idx += 16; }
502 if (val & 0x000000000000ff00ul)
503 { val >>= 8; idx += 8; }
505 if (val & 0x00000000000000f0ul)
506 { val >>= 4; idx += 4; }
507 if (val & 0x000000000000000cul)
508 { val >>= 2; idx += 2; }
509 if (val & 0x0000000000000002ul)
511 return idx + ((idx < -LO) ? LO : LO+1);
514#elif (_GLUCAT_BITS_PER_ULONG == 32)
516 template<const index_t LO, const index_t HI>
523 auto val = bitset_t::to_ulong();
529 const auto nbits = HI - LO;
532 if (val & 0xffff0000ul)
533 { val >>= 16; idx += 16; }
534 if (val & 0x0000ff00ul)
535 { val >>= 8; idx += 8; }
537 if (val & 0x000000f0ul)
538 { val >>= 4; idx += 4; }
539 if (val & 0x0000000cul)
540 { val >>= 2; idx += 2; }
541 if (val & 0x00000002ul)
543 return idx + ((idx < -LO) ? LO : LO+1);
548 template<const index_t LO, const index_t HI>
571 template<const index_t LO, const index_t HI>
585 template<const index_t LO, const index_t HI>
590 {
return bitset_t::to_ulong() < rhs.bitset_t::to_ulong(); }
594 template<const index_t LO, const index_t HI>
600 const auto this_grade = this->count();
601 const auto rhs_grade = rhs.count();
602 return (this_grade < rhs_grade)
604 : (this_grade > rhs_grade)
606 : this->lex_less_than(rhs);
610 template<const index_t LO, const index_t HI>
617 (i <= HI) && !(ist[i]);
632 template<const index_t LO, const index_t HI>
639 auto local_ist = index_set_t();
641 auto parse_index_list =
true;
642 auto expect_closing_brace =
false;
643 auto expect_index =
false;
648 parse_index_list =
false;
651 expect_closing_brace = (c == int(
'{'));
652 if (expect_closing_brace)
658 if (s.good() && (c == int(
'}')))
660 expect_closing_brace =
false;
664 parse_index_list =
false;
668 if (s.good() && parse_index_list)
675 if ((i < LO) || (i > HI))
677 s.clear(std::istream::failbit);
683 expect_index =
false;
695 if (expect_closing_brace && (c ==
int(
'}')))
699 expect_closing_brace =
false;
712 s.clear(std::istream::failbit);
718 if (expect_index || expect_closing_brace)
719 s.clear(std::istream::failbit);
729 template<const index_t LO, const index_t HI>
735 const auto min_index = this->min();
736 const auto max_index = this->max();
737 return (min_index < 0 && max_index > 0)
738 ? max_index - min_index == this->count()
739 : (min_index == 1 || max_index == -1) &&
740 (max_index - min_index == this->count() - 1);
744 template<const index_t LO, const index_t HI>
748 fold() const -> const
750 {
return this->fold(*
this,
true); }
753 template<const index_t LO, const index_t HI>
759 if (!prechecked && ((*
this | frm) != frm))
760 throw error_t(
"fold(frm): cannot fold from outside of frame");
761 const auto frm_min = frm.min();
762 const auto frm_max = frm.max();
766 unfold_idx = fold_idx;
767 unfold_idx >= frm_min;
769 if (frm.test(unfold_idx))
772 if (this->test(unfold_idx))
773 result.set(fold_idx);
778 unfold_idx = fold_idx;
779 unfold_idx <= frm_max;
781 if (frm.test(unfold_idx))
784 if (this->test(unfold_idx))
785 result.set(fold_idx);
792 template<const index_t LO, const index_t HI>
798 "unfold(frm): cannot unfold into a smaller frame";
799 const auto frm_min = frm.
min();
800 const auto frm_max = frm.max();
804 unfold_idx = fold_idx;
805 unfold_idx >= frm_min;
807 if (frm.test(unfold_idx))
808 if (this->test(fold_idx--))
809 result.set(unfold_idx);
810 if (!prechecked && ((fold_idx+1) > this->min()))
814 unfold_idx = fold_idx;
815 unfold_idx <= frm_max;
817 if (frm.test(unfold_idx))
818 if (this->test(fold_idx++))
819 result.set(unfold_idx);
820 if (!prechecked && ((fold_idx-1) < this->max()))
826 template<const index_t LO, const index_t HI>
832 const auto min_index = frm.fold().min();
837 const auto folded_set = this->fold(frm);
839 return folded_set.bitset_t::to_ulong() >> (min_index-LO-skip);
849#if (_GLUCAT_BITS_PER_ULONG >= 64)
866#if (_GLUCAT_BITS_PER_ULONG >= 64)
878 template<const index_t LO, const index_t HI>
886 const auto uthis = this->bitset_t::to_ulong();
887 const auto urhs = rhs.bitset_t::to_ulong();
888 const auto nbits = HI - LO;
912 negative ^= h & (uthis >> j);
919 negative ^= h & (uthis >> j);
923 return 1 - int((negative & 1) << 1);
927 template<const index_t LO, const index_t HI>
933 auto result = 1 - int((this->count_neg() % 2) << 1);
934 switch (this->count() % 4)
947 template<const index_t LO, const index_t HI>
953 static const auto lo_mask = (1UL << -LO) - 1UL;
954 const auto uthis = bitset_t::to_ulong();
955 const auto neg_part = uthis & lo_mask;
956 const auto pos_part = uthis >> -LO;
957 return size_t(neg_part ^ pos_part);
964 {
return (j < 0) ? -1 : 1; }
967 template<const index_t LO, const index_t HI>
971 {
return std::min(ist.min(), 0); }
974 template<const index_t LO, const index_t HI>
978 {
return std::max(ist.max(), 0); }
983 template<const index_t LO, const index_t HI>
992 template<const index_t LO, const index_t HI>
997 {
return m_pst == c_j.m_pst && m_idx == c_j.m_idx; }
1000 template<const index_t LO, const index_t HI>
1009 m_pst->reset(m_idx);
1014 template<const index_t LO, const index_t HI>
1020 if (&c_j !=
this && c_j != *
this)
1022 if ( (c_j.m_pst)[c_j.m_idx] )
1025 m_pst->reset(m_idx);
1031 template<const index_t LO, const index_t HI>
1036 {
return !(m_pst->test(m_idx)); }
1039 template<const index_t LO, const index_t HI>
1042 operator bool ()
const
1043 {
return m_pst->test(m_idx); }
1046 template<const index_t LO, const index_t HI>
Specific exception class.
Index set member reference.
auto operator=(const bool x) -> reference &
for b[i] = x;
auto flip() -> reference &
for b[i].flip();
reference()=delete
Default constructor is deleted.
auto operator~() const -> bool
Flips a bit.
auto operator==(const reference &c_j) const -> bool
for b[i] == c[j];
Index set class based on std::bitset<> in Gnu standard C++ library.
auto value_of_fold(const index_set_t frm) const -> set_value_t
The set value of the fold of this index set within the given frame.
auto count() const -> index_t
Cardinality: Number of indices included in set.
std::bitset< HI - LO > bitset_t
auto flip() -> index_set_t &
Set complement, except 0: flip all bits, except 0.
auto operator[](const index_t idx) const -> bool
Subscripting: Test idx for membership: test value of bit idx.
auto lex_less_than(const index_set_t rhs) const -> bool
Lexicographic ordering of two sets: *this < rhs.
auto reset() -> index_set_t &
Make set empty: Set all bits to 0.
auto sign_of_square() const -> int
Sign of geometric square of a Clifford basis element.
auto operator<(const index_set_t rhs) const -> bool
Less than operator used for comparisons, map, etc.
auto min() const -> index_t
Minimum member.
auto hash_fn() const -> size_t
Hash function.
auto set() -> index_set_t &
Include all indices except 0: set all bits except 0.
auto is_contiguous() const -> bool
Determine if the index set is contiguous, ie. has no gaps.
auto count_pos() const -> index_t
Number of positive indices included in set.
std::pair< index_t, index_t > index_pair_t
auto operator|=(const index_set_t rhs) -> index_set_t &
Set union: or.
auto count_neg() const -> index_t
Number of negative indices included in set.
auto operator!=(const index_set_t rhs) const -> bool
Inequality.
static auto classname() -> const std::string
auto operator~() const -> index_set_t
Set complement: not.
auto operator&=(const index_set_t rhs) -> index_set_t &
Set intersection: and.
auto operator^=(const index_set_t rhs) -> index_set_t &
Symmetric set difference: exclusive or.
auto max() const -> index_t
Maximum member.
auto sign_of_mult(const index_set_t ist) const -> int
Sign of geometric product of two Clifford basis elements.
auto unfold(const index_set_t frm, const bool prechecked=false) const -> const index_set_t
Unfold this index set within the given frame.
index_set()=default
Default constructor creates an empty set.
auto operator==(const index_set_t rhs) const -> bool
Equality.
auto test(const index_t idx) const -> bool
Test idx for membership: test value of bit idx.
auto fold() const -> const index_set_t
Fold this index set within itself as a frame.
auto operator<<(std::ostream &os, const framed_multi< Scalar_T, LO, HI, Tune_P > &val) -> std::ostream &
Write multivector to output.
auto operator|(const Multivector< Scalar_T, LO, HI, Tune_P > &lhs, const RHS< Scalar_T, LO, HI, Tune_P > &rhs) -> const Multivector< Scalar_T, LO, HI, Tune_P >
Transformation via twisted adjoint action.
auto operator&(const Multivector< Scalar_T, LO, HI, Tune_P > &lhs, const RHS< Scalar_T, LO, HI, Tune_P > &rhs) -> const Multivector< Scalar_T, LO, HI, Tune_P >
Inner product.
auto compare(const index_set< LO, HI > &a, const index_set< LO, HI > &b) -> int
"lexicographic compare" eg. {3,4,5} is less than {3,7,8}
static auto inverse_reversed_gray(unsigned long x) -> unsigned long
Inverse reversed Gray code.
static auto inverse_gray(unsigned long x) -> unsigned long
Inverse Gray code.
auto sign_of_square(index_t j) -> int
Square of generator {j}.
auto min_neg(const index_set< LO, HI > &ist) -> index_t
Minimum negative index, or 0 if none.
unsigned long set_value_t
Size of set_value_t should be enough to contain index_set<LO,HI>
auto operator>>(std::istream &s, framed_multi< Scalar_T, LO, HI, Tune_P > &val) -> std::istream &
Read multivector from input.
int index_t
Size of index_t should be enough to represent LO, HI.
auto operator^(const Multivector< Scalar_T, LO, HI, Tune_P > &lhs, const RHS< Scalar_T, LO, HI, Tune_P > &rhs) -> const Multivector< Scalar_T, LO, HI, Tune_P >
Outer product.
auto max_pos(const index_set< LO, HI > &ist) -> index_t
Maximum positive index, or 0 if none.