/*
 * Project: MoleCuilder
 * Description: creates and alters molecular systems
 * Copyright (C)  2012 University of Bonn. All rights reserved.
 * Copyright (C)  2013 Frederik Heber. All rights reserved.
 * 
 *
 *   This file is part of MoleCuilder.
 *
 *    MoleCuilder is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    MoleCuilder is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with MoleCuilder.  If not, see .
 */
/*
 * IndexedVectors.cpp
 *
 *  Created on: 29.07.2012
 *      Author: heber
 */
// include config.h
#ifdef HAVE_CONFIG_H
#include 
#endif
#include "CodePatterns/MemDebug.hpp"
#include "Fragmentation/Summation/SetValues/IndexedVectors.hpp"
#include 
#include "CodePatterns/Assert.hpp"
// static member variables
const size_t IndexedVectors::FixedSize = 3;
const IndexedVectors::vector_t IndexedVectors::nullvector( FixedSize, 0.);
IndexedVectors::IndexedVectors(const indices_t &_indices, const vectors_t &_vectors)
{
  ASSERT(_indices.size() == _vectors.size(),
      "IndexedVectors::IndexedVectors() - vector of indices and vectors don't match in size.");
  indices_t::const_iterator indexiter = _indices.begin();
  vectors_t::const_iterator vectoriter = _vectors.begin();
  for (; vectoriter != _vectors.end(); ++indexiter, ++vectoriter) {
    ASSERT( vectoriter->size() == FixedSize,
        "IndexedVectors::IndexedVectors() - vector to instance "
        +toString(*indexiter)+" has size "
        +toString(vectoriter->size())+" different to FixedSize "
        +toString(FixedSize)+".");
    if (*indexiter != (size_t)DropIndex) { // skip all force vectors associated to -1
#ifndef NDEBUG
      std::pair inserter =
#endif
      vectors.insert( std::make_pair( *indexiter, *vectoriter) );
      ASSERT( inserter.second,
          "IndexedVectors::IndexedVectors() - index "
          +toString(inserter.first->first)+" already present with vector "
          +toString(inserter.first->second)+".");
    }
  }
}
IndexedVectors& IndexedVectors::operator=(const IndexedVectors &other)
{
  // check for self-assignment
  if (this != &other) {
    vectors.clear();
    vectors = other.vectors;
  }
  return *this;
}
void IndexedVectors::superposeOtherIndexedVectors(const IndexedVectors &other, const double prefactor)
{
  for (indexedvectors_t::const_iterator otheriter = other.vectors.begin();
      otheriter != other.vectors.end(); ++otheriter) {
    indexedvectors_t::iterator iter = vectors.find(otheriter->first);
    if (iter == vectors.end()) {
      // index does not exist
      std::pair inserter =
          vectors.insert( std::make_pair( otheriter->first, nullvector) );
      ASSERT( inserter.second,
          "IndexedVectors::superposeOtherIndexedVectors() - index is present though unfound before?");
      iter = inserter.first;
    }
    // now simply vector to index from other instance add with prefactor
    vector_t::iterator vectoriter = iter->second.begin();
    vector_t::const_iterator othervectoriter = otheriter->second.begin();
    for (;vectoriter != iter->second.end(); ++vectoriter, ++othervectoriter) {
      *vectoriter += prefactor * (*othervectoriter);
    }
  }
}
std::ostream & operator<<(std::ostream &ost, const IndexedVectors &other)
{
  for (IndexedVectors::indexedvectors_t::const_iterator iter = other.vectors.begin();
      iter != other.vectors.end(); ++iter)
    ost << "(" << iter->first << "," << iter->second << ") ";
  return ost;
}
template<> IndexedVectors ZeroInstance()
{
  IndexedVectors returnvalue;
  return returnvalue;
}