Salome HOME
Merge from V6_main 11/02/2013
[modules/med.git] / src / MEDCoupling / MEDCouplingMemArray.txx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #ifndef __PARAMEDMEM_MEDCOUPLINGMEMARRAY_TXX__
22 #define __PARAMEDMEM_MEDCOUPLINGMEMARRAY_TXX__
23
24 #include "MEDCouplingMemArray.hxx"
25 #include "NormalizedUnstructuredMesh.hxx"
26 #include "InterpKernelException.hxx"
27 #include "InterpolationUtils.hxx"
28
29 #include <sstream>
30 #include <algorithm>
31
32 namespace ParaMEDMEM
33 {
34   template<class T>
35   void MEDCouplingPointer<T>::setInternal(T *pointer)
36   {
37     _internal=pointer;
38     _external=0;
39   }
40
41   template<class T>
42   void MEDCouplingPointer<T>::setExternal(const T *pointer)
43   {
44     _external=pointer;
45     _internal=0;
46   }
47
48   template<class T>
49   MemArray<T>::MemArray(const MemArray<T>& other):_nb_of_elem(0),_nb_of_elem_alloc(0),_ownership(false),_dealloc(CPP_DEALLOC)
50   {
51     if(!other._pointer.isNull())
52       {
53         _nb_of_elem_alloc=other._nb_of_elem;
54         T *pointer=new T[_nb_of_elem_alloc];
55         std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+other._nb_of_elem,pointer);
56         useArray(pointer,true,CPP_DEALLOC,other._nb_of_elem);
57       }
58   }
59
60   template<class T>
61   void MemArray<T>::useArray(const T *array, bool ownership, DeallocType type, int nbOfElem)
62   {
63     _nb_of_elem=nbOfElem;
64     _nb_of_elem_alloc=nbOfElem;
65     destroy();
66     if(ownership)
67       _pointer.setInternal(const_cast<T *>(array));
68     else
69       _pointer.setExternal(array);
70     _ownership=ownership;
71     _dealloc=type;
72   }
73
74   template<class T>
75   void MemArray<T>::useExternalArrayWithRWAccess(const T *array, int nbOfElem)
76   {
77     _nb_of_elem=nbOfElem;
78     _nb_of_elem_alloc=nbOfElem;
79     destroy();
80     _pointer.setInternal(const_cast<T *>(array));
81     _ownership=false;
82     _dealloc=CPP_DEALLOC;
83   }
84   
85   template<class T>
86   void MemArray<T>::writeOnPlace(int id, T element0, const T *others, int sizeOfOthers)
87   {
88     if(id+sizeOfOthers>=_nb_of_elem_alloc)
89       reserve(2*_nb_of_elem+sizeOfOthers+1);
90     T *pointer=_pointer.getPointer();
91     pointer[id]=element0;
92     std::copy(others,others+sizeOfOthers,pointer+id+1);
93     _nb_of_elem=std::max<int>(_nb_of_elem,id+sizeOfOthers+1);
94   }
95   
96   template<class T>
97   template<class InputIterator>
98   void MemArray<T>::insertAtTheEnd(InputIterator first, InputIterator last)
99   {
100     T *pointer=_pointer.getPointer();
101     while(first!=last)
102       {
103         if(_nb_of_elem>=_nb_of_elem_alloc || _nb_of_elem==0)
104           {
105             reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1);
106             pointer=_pointer.getPointer();
107           }
108         pointer[_nb_of_elem++]=*first++;
109       }
110   }
111   
112   template<class T>
113   void MemArray<T>::pushBack(T elem) throw(INTERP_KERNEL::Exception)
114   {
115     if(_nb_of_elem>=_nb_of_elem_alloc)
116       reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1);
117     T *pt=getPointer();
118     pt[_nb_of_elem++]=elem;
119   }
120   
121   template<class T>
122   T MemArray<T>::popBack() throw(INTERP_KERNEL::Exception)
123   {
124     if(_nb_of_elem>0)
125       {
126         const T *pt=getConstPointer();
127         return pt[--_nb_of_elem];
128       }
129     throw INTERP_KERNEL::Exception("MemArray::popBack : nothing to pop in array !");
130   }
131   
132   template<class T>
133   void MemArray<T>::pack() const
134   {
135     if(_nb_of_elem>=0)
136       (const_cast<MemArray<T> * >(this))->reserve(_nb_of_elem);
137   }
138
139   template<class T>
140   bool MemArray<T>::isEqual(const MemArray<T>& other, T prec, std::string& reason) const
141   {
142     std::ostringstream oss; oss.precision(15);
143     if(_nb_of_elem!=other._nb_of_elem)
144       {
145         oss << "Number of elements in coarse data of DataArray mismatch : this=" << _nb_of_elem << " other=" << other._nb_of_elem;
146         reason=oss.str();
147         return false;
148       }
149     const T *pt1=_pointer.getConstPointer();
150     const T *pt2=other._pointer.getConstPointer();
151     if(pt1==0 && pt2==0)
152       return true;
153     if(pt1==0 || pt2==0)
154       {
155         oss << "coarse data pointer is defined for only one DataArray instance !";
156         reason=oss.str();
157         return false;
158       }
159     if(pt1==pt2)
160       return true;
161     for(int i=0;i<_nb_of_elem;i++)
162       if(pt1[i]-pt2[i]<-prec || (pt1[i]-pt2[i])>prec)
163         {
164           oss << "The content of data differs at pos #" << i << " of coarse data ! this[i]=" << pt1[i] << " other[i]=" << pt2[i];
165           reason=oss.str();
166           return false;
167         }
168     return true;
169   }
170   
171   /*!
172    * \param [in] sl is typically the number of components
173    */
174   template<class T>
175   void MemArray<T>::repr(int sl, std::ostream& stream) const
176   {
177     stream << "Number of tuples : ";
178     if(!_pointer.isNull())
179       {
180         if(sl!=0)
181           stream << _nb_of_elem/sl << std::endl << "Internal memory facts : " << _nb_of_elem << "/" << _nb_of_elem_alloc;
182        else
183           stream << "Empty Data";
184       }
185     else
186       stream << "No data";
187     stream << "\n";
188     stream << "Data content :\n";
189     const T *data=getConstPointer();
190     if(!_pointer.isNull())
191       {
192         if(_nb_of_elem!=0 && sl!=0)
193           {
194             int nbOfTuples=_nb_of_elem/sl;
195             for(int i=0;i<nbOfTuples;i++)
196               {
197                 stream << "Tuple #" << i << " : ";
198                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
199                 stream << "\n";
200                 data+=sl;
201               }
202           }
203         else
204           stream << "Empty Data\n";
205       }
206     else
207       stream << "No data !\n";
208   }
209   
210   /*!
211    * \param [in] sl is typically the number of components
212    */
213   template<class T>
214   void MemArray<T>::reprZip(int sl, std::ostream& stream) const
215   {
216     stream << "Number of tuples : ";
217     if(!_pointer.isNull())
218       {
219         if(sl!=0)
220           stream << _nb_of_elem/sl;
221         else
222           stream << "Empty Data";
223       }
224     else
225       stream << "No data";
226     stream << "\n";
227     stream << "Data content : ";
228     const T *data=getConstPointer();
229     if(!_pointer.isNull())
230       {
231         if(_nb_of_elem!=0 && sl!=0)
232           {
233             int nbOfTuples=_nb_of_elem/sl;
234             for(int i=0;i<nbOfTuples;i++)
235               {
236                 stream << "|";
237                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
238                 stream << "| ";
239                 data+=sl;
240               }
241             stream << "\n";
242           }
243         else
244           stream << "Empty Data\n";
245       }
246     else
247       stream << "No data !\n";
248   }
249   
250   template<class T>
251   void MemArray<T>::fillWithValue(const T& val)
252   {
253     T *pt=_pointer.getPointer();
254     std::fill(pt,pt+_nb_of_elem,val);
255   }
256   
257   template<class T>
258   T *MemArray<T>::fromNoInterlace(int nbOfComp) const
259   {
260     const T *pt=_pointer.getConstPointer();
261     int nbOfTuples=_nb_of_elem/nbOfComp;
262     T *ret=new T[_nb_of_elem];
263     T *w=ret;
264     for(int i=0;i<nbOfTuples;i++)
265       for(int j=0;j<nbOfComp;j++,w++)
266         *w=pt[j*nbOfTuples+i];
267     return ret;
268   }
269   
270   template<class T>
271   T *MemArray<T>::toNoInterlace(int nbOfComp) const
272   {
273     const T *pt=_pointer.getConstPointer();
274     int nbOfTuples=_nb_of_elem/nbOfComp;
275     T *ret=new T[_nb_of_elem];
276     T *w=ret;
277     for(int i=0;i<nbOfComp;i++)
278       for(int j=0;j<nbOfTuples;j++,w++)
279         *w=pt[j*nbOfComp+i];
280     return ret;
281   }
282
283   template<class T>
284   void MemArray<T>::sort(bool asc)
285   {
286     T *pt=_pointer.getPointer();
287     if(asc)
288       std::sort(pt,pt+_nb_of_elem);
289     else
290       {
291         typename std::reverse_iterator<T *> it1(pt+_nb_of_elem);
292         typename std::reverse_iterator<T *> it2(pt);
293         std::sort(it1,it2);
294       }
295   }
296
297   template<class T>
298   void MemArray<T>::reverse()
299   {
300     T *pt=_pointer.getPointer();
301     std::reverse(pt,pt+_nb_of_elem);
302   }
303
304   template<class T>
305   void MemArray<T>::alloc(int nbOfElements) throw(INTERP_KERNEL::Exception)
306   {
307     destroy();
308     if(nbOfElements<0)
309       throw INTERP_KERNEL::Exception("MemArray::alloc : request for negative length of data !");
310     _nb_of_elem=nbOfElements;
311     _nb_of_elem_alloc=nbOfElements;
312     _pointer.setInternal(new T[_nb_of_elem_alloc]);
313     _ownership=true;
314     _dealloc=CPP_DEALLOC;
315   }
316
317   /*!
318    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
319    * \a _nb_of_elem and \a _nb_of_elem_alloc will \b NOT be systematically equal (contrary to MemArray<T>::reAlloc method.
320    * So after the call of this method \a _nb_of_elem will be equal tostd::min<int>(_nb_of_elem,newNbOfElements) and \a _nb_of_elem_alloc equal to 
321    * \a newNbOfElements. This method is typically used to perform a pushBack to avoid systematic allocations-copy-deallocation.
322    * So after the call of this method the accessible content is perfectly set.
323    * 
324    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
325    */
326   template<class T>
327   void MemArray<T>::reserve(int newNbOfElements) throw(INTERP_KERNEL::Exception)
328   {
329     if(newNbOfElements<0)
330       throw INTERP_KERNEL::Exception("MemArray::reAlloc : request for negative length of data !");
331     if(_nb_of_elem_alloc==newNbOfElements)
332       return ;
333     T *pointer=new T[newNbOfElements];
334     std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<int>(_nb_of_elem,newNbOfElements),pointer);
335     if(_ownership)
336       destroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc);//Do not use getPointer because in case of _external
337     _pointer.setInternal(pointer);
338     _nb_of_elem=std::min<int>(_nb_of_elem,newNbOfElements);
339     _nb_of_elem_alloc=newNbOfElements;
340     _ownership=true;
341     _dealloc=CPP_DEALLOC;
342   }
343
344   /*!
345    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
346    * \a _nb_of_elem and \a _nb_of_elem_alloc will be equal even if only std::min<int>(_nb_of_elem,newNbOfElements) come from the .
347    * The remaing part of the new allocated chunk are available but not set previouly !
348    * 
349    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
350    */
351   template<class T>
352   void MemArray<T>::reAlloc(int newNbOfElements) throw(INTERP_KERNEL::Exception)
353   {
354     if(newNbOfElements<0)
355       throw INTERP_KERNEL::Exception("MemArray::reAlloc : request for negative length of data !");
356     if(_nb_of_elem==newNbOfElements)
357       return ;
358     T *pointer=new T[newNbOfElements];
359     std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<int>(_nb_of_elem,newNbOfElements),pointer);
360     if(_ownership)
361       destroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc);//Do not use getPointer because in case of _external
362     _pointer.setInternal(pointer);
363     _nb_of_elem=newNbOfElements;
364     _nb_of_elem_alloc=newNbOfElements;
365     _ownership=true;
366     _dealloc=CPP_DEALLOC;
367   }
368
369   template<class T>
370   void MemArray<T>::destroyPointer(T *pt, DeallocType type)
371   {
372     switch(type)
373       {
374       case CPP_DEALLOC:
375         {
376           delete [] pt;
377           return ;
378         }
379       case C_DEALLOC:
380         {
381           free(pt);
382           return ;
383         }
384       default:
385         std::ostringstream stream;
386         stream << "Invalid deallocation requested for pointer " << pt;
387         throw INTERP_KERNEL::Exception(stream.str().c_str());
388       }
389   }
390
391   template<class T>
392   void MemArray<T>::destroy()
393   {
394     if(_ownership)
395       destroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc);//Do not use getPointer because in case of _external
396     _pointer.null();
397     _ownership=false;
398   }
399   
400   template<class T>
401   MemArray<T> &MemArray<T>::operator=(const MemArray<T>& other)
402   {
403     alloc(other._nb_of_elem);
404     std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+_nb_of_elem,_pointer.getPointer());
405     return *this;
406   }
407 }
408
409 #endif