//-------------------------------------------------------------------------
void A::deaccumulate(const Feature& f)
{
  const unsigned long vectSize = f.getVectSize();
  if (!_vectSizeDefined)
  {
	return;
  }
  else if (vectSize != _vectSize)
    throw Exception("Incompatible vectSize ("
          + String::valueOf(vectSize) + "/"
          + String::valueOf(_vectSize) + ")", __FILE__, __LINE__);

  const double* dataVect = f.getDataVector();

  for (unsigned long i=0; i<_vectSize; i++)
  {
    const double v = dataVect[i];
    _accVect[i] -= v;
    _xaccVect[i] -= v*v;
  }
  _count--;
  _computed = false;
  _stdComputed = false;

}
void featureMapping(MixtureServer & ms, Feature & f,Config &config) {
  unsigned long vectsize=f.getVectSize();                                       // Get the vect size (number of coeff)
  unsigned long idCD=getBestGaussian(ms.getMixture(1),f);						// Finding the best gaussian in the sub-model	
  DistribGD & DCD=ms.getMixtureGD(1).getDistrib(idCD); // get the gaussian in both models
  DistribGD & DCI=ms.getMixtureGD(0).getDistrib(idCD);
  for (unsigned int i = 0; i < vectsize; i++) {					// map
    if (debug && (i==0 || i==1)) cout<<"C:"<<idCD<<"["<<i<<"] CDm,v:"<<DCD.getMean(i)<<","<<DCD.getCov(i)<<" CIm,v: "<<DCI.getMean(i)<<","<<DCI.getCov(i)<< endl;	
    mapDataToDistrib(f[i],DCD.getMean(i),DCD.getCov(i),DCI.getMean(i),DCI.getCov(i));}
}
//-------------------------------------------------------------------------
// TODO : A OPTIMISER !!
//-------------------------------------------------------------------------
lk_t DistribGD::computeLK(const Feature& frame) const
{
  if (frame.getVectSize() != _vectSize)
    throw Exception("distrib vectSize ("
        + String::valueOf(_vectSize) + ") != feature vectSize ("
      + String::valueOf(frame.getVectSize()) + ")", __FILE__, __LINE__);
  real_t tmp = 0.0;
  real_t*      m = _meanVect.getArray();
  real_t*      c = _covInvVect.getArray();
  Feature::data_t* f = frame.getDataVector();

  for (unsigned long i=0; i<_vectSize; i++)
    tmp += (f[i] - m[i]) * (f[i] - m[i]) * c[i];

  tmp = _cst * exp(-0.5*tmp);
  if (ISNAN(tmp))
    return EPS_LK;
  return tmp;
}
//-------------------------------------------------------------------------
bool M::writeFeature(const Feature& f, unsigned long step)
{
  bool ok;
  if (!_useMask)
    ok = _pInput->writeFeature(f, step);
  else
  {
    if (_selectionSize != f.getVectSize())
       throw Exception("Invalid feature mask : " + _mask,
                       __FILE__, __LINE__);
    _feature.setVectSize(K::k, _pInput->getVectSize());
    Feature::data_t* outputVect = _feature.getDataVector();
    Feature::data_t* inputVect = f.getDataVector();
    for (unsigned long i=0; i<_selectionSize; i++)
      outputVect[_selection[i]] = inputVect[i];
    ok = _pInput->writeFeature(_feature, step);
  }
  _error = _pInput->getError();
  return ok;
}
//-------------------------------------------------------------------------
void W::writeFeature(const Feature& f)
{
  if (!_vectSizeDefined)
  {
    _vectSize = f.getVectSize();
    _vectSizeDefined = true;
  }
  else
    if (f.getVectSize() != _vectSize)
      throw Exception("Incompatible vectSize", __FILE__, __LINE__);

  if (isClosed())
    open();

  if (_format == FeatureFileWriterFormat_RAW) // **************************************************
  {
    for (unsigned long i=0; i<_vectSize; i++)
    {
      writeFloat((float)f[i]);
    }
  }
  else if (_format == FeatureFileWriterFormat_SPRO3) // *******************************************
  {
    if (!_headerWritten)
    {
      const FeatureFlags flags = _config.getParam_featureFlags();
      unsigned long dim = 0;
      const String& s = flags.getString();
      if (s == "100000")
        dim = _vectSize;
      else if (s == "110000")
        dim = _vectSize-1;
      else if (s == "101000")
        dim = _vectSize/2;
      else if (s == "111000" || s == "101100")
        dim = (_vectSize-1)/2;
      else if (s == "111100")
        dim = (_vectSize-2)/2;
      else if (s == "100010")
        dim = _vectSize/2;
      else if (s == "110010")
        dim = (_vectSize-1)/2;
      else if (s == "101010")
        dim = _vectSize/3;
      else if (s == "111010" || s == "101110")
        dim = (_vectSize-1)/3;
      else if (s == "111110")
        dim = (_vectSize-2)/3;
      else if (s == "100011")
        dim = (_vectSize-1)/2;
      else if (s == "110011")
        dim = (_vectSize-2)/2;
      else if (s == "101011")
        dim = (_vectSize-1)/3;
      else if (s == "111011" || s == "101111")
        dim = (_vectSize-2)/3;
      else if (s == "111111")
        dim = (_vectSize-3)/3;
      else
        throw Exception("Wrong featureFlag : " + s,
                 __FILE__, __LINE__);
      writeUInt4(_config.getParam_saveFeatureFileSPro3DataKind());
      writeUInt4(dim);
      writeUInt4(0);
      writeUInt4(flags.toSPro3());
      _headerWritten = true;
      _featureCount = 0;
    }
    for (unsigned long i=0; i<_vectSize; i++)
    { writeFloat((float)f[i]); }
    _featureCount++;
  }
  else if (_format == FeatureFileWriterFormat_SPRO4) // *******************************************
  {
    if (!_headerWritten)
    {
      writeString("<header>\n");
      writeString("</header>\n");
      writeShort((short)_vectSize);
      writeUInt4(_config.getParam_featureFlags().toSPro4());
      writeFloat((float)_config.getParam_sampleRate());
      _headerWritten = true;
    }
    for (unsigned long i=0; i<_vectSize; i++)
    { writeFloat((float)f[i]); }
  }
  else
     ;
}
//-------------------------------------------------------------------------
bool R::writeFeature(const Feature& f, unsigned long step)
{
  if (!_featuresAreWritable)
    throw Exception("Feature writing forbidden", __FILE__, __LINE__);
  assert(_pReader != NULL || _pFeatureInputStream != NULL);
  if (_seekWanted)
  {
    _seekWanted = false;
    if (_historicUsage == LIMITED && !featureWantedIsInHistoric())
      throw Exception("Feature out of Historic", __FILE__, __LINE__);
    _featureIndex = _seekWantedIdx;
  }
  // si on depasse la fin du fichier
  unsigned long featureCount = getFeatureCount();
  if (_featureIndex >= featureCount)
    return false;

  // si on demande une feature hors du buffer
  if (_featureIndex < _featureIndexOfBuffer ||
      _featureIndex >= _featureIndexOfBuffer + _nbStored)
  {
    if (!_bufferSizeDefined)
    {
      unsigned long m = _pBuffer->size();
      if (_bufferIsInternal)
      {
        if (_bufferUsage == BUFFER_USERDEFINE)
          m = _userDefineBufferSize/sizeof(float);
        else if (_bufferUsage == BUFFER_AUTO)
        {
          if (getConfig().existsParam_loadFeatureFileMemAlloc)
          {
            m = getConfig().getParam_loadFeatureFileMemAlloc()/sizeof(float);
            unsigned long n = featureCount*getVectSize();
            if (n < m)
              m = n;
          }
        }
      }
      if (m < getVectSize()) // minimum size
        m = getVectSize();
      _pBuffer->setSize(m);
      _bufferSizeDefined = true;
    }
    unsigned long start = _featureIndex;
    if (featureCount-_featureIndex < _pBuffer->size()/getVectSize())
    {
      unsigned long x = _pBuffer->size()/getVectSize() -
                        (featureCount-_featureIndex);
      if (x < _featureIndex)
        start -= x;
      else
        start = 0;
    }
    // si le bloc de donnees a charger ne suit pas le bloc deja en memoire
    // on se repositionne dans le fichier
    if (start != _featureIndexOfBuffer + _nbStored + 1) {
      if (_pReader != NULL) {
        _pReader->seek(getHeaderLength() + start*getVectSize()*sizeof(float));
      }
      else {
        _pFeatureInputStream->seekFeature(start);
      }
    }
    // chargement des donnees dans le buffer
    if (_pReader != NULL)
      _nbStored = _pReader->readSomeFloats(*_pBuffer)/getVectSize();
    else
    {
      // Pas performant. A améliorer
      _nbStored = 0;
      unsigned long vectSize = _pFeatureInputStream->getVectSize();
      while ((_nbStored+1)*vectSize <= _pBuffer->size()
              && _pFeatureInputStream->readFeature(_f))
      {
        unsigned long ii = _nbStored*vectSize;
        for (unsigned long j=0; j<vectSize; j++)
          (*_pBuffer)[ii+j] = (float) _f[j];
        _nbStored++;
      }
    }

    _featureIndexOfBuffer = start;
    // if all the features are loaded in the buffer, we close the file
    if (_nbStored == featureCount)
      close();
    else
      // données pas toutes en mémoire -> interdit le writeFeature()
      throw Exception("Feature writing forbidden (data are not all in memory)"
                      , __FILE__, __LINE__);
  }
  unsigned long vectSize = getVectSize();
  if (vectSize != f.getVectSize())
    throw Exception("incompatibles vectSize (" + String::valueOf(vectSize)
        + "/" + String::valueOf(f.getVectSize()) + ")", __FILE__, __LINE__);
  unsigned long offset = (_featureIndex-_featureIndexOfBuffer)*vectSize;
  for (unsigned long i=0; i<vectSize; i++)
    (*_pBuffer)[i+offset] = (float)f[i]; // TODO : conversion a revoir ?
  _featureIndex += step;
  if (_featureIndex > _lastFeatureIndex)
    _lastFeatureIndex = _featureIndex;
  return true;
}