// Gestion de block de donnees avec partage de references // C.Magneville 04/99 // LAL (Orsay) / IN2P3-CNRS DAPNIA/SPP (Saclay) / CEA #include "machdefs.h" #include #include #include #include #include "pexceptions.h" #include "ndatablock.h" #include "objfio.h" using namespace PlanckDPC; // define DEBUG_NDATABLOCK #ifdef DEBUG_NDATABLOCK static size_t NallocData = 0; static size_t NallocSRef = 0; #endif // LOGIQUE DE BASE: // - le createur par copie et la surcharge de l operateur = "partage" les donnees // - gestion du partage de reference //////////////////////////////////////////////////////////////// //************ Createur, Destructeur, gestion des donnees template NDataBlock::NDataBlock(size_t n) // Createur d'une structure de "n" donnees : mSz(0), mSRef(NULL), mIsTemp(false) { #ifdef DEBUG_NDATABLOCK cout<<"DEBUG_NDataBlock::NDataBlock("< NDataBlock::NDataBlock(size_t n, T* data, Bridge* br) // Createur d'une structure de "n" donnees, avec donnees preallouees // (Voir explications dans Alloc()) : mSz(0), mSRef(NULL), mIsTemp(false) { #ifdef DEBUG_NDATABLOCK cout<<"DEBUG_NDataBlock::NDataBlock("< NDataBlock::NDataBlock() // Createur par default : mSz(0), mSRef(NULL), mIsTemp(false) { #ifdef DEBUG_NDATABLOCK cout<<"DEBUG_NDataBlock::NDataBlock("< NDataBlock::NDataBlock(const NDataBlock& a) // Createur par copie // ATTENTION: partage les donnees avec "a" // Ecriture: NDataBlock a = b; // NDataBlock a(b) : mSz(0), mSRef(NULL), mIsTemp(false) { #ifdef DEBUG_NDATABLOCK cout<<"DEBUG_NDataBlock::NDataBlock("< NDataBlock::NDataBlock(const NDataBlock& a,bool share) // Createur avec choix de partager ou non : mSz(0), mSRef(NULL), mIsTemp(false) { #ifdef DEBUG_NDATABLOCK cout<<"DEBUG_NDataBlock::NDataBlock("< NDataBlock::~NDataBlock() // Destructeur { #ifdef DEBUG_NDATABLOCK cout<<"DEBUG_NDataBlock::~NDataBlock("< void NDataBlock::SetTemp(bool temp) const // Set temporary { mIsTemp=temp; #ifdef DEBUG_NDATABLOCK cout<<"DEBUG_NDataBlock::SetTemp("<nref = 1; if(data) mSRef->data = data; else mSRef->data = new T[n]; mSRef->bridge = br; #ifdef DEBUG_NDATABLOCK // Meme dans le cas data!=0 et br==0 (connexion d'un tableau // avec destruction geree par ~NDataBlock (cas 2-) on compte // comme si on avait fait une allocation du tableau (ce qui a ete // fait au niveau du dessus!). if(!br) NallocData++; NallocSRef++; cout<<"...DEBUG_NDataBlock::Alloc mSz="<nref="<nref<<" mSRef->data="<< mSRef->data <<" mSRef->bridge="<bridge<<" IsTemp="< void NDataBlock::Clone(const NDataBlock& a) // Clone (copie de donnee) a partir de "a" // sauf si "a" est une classe temporaire (dans ce cas share!) { #ifdef DEBUG_NDATABLOCK cout<<"DEBUG_NDataBlock::Clone("< void NDataBlock::Share(const NDataBlock& a) // Partage des donnees avec "a" { #ifdef DEBUG_NDATABLOCK cout<<"DEBUG_NDataBlock::Share("<nref++; #ifdef DEBUG_NDATABLOCK cout<<"...DEBUG_NDataBlock::Share mSz="<nref="<nref<<" mSRef->data="<< mSRef->data <<" mSRef->bridge="<bridge<<" IsTemp="< void NDataBlock::Delete(void) // Pour detruire les pointeurs en tenant compte des references { #ifdef DEBUG_NDATABLOCK cout<<"DEBUG_NDataBlock::Delete("<nref="<nref<<" mSRef->data=" <data<<" mSRef->bridge="<bridge; cout<nref--; if(mSRef->nref != 0) { #ifdef DEBUG_NDATABLOCK cout<<"...DEBUG_NDataBlock::Delete() pas de desallocation il reste nref=" <nref<<" Total("<bridge) NallocData--; NallocSRef--; cout<<"...DEBUG_NDataBlock::Delete() desallocation complete il reste nref=" <nref<<" Total("<bridge) delete mSRef->bridge; // sinon, les donnees ont ete allouees par nos soins, on libere l'espace memoire else delete [] mSRef->data; mSRef->bridge=NULL; mSRef->data=NULL; delete mSRef; mSRef=NULL; } //////////////////////////////////////////////////////////////// template void NDataBlock::Reset(T v) { if(mSRef==NULL) return; if(mSRef->data==NULL) return; if(mSz==0) return; T *p=Begin(), *pe=End(); while(p void NDataBlock::ReSize(size_t n,bool force_alloc) // Re-dimension, avec re-allocation de la place si n != mSz // Si n==mSz, la place n'est re-allouee que si force_alloc=true { if(!force_alloc && n == mSz) return; Alloc(n); } template void NDataBlock::FillFrom(size_t n,T* data) // Remplissage par un tableau de donnees // - Si classe vide : creation de l'espace memoire // - Si classe connectee : on ecrit selon la longueur { if(data==NULL) throw(NullPtrError("NDataBlock::FillFrom data==NULL\n")); if(n==0) throw(ParmError("NDataBlock::FillFrom n<=0\n")); if(mSRef==NULL) Alloc(n); // cas du createur par default if(mSz void NDataBlock::Print(ostream& os,size_t i1,size_t n) const // Impression de n elements a partir de i1 { size_t nr = 0; T* p = NULL; Bridge* br = NULL; if(mSRef) {nr = mSRef->nref; p = mSRef->data; br = mSRef->bridge;} os<<"NDataBlock::Print("<=mSz || n<=0 || !p) return; size_t i2 = i1+n; if(i2>mSz) i2=mSz; size_t im = 1; bool enl=false; while(i1 b; template NDataBlock& NDataBlock::operator = (const NDataBlock& a) // surcharge avec partage des donnees // Ecriture: NDataBlock a; a = b; // NDataBlock a(10); a = b; (a est re-affecte) { #ifdef DEBUG_NDATABLOCK cout<<"DEBUG_NDataBlock::operator=("< NDataBlock& NDataBlock::operator = (T v) // surcharge avec copie des donnees (pas de partage) // "this" est sur-ecrit, attention au partage de reference! // NDataBlock a; a = v; ou bien NDataBlock a(10); a = v; { #ifdef DEBUG_NDATABLOCK cout<<"DEBUG_NDataBlock::operator=("< T NDataBlock::Sum(size_t i1,size_t n) const // Somme des elements de i1 a i1+n-1 { if(i1>=mSz) return 0; if(n>mSz) n = mSz; if(n==0) n = mSz-i1; T const *p=Begin()+i1, *pe=p+n; T val = 0; while (p T NDataBlock::Product(size_t i1,size_t n) const // Produit des elements de i1 a i1+n-1 { if(i1>=mSz) return 0; if(n>mSz) n = mSz; if(n==0) n = mSz-i1; T const *p=Begin()+i1, *pe=p+n; T val = 0; while (p b; template NDataBlock& NDataBlock::operator += (T b) { if(mSz==0) throw(SzMismatchError("NDataBlock::operator+=v null size\n")); T *p=Begin(), *pe=End(); while (p NDataBlock& NDataBlock::operator -= (T b) { if(mSz==0) throw(SzMismatchError("NDataBlock::operator-=v null size\n")); T *p=Begin(), *pe=End(); while (p NDataBlock& NDataBlock::operator *= (T b) { if(mSz==0) throw(SzMismatchError("NDataBlock::operator*=v null size\n")); T *p=Begin(), *pe=End(); while (p NDataBlock& NDataBlock::operator /= (T b) { if(b==(T) 0) throw(ParmError("NDataBlock::operator/=v divide by zero\n")); if(mSz==0) throw(SzMismatchError("NDataBlock::operator/=v null size\n")); T *p=Begin(), *pe=End(); while (p NDataBlock& NDataBlock::operator += (const NDataBlock& a) { if(mSz==0 || mSz!=a.mSz) throw(SzMismatchError("NDataBlock::operator+=A size mismatch/null")); T *p=Begin(), *pe=End(); T const * pa=a.Begin(); while (p NDataBlock& NDataBlock::operator -= (const NDataBlock& a) { if(mSz==0 || mSz!=a.mSz) throw(SzMismatchError("NDataBlock::operator-=A size mismatch/null")); T *p=Begin(), *pe=End(); T const *pa=a.Begin(); while (p NDataBlock& NDataBlock::operator *= (const NDataBlock& a) { if(mSz==0 || mSz!=a.mSz) throw(SzMismatchError("NDataBlock::operator*=A size mismatch/null")); T *p=Begin(), *pe=End(); T const *pa=a.Begin(); while (p NDataBlock& NDataBlock::operator /= (const NDataBlock& a) { if(mSz==0 || mSz!=a.mSz) throw(SzMismatchError("NDataBlock::operator/=A size mismatch/null")); T *p=Begin(), *pe=End(); T const *pa=a.Begin(); while (pb; // NDataBlock = b+NDataBlock; // ATTENTION: re-affectation imposee template NDataBlock NDataBlock::Add(T b) const // Pour A+b { NDataBlock result(*this,false); result.SetTemp(true); result += b; return result; } template NDataBlock NDataBlock::Sub(T b) const // Pour A-b { NDataBlock result(*this,false); result.SetTemp(true); return result -= b; } template NDataBlock NDataBlock::SubInv(T b) const // Pour b-A { NDataBlock result(*this,false); result.SetTemp(true); T *p=result.Begin(), *pe=result.End(); T const *pa=this->Begin(); while(p NDataBlock NDataBlock::Mul(T b) const // Pour A*b { NDataBlock result(*this,false); result.SetTemp(true); return result *= b; } template NDataBlock NDataBlock::Div(T b) const // Pour A/b { NDataBlock result(*this,false); result.SetTemp(true); return result /= b; } template NDataBlock NDataBlock::DivInv(T b) const // Pour b/A { NDataBlock result(*this,false); result.SetTemp(true); T *p=result.Begin(), *pe=result.End(); T const *pa = this->Begin(); while(p NDataBlock NDataBlock::Add(const NDataBlock& b) const // Pour A+B { if(this->mSz!=b.mSz) throw(SzMismatchError("NDataBlock operator C=A+B size mismatch/null\n")); NDataBlock result; result.SetTemp(true); if(b.IsTemp()) { result.Share(b); result += *this; } else { result.Clone(*this); result += b; } return result; } template NDataBlock NDataBlock::Mul(const NDataBlock& b) const // Pour A*B { if(this->mSz!=b.mSz) throw(SzMismatchError("NDataBlock operator C=A*B size mismatch/null\n")); NDataBlock result; result.SetTemp(true); if(b.IsTemp()) { result.Share(b); result *= *this; } else { result.Clone(*this); result *= b; } return result; } template NDataBlock NDataBlock::Sub(const NDataBlock& b) const // Pour A-B { if(this->mSz!=b.mSz) throw(SzMismatchError("NDataBlock operator C=A-B size mismatch/null\n")); NDataBlock result; result.SetTemp(true); if(b.IsTemp()) { result.Share(b); T *p=result.Begin(), *pe=result.End(); T const *pa=this->Begin(); while(p NDataBlock NDataBlock::Div(const NDataBlock& b) const // Pour A/B { if(this->mSz!=b.mSz) throw(SzMismatchError("NDataBlock operator C=A/B size mismatch/null\n")); NDataBlock result; result.SetTemp(true); if(b.IsTemp()) { result.Share(b); T *p=result.Begin(), *pe=result.End(); T const *pa=this->Begin(); while(p void ObjFileIO< NDataBlock >::ReadSelf(PInPersist& is) template void ObjFileIO< NDataBlock >::WriteSelf(POutPersist& os) */ template FIO_NDataBlock::FIO_NDataBlock() { dobj=new NDataBlock; } template FIO_NDataBlock::FIO_NDataBlock(string const & filename) { dobj=new NDataBlock; Read(filename); } template FIO_NDataBlock::FIO_NDataBlock(const NDataBlock & obj) { dobj = new NDataBlock(obj); } template FIO_NDataBlock::FIO_NDataBlock(const NDataBlock * obj) { dobj = new NDataBlock(*obj); } template FIO_NDataBlock::~FIO_NDataBlock() { if (dobj) delete dobj; } template AnyDataObj* FIO_NDataBlock::DataObj() { return(dobj); } template void FIO_NDataBlock::ReadSelf(PInPersist& is) { // On lit les 3 premiers uint_8 uint_8 itab[3]; is.Get(itab, 3); if (dobj == NULL) dobj = new NDataBlock(itab[1]); else dobj->ReSize(itab[1]); // On lit le tableau de nombres PIOSReadArray(is, dobj->Data(), dobj->Size()); } template void FIO_NDataBlock::WriteSelf(POutPersist& os) const { if (dobj == NULL) return; // Attention - $CHECK$ Reza 26/04/99 // On ecrit 3 uint_4 // 0 : Numero de version, 1 : Taille, 2 reserve a l uint_8 itab[3]; itab[0] = 1; itab[1] = dobj->Size(); itab[2] = 0; os.Put(itab, 3); // On ecrit le tableau de nombres PIOSWriteArray(os, dobj->Data(), dobj->Size()); } /////////////////////////////////////////////////////////////// #ifdef __CXX_PRAGMA_TEMPLATES__ #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock #pragma define_template NDataBlock< complex > #pragma define_template NDataBlock< complex > // Instances des delegues FileIO (PPersist) #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock #pragma define_template FIO_NDataBlock< complex > #pragma define_template FIO_NDataBlock< complex > #endif #if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES) template class NDataBlock; template class NDataBlock; template class NDataBlock; template class NDataBlock; template class NDataBlock; template class NDataBlock; template class NDataBlock; template class NDataBlock; template class NDataBlock; template class NDataBlock; template class NDataBlock< complex >; template class NDataBlock< complex >; // Instances des delegues FileIO (PPersist) template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock; template class FIO_NDataBlock< complex >; template class FIO_NDataBlock< complex >; #endif