source: Sophya/trunk/SophyaLib/BaseTools/ndatablock.cc@ 268

Last change on this file since 268 was 268, checked in by ansari, 26 years ago

fin ndataBlock + AnyDataObj cree rz+cmv 26/4/99

File size: 16.1 KB
Line 
1// Gestion de block de donnees avec partage de references
2// C.Magneville 04/99
3// LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA
4#include "machdefs.h"
5#include <stdio.h>
6#include <stdlib.h>
7#include <iostream.h>
8#include <complex>
9#include "pexceptions.h"
10#include "ndatablock.h"
11
12using namespace PlanckDPC;
13
14//define DEBUG_NDATABLOCK
15
16#ifdef DEBUG_NDATABLOCK
17 static size_t NallocData = 0;
18 static size_t NallocSRef = 0;
19#endif
20
21// LOGIQUE DE BASE:
22// - le createur par copie et la surcharge de l operateur = "partage" les donnees
23// - gestion du partage de reference
24
25//************ Createur, Destructeur, gestion des donnees
26
27template <class T>
28NDataBlock<T>::NDataBlock(size_t n)
29// Createur d'une structure de "n" donnees
30: mSz(0), mSRef(NULL), mIsTemp(false)
31{
32#ifdef DEBUG_NDATABLOCK
33cout<<"DEBUG_NDataBlock::NDataBlock("<<this<<",n="<<n<<")"<<endl;
34#endif
35
36Alloc(n);
37}
38
39template <class T>
40NDataBlock<T>::NDataBlock(size_t n, T* data, Bridge* br)
41// Createur d'une structure de "n" donnees, avec donnees preallouees
42: mSz(0), mSRef(NULL), mIsTemp(false)
43{
44#ifdef DEBUG_NDATABLOCK
45cout<<"DEBUG_NDataBlock::NDataBlock("<<this
46 <<",data="<<data<<",br="<<br<<")"<<endl;
47#endif
48
49Alloc(n,data,br);
50}
51
52template <class T>
53NDataBlock<T>::NDataBlock()
54// Createur par default
55: mSz(0), mSRef(NULL), mIsTemp(false)
56{
57#ifdef DEBUG_NDATABLOCK
58cout<<"DEBUG_NDataBlock::NDataBlock("<<this<<") default"<<endl;
59#endif
60}
61
62template <class T>
63NDataBlock<T>::NDataBlock(const NDataBlock<T>& a)
64// Createur par copie
65// ATTENTION: partage les donnees avec "a"
66// Ecriture: NDataBlock a = b;
67// NDataBlock a(b)
68: mSz(0), mSRef(NULL), mIsTemp(false)
69{
70#ifdef DEBUG_NDATABLOCK
71cout<<"DEBUG_NDataBlock::NDataBlock("<<this<<",&a="<<&a<<") a.(mSz="
72 <<a.mSz<<" mSRef="<<a.mSRef<<" IsTemp="<<a.IsTemp()<<")"<<endl;
73#endif
74
75Share(a);
76}
77
78template <class T>
79NDataBlock<T>::NDataBlock(const NDataBlock<T>& a,bool share)
80// Createur avec choix de partager ou non
81: mSz(0), mSRef(NULL), mIsTemp(false)
82{
83#ifdef DEBUG_NDATABLOCK
84cout<<"DEBUG_NDataBlock::NDataBlock("<<this<<",&a="<<&a<<",sh=<<"<<share<<")"
85 <<" a.(mSz="<<a.mSz<<" mSRef="<<a.mSRef<<" IsTemp="<<a.IsTemp()<<")"<<endl;
86#endif
87
88if(share) Share(a); else Clone(a);
89}
90
91template <class T>
92NDataBlock<T>::~NDataBlock()
93// Destructeur
94{
95#ifdef DEBUG_NDATABLOCK
96cout<<"DEBUG_NDataBlock::~NDataBlock("<<this<<")"<<endl;
97#endif
98
99Delete();
100}
101
102template <class T>
103void NDataBlock<T>::SetTemp(bool temp) const
104// Set temporary
105{
106mIsTemp=temp;
107
108#ifdef DEBUG_NDATABLOCK
109cout<<"DEBUG_NDataBlock::SetTemp("<<this<<","<<temp
110 <<"), mSz="<<mSz<<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp<<endl;
111#endif
112}
113
114template <class T>
115void NDataBlock<T>::Alloc(size_t n,T* data,Bridge* br)
116// Allocation d'un NOUVEL espace de stoquage
117// Si data==NULL : allocation de l'espace memoire
118// data!=NULL : partage des donnees avec l'adresse data
119// Si br==NULL : les donnees nous appartiennent
120// br!=NULL : les donnees ne nous appartiennent pas (ex Blitz)
121// Exemple: on veut connecter a un tableau de T*
122// -- On veut que NDataBlock ne desalloue pas le tableau
123// float *x = new float[5]; ... remplissage de x[] ...;
124// NDataBlock A(5,x,new Bridge);
125// delete [] x; // Il faut deleter explicitement
126// -- On veut que NDataBlock desalloue le tableau
127// ( Ne Pas Faire "delete [] x;" )
128// float *x = new float[5]; ... remplissage de x[] ...;
129// NDataBlock A(5,x);
130// -- Autre solution:
131// NDataBlock A(5); A.FillFrom(5,x);
132{
133#ifdef DEBUG_NDATABLOCK
134cout<<"DEBUG_NDataBlock::Alloc("<<this<<","
135 <<n<<","<<data<<","<<br<<") mSz="<<mSz
136 <<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp<<endl;
137#endif
138
139if(n==0) throw(SzMismatchError("NDataBlock::Alloc n==0\n"));
140if(mSRef) Delete();
141mSz = n;
142mSRef = new NDREF;
143mSRef->nref = 1;
144if(data) mSRef->data = data; else mSRef->data = new T[n];
145mSRef->bridge = br;
146
147#ifdef DEBUG_NDATABLOCK
148if(!data) NallocData++; NallocSRef++;
149cout<<"...DEBUG_NDataBlock::Alloc mSz="<<mSz<<" mSRef="<<mSRef
150 <<" mSRef->nref="<<mSRef->nref<<" mSRef->data="<< mSRef->data
151 <<" mSRef->bridge="<<mSRef->bridge<<" IsTemp="<<mIsTemp
152 <<" Total("<<NallocData<<","<<NallocSRef<<")"<<endl;
153#endif
154}
155
156template <class T>
157void NDataBlock<T>::Clone(const NDataBlock<T>& a)
158// Clone (copie de donnee) a partir de "a"
159{
160 #ifdef DEBUG_NDATABLOCK
161 cout<<"DEBUG_NDataBlock::Clone("<<this<<","<<&a<<") a.(mSz="
162 <<a.mSz<<" mSRef="<<a.mSRef<<" IsTemp="<<a.IsTemp()
163 <<"), mSz="<<mSz<<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp<<endl;
164 #endif
165if(!a.mSRef) {mSz=0; mSRef=NULL;} // cas ou "a" est cree par defaut
166else if(a.IsTemp()) Share(a);
167else {Alloc(a.mSz); memcpy(Data(),a.Data(),mSz*sizeof(T));}
168}
169
170template <class T>
171void NDataBlock<T>::Share(const NDataBlock<T>& a)
172// Partage des donnees avec "a"
173{
174#ifdef DEBUG_NDATABLOCK
175cout<<"DEBUG_NDataBlock::Share("<<this<<","<<&a<<")";
176if(&a!=NULL) cout<<" a.(mSz="<<a.mSz<<" mSRef="<<a.mSRef
177 <<" IsTemp="<<a.IsTemp()<<")";
178cout<<", mSz="<<mSz<<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp<<endl;
179#endif
180
181if(&a==NULL) throw(NullPtrError("NDataBlock::Share &a==NULL\n"));
182// on ne peut partager si "a" pas alloue
183if(!a.mSRef) throw(NullPtrError("NDataBlock::Share not allocated a\n"));
184if(mSRef) Delete();
185mSz = a.mSz; mSRef = a.mSRef; mSRef->nref++;
186
187#ifdef DEBUG_NDATABLOCK
188cout<<"...DEBUG_NDataBlock::Share mSz="<<mSz<<" mSRef="<<mSRef
189 <<" mSRef->nref="<<mSRef->nref<<" mSRef->data="<< mSRef->data
190 <<" mSRef->bridge="<<mSRef->bridge<<" IsTemp="<<mIsTemp<<endl;
191#endif
192}
193
194template <class T>
195void NDataBlock<T>::Delete(void)
196// Pour detruire les pointeurs en tenant compte des references
197{
198#ifdef DEBUG_NDATABLOCK
199cout<<"DEBUG_NDataBlock::Delete("<<this<<") mSz="<<mSz
200 <<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp;
201if(mSRef)
202 cout<<" mSRef->nref="<<mSRef->nref<<" mSRef->data="
203 <<mSRef->data<<" mSRef->bridge="<<mSRef->bridge;
204cout<<endl;
205#endif
206
207if(mSRef==NULL) return; // cas du createur par defaut
208mSRef->nref--;
209if(mSRef->nref != 0) {
210
211#ifdef DEBUG_NDATABLOCK
212cout<<"...DEBUG_NDataBlock::Delete() pas de desallocation il reste nref="
213 <<mSRef->nref<<endl;
214#endif
215
216 return;
217}
218
219#ifdef DEBUG_NDATABLOCK
220if(!mSRef->bridge) NallocData--; NallocSRef--;
221cout<<"...DEBUG_NDataBlock::Delete() desallocation complete il reste nref="
222 <<mSRef->nref<<" Total("<<NallocData<<","<<NallocSRef<<")"<<endl;
223#endif
224
225// Si il y a un Bridge les donnees ne n'appartiennent pas, on detruit le Bridge
226if(mSRef->bridge) delete mSRef->bridge;
227// sinon, les donnees ont ete allouees par nos soins, on libere l'espace memoire
228else delete [] mSRef->data;
229mSRef->bridge=NULL; mSRef->data=NULL;
230delete mSRef; mSRef=NULL;
231}
232
233template <class T>
234void NDataBlock<T>::Reset(T v)
235{
236if(mSRef==NULL) return;
237if(mSRef->data==NULL) return;
238if(mSz==0) return;
239T *p=Begin(), *pe=End();
240while(p<pe) *p++ = v;
241}
242
243template <class T>
244void NDataBlock<T>::ReSize(size_t n)
245// Re-dimension, dans ce cas re-allocation de la place
246{
247Alloc(n);
248}
249
250template <class T>
251void NDataBlock<T>::FillFrom(size_t n,T* data)
252// Remplissage par un tableau de donnees
253// - Si classe vide : creation de l'espace memoire
254// - Si classe connectee : on ecrit selon la longueur
255{
256if(data==NULL) throw(NullPtrError("NDataBlock::FillFrom data==NULL\n"));
257if(n==0) throw(ParmError("NDataBlock::FillFrom n<=0\n"));
258if(mSRef==NULL) Alloc(n); // cas du createur par default
259if(mSz<n) n= mSz;
260memcpy(Data(),data,n*sizeof(T));
261}
262
263//**** Impression
264
265template <class T>
266void NDataBlock<T>::Print(ostream& os,size_t i1,size_t n) const
267// Impression de n elements a partir de i1
268{
269size_t nr = 0;
270T* p = NULL; Bridge* br = NULL;
271if(mSRef) {nr = mSRef->nref; p = mSRef->data; br = mSRef->bridge;}
272os<<"NDataBlock::Print("<<this<<",Sz="<<mSz<<",IsTemp="<<mIsTemp<<")\n"
273 <<" mSRef="<<mSRef<<"(nref="<<nr<<",data="<<p
274 <<",bridge="<<br<<")"<<endl;
275if(i1>=mSz || n<=0 || !p) return;
276size_t i2 = i1+n; if(i2>mSz) i2=mSz;
277size_t im = 1; bool enl;
278while(i1<i2) {
279 enl = false;
280 os<<" "<<(*this)(i1); i1++;
281 if(im==8) {os<<"\n"; im=1; enl=true;} else im++;
282}
283if(!enl) os<<endl;
284}
285
286//**** Surcharge de = : NDataBlock=NDataBlock; NDataBlock=<T> b;
287
288template <class T>
289NDataBlock<T>& NDataBlock<T>::operator = (const NDataBlock<T>& a)
290// surcharge avec partage des donnees
291// Ecriture: NDataBlock a; a = b;
292// NDataBlock a(10); a = b; (a est re-affecte)
293{
294#ifdef DEBUG_NDATABLOCK
295cout<<"DEBUG_NDataBlock::operator=("<<this<<","<<&a<<") a.(mSz="
296 <<a.mSz<<" mSRef="<<a.mSRef<<" IsTemp="<<a.IsTemp()
297 <<"), mSz="<<mSz<<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp<<endl;
298#endif
299
300if(this == &a) return *this;
301if(a.mSz!=mSz)
302 throw(SzMismatchError("NDataBlock::operator=A size mismatch/null\n"));
303Share(a);
304return *this;
305}
306
307template <class T>
308NDataBlock<T>& NDataBlock<T>::operator = (T v)
309// surcharge avec copie des donnees (pas de partage)
310// "this" est sur-ecrit, attention au partage de reference!
311// NDataBlock a; a = v; ou bien NDataBlock a(10); a = v;
312{
313#ifdef DEBUG_NDATABLOCK
314cout<<"DEBUG_NDataBlock::operator=("<<this<<","<<v<<")"
315 <<" mSz="<<mSz<<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp<<endl;
316#endif
317
318if(mSz==0) throw(SzMismatchError("NDataBlock::operator=v null size\n"));
319T *p=Begin(), *pe=End();
320while (p<pe) *p++ = v;
321return *this;
322}
323
324template <class T>
325T NDataBlock<T>::Sum(size_t i1,size_t n) const
326// Somme des elements de i1 a i1+n-1
327{
328if(i1>=mSz) return 0;
329if(n>mSz) n = mSz; if(n==0) n = mSz-i1;
330T const *p=Begin()+i1, *pe=p+n;
331T val = 0;
332while (p<pe) val += *p++;
333return val;
334}
335
336template <class T>
337T NDataBlock<T>::Product(size_t i1,size_t n) const
338// Produit des elements de i1 a i1+n-1
339{
340if(i1>=mSz) return 0;
341if(n>mSz) n = mSz; if(n==0) n = mSz-i1;
342T const *p=Begin()+i1, *pe=p+n;
343T val = 0;
344while (p<pe) val *= *p++;
345return val;
346}
347
348//**** Surcharge de +=,-=,*=,/= (INPLACE): NDataBlock += <T> b;
349
350template <class T>
351NDataBlock<T>& NDataBlock<T>::operator += (T b)
352{
353if(mSz==0) throw(SzMismatchError("NDataBlock::operator+=v null size\n"));
354T *p=Begin(), *pe=End();
355while (p<pe) *p++ += b;
356return *this;
357}
358
359template <class T>
360NDataBlock<T>& NDataBlock<T>::operator -= (T b)
361{
362if(mSz==0) throw(SzMismatchError("NDataBlock::operator-=v null size\n"));
363T *p=Begin(), *pe=End();
364while (p<pe) *p++ -= b;
365return *this;
366}
367
368template <class T>
369NDataBlock<T>& NDataBlock<T>::operator *= (T b)
370{
371if(mSz==0) throw(SzMismatchError("NDataBlock::operator*=v null size\n"));
372T *p=Begin(), *pe=End();
373while (p<pe) *p++ *= b;
374return *this;
375}
376
377template <class T>
378NDataBlock<T>& NDataBlock<T>::operator /= (T b)
379{
380if(b==(T) 0) throw(ParmError("NDataBlock::operator/=v divide by zero\n"));
381if(mSz==0) throw(SzMismatchError("NDataBlock::operator/=v null size\n"));
382T *p=Begin(), *pe=End();
383while (p<pe) *p++ /= b;
384return *this;
385}
386
387//**** Surcharge de +=,-=,*=,/= (INPLACE): NDataBlock += NDataBlock;
388
389template <class T>
390NDataBlock<T>& NDataBlock<T>::operator += (const NDataBlock<T>& a)
391{
392if(mSz==0 || mSz!=a.mSz)
393 throw(SzMismatchError("NDataBlock::operator+=A size mismatch/null"));
394T *p=Begin(), *pe=End();
395T const * pa=a.Begin();
396while (p<pe) *p++ += *pa++; // ca marche meme si *this=a
397return *this;
398}
399
400template <class T>
401NDataBlock<T>& NDataBlock<T>::operator -= (const NDataBlock<T>& a)
402{
403if(mSz==0 || mSz!=a.mSz)
404 throw(SzMismatchError("NDataBlock::operator-=A size mismatch/null"));
405T *p=Begin(), *pe=End();
406T const *pa=a.Begin();
407while (p<pe) *p++ -= *pa++; // ca marche meme si *this=a
408return *this;
409}
410
411template <class T>
412NDataBlock<T>& NDataBlock<T>::operator *= (const NDataBlock<T>& a)
413{
414if(mSz==0 || mSz!=a.mSz)
415 throw(SzMismatchError("NDataBlock::operator*=A size mismatch/null"));
416T *p=Begin(), *pe=End();
417T const *pa=a.Begin();
418while (p<pe) *p++ *= *pa++; // ca marche meme si *this=a
419return *this;
420}
421
422template <class T>
423NDataBlock<T>& NDataBlock<T>::operator /= (const NDataBlock<T>& a)
424{
425if(mSz==0 || mSz!=a.mSz)
426 throw(SzMismatchError("NDataBlock::operator/=A size mismatch/null"));
427T *p=Begin(), *pe=End();
428T const *pa=a.Begin();
429while (p<pe) *p++ /= *pa++;
430return *this;
431}
432
433//**** Surcharge de +,-,*,/ : NDataBlock = NDataBlock+<T>b; NDataBlock = <T>b+NDataBlock;
434// ATTENTION: re-affectation imposee
435
436template <class T>
437NDataBlock<T> NDataBlock<T>::Add(T b) const
438// Pour A+b
439{
440NDataBlock<T> result(*this,false); result.SetTemp(true);
441result += b;
442return result;
443}
444
445template <class T>
446NDataBlock<T> NDataBlock<T>::Sub(T b) const
447// Pour A-b
448{
449NDataBlock<T> result(*this,false); result.SetTemp(true);
450return result -= b;
451}
452
453template <class T>
454NDataBlock<T> NDataBlock<T>::SubInv(T b) const
455// Pour b-A
456{
457NDataBlock<T> result(*this,false); result.SetTemp(true);
458T *p=result.Begin(), *pe=result.End();
459T const *pa=this->Begin();
460while(p<pe) {*p++ = b - *pa++;}
461return result;
462}
463
464template <class T>
465NDataBlock<T> NDataBlock<T>::Mul(T b) const
466// Pour A*b
467{
468NDataBlock<T> result(*this,false); result.SetTemp(true);
469return result *= b;
470}
471
472template <class T>
473NDataBlock<T> NDataBlock<T>::Div(T b) const
474// Pour A/b
475{
476NDataBlock<T> result(*this,false); result.SetTemp(true);
477return result /= b;
478}
479
480template <class T>
481NDataBlock<T> NDataBlock<T>::DivInv(T b) const
482// Pour b/A
483{
484NDataBlock<T> result(*this,false); result.SetTemp(true);
485T *p=result.Begin(), *pe=result.End();
486T const *pa = this->Begin();
487while(p<pe) {*p++ = b / *pa++;}
488return result;
489}
490
491//**** Surcharge de +,-,*,/ : NDataBlock = NDataBlock+NDataBlock;
492
493template <class T>
494NDataBlock<T> NDataBlock<T>::Add(const NDataBlock<T>& b) const
495// Pour A+B
496{
497if(this->mSz!=b.mSz)
498 throw(SzMismatchError("NDataBlock operator C=A+B size mismatch/null\n"));
499NDataBlock<T> result; result.SetTemp(true);
500if(b.IsTemp()) {
501 result.Share(b);
502 result += *this;
503} else {
504 result.Clone(*this);
505 result += b;
506}
507return result;
508}
509
510template <class T>
511NDataBlock<T> NDataBlock<T>::Mul(const NDataBlock<T>& b) const
512// Pour A*B
513{
514if(this->mSz!=b.mSz)
515 throw(SzMismatchError("NDataBlock operator C=A*B size mismatch/null\n"));
516NDataBlock<T> result; result.SetTemp(true);
517if(b.IsTemp()) {
518 result.Share(b);
519 result *= *this;
520} else {
521 result.Clone(*this);
522 result *= b;
523}
524return result;
525}
526
527template <class T>
528NDataBlock<T> NDataBlock<T>::Sub(const NDataBlock<T>& b) const
529// Pour A-B
530{
531if(this->mSz!=b.mSz)
532 throw(SzMismatchError("NDataBlock operator C=A-B size mismatch/null\n"));
533NDataBlock<T> result; result.SetTemp(true);
534if(b.IsTemp()) {
535 result.Share(b);
536 T *p=result.Begin(), *pe=result.End();
537 T const *pa=this->Begin();
538 while(p<pe) {*p = *pa++ - *p; p++;}
539} else {
540 result.Clone(*this);
541 result -= b;
542}
543return result;
544}
545
546template <class T>
547NDataBlock<T> NDataBlock<T>::Div(const NDataBlock<T>& b) const
548// Pour A/B
549{
550if(this->mSz!=b.mSz)
551 throw(SzMismatchError("NDataBlock operator C=A/B size mismatch/null\n"));
552NDataBlock<T> result; result.SetTemp(true);
553if(b.IsTemp()) {
554 result.Share(b);
555 T *p=result.Begin(), *pe=result.End();
556 T const *pa=this->Begin();
557 while(p<pe) {*p = *pa++ / *p; p++;}
558} else {
559 result.Clone(*this);
560 result /= b;
561}
562return result;
563}
564
565
566#ifdef __CXX_PRAGMA_TEMPLATES__
567#pragma define_template NDataBlock<uint_1>
568#pragma define_template NDataBlock<uint_2>
569#pragma define_template NDataBlock<int_2>
570#pragma define_template NDataBlock<int_4>
571#pragma define_template NDataBlock<int_8>
572#pragma define_template NDataBlock<uint_2>
573#pragma define_template NDataBlock<uint_4>
574#pragma define_template NDataBlock<uint_8>
575#pragma define_template NDataBlock<r_4>
576#pragma define_template NDataBlock<r_8>
577#pragma define_template NDataBlock< complex<float> >
578#pragma define_template NDataBlock< complex<double> >
579#endif
580
581#ifdef __GNU_TEMPLATES__
582template class NDataBlock<uint_1>;
583template class NDataBlock<uint_2>;
584template class NDataBlock<int_2>;
585template class NDataBlock<int_4>;
586template class NDataBlock<int_8>;
587template class NDataBlock<uint_2>;
588template class NDataBlock<uint_4>;
589template class NDataBlock<uint_8>;
590template class NDataBlock<r_4>;
591template class NDataBlock<r_8>;
592template class NDataBlock< complex<float> >;
593template class NDataBlock< complex<double> >;
594#endif
595
596#if defined(__ANSI_TEMPLATES__)
597template class NDataBlock<uint_1>;
598template class NDataBlock<uint_2>;
599template class NDataBlock<int_2>;
600template class NDataBlock<int_4>;
601template class NDataBlock<int_8>;
602template class NDataBlock<uint_2>;
603template class NDataBlock<uint_4>;
604template class NDataBlock<uint_8>;
605template class NDataBlock<r_4>;
606template class NDataBlock<r_8>;
607template class NDataBlock< complex<float> >;
608template class NDataBlock< complex<double> >;
609#endif
Note: See TracBrowser for help on using the repository browser.