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

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

Ajout de l'argument bool zero ds NDataBlock<T>::Alloc()
Fonction pour construire un message d'exception avec num de ligne et
nom de fichier ds pexceptions.h .cc

Reza 10/3/2000

File size: 22.8 KB
Line 
1// Gestion de block de donnees avec partage de references
2// malheureusement tres mal concu... 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#include "objfio.h"
12
13// define DEBUG_NDATABLOCK
14
15#ifdef DEBUG_NDATABLOCK
16 static size_t NallocData = 0;
17 static size_t NallocSRef = 0;
18#endif
19
20////////////////////////////////////////////////////////////////
21//************ Createur, Destructeur
22
23template <class T>
24NDataBlock<T>::NDataBlock(size_t n)
25// Createur d'une structure de "n" donnees
26: mSz(0), mSRef(NULL), mIsTemp(false)
27{
28#ifdef DEBUG_NDATABLOCK
29cout<<"?_NDataBlock::NDataBlock("<<this<<",n="<<n<<")"<<endl;
30#endif
31
32Alloc(n, NULL, NULL, true); // allocation et mise a zero
33}
34
35template <class T>
36NDataBlock<T>::NDataBlock(size_t n, T* data, Bridge* br)
37// Createur d'une structure de "n" donnees, avec donnees preallouees.
38// Attention createur TRES DANGEREUX (Voir explications dans Alloc()).
39: mSz(0), mSRef(NULL), mIsTemp(false)
40{
41#ifdef DEBUG_NDATABLOCK
42cout<<"?_NDataBlock::NDataBlock("<<this
43 <<",data="<<data<<",br="<<br<<")"<<endl;
44#endif
45
46Alloc(n,data,br);
47}
48
49template <class T>
50NDataBlock<T>::NDataBlock()
51// Createur par default
52: mSz(0), mSRef(NULL), mIsTemp(false)
53{
54#ifdef DEBUG_NDATABLOCK
55cout<<"?_NDataBlock::NDataBlock("<<this<<") default"<<endl;
56#endif
57}
58
59template <class T>
60NDataBlock<T>::NDataBlock(const NDataBlock<T>& a)
61// Createur par copie: partage les donnees si "a" temporaire, clone sinon.
62: mSz(0), mSRef(NULL), mIsTemp(false)
63{
64#ifdef DEBUG_NDATABLOCK
65cout<<"?_NDataBlock::NDataBlock("<<this<<",&a="<<&a<<")"<<endl;
66#endif
67
68CloneOrShare(a);
69}
70
71template <class T>
72NDataBlock<T>::NDataBlock(const NDataBlock<T>& a,bool share)
73// Createur avec choix de partager ou non selon "share"
74: mSz(0), mSRef(NULL), mIsTemp(false)
75{
76#ifdef DEBUG_NDATABLOCK
77cout<<"?_NDataBlock::NDataBlock("<<this<<",&a="<<&a<<",sh=<<"<<share<<")"<<endl;
78#endif
79
80if(share) Share(a); else Clone(a);
81}
82
83template <class T>
84NDataBlock<T>::~NDataBlock()
85// Destructeur
86{
87#ifdef DEBUG_NDATABLOCK
88cout<<"?_NDataBlock::~NDataBlock("<<this<<")"<<endl;
89#endif
90
91Delete();
92}
93
94////////////////////////////////////////////////////////////////
95//************ Gestion de donnees
96
97template <class T>
98void NDataBlock<T>::Alloc(size_t n,T* data,Bridge* br,bool zero)
99// Allocation d'un NOUVEL espace de stoquage de "n" donnees
100// Si data==NULL : allocation de l'espace memoire
101// si zero == true , l'espace est remplis de zeros
102// data!=NULL : partage des donnees avec l'adresse data
103// Si br==NULL : les donnees nous appartiennent
104// br!=NULL : les donnees ne nous appartiennent pas (ex: Blitz)
105//
106// Exemple: on veut connecter a un tableau de T*
107// > float *x = new float[5]; ... remplissage de x[] ...;
108// 1- On veut que NDataBlock NE DESALLOUE PAS le tableau "x[]"
109// a- Premiere solution
110// > NDataBlock A(5,x,new Bridge);
111// ......
112// > delete [] x;
113// - Il faut deleter x[] explicitement.
114// - Le destructeur de "A" ne detruit pas x[].
115// ATTENTION: Une fois x[] detruit, "A" ne peut
116// plus acceder les donnees!
117// - Bridge est detruit par le destructeur de "A"
118// b- Autre solution:
119// > NDataBlock A(5); A.FillFrom(5,x);
120// > delete [] x;
121// ......
122// - Il faut deleter x[] explicitement.
123// - "A" possede une copie en local de x[].
124// - Le destructeur de "A" ne detruit pas x[] mais la copie locale.
125// 2- On veut que NDataBlock desalloue le tableau
126// > NDataBlock A(5,x);
127// - Ne Pas Faire "delete [] x;"
128// - "A" partage les donnees avec x[].
129// - Le destructeur de "A" detruit x[].
130//
131// --- REMARQUE SUR LE DANGER DE CERTAINES SITUATIONS (CMV):
132// 1-/ x = new float[n1]; NDataBlock A(n2,x);
133// 1er danger: si n2>n1 depassement de tableaux (core dump)
134// 2sd danger: celui qui alloue x[] ne doit pas faire le "delete"
135// en desaccord avec toutes les regles de bonne conduite.
136// 2-/ float x[5]={1,2,3,4,5}; {NDataBlock A(n2,&x[0]);} cout<<x[2];
137// Ici, a la sortie du bloc {}, le destructeur de "A" va detruire
138// l'adresse de &x[0]: je n'ose imaginer que ca se fasse sans probleme
139// et de toute facon, cout<<x[2]; va surement faire des etincelles.
140// 3-/ x = new float[n1]; NDataBlock A(n2,x,new Bridge);
141// 1er danger: si n2>n1 depassement de tableaux (core dump)
142// 2sd danger: si la methode bridgee (blitz?) detruit x[]
143// "A" n'a plus de donnees connectees!
144// --- CONCLUSION
145// Cette classe est franchement merdique.
146// - On peut accepter la prise de risque liee a NDataBlock(n2,x,new Bridge);
147// car je ne vois pas comment on pourrait faire autrement pour connecter
148// un tableau de type blitz par exemple.
149// - Par contre le createur NDataBlock(n2,x); doit etre interdit
150// dans sa forme actelle car trop dangereux et il me semble inutile.
151// - Dans cette nouvelle optique:
152// NDataBlock(n2,x,new Bridge) et NDataBlock(n2,x) disparaissent
153// On remplace par NDataBlock(n2,x) {Alloc(n2,x,new Bridge);}
154// qui force le Bridge dans tout les cas puisque NDataBlock
155// ne possede pas les donnees.
156// Mais puis-je encore le faire vu que NDataBlock est a la base
157// de TVector,TMatrix et qu'il faut donc reprendre tout le code DPC
158// - Quoiqu'il arrive Alloc est une methode privee et peut donc rester
159// sous sa forme actuelle.
160//
161{
162#ifdef DEBUG_NDATABLOCK
163cout<<"?_NDataBlock::Alloc("<<this<<","
164 <<n<<","<<data<<","<<br<<") mSz="<<mSz
165 <<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp<<endl;
166#endif
167
168if(br && !data)
169 throw(NullPtrError("NDataBlock::Alloc br!=NULL && data==NULL\n"));
170if(n==0) throw(SzMismatchError("NDataBlock::Alloc n==0\n"));
171if(mSRef) Delete();
172mSz = n;
173mSRef = new NDREF;
174mSRef->nref = 1;
175if(data) mSRef->data = data;
176else {mSRef->data = new T[n]; if (zero) memset(mSRef->data,0,n*sizeof(T));}
177mSRef->bridge = br;
178
179#ifdef DEBUG_NDATABLOCK
180// Meme dans le cas data!=0 et br==0 (connexion d'un tableau
181// avec destruction geree par ~NDataBlock (cas 2-) on compte
182// comme si on avait fait une allocation du tableau (ce qui a ete
183// fait au niveau du dessus!).
184if(!br) NallocData++; NallocSRef++;
185cout<<"...?_NDataBlock::Alloc mSz="<<mSz<<" mSRef="<<mSRef
186 <<" mSRef->nref="<<mSRef->nref<<" mSRef->data="<< mSRef->data
187 <<" mSRef->bridge="<<mSRef->bridge<<" IsTemp="<<mIsTemp
188 <<" Total("<<NallocData<<","<<NallocSRef<<")"<<endl;
189#endif
190}
191
192template <class T>
193void NDataBlock<T>::Clone(const NDataBlock<T>& a)
194// Clone: copie de donnees a partir de "a"
195{
196#ifdef DEBUG_NDATABLOCK
197cout<<"?_NDataBlock::Clone("<<this<<","<<&a<<") a.(mSz="
198 <<a.mSz<<" mSRef="<<a.mSRef<<" IsTemp="<<a.IsTemp()
199 <<"), mSz="<<mSz<<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp<<endl;
200#endif
201
202if(&a==NULL) throw(NullPtrError("NDataBlock::Clone &a==NULL\n"));
203if(!a.mSRef || a.mSz==0) throw(SzMismatchError("NDataBlock::Clone a.mSz==0\n"));
204Alloc(a.mSz, NULL, NULL, false); // pas de mise a zero
205memcpy(Data(),a.Data(),mSz*sizeof(T));
206}
207
208template <class T>
209void NDataBlock<T>::CloneOrShare(const NDataBlock<T>& a)
210// CloneOrShare: Share si "a" temporaire, Clone sinon.
211{
212#ifdef DEBUG_NDATABLOCK
213cout<<"?_NDataBlock::CloneOrShare("<<this<<","<<&a<<")"<<endl;
214#endif
215
216if(&a==NULL) throw(NullPtrError("NDataBlock::CloneOrShare &a==NULL\n"));
217if(a.IsTemp()) Share(a); else Clone(a);
218}
219
220template <class T>
221void NDataBlock<T>::Share(const NDataBlock<T>& a)
222// Share: Partage les donnees avec "a"
223{
224#ifdef DEBUG_NDATABLOCK
225cout<<"?_NDataBlock::Share("<<this<<","<<&a<<")";
226if(&a!=NULL) cout<<" a.(mSz="<<a.mSz<<" mSRef="<<a.mSRef
227 <<" IsTemp="<<a.IsTemp()<<")";
228cout<<", mSz="<<mSz<<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp<<endl;
229#endif
230
231if(&a==NULL) throw(NullPtrError("NDataBlock::Share &a==NULL\n"));
232if(!a.mSRef || a.mSz==0) throw(NullPtrError("NDataBlock::Share a.mSz=0\n"));
233if(mSRef) Delete();
234mSz = a.mSz; mSRef = a.mSRef; mSRef->nref++;
235
236#ifdef DEBUG_NDATABLOCK
237cout<<"...?_NDataBlock::Share mSz="<<mSz<<" mSRef="<<mSRef
238 <<" mSRef->nref="<<mSRef->nref<<" mSRef->data="<< mSRef->data
239 <<" mSRef->bridge="<<mSRef->bridge<<" IsTemp="<<mIsTemp<<endl;
240#endif
241}
242
243template <class T>
244void NDataBlock<T>::Delete(void)
245// Pour detruire les pointeurs en tenant compte des references
246{
247#ifdef DEBUG_NDATABLOCK
248cout<<"?_NDataBlock::Delete("<<this<<") mSz="<<mSz
249 <<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp;
250if(mSRef)
251 cout<<" mSRef->nref="<<mSRef->nref<<" mSRef->data="
252 <<mSRef->data<<" mSRef->bridge="<<mSRef->bridge;
253cout<<endl;
254#endif
255
256if(mSRef==NULL) return;
257mSRef->nref--;
258if(mSRef->nref != 0) {
259
260#ifdef DEBUG_NDATABLOCK
261 cout<<"...?_NDataBlock::Delete() pas de desallocation il reste nref="
262 <<mSRef->nref<<" Total("<<NallocData<<","<<NallocSRef<<")"<<endl;
263#endif
264
265 mSz = 0; mSRef=NULL;
266 return;
267}
268
269#ifdef DEBUG_NDATABLOCK
270if(!mSRef->bridge) NallocData--; NallocSRef--;
271cout<<"...?_NDataBlock::Delete() desallocation complete il reste nref="
272 <<mSRef->nref<<" Total("<<NallocData<<","<<NallocSRef<<")"<<endl;
273#endif
274
275// Si il y a un Bridge les donnees ne n'appartiennent pas, on detruit le Bridge
276// sinon, les donnees ont ete allouees par nos soins, on libere l'espace
277if(mSRef->bridge) delete mSRef->bridge; else delete [] mSRef->data;
278mSRef->bridge=NULL; mSRef->data=NULL;
279delete mSRef; mSRef=NULL; mSz = 0;
280}
281
282template <class T>
283void NDataBlock<T>::FillFrom(size_t n,T* data)
284// Remplissage par un tableau de donnees
285// - Si classe vide : creation de l'espace memoire
286// - Si classe connectee : on ecrit selon la longueur minimale
287// (cad this->mSz ou "n")
288{
289if(data==NULL) throw(NullPtrError("NDataBlock::FillFrom data==NULL\n"));
290if(n==0) throw(ParmError("NDataBlock::FillFrom n<=0\n"));
291if(mSRef==NULL) Alloc(n, NULL, NULL, false); // Pas de mise a zero
292if(mSz<n) n = mSz;
293memcpy(Data(),data,n*sizeof(T));
294}
295
296template <class T>
297void NDataBlock<T>::Realloc(size_t nnew,bool force)
298// Re-allocation de "nnew" place memoire pour les donnees
299// avec conservation des "nold" donnees precedentes si possible.
300// "force" gere la re-allocation de la place memoire pour les donnees.
301// Divers cas se presentent:
302// a-/ *** nnew>nold force=quelconque ***
303// place re-allouee, donnees [0,nold[ copiees, surplus [nold,new[ mis a zero
304// b-/ *** nnew<=nold force=true ***
305// place re-allouee, donnees [0,nnew[ copiees, pas de surplus
306// c-/ *** nnew<=nold force=false ***
307// place non re-allouee, seule la valeur de la taille est diminuee
308// - On tient compte du partage des donnees dans tous les cas.
309// - Si il n'y a pas de donnees connectees a la classe, on re-alloue
310// dans tous les cas
311{
312if(nnew==0) throw(ParmError("NDataBlock::Realloc n<=0\n"));
313
314// Cas sans re-allocation memoire
315if(mSRef && nnew<=mSz && ! force) { mSz=nnew; return;}
316
317// Cas avec re-allocation memoire
318size_t ncop;
319if(!mSRef || mSz==0) ncop=0; else if(mSz<nnew) ncop=mSz; else ncop=nnew;
320T* dataloc = new T[nnew];
321if(ncop>0) memcpy(dataloc,mSRef->data,ncop*sizeof(T));
322if(nnew>ncop) memset(dataloc+ncop,0,(nnew-ncop)*sizeof(T));
323Alloc(nnew,dataloc,NULL); //Alloc gere partage de reference et bridge
324}
325
326////////////////////////////////////////////////////////////////
327//**** Impression
328
329template <class T>
330void NDataBlock<T>::Print(ostream& os,size_t i1,size_t n) const
331// Impression de n elements a partir de i1
332{
333size_t nr = 0;
334T* p = NULL; Bridge* br = NULL;
335if(mSRef) {nr = mSRef->nref; p = mSRef->data; br = mSRef->bridge;}
336os<<"NDataBlock::Print("<<this<<",Sz="<<mSz<<",IsTemp="<<mIsTemp<<")\n"
337 <<" mSRef="<<mSRef<<"(nref="<<nr<<",data="<<p
338 <<",bridge="<<br<<")"<<endl;
339if(i1>=mSz || n<=0 || !p) return;
340size_t i2 = i1+n; if(i2>mSz) i2=mSz;
341size_t im = 1; bool enl=false;
342while(i1<i2) {
343 enl = false;
344 os<<" "<<(*this)(i1); i1++;
345 if(im==8) {os<<"\n"; im=1; enl=true;} else im++;
346}
347if(!enl) os<<endl;
348}
349
350////////////////////////////////////////////////////////////////
351
352template <class T>
353T NDataBlock<T>::Sum(size_t i1,size_t n) const
354// Somme des elements de i1 a i1+n-1
355{
356if(i1>=mSz) return 0;
357if(n>mSz) n = mSz; if(n==0) n = mSz-i1;
358T const *p=Begin()+i1, *pe=p+n;
359T val = 0;
360while (p<pe) val += *p++;
361return val;
362}
363
364template <class T>
365T NDataBlock<T>::Product(size_t i1,size_t n) const
366// Produit des elements de i1 a i1+n-1
367{
368if(i1>=mSz) return 0;
369if(n>mSz) n = mSz; if(n==0) n = mSz-i1;
370T const *p=Begin()+i1, *pe=p+n;
371T val = 0;
372while (p<pe) val *= *p++;
373return val;
374}
375
376////////////////////////////////////////////////////////////////
377//**** Surcharge de = : NDataBlock=NDataBlock; NDataBlock=<T> b;
378
379template <class T>
380NDataBlock<T>& NDataBlock<T>::operator = (const NDataBlock<T>& a)
381// Affectation: partage des donnees si "a" temporaire, clone sinon.
382{
383#ifdef DEBUG_NDATABLOCK
384cout<<"?_NDataBlock::operator=("<<this<<","<<&a<<") a.(mSz="
385 <<a.mSz<<" mSRef="<<a.mSRef<<" IsTemp="<<a.IsTemp()
386 <<"), mSz="<<mSz<<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp<<endl;
387#endif
388
389if(this == &a) return *this;
390if(a.mSz==0)
391 throw(SzMismatchError("NDataBlock::operator=A null size\n"));
392CloneOrShare(a);
393return *this;
394}
395
396template <class T>
397NDataBlock<T>& NDataBlock<T>::operator = (T v)
398// Affectation de tous les elements a une constante "v"
399{
400#ifdef DEBUG_NDATABLOCK
401cout<<"?_NDataBlock::operator=("<<this<<","<<v<<")"
402 <<" mSz="<<mSz<<" mSRef="<<mSRef<<" IsTemp="<<mIsTemp<<endl;
403#endif
404
405if(mSz==0) throw(SzMismatchError("NDataBlock::operator=v null size\n"));
406T *p=Begin(), *pe=End();
407while (p<pe) *p++ = v;
408return *this;
409}
410
411////////////////////////////////////////////////////////////////
412//**** Surcharge de +=,-=,*=,/= (INPLACE): NDataBlock += <T> b;
413
414template <class T>
415NDataBlock<T>& NDataBlock<T>::operator += (T b)
416{
417if(mSz==0) throw(SzMismatchError("NDataBlock::operator+=v null size\n"));
418T *p=Begin(), *pe=End();
419while (p<pe) *p++ += b;
420return *this;
421}
422
423template <class T>
424NDataBlock<T>& NDataBlock<T>::operator -= (T b)
425{
426if(mSz==0) throw(SzMismatchError("NDataBlock::operator-=v null size\n"));
427T *p=Begin(), *pe=End();
428while (p<pe) *p++ -= b;
429return *this;
430}
431
432template <class T>
433NDataBlock<T>& NDataBlock<T>::operator *= (T b)
434{
435if(mSz==0) throw(SzMismatchError("NDataBlock::operator*=v null size\n"));
436T *p=Begin(), *pe=End();
437while (p<pe) *p++ *= b;
438return *this;
439}
440
441template <class T>
442NDataBlock<T>& NDataBlock<T>::operator /= (T b)
443{
444if(b==(T) 0) throw(ParmError("NDataBlock::operator/=v divide by zero\n"));
445if(mSz==0) throw(SzMismatchError("NDataBlock::operator/=v null size\n"));
446T *p=Begin(), *pe=End();
447while (p<pe) *p++ /= b;
448return *this;
449}
450
451////////////////////////////////////////////////////////////////
452//**** Surcharge de +=,-=,*=,/= (INPLACE): NDataBlock += NDataBlock;
453
454template <class T>
455NDataBlock<T>& NDataBlock<T>::operator += (const NDataBlock<T>& a)
456{
457if(mSz==0 || mSz!=a.mSz)
458 throw(SzMismatchError("NDataBlock::operator+=A size mismatch/null"));
459T *p=Begin(), *pe=End();
460T const * pa=a.Begin();
461while (p<pe) *p++ += *pa++;
462return *this;
463}
464
465template <class T>
466NDataBlock<T>& NDataBlock<T>::operator -= (const NDataBlock<T>& a)
467{
468if(mSz==0 || mSz!=a.mSz)
469 throw(SzMismatchError("NDataBlock::operator-=A size mismatch/null"));
470T *p=Begin(), *pe=End();
471T const *pa=a.Begin();
472while (p<pe) *p++ -= *pa++;
473return *this;
474}
475
476template <class T>
477NDataBlock<T>& NDataBlock<T>::operator *= (const NDataBlock<T>& a)
478{
479if(mSz==0 || mSz!=a.mSz)
480 throw(SzMismatchError("NDataBlock::operator*=A size mismatch/null"));
481T *p=Begin(), *pe=End();
482T const *pa=a.Begin();
483while (p<pe) *p++ *= *pa++;
484return *this;
485}
486
487template <class T>
488NDataBlock<T>& NDataBlock<T>::operator /= (const NDataBlock<T>& a)
489// Attention, aucune protection si un element de "a" est nul.
490{
491if(mSz==0 || mSz!=a.mSz)
492 throw(SzMismatchError("NDataBlock::operator/=A size mismatch/null"));
493T *p=Begin(), *pe=End();
494T const *pa=a.Begin();
495while (p<pe) *p++ /= *pa++;
496return *this;
497}
498
499////////////////////////////////////////////////////////////////
500//**** Surcharge de +,-,*,/ : NDataBlock = NDataBlock+<T>b;
501// NDataBlock = <T>b+NDataBlock;
502
503template <class T>
504NDataBlock<T> NDataBlock<T>::Add(T b) const
505// Pour A+b
506{
507NDataBlock<T> result(*this); result.SetTemp(true);
508result += b;
509return result;
510}
511
512template <class T>
513NDataBlock<T> NDataBlock<T>::Sub(T b) const
514// Pour A-b
515{
516NDataBlock<T> result(*this); result.SetTemp(true);
517return result -= b;
518}
519
520template <class T>
521NDataBlock<T> NDataBlock<T>::SubInv(T b) const
522// Pour b-A
523{
524NDataBlock<T> result(*this); result.SetTemp(true);
525T *p=result.Begin(), *pe=result.End();
526T const *pa=this->Begin();
527while(p<pe) {*p++ = b - *pa++;}
528return result;
529}
530
531template <class T>
532NDataBlock<T> NDataBlock<T>::Mul(T b) const
533// Pour A*b
534{
535NDataBlock<T> result(*this); result.SetTemp(true);
536return result *= b;
537}
538
539template <class T>
540NDataBlock<T> NDataBlock<T>::Div(T b) const
541// Pour A/b
542{
543NDataBlock<T> result(*this); result.SetTemp(true);
544return result /= b;
545}
546
547template <class T>
548NDataBlock<T> NDataBlock<T>::DivInv(T b) const
549// Pour b/A
550{
551NDataBlock<T> result(*this); result.SetTemp(true);
552T *p=result.Begin(), *pe=result.End();
553T const *pa = this->Begin();
554while(p<pe) {*p++ = b / *pa++;}
555return result;
556}
557
558////////////////////////////////////////////////////////////////
559//**** Surcharge de +,-,*,/ : NDataBlock = NDataBlock+NDataBlock;
560
561template <class T>
562NDataBlock<T> NDataBlock<T>::Add(const NDataBlock<T>& b) const
563// Pour A+B
564{
565if(mSz!=b.mSz)
566 throw(SzMismatchError("NDataBlock operator C=A+B size mismatch/null\n"));
567NDataBlock<T> result; result.SetTemp(true);
568if(b.IsTemp()) {result.Share(b); result += *this;}
569 else {result.CloneOrShare(*this); result += b;}
570return result;
571}
572
573template <class T>
574NDataBlock<T> NDataBlock<T>::Mul(const NDataBlock<T>& b) const
575// Pour A*B
576{
577if(mSz!=b.mSz)
578 throw(SzMismatchError("NDataBlock operator C=A*B size mismatch/null\n"));
579NDataBlock<T> result; result.SetTemp(true);
580if(b.IsTemp()) {result.Share(b); result *= *this;}
581 else {result.CloneOrShare(*this); result *= b;}
582return result;
583}
584
585template <class T>
586NDataBlock<T> NDataBlock<T>::Sub(const NDataBlock<T>& b) const
587// Pour A-B
588{
589if(mSz!=b.mSz)
590 throw(SzMismatchError("NDataBlock operator C=A-B size mismatch/null\n"));
591NDataBlock<T> result; result.SetTemp(true);
592if(b.IsTemp()) {
593 result.Share(b);
594 T *p=result.Begin(), *pe=result.End(); T const *pa=Begin();
595 while(p<pe) {*p = *pa++ - *p; p++;}
596} else {result.CloneOrShare(*this); result -= b;}
597return result;
598}
599
600template <class T>
601NDataBlock<T> NDataBlock<T>::Div(const NDataBlock<T>& b) const
602// Pour A/B
603{
604if(mSz!=b.mSz)
605 throw(SzMismatchError("NDataBlock operator C=A/B size mismatch/null\n"));
606NDataBlock<T> result; result.SetTemp(true);
607if(b.IsTemp()) {
608 result.Share(b);
609 T *p=result.Begin(), *pe=result.End(); T const *pa=Begin();
610 while(p<pe) {*p = *pa++ / *p; p++;}
611} else {result.CloneOrShare(*this); result /= b;}
612return result;
613}
614
615////////////////////////////////////////////////////////////////
616// -------------------------------------------------------------------------
617// Les objets delegues pour la gestion de persistance
618// -------------------------------------------------------------------------
619
620/*
621template <class T>
622void ObjFileIO< NDataBlock<T> >::ReadSelf(PInPersist& is)
623template <class T>
624void ObjFileIO< NDataBlock<T> >::WriteSelf(POutPersist& os)
625*/
626
627// Pour pouvoir ecrire des tableaux de complex, en attendant
628// PIn/POutPersist::Get/Put(complex<>)
629#include "piocmplx.h"
630
631template <class T>
632FIO_NDataBlock<T>::FIO_NDataBlock()
633{
634dobj=new NDataBlock<T>;
635ownobj=true;
636}
637
638template <class T>
639FIO_NDataBlock<T>::FIO_NDataBlock(string const & filename)
640{
641dobj=new NDataBlock<T>;
642ownobj=true;
643Read(filename);
644}
645
646template <class T>
647FIO_NDataBlock<T>::FIO_NDataBlock(const NDataBlock<T> & obj)
648{
649dobj = new NDataBlock<T>(obj);
650ownobj=true;
651}
652
653template <class T>
654FIO_NDataBlock<T>::FIO_NDataBlock(NDataBlock<T> * obj)
655{
656dobj = obj;
657ownobj=false;
658}
659
660template <class T>
661FIO_NDataBlock<T>::~FIO_NDataBlock()
662{
663if (ownobj && dobj) delete dobj;
664}
665
666template <class T>
667AnyDataObj* FIO_NDataBlock<T>::DataObj()
668{
669return(dobj);
670}
671
672template <class T>
673void FIO_NDataBlock<T>::SetDataObj(AnyDataObj & o)
674{
675NDataBlock<T> * po = dynamic_cast< NDataBlock<T> * >(&o);
676if (po == NULL) return;
677if (ownobj && dobj) delete dobj;
678dobj = po; ownobj = false;
679}
680
681template <class T>
682void FIO_NDataBlock<T>::ReadSelf(PInPersist& is)
683{
684// On lit les 3 premiers uint_8
685uint_8 itab[3];
686is.Get(itab, 3);
687if (dobj == NULL) dobj = new NDataBlock<T>(itab[1]);
688else if (itab[1] != dobj->Size()) dobj->ReSize(itab[1]);
689// On lit le tableau de nombres
690PIOSReadArray(is, dobj->Data(), dobj->Size());
691}
692
693
694template <class T>
695void FIO_NDataBlock<T>::WriteSelf(POutPersist& os) const
696{
697if (dobj == NULL) return; // Attention - $CHECK$ Reza 26/04/99
698// On ecrit 3 uint_8
699// 0 : Numero de version, 1 : Taille, 2 reserve a l
700uint_8 itab[3];
701itab[0] = 1;
702itab[1] = dobj->Size();
703itab[2] = 0;
704os.Put(itab, 3);
705// On ecrit le tableau de nombres
706PIOSWriteArray(os, dobj->Data(), dobj->Size());
707}
708
709///////////////////////////////////////////////////////////////
710#ifdef __CXX_PRAGMA_TEMPLATES__
711#pragma define_template NDataBlock<uint_1>
712#pragma define_template NDataBlock<uint_2>
713#pragma define_template NDataBlock<int_2>
714#pragma define_template NDataBlock<int_4>
715#pragma define_template NDataBlock<int_8>
716#pragma define_template NDataBlock<uint_4>
717#pragma define_template NDataBlock<uint_8>
718#pragma define_template NDataBlock<r_4>
719#pragma define_template NDataBlock<r_8>
720#pragma define_template NDataBlock< complex<float> >
721#pragma define_template NDataBlock< complex<double> >
722// Instances des delegues FileIO (PPersist)
723#pragma define_template FIO_NDataBlock<uint_1>
724#pragma define_template FIO_NDataBlock<uint_2>
725#pragma define_template FIO_NDataBlock<int_2>
726#pragma define_template FIO_NDataBlock<int_4>
727#pragma define_template FIO_NDataBlock<int_8>
728#pragma define_template FIO_NDataBlock<uint_4>
729#pragma define_template FIO_NDataBlock<uint_8>
730#pragma define_template FIO_NDataBlock<r_8>
731#pragma define_template FIO_NDataBlock<r_4>
732#pragma define_template FIO_NDataBlock< complex<float> >
733#pragma define_template FIO_NDataBlock< complex<double> >
734#endif
735
736#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
737template class NDataBlock<uint_1>;
738template class NDataBlock<uint_2>;
739template class NDataBlock<int_2>;
740template class NDataBlock<int_4>;
741template class NDataBlock<int_8>;
742template class NDataBlock<uint_4>;
743template class NDataBlock<uint_8>;
744template class NDataBlock<r_4>;
745template class NDataBlock<r_8>;
746template class NDataBlock< complex<float> >;
747template class NDataBlock< complex<double> >;
748// Instances des delegues FileIO (PPersist)
749template class FIO_NDataBlock<uint_1>;
750template class FIO_NDataBlock<uint_2>;
751template class FIO_NDataBlock<int_2>;
752template class FIO_NDataBlock<int_4>;
753template class FIO_NDataBlock<int_8>;
754template class FIO_NDataBlock<uint_4>;
755template class FIO_NDataBlock<uint_8>;
756template class FIO_NDataBlock<r_8>;
757template class FIO_NDataBlock<r_4>;
758template class FIO_NDataBlock< complex<float> >;
759template class FIO_NDataBlock< complex<double> >;
760#endif
Note: See TracBrowser for help on using the repository browser.