Salome HOME
Unwarningization under Win.
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingMemArray.txx
1 // Copyright (C) 2007-2013  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 <cstdlib>
31 #include <algorithm>
32
33 namespace ParaMEDMEM
34 {
35   template<class T>
36   void MEDCouplingPointer<T>::setInternal(T *pointer)
37   {
38     _internal=pointer;
39     _external=0;
40   }
41
42   template<class T>
43   void MEDCouplingPointer<T>::setExternal(const T *pointer)
44   {
45     _external=pointer;
46     _internal=0;
47   }
48
49   template<class T>
50   MemArray<T>::MemArray(const MemArray<T>& other):_nb_of_elem(0),_nb_of_elem_alloc(0),_ownership(false),_dealloc(0),_param_for_deallocator(0)
51   {
52     if(!other._pointer.isNull())
53       {
54         _nb_of_elem_alloc=other._nb_of_elem;
55         T *pointer=(T*)malloc(_nb_of_elem_alloc*sizeof(T));
56         std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+other._nb_of_elem,pointer);
57         useArray(pointer,true,C_DEALLOC,other._nb_of_elem);
58       }
59   }
60
61   template<class T>
62   void MemArray<T>::useArray(const T *array, bool ownership, DeallocType type, std::size_t nbOfElem)
63   {
64     destroy();
65     _nb_of_elem=nbOfElem;
66     _nb_of_elem_alloc=nbOfElem;
67     if(ownership)
68       _pointer.setInternal(const_cast<T *>(array));
69     else
70       _pointer.setExternal(array);
71     _ownership=ownership;
72     _dealloc=BuildFromType(type);
73   }
74
75   template<class T>
76   void MemArray<T>::useExternalArrayWithRWAccess(const T *array, std::size_t nbOfElem)
77   {
78     destroy();
79     _nb_of_elem=nbOfElem;
80     _nb_of_elem_alloc=nbOfElem;
81     _pointer.setInternal(const_cast<T *>(array));
82     _ownership=false;
83     _dealloc=CPPDeallocator;
84   }
85   
86   template<class T>
87   void MemArray<T>::writeOnPlace(std::size_t id, T element0, const T *others, std::size_t sizeOfOthers)
88   {
89     if(id+sizeOfOthers>=_nb_of_elem_alloc)
90       reserve(2*_nb_of_elem+sizeOfOthers+1);
91     T *pointer=_pointer.getPointer();
92     pointer[id]=element0;
93     std::copy(others,others+sizeOfOthers,pointer+id+1);
94     _nb_of_elem=std::max<std::size_t>(_nb_of_elem,id+sizeOfOthers+1);
95   }
96   
97   template<class T>
98   template<class InputIterator>
99   void MemArray<T>::insertAtTheEnd(InputIterator first, InputIterator last)
100   {
101     T *pointer=_pointer.getPointer();
102     while(first!=last)
103       {
104         if(_nb_of_elem>=_nb_of_elem_alloc)
105           {
106             reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1);
107             pointer=_pointer.getPointer();
108           }
109         pointer[_nb_of_elem++]=*first++;
110       }
111   }
112   
113   template<class T>
114   void MemArray<T>::pushBack(T elem)
115   {
116     if(_nb_of_elem>=_nb_of_elem_alloc)
117       reserve(_nb_of_elem_alloc>0?2*_nb_of_elem_alloc:1);
118     T *pt=getPointer();
119     pt[_nb_of_elem++]=elem;
120   }
121   
122   template<class T>
123   T MemArray<T>::popBack()
124   {
125     if(_nb_of_elem>0)
126       {
127         const T *pt=getConstPointer();
128         return pt[--_nb_of_elem];
129       }
130     throw INTERP_KERNEL::Exception("MemArray::popBack : nothing to pop in array !");
131   }
132   
133   template<class T>
134   void MemArray<T>::pack() const
135   {
136     if(_nb_of_elem>=0)
137       (const_cast<MemArray<T> * >(this))->reserve(_nb_of_elem);
138   }
139
140   template<class T>
141   bool MemArray<T>::isEqual(const MemArray<T>& other, T prec, std::string& reason) const
142   {
143     std::ostringstream oss; oss.precision(15);
144     if(_nb_of_elem!=other._nb_of_elem)
145       {
146         oss << "Number of elements in coarse data of DataArray mismatch : this=" << _nb_of_elem << " other=" << other._nb_of_elem;
147         reason=oss.str();
148         return false;
149       }
150     const T *pt1=_pointer.getConstPointer();
151     const T *pt2=other._pointer.getConstPointer();
152     if(pt1==0 && pt2==0)
153       return true;
154     if(pt1==0 || pt2==0)
155       {
156         oss << "coarse data pointer is defined for only one DataArray instance !";
157         reason=oss.str();
158         return false;
159       }
160     if(pt1==pt2)
161       return true;
162     for(std::size_t i=0;i<_nb_of_elem;i++)
163       if(pt1[i]-pt2[i]<-prec || (pt1[i]-pt2[i])>prec)
164         {
165           oss << "The content of data differs at pos #" << i << " of coarse data ! this[i]=" << pt1[i] << " other[i]=" << pt2[i];
166           reason=oss.str();
167           return false;
168         }
169     return true;
170   }
171
172   /*!
173    * \param [in] sl is typically the number of components
174    * \return True if a not null pointer is present, False if not.
175    */
176   template<class T>
177   bool MemArray<T>::reprHeader(int sl, std::ostream& stream) const
178   {
179     stream << "Number of tuples : ";
180     if(!_pointer.isNull())
181       {
182         if(sl!=0)
183           stream << _nb_of_elem/sl << std::endl << "Internal memory facts : " << _nb_of_elem << "/" << _nb_of_elem_alloc;
184        else
185           stream << "Empty Data";
186       }
187     else
188       stream << "No data";
189     stream << "\n";
190     stream << "Data content :\n";
191     bool ret=!_pointer.isNull();
192     if(!ret)
193       stream << "No data !\n";
194     return ret;
195   }
196   
197   /*!
198    * \param [in] sl is typically the number of components
199    */
200   template<class T>
201   void MemArray<T>::repr(int sl, std::ostream& stream) const
202   {
203     if(reprHeader(sl,stream))
204       {
205         const T *data=getConstPointer();
206         if(_nb_of_elem!=0 && sl!=0)
207           {
208             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
209             for(std::size_t i=0;i<nbOfTuples;i++)
210               {
211                 stream << "Tuple #" << i << " : ";
212                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
213                 stream << "\n";
214                 data+=sl;
215               }
216           }
217         else
218           stream << "Empty Data\n";
219       }
220   }
221   
222   /*!
223    * \param [in] sl is typically the number of components
224    */
225   template<class T>
226   void MemArray<T>::reprZip(int sl, std::ostream& stream) const
227   {
228     stream << "Number of tuples : ";
229     if(!_pointer.isNull())
230       {
231         if(sl!=0)
232           stream << _nb_of_elem/sl;
233         else
234           stream << "Empty Data";
235       }
236     else
237       stream << "No data";
238     stream << "\n";
239     stream << "Data content : ";
240     const T *data=getConstPointer();
241     if(!_pointer.isNull())
242       {
243         if(_nb_of_elem!=0 && sl!=0)
244           {
245             std::size_t nbOfTuples=_nb_of_elem/std::abs(sl);
246             for(std::size_t i=0;i<nbOfTuples;i++)
247               {
248                 stream << "|";
249                 std::copy(data,data+sl,std::ostream_iterator<T>(stream," "));
250                 stream << "| ";
251                 data+=sl;
252               }
253             stream << "\n";
254           }
255         else
256           stream << "Empty Data\n";
257       }
258     else
259       stream << "No data !\n";
260   }
261   
262   template<class T>
263   void MemArray<T>::fillWithValue(const T& val)
264   {
265     T *pt=_pointer.getPointer();
266     std::fill(pt,pt+_nb_of_elem,val);
267   }
268   
269   template<class T>
270   T *MemArray<T>::fromNoInterlace(int nbOfComp) const
271   {
272     if(nbOfComp<1)
273       throw INTERP_KERNEL::Exception("MemArray<T>::fromNoInterlace : number of components must be > 0 !");
274     const T *pt=_pointer.getConstPointer();
275     std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
276     T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
277     T *w=ret;
278     for(std::size_t i=0;i<nbOfTuples;i++)
279       for(int j=0;j<nbOfComp;j++,w++)
280         *w=pt[j*nbOfTuples+i];
281     return ret;
282   }
283   
284   template<class T>
285   T *MemArray<T>::toNoInterlace(int nbOfComp) const
286   {
287     if(nbOfComp<1)
288       throw INTERP_KERNEL::Exception("MemArray<T>::toNoInterlace : number of components must be > 0 !");
289     const T *pt=_pointer.getConstPointer();
290     std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
291     T *ret=(T*)malloc(_nb_of_elem*sizeof(T));
292     T *w=ret;
293     for(int i=0;i<nbOfComp;i++)
294       for(std::size_t j=0;j<nbOfTuples;j++,w++)
295         *w=pt[j*nbOfComp+i];
296     return ret;
297   }
298
299   template<class T>
300   void MemArray<T>::sort(bool asc)
301   {
302     T *pt=_pointer.getPointer();
303     if(asc)
304       std::sort(pt,pt+_nb_of_elem);
305     else
306       {
307         typename std::reverse_iterator<T *> it1(pt+_nb_of_elem);
308         typename std::reverse_iterator<T *> it2(pt);
309         std::sort(it1,it2);
310       }
311   }
312
313   template<class T>
314   void MemArray<T>::reverse(int nbOfComp)
315   {
316     if(nbOfComp<1)
317       throw INTERP_KERNEL::Exception("MemArray<T>::reverse : only supported with 'this' array with ONE or more than ONE component !");
318     T *pt=_pointer.getPointer();
319     if(nbOfComp==1)
320       {
321         std::reverse(pt,pt+_nb_of_elem);
322         return ;
323       }
324     else
325       {
326         T *pt2=pt+_nb_of_elem-nbOfComp;
327         std::size_t nbOfTuples=_nb_of_elem/nbOfComp;
328         for(std::size_t i=0;i<nbOfTuples/2;i++,pt+=nbOfComp,pt2-=nbOfComp)
329           {
330             for(int j=0;j<nbOfComp;j++)
331               std::swap(pt[j],pt2[j]);
332           }
333       }
334   }
335
336   template<class T>
337   void MemArray<T>::alloc(std::size_t nbOfElements)
338   {
339     destroy();
340     if(nbOfElements<0)
341       throw INTERP_KERNEL::Exception("MemArray::alloc : request for negative length of data !");
342     _nb_of_elem=nbOfElements;
343     _nb_of_elem_alloc=nbOfElements;
344     _pointer.setInternal((T*)malloc(_nb_of_elem_alloc*sizeof(T)));
345     _ownership=true;
346     _dealloc=CDeallocator;
347   }
348
349   /*!
350    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
351    * \a _nb_of_elem and \a _nb_of_elem_alloc will \b NOT be systematically equal (contrary to MemArray<T>::reAlloc method.
352    * So after the call of this method \a _nb_of_elem will be equal tostd::min<std::size_t>(_nb_of_elem,newNbOfElements) and \a _nb_of_elem_alloc equal to 
353    * \a newNbOfElements. This method is typically used to perform a pushBack to avoid systematic allocations-copy-deallocation.
354    * So after the call of this method the accessible content is perfectly set.
355    * 
356    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
357    */
358   template<class T>
359   void MemArray<T>::reserve(std::size_t newNbOfElements)
360   {
361     if(newNbOfElements<0)
362       throw INTERP_KERNEL::Exception("MemArray::reAlloc : request for negative length of data !");
363     if(_nb_of_elem_alloc==newNbOfElements)
364       return ;
365     T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
366     std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
367     if(_ownership)
368       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
369     _pointer.setInternal(pointer);
370     _nb_of_elem=std::min<std::size_t>(_nb_of_elem,newNbOfElements);
371     _nb_of_elem_alloc=newNbOfElements;
372     _ownership=true;
373     _dealloc=CDeallocator;
374     _param_for_deallocator=0;
375   }
376
377   /*!
378    * This method performs systematically an allocation of \a newNbOfElements elements in \a this.
379    * \a _nb_of_elem and \a _nb_of_elem_alloc will be equal even if only std::min<std::size_t>(_nb_of_elem,newNbOfElements) come from the .
380    * The remaing part of the new allocated chunk are available but not set previouly !
381    * 
382    * So this method should not be confused with MemArray<T>::reserve that is close to MemArray<T>::reAlloc but not same.
383    */
384   template<class T>
385   void MemArray<T>::reAlloc(std::size_t newNbOfElements)
386   {
387     if(newNbOfElements<0)
388       throw INTERP_KERNEL::Exception("MemArray::reAlloc : request for negative length of data !");
389     if(_nb_of_elem==newNbOfElements)
390       return ;
391     T *pointer=(T*)malloc(newNbOfElements*sizeof(T));
392     std::copy(_pointer.getConstPointer(),_pointer.getConstPointer()+std::min<std::size_t>(_nb_of_elem,newNbOfElements),pointer);
393     if(_ownership)
394       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
395     _pointer.setInternal(pointer);
396     _nb_of_elem=newNbOfElements;
397     _nb_of_elem_alloc=newNbOfElements;
398     _ownership=true;
399     _dealloc=CDeallocator;
400     _param_for_deallocator=0;
401   }
402
403   template<class T>
404   void MemArray<T>::CPPDeallocator(void *pt, void *param)
405   {
406     delete [] reinterpret_cast<T*>(pt);
407   }
408
409   template<class T>
410   void MemArray<T>::CDeallocator(void *pt, void *param)
411   {
412     free(pt);
413   }
414
415   template<class T>
416   typename MemArray<T>::Deallocator MemArray<T>::BuildFromType(DeallocType type)
417   {
418     switch(type)
419       {
420       case CPP_DEALLOC:
421         return CPPDeallocator;
422       case C_DEALLOC:
423         return CDeallocator;
424       default:
425         throw INTERP_KERNEL::Exception("Invalid deallocation requested ! Unrecognized enum DeallocType !");
426       }
427   }
428
429   template<class T>
430   void MemArray<T>::DestroyPointer(T *pt, typename MemArray<T>::Deallocator dealloc, void *param)
431   {
432     if(dealloc)
433       dealloc(pt,param);
434   }
435
436   template<class T>
437   void MemArray<T>::destroy()
438   {
439     if(_ownership)
440       DestroyPointer(const_cast<T *>(_pointer.getConstPointer()),_dealloc,_param_for_deallocator);//Do not use getPointer because in case of _external
441     _pointer.null();
442     _ownership=false;
443     _dealloc=NULL;
444     _param_for_deallocator=NULL;
445     _nb_of_elem=0;
446     _nb_of_elem_alloc=0;
447   }
448   
449   template<class T>
450   MemArray<T> &MemArray<T>::operator=(const MemArray<T>& other)
451   {
452     alloc(other._nb_of_elem);
453     std::copy(other._pointer.getConstPointer(),other._pointer.getConstPointer()+_nb_of_elem,_pointer.getPointer());
454     return *this;
455   }
456 }
457
458 #endif