/*
 * Copyright (c) 1999 Johnny C. Lam.
 * All rights reserved.
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without fee,
 * provided that the above copyright notice appear in all copies and
 * that both that copyright notice and this permission notice appear
 * in supporting documentation.  The author makes no representations
 * about the suitability of this software for any purpose.  It is
 * provided "as is" without express or implied warranty.
 */

// -*- C++ -*-

#ifndef STL_NUMERIC_INCLUDED
#include <numeric>
#define STL_NUMERIC_INCLUDED
#endif

inline
Path::Path()
    : _value(new PathValue())
{}

inline
Path::Path(const Haplotype& haplotype)
    : _value(new PathValue())
{
    Add(Edge(haplotype, 0));
}

inline
log_probability
Path::Weight() const
{
  return std::accumulate(begin(), end(), static_cast<log_probability>(0),
			 EdgePlus());
}

inline
Path::Edge::Edge()
{}

inline
Path::Edge::Edge(const Haplotype& h, log_probability w)
    : haplotype(h), weight(w)
{}

inline
log_probability
Path::EdgePlus::operator()(log_probability weight, const Edge& edge) const
{
    return weight + edge.weight;
}

inline
Path::const_iterator
Path::begin() const
{
    return _value->edges.begin();
}

inline
Path::const_iterator
Path::end() const
{
    return _value->edges.end();
}

inline
unsigned int
Path::size() const
{
  return _value->edges.size();
}

inline
const Haplotype&
Path::From() const
{
  return _value->edges.front().haplotype;
}

inline
const Haplotype&
Path::To() const
{
  return _value->edges.back().haplotype;
}

inline
void
Path::Add(const Edge& edge)
{
    if (_value->is_shared())
	_value = new PathValue(*_value);
    _value->edges.push_back(edge);
}

inline
ostream&
operator<<(ostream& ostr, const Path& path)
{
    path.Write(ostr);
    return ostr;
}

inline
const Path
operator+(const Path& lhs, const Path& rhs)
{
    return Path(lhs) += rhs;
}
