dune-common  2.2.1
indexset.hh
Go to the documentation of this file.
1 // $Id$
2 #ifndef DUNE_INDEXSET_HH
3 #define DUNE_INDEXSET_HH
4 
5 #include<algorithm>
8 #include<iostream>
9 
10 #include"localindex.hh"
11 
12 #include <stdint.h> // for uint32_t
13 
14 namespace Dune
15 {
25  // forward declarations
26 
27  template<class TG, class TL>
28  class IndexPair;
29 
35  template<class TG, class TL>
36  std::ostream& operator<<(std::ostream& os, const IndexPair<TG,TL>& pair);
37 
38  template<class TG, class TL>
39  bool operator==(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
40 
41  template<class TG, class TL>
42  bool operator!=(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
43 
44  template<class TG, class TL>
45  bool operator<(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
46 
47  template<class TG, class TL>
48  bool operator>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
49 
50  template<class TG, class TL>
51  bool operator<=(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
52 
53  template<class TG, class TL>
54  bool operator >=(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
55 
56  template<class TG, class TL>
57  bool operator==(const IndexPair<TG,TL>&, const TG&);
58 
59  template<class TG, class TL>
60  bool operator!=(const IndexPair<TG,TL>&, const TG&);
61 
62  template<class TG, class TL>
63  bool operator<(const IndexPair<TG,TL>&, const TG&);
64 
65  template<class TG, class TL>
66  bool operator>(const IndexPair<TG,TL>&, const TG&);
67 
68  template<class TG, class TL>
69  bool operator<=(const IndexPair<TG,TL>&, const TG&);
70 
71  template<class TG, class TL>
72  bool operator >=(const IndexPair<TG,TL>&, const TG&);
73 
74  template<typename T>
75  class MPITraits;
76 
80  template<class TG, class TL>
81  class IndexPair
82  {
83  friend std::ostream& operator<<<>(std::ostream&, const IndexPair<TG,TL>&);
84  friend bool operator==<>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
85  friend bool operator!=<>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
86  friend bool operator< <>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
87  friend bool operator><>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
88  friend bool operator<=<>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
89  friend bool operator>=<>(const IndexPair<TG,TL>&, const IndexPair<TG,TL>&);
90  friend bool operator==<>(const IndexPair<TG,TL>&, const TG&);
91  friend bool operator!=<>(const IndexPair<TG,TL>&, const TG&);
92  friend bool operator< <>(const IndexPair<TG,TL>&, const TG&);
93  friend bool operator> <>(const IndexPair<TG,TL>&, const TG&);
94  friend bool operator<=<>(const IndexPair<TG,TL>&, const TG&);
95  friend bool operator>=<>(const IndexPair<TG,TL>&, const TG&);
96  friend class MPITraits<IndexPair<TG,TL> >;
97 
98  public:
104  typedef TG GlobalIndex;
105 
117  typedef TL LocalIndex;
118 
125  IndexPair(const GlobalIndex& global, const LocalIndex& local);
126 
130  IndexPair();
137  IndexPair(const GlobalIndex& global);
138 
144  inline const GlobalIndex& global() const;
145 
151  inline LocalIndex& local();
152 
158  inline const LocalIndex& local()const;
159 
165  inline void setLocal(int index);
166  private:
168  GlobalIndex global_;
170  LocalIndex local_;
171  };
172 
178  {
197  };
198 
203 
204  // Forward declaration
205  template<class I> class GlobalLookupIndexSet;
206 
213  template<typename TG, typename TL, int N=100>
215  {
216  friend class GlobalLookupIndexSet<ParallelIndexSet<TG,TL,N> >;
217 
218  public:
223  typedef TG GlobalIndex;
224 
236  typedef TL LocalIndex;
237 
242 
243  enum{
250  arraySize= (N>0)?N:1
251  };
252 
254  class iterator :
255  public ArrayList<IndexPair,N>::iterator
256  {
257  typedef typename ArrayList<IndexPair,N>::iterator
258  Father;
260  public:
261  iterator(ParallelIndexSet<TG,TL,N>& indexSet, const Father& father)
262  : Father(father), indexSet_(&indexSet)
263  {}
264 
265  iterator(const iterator& other)
266  : Father(other), indexSet_(other.indexSet_)
267  {}
268 
269  iterator& operator==(const iterator& other)
270  {
271  Father::operator==(other);
272  indexSet_ = other.indexSet_;
273  }
274 
275  private:
283  inline void markAsDeleted() const throw(InvalidIndexSetState)
284  {
285 #ifndef NDEBUG
286  if(indexSet_->state_ != RESIZE)
287  DUNE_THROW(InvalidIndexSetState, "Indices can only be removed "
288  <<"while in RESIZE state!");
289 #endif
290  Father::operator*().local().setState(DELETED);
291  }
292 
294  ParallelIndexSet<TG,TL,N>* indexSet_;
295 
296  };
297 
298 
299 
301  typedef typename
302  ArrayList<IndexPair,N>::const_iterator
304 
309 
314  inline const ParallelIndexSetState& state()
315  {
316  return state_;
317  }
318 
324  void beginResize() throw(InvalidIndexSetState);
325 
334  inline void add(const GlobalIndex& global) throw(InvalidIndexSetState);
335 
344  inline void add(const GlobalIndex& global, const LocalIndex& local)
345  throw(InvalidIndexSetState);
346 
354  inline void markAsDeleted(const iterator& position)
355  throw(InvalidIndexSetState);
356 
369  void endResize() throw(InvalidIndexSetState);
370 
381  inline IndexPair&
382  operator[](const GlobalIndex& global);
383 
393  inline IndexPair&
394  at(const GlobalIndex& global);
395 
406  inline const IndexPair&
407  operator[](const GlobalIndex& global) const;
408 
418  inline const IndexPair&
419  at(const GlobalIndex& global) const;
420 
425  inline iterator begin();
426 
431  inline iterator end();
432 
437  inline const_iterator begin() const;
438 
443  inline const_iterator end() const;
444 
454  inline void renumberLocal();
455 
462  inline int seqNo() const;
463 
468  inline size_t size() const;
469 
470  private:
472  ArrayList<IndexPair,N> localIndices_;
474  ArrayList<IndexPair,N> newIndices_;
476  ParallelIndexSetState state_;
478  int seqNo_;
480  bool deletedEntries_;
485  inline void merge();
486  };
487 
488 
494  template<class TG, class TL, int N>
495  std::ostream& operator<<(std::ostream& os, const ParallelIndexSet<TG,TL,N>& indexSet);
496 
502  template<class I>
504  {
505  public:
509  typedef I ParallelIndexSet;
510 
515 
520 
525 
527 
534  GlobalLookupIndexSet(const ParallelIndexSet& indexset, std::size_t size);
535 
541  GlobalLookupIndexSet(const ParallelIndexSet& indexset);
542 
546  ~GlobalLookupIndexSet();
547 
557  inline const IndexPair&
558  operator[](const GlobalIndex& global) const;
559 
563  inline const IndexPair*
564  pair(const std::size_t& local) const;
565 
570  inline const_iterator begin() const;
571 
576  inline const_iterator end() const;
577 
584  inline int seqNo() const;
585 
590  inline size_t size() const;
591  private:
595  const ParallelIndexSet& indexSet_;
596 
600  std::size_t size_;
601 
605  std::vector<const IndexPair*> indices_;
606 
607  };
608 
609 
610  template<typename T>
612  {
613  static bool compare(const T& t1, const T& t2){
614  return false;
615  }
616  };
617 
618  template<class TG, class TL>
620  {
621  bool operator()(const IndexPair<TG,TL>& i1, const IndexPair<TG,TL>& i2)
622  {
623  return i1.global()<i2.global() || (i1.global()==i2.global() &&
625  i2.local()));
626  }
627  };
628 
629 
630 
631  template<class TG, class TL>
632  inline std::ostream& operator<<(std::ostream& os, const IndexPair<TG,TL>& pair)
633  {
634  os<<"{global="<<pair.global_<<", local="<<pair.local_<<"}";
635  return os;
636  }
637 
638  template<class TG, class TL, int N>
639  inline std::ostream& operator<<(std::ostream& os, const ParallelIndexSet<TG,TL,N>& indexSet)
640  {
641  typedef typename ParallelIndexSet<TG,TL,N>::const_iterator Iterator;
642  Iterator end = indexSet.end();
643  os<<"{";
644  for(Iterator index = indexSet.begin(); index != end; ++index)
645  os<<*index<<" ";
646  os<<"}";
647  return os;
648 
649  }
650 
651  template<class TG, class TL>
652  inline bool operator==(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
653  {
654  return a.global_==b.global_;
655  }
656 
657  template<class TG, class TL>
658  inline bool operator!=(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
659  {
660  return a.global_!=b.global_;
661  }
662 
663  template<class TG, class TL>
664  inline bool operator<(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
665  {
666  return a.global_<b.global_;
667  }
668 
669  template<class TG, class TL>
670  inline bool operator>(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
671  {
672  return a.global_>b.global_;
673  }
674 
675  template<class TG, class TL>
676  inline bool operator<=(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
677  {
678  return a.global_<=b.global_;
679  }
680 
681  template<class TG, class TL>
682  inline bool operator >=(const IndexPair<TG,TL>& a, const IndexPair<TG,TL>& b)
683  {
684  return a.global_>=b.global_;
685  }
686 
687  template<class TG, class TL>
688  inline bool operator==(const IndexPair<TG,TL>& a, const TG& b)
689  {
690  return a.global_==b;
691  }
692 
693  template<class TG, class TL>
694  inline bool operator!=(const IndexPair<TG,TL>& a, const TG& b)
695  {
696  return a.global_!=b;
697  }
698 
699  template<class TG, class TL>
700  inline bool operator<(const IndexPair<TG,TL>& a, const TG& b)
701  {
702  return a.global_<b;
703  }
704 
705  template<class TG, class TL>
706  inline bool operator>(const IndexPair<TG,TL>& a, const TG& b)
707  {
708  return a.global_>b;
709  }
710 
711  template<class TG, class TL>
712  inline bool operator<=(const IndexPair<TG,TL>& a, const TG& b)
713  {
714  return a.global_<=b;
715  }
716 
717  template<class TG, class TL>
718  inline bool operator >=(const IndexPair<TG,TL>& a, const TG& b)
719  {
720  return a.global_>=b;
721  }
722 
723 #ifndef DOXYGEN
724 
725  template<class TG, class TL>
726  IndexPair<TG,TL>::IndexPair(const TG& global, const TL& local)
727  : global_(global), local_(local){}
728 
729  template<class TG, class TL>
730  IndexPair<TG,TL>::IndexPair(const TG& global)
731  : global_(global), local_(){}
732 
733  template<class TG, class TL>
734  IndexPair<TG,TL>::IndexPair()
735  : global_(), local_(){}
736 
737  template<class TG, class TL>
738  inline const TG& IndexPair<TG,TL>::global() const{
739  return global_;
740  }
741 
742  template<class TG, class TL>
743  inline TL& IndexPair<TG,TL>::local() {
744  return local_;
745  }
746 
747  template<class TG, class TL>
748  inline const TL& IndexPair<TG,TL>::local() const{
749  return local_;
750  }
751 
752  template<class TG, class TL>
753  inline void IndexPair<TG,TL>::setLocal(int local){
754  local_=local;
755  }
756 
757  template<class TG, class TL, int N>
758  ParallelIndexSet<TG,TL,N>::ParallelIndexSet()
759  : state_(GROUND), seqNo_(0)
760  {}
761 
762  template<class TG, class TL, int N>
763  void ParallelIndexSet<TG,TL,N>::beginResize() throw(InvalidIndexSetState)
764  {
765 
766  // Checks in unproductive code
767 #ifndef NDEBUG
768  if(state_!=GROUND)
769  DUNE_THROW(InvalidIndexSetState,
770  "IndexSet has to be in GROUND state, when "
771  << "beginResize() is called!");
772 #endif
773 
774  state_ = RESIZE;
775  deletedEntries_ = false;
776  }
777 
778  template<class TG, class TL, int N>
779  inline void ParallelIndexSet<TG,TL,N>::add(const GlobalIndex& global)
780  throw(InvalidIndexSetState)
781  {
782  // Checks in unproductive code
783 #ifndef NDEBUG
784  if(state_ != RESIZE)
785  DUNE_THROW(InvalidIndexSetState, "Indices can only be added "
786  <<"while in RESIZE state!");
787 #endif
788  newIndices_.push_back(IndexPair(global));
789  }
790 
791  template<class TG, class TL, int N>
792  inline void ParallelIndexSet<TG,TL,N>::add(const TG& global, const TL& local)
793  throw(InvalidIndexSetState)
794  {
795  // Checks in unproductive code
796 #ifndef NDEBUG
797  if(state_ != RESIZE)
798  DUNE_THROW(InvalidIndexSetState, "Indices can only be added "
799  <<"while in RESIZE state!");
800 #endif
801  newIndices_.push_back(IndexPair(global,local));
802  }
803 
804  template<class TG, class TL, int N>
805  inline void ParallelIndexSet<TG,TL,N>::markAsDeleted(const iterator& global)
806  throw(InvalidIndexSetState){
807  // Checks in unproductive code
808 #ifndef NDEBUG
809  if(state_ != RESIZE)
810  DUNE_THROW(InvalidIndexSetState, "Indices can only be removed "
811  <<"while in RESIZE state!");
812 #endif
813  deletedEntries_ = true;
814 
815  global.markAsDeleted();
816  }
817 
818  template<class TG, class TL, int N>
819  void ParallelIndexSet<TG,TL,N>::endResize() throw(InvalidIndexSetState){
820  // Checks in unproductive code
821 #ifndef NDEBUG
822  if(state_ != RESIZE)
823  DUNE_THROW(InvalidIndexSetState, "endResize called while not "
824  <<"in RESIZE state!");
825 #endif
826 
827  std::sort(newIndices_.begin(), newIndices_.end(), IndexSetSortFunctor<TG,TL>());
828  merge();
829  seqNo_++;
830  state_ = GROUND;
831  }
832 
833 
834  template<class TG, class TL, int N>
835  inline void ParallelIndexSet<TG,TL,N>::merge(){
836  if(localIndices_.size()==0)
837  {
838  localIndices_=newIndices_;
839  newIndices_.clear();
840  }
841  else if(newIndices_.size()>0 || deletedEntries_)
842  {
843  ArrayList<IndexPair,N> tempPairs;
844  typedef typename ArrayList<IndexPair,N>::iterator iterator;
845  typedef typename ArrayList<IndexPair,N>::const_iterator const_iterator;
846 
847  iterator old=localIndices_.begin();
848  iterator added=newIndices_.begin();
849  const const_iterator endold=localIndices_.end();
850  const const_iterator endadded=newIndices_.end();
851 
852  while(old != endold && added!= endadded)
853  {
854  if(old->local().state()==DELETED){
855  old.eraseToHere();
856  }
857  else
858  {
859  if(old->global() < added->global() ||
860  (old->global() == added->global()
861  && LocalIndexComparator<TL>::compare(old->local(),added->local())))
862  {
863  tempPairs.push_back(*old);
864  old.eraseToHere();
865  continue;
866  }else
867  {
868  tempPairs.push_back(*added);
869  added.eraseToHere();
870  }
871  }
872  }
873 
874  while(old != endold)
875  {
876  if(old->local().state()!=DELETED){
877  tempPairs.push_back(*old);
878  }
879  old.eraseToHere();
880  }
881 
882  while(added!= endadded)
883  {
884  tempPairs.push_back(*added);
885  added.eraseToHere();
886  }
887  localIndices_ = tempPairs;
888  }
889  }
890 
891 
892  template<class TG, class TL, int N>
893  inline const IndexPair<TG,TL>&
894  ParallelIndexSet<TG,TL,N>::at(const TG& global) const
895  {
896  // perform a binary search
897  int low=0, high=localIndices_.size()-1, probe=-1;
898 
899  while(low<high)
900  {
901  probe = (high + low) / 2;
902  if(global <= localIndices_[probe].global())
903  high = probe;
904  else
905  low = probe+1;
906  }
907 
908  if(probe==-1)
909  DUNE_THROW(RangeError, "No entries!");
910 
911  if( localIndices_[low].global() != global)
912  DUNE_THROW(RangeError, "Could not find entry of "<<global);
913  else
914  return localIndices_[low];
915  }
916 
917  template<class TG, class TL, int N>
918  inline const IndexPair<TG,TL>&
919  ParallelIndexSet<TG,TL,N>::operator[](const TG& global) const
920  {
921  // perform a binary search
922  int low=0, high=localIndices_.size()-1, probe=-1;
923 
924  while(low<high)
925  {
926  probe = (high + low) / 2;
927  if(global <= localIndices_[probe].global())
928  high = probe;
929  else
930  low = probe+1;
931  }
932 
933  return localIndices_[low];
934  }
935  template<class TG, class TL, int N>
936  inline IndexPair<TG,TL>& ParallelIndexSet<TG,TL,N>::at(const TG& global)
937  {
938  // perform a binary search
939  int low=0, high=localIndices_.size()-1, probe=-1;
940 
941  while(low<high)
942  {
943  probe = (high + low) / 2;
944  if(localIndices_[probe].global() >= global)
945  high = probe;
946  else
947  low = probe+1;
948  }
949 
950  if(probe==-1)
951  DUNE_THROW(RangeError, "No entries!");
952 
953  if( localIndices_[low].global() != global)
954  DUNE_THROW(RangeError, "Could not find entry of "<<global);
955  else
956  return localIndices_[low];
957  }
958 
959  template<class TG, class TL, int N>
960  inline IndexPair<TG,TL>& ParallelIndexSet<TG,TL,N>::operator[](const TG& global)
961  {
962  // perform a binary search
963  int low=0, high=localIndices_.size()-1, probe=-1;
964 
965  while(low<high)
966  {
967  probe = (high + low) / 2;
968  if(localIndices_[probe].global() >= global)
969  high = probe;
970  else
971  low = probe+1;
972  }
973 
974  return localIndices_[low];
975  }
976  template<class TG, class TL, int N>
977  inline typename ParallelIndexSet<TG,TL,N>::iterator
978  ParallelIndexSet<TG,TL,N>::begin()
979  {
980  return iterator(*this, localIndices_.begin());
981  }
982 
983 
984  template<class TG, class TL, int N>
985  inline typename ParallelIndexSet<TG,TL,N>::iterator
986  ParallelIndexSet<TG,TL,N>::end()
987  {
988  return iterator(*this,localIndices_.end());
989  }
990 
991  template<class TG, class TL, int N>
992  inline typename ParallelIndexSet<TG,TL,N>::const_iterator
993  ParallelIndexSet<TG,TL,N>::begin() const
994  {
995  return localIndices_.begin();
996  }
997 
998 
999  template<class TG, class TL, int N>
1000  inline typename ParallelIndexSet<TG,TL,N>::const_iterator
1001  ParallelIndexSet<TG,TL,N>::end() const
1002  {
1003  return localIndices_.end();
1004  }
1005 
1006  template<class TG, class TL, int N>
1007  void ParallelIndexSet<TG,TL,N>::renumberLocal(){
1008 #ifndef NDEBUG
1009  if(state_==RESIZE)
1010  DUNE_THROW(InvalidIndexSetState, "IndexSet has to be in "
1011  <<"GROUND state for renumberLocal()");
1012 #endif
1013 
1014  typedef typename ArrayList<IndexPair,N>::iterator iterator;
1015  const const_iterator end_ = end();
1016  uint32_t index=0;
1017 
1018  for(iterator pair=begin(); pair!=end_; index++, ++pair)
1019  pair->local()=index;
1020  }
1021 
1022  template<class TG, class TL, int N>
1023  inline int ParallelIndexSet<TG,TL,N>::seqNo() const
1024  {
1025  return seqNo_;
1026  }
1027 
1028  template<class TG, class TL, int N>
1029  inline size_t ParallelIndexSet<TG,TL,N>::size() const
1030  {
1031  return localIndices_.size();
1032  }
1033 
1034  template<class I>
1035  GlobalLookupIndexSet<I>::GlobalLookupIndexSet(const I& indexset,
1036  std::size_t size)
1037  : indexSet_(indexset), size_(size),
1038  indices_(size_, static_cast<const IndexPair*>(0))
1039  {
1040  const_iterator end_ = indexSet_.end();
1041 
1042  for(const_iterator pair = indexSet_.begin(); pair!=end_; ++pair){
1043  assert(pair->local()<size_);
1044  indices_[pair->local()] = &(*pair);
1045  }
1046  }
1047 
1048  template<class I>
1049  GlobalLookupIndexSet<I>::GlobalLookupIndexSet(const I& indexset)
1050  : indexSet_(indexset), size_(0)
1051  {
1052  const_iterator end_ = indexSet_.end();
1053  for(const_iterator pair = indexSet_.begin(); pair!=end_; ++pair)
1054  size_=std::max(size_,static_cast<std::size_t>(pair->local()));
1055 
1056  indices_.resize(++size_, 0);
1057 
1058  for(const_iterator pair = indexSet_.begin(); pair!=end_; ++pair)
1059  indices_[pair->local()] = &(*pair);
1060  }
1061 
1062  template<class I>
1063  GlobalLookupIndexSet<I>::~GlobalLookupIndexSet()
1064  {}
1065 
1066  template<class I>
1067  inline const IndexPair<typename I::GlobalIndex, typename I::LocalIndex>*
1068  GlobalLookupIndexSet<I>::pair(const std::size_t& local) const
1069  {
1070  return indices_[local];
1071  }
1072 
1073  template<class I>
1074  inline const IndexPair<typename I::GlobalIndex, typename I::LocalIndex>&
1075  GlobalLookupIndexSet<I>::operator[](const GlobalIndex& global) const
1076  {
1077  return indexSet_[global];
1078  }
1079 
1080  template<class I>
1081  typename I::const_iterator GlobalLookupIndexSet<I>::begin() const
1082  {
1083  return indexSet_.begin();
1084  }
1085 
1086  template<class I>
1087  typename I::const_iterator GlobalLookupIndexSet<I>::end() const
1088  {
1089  return indexSet_.end();
1090  }
1091 
1092  template<class I>
1093  inline size_t GlobalLookupIndexSet<I>::size() const
1094  {
1095  return size_;
1096  }
1097 
1098  template<class I>
1099  inline int GlobalLookupIndexSet<I>::seqNo() const
1100  {
1101  return indexSet_.seqNo();
1102  }
1103 
1104  template<typename TG, typename TL, int N, typename TG1, typename TL1, int N1>
1105  bool operator==(const ParallelIndexSet<TG,TL,N>& idxset,
1106  const ParallelIndexSet<TG1,TL1,N1>& idxset1)
1107  {
1108  if(idxset.size()!=idxset1.size())
1109  return false;
1110  typedef typename ParallelIndexSet<TG,TL,N>::const_iterator Iter;
1111  typedef typename ParallelIndexSet<TG1,TL1,N1>::const_iterator Iter1;
1112  Iter iter=idxset.begin();
1113  for(Iter1 iter1=idxset1.begin(); iter1 != idxset1.end(); ++iter, ++iter1){
1114  if(iter1->global()!=iter->global())
1115  return false;
1116  typedef typename ParallelIndexSet<TG,TL,N>::LocalIndex PI;
1117  const PI& pi=iter->local(), pi1=iter1->local();
1118 
1119  if(pi!=pi1)
1120  return false;
1121  }
1122  return true;
1123  }
1124 
1125  template<typename TG, typename TL, int N, typename TG1, typename TL1, int N1>
1126  bool operator!=(const ParallelIndexSet<TG,TL,N>& idxset,
1127  const ParallelIndexSet<TG1,TL1,N1>& idxset1)
1128  {
1129  return !(idxset==idxset1);
1130  }
1131 
1132 
1133 #endif // DOXYGEN
1134 
1135 }
1136 #endif