/*
$Id: ElementContainer.cc 2374 2012-04-19 01:57:28Z jisuzuki $
*/

#include <functional>
#include <numeric>
#include "ElementContainer.hh"

#include "SplitString.hh"
#include "DoubleBinArrange.hh"
#include "StringTools.hh"

/*
 * index of methods
 *
 *
 * 1. constructor, operator=, destructor
 * 2. private function used in operators
 * 3. operators, +=, -=, *=, /=
 * 4. removed.
 * 5. ReBin and Binning; rebinning
 * 6. SetKeys and Dumpkey
 * 7. series of Add() method
 * 8. InputHeader, InputUnitHeader
 * 9. Copy, AddBlankVecvot, Remove, Replace, AddValue, SetValue
 * 10. series of Dump, DumpValue
 * 11. StringToInt, IntToString, DoubleToString (removed)
 * 12. series of Put()
 * 13. others
 * 14. sum, integral, average, min, max
 */


/**********************************************
 *** 0. global functions (not class methods)***
 **********************************************/

///////////////////////////////////////////
bool
Compare( const std::vector<Double> &v1, const std::vector<Double> &v2 )
{
  UInt4 size = (UInt4)(v1.size());

  if( size ==0 || v2.size() == 0 ){
    std::cout << "Compare(std::vector,std::vector) (in ElementContainer.cc)" << std::endl;
    std::cout << "The size of input vector is zero."      << std::endl;
    std::cout << "I cannot compare the vectors."          << std::endl;
    return false;
  }

  if( size != v2.size() ){
    return false;
  }

  Double Y = 0.0;
  Double X = 0.0;

  for( UInt4 i=0; i<size; i++ ){
    Y = Y + v1[i];
    X = X + v2[i];
  }
  Y = Y / (Double)size;
  X = X / (Double)size;

  Double sx2 = 0.0;
  Double sy2 = 0.0;
  Double sxy = 0.0;

  for( UInt4 i=0; i<size; i++ ){
    sx2 = sx2 + (v2[i]-X)*(v2[i]-X);
    sy2 = sy2 + (v1[i]-Y)*(v1[i]-Y);
    sxy = sxy + ( v2[i] - X) * ( v1[i] - Y );
  }

  Double slope = sxy / sx2;
  Double intercept = Y - slope * X;
  Double r2 = sxy * sxy / ( sx2 * sy2 );

  if( slope <= 0.99 )       return false;
  if( slope >= 1.01 )       return false;
  if( intercept <= -0.001 ) return false;
  if( intercept >=  0.001 ) return false;
  if( r2    <= 0.999 )      return false;

  return true;
}
///////////////////////////////////////////

/** makes new std::string for the unit std::string
 **
 * @param  L unit of left object
 * @param  ope operator
 * @param  R unit of right object
 * @return new std::string according to the following rule.
 *       same  not same
 *   +    L      L+R
 *   -    L      L-R
 *   *   L*L     L*R
 *   /   None    L/R
 *  When L or R contains + or -, it is enclosed in parentheses.
 *  When L or R is None, "None" is returned.
 *  When the operator is illegal, "IllegalOperator" is returned.
 */
std::string ReArrangeUnit( const std::string &L, const std::string &ope, const std::string &R ) {
  //return "(" + L + ope + R + ")";  // [TI 2015.09.30] Change the rule
  if (L == "None" or R == "None"){
    return "None";
  }else{
    std::ostringstream oss;
    if (L == R){
      if (ope == "+" or ope == "-"){
        return L;
      } else if (ope == "*"){
        if (L.find("+") == std::string::npos and L.find("-") == std::string::npos){
          oss << L << ope << L;
        } else {
          oss << "(" << L << ")*(" << L << ")";
        }
      } else if (ope == "/"){
        oss << "None";
      } else {
        std::cout << "Illegal operator" << std::endl;
        return "IllegalOperator";
      }
    } else {
      if (ope == "+" or ope == "-"){
        oss << L << ope << R;
      } else if (ope == "*" or ope == "/"){
        if (L.find("+") == std::string::npos and L.find("-") == std::string::npos){
          oss << L << ope;
        } else {
          oss << "(" << L << ")" << ope;
        }
        if (R.find("+") == std::string::npos and R.find("-") == std::string::npos){
          oss << R;
        } else {
          oss << "(" << R << ")";
        }
      } else {
        std::cout << "Illegal operator" << std::endl;
        return "IllegalOperator";
      }
    }
    return oss.str();
  }
}

/**********************************************
 *** 1. constructor, operator=, destructor  ***
 **********************************************/

////////////////////////////////////////////////////////
ElementContainer::
ElementContainer() :
  Xkey("None"), Ykey("None"), Ekey("None"), safesum(false)
{
  header     = new HeaderBase();
  UnitHeader = new HeaderBase();
  HistFlag = true;
}
////////////////////////////////////////////////////////
ElementContainer::
ElementContainer( const HeaderBase &Header ) :
  Xkey("None"), Ykey("None"), Ekey("None"), safesum(false)
{
  header = new HeaderBase( Header );
  UnitHeader = new HeaderBase();
  HistFlag = true;
}
////////////////////////////////////////////////////////
ElementContainer::
ElementContainer( const ElementContainer &ob ) :
  Xkey(ob.Xkey), Ykey(ob.Ykey), Ekey(ob.Ekey), safesum(ob.safesum),
  M(ob.M)
{
  header = new HeaderBase( *ob.header );
  UnitHeader = new HeaderBase( *ob.UnitHeader );
  HistFlag = ob.HistFlag;
}
/////////////////////////////////////////////////////////
ElementContainer &ElementContainer ::
operator=( const ElementContainer &ob )
{
  *header     = *ob.header;
  *UnitHeader = *ob.UnitHeader;

  M = ob.M;

  Xkey = ob.Xkey;
  Ykey = ob.Ykey;
  Ekey = ob.Ekey;

  safesum = ob.safesum;
  HistFlag = ob.HistFlag;

  return *this;
}
////////////////////////////////////////////////////////
ElementContainer::
 ~ElementContainer()
{
  delete header;
  delete UnitHeader;
  M.clear();
}


/**********************************************
 *** 2. private function used in operators  ***
 **********************************************/

////////////////////////////////////////////////////////
void ElementContainer ::
Formatter2(
  const std::vector<Double> *rx, const std::vector<Double> *&ry,
  const std::vector<Double> *&re) {

  // references to vectors in myself
  std::vector<Double> &lx = M.ref(PutXKey());
  std::vector<Double> &ly = M.ref(PutYKey());
  std::vector<Double> &le = M.ref(PutEKey());
  DoubleBinArrange *a = NULL;

  if (lx.size() > (*rx).size() ) {
    // rebin myself
    a = new DoubleBinArrange( (UInt4)(ly.size()), (UInt4)((*ry).size()) );
    // rivised by T.Ito & Y.Inamura (2009.12.21)

    a -> SetHist(lx, ly, le, *rx);
    //a -> Averaging();
    a -> Binning();
    lx = a -> PutResultBinVector();
    ly = a -> PutResultValue();
    le = a -> PutResultError();

  } else if (Compare(lx, *rx) == false ) {
    // lx.size() > rx.size() or size is equal but bins are not identical
    // rebin'ed vectors are generated
        a = new DoubleBinArrange( (UInt4)((*ry).size()), (UInt4)(ly.size()) );
    a -> SetHist( *rx, *ry, *re, lx );
    //a -> Averaging();
    a -> Binning();
    ry = new std::vector<Double> (a -> PutResultValue());
    re = new std::vector<Double> (a -> PutResultError());
  }
  delete a;
}

/**********************************************
 *** 3. operators, +, -, *, /               ***
 **********************************************/

////////////////////////////////////////////////////////
bool ElementContainer::
IsMaskData( std::vector<Double> &v, const std::vector<Double> *vp ){

  for( UInt4 i=0; i<v.size(); i++ ){
    if( v[i] < 0.0 ){ return true; }
  }
  for( UInt4 i=0; i<vp->size(); i++ ){
    if( (*vp)[i] < 0.0 ){ return true; }
  }
  return false;
}
////////////////////////////////////////////////////////
ElementContainer &ElementContainer ::
MaskedPlus(const ElementContainer &r )
{
  std::vector<Double> *lex = M( PutXKey() );
  std::vector<Double> *ley = M( PutYKey() );
  std::vector<Double> *lee = M( PutEKey() );

  // pointers to vectors in r or new rebin'ed vectors
  const std::vector<Double> *rex = &r.M.ref(r.PutXKey());
  const std::vector<Double> *rey = &r.M.ref(r.PutYKey());
  const std::vector<Double> *ree = &r.M.ref(r.PutEKey());

  std::vector<Double> v0y;
  std::vector<Double> v0e;
  std::vector<Double> v1y;
  std::vector<Double> v1e;


  std::vector<Double> *x = new std::vector<Double>();
  DoubleBinArrange *dba0 = NULL;
  DoubleBinArrange *dba1 = NULL;

  if( lex->size() <= rex->size() ){

    //x = lex;
    for( UInt4 i=0; i<lex->size(); i++ ){ x->push_back( (*lex)[i]); }

    v0y = *ley;
    v0e = *lee;

    dba1 = new DoubleBinArrange( (UInt4)(rex->size())-1, (UInt4)(x->size())-1 );
    dba1 -> SetHist( *rex, *rey, *ree, *x );
    dba1 -> Binning( -1 );
    v1y = dba1->PutResultValue();
    v1e = dba1->PutResultError();

  }
  else{
    //x = rex;
    for( UInt4 i=0; i<rex->size(); i++ ){ x->push_back( (*rex)[i]); }
    v1y = *rey;
    v1e = *ree;

    dba0 = new DoubleBinArrange( (UInt4)(lex->size())-1, (UInt4)(x->size())-1 );
    dba0 -> SetHist( *lex, *ley, *lee, *x );
    dba0 -> Binning( -1 );
    v0y = dba0->PutResultValue();
    v0e = dba0->PutResultError();
  }

  std::vector<Double> *y = new std::vector<Double>( x->size()-1 );
  std::vector<Double> *e = new std::vector<Double>( x->size()-1 );

  for( UInt4 i=0; i<y->size(); i++ ){
    if( v0e[i] < 0.0 && v1e[i] >= 0.0 ){
      (*y)[i] = v1y[i];
      (*e)[i] = -1.0;
    }
    else if( v1e[i] < 0.0 && v0e[i] >= 0.0 ){
      (*y)[i] = v0y[i];
      (*e)[i] = -1.0;
    }
    else if( v1e[i] < 0.0 && v0e[i] < 0.0){
      (*y)[i] =  v0y[i] + v1y[i];
      (*e)[i] = -1.0;
    }
    else{
      (*y)[i] = v0y[i] + v1y[i];
      (*e)[i] = sqrt( v0e[i]*v0e[i] + v1e[i]*v1e[i] );
    }
  }

  std::string xkey = PutXKey();
  std::string ykey = PutYKey();
  std::string ekey = PutEKey();
  Replace( xkey, *x );
  Replace( ykey, *y );
  Replace( ekey, *e );
  SetKeys( xkey, ykey, ekey );

  delete dba0;
  delete dba1;
  delete x;
  delete y;
  delete e;
  return *this;
}
////////////////////////////////////////////////////////
ElementContainer &ElementContainer ::
MaskedSub(const ElementContainer &r )
{
  std::vector<Double> *lex = M( PutXKey() );
  std::vector<Double> *ley = M( PutYKey() );
  std::vector<Double> *lee = M( PutEKey() );

  // pointers to vectors in r or new rebin'ed vectors
  const std::vector<Double> *rex = &r.M.ref(r.PutXKey());
  const std::vector<Double> *rey = &r.M.ref(r.PutYKey());
  const std::vector<Double> *ree = &r.M.ref(r.PutEKey());

  std::vector<Double> v0y;
  std::vector<Double> v0e;
  std::vector<Double> v1y;
  std::vector<Double> v1e;


  std::vector<Double> *x = new std::vector<Double>();
  DoubleBinArrange *dba0 = NULL;
  DoubleBinArrange *dba1 = NULL;

  if( lex->size() <= rex->size() ){

    //x = lex;
    for( UInt4 i=0; i<lex->size(); i++ ){ x->push_back( (*lex)[i]); }

    v0y = *ley;
    v0e = *lee;

    dba1 = new DoubleBinArrange( (UInt4)(rex->size())-1, (UInt4)(x->size())-1 );
    dba1 -> SetHist( *rex, *rey, *ree, *x );
    dba1 -> Binning( -1 );
    v1y = dba1->PutResultValue();
    v1e = dba1->PutResultError();

  }
  else{
    //x = rex;
    for( UInt4 i=0; i<rex->size(); i++ ){ x->push_back( (*rex)[i]); }
    v1y = *rey;
    v1e = *ree;

    dba0 = new DoubleBinArrange( (UInt4)(lex->size())-1, (UInt4)(x->size())-1 );
    dba0 -> SetHist( *lex, *ley, *lee, *x );
    dba0 -> Binning( -1 );
    v0y = dba0->PutResultValue();
    v0e = dba0->PutResultError();
  }

  std::vector<Double> *y = new std::vector<Double>( x->size()-1 );
  std::vector<Double> *e = new std::vector<Double>( x->size()-1 );

  for( UInt4 i=0; i<y->size(); i++ ){
    if( v0e[i] < 0.0 && v1e[i] >= 0.0 ){
      (*y)[i] = -v1y[i];
      (*e)[i] = -1.0;
    }
    else if( v1e[i] < 0.0 && v0e[i] >= 0.0 ){
      (*y)[i] = v0y[i];
      (*e)[i] = -1.0;
    }
    else if( v1e[i] < 0.0 && v0e[i] < 0.0){
      (*y)[i] =  v0y[i] - v1y[i];
      (*e)[i] = -1.0;
    }
    else{
      (*y)[i] = v0y[i] - v1y[i];
      (*e)[i] = sqrt( v0e[i]*v0e[i] + v1e[i]*v1e[i] );
    }
  }

  std::string xkey = PutXKey();
  std::string ykey = PutYKey();
  std::string ekey = PutEKey();
  Replace( xkey, *x );
  Replace( ykey, *y );
  Replace( ekey, *e );
  SetKeys( xkey, ykey, ekey );

  delete dba0;
  delete dba1;
  delete x;
  delete y;
  delete e;
  return *this;
}
////////////////////////////////////////////////////////
ElementContainer &ElementContainer ::
MaskedMul(const ElementContainer &r )
{
  std::vector<Double> *lex = M( PutXKey() );
  std::vector<Double> *ley = M( PutYKey() );
  std::vector<Double> *lee = M( PutEKey() );

  // pointers to vectors in r or new rebin'ed vectors
  const std::vector<Double> *rex = &r.M.ref(r.PutXKey());
  const std::vector<Double> *rey = &r.M.ref(r.PutYKey());
  const std::vector<Double> *ree = &r.M.ref(r.PutEKey());

  std::vector<Double> v0y;
  std::vector<Double> v0e;
  std::vector<Double> v1y;
  std::vector<Double> v1e;


  std::vector<Double> *x = new std::vector<Double>();
  DoubleBinArrange *dba0 = NULL;
  DoubleBinArrange *dba1 = NULL;

  if( lex->size() <= rex->size() ){

    //x = lex;
    for( UInt4 i=0; i<lex->size(); i++ ){ x->push_back( (*lex)[i]); }

    v0y = *ley;
    v0e = *lee;

    dba1 = new DoubleBinArrange( (UInt4)(rex->size())-1, (UInt4)(x->size())-1 );
    dba1 -> SetHist( *rex, *rey, *ree, *x );
    dba1 -> Binning( -1 );
    v1y = dba1->PutResultValue();
    v1e = dba1->PutResultError();

  }
  else{
    //x = rex;
    for( UInt4 i=0; i<rex->size(); i++ ){ x->push_back( (*rex)[i]); }
    v1y = *rey;
    v1e = *ree;

    dba0 = new DoubleBinArrange( (UInt4)(lex->size())-1, (UInt4)(x->size())-1 );
    dba0 -> SetHist( *lex, *ley, *lee, *x );
    dba0 -> Binning( -1 );
    v0y = dba0->PutResultValue();
    v0e = dba0->PutResultError();
  }

  std::vector<Double> *y = new std::vector<Double>( x->size()-1 );
  std::vector<Double> *e = new std::vector<Double>( x->size()-1 );

  for( UInt4 i=0; i<y->size(); i++ ){
    if( v0e[i] < 0.0 && v1e[i] >= 0.0 ){
      (*y)[i] = v1y[i];
      (*e)[i] = -1.0;
    }
    else if( v1e[i] < 0.0 && v0e[i] >= 0.0 ){
      (*y)[i] = v0y[i];
      (*e)[i] = -1.0;
    }
    else if( v1e[i] < 0.0 && v0e[i] < 0.0){
      (*y)[i] =  v0y[i] * v1y[i];
      (*e)[i] = -1.0;
    }
    else{
      (*y)[i] = v0y[i] * v1y[i];
      (*e)[i] = sqrt( v1y[i]*v0e[i]*v1y[i]*v0e[i] + v0y[i]*v1e[i]*v0y[i]*v1e[i] );
    }
  }

  std::string xkey = PutXKey();
  std::string ykey = PutYKey();
  std::string ekey = PutEKey();
  Replace( xkey, *x );
  Replace( ykey, *y );
  Replace( ekey, *e );
  SetKeys( xkey, ykey, ekey );

  delete dba0;
  delete dba1;
  delete x;
  delete y;
  delete e;
  return *this;
}
////////////////////////////////////////////////////////
ElementContainer &ElementContainer ::
MaskedDiv(const ElementContainer &r )
{
  std::vector<Double> *lex = M( PutXKey() );
  std::vector<Double> *ley = M( PutYKey() );
  std::vector<Double> *lee = M( PutEKey() );

  // pointers to vectors in r or new rebin'ed vectors
  const std::vector<Double> *rex = &r.M.ref(r.PutXKey());
  const std::vector<Double> *rey = &r.M.ref(r.PutYKey());
  const std::vector<Double> *ree = &r.M.ref(r.PutEKey());

  std::vector<Double> v0y;
  std::vector<Double> v0e;
  std::vector<Double> v1y;
  std::vector<Double> v1e;


  std::vector<Double> *x = new std::vector<Double>();
  DoubleBinArrange *dba0 = NULL;
  DoubleBinArrange *dba1 = NULL;

  if( lex->size() <= rex->size() ){

    //x = lex;
    for( UInt4 i=0; i<lex->size(); i++ ){ x->push_back( (*lex)[i]); }

    v0y = *ley;
    v0e = *lee;

    dba1 = new DoubleBinArrange( (UInt4)(rex->size())-1, (UInt4)(x->size())-1 );
    dba1 -> SetHist( *rex, *rey, *ree, *x );
    dba1 -> Binning( -1 );
    v1y = dba1->PutResultValue();
    v1e = dba1->PutResultError();

  }
  else{
    //x = rex;
    for( UInt4 i=0; i<rex->size(); i++ ){ x->push_back( (*rex)[i]); }
    v1y = *rey;
    v1e = *ree;

    dba0 = new DoubleBinArrange( (UInt4)(lex->size())-1, (UInt4)(x->size())-1 );
    dba0 -> SetHist( *lex, *ley, *lee, *x );
    dba0 -> Binning( -1 );
    v0y = dba0->PutResultValue();
    v0e = dba0->PutResultError();
  }

  std::vector<Double> *y = new std::vector<Double>( x->size()-1 );
  std::vector<Double> *e = new std::vector<Double>( x->size()-1 );

  for( UInt4 i=0; i<y->size(); i++ ){

    if( v1y[i] == 0.0 ){
      (*y)[i] =  0.0;
      (*e)[i] = -1.0;
    }
    else if( v0e[i] < 0.0 && v1e[i] >= 0.0 ){
      (*y)[i] = v0y[i] / v1y[i];
      (*e)[i] = -1.0;
    }
    else if( v1e[i] < 0.0 && v0e[i] >= 0.0 ){
      (*y)[i] = v0y[i] / v1y[i];
      (*e)[i] = -1.0;
    }
    else if( v1e[i] < 0.0 && v0e[i] < 0.0){
      (*y)[i] =  v0y[i] / v1y[i];
      (*e)[i] = -1.0;
    }
    else{
      (*y)[i] = v0y[i] / v1y[i];
      (*e)[i] = sqrt( v1y[i]*v0e[i]*v1y[i]*v0e[i] + v0y[i]*v1e[i]*v0y[i]*v1e[i] ) / (v1y[i]*v1y[i]);
    }
  }

  std::string xkey = PutXKey();
  std::string ykey = PutYKey();
  std::string ekey = PutEKey();
  Replace( xkey, *x );
  Replace( ykey, *y );
  Replace( ekey, *e );
  SetKeys( xkey, ykey, ekey );

  delete dba0;
  delete dba1;
  delete x;
  delete y;
  delete e;
  return *this;
}
////////////////////////////////////////////////////////
ElementContainer &ElementContainer ::
operator+=(const ElementContainer &r )
{
  // references to vectors in myself
  std::vector<Double> &lx = M.ref(PutXKey());
  std::vector<Double> &ly = M.ref(PutYKey());
  std::vector<Double> &le = M.ref(PutEKey());

  // pointers to vectors in r or new rebin'ed vectors
  const std::vector<Double> *rx = &r.M.ref(r.PutXKey());
  const std::vector<Double> *ry = &r.M.ref(r.PutYKey());
  const std::vector<Double> *re = &r.M.ref(r.PutEKey());

  /*
  if( IsMaskData( le, re ) == true ){
    return MaskedPlus( r );
  }
  */

  if( // if dispersed type data
     ( lx. size() == ly. size() ) &&
     ( lx. size() == le. size() ) &&
     ( rx->size() == ry->size() ) &&
     ( rx->size() == re->size() ) &&
     ( lx. size() == rx->size() )
      ){
    UInt4 size = (UInt4)(lx.size());
    for( UInt4 i=0; i<size; i++ ){
      ly[i] = ly[i] + (*ry)[i];
      le[i] = sqrt( (*re)[i]*(*re)[i] + le[i]*le[i] );
    }
    std::string NewYUnit = ReArrangeUnit( PutUnit( Ykey ), "+", r.PutUnit( r.PutYKey() ) );
    std::string NewEUnit = ReArrangeUnit( PutUnit( Ekey ), "+", r.PutUnit( r.PutEKey() ) );
    ReSetUnit(PutYKey(), NewYUnit);
    ReSetUnit(PutEKey(), NewEUnit);
  }
  else if(
      ( lx. size() == ly. size()+1 ) &&
      ( lx. size() == le. size()+1 ) &&
      ( rx->size() == ry->size()+1 ) &&
      ( rx->size() == re->size()+1 ) )
  { // if histogram type data

    std::vector<Double> *NewBin = NULL; // for calculation result
    std::vector<Double> NewLy;
    std::vector<Double> NewLe;
    std::vector<Double> NewRy;
    std::vector<Double> NewRe;

    BinConverter *bc = NULL;

    if( Compare( lx, *rx ) == true ){
      // when both bins are same, do not convert bin
      NewBin = new std::vector<Double>( rx->size() );
      for( int i=0; i<rx->size(); i++ ){ (*NewBin)[i] = (*rx)[i]; }
      NewLy = ly;
      NewLe = le;
      NewRy = *ry;
      NewRe = *re;

    }

    else{
      // when bins are different, do covert bins
      bc = new BinConverter( lx, ly, le, rx, ry, re );
      // delete bc; cause the error when NewLy etc are used.

      if( bc -> prepare() == -1 ){
        std::cout << "Bin Conversion error!!" << std::endl;
        return *this;
      }
      NewBin = bc -> NewBin; // for results
      NewLy = bc -> al->PutResultValue();
      NewLe = bc -> al->PutResultError();
      NewRy = bc -> ar->PutResultValue();
      NewRe = bc -> ar->PutResultError();
    }

    std::vector<Double> y; // for y results
    std::vector<Double> e; // for e results

    for( UInt4 i=0; i<NewBin->size()-1; i++ ){

      y.push_back( NewLy[i] + NewRy[i] );
      double err = sqrt( NewRe[i]*NewRe[i] + NewLe[i]*NewLe[i] );

      if( NewRe[i] < 0.0 || NewLe[i] < 0.0 ){
        e.push_back( -1.0 * err );
      }
      else{
        e.push_back( err );
      }
    }

    // remake ElementContainer
    std::string _xkey = PutXKey();
    std::string _ykey = PutYKey();
    std::string _ekey = PutEKey();

    std::string _x_unit(PutUnit( Xkey ));
    std::string NewYUnit( ReArrangeUnit(PutUnit( Ykey ), "+", r.PutUnit( r.PutYKey() )) );
    std::string NewEUnit( ReArrangeUnit(PutUnit( Ekey ), "+", r.PutUnit( r.PutEKey() )) );

    Remove( _xkey );
    Remove( _ykey );
    Remove( _ekey );

    Add( _xkey, *NewBin, _x_unit );
    Add( _ykey, y, NewYUnit );
    Add( _ekey, e, NewEUnit );
    SetKeys( _xkey, _ykey, _ekey );
    //

    if( bc != NULL ){
      delete bc;
    }
      //delete NewBin;
  }
  else{
    std::cout << "operation failed" << std::endl;
  }

  return *this;
}

////////////////////////////////////////////////////////
ElementContainer &ElementContainer ::
operator+=(const std::pair<Double, Double> &r )
{
  // references to vectors in myself
  std::vector<Double> &ly = M.ref(PutYKey());
  std::vector<Double> &le = M.ref(PutEKey());

  UInt4 size = (UInt4)(le . size());
  for( UInt4 i=0; i<size; i++ ) ly[i] += r.first;

  double r2 = r.second*r.second;
  for( UInt4 i=0; i<size; i++ ) le[i] *= le[i];
  for( UInt4 i=0; i<size; i++ ) le[i] += r2;
  for( UInt4 i=0; i<size; i++ ) le[i] = sqrt(le[i]);

  return *this;
}

////////////////////////////////////////////////////////
ElementContainer &ElementContainer ::
operator-=(const ElementContainer &r )
{
  // references to vectors in myself
  std::vector<Double> &lx = M.ref(PutXKey());
  std::vector<Double> &ly = M.ref(PutYKey());
  std::vector<Double> &le = M.ref(PutEKey());

  // pointers to vectors in r or new rebin'ed vectors
  const std::vector<Double> *rx = &r.M.ref(r.PutXKey());
  const std::vector<Double> *ry = &r.M.ref(r.PutYKey());
  const std::vector<Double> *re = &r.M.ref(r.PutEKey());

  /*
  if( IsMaskData( le, re ) == true ){
    return MaskedSub( r );
  }
  */
  if( // if dispersed type data
     ( lx. size() == ly. size() ) &&
     ( lx. size() == le. size() ) &&
     ( rx->size() == ry->size() ) &&
     ( rx->size() == re->size() ) &&
     ( lx. size() == rx->size() )
      ){
    UInt4 size = (UInt4)(lx.size());
    for( UInt4 i=0; i<size; i++ ){
      ly[i] = ly[i] - (*ry)[i];
      le[i] = sqrt( (*re)[i]*(*re)[i] + le[i]*le[i] );
    }
    std::string NewYUnit = ReArrangeUnit( PutUnit( Ykey ), "-", r.PutUnit( r.PutYKey() ) );
    std::string NewEUnit = ReArrangeUnit( PutUnit( Ekey ), "-", r.PutUnit( r.PutEKey() ) );
    ReSetUnit(PutYKey(), NewYUnit);
    ReSetUnit(PutEKey(), NewEUnit);
  }
  else if(
        ( lx. size() == ly. size()+1 ) &&
        ( lx. size() == le. size()+1 ) &&
        ( rx->size() == ry->size()+1 ) &&
        ( rx->size() == re->size()+1 ) )
  { // if histogram type data


    std::vector<Double> *NewBin = NULL; // for calculation result
    std::vector<Double> NewLy;
    std::vector<Double> NewLe;
    std::vector<Double> NewRy;
    std::vector<Double> NewRe;

    BinConverter *bc = NULL;

    if( Compare( lx, *rx ) == true ){
      // when both bins are same, do not convert bin
      NewBin = new std::vector<Double>( rx->size() );
      for( int i=0; i<rx->size(); i++ ){ (*NewBin)[i] = (*rx)[i]; }
      NewLy = ly;
      NewLe = le;
      NewRy = *ry;
      NewRe = *re;
    }

    else{
      // when bins are different, do convert bins
      bc = new BinConverter( lx, ly, le, rx, ry, re );
      // delete bc; cause the error when NewLy etc are used.

      if( bc -> prepare() == -1 ){
        std::cout << "Bin Conversion error!!" << std::endl;
        return *this;
      }
      NewBin = bc -> NewBin; // for results
      NewLy = bc -> al->PutResultValue();
      NewLe = bc -> al->PutResultError();
      NewRy = bc -> ar->PutResultValue();
      NewRe = bc -> ar->PutResultError();
    }

    std::vector<Double> y; // for y results
    std::vector<Double> e; // for e results

    for( UInt4 i=0; i<NewBin->size()-1; i++ ){
      y.push_back( NewLy[i] - NewRy[i] );
      double err = sqrt( NewRe[i]*NewRe[i] + NewLe[i]*NewLe[i] );

      if( NewRe[i] < 0.0 || NewLe[i] < 0.0 ){
        e.push_back( -1.0 * err );
      }
      else{
        e.push_back( err );
      }

    }

    // remake ElementContainer
    std::string _xkey = PutXKey();
    std::string _ykey = PutYKey();
    std::string _ekey = PutEKey();

    std::string _x_unit(PutUnit( Xkey ));
    std::string NewYUnit( ReArrangeUnit(PutUnit( Ykey ), "+", r.PutUnit( r.PutYKey() )) );
    std::string NewEUnit( ReArrangeUnit(PutUnit( Ekey ), "+", r.PutUnit( r.PutEKey() )) );

    Remove( _xkey );
    Remove( _ykey );
    Remove( _ekey );
    Add( _xkey, *NewBin, _x_unit );
    Add( _ykey, y, NewYUnit );
    Add( _ekey, e, NewEUnit );
    SetKeys( _xkey, _ykey, _ekey );
    //

    if( bc != NULL ){
      delete bc;
    }


  }
  else{
    std::cout << "operation failed" << std::endl;
  }

  return *this;
}

////////////////////////////////////////////////////////
ElementContainer &ElementContainer ::
operator-=(const std::pair<Double, Double> &r )
{
  // references to vectors in myself
  std::vector<Double> &ly = M.ref(PutYKey());
  std::vector<Double> &le = M.ref(PutEKey());

  UInt4 size = (UInt4)(le . size());
  for( UInt4 i=0; i<size; i++ ) ly[i] -= r.first;

  double r2 = r.second*r.second;
  for( UInt4 i=0; i<size; i++ ) le[i] *= le[i];
  for( UInt4 i=0; i<size; i++ ) le[i] += r2;
  for( UInt4 i=0; i<size; i++ ) le[i] = sqrt(le[i]);

  return *this;
}

////////////////////////////////////////////////////////
ElementContainer &ElementContainer ::
operator*=(const ElementContainer &r )
{
  // references to vectors in myself
  std::vector<Double> &lx = M.ref(PutXKey());
  std::vector<Double> &ly = M.ref(PutYKey());
  std::vector<Double> &le = M.ref(PutEKey());

  // pointers to vectors in r or new rebin'ed vectors
  const std::vector<Double> *rx = &r.M.ref(r.PutXKey());
  const std::vector<Double> *ry = &r.M.ref(r.PutYKey());
  const std::vector<Double> *re = &r.M.ref(r.PutEKey());

  /*
  if( IsMaskData( le, re ) == true ){
    return MaskedMul( r );
  }
  */

  if( // if dispersed type data
     ( lx. size() == ly. size() ) &&
     ( lx. size() == le. size() ) &&
     ( rx->size() == ry->size() ) &&
     ( rx->size() == re->size() ) &&
     ( lx. size() == rx->size() ))
  {
    UInt4 size = (UInt4)(lx.size());
    for( UInt4 i=0; i<size; i++ ){
      double r0 = (*re)[i]*ly[i];
      double r1=le[i]*(*ry)[i];
      le[i] = sqrt( r0*r0 + r1*r1 );
      ly[i] = ly[i] * (*ry)[i];
    }
    std::string NewYUnit = ReArrangeUnit( PutUnit( Ykey ), "*", r.PutUnit( r.PutYKey() ) );
    std::string NewEUnit = ReArrangeUnit( PutUnit( Ekey ), "*", r.PutUnit( r.PutEKey() ) );
    ReSetUnit(PutYKey(), NewYUnit);
    ReSetUnit(PutEKey(), NewEUnit);
  }
  else if(
          ( lx. size() == ly. size()+1 ) &&
          ( lx. size() == le. size()+1 ) &&
          ( rx->size() == ry->size()+1 ) &&
          ( rx->size() == re->size()+1 ) )
  { // if histogram type data

    std::vector<Double> *NewBin = NULL; // for calculation result
    std::vector<Double> NewLy;
    std::vector<Double> NewLe;
    std::vector<Double> NewRy;
    std::vector<Double> NewRe;

    BinConverter *bc = NULL;

    if( Compare( lx, *rx ) == true ){
      // when both bins are same, do not convert bin
      NewBin = new std::vector<Double>( rx->size() );
      for( int i=0; i<rx->size(); i++ ){ (*NewBin)[i] = (*rx)[i]; }
      NewLy = ly;
      NewLe = le;
      NewRy = *ry;
      NewRe = *re;
    }

    else{
      // when bins are different, do convert bins
      bc = new BinConverter( lx, ly, le, rx, ry, re );
      // delete bc; cause the error when NewLy etc are used.

      if( bc -> prepare() == -1 ){
        std::cout << "Bin Conversion error!!" << std::endl;
        return *this;
      }
      NewBin = bc -> NewBin; // for results
      NewLy = bc -> al->PutResultValue();
      NewLe = bc -> al->PutResultError();
      NewRy = bc -> ar->PutResultValue();
      NewRe = bc -> ar->PutResultError();
    }

    std::vector<Double> y; // for y results
    std::vector<Double> e; // for e results

    for( UInt4 i=0; i<NewBin->size()-1; i++ ){
      y.push_back( NewLy[i] * NewRy[i] );
      double err = sqrt( ( NewLy[i]*NewRe[i] )*( NewLy[i]*NewRe[i] ) +
                         ( NewRy[i]*NewLe[i] )*( NewRy[i]*NewLe[i] ) );

      if( NewRe[i] < 0.0 || NewLe[i] < 0.0 ){
        e.push_back( -1.0 * err );
      }
      else{
        e.push_back( err );
      }

    }

    // remake ElementContainer
    std::string _xkey = PutXKey();
    std::string _ykey = PutYKey();
    std::string _ekey = PutEKey();

    std::string _x_unit(PutUnit( Xkey ));
    std::string NewYUnit( ReArrangeUnit(PutUnit( Ykey ), "+", r.PutUnit( r.PutYKey() )) );
    std::string NewEUnit( ReArrangeUnit(PutUnit( Ekey ), "+", r.PutUnit( r.PutEKey() )) );

    Remove( _xkey );
    Remove( _ykey );
    Remove( _ekey );
    Add( _xkey, *NewBin, _x_unit );
    Add( _ykey, y, NewYUnit );
    Add( _ekey, e, NewEUnit );
    SetKeys( _xkey, _ykey, _ekey );
    //

    if( bc != NULL ){
      delete bc;
    }


  }
  else{
    std::cout << "operation failed" << std::endl;
  }

  return *this;
}

////////////////////////////////////////////////////////
ElementContainer &ElementContainer ::
operator*=(const std::pair<Double, Double> &r )
{
  // references to vectors in myself
  std::vector<Double> &ly = M.ref(PutYKey());
  std::vector<Double> &le = M.ref(PutEKey());

  UInt4 size = (UInt4)(le . size());

  for( UInt4 i=0; i<size; i++ ){
    double r0 = r.second*ly[i];
    double r1=le[i]*r.first;
    le[i] = sqrt( r0*r0 + r1*r1 );
  }
  for( UInt4 i=0; i<size; i++ ){
    ly[i] *= r.first;
  }
  return *this;
}

////////////////////////////////////////////////////////
ElementContainer &ElementContainer ::
operator/=(const ElementContainer &r )
{
  // references to vectors in myself
  std::vector<Double> &lx = M.ref(PutXKey());
  std::vector<Double> &ly = M.ref(PutYKey());
  std::vector<Double> &le = M.ref(PutEKey());

  // pointers to vectors in r or new rebin'ed vectors
  const std::vector<Double> *rx = &r.M.ref(r.PutXKey());
  const std::vector<Double> *ry = &r.M.ref(r.PutYKey());
  const std::vector<Double> *re = &r.M.ref(r.PutEKey());

  /*
  if( IsMaskData( le, re ) == true ){
    return MaskedDiv( r );
  }
  */

  if( // if dispersed type data
     ( lx. size() == ly. size() ) &&
     ( lx. size() == le. size() ) &&
     ( rx->size() == ry->size() ) &&
     ( rx->size() == re->size() ) &&
     ( lx. size() == rx->size() ))
  {
    UInt4 size = (UInt4)(lx.size());
    for( UInt4 i=0; i<size; i++ ){
      if( (*ry)[i] == 0.0 ){
        ly[i] = 0.0;
        le[i]  = 1.0;
      }
      else {
        double r0 = (*re)[i]*ly[i];
        double r1 = le[i]*(*ry)[i];
        le[i] = sqrt( r0*r0 + r1*r1 ) / ((*ry)[i]*(*ry)[i]);
        ly[i] = ly[i] / (*ry)[i];
      }
    }
    std::string NewYUnit = ReArrangeUnit( PutUnit( Ykey ), "/", r.PutUnit( r.PutYKey() ) );
    std::string NewEUnit = ReArrangeUnit( PutUnit( Ekey ), "/", r.PutUnit( r.PutEKey() ) );
    ReSetUnit(PutYKey(), NewYUnit);
    ReSetUnit(PutEKey(), NewEUnit);
  }
  else if(
          ( lx. size() == ly. size()+1 ) &&
          ( lx. size() == le. size()+1 ) &&
          ( rx->size() == ry->size()+1 ) &&
          ( rx->size() == re->size()+1 ) )
  { // if histogram type data
    std::vector<Double> *NewBin = NULL; // for calculation result
    std::vector<Double> NewLy;
    std::vector<Double> NewLe;
    std::vector<Double> NewRy;
    std::vector<Double> NewRe;

    BinConverter *bc = NULL;

    if( Compare( lx, *rx ) == true ){
      // when both bins are same, do not convert bin
      NewBin = new std::vector<Double>( rx->size() );
      for( int i=0; i<rx->size(); i++ ){ (*NewBin)[i] = (*rx)[i]; }
      NewLy = ly;
      NewLe = le;
      NewRy = *ry;
      NewRe = *re;
    }

    else{
      // when bins are different, do covert bins
      bc = new BinConverter( lx, ly, le, rx, ry, re );
      // delete bc; cause the error when NewLy etc are used.

      if( bc -> prepare() == -1 ){
        std::cout << "Bin Conversion error!!" << std::endl;
        return *this;
      }
      NewBin = bc -> NewBin; // for results
      NewLy = bc -> al->PutResultValue();
      NewLe = bc -> al->PutResultError();
      NewRy = bc -> ar->PutResultValue();
      NewRe = bc -> ar->PutResultError();
    }

    std::vector<Double> y; // for y results
    std::vector<Double> e; // for e results

    for( UInt4 i=0; i<NewBin->size()-1; i++ ){

      if( NewRy[i] == 0.0 ){
        y.push_back( 0.0 );
        e.push_back( 1.0 );
      }
      else{
        y.push_back( NewLy[i] / NewRy[i] );

        double err = ( 1.0 / NewRy[i] / NewRy[i] ) *
          sqrt( ( NewLy[i]*NewRe[i] )*( NewLy[i]*NewRe[i] ) +
                ( NewRy[i]*NewLe[i] )*( NewRy[i]*NewLe[i] ) );

        if( NewRe[i] < 0.0 || NewLe[i] < 0.0 ){
          e.push_back( -1.0 * err );
        }
        else{
          e.push_back( err );
        }
      }
    }

    // remake ElementContainer
    std::string _xkey = PutXKey();
    std::string _ykey = PutYKey();
    std::string _ekey = PutEKey();

    std::string _x_unit(PutUnit( Xkey ));
    std::string NewYUnit( ReArrangeUnit(PutUnit( Ykey ), "+", r.PutUnit( r.PutYKey() )) );
    std::string NewEUnit( ReArrangeUnit(PutUnit( Ekey ), "+", r.PutUnit( r.PutEKey() )) );

    Remove( _xkey );
    Remove( _ykey );
    Remove( _ekey );
    Add( _xkey, *NewBin, _x_unit );
    Add( _ykey, y, NewYUnit );
    Add( _ekey, e, NewEUnit );
    SetKeys( _xkey, _ykey, _ekey );
    //

    if( bc != NULL ){
      delete bc;
    }


  }
  else{
    std::cout << "operation failed" << std::endl;
  }

  return *this;
}

////////////////////////////////////////////////////////
ElementContainer &ElementContainer ::
operator/=(const std::pair<Double, Double> &r )
{
  // references to vectors in myself
  std::vector<Double> &ly = M.ref(PutYKey());
  std::vector<Double> &le = M.ref(PutEKey());

  UInt4 size = (UInt4)(le . size());


  double r2 = r.first*r.first;
  for( UInt4 i=0; i<size; i++ ){
    double r0 = r.second*ly[i];
    double r1=le[i]*r.first;
    le[i] = sqrt( r0*r0 + r1*r1 ) / r2;
  }
  for( UInt4 i=0; i<size; i++ ){
    ly[i] /= r.first;
  }

  /*
  for( UInt4 i=0; i<size; i++ ){
    ly[i] /= r.first;
  }
  double r2 = r.first*r.first;
  for( UInt4 i=0; i<size; i++ ){
    double r0 = r.second*ly[i];
    double r1=le[i]*r.first;
    le[i] = sqrt( r0*r0 + r1*r1 ) / r2;
  }
  */

  return *this;
}

/**********************************************
 *** 4. removed                             ***
 **********************************************/

/**********************************************
 *** 5. ReBin and Binning; rebinning        ***
 **********************************************/

////////////////////////////////////////////////////////
ElementContainer ElementContainer::
ReBin( const std::vector<Double> &v )
{
  if( Xkey == "None" ||
      Ykey == "None" ||
      Ekey == "None" ){
    ElementContainer tmp;
    return tmp;
  }

  std::vector<Double> ResultBin   = v;
  std::vector<Double> SourceBin   = PutX();
  std::vector<Double> SourceValue = PutY();
  std::vector<Double> SourceError = PutE();

  DoubleBinArrange *a =
    new DoubleBinArrange( (UInt4)(SourceBin.size())-1, (UInt4)(ResultBin.size())-1 );
  a -> SetHist( SourceBin, SourceValue, SourceError, ResultBin );
  a -> Binning();

  ElementContainer result;
  result . InputHeader( PutHeader() );
  result . Add( Xkey, a->PutResultBinVector(),
                UnitHeader->PutString( Xkey ) );
  result . Add( Ykey, a->PutResultValue(),
                UnitHeader->PutString( Ykey ) );
  result . Add( Ekey, a->PutResultError(),
                UnitHeader->PutString( Ekey ) );
  result . SetKeys( Xkey, Ykey, Ekey );

  delete a;
  return result;
}
////////////////////////////////////////////////////////
ElementContainer ElementContainer::
ReBin( UInt4 n ){
  return ReBin( PrepareXbin( n ) );
}
////////////////////////////////////////////////////////
ElementContainer ElementContainer::
Binning( UInt4 n ){
  return Binning( PrepareXbin( n ) );
}
////////////////////////////////////////////////////////
ElementContainer ElementContainer::
Averaging( UInt4 n ){
  return Averaging( PrepareXbin( n ) );
}
////////////////////////////////////////////////////////
ElementContainer ElementContainer::
MergeWithWeight( ElementContainer &e ){

  ElementContainer r = ElementContainer( PutHeader() );

  std::vector<Double> y0 = PutY();
  std::vector<Double> e0 = PutE();
  std::vector<Double> y1 = e.PutY();
  std::vector<Double> e1 = e.PutE();

  std::vector<Double> y  = std::vector<Double>( y0.size() );
  std::vector<Double> er = std::vector<Double>( e0.size() );

  for( UInt4 i=0; i<y0.size(); i++ ){

    double b = 1.0;
    double er0 =  e0[i];
    double er1 =  e1[i];

    if(er0 > 0.0 && er1 > 0.0){
      b = 1.0 / ( er0 * er0 ) + 1.0 / ( er1 * er1 );
      y[i]  = ( y0[i] / ( er0 * er0 ) + y1[i] / ( er1 * er1 ) ) / b;
      er[i] = 1 / sqrt( b );
      //std::cout << "y0="<<y0[i] <<", e0=" <<er0 <<", y1="<< y1[i] <<", e1="<<e1[i] <<", ry="<<y[i] <<", re="<< er[i] <<", n0" << std::endl;
    }
    else if( er0 <= 0.0 && er1 > 0){
      y[i]  = y1[i];
      er[i] = er1;
      //std::cout << "y0="<<y0[i] <<", e0=" <<er0 <<", y1="<< y1[i] <<", e1="<<e1[i] <<", ry="<<y[i] <<", re="<< er[i] <<", n1" << std::endl;
    }
    else if( er1 <= 0.0 && er0 > 0){
      y[i]  = y0[i];
      er[i] = er0;
      //std::cout << "y0="<<y0[i] <<", e0=" <<er0 <<", y1="<< y1[i] <<", e1="<<e1[i] <<", ry="<<y[i] <<", re="<< er[i] <<", n2" << std::endl;
    }
    else if( er0 <= 0.0 && er1 <= 0.0){
      y[i] = 0.0;
      er[i] = 0.0;
      //std::cout << "y0="<<y0[i] <<", e0=" <<er0 <<", y1="<< y1[i] <<", e1="<<e1[i] <<", ry="<<y[i] <<", re="<< er[i] <<", n3" << std::endl;
      if( er0 < 0.0 && er1 < 0.0){
        y[i]  = 0.0;
        er[i] = -1.0;
        //std::cout << "y0="<<y0[i] <<", e0=" <<er0 <<", y1="<< y1[i] <<", e1="<<e1[i] <<", ry="<<y[i] <<", re="<< er[i] <<", n4" << std::endl;
      }
    }
    /*else if( er0 == 0.0 && er1 == 0.0){
      y[i]  = 0.0;
      er[i] = 0.0;
      std::cout << "y0="<<y0[i] <<", e0=" <<er0 <<", y1="<< y1[i] <<", e1="<<e1[i] <<", ry="<<y[i] <<", re="<< er[i] <<", n0" << std::endl;
    }*/
    else{
      std::cout << "y0="<<y0[i] <<", e0=" <<er0 <<", y1="<< y1[i] <<", e1="<<e1[i] <<", ry="<<y[i] <<", re="<< er[i] <<", n5" << std::endl;
    }
  }

  r.Add( PutXKey(), PutX() );
  r.Add( PutYKey(), y  );
  r.Add( PutEKey(), er );
  r.SetKeys( PutXKey(), PutYKey(), PutEKey() );

  return r;
}
////////////////////////////////////////////////////////
std::vector<Double> ElementContainer::
PrepareXbin( UInt4 n ){
  std::vector<Double> v;
  std::vector<Double> x = PutX();

  UInt4 t = ( (UInt4)(x.size())-1 ) / n;
  for( UInt4 i=0; i<=t; i++ ){
    v.push_back( x[ i*n ] );
  }

  if( (x.size()-1) % n != 0 ){
    v.push_back( x[ x.size() -1 ] );
  }
  return v;
}
////////////////////////////////////////////////////////
ElementContainer ElementContainer::
Binning( const std::vector<Double> &v )
{
  return ReBin( v );
}
/*
ElementContainer ElementContainer::
Binning( const std::vector<Double> &v )
{
  if( Xkey == "None" ||
      Ykey == "None" ||
      Ekey == "None" ){
    ElementContainer tmp;
    return tmp;
  }
  std::vector<Double> ResultBin   = v;
  std::vector<Double> SourceBin   = PutX();
  std::vector<Double> SourceValue = PutY();
  std::vector<Double> SourceError = PutE();

  DoubleBinArrange *a =
    new DoubleBinArrange( SourceBin.size()-1, ResultBin.size()-1 );
  a -> SetHist( SourceBin, SourceValue, SourceError, ResultBin );
  a -> Binning();

  ElementContainer result;
  result . InputHeader( PutHeader() );
  result . Add( Xkey, a->PutResultBinVector(),
                UnitHeader->PutString( Xkey ) );
  result . Add( Ykey, a->PutResultValue(),
                UnitHeader->PutString( Ykey ) );
  result . Add( Ekey, a->PutResultError(),
                UnitHeader->PutString( Ekey ) );
  result . SetKeys( Xkey, Ykey, Ekey );

  delete a;
  return result;
}
*/
////////////////////////////////////////////////////////
ElementContainer ElementContainer::
Averaging( const std::vector<Double> &v )
{
  if( Xkey == "None" ||
      Ykey == "None" ||
      Ekey == "None" ){
    ElementContainer tmp;
    return tmp;
  }
  std::vector<Double> ResultBin   = v;
  std::vector<Double> SourceBin   = PutX();
  std::vector<Double> SourceValue = PutY();
  std::vector<Double> SourceError = PutE();

  DoubleBinArrange *a =
    new DoubleBinArrange( (UInt4)(SourceBin.size())-1, (UInt4)(ResultBin.size())-1 );
  a -> SetHist( SourceBin, SourceValue, SourceError, ResultBin );
  a -> Averaging();

  ElementContainer result;
  result . InputHeader( PutHeader() );
  result . Add( Xkey, a->PutResultBinVector(),
                UnitHeader->PutString( Xkey ) );
  result . Add( Ykey, a->PutResultValue(),
                UnitHeader->PutString( Ykey ) );
  result . Add( Ekey, a->PutResultError(),
                UnitHeader->PutString( Ekey ) );
  result . SetKeys( Xkey, Ykey, Ekey );

  delete a;
  return result;
}


/**********************************************
 *** 6. SetKeys and Dumpkey                 ***
 **********************************************/

////////////////////////////////////////////////////////
bool ElementContainer::
SetKeys( const std::string &X, const std::string &Y, const std::string &E )
{
  if( CheckKey( X ) != 1 ){
    std::cout << "ElementContainer::SetKeys(std::string,std::string,std::string)" << std::endl;
    std::cout << "The key of " << X << " cannot be found in this container." << std::endl;
    return false;
  }
  else if( CheckKey( Y ) != 1 ){
    std::cout << "ElementContainer::SetKeys(std::string,std::string,std::string)" << std::endl;
    std::cout << "The key of " << Y << " cannot be found in this container." << std::endl;
    return false;
  }
  else if( CheckKey( E ) != 1 ){
    std::cout << "ElementContainer::SetKeys(std::string,std::string,std::string)" << std::endl;
    std::cout << "The key of " << E << " cannot be found in this container." << std::endl;
    return false;
  }
  else if( PutSize( X ) <= 1 ){
    std::cout << "ElementContainer::SetKeys(std::string,std::string,std::string)" << std::endl;
    std::cout << "Because the size of the vector named as " << X
              << " is zero or one. "
              << "A histogram cannot be defined." << std::endl;
      return false;
  }
  else if( ( PutSize( X ) == PutSize( Y ) ) && ( PutSize( X ) == PutSize( E ) ) ){
    // Appended by Jiro SUZUKI, on 2011.12.14
    // Modified by Jiro SUZUKI, on 2013.01.30

    Xkey = X;
    Ykey = Y;
    Ekey = E;

    // Appended by Jiro SUZUKI, on 2016.03.14
    HistFlag = false;
    return true;

    // comment out on 2031.01.30 [start]
    /*
    std::vector<Double> * OrigX0 = (*this)( X );
    std::vector<Double> * OrigX  = new std::vector<Double>( OrigX0->size() );
    for( UInt4 i=0; i<OrigX->size(); i++ ){
      (*OrigX)[i] = (*OrigX0)[i];
    }

    std::vector<Double> * NewX  = new std::vector<Double>( OrigX->size() + 1 );
    Remove( X );

    ( *NewX )[0] = (*OrigX)[0] - ( (*OrigX)[1] - (*OrigX)[0] ) / 2.0;

    for( UInt4 i=1; i<NewX->size()-1; i++ ){
      (*NewX)[i] = ( (*OrigX)[i-1] + (*OrigX)[i] ) / 2.0;
    }

    ( *NewX )[NewX->size()-1] = (*OrigX)[NewX->size()-2] +
      ( (*OrigX)[NewX->size()-2] - (*OrigX)[NewX->size()-3] ) / 2.0;


    Add( X + "_orig", *OrigX );
    Add( X, *NewX );
    SetKeys( X, Y, E );
    return;
    */
    // comment out on 2031.01.30 [end]
  }
  else if( PutSize( X )  != PutSize( Y )+1 ){
    std::cout << "ElementContainer::SetKeys(std::string,std::string,std::string)" << std::endl;
    std::cout << "The size of Y-vector is wrong." << std::endl;
    return false;
  }
  else if( PutSize( X ) != PutSize( E )+1 ){
    std::cout << "ElementContainer::SetKeys(std::string,std::string,std::string)" << std::endl;
    std::cout << "The size of E-vector is wrong." << std::endl;
    return false;
  }
  else{
    Xkey = X;
    Ykey = Y;
    Ekey = E;

    // Appended by Jiro SUZUKI, on 2016.03.14
    HistFlag = true;
    return true;
  }
}
bool ElementContainer::
isHist(){
  return HistFlag;
}
////////////////////////////////////////////////////////
void ElementContainer::
DumpKey()
{
  //M.DumpKeyList();

  std::cout << " " << "\t" << "Key" << "\t" << "Unit" << std::endl;
  std::vector<std::string> KeyList = M.PutKeyList();
  for( UInt4 i=0; i<KeyList.size(); i++ ){
    std::cout << i << "\t"
         << KeyList[ i ] << "\t"
         << PutUnit( KeyList[ i ] ) << std::endl;
  }
}


/**********************************************
 *** 7. series of Add() method              ***
 **********************************************/

////////////////////////////////////////////////////////
void ElementContainer::
Add( const std::string &Key, std::vector< Double > value, const std::string &Unit )
{
  if( M.CheckKey( Key ) != 0 ){
    std::cout << "\"" << Key << "\" has been installed in this container." << std::endl;
    std::cout << "Please choose another Key." << std::endl;
    return;
  }

  _Add(Key, value, Unit);
}
////////////////////////////////////////////////////////
void ElementContainer::
Add( const std::string &Key, Double *&Array, UInt4 ArraySize, const std::string &Unit )
{
  if( M.CheckKey( Key ) != 0 ){
    std::cout << "\"" << Key << "\" has been installed in this container." << std::endl;
    std::cout << "Please choose another Key." << std::endl;
    return;
  }

  std::vector<Double> TmpVec( ArraySize );
  for( UInt4 i=0; i<ArraySize; i++ ){
    TmpVec[i] = Array[ i ];
  }

  _Add(Key, TmpVec, Unit);
}
////////////////////////////////////////////////////////
void ElementContainer::
Add( const std::string &Key, std::vector< Float > value, const std::string &Unit )
{
  if( M.CheckKey( Key ) != 0 ){
    std::cout << "\"" << Key << "\" has been installed in this container." << std::endl;
    std::cout << "Please choose another Key." << std::endl;
    return;
  }

  UInt4 Size = (UInt4)(value.size());
  std::vector<Double> TmpVec( Size );
  for( UInt4 i=0; i<Size; i++ ){
    TmpVec[i] = (Double)value[ i ];
  }

  _Add(Key, TmpVec, Unit);
}
///////////////////////////////////////////////////////
void ElementContainer::
Add( const std::string &Key, std::vector< UInt4 > value, const std::string &Unit )
{
  if( M.CheckKey( Key ) != 0 ){
    std::cout << "\"" << Key << "\" has been installed in this container." << std::endl;
    std::cout << "Please choose another Key." << std::endl;
    return;
  }

  UInt4 Size = (UInt4)(value.size());
  std::vector<Double> TmpVec( Size );
  for( UInt4 i=0; i<Size; i++ ){
    TmpVec[i] = (Double)value[ i ];
  }

  _Add(Key, TmpVec, Unit);
}
///////////////////////////////////////////////////////
void ElementContainer::
Add( const std::string &Key, std::vector< UInt2 > value, const std::string &Unit )
{
  if( M.CheckKey( Key ) != 0 ){
    std::cout << "\"" << Key << "\" has been installed in this container." << std::endl;
    std::cout << "Please choose another Key." << std::endl;
    return;
  }

  UInt4 Size = (UInt4)(value.size());
  std::vector<Double> TmpVec( Size );
  for( UInt4 i=0; i<Size; i++ ){
    TmpVec[i] = (Double)value[ i ];
  }

  _Add(Key, TmpVec, Unit);
}
////////////////////////////////////////////////////////
void ElementContainer::
Add( const std::string &Key, PyObject *value, const std::string &Unit )
{
  if( M.CheckKey( Key ) != 0 ){
    std::cout << "\"" << Key << "\" has been installed in this container." << std::endl;
    std::cout << "Please choose another Key." << std::endl;
    return;
  }

  std::vector< Double > TmpVec = __gCppToPython.ListToDoubleVector( value );

  if( TmpVec.size() == 0 ){
    std::cout << "ElementContainer::Add(std::string,PyObject*)" << std::endl;
    std::cout << Key << " cannnot convert into vector<Double>." << std::endl;
    std::cout << "Is the type of each element number ?" << std::endl;
  }
  else{
    _Add(Key, TmpVec, Unit);
  }
}
////////////////////////////////////////////////////////
void ElementContainer::
Add( const std::string &Key, Float *&Array, UInt4 ArraySize, const std::string &Unit )
{
  if( M.CheckKey( Key ) != 0 ){
    std::cout << "\"" << Key << "\" has been installed in this container." << std::endl;
    std::cout << "Please choose another Key." << std::endl;
    return;
  }

  std::vector<Double> TmpVec( ArraySize );
  for( UInt4 i=0; i<ArraySize; i++ ){
    TmpVec[i] = (Double)Array[ i ];
  }
  _Add(Key, TmpVec, Unit);
}
////////////////////////////////////////////////////////
void ElementContainer::
Add( const std::string &Key, UInt4 *&Array, UInt4 ArraySize, const std::string &Unit )
{
  if( M.CheckKey( Key ) != 0 ){
    std::cout << "\"" << Key << "\" has been installed in this container." << std::endl;
    std::cout << "Please choose another Key." << std::endl;
    return;
  }
  std::vector<Double> TmpVec( ArraySize );
  for( UInt4 i=0; i<ArraySize; i++ ){
    TmpVec[i] = (Double)Array[ i ];
  }
  _Add(Key, TmpVec, Unit);
}
////////////////////////////////////////////////////////
void ElementContainer::
Add( const std::string &Key, UInt2 *&Array, UInt4 ArraySize, const std::string &Unit )
{
  if( M.CheckKey( Key ) != 0 ){
    std::cout << "\"" << Key << "\" has been installed in this container." << std::endl;
    std::cout << "Please choose another Key." << std::endl;
    return;
  }

  std::vector<Double> TmpVec( ArraySize );
  for( UInt4 i=0; i<ArraySize; i++ ){
    TmpVec[i] = (Double)Array[ i ];
  }
  _Add(Key, TmpVec, Unit);
}


/**********************************************
 *** 8. InputHeader, InputUnitHeader        ***
 **********************************************/

////////////////////////////////////////////////////////
void ElementContainer::
InputHeader( const HeaderBase &Header )
{
  delete header;

  header = new HeaderBase( Header );

  return;
}
////////////////////////////////////////////////////////
void ElementContainer::
InputUnitHeader( const HeaderBase &uHeader )
{
  delete UnitHeader;

  UnitHeader = new HeaderBase( uHeader );

  std::vector<std::string> KeyList = M.PutKeyList();

  for( UInt4 i=0; i<KeyList.size(); i++ ){
    if( UnitHeader->CheckKey( KeyList[ i ] ) == 0 ){
      UnitHeader->Add( KeyList[ i ], "None" );
    }
  }
  return;
}


/**********************************************
 *** 9. Copy, AddBlankVecvot, Remove,       ***
 ***   Replace, AddValue, SetValue          ***
 **********************************************/

////////////////////////////////////////////////////////
void  ElementContainer::
Copy( const std::string &s, const std::string &x )
{
  M.Copy( s, x );
  std::string u = UnitHeader -> PutString( s );
  UnitHeader -> Add( x, u );
}
////////////////////////////////////////////////////////
void ElementContainer::
AddBlankVector( const std::string &Key, UInt4 Size, const std::string &Unit )
{
  std::vector<Double> TmpVec( Size );
  for( UInt4 i=0; i<Size; i++ ){
    TmpVec[i] = (Double)i;
  }
  M.Add( Key, TmpVec );
  UnitHeader -> Add( Key, Unit );
}
////////////////////////////////////////////////////////
void ElementContainer::
Remove( const std::string &Key )
{
  if( CheckKey( Key ) != 1 ){
    std::cout << "ElementContainer::Remove(std::string)" << std::endl;
    std::cout << Key << " is not found in this container." << std::endl;
    return;
  }
  M.Erase( Key );
  UnitHeader -> Erase( Key );

  if( Xkey == Key ||
      Ykey == Key ||
      Ekey == Key ){
    Xkey = "None";
    Ykey = "None";
    Ekey = "None";
    HistFlag = true;
  }
}
////////////////////////////////////////////////////////
void ElementContainer::
Replace( const std::string &Key, const std::vector<Double> &value )
{
  if( CheckKey( Key ) != 1 ){
    std::cout << "ElementContainer::Replace(std::string,std::vector<Double>)"
              << std::endl;
    std::cout << Key << " is not found in this container." << std::endl;
    return;
  }
  Remove( Key );
  Add( Key, value );
}
////////////////////////////////////////////////////////
void ElementContainer::
Replace( const std::string &Key, PyObject *value )
{
  if( CheckKey( Key ) != 1 ){
    std::cout << "ElementContainer::Replace(std::string,std::vector<Double>)"
              << std::endl;
    std::cout << Key << " is not found in this container." << std::endl;
    return;
  }
  Remove( Key );
  Add( Key, value );
}
////////////////////////////////////////////////////////
void ElementContainer::
AppendValue( const std::string &Key, const std::vector<Double> &value )
{
  if( CheckKey( Key ) != 1 ){
    std::cout << "ElementContainer::AppendValue(std::string,std::vector<Double>)"
              << std::endl;
    std::cout << Key << " is not found in this container." << std::endl;
    return;
  }
  std::vector<Double> *TmpVec = M( Key );
  UInt4 Size = (UInt4)(value.size());
  for( UInt4 i=0; i<Size; i++ ){
    TmpVec->push_back( value[ i ] );
  }
}
////////////////////////////////////////////////////////
void ElementContainer::
SetValue( const std::string &Key, UInt4 Number, Double value )
{
  if( CheckKey( Key ) != 1 ){
    std::cout << "ElementContainer::SetValue(std::string,UInt4, Double)"
              << std::endl;
    std::cout << Key << " is not found in this container." << std::endl;
    return;
  }
  std::vector< Double > *vec = M( Key );

  if( Number >= vec->size() ){
    std::cout << "ElementContainer::SetValue(std::string,UInt4,Double)" << std::endl;
    std::cout << "The value of \"Number\" is too large to set the value." << std::endl;
    return;
  }

  ( *vec )[Number] = value;
}


/**********************************************
 *** 10. series of Dump, DumpValue          ***
 **********************************************/

////////////////////////////////////////////////////////
void ElementContainer::
Dump()
{
  std::cout << "*** header object start" << std::endl;
  header -> Dump();
  std::cout << "*** header object end"   << std::endl;
  std::cout << std::endl;

  UInt4 TableSize = PutTableSize();
  std::cout << "The number of vectors is ";
  std::cout << TableSize << std::endl;
  std::cout << std::endl;

  std::cout << "x key = "
            << Xkey << std::endl;
  std::cout << "y key = "
            << Ykey << std::endl;
  std::cout << "e key = "
            << Ekey << std::endl;
  std::cout << std::endl;


  std::cout << "Index"  << "\t"
            << "Key"    << "\t"
            << "Size"   << "\t"
            << "Unit"   << "\t"
            << "Values" << std::endl;
  DumpValue();
}
////////////////////////////////////////////////////////
PyObject* ElementContainer::
PyDump(){
  std::vector<std::string> vs;
  vs.clear();
  std::string s;


  // start procedure for HeaderBase
  s = "*** header object start";
  vs.push_back( s );
  PyObject *hpo = header -> PyDump();
  CppToPython *hcp = new CppToPython();
  std::vector<std::string> hvs = hcp -> ListToStringVector( hpo );
  delete hcp;
  for( UInt4 i=0; i<hvs.size(); i++ ){
    vs.push_back( hvs[ i ] );
  }
  s = "*** header object end";
  vs.push_back( s );
  // end procedure for HeaderBase


  StringTools *st = new StringTools();

  UInt4 TableSize = PutTableSize();
  s = "The number of vectors is ";
  s = s + st->UInt4ToString( TableSize );
  vs.push_back( s );

  s = "x key = " + Xkey + ", y key = " + Ykey + ", e key = " + Ekey;
  vs.push_back( s );

  s = "Index" + std::string( "\t" ) +
      "Key"   + std::string( "\t" ) +
      "Size"  + std::string( "\t" ) +
      "Unit"  + std::string( "\t" ) +
      "Values";
  vs.push_back( s );

  for( UInt4 t=0; t<TableSize; t++ ){
    std::string key   = PutName( t );
    std::string depth = st->UInt4ToString( PutSize( t ) );
    std::string unit  = UnitHeader->PutString( key );

    s = st->UInt4ToString( t ) + std::string( "\t" ) +
        key   + std::string( "\t" ) +
        depth + std::string( "\t" ) +
        unit  + std::string( "\t" );

    if( PutSize(t) >= 1){
      std::vector<Double> V = Put( t );
      s = s + std::string( "[" );
      for( UInt4 d=0; d<PutSize(t)-1; d++ ){
        s = s + st->DoubleToString( V[d] ) + std::string( "," );
      }
      s = s + st->DoubleToString( V[PutSize(t)-1] ) + std::string( "]" );
      vs.push_back( s );
    }
    else{
      vs.push_back( std::string( "The size of vector is zero." ) );
    }
  }

  CppToPython *cp = new CppToPython();
  PyObject *p = cp -> VectorStringToList( vs );
  delete cp;
  delete st;
  return p;
}
////////////////////////////////////////////////////////
void ElementContainer::
DumpValue()
{
  UInt4 TableSize = PutTableSize();
  for( UInt4 t=0; t<TableSize; t++ ){
    std::string key   = PutName( t );
    UInt4  depth = PutSize( t );
    std::string unit  = UnitHeader->PutString( key );

    std::cout << t     << "\t"
              << key   << "\t"
              << depth << "\t"
              << unit  << "\t";

    if( depth >= 1){
      std::vector<Double> V = Put( t );
      std::cout << "[";
      for( UInt4 d=0; d<depth-1; d++ ){
        std::cout << V[d] << ",";
      }
      std::cout << V[depth-1] << "]" << std::endl;
    }
    else{
      std::cout << "The size of vector is zero." << std::endl;
    }
  }
}
////////////////////////////////////////////////////////
void ElementContainer::
DumpFromVectorContainer()
{
  UInt4 TableSize = PutTableSize();
  for( UInt4 t=0; t<TableSize; t++ ){
    std::string key   = PutName( t );
    UInt4  depth = PutSize( t );
    std::string unit  = UnitHeader->PutString( key );

    std::cout << key   << "\t"
              << depth << "\t";

    if( depth >= 1){
      std::vector<Double> V = Put( t );
      std::cout << "[";
      for( UInt4 d=0; d<depth-1; d++ ){
        std::cout << V[d] << ",";
      }
      std::cout << V[depth-1] << "]" << std::endl;
    }
    else{
      std::cout << "The size of vector is zero." << std::endl;
    }
  }
}
////////////////////////////////////////////////////////
void ElementContainer::
Dump( UInt4 size )
{
  std::cout << "*** header object start" << std::endl;
  header -> dump();
  std::cout << "*** header object end"   << std::endl;
  std::cout << std::endl;

  UInt4 TableSize = PutTableSize();
  std::cout << "The number of vectors is ";
  std::cout << TableSize << std::endl;
  std::cout << std::endl;

  std::cout << "x key = "
            << Xkey << std::endl;
  std::cout << "y key = "
            << Ykey << std::endl;
  std::cout << "e key = "
            << Ekey << std::endl;
  std::cout << std::endl;

  std::cout << "Index" << "\t"
            << "Key"  << "\t"
            << "Size"   << "\t"
            << "Unit" << "\t"
            << "Values" << std::endl;
  DumpValue( size );
}
////////////////////////////////////////////////////////
void ElementContainer::
DumpValue( UInt4 size )
{

  UInt4 TableSize = PutTableSize();
  if( size == 0 ){
    for( UInt4 t=0; t<TableSize; t++ ){
      std::string key   = PutName( t );
      UInt4  depth = PutSize( t );
      std::string unit = UnitHeader -> PutString( key );

      std::cout << t     << "\t"
                << key   << "\t"
                << depth << "\t"
                << unit  << "\t"
                << "[...]" << std::endl;
    }
  }

  else{
    for( UInt4 t=0; t<TableSize; t++ ){
      std::string key   = PutName( t );
      UInt4  depth = PutSize( t );
      std::string unit = UnitHeader -> PutString( key );

      std::cout << t     << "\t"
                << key   << "\t"
                << depth << "\t"
                << unit  << "\t[ ";

      if( depth >= 1 && depth <= size ){
        std::vector<Double> V = Put( t );
        for( UInt4 d=0; d<depth-1; d++ ){
          std::cout << V[d] << ",";
        }
        std::cout << V[depth-1] << " ]" << std::endl;
      }

      else if( depth >= 1 && depth > size ){
        std::vector<Double> V = Put( t );
        for( UInt4 d=0; d<size-1; d++ ){
          std::cout << V[d] << ",";
        }
        std::cout << V[size-1] << " ,..... ]" << std::endl;
      }

      else{
        std::cout << "The size of vector is zero.]" << std::endl;
      }
    }
  }
}
////////////////////////////////////////////////////////
void ElementContainer::
DumpFromVectorContainer( UInt4 size )
{
  UInt4 TableSize = PutTableSize();
  if( size == 0 ){
    for( UInt4 t=0; t<TableSize; t++ ){
      std::string key   = PutName( t );
      UInt4  depth = PutSize( t );
      std::string unit = UnitHeader -> PutString( key );

      std::cout << key   << "\t"
                << depth << "\t"
                << "[...]" << std::endl;
    }
  }

  else{
    for( UInt4 t=0; t<TableSize; t++ ){
      std::string key   = PutName( t );
      UInt4  depth = PutSize( t );

      std::cout << key   << "\t"
                << depth << "\t[ ";

      if( depth >= 1 && depth <= size ){
        std::vector<Double> V = Put( t );
        for( UInt4 d=0; d<depth-1; d++ ){
          std::cout << V[d] << ",";
        }
        std::cout << V[depth-1] << " ]" << std::endl;
      }

      else if( depth >= 1 && depth > size ){
        std::vector<Double> V = Put( t );
        for( UInt4 d=0; d<size-1; d++ ){
          std::cout << V[d] << ",";
        }
        std::cout << V[size-1] << " ,..... ]" << std::endl;
      }

      else{
        std::cout << "The size of vector is zero.]" << std::endl;
      }
    }
  }
}


/**********************************************
 *** 11. StringToInt, IntToString, DoubleToString
 **********************************************/

// StringToInt, IntToString, DoubleToString were removed

/**********************************************
 *** 12. series of Put()                    ***
 **********************************************/

////////////////////////////////////////////////////////
std::vector<Double> ElementContainer::
PutX()
{
  if( Xkey != "None" ){
    return M.Put( Xkey );
  }

  std::cout << "ElementContainer::PutX()"   << std::endl;
  std::cout << "The X-key is not assigned." << std::endl;
  std::cout << "Returns a blanc std::vector."    << std::endl;

  std::vector<Double> blanc;
  blanc.clear();
  return blanc;
}
/////////////////////////////////////////////////////////
std::vector<Double> ElementContainer::
PutY()
{
  if( Ykey != "None" ){
    return M.Put( Ykey );
  }

  std::cout << "ElementContainer::PutY()"   << std::endl;
  std::cout << "The Y-key is not assigned." << std::endl;
  std::cout << "Returns a blanc std::vector."    << std::endl;

  std::vector<Double> blanc;
  blanc.clear();
  return blanc;
}
/////////////////////////////////////////////////////////
std::vector<Double> ElementContainer::
PutE()
{
  if( Ekey != "None" ){
    return M.Put( Ekey );
  }

  std::cout << "ElementContainer::PutE()"   << std::endl;
  std::cout << "The E-key is not assigned." << std::endl;
  std::cout << "Returns a blanc std::vector."    << std::endl;

  std::vector<Double> blanc;
  blanc.clear();
  return blanc;
}
/////////////////////////////////////////////////////////
std::string ElementContainer::
PutXYEKeys()
{
  std::string st;
  st = Xkey + std::string( "," )
     + Ykey + std::string( "," )
     + Ekey;
  return st;
}
/////////////////////////////////////////////////////////
std::string ElementContainer::
PutMergedKey()
{
  std::string st;
  st.clear();

  std::vector<std::string> vs = M.PutKeyList();

  UInt4 size = (UInt4)(vs.size());
  if( size == 0 ){
    st = "NULL";
  }
  else{
    for( UInt4 i=0; i<size-1; i++){
      st = st + vs[i] + std::string( "," );
    }
    st = st + vs[ size-1 ];
  }
  return st;
}
/////////////////////////////////////////////////////////
std::vector<UInt4> ElementContainer::
PutSizeVector()
{
  std::vector<std::string> vs = M.PutKeyList();
  UInt4 Size = (UInt4)(vs.size());
  std::vector<UInt4> SizeVector( Size );
  for( UInt4 i=0; i<Size; i++ ){
    SizeVector[ i ] = (UInt4)(M( vs[ i ] )->size());
  }
  return SizeVector;
}
/////////////////////////////////////////////////////////
std::vector<Double> ElementContainer::
PutMergedDataVector()
{
  UInt4 Total = 0;

  std::vector<UInt4> SizeVector = PutSizeVector();
  UInt4 VecSize = (UInt4)(SizeVector.size());
  for( UInt4 i=0; i<VecSize; i++ ){
    Total = Total + SizeVector[ i ];
  }

  UInt4 Counter = 0;
  std::vector<Double> MergedDataVector( Total );
  std::vector<std::string> vs = M.PutKeyList();
  for( UInt4 i=0; i<vs.size(); i++ ){
    std::vector<Double> *target = M( vs[ i ] );
    UInt4 TargetSize = (UInt4)(target -> size());
    for( UInt4 j=0; j<TargetSize; j++ ){
      MergedDataVector[Counter++] = ( *target )[ j ];
    }
  }
  return MergedDataVector;
}
/////////////////////////////////////////////////////////
std::string ElementContainer::
PutUnit( const std::string &Key ) const
{
  if( UnitHeader->CheckKey( Key ) != 1 ){
    return "NoKey";
  }
  return UnitHeader->PutString( Key );
}


/**********************************************
 *** 13. others                             ***
 **********************************************/
/////////////////////////////////////////////////////////
void ElementContainer::
SaveToBinFile( std::string key, std::string FileName ){
  NeutronWriteBinaryData<Double> *nw
    = new NeutronWriteBinaryData<Double>();
  nw -> Write( Put( key ), FileName );
  delete nw;
}
/////////////////////////////////////////////////////////
void ElementContainer::
ReadBinFile( std::string FileName, std::string key ){
  NeutronReadBinaryData<Double> *nr =
    new NeutronReadBinaryData<Double>();
  Add( key, nr->ReadData( FileName ) );
  delete nr;
}
/////////////////////////////////////////////////////////
std::vector<Double> ElementContainer::
ReduceColumn( const std::string &Key )
{
  if( CheckKey( Key ) != 1 ){
    std::cout << "ElementContainer::ReduceColumn(std::string)"
         << std::endl;
    std::cout << Key << " is not found in this container." << std::endl;
    std::vector<Double> blanc;
    blanc.clear();
    return blanc;
  }
  std::vector<Double> vec = Put( Key );
  UInt4 size = (UInt4)(vec.size());

  std::vector<Double> NewVec( size-1 );
  for( UInt4 i=0; i<size-1; i++ ){
    NewVec[i] = ( vec[i] + vec[i+1] ) / 2.0;
  }

  return NewVec;
}
/////////////////////////////////////////////////////////
void ElementContainer::
BuildElementContainer( std::string XYEKeys,
                       std::string MergedKey,
                       std::vector<UInt4> SizeVector,
                       std::vector<Double> MergedDataVector,
                       HeaderBase h,
                       HeaderBase uh )
{
  SplitString *ss = new SplitString();

  if( MergedKey == "NULL" || SizeVector.size() == 0
      || MergedDataVector.size() == 0 ){
    //std::cout << "ElementContainer::BuildElementContainer(.....)" << std::endl;
    //std::cout << "Data is not contained in the arguments." << std::endl;
    return;
  }

  std::vector<std::string> MergedKeyVector = ss -> Split( MergedKey, "," );
  if( MergedKeyVector.size() != SizeVector.size() ){
    std::cout << "ElementContainer::BuildElementContainer(.....)" << std::endl;
    std::cout << "The data size of the second argument ";
    std::cout << "is inconsistent with the third argumet. ";
    std::cout << "Please check them !!" << std::endl;
    return;
  }

  UInt4 Total = 0;
  UInt4 SizeVectorSize = (UInt4)(SizeVector.size());
  for( UInt4 i=0; i<SizeVectorSize; i++ ){
    Total = Total + SizeVector[ i ];
  }
  if( Total != MergedDataVector.size() ){
    std::cout << "ElementContainer::BuildElementContainer(.....)" << std::endl;
    std::cout << "The data size of the third argument is inconsistent ";
    std::cout << "with the fourth argument. Please check them !!" << std::endl;
    return;
  }


  UInt4 Counter = 0;
  for( UInt4 i=0; i<SizeVectorSize; i++ ){
    UInt4 TargetSize = SizeVector[ i ];
    std::vector<Double> Target( TargetSize );
    for( UInt4 j=0; j<TargetSize; j++ ){
      Target[ j ] = MergedDataVector[ Counter++ ];
    }
    M.Add( MergedKeyVector[ i ], Target );
  }
  std::vector<std::string> xye = ss -> Split( XYEKeys, "," );
  if( xye[0] != "None" ||
      xye[1] != "None" ||
      xye[2] != "None" ){
    SetKeys( xye[0], xye[1], xye[2] );
  }
  InputHeader( h );
  delete UnitHeader;
  UnitHeader = new HeaderBase();
  *UnitHeader = uh;

  delete ss;
}
/////////////////////////////////////////////////////////
void ElementContainer::
SetUnit( const std::string &Key, const std::string &NewUnit )
{
  if( UnitHeader->CheckKey( Key ) != 1 ){
    std::cout << Key << " cannot be found in this container." << std::endl;
    return;
  }
  UnitHeader->OverWrite( Key, NewUnit );
}
/////////////////////////////////////////////////////////

/**********************************************
 *** 14. sum, integral, average, min, max   ***
 **********************************************/


/** binary function object used in ElementContainer::Ave() and ElementContainer::Integrate()
 *
 * S1 is used to calculate
 * (E[i] * (X[i+1] - X[i]))^2
 * instead of normal std::inner_product which calculates E[i]*(X[i+1]-X[i])
 */
/* typename are needed to compile with gcc */
/*
template <class T> class S1 : public binary_function<T, T, T>
{
public:
  typedef typename binary_function<T, T, T>::result_type result_type;
  typedef typename binary_function<T, T, T>::first_argument_type first_argument_type;
  typedef typename binary_function<T, T, T>::second_argument_type second_argument_type;
  result_type operator()(first_argument_type arg1, second_argument_type arg2) {
    return arg1*arg1*arg2*arg2;
  }
};
*/
/** binary function object used in ElementContainer::Ave() and ElementContainer::Integrate()
 *
 * S2 is used to calculate 1 / (Error[i] * Error[i])
 */
/*
template <class T> class S2 : public binary_function<T, T, T>
{
public:
  typedef typename binary_function<T, T, T>::result_type result_type;
  typedef typename binary_function<T, T, T>::first_argument_type first_argument_type;
  typedef typename binary_function<T, T, T>::second_argument_type second_argument_type;
  result_type operator()(first_argument_type arg1, second_argument_type arg2) {
    return 1 / (arg1 * arg2);
  }
};
*/

/*
template <class T> class S2 : public function<T(T, T)>
{
public:
    typedef typename function<T(T, T)>::result_type result_type;
    typedef typename function<T(T, T)>::first_argument_type first_argument_type;
    typedef typename function<T(T, T)>::second_argument_type second_argument_type;
    result_type operator()(first_argument_type arg1, second_argument_type arg2) {
        return 1 / (arg1 * arg2);
  }
};
*/

/** binary function object used in ElementContainer::Ave() and ElementContainer::Integrate()
 *
 * S3 is used to calculate T[i] / (Error[i] * Error[i])
 */
/*
template <class T> class S3 : public binary_function<T, T, T>
{
public:
  typedef typename binary_function<T, T, T>::result_type result_type;
  typedef typename binary_function<T, T, T>::first_argument_type first_argument_type;
  typedef typename binary_function<T, T, T>::second_argument_type second_argument_type;
  result_type operator()(first_argument_type arg1, second_argument_type arg2) {
    return arg1 / (arg2 * arg2);
  }
};
*/

/*
template <class T> class S3 : public function<T(T, T)>
{
public:
    typedef typename function<T(T, T)>::result_type result_type;
    typedef typename function<T(T, T)>::first_argument_type first_argument_type;
    typedef typename function<T(T, T)>::second_argument_type second_argument_type;
    result_type operator()(first_argument_type arg1, second_argument_type arg2) {
        return arg1 / (arg2 * arg2);
    }
};
*/

/////////////////////////////////////////////////////////
/** function class to calculate summation with Kahan's algorithm
 * http://en.wikipedia.org/wiki/Kahan_summation_algorithm
 *
 */
class KahanSum {
private:
  double c;
public:
  KahanSum() : c(0.0) {};

  /** performs Kahan's Compensated Summation; it is designed to used from std::accumulate() as a function object
   *
   * @param  s initial value
   * @param  d value to add to s
   * @return summation result
   */
  double operator()(double &s, const double &d) {
    double y = d - c;
    double t = s + y;
    c = (t-s) - y;
    return t;
  }
};



/////////////////////////////////////////////////////////
Double ElementContainer::
Sum( const std::string &key, const UInt4 i0, const UInt4 i1 ) const {
  if (!(i0<i1)) {
    std::cout << "ElementContainer::Sum(UInt4, UInt4)" << std::endl;
    std::cout << "i0 should be smaller than i1" << std::endl;
  }
  //if ((i0<0) || (i1>(M.Size(key)-1)))
  if ((i0<0) || (i1>(M.Size(key)))) { //[inamura 140228]
    std::cout << "ElementContainer::Sum(UInt4, UInt4)" << std::endl;
    std::cout << "i0 and i1 should be in the range of array index" << std::endl;
  }
  /*
  const std::vector<Double> *Target = M( key );

  if (safesum) {
        class KahanSum K;
        return std::accumulate(&((*Target)[i0+1]), &((*Target)[i1]),
                                          (*Target)[i0], K);
  }
  else
  return std::accumulate(&((*Target)[i0]), &((*Target)[i1]), 0.0);
  */
  std::vector<Double>::const_iterator it = M( key )->begin();
  if (safesum) {
    class KahanSum K;
    return std::accumulate( it+i0+1, it+i1, *(it+i0), K );
  }
  else{
    return std::accumulate( it+i0, it+i1, 0.0 );
  }
}
/////////////////////////////////////////////////////////
Double ElementContainer::
Sum( const std::string &key ) const {

  //return Sum(key, 0, M.Size(key)-1);
  return Sum(key, 0, M.Size(key));   //[inamura 140228]
}
/////////////////////////////////////////////////////////
Double ElementContainer::
Sum( void ) const {
  if ( Ykey == "None" ) {
    std::cout << "ElementContainer::Sum( void )" << std::endl;
    std::cout << "Ykey have not been set." << std::endl;
    return 0;
  }
  return Sum( Ykey );
}
/////////////////////////////////////////////////////////
std::pair<Double, Double> ElementContainer::
Sum( const std::string &key, const std::string &err_key, UInt4 i0, UInt4 i1 ) const {

  std::pair<Double, Double> r;

  const std::vector<Double> *Error  = M( err_key );

  if( M( key )->size() != Error->size() ){
    std::cout << "ElementContainer::Sum(std::string,std::string)" << std::endl;
    std::cout << "The size of Target and Error std::vector should be equal." << std::endl;
    return r;
  }

  r.first = Sum( key, i0, i1 );

  if (safesum) {

    std::vector<double> e(&((*Error)[i0]), &((*Error)[i1]));
    for (unsigned int i=0;i<e.size();++i) e[i] *= e[i];

    class KahanSum K;
    Double t = std::accumulate(&(e[1]), &(e[e.size()]), e[0], K);
    r.second = sqrt( t );

  } else {
  // Error is added as a inner product sum{E[i]*E[i]}
    Double t = std::inner_product(&((*Error)[i0]), &((*Error)[i1]), &((*Error)[i0]), 0.0);

    r.second = sqrt( t );
  }

  return r;
}
/////////////////////////////////////////////////////////
std::pair<Double, Double> ElementContainer::
Sum( const std::string &key, const std::string &err_key ) const {
  return Sum(key, err_key, 0, M.Size(key)-1 );
}
/////////////////////////////////////////////////////////
std::pair<Double, Double> ElementContainer::
Sum2( void ) const {
  if ( ( Ykey == "None" ) || ( Ekey == "None" ) ) {
    std::cout << "ElementContainer::Sum( void )" << std::endl;
    std::cout << "Ykey or Ekey have not been set." << std::endl;
    std::pair<Double, Double> v(2, 0.0);
    return v;
  }
  return Sum( Ykey, Ekey );
}
/////////////////////////////////////////////////////////
std::pair<Double, Double> ElementContainer::
Sum( Double ini, Double fin ) const {
  std::pair<Double, Double> r;

  if( ini >= fin ){
    std::cout << "ElementContainer::Sum(Double,Double)" << std::endl;
    std::cout << "The values of first and second arguments are wrong." << std::endl;
    return r;
  }

  if( Xkey == "None" || Ykey == "None" || Ekey == "None" ){
    std::cout << "ElementContainer::Sum(Double,Double)" << std::endl;
    std::cout << "Xkey, Ykey and Ekey have not been set." << std::endl;
    return r;
  }

  const std::vector<Double> *X = M(Xkey);
  UInt4 i0=0, i1=M.Size(Xkey)-1;
  while ((*X)[i0] < ini ) ++i0;
  while ((*X)[i1] > fin ) --i1;

  return Sum( Ykey, Ekey, i0, i1);
}
/////////////////////////////////////////////////////////
Double ElementContainer::
Ave( const std::string &key ){
  return Sum( key ) / ( (Double)( M( key )->size() ) );
}
/////////////////////////////////////////////////////////
Double ElementContainer::
Ave( const std::string &key, const std::string &err ){

  std::vector<Double> *Target = M( key );
  std::vector<Double> *Error  = M( err );

  if( Target->size() != Error->size() ){
    std::cout << "ElementContainer::Ave(std::string,std::string)" << std::endl;
    std::cout << "The size of Target and Error std::vector should be equal." << std::endl;
    return 0.0;
  }

  std::vector<Double>::iterator zero = find(Error->begin(), Error->end(), 0.0);
  if (zero != Error->end()) {
      std::cout << "ElementContainer::Ave(std::string,std::string)" << std::endl;
      std::cout << "Each error value shuld not be zero."  << std::endl;
      return 0.0;
  }

  Double A = 0.0;
  Double B = 0.0;

  // A = sum{T[i]/(E[i]*E[i])}
  auto S3 = [](Double &arg1, Double &arg2)->Double{ return arg1 / (arg2 * arg2); };
  A = std::inner_product(Target->begin(), Target->end(), Error->begin(), 0.0,
                         std::plus<Double>(), S3 );
//                      std::plus<Double>(), S3<Double>() );
  // B = sum{1/(E[i]*E[i])}
  auto S2 = [](Double &arg1, Double &arg2)->Double{ return 1.0 / (arg1 * arg2); };
  B = std::inner_product(Error->begin(), Error->end(), Error->begin(), 0.0,
                         std::plus<Double>(), S2 );
//                      std::plus<Double>(), S2<Double>() );

  return A / B;
}
/////////////////////////////////////////////////////////
Double ElementContainer::
Min( const std::string &key ){
  std::vector<Double> *target = M( key );

  std::vector<Double>::iterator Min;
  Min = min_element(target->begin(), target->end());

  return *Min;
}
/////////////////////////////////////////////////////////
Double ElementContainer::
Max( const std::string &key ){
  std::vector<Double> *target = M( key );

  std::vector<Double>::iterator Max;
  Max = max_element(target->begin(), target->end());

  return *Max;
}
/////////////////////////////////////////////////////////
std::pair<Double, Double> ElementContainer::
Integrate(){
  return Integrate( 0, (Double)(M(Ykey)->size()-1) );
}
/////////////////////////////////////////////////////////
/*
std::vector<Double> ElementContainer::
Integrate( UInt4 ini, UInt4 fin ){
  std::vector<Double> r;
  r.clear();

  if( ini >= fin ){
    std::cout << "ElementContainer::Integrate(UInt4,UInt4)" << std::endl;
    std::cout << "The values of first and second arguments are wrong." << std::endl;
    return r;
  }

  if( Xkey == "None" || Ykey == "None" || Ekey == "None" ){
    std::cout << "ElementContainer::Integrate(UInt4,UInt4)" << std::endl;
    std::cout << "Xkey, Ykey and Ekey have not been set." << std::endl;
    return r;
  }

  std::vector<Double> *X = M(Xkey);
  std::vector<Double> *Y = M(Ykey);
  std::vector<Double> *E = M(Ekey);

  if( Y->size() <= fin ){
    std::cout << "ElementContainer::Integrate(UInt4,UInt4)" << std::endl;
    std::cout << "The second argument is too large." << std::endl;
    return r;
  }

  std::vector<Double> bin;
  bin.resize(X->size());
  // bin[i] = X[i]-X[i-1]; bin[0]=0
  adjacent_difference(X->begin(), X->end(), bin.begin());

  std::vector<Double>::iterator pbin = bin.begin();
  ++pbin;

  Double sum = 0.0;
  Double err = 0.0;

  // sum = sum{Y[i]*(X[i+1]-X[i])}
  sum = std::inner_product(Y->begin(), Y->end(), pbin, 0.0);
  // err = sum{(E[i]*(X[i+1]-X[i]))^2}
  err = std::inner_product(E->begin(), E->end(), pbin, 0.0,
                      std::plus<Double>(), S1<Double>() );

  r.push_back( sum );
  r.push_back( sqrt( err ) );

  return r;
}
*/
/////////////////////////////////////////////////////////
std::pair<Double, Double> ElementContainer::
Integrate( Double ini, Double fin ){
  std::pair<Double, Double> r;

  if( ini >= fin ){
    std::cout << "ElementContainer::Integrate(Double,Double)" << std::endl;
    std::cout << "The values of first and second arguments are wrong." << std::endl;
    return r;
  }

  if( Xkey == "None" || Ykey == "None" || Ekey == "None" ){
    std::cout << "ElementContainer::Integrate(Double,Double)" << std::endl;
    std::cout << "Xkey, Ykey and Ekey have not been set." << std::endl;
    return r;
  }

  std::vector<Double> *X = M(Xkey);
  std::vector<Double> *Y = M(Ykey);
  std::vector<Double> *E = M(Ekey);

  double sum = 0.0;
  double err = 0.0;
  double area = 0.0;

  for (UInt4 i=0;i<((*X).size()-1); ++i){
    if ( ( (*X)[i]>=ini )&&((*X)[i+1]<=fin) ){
      sum += (*Y)[i]*fabs((double)((*X)[i+1]-(*X)[i]));
      area = (*E)[i]*fabs((double)((*X)[i+1]-(*X)[i]));
      err += area*area;
    }
  }

  r.first = sum;
  r.second = sqrt( err );

  return r;
}

//////////////////////////////////////////////////////////
std::string ElementContainer::
PutName( UInt4 IndexNumber ){
  if( IndexNumber >= PutSize() ){
    std::cout << "ElementContainer::PutName(UInt4)" << std::endl;
    std::cout << "The argument is too large." << std::endl;
    return "None";
  }
  return (M.PutKeyList())[IndexNumber];
}
//////////////////////////////////////////////////////////
std::vector<std::string> ElementContainer::
PutKeys(){
  UInt4 s = PutSize();
  std::vector<std::string> vs;
  vs.clear();
  for( UInt4 i=0; i<s; i++ ){
    vs.push_back( PutName( i ) );
  }
  return vs;
}
//////////////////////////////////////////////////////////
PyObject * ElementContainer::
PutKeysList(){
  CppToPython *cp = new CppToPython();
  PyObject *r = cp -> VectorStringToList( PutKeys() );
  delete cp;
  return r;
}
//////////////////////////////////////////////////////////
PyObject * ElementContainer::
PutHistKeyList(){
  CppToPython *cp = new CppToPython();
  std::vector<std::string> vs;
  vs.clear();
  vs.push_back( Xkey );
  vs.push_back( Ykey );
  vs.push_back( Ekey );
  PyObject *r = cp -> VectorStringToList( vs );
  delete cp;
  return r;
}
//////////////////////////////////////////////////////////
void ElementContainer::
SaveTextFile( std::string FileName ){
  SaveTextFile( FileName, -1, ',' );
}
//////////////////////////////////////////////////////////
void ElementContainer::
SaveTextFile( std::string FileName, Int4 prec ){
  SaveTextFile( FileName, prec, ',' );
}
//////////////////////////////////////////////////////////
void ElementContainer::
SaveTextFile( std::string FileName, Char deli ){
  SaveTextFile( FileName,-1, deli );
}
//////////////////////////////////////////////////////////
void ElementContainer::
SaveTextFile( std::string FileName, Int4 prec, Char deli ){
  SimpleIOVectorToTextFile *ss = new SimpleIOVectorToTextFile();

  std::vector<Double> xv = PutX();
  std::vector<Double> yv = PutY();
  std::vector<Double> ev = PutE();
  ss->SetTarget(xv,yv,ev);
  ss->SaveFile( FileName, prec, deli );
  delete ss;
}
//////////////////////////////////////////////////////////
void ElementContainer::
SaveHistTextFile( std::string FileName ){
  SaveHistTextFile( FileName, -1, ',' );
}
//////////////////////////////////////////////////////////
void ElementContainer::
SaveHistTextFile( std::string FileName, Int4 prec ){
  SaveHistTextFile( FileName, prec, ',' );
}
//////////////////////////////////////////////////////////
void ElementContainer::
SaveHistTextFile( std::string FileName, Char deli ){
  SaveHistTextFile( FileName,-1, deli );
}
//////////////////////////////////////////////////////////
void ElementContainer::
SaveHistTextFile( std::string FileName, Int4 prec, Char deli ){
  SimpleIOVectorToTextFile *ss = new SimpleIOVectorToTextFile();

  std::vector<Double> xv = PutX();
  std::vector<Double> yv = PutY();
  std::vector<Double> ev = PutE();
  ss->SetTarget(xv,yv,ev, true);
  ss->SaveFile( FileName, prec, deli );
  delete ss;
}
//////////////////////////////////////////////////////////
void ElementContainer::
LoadTextFile( std::string FileName ){
  SimpleIOVectorToTextFile *ss = new SimpleIOVectorToTextFile();

  ss->LoadFile( FileName );

  Add("x",ss->PutX());
  Add("y",ss->PutY());
  Add("e",ss->PutE());
  SetKeys("x","y","e");

  delete ss;
}
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
ElementContainer &ElementContainer::
MulMySelf( Double d )
{ // Multiply itself and returns (*this)
  std::vector<Double> &YVec = M.ref( PutYKey() );
  std::vector<Double> &EVec = M.ref( PutEKey() );
  UInt4 Size = (UInt4)(YVec.size());
  for( UInt4 i=0; i<Size; i++ ){
    (YVec)[i] *= d;
    (EVec)[i] *= d;
  }
  return *this;
}
////////////////////////////////////////////////////////
ElementContainer &ElementContainer::
PlusMySelf( Double d )
{ // Plus itself and returns (*this)
  std::vector<Double> &YVec = M.ref( PutYKey() );
  std::vector<Double> &EVec = M.ref( PutEKey() );
  UInt4 Size = (UInt4)(YVec.size());
  for( UInt4 i=0; i<Size; i++ ){
    (YVec)[i] += d;
  }
  return *this;
}
////////////////////////////////////////////////////////////
ElementContainer &ElementContainer::
PowMySelf( Double d )
{ // Power itself and returns (*this)
  std::vector<Double> &YVec = M.ref( PutYKey() );
  std::vector<Double> &EVec = M.ref( PutEKey() );
  UInt4 Size = (UInt4)(YVec.size());
  for( UInt4 i=0; i<Size; i++ ){
    double y = (YVec)[i];
    double e = (EVec)[i];
    (YVec)[i] = pow(y, d);
    double ed = d*pow(y, (d-1));
    (EVec)[i] = fabs( ed*e );
  }
  return *this;
}
////////////////////////////////////////////////////////
ElementContainer ElementContainer::
Mul( Double d )
{
  ElementContainer result (*this);
  return result.MulMySelf(d);
}
///////////////////////////////////////////////////////
ElementContainer ElementContainer::
Plus( Double d )
{
  ElementContainer result (*this);
  return result.PlusMySelf(d);
}
////////////////////////////////////////////////////////
ElementContainer ElementContainer::
Pow( Double d )
{
  ElementContainer result (*this);
  return result.PowMySelf(d);
}
///////////////////////////////////////////////////////
ElementContainer &ElementContainer::
MulMySelf( Double d, Double e )
{
  std::vector<Double> &ly = M.ref( PutYKey() );
  std::vector<Double> &le = M.ref( PutEKey() );
  UInt4 size = (UInt4)(le.size());

  for( UInt4 i=0; i<size; i++ ){
    double r0 = e * ly[i];
    double r1 = le[i] * d;
    le[i] = sqrt( r0*r0 + r1*r1 );
  }
  for( UInt4 i=0; i<size; i++ ){
    ly[i] *= d;
  }
  return *this;
}
////////////////////////////////////////////////////////
ElementContainer &ElementContainer::
PlusMySelf( Double d, Double e )
{
  std::vector<Double> &ly = M.ref( PutYKey() );
  std::vector<Double> &le = M.ref( PutEKey() );
  UInt4 size = (UInt4)(le.size());

  for( UInt4 i=0; i<size; i++ ){ ly[i] += d; }

  Double r2 = e * e;
  for( UInt4 i=0; i<size; i++ ){ le[i] *= le[i]; }
  for( UInt4 i=0; i<size; i++ ){ le[i] += r2; }
  for( UInt4 i=0; i<size; i++ ){ le[i] = sqrt( le[i] ); }

  return *this;
}
////////////////////////////////////////////////////////
ElementContainer ElementContainer::
Mul( Double d, Double e )
{
  ElementContainer result (*this);
  return result.MulMySelf(d,e);
}
///////////////////////////////////////////////////////
ElementContainer ElementContainer::
Plus( Double d, Double e )
{
  ElementContainer result (*this);
  return result.PlusMySelf(d,e);
}
///////////////////////////////////////////////////////
void ElementContainer::
HistToScat(){

  if( isHist() != true ){
    std::cout << "This is NOT histogram type data." << std::endl;
    return;
  }

  std::vector<Double> *X = PutP( PutXKey() );
  std::vector<Double> *Y = PutP( PutYKey() );
  std::vector<Double> *E = PutP( PutEKey() );

  std::vector<Double> *newX = new std::vector<Double>();
  for( UInt4 i=0; i<X->size()-1; i++ ){
    Double ini = (*X)[ i   ];
    Double fin = (*X)[ i+1 ];
    newX->push_back( ( ini + fin ) / 2.0 );

    (*Y)[ i ] = (*Y)[ i ] / fabs( fin - ini );
    (*E)[ i ] = (*E)[ i ] / fabs( fin - ini );
  }

  std::string xkey = PutXKey();
  std::string ykey = PutYKey();
  std::string ekey = PutEKey();

  Copy( PutXKey(), PutXKey()+"_hist" );
  Remove( PutXKey() );
  Add( xkey, *newX );
  SetKeys( xkey, ykey, ekey );
  delete newX;
}
//////////////////////////////////////////////////////
void ElementContainer::
ScatToHist(){

  if( isHist() == true ){
    std::cout << "This is histogram type data." << std::endl;
    return;
  }

  if( CheckKey( PutXKey() + "_hist" ) != 1 ){
    std::cout << "This coordinate type data cannot return to a histogram type data." << std::endl;
    std::cout << "Is a vector object named "
         << PutXKey() << "_hist in this container ?" << std::endl;
    return;
  }

  std::vector<Double> *X = PutP( PutXKey() + "_hist" );
  std::vector<Double> *Y = PutP( PutYKey() );
  std::vector<Double> *E = PutP( PutEKey() );

  for( UInt4 i=0; i<X->size()-1; i++ ){
    Double ini = (*X)[ i   ];
    Double fin = (*X)[ i+1 ];

    (*Y)[ i ] = (*Y)[ i ] * fabs( fin - ini );
    (*E)[ i ] = (*E)[ i ] * fabs( fin - ini );
  }

  std::string CoordinateX = PutXKey();
  std::string ykey = PutYKey();
  std::string ekey = PutEKey();

  Remove( CoordinateX );
  Copy( CoordinateX + "_hist", CoordinateX );
  Remove( CoordinateX + "_hist" );
  SetKeys( CoordinateX, ykey, ekey );
}

bool ElementContainer::
RenameKey( const std::string &OldKey, const std::string & NewKey ){

  if( !( CheckKey( OldKey ) == 1 && CheckKey( NewKey ) == 0 ) ){
    return false;
  } // キーのチェックをする

  UnitHeader -> Add( NewKey, UnitHeader->PutString( OldKey ) ); // unitのコピー
  M.Copy( OldKey, NewKey ); // コピーをして
  M.Erase( OldKey );        // 不要なものを消す

  if( !( Xkey == "None" ) && Xkey == OldKey ){ // キーのコピーを必要に応じて行う
    SetKeys( NewKey, Ykey, Ekey );
  }
  if( !( Ykey == "None" ) && Ykey == OldKey ){
    SetKeys( Xkey, NewKey, Ekey );
  }
  if( !( Ekey == "None" ) && Ekey == OldKey ){
    SetKeys( Xkey, Ykey, NewKey );
  }

  return true;
}

/////////////////////////////////////////////////////////////
BinConverter::
BinConverter( std::vector<Double> &LX, std::vector<Double> &LY, std::vector<Double> &LE,
              const std::vector<Double> *RX, const std::vector<Double> *RY, const std::vector<Double> *RE ){
  lx = LX;
  ly = LY;
  le = LE;

  rx = RX;
  ry = RY;
  re = RE;

}
/////////////////////////////////////////////////////////////
BinConverter::
~BinConverter(){

  delete LBin;
  delete RBin;
  delete al;
  delete ar;

}
////////////////////////////////////////////////////////////
Int4 BinConverter::
prepare(){
  UInt4 lsize = (UInt4)(lx.size());
  UInt4 rsize = (UInt4)(rx->size());

  double lmin = lx[0];
  double lmax = lx[lsize-1];
  double rmin = (*rx)[0];
  double rmax = (*rx)[rsize-1];

  if( rmax < lmin || lmax < rmin ){
    // Two histogram are not overraped
    std::cout << "operation failed" << std::endl;
    return -1;
  }

  double min = lmin;
  if( rmin > lmin ){ min = rmin; }
  double max = lmax;
  if( rmax < lmax ){ max = rmax; }


  LBin = new std::vector<Double>();
  RBin = new std::vector<Double>();
  NewBin = NULL;

  for( UInt4 i=0; i<lsize; i++ ){
    Double val = lx[i];
    if( val >= min && val <= max ){ LBin->push_back( val ); }
  }
  for( UInt4 i=0; i<rsize; i++ ){
    Double val = (*rx)[i];
    if( val >= min && val <= max ){ RBin->push_back( val ); }
  }

  if( RBin->size() < LBin->size() ){ NewBin = RBin; }
  else{ NewBin = LBin; }

  if( NewBin->size() < 2 ){
    std::cout << "operation failed, new histogram cannot be created" << std::endl;
    return -1;
  }

  al = new DoubleBinArrange( lsize-1, (UInt4)(NewBin->size())-1 );
  ar = new DoubleBinArrange( rsize-1, (UInt4)(NewBin->size())-1 );
  al->SetHist( lx,   ly,  le, *NewBin );
  ar->SetHist( *rx, *ry, *re, *NewBin );

  al -> Binning();
  ar -> Binning();

  return 1;
}
/////////////////////////////////////////////////////////////

