glucat  0.8.2
index_set_imp.h
Go to the documentation of this file.
1 #ifndef _GLUCAT_INDEX_SET_IMP_H
2 #define _GLUCAT_INDEX_SET_IMP_H
3 /***************************************************************************
4  GluCat : Generic library of universal Clifford algebra templates
5  index_set_imp.h : Implement a class for a set of non-zero integer indices
6  -------------------
7  begin : Sun 2001-12-09
8  copyright : (C) 2001-2016 by Paul C. Leopardi
9  ***************************************************************************
10 
11  This library is free software: you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published
13  by the Free Software Foundation, either version 3 of the License, or
14  (at your option) any later version.
15 
16  This library is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with this library. If not, see <http://www.gnu.org/licenses/>.
23 
24  ***************************************************************************
25  This library is based on a prototype written by Arvind Raja and was
26  licensed under the LGPL with permission of the author. See Arvind Raja,
27  "Object-oriented implementations of Clifford algebras in C++: a prototype",
28  in Ablamowicz, Lounesto and Parra (eds.)
29  "Clifford algebras with numeric and symbolic computations", Birkhauser, 1996.
30  ***************************************************************************
31  See also Arvind Raja's original header comments in glucat.h
32  ***************************************************************************/
33 
34 #include "glucat/index_set.h"
35 
36 #include <sstream>
37 
38 namespace glucat
39 {
40  // References for algorithms:
41  // [JA]: Joerg Arndt, "Algorithms for programmers", http://www.jjj.de/fxt/fxtbook.pdf
42  // Chapter 1, Bit wizardry, http://www.jjj.de/bitwizardry/bitwizardrypage.html
43  // [L]: Pertti Lounesto, "Clifford algebras and spinors", Cambridge UP, 1997.
44 
45  template<const index_t LO, const index_t HI>
46  inline
47  const std::string
50  { return "index_set"; }
51 
53  template<const index_t LO, const index_t HI>
55  index_set(const index_t idx)
56  { this->set(idx); }
57 
59  template<const index_t LO, const index_t HI>
61  index_set(const bitset_t bst):
62  bitset_t(bst)
63  { }
64 
66  template<const index_t LO, const index_t HI>
68  index_set(const set_value_t folded_val, const index_set_t frm, const bool prechecked)
69  {
70  if (!prechecked && folded_val >= set_value_t(1 << frm.count()))
71  throw error_t("index_set(val,frm): cannot create: value gives an index set outside of frame");
72  const index_set_t folded_frame = frm.fold();
73  const index_t min_index = folded_frame.min();
74  const index_t skip = min_index > 0 ? 1 : 0;
75  const index_set_t folded_set = index_set_t(bitset_t(folded_val) << (min_index - skip - LO));
76  *this = folded_set.unfold(frm);
77  }
78 
80  template<const index_t LO, const index_t HI>
82  index_set(const index_pair_t& range, const bool prechecked)
83  {
84  if (!prechecked && (range.first < LO || range.second > HI))
85  throw error_t("index_set(range): cannot create: range is too large");
86  const index_t begin_bit = (range.first < 0)
87  ? range.first-LO
88  : range.first-LO-1;
89  const index_t end_bit = (range.second < 0)
90  ? range.second-LO+1
91  : range.second-LO;
92  unsigned long mask = ( (end_bit == _GLUCAT_BITS_PER_ULONG)
93  ? -1UL
94  : (1UL << end_bit)-1UL)
95  & ~((1UL << begin_bit)-1UL);
96  *this = bitset_t(mask);
97  }
98 
100  template<const index_t LO, const index_t HI>
102  index_set(const std::string& str)
103  {
104  std::istringstream ss(str);
105  ss >> *this;
106  if (!ss)
107  throw error_t("index_set_t(str): could not parse string");
108  // Peek to see if the end of the string has been reached.
109  ss.peek();
110  if (!ss.eof())
111  throw error_t("index_set_t(str): could not parse entire string");
112  }
113 
115  template<const index_t LO, const index_t HI>
116  inline
117  bool
119  operator== (const index_set_t rhs) const
120  {
121  const bitset_t* pthis = static_cast<const bitset_t*>(this);
122  return *pthis == static_cast<bitset_t>(rhs);
123  }
124 
126  template<const index_t LO, const index_t HI>
127  inline
128  bool
130  operator!= (const index_set_t rhs) const
131  {
132  const bitset_t* pthis = static_cast<const bitset_t*>(this);
133  return *pthis != static_cast<bitset_t>(rhs);
134  }
135 
137  template<const index_t LO, const index_t HI>
138  inline
141  operator~ () const
142  { return bitset_t::operator~(); }
143 
145  template<const index_t LO, const index_t HI>
146  inline
150  {
151  bitset_t* pthis = this;
152  *pthis ^= static_cast<bitset_t>(rhs);
153  return *this;
154  }
155 
157  template<const index_t LO, const index_t HI>
158  inline
159  const
162  const index_set<LO,HI>& rhs)
163  {
165  typedef typename index_set_t::bitset_t bitset_t;
166  return static_cast<bitset_t>(lhs) ^ static_cast<bitset_t>(rhs);
167  }
168 
170  template<const index_t LO, const index_t HI>
171  inline
175  {
176  bitset_t* pthis = this;
177  *pthis &= static_cast<bitset_t>(rhs);
178  return *this;
179  }
180 
182  template<const index_t LO, const index_t HI>
183  inline
184  const
187  const index_set<LO,HI>& rhs)
188  {
190  typedef typename index_set_t::bitset_t bitset_t;
191  return static_cast<bitset_t>(lhs) & static_cast<bitset_t>(rhs);
192  }
193 
195  template<const index_t LO, const index_t HI>
196  inline
200  {
201  bitset_t* pthis = this;
202  *pthis |= static_cast<bitset_t>(rhs);
203  return *this;
204  }
205 
207  template<const index_t LO, const index_t HI>
208  inline
209  const
212  const index_set<LO,HI>& rhs)
213  {
215  typedef typename index_set_t::bitset_t bitset_t;
216  return static_cast<bitset_t>(lhs) | static_cast<bitset_t>(rhs);
217  }
218 
220  template<const index_t LO, const index_t HI>
221  inline
225  { return reference(*this, idx); }
226 
228  template<const index_t LO, const index_t HI>
229  inline
230  bool
232  operator[] (const index_t idx) const
233  { return this->test(idx); }
234 
236  template<const index_t LO, const index_t HI>
237  inline
238  bool
240  test(const index_t idx) const
241  {
242  // Reference: [JA], 1.2.1
243  return (idx < 0)
244  ? bool(bitset_t::to_ulong() & (1UL << (idx - LO)))
245  : (idx > 0)
246  ? bool(bitset_t::to_ulong() & (1UL << (idx - LO - 1)))
247  : false;
248  }
249 
251  template<const index_t LO, const index_t HI>
252  inline
256  {
257  bitset_t::set();
258  return *this;
259  }
260 
262  template<const index_t LO, const index_t HI>
263  inline
267  {
268  if (idx > 0)
269  bitset_t::set(idx-LO-1);
270  else if (idx < 0)
271  bitset_t::set(idx-LO);
272  return *this;
273  }
274 
276  template<const index_t LO, const index_t HI>
277  inline
280  set(const index_t idx, const int val)
281  {
282  if (idx > 0)
283  bitset_t::set(idx-LO-1, val);
284  else if (idx < 0)
285  bitset_t::set(idx-LO, val);
286  return *this;
287  }
288 
290  template<const index_t LO, const index_t HI>
291  inline
295  {
296  bitset_t::reset();
297  return *this;
298  }
299 
301  template<const index_t LO, const index_t HI>
302  inline
305  reset(const index_t idx)
306  {
307  if (idx > 0)
308  bitset_t::reset(idx-LO-1);
309  else if (idx < 0)
310  bitset_t::reset(idx-LO);
311  return *this;
312  }
313 
315  template<const index_t LO, const index_t HI>
316  inline
320  {
321  bitset_t::flip();
322  return *this;
323  }
324 
326  template<const index_t LO, const index_t HI>
327  inline
330  flip(const index_t idx)
331  {
332  if (idx > 0)
333  bitset_t::flip(idx-LO-1);
334  else if (idx < 0)
335  bitset_t::flip(idx-LO);
336  return *this;
337  }
338 
340  template<const index_t LO, const index_t HI>
341  inline
342  index_t
344  count() const
345  {
346  unsigned long val = bitset_t::to_ulong();
347  // Reference: [JA], 1.3
348  if (val == 0)
349  return 0;
350  else
351  {
352  index_t result = 1;
353  while (val &= val-1)
354  ++result;
355  return result;
356  }
357  }
358 
360  template<const index_t LO, const index_t HI>
361  inline
362  index_t
364  count_neg() const
365  {
366  static const index_set_t lo_mask = bitset_t((1UL << -LO) - 1UL);
367  const index_set_t neg_part = *this & lo_mask;
368  return neg_part.count();
369  }
370 
372  template<const index_t LO, const index_t HI>
373  inline
374  index_t
376  count_pos() const
377  {
378  const bitset_t* pthis = static_cast<const bitset_t*>(this);
379  const index_set_t pos_part = *pthis >> -LO;
380  return pos_part.count();
381  }
382 
383 #if (_GLUCAT_BITS_PER_ULONG == 64)
384  template<const index_t LO, const index_t HI>
386  inline
387  index_t
389  min() const
390  {
391  // Reference: [JA], 1.3
392  unsigned long val = bitset_t::to_ulong();
393  if (val == 0)
394  return 0;
395  else
396  {
397  val -= val & (val-1); // isolate lowest bit
398 
399  index_t idx = 0;
400  const index_t nbits = HI - LO;
401 
402  if (nbits > 8)
403  {
404  if (val & 0xffffffff00000000ul)
405  idx += 32;
406  if (val & 0xffff0000ffff0000ul)
407  idx += 16;
408  if (val & 0xff00ff00ff00ff00ul)
409  idx += 8;
410  }
411  if (val & 0xf0f0f0f0f0f0f0f0ul)
412  idx += 4;
413  if (val & 0xccccccccccccccccul)
414  idx += 2;
415  if (val & 0xaaaaaaaaaaaaaaaaul)
416  idx += 1;
417 
418  return idx + ((idx < -LO) ? LO : LO+1);
419  }
420  }
421 #elif (_GLUCAT_BITS_PER_ULONG == 32)
422  template<const index_t LO, const index_t HI>
424  inline
425  index_t
427  min() const
428  {
429  // Reference: [JA], 1.3
430  unsigned long val = bitset_t::to_ulong();
431  if (val == 0)
432  return 0;
433  else
434  {
435  val -= val & (val-1); // isolate lowest bit
436 
437  index_t idx = 0;
438  const index_t nbits = HI - LO;
439  if (nbits > 8)
440  {
441  if (val & 0xffff0000ul)
442  idx += 16;
443  if (val & 0xff00ff00ul)
444  idx += 8;
445  }
446  if (val & 0xf0f0f0f0ul)
447  idx += 4;
448  if (val & 0xccccccccul)
449  idx += 2;
450  if (val & 0xaaaaaaaaul)
451  idx += 1;
452 
453  return idx + ((idx < -LO) ? LO : LO+1);
454  }
455  }
456 #else
457  template<const index_t LO, const index_t HI>
459  index_t
461  min() const
462  {
463  for (index_t
464  idx = LO;
465  idx != 0;
466  ++idx)
467  if (this->test(idx))
468  return idx;
469  for (index_t
470  idx = 1;
471  idx <= HI;
472  ++idx)
473  if (this->test(idx))
474  return idx;
475  return 0;
476  }
477 #endif
478 
479 #if (_GLUCAT_BITS_PER_ULONG == 64)
480  template<const index_t LO, const index_t HI>
482  inline
483  index_t
485  max() const
486  {
487  // Reference: [JA], 1.6
488  unsigned long val = bitset_t::to_ulong();
489  if (val == 0)
490  return 0;
491  else
492  {
493  index_t idx = 0;
494  const index_t nbits = HI - LO;
495  if (nbits > 8)
496  {
497  if (val & 0xffffffff00000000ul)
498  { val >>= 32; idx += 32; }
499  if (val & 0x00000000ffff0000ul)
500  { val >>= 16; idx += 16; }
501  if (val & 0x000000000000ff00ul)
502  { val >>= 8; idx += 8; }
503  }
504  if (val & 0x00000000000000f0ul)
505  { val >>= 4; idx += 4; }
506  if (val & 0x000000000000000cul)
507  { val >>= 2; idx += 2; }
508  if (val & 0x0000000000000002ul)
509  { idx += 1; }
510  return idx + ((idx < -LO) ? LO : LO+1);
511  }
512  }
513 #elif (_GLUCAT_BITS_PER_ULONG == 32)
514  template<const index_t LO, const index_t HI>
516  inline
517  index_t
519  max() const
520  {
521  // Reference: [JA], 1.6
522  unsigned long val = bitset_t::to_ulong();
523  if (val == 0)
524  return 0;
525  else
526  {
527  index_t idx = 0;
528  const index_t nbits = HI - LO;
529  if (nbits > 8)
530  {
531  if (val & 0xffff0000ul)
532  { val >>= 16; idx += 16; }
533  if (val & 0x0000ff00ul)
534  { val >>= 8; idx += 8; }
535  }
536  if (val & 0x000000f0ul)
537  { val >>= 4; idx += 4; }
538  if (val & 0x0000000cul)
539  { val >>= 2; idx += 2; }
540  if (val & 0x00000002ul)
541  { idx += 1; }
542  return idx + ((idx < -LO) ? LO : LO+1);
543  }
544  }
545 #else
546  template<const index_t LO, const index_t HI>
548  index_t
550  max() const
551  {
552  for (index_t
553  idx = HI;
554  idx != 0;
555  --idx)
556  if (this->test(idx))
557  return idx;
558  for (index_t
559  idx = -1;
560  idx >= LO;
561  --idx)
562  if (this->test(idx))
563  return idx;
564  return 0;
565  }
566 #endif
567 
569  // eg. {3,4,5} is less than {3,7,8}
570  template<const index_t LO, const index_t HI>
571  inline
572  int
574  {
575  return (a == b)
576  ? 0
577  : a.lex_less_than(b)
578  ? -1
579  : 1;
580  }
581 
583  // eg. {3,4,5} is less than {3,7,8}
584  template<const index_t LO, const index_t HI>
585  inline
586  bool
588  lex_less_than(const index_set_t rhs) const
589  { return bitset_t::to_ulong() < rhs.bitset_t::to_ulong(); }
590 
592  // Order by count, then order lexicographically within the equivalence class of count.
593  template<const index_t LO, const index_t HI>
594  inline
595  bool
597  operator< (const index_set_t rhs) const
598  {
599  const index_t this_grade = this->count();
600  const index_t rhs_grade = rhs.count();
601  return (this_grade < rhs_grade)
602  ? true
603  : (this_grade > rhs_grade)
604  ? false
605  : this->lex_less_than(rhs);
606  }
607 
609  template<const index_t LO, const index_t HI>
610  std::ostream&
611  operator<< (std::ostream& os, const index_set<LO,HI>& ist)
612  {
613  index_t i;
614  os << '{';
615  for (i= LO;
616  (i <= HI) && !(ist[i]);
617  ++i)
618  { }
619  if (i <= HI)
620  os << i;
621  for (++i;
622  i <= HI;
623  ++i)
624  if (ist[i])
625  os << ',' << i;
626  os << '}';
627  return os;
628  }
629 
631  template<const index_t LO, const index_t HI>
632  std::istream&
633  operator>> (std::istream& s, index_set<LO,HI>& ist)
634  {
635  // Parsing variables.
636  int c = 0;
637  index_t i = 0;
638  index_set<LO,HI> local_ist;
639  // Parsing control variables.
640  bool parse_index_list = true;
641  bool expect_closing_brace = false;
642  bool expect_index = false;
643  // Parse an optional opening brace.
644  c = s.peek();
645  // If there is a failure or end of file, this ends parsing.
646  if (!s.good())
647  parse_index_list = false;
648  else
649  { // Check for an opening brace.
650  expect_closing_brace = (c == int('{'));
651  if (expect_closing_brace)
652  { // Consume the opening brace.
653  s.get();
654  // The next character may be a closing brace,
655  // indicating the empty index set.
656  c = s.peek();
657  if (s.good() && (c == int('}')))
658  { // A closing brace has been parsed and is no longer expected.
659  expect_closing_brace = false;
660  // Consume the closing brace.
661  s.get();
662  // This ends parsing.
663  parse_index_list = false;
664  }
665  }
666  }
667  if (s.good() && parse_index_list)
668  { // Parse an optional index list.
669  // The index list starts with a first index.
670  for (s >> i;
671  !s.fail();
672  s >> i)
673  { // An index has been parsed. Check to see if it is in range.
674  if ((i < LO) || (i > HI))
675  { // An index out of range is a failure.
676  s.clear(std::istream::failbit);
677  break;
678  }
679  // Add the index to the index set local_ist.
680  local_ist.set(i);
681  // Immediately after parsing an index, an index is no longer expected.
682  expect_index = false;
683  // Reading the index may have resulted in an end of file condition.
684  // If so, this ends the index list.
685  if (s.eof())
686  break;
687  // The index list continues with a comma, and
688  // may be ended by a closing brace, if it was begun with an opening brace.
689  // Parse a possible comma or closing brace.
690  c = s.peek();
691  if (!s.good())
692  break;
693  // First, test for a closing brace, if expected.
694  if (expect_closing_brace && (c == int('}')))
695  { // Consume the closing brace.
696  s.get();
697  // Immediately after parsing the closing brace, it is no longer expected.
698  expect_closing_brace = false;
699  // A closing brace ends the index list.
700  break;
701  }
702  // Now test for a comma.
703  if (c == int(','))
704  { // Consume the comma.
705  s.get();
706  // A index is expected after the comma.
707  expect_index = true;
708  }
709  else
710  { // Any other character here is a failure.
711  s.clear(std::istream::failbit);
712  break;
713  }
714  }
715  }
716  // If an index or a closing brace is still expected, this is a failure.
717  if (expect_index || expect_closing_brace)
718  s.clear(std::istream::failbit);
719  // End of file is not a failure.
720  if (s)
721  { // The index set has been successfully parsed.
722  ist = local_ist;
723  }
724  return s;
725  }
726 
728  template<const index_t LO, const index_t HI>
729  inline
730  bool
733  {
734  const index_t min_index = this->min();
735  const index_t max_index = this->max();
736  return (min_index < 0 && max_index > 0)
737  ? max_index - min_index == this->count()
738  : (min_index == 1 || max_index == -1) &&
739  (max_index - min_index == this->count() - 1);
740  }
741 
743  template<const index_t LO, const index_t HI>
744  inline
745  const
748  fold() const
749  { return this->fold(*this, true); }
750 
752  template<const index_t LO, const index_t HI>
753  const
756  fold(const index_set_t frm, const bool prechecked) const
757  {
758  if (!prechecked && ((*this | frm) != frm))
759  throw error_t("fold(frm): cannot fold from outside of frame");
760  const index_t frm_min = frm.min();
761  const index_t frm_max = frm.max();
762  index_set_t result;
763  index_t fold_idx = -1;
764  index_t unfold_idx;
765  for (unfold_idx = -1;
766  unfold_idx >= frm_min;
767  --unfold_idx)
768  if (frm.test(unfold_idx))
769  // result.set(fold_idx--, this->test(unfold_idx));
770  {
771  if (this->test(unfold_idx))
772  result.set(fold_idx);
773  --fold_idx;
774  }
775  fold_idx = 1;
776  for (unfold_idx = 1;
777  unfold_idx <= frm_max;
778  ++unfold_idx)
779  if (frm.test(unfold_idx))
780  // result.set(fold_idx++, this->test(unfold_idx));
781  {
782  if (this->test(unfold_idx))
783  result.set(fold_idx);
784  ++fold_idx;
785  }
786  return result;
787  }
788 
790  template<const index_t LO, const index_t HI>
791  const
794  unfold(const index_set_t frm, const bool prechecked) const
795  {
796  const char* msg =
797  "unfold(frm): cannot unfold into a smaller frame";
798  const index_t frm_min = frm.min();
799  const index_t frm_max = frm.max();
800  index_set_t result;
801  index_t fold_idx = -1;
802  index_t unfold_idx;
803  for (unfold_idx = -1;
804  unfold_idx >= frm_min;
805  --unfold_idx)
806  if (frm.test(unfold_idx))
807  if (this->test(fold_idx--))
808  result.set(unfold_idx);
809  if (!prechecked && ((fold_idx+1) > this->min()))
810  throw error_t(msg);
811  fold_idx = 1;
812  for (unfold_idx = 1;
813  unfold_idx <= frm_max;
814  ++unfold_idx)
815  if (frm.test(unfold_idx))
816  if (this->test(fold_idx++))
817  result.set(unfold_idx);
818  if (!prechecked && ((fold_idx-1) < this->max()))
819  throw error_t(msg);
820  return result;
821  }
822 
824  template<const index_t LO, const index_t HI>
825  inline
828  value_of_fold(const index_set_t frm) const
829  {
830  const index_t min_index = frm.fold().min();
831  if (min_index == 0)
832  return 0;
833  else
834  {
835  const index_set_t folded_set = this->fold(frm);
836  const index_t skip = min_index > 0 ? 1 : 0;
837  return folded_set.bitset_t::to_ulong() >> (min_index-LO-skip);
838  }
839  }
840 
842  inline
843  static
844  unsigned long inverse_reversed_gray(unsigned long x)
845  {
846  // Reference: [JA]
847 #if (_GLUCAT_BITS_PER_ULONG >= 64)
848  x ^= x << 32; // for 64-bit words
849 #endif
850  x ^= x << 16; // reversed_gray ** 16
851  x ^= x << 8; // reversed_gray ** 8
852  x ^= x << 4; // reversed_gray ** 4
853  x ^= x << 2; // reversed_gray ** 2
854  x ^= x << 1; // reversed_gray ** 1
855  return x;
856  }
857 
859  inline
860  static
861  unsigned long inverse_gray(unsigned long x)
862  {
863  // Reference: [JA]
864 #if (_GLUCAT_BITS_PER_ULONG >= 64)
865  x ^= x >> 32; // for 64-bit words
866 #endif
867  x ^= x >> 16; // gray ** 16
868  x ^= x >> 8; // gray ** 8
869  x ^= x >> 4; // gray ** 4
870  x ^= x >> 2; // gray ** 2
871  x ^= x >> 1; // gray ** 1
872  return x;
873  }
874 
876  template<const index_t LO, const index_t HI>
877  int
879  sign_of_mult(const index_set_t rhs) const
880  {
881  // Implemented using Walsh functions and Gray codes.
882  // Reference: [L] Chapter 21, 21.3
883  // Reference: [JA]
884  const unsigned long uthis = this->bitset_t::to_ulong();
885  const unsigned long urhs = rhs.bitset_t::to_ulong();
886  const index_t nbits = HI - LO;
887  unsigned long negative = 0;
888  if (nbits > 8)
889  {
890  // Set h to be the inverse reversed Gray code of rhs.
891  // This sets each bit of h to be the cumulative ^ of
892  // the same and lower bits of rhs.
893  const unsigned long h = inverse_reversed_gray(urhs);
894  // Set k to be the inverse Gray code of *this & h.
895  // This sets the low bit of k to be parity(*this & h).
896  const unsigned long k = inverse_gray(uthis & h);
897  // Set q to be the inverse Gray code of the positive part of *this & rhs.
898  const unsigned long q = inverse_gray((uthis & urhs) >> -LO);
899  negative = k ^ q;
900  }
901  else
902  {
903  unsigned long h = 0;
904  index_t j;
905  for (j = 0;
906  j < -LO;
907  ++j)
908  {
909  h ^= urhs >> j;
910  negative ^= h & (uthis >> j);
911  }
912  for (j = -LO;
913  j < nbits;
914  ++j)
915  {
916  negative ^= h & (uthis >> j);
917  h ^= urhs >> j;
918  }
919  }
920  return 1 - int((negative & 1) << 1);
921  }
922 
924  template<const index_t LO, const index_t HI>
925  inline
926  int
929  {
930  int result = 1 - int((this->count_neg() % 2) << 1);
931  switch (this->count() % 4)
932  {
933  case 2:
934  case 3:
935  result *= -1;
936  break;
937  default:
938  break;
939  }
940  return result;
941  }
942 
944  template<const index_t LO, const index_t HI>
945  inline
946  size_t
948  hash_fn() const
949  {
950  static const unsigned long lo_mask = (1UL << -LO) - 1UL;
951  const unsigned long uthis = bitset_t::to_ulong();
952  const unsigned long neg_part = uthis & lo_mask;
953  const unsigned long pos_part = uthis >> -LO;
954  return size_t(neg_part ^ pos_part);
955  }
956 
958  inline
959  int
961  { return (j < 0) ? -1 : 1; }
962 
964  template<const index_t LO, const index_t HI>
965  inline
966  index_t
968  { return std::min(ist.min(), 0); }
969 
971  template<const index_t LO, const index_t HI>
972  inline
973  index_t
975  { return std::max(ist.max(), 0); }
976 
977 // index_set reference
978 
980  template<const index_t LO, const index_t HI>
981  inline
984  m_pst(&ist),
985  m_idx(idx)
986  { }
987 
989  template<const index_t LO, const index_t HI>
990  inline
993  operator= (bool x)
994  {
995  if ( x )
996  m_pst->set(m_idx);
997  else
998  m_pst->reset(m_idx);
999  return *this;
1000  }
1001 
1003  template<const index_t LO, const index_t HI>
1004  inline
1005  typename index_set<LO,HI>::reference&
1008  {
1009  if ( (j.m_pst)[j.m_idx] )
1010  m_pst->set(m_idx);
1011  else
1012  m_pst->reset(m_idx);
1013  return *this;
1014  }
1015 
1017  template<const index_t LO, const index_t HI>
1018  inline
1019  bool
1022  { return !(m_pst->test(m_idx)); }
1023 
1025  template<const index_t LO, const index_t HI>
1026  inline
1028  operator bool () const
1029  { return m_pst->test(m_idx); }
1030 
1032  template<const index_t LO, const index_t HI>
1033  inline
1034  typename index_set<LO,HI>::reference&
1037  {
1038  m_pst->flip(m_idx);
1039  return *this;
1040  }
1041 }
1042 #endif // _GLUCAT_INDEX_SET_IMP_H
reference & flip()
for b[i].flip();
friend int compare(const index_set_t &lhs, const index_set_t &rhs)
bool operator==(const index_set_t rhs) const
Equality.
index_t count_pos() const
Number of positive indices included in set.
const index_set_t fold() const
Fold this index set within itself as a frame.
index_set index_set_t
Definition: index_set.h:84
const index_set_t unfold(const index_set_t frm, const bool prechecked=false) const
Unfold this index set within the given frame.
error< index_set > error_t
Definition: index_set.h:82
index_t max() const
Maximum member.
int sign_of_square() const
Sign of geometric square of a Clifford basis element.
set_value_t value_of_fold(const index_set_t frm) const
The set value of the fold of this index set within the given frame.
index_t count() const
Cardinality: Number of indices included in set.
bool lex_less_than(const index_set_t rhs) const
Lexicographic ordering of two sets: *this < rhs.
static const std::string classname()
Definition: index_set_imp.h:49
index_set_t & operator^=(const index_set_t rhs)
Symmetric set difference: exclusive or.
friend const index_set_t operator^(const index_set_t &lhs, const index_set_t &rhs)
friend class reference
Definition: index_set.h:173
bool operator<(const index_set_t rhs) const
Less than operator used for comparisons, map, etc.
reference & operator=(const bool x)
for b[i] = x;
index_t min() const
Minimum member.
bool is_contiguous() const
Determine if the index set is contiguous, ie. has no gaps.
index_set_t operator~() const
Set complement: not.
int sign_of_mult(const index_set_t ist) const
Sign of geometric product of two Clifford basis elements.
bool operator~() const
Flips a bit.
friend const index_set_t operator&(const index_set_t &lhs, const index_set_t &rhs)
index_t min_neg(const index_set< LO, HI > &ist)
Minimum negative index, or 0 if none.
reference()
Private default constructor is left undefined.
bool operator[](const index_t idx) const
Subscripting: Test idx for membership: test value of bit idx.
index_set_t & operator|=(const index_set_t rhs)
Set union: or.
std::pair< index_t, index_t > index_pair_t
Definition: index_set.h:85
friend const index_set_t operator|(const index_set_t &lhs, const index_set_t &rhs)
index_set_t & flip()
Set complement, except 0: flip all bits, except 0.
bool operator!=(const index_set_t rhs) const
Inequality.
std::bitset< HI-LO > bitset_t
Definition: index_set.h:81
index_set_t & set()
Include all indices except 0: set all bits except 0.
index_set()
Default constructor creates an empty set.
Definition: index_set.h:92
Index set class based on std::bitset<> in Gnu standard C++ library.
Definition: index_set.h:45
Index set member reference.
Definition: index_set.h:177
size_t hash_fn() const
Hash function.
index_t max_pos(const index_set< LO, HI > &ist)
Maximum positive index, or 0 if none.
index_set_t & reset()
Make set empty: Set all bits to 0.
int index_t
Size of index_t should be enough to represent LO, HI.
Definition: global.h:77
unsigned long set_value_t
Size of set_value_t should be enough to contain index_set<LO,HI>
Definition: global.h:79
static unsigned long inverse_reversed_gray(unsigned long x)
Inverse reversed Gray code.
index_set_t & operator&=(const index_set_t rhs)
Set intersection: and.
std::istream & operator>>(std::istream &s, framed_multi< Scalar_T, LO, HI > &val)
Read multivector from input.
static unsigned long inverse_gray(unsigned long x)
Inverse Gray code.
index_t count_neg() const
Number of negative indices included in set.
bool test(const index_t idx) const
Test idx for membership: test value of bit idx.