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