You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							221 lines
						
					
					
						
							8.4 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							221 lines
						
					
					
						
							8.4 KiB
						
					
					
				| /* -*- c++ -*- (enables emacs c++ mode) */ | |
| /*=========================================================================== | |
|   | |
|  Copyright (C) 2002-2012 Yves Renard | |
|   | |
|  This file is a part of GETFEM++ | |
|   | |
|  Getfem++  is  free software;  you  can  redistribute  it  and/or modify it | |
|  under  the  terms  of the  GNU  Lesser General Public License as published | |
|  by  the  Free Software Foundation;  either version 3 of the License,  or | |
|  (at your option) any later version along with the GCC Runtime Library | |
|  Exception either version 3.1 or (at your option) any later version. | |
|  This program  is  distributed  in  the  hope  that it will be useful,  but | |
|  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
|  or  FITNESS  FOR  A PARTICULAR PURPOSE.  See the GNU Lesser General Public | |
|  License and GCC Runtime Library Exception for more details. | |
|  You  should  have received a copy of the GNU Lesser General Public License | |
|  along  with  this program;  if not, write to the Free Software Foundation, | |
|  Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA. | |
|   | |
|  As a special exception, you  may use  this file  as it is a part of a free | |
|  software  library  without  restriction.  Specifically,  if   other  files | |
|  instantiate  templates  or  use macros or inline functions from this file, | |
|  or  you compile this  file  and  link  it  with other files  to produce an | |
|  executable, this file  does  not  by itself cause the resulting executable | |
|  to be covered  by the GNU Lesser General Public License.  This   exception | |
|  does not  however  invalidate  any  other  reasons why the executable file | |
|  might be covered by the GNU Lesser General Public License. | |
|   | |
| ===========================================================================*/ | |
| 
 | |
| /**@file gmm_sub_index.h | |
|    @author  Yves Renard <Yves.Renard@insa-lyon.fr> | |
|    @date October 13, 2002. | |
|    @brief sub-indices. | |
| */ | |
| 
 | |
| #ifndef GMM_SUB_INDEX_H__ | |
| #define GMM_SUB_INDEX_H__ | |
|  | |
| #include "gmm_def.h" | |
|  | |
| namespace gmm { | |
| 
 | |
|   /* ******************************************************************** */ | |
|   /*		sub indices                               		  */ | |
|   /* ******************************************************************** */ | |
| 
 | |
|   struct basic_index : public std::vector<size_t> { | |
|      | |
|     mutable size_type nb_ref; | |
|     // size_type key1; faire la somme des composantes | |
|     // const basic_index *rind; rindex s'il existe | |
|      | |
| 
 | |
|     size_t operator[](size_type i) const { | |
|       return (i < size()) ? std::vector<size_t>::operator[](i) : size_type(-1); | |
|     } | |
|      | |
|     basic_index() : nb_ref(1) {} | |
|     basic_index(size_type j) : std::vector<size_t>(j), nb_ref(1) {} | |
|     template <typename IT> basic_index(IT b, IT e) | |
|       : std::vector<size_t>(e-b), nb_ref(1) { std::copy(b, e, begin()); } | |
|     basic_index(const basic_index *pbi) : nb_ref(1) { | |
|       const_iterator it = pbi->begin(), ite = pbi->end(); | |
|       size_type i = 0; | |
|       for ( ; it != ite; ++it) i = std::max(i, *it); | |
|       resize(i+1); std::fill(begin(), end(), size_type(-1)); | |
|       for (it = pbi->begin(), i = 0; it != ite; ++it, ++i) | |
| 	std::vector<size_t>::operator[](*it) = i; | |
|     } | |
|     void swap(size_type i, size_type j) { | |
|       std::swap(std::vector<size_t>::operator[](i), | |
| 		std::vector<size_t>::operator[](j)); | |
|     } | |
|      | |
|   }; | |
| 
 | |
|   typedef basic_index *pbasic_index; | |
| 
 | |
|   struct index_generator { | |
| 
 | |
|     template <typename IT> static pbasic_index create_index(IT begin, IT end) | |
|     { return new basic_index(begin, end); } | |
|     static pbasic_index create_rindex(pbasic_index pbi) | |
|     { return new basic_index(pbi); } | |
|     static void attach(pbasic_index pbi) { if (pbi) pbi->nb_ref++; } | |
|     static void unattach(pbasic_index pbi) | |
|       { if (pbi && --(pbi->nb_ref) == 0) delete pbi; } | |
| 
 | |
|   }; | |
| 
 | |
|   struct sub_index { | |
| 
 | |
|     size_type first_, last_; | |
|     typedef basic_index base_type; | |
|     typedef base_type::const_iterator const_iterator; | |
| 
 | |
|     mutable pbasic_index ind; | |
|     mutable pbasic_index rind; | |
| 
 | |
|     void comp_extr(void) { | |
|       std::vector<size_t>::const_iterator it = ind->begin(), ite = ind->end(); | |
|       if (it != ite) { first_=last_= *it; ++it; } else { first_=last_= 0; } | |
|       for (; it != ite; ++it)  | |
| 	{ first_ = std::min(first_, *it); last_ = std::max(last_, *it); } | |
|     } | |
| 
 | |
|     // inline void test_rind(void) const | |
|     //  { if (!rind) rind = index_generator::create_rindex(ind); } | |
|     size_type size(void) const { return ind->size(); } | |
|     size_type first(void) const { return first_; } | |
|     size_type last(void) const { return last_; } | |
|     size_type index(size_type i) const { return (*ind)[i]; } | |
|     size_type rindex(size_type i) const { | |
|       // test_rind(); | |
|       if (i < rind->size()) return (*rind)[i]; else return size_type(-1); | |
|     } | |
|     | |
|     const_iterator  begin(void) const { return  ind->begin(); } | |
|     const_iterator    end(void) const { return  ind->end();   } | |
|     const_iterator rbegin(void) const {/*test_rind();*/ return rind->begin(); } | |
|     const_iterator   rend(void) const {/*test_rind();*/ return rind->end();   } | |
| 
 | |
|     sub_index() : ind(0), rind(0) {} | |
|     template <typename IT> sub_index(IT it, IT ite) | |
|       : ind(index_generator::create_index(it, ite)), | |
| 	rind(index_generator::create_rindex(ind)) { comp_extr(); } | |
|     template <typename CONT> sub_index(const CONT &c) | |
|       : ind(index_generator::create_index(c.begin(), c.end())), | |
| 	rind(index_generator::create_rindex(ind)) | |
|     { comp_extr(); } | |
|     ~sub_index() | |
|       { index_generator::unattach(rind); index_generator::unattach(ind); } | |
|     sub_index(const sub_index &si) : first_(si.first_), last_(si.last_), | |
| 				     ind(si.ind), rind(si.rind) | |
|       { index_generator::attach(rind); index_generator::attach(ind); } | |
|     sub_index &operator =(const sub_index &si) { | |
|       index_generator::unattach(rind); index_generator::unattach(ind); | |
|       ind = si.ind; rind = si.rind; index_generator::attach(rind); | |
|       index_generator::attach(ind); | |
|       first_ = si.first_; last_ = si.last_; | |
|       return *this; | |
|     } | |
|   }; | |
| 
 | |
|   struct unsorted_sub_index : public sub_index { | |
|     typedef basic_index base_type; | |
|     typedef base_type::const_iterator const_iterator; | |
|      | |
|     template <typename IT> unsorted_sub_index(IT it, IT ite) | |
|       : sub_index(it, ite) {} | |
|     template <typename CONT> unsorted_sub_index(const CONT &c) | |
|       : sub_index(c) {} | |
|     unsorted_sub_index() {} | |
|     unsorted_sub_index(const unsorted_sub_index &si) : sub_index((sub_index &)(si)) { } | |
|     unsorted_sub_index &operator =(const unsorted_sub_index &si) | |
|     { sub_index::operator =(si); return *this; } | |
|     void swap(size_type i, size_type j) { | |
|       GMM_ASSERT2(ind->nb_ref <= 1, "Operation not allowed on this index"); | |
|       if (rind) rind->swap((*ind)[i], (*ind)[j]); | |
|       ind->swap(i, j); | |
|     } | |
|   }; | |
| 
 | |
|   inline std::ostream &operator << (std::ostream &o, const sub_index &si) {  | |
|     o << "sub_index("; | |
|     if (si.size() != 0) o << si.index(0); | |
|     for (size_type i = 1; i < si.size(); ++i) o << ", " << si.index(i); | |
|     o << ")"; | |
|     return o; | |
|   } | |
| 
 | |
|   struct sub_interval { | |
|     size_type min, max;  | |
| 
 | |
|     size_type size(void) const { return max - min; } | |
|     size_type first(void) const { return min; } | |
|     size_type last(void) const { return max; } | |
|     size_type index(size_type i) const { return min + i; } | |
|     size_type step(void) const { return 1; } | |
|     size_type rindex(size_type i) const | |
|     { if (i >= min && i < max) return i - min; return size_type(-1); } | |
|     sub_interval(size_type mi, size_type l) : min(mi), max(mi+l) {} | |
|     sub_interval() {} | |
|   }; | |
| 
 | |
|   inline std::ostream &operator << (std::ostream &o, const sub_interval &si) | |
|   { o << "sub_interval(" << si.min << ", " << si.size() << ")"; return o; } | |
| 
 | |
|   struct sub_slice { | |
|     size_type min, max, N; | |
| 
 | |
|     size_type size(void) const { return (max - min) / N; } | |
|     size_type first(void) const { return min; } | |
|     size_type last(void) const { return (min == max) ? max : max+1-N; } | |
|     size_type step(void) const { return N; } | |
|     size_type index(size_type i) const { return min + N * i; } | |
|     size_type rindex(size_type i) const {  | |
|       if (i >= min && i < max) | |
| 	{ size_type j = (i - min); if (j % N == 0) return j / N; } | |
|       return size_type(-1); | |
|     } | |
|     sub_slice(size_type mi, size_type l, size_type n) | |
|       : min(mi), max(mi+l*n), N(n) {} | |
|     sub_slice(void) {} | |
|   }; | |
| 
 | |
|   inline std::ostream &operator << (std::ostream &o, const sub_slice &si) { | |
|     o << "sub_slice(" << si.min << ", " << si.size() << ", " << si.step()  | |
|       << ")"; return o; | |
|   } | |
| 
 | |
|   template<class SUBI> struct index_is_sorted | |
|   {  typedef linalg_true bool_type; }; | |
|   template<> struct index_is_sorted<unsorted_sub_index> | |
|   {  typedef linalg_false bool_type; }; | |
| 
 | |
| } | |
| 
 | |
| #endif //  GMM_SUB_INDEX_H__
 |