Index: trunk/SophyaLib/HiStats/ntuple.cc
===================================================================
--- trunk/SophyaLib/HiStats/ntuple.cc	(revision 2615)
+++ trunk/SophyaLib/HiStats/ntuple.cc	(revision 2663)
@@ -8,7 +8,7 @@
 
 
-#define BADVAL -1.e19
 #define LENNAME 8
 #define LENNAME1  (LENNAME+1)
+#define BADVAL -1.e19
 
 /*!
@@ -53,5 +53,5 @@
 
 /* --Methode-- */
-//! Default constructor
+//! Default constructor 
 //++
 NTuple::NTuple()
@@ -63,5 +63,5 @@
 mVar = NULL;
 mVarD = NULL;
-mNames = NULL;
+mFgDouble = true;
 mInfo = NULL;
 }
@@ -74,7 +74,9 @@
   \param blk : Optional argument specifying number of table lines
   in a given data block
+  \param fgdouble : if \b true: internal data kept as double precision values (r_8),
+  simple precision (r_4) otherwise
  */
 //++
-NTuple::NTuple(int nvar, char** noms, int blk)
+NTuple::NTuple(int nvar, char** noms, int blk, bool fgdouble)
 //
 //	Createur d'un ntuple de `nvar' variables dont les
@@ -86,5 +88,4 @@
 mVar = NULL;
 mVarD = NULL;
-mNames = NULL;
 mInfo = NULL;
 if (nvar <= 0)  throw ParmError("NTuple::NTuple(nvar<=0) "); 
@@ -94,13 +95,18 @@
 if (blk < 10) blk = 10;
 mBlk = blk;
-// On prend des noms de LENNAME char pour le moment
-mNames = new char[nvar*LENNAME1];
-r_4* pt = new r_4[nvar*blk];
-mNBlk = 1;
-mPtr.push_back(pt);
-int i;
-for(i=0; i<nvar; i++)
-  { strncpy(mNames+i*LENNAME1, noms[i], LENNAME);  
-  mNames[i*LENNAME1+LENNAME] = '\0'; }
+
+if (fgdouble) {
+  r_8* pt = new r_8[nvar*blk];
+  mNBlk = 1;
+  mPtrD.push_back(pt);
+  mFgDouble = true;
+}
+else { 
+  r_4* pt = new r_4[nvar*blk];
+  mNBlk = 1;
+  mPtr.push_back(pt);
+  mFgDouble = false;
+}
+for(int i=0; i<nvar; i++) mNames.push_back(noms[i]);
 return;
 }
@@ -114,5 +120,5 @@
 //--
 : mNVar(0), mNEnt(0), mBlk(0), mNBlk(0)
-, mVar(NULL), mVarD(NULL), mNames(NULL), mInfo(NULL)
+, mVar(NULL), mVarD(NULL), mInfo(NULL)
 {
 if(NT.mNVar<=0) return; // cas ou NT est cree par defaut
@@ -121,21 +127,29 @@
 mVar = new r_4[NT.mNVar];
 mVarD = new r_8[NT.mNVar];
-mNames = new char[NT.mNVar*LENNAME1];
+
+mNames = NT.mNames;
 
 int i;
-r_4* pt = new r_4[mNVar*mBlk];
-mNBlk = 1; mPtr.push_back(pt);
-
-for(i=0;i<mNVar;i++) strcpy(mNames+i*LENNAME1,NT.NomIndex(i)); 
+mFgDouble = NT.mFgDouble;
+if (mFgDouble) {
+  r_8* pt = new r_8[mNVar*mBlk];
+  mNBlk = 1; mPtrD.push_back(pt);
+  if(NT.mNEnt > 0)
+    for(i=0;i<NT.mNEnt;i++) {pt=NT.GetVecD(i,NULL); Fill(pt);}
+}
+else {
+  r_4* pt = new r_4[mNVar*mBlk];
+  mNBlk = 1; mPtr.push_back(pt);
+  for(i=0;i<NT.mNEnt;i++) {pt=NT.GetVec(i,NULL); Fill(pt);}
+}
+
+mNames = NT.mNames;
 
 if(NT.mInfo!=NULL) {mInfo = new DVList; *mInfo = *(NT.mInfo);}
 
-if(NT.mNEnt<=0) return;
-for(i=0;i<NT.mNEnt;i++) {r_4* x=NT.GetVec(i,NULL); Fill(x);}
-
 return;
 }
 
-/* --Methode-- */
+/* --Methode-- 
 //! Constructor with table initialized from a PPF file
 //++
@@ -154,4 +168,5 @@
 fiont.Read(s);
 }
+*/
 
 /* --Methode-- */
@@ -167,13 +182,15 @@
 if (mVar) delete[] mVar;
 if (mVarD) delete[] mVarD;
-if (mNames)  delete[] mNames;
 if (mInfo) delete mInfo;
 int i;
-if(mNBlk>0) for(i=0; i<mNBlk; i++)  delete[] mPtr[i];
-mPtr.erase(mPtr.begin(), mPtr.end());
+if(mNBlk>0) { 
+  if (mFgDouble) for(i=0; i<mNBlk; i++)  delete[] mPtrD[i];
+  else for(i=0; i<mNBlk; i++)  delete[] mPtr[i];
+}
+if (mFgDouble) mPtrD.erase(mPtrD.begin(), mPtrD.end());
+else mPtr.erase(mPtr.begin(), mPtr.end());
 mNVar = mNEnt = mBlk = mNBlk = 0;
 mVar = NULL;
 mVarD = NULL;
-mNames = NULL;
 mInfo = NULL;
 return;
@@ -195,19 +212,23 @@
 mVar = new r_4[NT.mNVar];
 mVarD = new r_8[NT.mNVar];
-mNames = new char[NT.mNVar*LENNAME1];
+
+mNames = NT.mNames;
 
 int i;
-r_4* pt = new r_4[mNVar*mBlk];
-mNBlk = 1; mPtr.push_back(pt);
-
-for(i=0;i<mNVar;i++) strcpy(mNames+i*LENNAME1,NT.NomIndex(i)); 
+mFgDouble = NT.mFgDouble; 
+if (mFgDouble) {
+  r_8* pt = new r_8[mNVar*mBlk];
+  mNBlk = 1; mPtrD.push_back(pt);
+  if(NT.mNEnt > 0)
+    for(i=0;i<NT.mNEnt;i++) {pt=NT.GetVecD(i,NULL); Fill(pt);}
+}
+else {
+  r_4* pt = new r_4[mNVar*mBlk];
+  mNBlk = 1; mPtr.push_back(pt);
+  for(i=0;i<NT.mNEnt;i++) {pt=NT.GetVec(i,NULL); Fill(pt);}
+}
 
 if(NT.mInfo!=NULL) {mInfo = new DVList; *mInfo = *(NT.mInfo);}
 
-if(NT.mNEnt<=0) return *this;
-for(i=0;i<NT.mNEnt;i++) {r_4* x=NT.GetVec(i,NULL); Fill(x);}
-
-// En fait il faudrait un createur par copie qui partage les donnees
-// quand l'objet est temporaire... trop complique A FAIRE !  cmv.
 return *this;
 }
@@ -226,10 +247,55 @@
 int numb = mNEnt/mBlk;
 if (numb >= mNBlk) {
-  r_4* pt = new r_4[mNVar*mBlk];
-  mNBlk++;
-  mPtr.push_back(pt);
-}
+  if (mFgDouble) {
+    r_8* pt = new r_8[mNVar*mBlk];
+    mNBlk++;
+    mPtrD.push_back(pt);
+  }
+  else {
+    r_4* pt = new r_4[mNVar*mBlk];
+    mNBlk++;
+    mPtr.push_back(pt);
+  }
+}
+
 int offb = mNEnt-numb*mBlk;
-memcpy((mPtr[numb]+offb*mNVar), x, mNVar*sizeof(r_4));
+if (mFgDouble) 
+  for(int i=0; i<mNVar; i++) (mPtrD[numb]+offb*mNVar)[i] = x[i];
+else memcpy((mPtr[numb]+offb*mNVar), x, mNVar*sizeof(r_4));
+mNEnt++;
+return;
+}
+
+/* --Methode-- */
+//! Adds an entry (a line) to the table (double precision)
+/*!
+  \param x : content of the line to be appended to the table
+ */
+//++
+void  NTuple::Fill(r_8* x)
+//
+//	Remplit le ntuple avec le tableau double precision `x'.
+//--
+{
+int numb = mNEnt/mBlk;
+if (numb >= mNBlk) {
+  if (mFgDouble) {
+    r_8* pt = new r_8[mNVar*mBlk];
+    mNBlk++;
+    mPtrD.push_back(pt);
+  }
+  else {
+    r_4* pt = new r_4[mNVar*mBlk];
+    mNBlk++;
+    mPtr.push_back(pt);
+  }
+}
+
+int offb = mNEnt-numb*mBlk;
+if (mFgDouble) 
+  memcpy((mPtrD[numb]+offb*mNVar), x, mNVar*sizeof(r_8));
+else
+  for(int i=0; i<mNVar; i++) (mPtr[numb]+offb*mNVar)[i] = x[i];
+
 mNEnt++;
 return;
@@ -248,5 +314,6 @@
 int numb = n/mBlk;
 int offb = n-numb*mBlk;
-return(*(mPtr[numb]+offb*mNVar+k));
+if ( mFgDouble) return(*(mPtrD[numb]+offb*mNVar+k));
+else return(*(mPtr[numb]+offb*mNVar+k));
 }
 
@@ -260,11 +327,12 @@
 {
 int i;
+string snom = nom;
 for(i=0; i<mNVar; i++)  
-  if ( strcmp(nom, mNames+i*LENNAME1) == 0)  return(i);
+  if ( mNames[i] == snom)  return(i);
 return(-1);
 }
 
 
-static char nomretour[2*LENNAME1];
+static char nomretour[256];
 /* --Methode-- */
 //++
@@ -275,5 +343,5 @@
 {
 nomretour[0] = '\0';
-if ((k >= 0) && (k < mNVar))  strcpy(nomretour, mNames+k*LENNAME1);
+if ((k >= 0) && (k < mNVar))  strncpy(nomretour, mNames[k].c_str(), 255);
 return(nomretour);
 }
@@ -296,5 +364,6 @@
 int numb = n/mBlk;
 int offb = n-numb*mBlk;
-memcpy(ret, (mPtr[numb]+offb*mNVar), mNVar*sizeof(r_4));
+if (mFgDouble) for(i=0; i<mNVar; i++) ret[i] = (mPtrD[numb]+offb*mNVar)[i];
+else  memcpy(ret, (mPtr[numb]+offb*mNVar), mNVar*sizeof(r_4));
 return(ret);
 }
@@ -309,6 +378,14 @@
 int i;
 if (ret == NULL)   ret = mVarD;
-float *  fr = GetVec(n);
-for(i=0; i<mNVar; i++)   ret[i] = fr[i];
+if (n >= mNEnt) {
+  for(i=0; i<mNVar; i++)   ret[i] = BADVAL;
+  return(ret);
+}
+  
+int numb = n/mBlk;
+int offb = n-numb*mBlk;
+if (mFgDouble) 
+  memcpy(ret, (mPtrD[numb]+offb*mNVar), mNVar*sizeof(r_8));
+for(i=0; i<mNVar; i++) ret[i] = (mPtr[numb]+offb*mNVar)[i];
 return(ret);
 }
@@ -337,5 +414,5 @@
 
 printf("Num     ");
-for(i=0; i<mNVar; i++)  printf("%8s ", mNames+i*LENNAME1);
+for(i=0; i<mNVar; i++)  printf("%8s ", mNames[i].c_str());
 putchar('\n');
 
@@ -361,5 +438,7 @@
 //--
 {
-os << "NTuple: NVar= " << mNVar << " NEnt=" << mNEnt  
+char * tt = "float"; 
+if (mFgDouble) tt = "double";
+os << "NTuple T=" << tt << " : NVar= " << mNVar << " NEnt=" << mNEnt  
    << " (Blk Sz,Nb= " << mBlk << " ," << mNBlk << ")\n";
 os << "            Variables       Min      Max       \n";
@@ -369,5 +448,5 @@
 for(i=0; i<mNVar; i++) {
   GetMinMax(i, min, max);
-  sprintf(buff, "%3d  %16s  %10g  %10g \n", i, mNames+i*LENNAME1, min, max);
+  sprintf(buff, "%3d  %16s  %10g  %10g \n", i, mNames[i].c_str(), min, max);
   os << (string)buff ;
   }
@@ -404,5 +483,5 @@
 int j,kk;
 int postab, posb;
-float* xv = new float[NbColumns()];
+double* xv = new double[NbColumns()];
 
 int nlread = 0;
@@ -492,5 +571,5 @@
     if (i >= mNEnt)  break;
     i++;
-    x = *(mPtr[jb]+ib*mNVar+k);
+    x = (mFgDouble) ? *(mPtrD[jb]+ib*mNVar+k) : *(mPtr[jb]+ib*mNVar+k);
     if(i==1) {min = x; max = x;}
     if (x < min)  min = x;
@@ -533,5 +612,5 @@
   if (i%5 == 0)   rets += "\ndouble "; 
   else rets += ",";
-  rets += mNames+i*LENNAME1;
+  rets += mNames[i];
   }
 rets += "; \n";
@@ -539,5 +618,5 @@
   char buff[256];
   for(i=0; i<mNVar; i++) {
-    sprintf(buff,"%s=%s[%d]; ",  mNames+i*LENNAME1, nomx, i);
+    sprintf(buff,"%s=%s[%d]; ",  mNames[i].c_str(), nomx, i);
     rets += buff;
     if ( (i%3 == 0) && (i > 0) )  rets += "\n"; 
@@ -559,5 +638,5 @@
 string rets=" Num    ";
 for(int i=0; i<mNVar; i++) {
-  sprintf(buff, "%8s ", mNames+i*LENNAME1);
+  sprintf(buff, "%8s ", mNames[i].c_str());
   rets += buff;
   }
@@ -603,25 +682,33 @@
 if (dobj == NULL)   return;
 
-// On ecrit cette chaine pour compatibilite avec l'ancienne version 
+// On ecrit cette chaine pour compatibilite avec les anciennes version (1,2) 
 string strg = "NTuple";
 s.Put(strg);
 
 //  On ecrit 3 uint_4 .... 
-//  0: Numero de version,  1 : non nul -> has info,  2 : reserve
+//  [0]: Numero de version ;
+//  [1] : bit1 non nul -> has info, bit 2 non nul mFgDouble=true 
+//  [2] : reserve
 uint_4 itab[3];
-itab[0] = 2;  // Numero de version a 1
+itab[0] = 3;  // Numero de version a 3
 itab[1] = itab[2] = 0;
 if (dobj->mInfo)  itab[1] = 1;
+if (dobj->mFgDouble) itab[1] += 2;
 s.Put(itab, 3);
 
 s.Put(dobj->mNVar);
-s.PutBytes(dobj->mNames, dobj->mNVar*LENNAME1);
+for(int k=0; k<dobj->mNVar; k++) s.Put(dobj->mNames[k]);
 s.Put(dobj->mNEnt);
 s.Put(dobj->mBlk);
 s.Put(dobj->mNBlk);
+
 if (dobj->mInfo)  s << (*(dobj->mInfo));
 int jb;
-for(jb=0; jb<dobj->mNBlk; jb++)
-  s.Put(dobj->mPtr[jb], dobj->mNVar*dobj->mBlk); 
+if (dobj->mFgDouble) 
+  for(jb=0; jb<dobj->mNBlk; jb++)
+    s.Put(dobj->mPtrD[jb], dobj->mNVar*dobj->mBlk); 
+else 
+  for(jb=0; jb<dobj->mNBlk; jb++)
+    s.Put(dobj->mPtr[jb], dobj->mNVar*dobj->mBlk); 
 return;
 }
@@ -642,8 +729,9 @@
 string strg;
 s.Get(strg);
+uint_4 itab[3] = {0,0,0};
 if (strg == "NTuple") {
-  uint_4 itab[3];
   s.Get(itab, 3);
-  if (itab[1] != 0) hadinfo = true;
+  if ( ((itab[0] < 3) && (itab[1] != 0)) || 
+       ((itab[0] >= 3) && ((itab[1]&1) == 1)) ) hadinfo = true;
 }
 else {
@@ -653,24 +741,62 @@
   if (strncmp(buff+strlen(buff)-7, "HasInfo", 7) == 0)  hadinfo = true;
 }
-s.Get(dobj->mNVar);
-dobj->mNames = new char[dobj->mNVar*LENNAME1];
-dobj->mVar = new r_4[dobj->mNVar];
-dobj->mVarD = new r_8[dobj->mNVar];
-s.GetBytes(dobj->mNames, dobj->mNVar*LENNAME1);
-s.Get(dobj->mNEnt);
-s.Get(dobj->mBlk);
-s.Get(dobj->mNBlk);
-
-if (hadinfo) {    // Lecture eventuelle du DVList Info
-  if (dobj->mInfo == NULL)  dobj->mInfo = new DVList;
-  s >> (*(dobj->mInfo));
-  }
-
-int jb; 
-for(jb=0; jb<dobj->mNBlk; jb++) {
-  r_4* pt = new r_4[dobj->mNVar*dobj->mBlk];
-  dobj->mPtr.push_back(pt);
-  s.Get(dobj->mPtr[jb], dobj->mNVar*dobj->mBlk); 
-}
+if (itab[0] < 3) {  // Lecture version anterieures V= 1 , 2 
+  s.Get(dobj->mNVar);
+  dobj->mVar = new r_4[dobj->mNVar];
+  dobj->mVarD = new r_8[dobj->mNVar];
+  
+  char * names = new char[dobj->mNVar*LENNAME1];
+  s.GetBytes(names, dobj->mNVar*LENNAME1);
+  for(int k=0; k<dobj->mNVar; k++) dobj->mNames.push_back(names+k*LENNAME1);
+  s.Get(dobj->mNEnt);
+  s.Get(dobj->mBlk);
+  s.Get(dobj->mNBlk);  
+  if (hadinfo) {    // Lecture eventuelle du DVList Info
+    if (dobj->mInfo == NULL)  dobj->mInfo = new DVList;
+    s >> (*(dobj->mInfo));
+  }
+  // Il n'y avait que des NTuple avec data float pour V < 3
+  dobj->mFgDouble = false;   
+  int jb; 
+  for(jb=0; jb<dobj->mNBlk; jb++) {
+    r_4* pt = new r_4[dobj->mNVar*dobj->mBlk];
+    dobj->mPtr.push_back(pt);
+    s.Get(dobj->mPtr[jb], dobj->mNVar*dobj->mBlk); 
+  }
+}
+else {  // Lecture version V 3 
+  s.Get(dobj->mNVar);
+  dobj->mVar = new r_4[dobj->mNVar];
+  dobj->mVarD = new r_8[dobj->mNVar];
+  string nom;
+  for(int k=0; k<dobj->mNVar; k++) { 
+    s.Get(nom);
+    dobj->mNames.push_back(nom);
+  }
+  s.Get(dobj->mNEnt);
+  s.Get(dobj->mBlk);
+  s.Get(dobj->mNBlk);  
+  if (hadinfo) {    // Lecture eventuelle du DVList Info
+    if (dobj->mInfo == NULL)  dobj->mInfo = new DVList;
+    s >> (*(dobj->mInfo));
+  }
+  // Il n'y avait que des NTuple avec data float pour V < 3
+  dobj->mFgDouble =  ((itab[1]&2) == 2) ? true : false;   
+  int jb; 
+  if (dobj->mFgDouble) {
+    for(jb=0; jb<dobj->mNBlk; jb++) {
+      r_8* pt = new r_8[dobj->mNVar*dobj->mBlk];
+      dobj->mPtrD.push_back(pt);
+      s.Get(dobj->mPtrD[jb], dobj->mNVar*dobj->mBlk); 
+    }
+  }
+  else {
+    for(jb=0; jb<dobj->mNBlk; jb++) {
+      r_4* pt = new r_4[dobj->mNVar*dobj->mBlk];
+      dobj->mPtr.push_back(pt);
+      s.Get(dobj->mPtr[jb], dobj->mNVar*dobj->mBlk); 
+    }
+  }
+}  // Fin lecture V3 
 
 }
