text: /**
   * File: BowVector.cpp
   * Date: March 2011
   * Author: Dorian Galvez-Lopez
   * Description: bag of words vector
   * License: see the LICENSE.txt file
   *
   */
  
  #include <iostream>
  #include <fstream>
  #include <vector>
  #include <algorithm>
  #include <cmath>
  
  #include "../src/BowVector.h"
  
  namespace DBoW3 {
  
  // --------------------------------------------------------------------------
  
  BowVector::BowVector(void)
  {
  }
  
  // --------------------------------------------------------------------------
  
  BowVector::~BowVector(void)
  {
  }
  
  // --------------------------------------------------------------------------
  
  void BowVector::addWeight(WordId id, WordValue v)
  {
    BowVector::iterator vit = this->lower_bound(id);
    
    if(vit != this->end() && !(this->key_comp()(id, vit->first)))
    {
      vit->second += v;
    }
    else
    {
      this->insert(vit, BowVector::value_type(id, v));
    }
  }
  
  // --------------------------------------------------------------------------
  
  void BowVector::addIfNotExist(WordId id, WordValue v)
  {
    BowVector::iterator vit = this->lower_bound(id);
    
    if(vit == this->end() || (this->key_comp()(id, vit->first)))
    {
      this->insert(vit, BowVector::value_type(id, v));
    }
  }
  
  // --------------------------------------------------------------------------
  
  void BowVector::normalize(LNorm norm_type)
  {
    double norm = 0.0; 
    BowVector::iterator it;
  
    if(norm_type == DBoW3::L1)
    {
      for(it = begin(); it != end(); ++it)
        norm += fabs(it->second);
    }
    else
    {
      for(it = begin(); it != end(); ++it)
        norm += it->second * it->second;
  		norm = sqrt(norm);  
    }
  
    if(norm > 0.0)
    {
      for(it = begin(); it != end(); ++it)
        it->second /= norm;
    }
  }
  
  // --------------------------------------------------------------------------
  
  std::ostream& operator<< (std::ostream &out, const BowVector &v)
  {
    BowVector::const_iterator vit;
    std::vector<unsigned int>::const_iterator iit;
    unsigned int i = 0; 
    const size_t N = v.size();
    for(vit = v.begin(); vit != v.end(); ++vit, ++i)
    {
      out << "<" << vit->first << ", " << vit->second << ">";
      
      if(i < N-1) out << ", ";
    }
    return out;
  }
  
  // --------------------------------------------------------------------------
  
  void BowVector::saveM(const std::string &filename, size_t W) const
  {
    std::fstream f(filename.c_str(), std::ios::out);
    
    WordId last = 0;
    BowVector::const_iterator bit;
    for(bit = this->begin(); bit != this->end(); ++bit)
    {
      for(; last < bit->first; ++last)
      {
        f << "0 ";
      }
      f << bit->second << " ";
      
      last = bit->first + 1;
    }
    for(; last < (WordId)W; ++last)
      f << "0 ";
    
    f.close();
  }
  // --------------------------------------------------------------------------
  
  void BowVector::toStream(std::ostream &str)const{
      uint32_t s=size();
      str.write((char*)&s,sizeof(s));
      for(auto d:*this){
          str.write((char*)&d.first,sizeof(d.first));
          str.write((char*)&d.second,sizeof(d.second));
      }
  }
  // --------------------------------------------------------------------------
  
  void BowVector::fromStream(std::istream &str){
  clear();
  uint32_t s;
  
  str.read((char*)&s,sizeof(s));
  for(int i=0;i<s;i++){
      WordId wid;
      WordValue wv;
      str.read((char*)&wid,sizeof(wid));
      str.read((char*)&wv,sizeof(wv));
      insert(std::make_pair(wid,wv));
  }
  
  }
  
  uint64_t BowVector::getSignature()const{
  uint64_t sig=0;
  for(auto ww:*this) sig+=ww.first+1e6*ww.second;
  return sig;
  }
  
  
  // --------------------------------------------------------------------------
  
  } // namespace DBoW3
  
  