Index: /trunk/SophyaLib/HiStats/datatable.cc
===================================================================
--- /trunk/SophyaLib/HiStats/datatable.cc	(revision 2695)
+++ /trunk/SophyaLib/HiStats/datatable.cc	(revision 2696)
@@ -208,4 +208,10 @@
   col.ser = ser;
   mNames.push_back(col);
+
+  // Tableaux de calcul min-max
+  mMin.push_back(0.);
+  mMax.push_back(0.);
+  mMinMaxNEnt.push_back(0);
+
   return NVar();
 }
@@ -250,4 +256,10 @@
     s.Put(dobj->mNames[k].nom);
   }
+  // ------- Ecriture des tableaux min,max et n_minmax
+  for(uint_8 k=0; k<ltab[1]; k++) { 
+    s.Put(dobj->mMin[k]);
+    s.Put(dobj->mMax[k]);
+    s.Put(dobj->mMinMaxNEnt[k]);
+  }  
   //------- Ecriture du DVList Info() associe, si existant
   if (dobj->mInfo)  s << (*(dobj->mInfo));
@@ -310,4 +322,10 @@
     dobj->AddColumn(ft, cnom);
   }
+  // ------- Lecture des tableaux min,max et n_minmax
+  for(uint_8 k=0; k<ltab[1]; k++) { 
+    s.Get(dobj->mMin[k]);
+    s.Get(dobj->mMax[k]);
+    s.Get(dobj->mMinMaxNEnt[k]);
+  }  
   // ------- Lecture du DVList Info() associe, si necessaire
   if (hadinfo) {    // Lecture eventuelle du DVList Info
Index: /trunk/SophyaLib/HiStats/swppfdtable.cc
===================================================================
--- /trunk/SophyaLib/HiStats/swppfdtable.cc	(revision 2696)
+++ /trunk/SophyaLib/HiStats/swppfdtable.cc	(revision 2696)
@@ -0,0 +1,448 @@
+#include "swppfdtable.h"
+#include "sopnamsp.h"
+#include "pexceptions.h"
+
+
+/*!
+   \class SOPHYA::SwPPFDataTable
+   \ingroup HiStats
+   This class can be used to organize data in table (row-column) form.
+   Each column holds homogeneous data (same data type), while different
+   columns can be used for different data types (integer, float, string ...)
+   \sa SOPHYA::MuTyV
+   \sa SOPHYA::BaseDataTable
+   \sa SOPHYA::ObjFileIO<DataTable>
+
+   \code
+   #include "swppfdtable.h"
+   // ...
+   DataTable dt(64);
+   dt.AddFloatColumn("X0_f");
+   dt.AddFloatColumn("X1_f");
+   dt.AddDoubleColumn("X0X0pX1X1_d");
+   double x[5];
+   for(int i=0; i<63; i++) {
+     x[0] = (i%9)-4.;  x[1] = (i/9)-3.;  x[2] = x[0]*x[0]+x[1]*x[1];
+     dt.AddLine(x);
+   }
+   // Printing table info
+   cout << dt ;
+   // Saving object into a PPF file
+   POutPersist po("dtable.ppf");
+   po << dt ;
+   \endcode
+*/
+/*! Default constructor with optional specification of block (or segment) size - 
+    NOT intented for general use 
+*/
+SwPPFDataTable::SwPPFDataTable(sa_size_t segsz)
+  : BaseDataTable(segsz),
+    mSwOut(NULL), mSwIn(NULL)
+{
+}
+/*! Constructor with the specification of the output swap stream -
+    and optional specification of block (or segment) size
+*/
+SwPPFDataTable::SwPPFDataTable(POutPersist & os, sa_size_t segsz)
+  : BaseDataTable(segsz) ,
+    mISwapper(os), mLSwapper(os), mFSwapper(os), mDSwapper(os), mSSwapper(os),
+    mSwOut(&os), mSwIn(NULL)
+{
+}
+//! Protected constructor for creation from a swap stream 
+SwPPFDataTable::SwPPFDataTable(PInPersist & is, sa_size_t segsz)
+  : BaseDataTable(segsz) ,
+    mISwapper(is), mLSwapper(is), mFSwapper(is), mDSwapper(is), mSSwapper(is),
+    mSwOut(NULL), mSwIn(&is)
+{
+}
+
+//! copy constructor - shares the data
+SwPPFDataTable::SwPPFDataTable(SwPPFDataTable const & a)
+  : BaseDataTable(a.SegmentSize()),
+    mSwOut(NULL), mSwIn(NULL)
+{
+  Share(a);
+}
+
+void SwPPFDataTable::Share(SwPPFDataTable const & a)
+{
+  // Recopie (attention !) brutale des swappers  et les streams associes
+  mISwapper = a.mISwapper;
+  mLSwapper = a.mLSwapper;
+  mFSwapper = a.mFSwapper;
+  mDSwapper = a.mDSwapper;
+  mSSwapper = a.mSSwapper;
+  
+  mSwOut = a.mSwOut;
+  mSwIn = a.mSwIn;
+
+  // On recopie la taille de segment
+  mSegSz = a.SegmentSize();
+  if (a.NVar() == 0)  return;  // Table sans colonne 
+
+  // On copie la structure de table 
+  CopyStructure(a);
+
+  //
+  // Update nombre d'entree, ...
+  mNEnt = a.mNEnt;
+  mNSeg = a.mNSeg;
+  if (a.mInfo)  mInfo = new DVList(*(a.mInfo));
+
+  // mis a jour des tableax min-max 
+  mMin = a.mMin;
+  mMax = a.mMax;
+  mMinMaxNEnt = a.mMinMaxNEnt;
+
+  // Et on partage les donnees des colonnes 
+  for (size_t kk=0; kk<mNames.size(); kk++) {
+    sa_size_t sk = mNames[kk].ser;
+    sa_size_t ska = a.mNames[kk].ser;
+    switch (mNames[kk].type) {
+    case IntegerField :
+      mICols[sk] = a.mICols[ska];
+    break;
+    case LongField :
+      mLCols[sk] = a.mLCols[ska]; 
+      break;
+    case FloatField :
+      mFCols[sk] = a.mFCols[ska]; 
+      break;
+    case DoubleField :
+      mDCols[sk] = a.mDCols[ska]; 
+      break;
+    case StringField :
+      mSCols[sk] = a.mSCols[ska]; 
+      break;
+    default:
+      throw ForbiddenError("SwPPFDataTable::Share() : unknown column type ");
+    break;
+    }
+  }  
+}
+void SwPPFDataTable::SwapOutAll() const
+{
+  // Et on vide les buffers de swap 
+  for (size_t kk=0; kk<mNames.size(); kk++) {
+    sa_size_t sk = mNames[kk].ser;
+    switch (mNames[kk].type) {
+    case IntegerField :
+      mICols[sk].SwapOutBuffer();
+    break;
+    case LongField :
+      mLCols[sk].SwapOutBuffer();
+      break;
+    case FloatField :
+      mFCols[sk].SwapOutBuffer();
+      break;
+    case DoubleField :
+      mDCols[sk].SwapOutBuffer();
+      break;
+    case StringField :
+      mSCols[sk].SwapOutBuffer();
+      break;
+    default:
+      throw ForbiddenError("SwPPFDataTable::Share() : unknown column type ");
+    break;
+    }
+  }  
+}
+
+void SwPPFDataTable::Clear()
+{
+  if ( (NVar() == 0) && (NEntry() == 0)) return;
+  mNEnt = 0;
+  mNSeg = 0;
+  if (mVarD) delete[] mVarD;
+  mVarD = NULL;
+  if (mVarMTV) delete[] mVarMTV;
+  mVarMTV = NULL;
+  mNames.clear();
+  if (mInfo) delete mInfo;
+  mInfo = NULL;
+  mMin.clear();
+  mMax.clear();
+  mMinMaxNEnt.clear();
+  mIColsP.clear();
+  mLColsP.clear();
+  mFColsP.clear();
+  mDColsP.clear();
+  mSColsP.clear();
+
+  mIColIdx.clear();
+  mLColIdx.clear();
+  mFColIdx.clear();
+  mDColIdx.clear();
+  mSColIdx.clear();
+
+  mICols.clear();
+  mLCols.clear();
+  mFCols.clear();
+  mDCols.clear();
+  mSCols.clear();
+}
+
+
+sa_size_t SwPPFDataTable::AddColumn(FieldType ft, string const & cnom)
+{
+  if (NEntry() > 0) 
+    throw ParmError("SwPPFDataTable::AddColumn() Table contains already data ");
+  CheckColName(cnom);
+  sa_size_t ser; 
+  sa_size_t idx = NVar(); 
+  switch (ft) {
+  case IntegerField :
+    ser = mICols.size();
+    mICols.push_back(SwSegDataBlock<int_4>(mISwapper, mSegSz));
+    mIColIdx.push_back(idx);
+    mIColsP.push_back(NULL);
+    for(sa_size_t kk=0; kk<mICols.size(); kk++)
+      mIColsP[kk] = &(mICols[kk]);
+    break;
+  case LongField :
+    ser = mLCols.size();
+    mLCols.push_back(SwSegDataBlock<int_8>(mLSwapper, mSegSz));
+    mLColIdx.push_back(idx);
+    mLColsP.push_back(NULL);
+    for(sa_size_t kk=0; kk<mLCols.size(); kk++)
+      mLColsP[kk] = &(mLCols[kk]);
+    break;
+  case FloatField :
+    ser = mFCols.size();
+    mFCols.push_back(SwSegDataBlock<r_4>(mFSwapper, mSegSz));
+    mFColIdx.push_back(idx);
+    mFColsP.push_back(NULL);
+    for(sa_size_t kk=0; kk<mFCols.size(); kk++)
+      mFColsP[kk] = &(mFCols[kk]);
+    break;
+  case DoubleField :
+    ser = mDCols.size();
+    mDCols.push_back(SwSegDataBlock<r_8>( mDSwapper,mSegSz));
+    mDColIdx.push_back(idx);
+    mDColsP.push_back(NULL);
+    for(sa_size_t kk=0; kk<mDCols.size(); kk++)
+      mDColsP[kk] = &(mDCols[kk]);
+    break;
+  case StringField :
+    ser = mDCols.size();
+    mSCols.push_back(SwSegDataBlock<string>(mSSwapper, mSegSz));
+    mSColIdx.push_back(idx);
+    mSColsP.push_back(NULL);
+    for(sa_size_t kk=0; kk<mSCols.size(); kk++)
+      mSColsP[kk] = &(mSCols[kk]);
+    break;
+  default:
+    throw ParmError("SwPPFDataTable::AddColumn() unknown field type ");
+    break;
+  }
+  colst col;
+  col.nom = cnom;
+  col.type = ft;
+  col.ser = ser;
+  mNames.push_back(col);
+  // On est oblige de calculer les min-max lors du remplissage
+  // On ne peut pas en effet 'relire' le swap pendant l'ecriture
+  mMin.push_back(0.);
+  mMax.push_back(0.);
+  mMinMaxNEnt.push_back(0);
+
+  return NVar();
+}
+
+sa_size_t SwPPFDataTable::AddLine(const r_8* data)
+{
+  // On est oblige de calculer les min-max lors du remplissage
+  // On ne peut pas en effet 'relire' le swap pendant l'ecriture
+  for(sa_size_t k=0; k<NVar(); k++) {
+    double x = data[k];
+    if (x < mMin[k])  mMin[k] = x;
+    if (x > mMax[k])  mMax[k] = x;
+    mMinMaxNEnt[k]++;
+  }
+  return BaseDataTable::AddLine(data);
+}
+
+sa_size_t SwPPFDataTable::AddLine(const MuTyV * data)
+{
+  // On est oblige de calculer les min-max lors du remplissage
+  // On ne peut pas en effet 'relire' le swap pendant l'ecriture
+  for(sa_size_t k=0; k<NVar(); k++) {
+    double x = (double)data[k];
+    if (x < mMin[k])  mMin[k] = x;
+    if (x > mMax[k])  mMax[k] = x;
+    mMinMaxNEnt[k]++;
+  }
+  return BaseDataTable::AddLine(data);
+}
+
+/*!
+   \class SOPHYA::ObjFileIO<SwPPFDataTable>
+   \ingroup HiStats
+   Persistence (serialisation) handler for class SwPPFDataTable
+*/
+/* --Methode-- */ 
+DECL_TEMP_SPEC  /* equivalent a template <> , pour SGI-CC en particulier */
+void   ObjFileIO<SwPPFDataTable>::WriteSelf(POutPersist& s)  const
+//	Serialisation en ecriture du SwPPFDataTable sur stream PPF
+{
+  if (dobj == NULL)   
+    throw NullPtrError("ObjFileIO<SwPPFDataTable>::WriteSelf() NULL dobj pointer ");
+  if (dobj->mSwOut != &s) 
+    throw NotAvailableOperation("ObjFileIO<SwPPFDataTable>::WriteSelf() OutputStream <> SwapStream");
+  //-------  On ecrit 3 uint_4 .... 
+  //  [0]: Numero de version ;
+  //  [1] : bit1 non nul -> has info  
+  //  [2] : reserve
+  uint_4 itab[3];
+  itab[0] = 1;  // Numero de version a 1
+  itab[1] = itab[2] = 0;
+  if (dobj->mInfo)  itab[1] = 1;
+  s.Put(itab, 3);
+
+  //-------- Ecriture de segment size, nb de colonnes, nb de lignes ...  
+  // [0] : SegmentSize()        [1] : NVar()
+  // [2] : NEntry()             [3] : NbSegments()
+  uint_8 ltab[5];
+  ltab[0] = dobj->SegmentSize();
+  ltab[1] = dobj->NVar();
+  ltab[2] = dobj->NEntry();
+  ltab[3] = dobj->NbSegments();
+  ltab[4] = 0;
+  s.Put(ltab, 5);
+
+  //------ Ecriture du nom et type des colonnes
+  for(sa_size_t k=0; k<dobj->NVar(); k++) { 
+    uint_2 typ = dobj->mNames[k].type;
+    s.Put(typ);
+    s.Put(dobj->mNames[k].nom);
+  }
+  // ------- Ecriture des tableaux min,max et n_minmax
+  for(uint_8 k=0; k<ltab[1]; k++) { 
+    s.Put(dobj->mMin[k]);
+    s.Put(dobj->mMax[k]);
+    s.Put(dobj->mMinMaxNEnt[k]);
+  }  
+  //------- Ecriture du DVList Info() associe, si existant
+  if (dobj->mInfo)  s << (*(dobj->mInfo));
+
+  //------- Ecriture des tables de positionnement de SwSegDataBlock<T> 
+  for (size_t kk=0; kk<dobj->mNames.size(); kk++) {
+    sa_size_t sk = dobj->mNames[kk].ser;
+    switch (dobj->mNames[kk].type) {
+    case BaseDataTable::IntegerField :
+      s.PutPosTagTable(dobj->mICols[sk].GetSwapPosTagTable()); 
+      break;
+    case BaseDataTable::LongField :
+      s.PutPosTagTable(dobj->mLCols[sk].GetSwapPosTagTable()); 
+      break;
+    case BaseDataTable::FloatField :
+      s.PutPosTagTable(dobj->mFCols[sk].GetSwapPosTagTable()); 
+      break;
+    case BaseDataTable::DoubleField :
+      s.PutPosTagTable(dobj->mDCols[sk].GetSwapPosTagTable()); 
+      break;
+    case BaseDataTable::StringField :
+      s.PutPosTagTable(dobj->mSCols[sk].GetSwapPosTagTable()); 
+      break;
+    default:
+      throw ForbiddenError("ObjFileIO<SwPPFDataTable>::WriteSelf() : unknown column type ");
+    break;
+    }
+  }    
+  return;
+}
+
+/* --Methode-- */
+DECL_TEMP_SPEC  /* equivalent a template <> , pour SGI-CC en particulier */
+void  ObjFileIO<SwPPFDataTable>::ReadSelf(PInPersist& s)
+//	Serialisation en lecture du SwPPFDataTable sur stream PPF
+{
+  // ------- On lit les 3 premiers uint_4
+  //  [0]: Numero de version ;
+  //  [1] : bit1 non nul -> has info  
+  //  [2] : reserve
+  uint_4 itab[3] = {0,0,0};
+  s.Get(itab, 3);
+  bool hadinfo = false;
+  if ((itab[1]&1) == 1)  hadinfo = true;
+
+  // -------- Lecture de segment size, nb de colonnes, nb de lignes ...  
+  // [0] : SegmentSize()        [1] : NVar()
+  // [2] : NEntry()             [3] : NbSegments()
+  uint_8 ltab[5] = {0,0,0,0,0};
+  s.Get(ltab, 5);
+  if (dobj == NULL) dobj = new SwPPFDataTable(s, ltab[0]);
+  else { 
+    // Copie brutale en utilisant l'operateur = 
+     *dobj = SwPPFDataTable(s, ltab[0]);
+  }
+  // -------- Lecture nom/type colonnes et allocation des colonnes
+  uint_2 typ; 
+  string cnom;
+  for(uint_8 k=0; k<ltab[1]; k++) { 
+    s.Get(typ);
+    s.Get(cnom);
+    BaseDataTable::FieldType ft = (BaseDataTable::FieldType)typ;
+    dobj->AddColumn(ft, cnom);
+  }
+  // ------- Lecture des tableaux min,max et n_minmax
+  for(uint_8 k=0; k<ltab[1]; k++) { 
+    s.Get(dobj->mMin[k]);
+    s.Get(dobj->mMax[k]);
+    s.Get(dobj->mMinMaxNEnt[k]);
+  }  
+  // ------- Lecture du DVList Info() associe, si necessaire
+  if (hadinfo) {    // Lecture eventuelle du DVList Info
+    if (dobj->mInfo == NULL)  dobj->mInfo = new DVList;
+    s >> (*(dobj->mInfo));
+  }
+  // ------- Mise a jour des champs Nb d'entrees, nb segments ...
+  dobj->mNEnt = ltab[2];
+  dobj->mNSeg = ltab[3];
+  cout << " DEBUG___ SegmentSize()= " << dobj->SegmentSize() << endl;
+  // ------- Lecture des tag de positionnement des SwSegDataBlock<T> 
+  vector<int_8> swpos;
+  for (size_t kk=0; kk<dobj->mNames.size(); kk++) {
+    sa_size_t sk = dobj->mNames[kk].ser;
+    switch (dobj->mNames[kk].type) {
+    case BaseDataTable::IntegerField :
+      swpos.clear();
+      s.GetPosTagTable(swpos);
+      dobj->mICols[sk] = SwSegDataBlock<int_4>(dobj->mISwapper, swpos, dobj->SegmentSize());
+    break;
+    case BaseDataTable::LongField :
+      swpos.clear();
+      s.GetPosTagTable(swpos);
+      dobj->mLCols[sk] = SwSegDataBlock<int_8>(dobj->mLSwapper, swpos, dobj->SegmentSize());
+      break;
+    case BaseDataTable::FloatField :
+      swpos.clear();
+      s.GetPosTagTable(swpos);
+      dobj->mFCols[sk] = SwSegDataBlock<r_4>(dobj->mFSwapper, swpos, dobj->SegmentSize());
+      break;
+    case BaseDataTable::DoubleField :
+      swpos.clear();
+      s.GetPosTagTable(swpos);
+      dobj->mDCols[sk] = SwSegDataBlock<r_8>(dobj->mDSwapper, swpos, dobj->SegmentSize());
+      break;
+    case BaseDataTable::StringField :
+      swpos.clear();
+      s.GetPosTagTable(swpos);
+      dobj->mSCols[sk] = SwSegDataBlock<string>(dobj->mSSwapper, swpos, dobj->SegmentSize());
+      break;
+    default:
+      throw ForbiddenError("ObjFileIO<SwPPFDataTable>::ReadSelf() : unknown column type ");
+    break;
+    }
+  }    
+return;
+}
+
+#ifdef __CXX_PRAGMA_TEMPLATES__
+#pragma define_template ObjFileIO<SwPPFDataTable>
+#endif
+
+#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
+template class ObjFileIO<SwPPFDataTable>;
+#endif
Index: /trunk/SophyaLib/HiStats/swppfdtable.h
===================================================================
--- /trunk/SophyaLib/HiStats/swppfdtable.h	(revision 2696)
+++ /trunk/SophyaLib/HiStats/swppfdtable.h	(revision 2696)
@@ -0,0 +1,73 @@
+// This may look like C code, but it is really -*- C++ -*-
+// Class DataTable  (Row-Column data table in memory) 
+//   R. Ansari -  Avril 2005
+//   (C)  LAL-IN2P3/CNRS    CEA-DAPNIA  
+
+#ifndef SWPPFDTABLE_H_SEEN
+#define SWPPFDTABLE_H_SEEN
+
+#include "basedtable.h"
+#include "swsegdb.h"
+#include "ppfswapper.h"
+#include "objfio.h"
+
+
+namespace SOPHYA {
+
+class SwPPFDataTable : public BaseDataTable {
+public:
+  SwPPFDataTable(sa_size_t segsz=512);
+  SwPPFDataTable(POutPersist & os, sa_size_t segsz=512); 
+  SwPPFDataTable(SwPPFDataTable const& a); 
+  
+  virtual sa_size_t AddColumn(FieldType ft, string const & cnom);
+
+  // Filling data structures (adding lines)
+  virtual sa_size_t AddLine(const r_8* data);
+  virtual sa_size_t AddLine(const MuTyV * data);
+
+  //! Equal (copy) operator - Copies the structure and shares the data \b a   
+  inline SwPPFDataTable& operator = (SwPPFDataTable const& a) 
+  { Clear(); Share(a); return *this ; } 
+
+  //  Pour la gestion de persistance PPF
+  friend class ObjFileIO<SwPPFDataTable> ;
+  
+  //! Reset the table content and structure
+  void Clear();
+  /*! This method should be called in order to empty the swapout buffer, 
+     before saving object to PPF stream 
+  */
+  void SwapOutAll() const;
+protected:
+  SwPPFDataTable(PInPersist & is, sa_size_t segsz); 
+  void Share(SwPPFDataTable const & a);
+
+  // Donnees en memoire
+  std::vector< SwSegDataBlock<int_4> > mICols; 
+  PPFDataSwapper<int_4> mISwapper;
+  std::vector< SwSegDataBlock<int_8> > mLCols; 
+  PPFDataSwapper<int_8> mLSwapper;
+  std::vector< SwSegDataBlock<r_4> > mFCols;
+  PPFDataSwapper<r_4> mFSwapper;
+  std::vector< SwSegDataBlock<r_8> > mDCols; 
+  PPFDataSwapper<r_8> mDSwapper;
+  std::vector< SwSegDataBlock<string> > mSCols;    
+  PPFDataSwapper<string> mSSwapper;
+ 
+  POutPersist* mSwOut;
+  PInPersist* mSwIn;
+}; 
+  
+/*! Writes the object in the POutPersist stream \b os */
+inline POutPersist& operator << (POutPersist& os, SwPPFDataTable & obj)
+{ obj.SwapOutAll();  ObjFileIO<SwPPFDataTable> fio(&obj);  fio.Write(os);  return(os); }
+/*! Reads the object from the PInPersist stream \b is */
+inline PInPersist& operator >> (PInPersist& is, SwPPFDataTable & obj)
+{  ObjFileIO<SwPPFDataTable> fio(&obj); is.SkipToNextObject(); fio.Read(is); return(is); }
+// Classe pour la gestion de persistance
+// ObjFileIO<SwPPFDataTable>
+} // namespace SOPHYA
+
+#endif
+
