epoc32/include/stdapis/boost/graph/compressed_sparse_row_graph.hpp
author William Roberts <williamr@symbian.org>
Tue, 16 Mar 2010 16:12:26 +0000
branchSymbian2
changeset 2 2fe1408b6811
permissions -rw-r--r--
Final list of Symbian^2 public API header files
williamr@2
     1
// Copyright 2005-2006 The Trustees of Indiana University.
williamr@2
     2
williamr@2
     3
// Distributed under the Boost Software License, Version 1.0.
williamr@2
     4
// (See accompanying file LICENSE_1_0.txt or copy at
williamr@2
     5
// http://www.boost.org/LICENSE_1_0.txt)
williamr@2
     6
williamr@2
     7
//  Authors: Jeremiah Willcock
williamr@2
     8
//           Douglas Gregor
williamr@2
     9
//           Andrew Lumsdaine
williamr@2
    10
williamr@2
    11
// Compressed sparse row graph type
williamr@2
    12
williamr@2
    13
#ifndef BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP
williamr@2
    14
#define BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP
williamr@2
    15
williamr@2
    16
#include <vector>
williamr@2
    17
#include <utility>
williamr@2
    18
#include <algorithm>
williamr@2
    19
#include <climits>
williamr@2
    20
#include <iterator>
williamr@2
    21
#include <boost/graph/graph_traits.hpp>
williamr@2
    22
#include <boost/graph/properties.hpp>
williamr@2
    23
#include <boost/graph/detail/indexed_properties.hpp>
williamr@2
    24
#include <boost/iterator/counting_iterator.hpp>
williamr@2
    25
#include <boost/integer.hpp>
williamr@2
    26
#include <boost/iterator/iterator_facade.hpp>
williamr@2
    27
#include <boost/mpl/if.hpp>
williamr@2
    28
#include <boost/graph/graph_selectors.hpp>
williamr@2
    29
#include <boost/static_assert.hpp>
williamr@2
    30
williamr@2
    31
#ifdef BOOST_GRAPH_NO_BUNDLED_PROPERTIES
williamr@2
    32
#  error The Compressed Sparse Row graph only supports bundled properties.
williamr@2
    33
#  error You will need a compiler that conforms better to the C++ standard.
williamr@2
    34
#endif
williamr@2
    35
williamr@2
    36
namespace boost {
williamr@2
    37
williamr@2
    38
// A tag type indicating that the graph in question is a compressed
williamr@2
    39
// sparse row graph. This is an internal detail of the BGL.
williamr@2
    40
struct csr_graph_tag;
williamr@2
    41
williamr@2
    42
/****************************************************************************
williamr@2
    43
 * Local helper macros to reduce typing and clutter later on.               *
williamr@2
    44
 ****************************************************************************/
williamr@2
    45
#define BOOST_CSR_GRAPH_TEMPLATE_PARMS                                  \
williamr@2
    46
  typename Directed, typename VertexProperty, typename EdgeProperty,    \
williamr@2
    47
  typename GraphProperty, typename Vertex, typename EdgeIndex
williamr@2
    48
#define BOOST_CSR_GRAPH_TYPE                                            \
williamr@2
    49
   compressed_sparse_row_graph<Directed, VertexProperty, EdgeProperty,  \
williamr@2
    50
                               GraphProperty, Vertex, EdgeIndex>
williamr@2
    51
williamr@2
    52
// Forward declaration of CSR edge descriptor type, needed to pass to
williamr@2
    53
// indexed_edge_properties.
williamr@2
    54
template<typename Vertex, typename EdgeIndex>
williamr@2
    55
class csr_edge_descriptor;
williamr@2
    56
williamr@2
    57
/** Compressed sparse row graph.
williamr@2
    58
 *
williamr@2
    59
 * Vertex and EdgeIndex should be unsigned integral types and should
williamr@2
    60
 * specialize numeric_limits.
williamr@2
    61
 */
williamr@2
    62
template<typename Directed = directedS, 
williamr@2
    63
         typename VertexProperty = void,
williamr@2
    64
         typename EdgeProperty = void,
williamr@2
    65
         typename GraphProperty = no_property,
williamr@2
    66
         typename Vertex = std::size_t,
williamr@2
    67
         typename EdgeIndex = Vertex>
williamr@2
    68
class compressed_sparse_row_graph
williamr@2
    69
   : public detail::indexed_vertex_properties<BOOST_CSR_GRAPH_TYPE, VertexProperty,
williamr@2
    70
                                              Vertex>,
williamr@2
    71
     public detail::indexed_edge_properties<BOOST_CSR_GRAPH_TYPE, EdgeProperty,
williamr@2
    72
                                            csr_edge_descriptor<Vertex,
williamr@2
    73
                                                                EdgeIndex> >
williamr@2
    74
williamr@2
    75
{
williamr@2
    76
  typedef detail::indexed_vertex_properties<compressed_sparse_row_graph,
williamr@2
    77
                                            VertexProperty, Vertex>
williamr@2
    78
    inherited_vertex_properties;
williamr@2
    79
williamr@2
    80
  typedef detail::indexed_edge_properties<BOOST_CSR_GRAPH_TYPE, EdgeProperty,
williamr@2
    81
                                          csr_edge_descriptor<Vertex, EdgeIndex> >
williamr@2
    82
    inherited_edge_properties;
williamr@2
    83
williamr@2
    84
 public:
williamr@2
    85
  // For Property Graph
williamr@2
    86
  typedef GraphProperty graph_property_type;
williamr@2
    87
williamr@2
    88
 protected:
williamr@2
    89
  template<typename InputIterator>
williamr@2
    90
  void
williamr@2
    91
  maybe_reserve_edge_list_storage(InputIterator, InputIterator,
williamr@2
    92
                                  std::input_iterator_tag)
williamr@2
    93
  {
williamr@2
    94
    // Do nothing: we have no idea how much storage to reserve.
williamr@2
    95
  }
williamr@2
    96
williamr@2
    97
  template<typename InputIterator>
williamr@2
    98
  void
williamr@2
    99
  maybe_reserve_edge_list_storage(InputIterator first, InputIterator last,
williamr@2
   100
                                  std::forward_iterator_tag)
williamr@2
   101
  {
williamr@2
   102
    using std::distance;
williamr@2
   103
    typename std::iterator_traits<InputIterator>::difference_type n =
williamr@2
   104
      distance(first, last);
williamr@2
   105
    m_column.reserve(n);
williamr@2
   106
    inherited_edge_properties::reserve(n);
williamr@2
   107
  }
williamr@2
   108
williamr@2
   109
 public:
williamr@2
   110
  /* At this time, the compressed sparse row graph can only be used to
williamr@2
   111
   * create a directed graph. In the future, bidirectional and
williamr@2
   112
   * undirected CSR graphs will also be supported.
williamr@2
   113
   */
williamr@2
   114
  BOOST_STATIC_ASSERT((is_same<Directed, directedS>::value));
williamr@2
   115
williamr@2
   116
  // Concept requirements:
williamr@2
   117
  // For Graph
williamr@2
   118
  typedef Vertex vertex_descriptor;
williamr@2
   119
  typedef csr_edge_descriptor<Vertex, EdgeIndex> edge_descriptor;
williamr@2
   120
  typedef directed_tag directed_category;
williamr@2
   121
  typedef allow_parallel_edge_tag edge_parallel_category;
williamr@2
   122
williamr@2
   123
  class traversal_category: public incidence_graph_tag,
williamr@2
   124
                            public adjacency_graph_tag,
williamr@2
   125
                            public vertex_list_graph_tag,
williamr@2
   126
                            public edge_list_graph_tag {};
williamr@2
   127
williamr@2
   128
  static vertex_descriptor null_vertex() { return vertex_descriptor(-1); }
williamr@2
   129
williamr@2
   130
  // For VertexListGraph
williamr@2
   131
  typedef counting_iterator<Vertex> vertex_iterator;
williamr@2
   132
  typedef Vertex vertices_size_type;
williamr@2
   133
williamr@2
   134
  // For EdgeListGraph
williamr@2
   135
  typedef EdgeIndex edges_size_type;
williamr@2
   136
williamr@2
   137
  // For IncidenceGraph
williamr@2
   138
  class out_edge_iterator;
williamr@2
   139
  typedef EdgeIndex degree_size_type;
williamr@2
   140
williamr@2
   141
  // For AdjacencyGraph
williamr@2
   142
  typedef typename std::vector<Vertex>::const_iterator adjacency_iterator;
williamr@2
   143
williamr@2
   144
  // For EdgeListGraph
williamr@2
   145
  class edge_iterator;
williamr@2
   146
williamr@2
   147
  // For BidirectionalGraph (not implemented)
williamr@2
   148
  typedef void in_edge_iterator;
williamr@2
   149
williamr@2
   150
  // For internal use
williamr@2
   151
  typedef csr_graph_tag graph_tag;
williamr@2
   152
williamr@2
   153
  // Constructors
williamr@2
   154
williamr@2
   155
  // Default constructor: an empty graph.
williamr@2
   156
  compressed_sparse_row_graph()
williamr@2
   157
    : m_rowstart(1, EdgeIndex(0)), m_column(0), m_property(),
williamr@2
   158
      m_last_source(0) {}
williamr@2
   159
williamr@2
   160
  //  From number of vertices and sorted list of edges
williamr@2
   161
  template<typename InputIterator>
williamr@2
   162
  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
williamr@2
   163
                              vertices_size_type numverts,
williamr@2
   164
                              edges_size_type numedges = 0,
williamr@2
   165
                              const GraphProperty& prop = GraphProperty())
williamr@2
   166
    : inherited_vertex_properties(numverts), m_rowstart(numverts + 1),
williamr@2
   167
      m_column(0), m_property(prop), m_last_source(numverts)
williamr@2
   168
  {
williamr@2
   169
    // Reserving storage in advance can save us lots of time and
williamr@2
   170
    // memory, but it can only be done if we have forward iterators or
williamr@2
   171
    // the user has supplied the number of edges.
williamr@2
   172
    if (numedges == 0) {
williamr@2
   173
      typedef typename std::iterator_traits<InputIterator>::iterator_category
williamr@2
   174
        category;
williamr@2
   175
      maybe_reserve_edge_list_storage(edge_begin, edge_end, category());
williamr@2
   176
    } else {
williamr@2
   177
      m_column.reserve(numedges);
williamr@2
   178
    }
williamr@2
   179
williamr@2
   180
    EdgeIndex current_edge = 0;
williamr@2
   181
    Vertex current_vertex_plus_one = 1;
williamr@2
   182
    m_rowstart[0] = 0;
williamr@2
   183
    for (InputIterator ei = edge_begin; ei != edge_end; ++ei) {
williamr@2
   184
      Vertex src = ei->first;
williamr@2
   185
      Vertex tgt = ei->second;
williamr@2
   186
      for (; current_vertex_plus_one != src + 1; ++current_vertex_plus_one)
williamr@2
   187
        m_rowstart[current_vertex_plus_one] = current_edge;
williamr@2
   188
      m_column.push_back(tgt);
williamr@2
   189
      ++current_edge;
williamr@2
   190
    }
williamr@2
   191
williamr@2
   192
    // The remaining vertices have no edges
williamr@2
   193
    for (; current_vertex_plus_one != numverts + 1; ++current_vertex_plus_one)
williamr@2
   194
      m_rowstart[current_vertex_plus_one] = current_edge;
williamr@2
   195
williamr@2
   196
    // Default-construct properties for edges
williamr@2
   197
    inherited_edge_properties::resize(m_column.size());
williamr@2
   198
  }
williamr@2
   199
williamr@2
   200
  //  From number of vertices and sorted list of edges
williamr@2
   201
  template<typename InputIterator, typename EdgePropertyIterator>
williamr@2
   202
  compressed_sparse_row_graph(InputIterator edge_begin, InputIterator edge_end,
williamr@2
   203
                              EdgePropertyIterator ep_iter,
williamr@2
   204
                              vertices_size_type numverts,
williamr@2
   205
                              edges_size_type numedges = 0,
williamr@2
   206
                              const GraphProperty& prop = GraphProperty())
williamr@2
   207
    : inherited_vertex_properties(numverts), m_rowstart(numverts + 1),
williamr@2
   208
      m_column(0), m_property(prop), m_last_source(numverts)
williamr@2
   209
  {
williamr@2
   210
    // Reserving storage in advance can save us lots of time and
williamr@2
   211
    // memory, but it can only be done if we have forward iterators or
williamr@2
   212
    // the user has supplied the number of edges.
williamr@2
   213
    if (numedges == 0) {
williamr@2
   214
      typedef typename std::iterator_traits<InputIterator>::iterator_category
williamr@2
   215
        category;
williamr@2
   216
      maybe_reserve_edge_list_storage(edge_begin, edge_end, category());
williamr@2
   217
    } else {
williamr@2
   218
      m_column.reserve(numedges);
williamr@2
   219
    }
williamr@2
   220
williamr@2
   221
    EdgeIndex current_edge = 0;
williamr@2
   222
    Vertex current_vertex_plus_one = 1;
williamr@2
   223
    m_rowstart[0] = 0;
williamr@2
   224
    for (InputIterator ei = edge_begin; ei != edge_end; ++ei, ++ep_iter) {
williamr@2
   225
      Vertex src = ei->first;
williamr@2
   226
      Vertex tgt = ei->second;
williamr@2
   227
      for (; current_vertex_plus_one != src + 1; ++current_vertex_plus_one)
williamr@2
   228
        m_rowstart[current_vertex_plus_one] = current_edge;
williamr@2
   229
      m_column.push_back(tgt);
williamr@2
   230
      inherited_edge_properties::push_back(*ep_iter);
williamr@2
   231
      ++current_edge;
williamr@2
   232
    }
williamr@2
   233
williamr@2
   234
    // The remaining vertices have no edges
williamr@2
   235
    for (; current_vertex_plus_one != numverts + 1; ++current_vertex_plus_one)
williamr@2
   236
      m_rowstart[current_vertex_plus_one] = current_edge;
williamr@2
   237
  }
williamr@2
   238
williamr@2
   239
  //   Requires IncidenceGraph, a vertex index map, and a vertex(n, g) function
williamr@2
   240
  template<typename Graph, typename VertexIndexMap>
williamr@2
   241
  compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi,
williamr@2
   242
                              vertices_size_type numverts,
williamr@2
   243
                              edges_size_type numedges)
williamr@2
   244
    : m_property(), m_last_source(0)
williamr@2
   245
  {
williamr@2
   246
    assign(g, vi, numverts, numedges);
williamr@2
   247
  }
williamr@2
   248
williamr@2
   249
  //   Requires VertexListGraph and EdgeListGraph
williamr@2
   250
  template<typename Graph, typename VertexIndexMap>
williamr@2
   251
  compressed_sparse_row_graph(const Graph& g, const VertexIndexMap& vi)
williamr@2
   252
    : m_property(), m_last_source(0)
williamr@2
   253
  {
williamr@2
   254
    assign(g, vi, num_vertices(g), num_edges(g));
williamr@2
   255
  }
williamr@2
   256
williamr@2
   257
  // Requires vertex index map plus requirements of previous constructor
williamr@2
   258
  template<typename Graph>
williamr@2
   259
  explicit compressed_sparse_row_graph(const Graph& g)
williamr@2
   260
    : m_property(), m_last_source(0)
williamr@2
   261
  {
williamr@2
   262
    assign(g, get(vertex_index, g), num_vertices(g), num_edges(g));
williamr@2
   263
  }
williamr@2
   264
williamr@2
   265
  // From any graph (slow and uses a lot of memory)
williamr@2
   266
  //   Requires IncidenceGraph, a vertex index map, and a vertex(n, g) function
williamr@2
   267
  //   Internal helper function
williamr@2
   268
  template<typename Graph, typename VertexIndexMap>
williamr@2
   269
  void
williamr@2
   270
  assign(const Graph& g, const VertexIndexMap& vi,
williamr@2
   271
         vertices_size_type numverts, edges_size_type numedges)
williamr@2
   272
  {
williamr@2
   273
    inherited_vertex_properties::resize(numverts);
williamr@2
   274
    m_rowstart.resize(numverts + 1);
williamr@2
   275
    m_column.resize(numedges);
williamr@2
   276
    EdgeIndex current_edge = 0;
williamr@2
   277
    typedef typename boost::graph_traits<Graph>::vertex_descriptor g_vertex;
williamr@2
   278
    typedef typename boost::graph_traits<Graph>::edge_descriptor g_edge;
williamr@2
   279
    typedef typename boost::graph_traits<Graph>::out_edge_iterator
williamr@2
   280
      g_out_edge_iter;
williamr@2
   281
williamr@2
   282
    for (Vertex i = 0; i != numverts; ++i) {
williamr@2
   283
      m_rowstart[i] = current_edge;
williamr@2
   284
      g_vertex v = vertex(i, g);
williamr@2
   285
      EdgeIndex num_edges_before_this_vertex = current_edge;
williamr@2
   286
      g_out_edge_iter ei, ei_end;
williamr@2
   287
      for (tie(ei, ei_end) = out_edges(v, g); ei != ei_end; ++ei) {
williamr@2
   288
        m_column[current_edge++] = get(vi, target(*ei, g));
williamr@2
   289
      }
williamr@2
   290
      std::sort(m_column.begin() + num_edges_before_this_vertex,
williamr@2
   291
                m_column.begin() + current_edge);
williamr@2
   292
    }
williamr@2
   293
    m_rowstart[numverts] = current_edge;
williamr@2
   294
    m_last_source = numverts;
williamr@2
   295
  }
williamr@2
   296
williamr@2
   297
  // Requires the above, plus VertexListGraph and EdgeListGraph
williamr@2
   298
  template<typename Graph, typename VertexIndexMap>
williamr@2
   299
  void assign(const Graph& g, const VertexIndexMap& vi)
williamr@2
   300
  {
williamr@2
   301
    assign(g, vi, num_vertices(g), num_edges(g));
williamr@2
   302
  }
williamr@2
   303
williamr@2
   304
  // Requires the above, plus a vertex_index map.
williamr@2
   305
  template<typename Graph>
williamr@2
   306
  void assign(const Graph& g)
williamr@2
   307
  {
williamr@2
   308
    assign(g, get(vertex_index, g), num_vertices(g), num_edges(g));
williamr@2
   309
  }
williamr@2
   310
williamr@2
   311
  using inherited_vertex_properties::operator[];
williamr@2
   312
  using inherited_edge_properties::operator[];
williamr@2
   313
williamr@2
   314
  // private: non-portable, requires friend templates
williamr@2
   315
  inherited_vertex_properties&       vertex_properties()       {return *this;}
williamr@2
   316
  const inherited_vertex_properties& vertex_properties() const {return *this;}
williamr@2
   317
  inherited_edge_properties&       edge_properties()       { return *this; }
williamr@2
   318
  const inherited_edge_properties& edge_properties() const { return *this; }
williamr@2
   319
williamr@2
   320
  std::vector<EdgeIndex> m_rowstart;
williamr@2
   321
  std::vector<Vertex> m_column;
williamr@2
   322
  GraphProperty m_property;
williamr@2
   323
  Vertex m_last_source; // Last source of added edge, plus one
williamr@2
   324
};
williamr@2
   325
williamr@2
   326
template<typename Vertex, typename EdgeIndex>
williamr@2
   327
class csr_edge_descriptor
williamr@2
   328
{
williamr@2
   329
 public:
williamr@2
   330
  Vertex src;
williamr@2
   331
  EdgeIndex idx;
williamr@2
   332
williamr@2
   333
  csr_edge_descriptor(Vertex src, EdgeIndex idx): src(src), idx(idx) {}
williamr@2
   334
  csr_edge_descriptor(): src(0), idx(0) {}
williamr@2
   335
williamr@2
   336
  bool operator==(const csr_edge_descriptor& e) const {return idx == e.idx;}
williamr@2
   337
  bool operator!=(const csr_edge_descriptor& e) const {return idx != e.idx;}
williamr@2
   338
  bool operator<(const csr_edge_descriptor& e) const {return idx < e.idx;}
williamr@2
   339
  bool operator>(const csr_edge_descriptor& e) const {return idx > e.idx;}
williamr@2
   340
  bool operator<=(const csr_edge_descriptor& e) const {return idx <= e.idx;}
williamr@2
   341
  bool operator>=(const csr_edge_descriptor& e) const {return idx >= e.idx;}
williamr@2
   342
};
williamr@2
   343
williamr@2
   344
// Construction functions
williamr@2
   345
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   346
inline Vertex
williamr@2
   347
add_vertex(BOOST_CSR_GRAPH_TYPE& g) {
williamr@2
   348
  Vertex old_num_verts_plus_one = g.m_rowstart.size();
williamr@2
   349
  g.m_rowstart.push_back(EdgeIndex(0));
williamr@2
   350
  return old_num_verts_plus_one - 1;
williamr@2
   351
}
williamr@2
   352
williamr@2
   353
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   354
inline Vertex
williamr@2
   355
add_vertices(typename BOOST_CSR_GRAPH_TYPE::vertices_size_type count, BOOST_CSR_GRAPH_TYPE& g) {
williamr@2
   356
  Vertex old_num_verts_plus_one = g.m_rowstart.size();
williamr@2
   357
  g.m_rowstart.resize(old_num_verts_plus_one + count, EdgeIndex(0));
williamr@2
   358
  return old_num_verts_plus_one - 1;
williamr@2
   359
}
williamr@2
   360
williamr@2
   361
// This function requires that (src, tgt) be lexicographically at least as
williamr@2
   362
// large as the largest edge in the graph so far
williamr@2
   363
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   364
inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor
williamr@2
   365
add_edge(Vertex src, Vertex tgt, BOOST_CSR_GRAPH_TYPE& g) {
williamr@2
   366
  assert ((g.m_last_source == 0 || src >= g.m_last_source - 1) &&
williamr@2
   367
          src < num_vertices(g));
williamr@2
   368
  EdgeIndex num_edges_orig = g.m_column.size();
williamr@2
   369
  for (; g.m_last_source <= src; ++g.m_last_source)
williamr@2
   370
    g.m_rowstart[g.m_last_source] = num_edges_orig;
williamr@2
   371
  g.m_rowstart[src + 1] = num_edges_orig + 1;
williamr@2
   372
  g.m_column.push_back(tgt);
williamr@2
   373
  typedef typename BOOST_CSR_GRAPH_TYPE::edge_push_back_type push_back_type;
williamr@2
   374
  g.edge_properties().push_back(push_back_type());
williamr@2
   375
  return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, num_edges_orig);
williamr@2
   376
}
williamr@2
   377
williamr@2
   378
// This function requires that (src, tgt) be lexicographically at least as
williamr@2
   379
// large as the largest edge in the graph so far
williamr@2
   380
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   381
inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor
williamr@2
   382
add_edge(Vertex src, Vertex tgt,
williamr@2
   383
         typename BOOST_CSR_GRAPH_TYPE::edge_bundled const& p,
williamr@2
   384
         BOOST_CSR_GRAPH_TYPE& g) {
williamr@2
   385
  assert ((g.m_last_source == 0 || src >= g.m_last_source - 1) &&
williamr@2
   386
          src < num_vertices(g));
williamr@2
   387
  EdgeIndex num_edges_orig = g.m_column.size();
williamr@2
   388
  for (; g.m_last_source <= src; ++g.m_last_source)
williamr@2
   389
    g.m_rowstart[g.m_last_source] = num_edges_orig;
williamr@2
   390
  g.m_rowstart[src + 1] = num_edges_orig + 1;
williamr@2
   391
  g.m_column.push_back(tgt);
williamr@2
   392
  g.edge_properties().push_back(p);
williamr@2
   393
  return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, num_edges_orig);
williamr@2
   394
}
williamr@2
   395
williamr@2
   396
williamr@2
   397
// From VertexListGraph
williamr@2
   398
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   399
inline Vertex
williamr@2
   400
num_vertices(const BOOST_CSR_GRAPH_TYPE& g) {
williamr@2
   401
  return g.m_rowstart.size() - 1;
williamr@2
   402
}
williamr@2
   403
williamr@2
   404
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   405
std::pair<counting_iterator<Vertex>, counting_iterator<Vertex> >
williamr@2
   406
inline vertices(const BOOST_CSR_GRAPH_TYPE& g) {
williamr@2
   407
  return std::make_pair(counting_iterator<Vertex>(0),
williamr@2
   408
                        counting_iterator<Vertex>(num_vertices(g)));
williamr@2
   409
}
williamr@2
   410
williamr@2
   411
// From IncidenceGraph
williamr@2
   412
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   413
class BOOST_CSR_GRAPH_TYPE::out_edge_iterator
williamr@2
   414
  : public iterator_facade<typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator,
williamr@2
   415
                           typename BOOST_CSR_GRAPH_TYPE::edge_descriptor,
williamr@2
   416
                           std::random_access_iterator_tag,
williamr@2
   417
                           const typename BOOST_CSR_GRAPH_TYPE::edge_descriptor&,
williamr@2
   418
                           typename int_t<CHAR_BIT * sizeof(EdgeIndex)>::fast>
williamr@2
   419
{
williamr@2
   420
 public:
williamr@2
   421
  typedef typename int_t<CHAR_BIT * sizeof(EdgeIndex)>::fast difference_type;
williamr@2
   422
williamr@2
   423
  out_edge_iterator() {}
williamr@2
   424
  // Implicit copy constructor OK
williamr@2
   425
  explicit out_edge_iterator(edge_descriptor edge) : m_edge(edge) { }
williamr@2
   426
williamr@2
   427
 private:
williamr@2
   428
  // iterator_facade requirements
williamr@2
   429
  const edge_descriptor& dereference() const { return m_edge; }
williamr@2
   430
williamr@2
   431
  bool equal(const out_edge_iterator& other) const
williamr@2
   432
  { return m_edge == other.m_edge; }
williamr@2
   433
williamr@2
   434
  void increment() { ++m_edge.idx; }
williamr@2
   435
  void decrement() { ++m_edge.idx; }
williamr@2
   436
  void advance(difference_type n) { m_edge.idx += n; }
williamr@2
   437
williamr@2
   438
  difference_type distance_to(const out_edge_iterator& other) const
williamr@2
   439
  { return other.m_edge.idx - m_edge.idx; }
williamr@2
   440
williamr@2
   441
  edge_descriptor m_edge;
williamr@2
   442
williamr@2
   443
  friend class iterator_core_access;
williamr@2
   444
};
williamr@2
   445
williamr@2
   446
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   447
inline Vertex
williamr@2
   448
source(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e,
williamr@2
   449
       const BOOST_CSR_GRAPH_TYPE&)
williamr@2
   450
{
williamr@2
   451
  return e.src;
williamr@2
   452
}
williamr@2
   453
williamr@2
   454
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   455
inline Vertex
williamr@2
   456
target(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e,
williamr@2
   457
       const BOOST_CSR_GRAPH_TYPE& g)
williamr@2
   458
{
williamr@2
   459
  return g.m_column[e.idx];
williamr@2
   460
}
williamr@2
   461
williamr@2
   462
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   463
inline std::pair<typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator,
williamr@2
   464
                 typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator>
williamr@2
   465
out_edges(Vertex v, const BOOST_CSR_GRAPH_TYPE& g)
williamr@2
   466
{
williamr@2
   467
  typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor ed;
williamr@2
   468
  typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator it;
williamr@2
   469
  EdgeIndex v_row_start = g.m_rowstart[v];
williamr@2
   470
  EdgeIndex next_row_start = g.m_rowstart[v + 1];
williamr@2
   471
  return std::make_pair(it(ed(v, v_row_start)),
williamr@2
   472
                        it(ed(v, (std::max)(v_row_start, next_row_start))));
williamr@2
   473
}
williamr@2
   474
williamr@2
   475
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   476
inline EdgeIndex
williamr@2
   477
out_degree(Vertex v, const BOOST_CSR_GRAPH_TYPE& g)
williamr@2
   478
{
williamr@2
   479
  EdgeIndex v_row_start = g.m_rowstart[v];
williamr@2
   480
  EdgeIndex next_row_start = g.m_rowstart[v + 1];
williamr@2
   481
  return (std::max)(v_row_start, next_row_start) - v_row_start;
williamr@2
   482
}
williamr@2
   483
williamr@2
   484
// From AdjacencyGraph
williamr@2
   485
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   486
inline std::pair<typename BOOST_CSR_GRAPH_TYPE::adjacency_iterator,
williamr@2
   487
                 typename BOOST_CSR_GRAPH_TYPE::adjacency_iterator>
williamr@2
   488
adjacent_vertices(Vertex v, const BOOST_CSR_GRAPH_TYPE& g)
williamr@2
   489
{
williamr@2
   490
  EdgeIndex v_row_start = g.m_rowstart[v];
williamr@2
   491
  EdgeIndex next_row_start = g.m_rowstart[v + 1];
williamr@2
   492
  return std::make_pair(g.m_column.begin() + v_row_start,
williamr@2
   493
                        g.m_column.begin() +
williamr@2
   494
                                (std::max)(v_row_start, next_row_start));
williamr@2
   495
}
williamr@2
   496
williamr@2
   497
// Extra, common functions
williamr@2
   498
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   499
inline typename graph_traits<BOOST_CSR_GRAPH_TYPE>::vertex_descriptor
williamr@2
   500
vertex(typename graph_traits<BOOST_CSR_GRAPH_TYPE>::vertex_descriptor i, 
williamr@2
   501
       const BOOST_CSR_GRAPH_TYPE&)
williamr@2
   502
{
williamr@2
   503
  return i;
williamr@2
   504
}
williamr@2
   505
williamr@2
   506
// Unlike for an adjacency_matrix, edge_range and edge take lg(out_degree(i))
williamr@2
   507
// time
williamr@2
   508
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   509
inline std::pair<typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator,
williamr@2
   510
                 typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator>
williamr@2
   511
edge_range(Vertex i, Vertex j, const BOOST_CSR_GRAPH_TYPE& g)
williamr@2
   512
{
williamr@2
   513
  typedef typename std::vector<Vertex>::const_iterator adj_iter;
williamr@2
   514
  typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator out_edge_iter;
williamr@2
   515
  typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor edge_desc;
williamr@2
   516
  std::pair<adj_iter, adj_iter> raw_adjacencies = adjacent_vertices(i, g);
williamr@2
   517
  std::pair<adj_iter, adj_iter> adjacencies =
williamr@2
   518
    std::equal_range(raw_adjacencies.first, raw_adjacencies.second, j);
williamr@2
   519
  EdgeIndex idx_begin = adjacencies.first - g.m_column.begin();
williamr@2
   520
  EdgeIndex idx_end = adjacencies.second - g.m_column.begin();
williamr@2
   521
  return std::make_pair(out_edge_iter(edge_desc(i, idx_begin)),
williamr@2
   522
                        out_edge_iter(edge_desc(i, idx_end)));
williamr@2
   523
}
williamr@2
   524
williamr@2
   525
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   526
inline std::pair<typename BOOST_CSR_GRAPH_TYPE::edge_descriptor, bool>
williamr@2
   527
edge(Vertex i, Vertex j, const BOOST_CSR_GRAPH_TYPE& g)
williamr@2
   528
{
williamr@2
   529
  typedef typename BOOST_CSR_GRAPH_TYPE::out_edge_iterator out_edge_iter;
williamr@2
   530
  std::pair<out_edge_iter, out_edge_iter> range = edge_range(i, j, g);
williamr@2
   531
  if (range.first == range.second)
williamr@2
   532
    return std::make_pair(typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(),
williamr@2
   533
                          false);
williamr@2
   534
  else
williamr@2
   535
    return std::make_pair(*range.first, true);
williamr@2
   536
}
williamr@2
   537
williamr@2
   538
// Find an edge given its index in the graph
williamr@2
   539
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   540
inline typename BOOST_CSR_GRAPH_TYPE::edge_descriptor
williamr@2
   541
edge_from_index(EdgeIndex idx, const BOOST_CSR_GRAPH_TYPE& g)
williamr@2
   542
{
williamr@2
   543
  typedef typename std::vector<EdgeIndex>::const_iterator row_start_iter;
williamr@2
   544
  assert (idx < num_edges(g));
williamr@2
   545
  row_start_iter src_plus_1 =
williamr@2
   546
    std::upper_bound(g.m_rowstart.begin(),
williamr@2
   547
                     g.m_rowstart.begin() + g.m_last_source + 1,
williamr@2
   548
                     idx);
williamr@2
   549
    // Get last source whose rowstart is at most idx
williamr@2
   550
    // upper_bound returns this position plus 1
williamr@2
   551
  Vertex src = (src_plus_1 - g.m_rowstart.begin()) - 1;
williamr@2
   552
  return typename BOOST_CSR_GRAPH_TYPE::edge_descriptor(src, idx);
williamr@2
   553
}
williamr@2
   554
williamr@2
   555
// From EdgeListGraph
williamr@2
   556
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   557
class BOOST_CSR_GRAPH_TYPE::edge_iterator
williamr@2
   558
{
williamr@2
   559
 public:
williamr@2
   560
  typedef std::forward_iterator_tag iterator_category;
williamr@2
   561
  typedef edge_descriptor value_type;
williamr@2
   562
williamr@2
   563
  typedef const edge_descriptor* pointer;
williamr@2
   564
williamr@2
   565
  typedef edge_descriptor reference;
williamr@2
   566
  typedef typename int_t<CHAR_BIT * sizeof(EdgeIndex)>::fast difference_type;
williamr@2
   567
williamr@2
   568
  edge_iterator() : rowstart_array(0), current_edge(), end_of_this_vertex(0) {}
williamr@2
   569
williamr@2
   570
  edge_iterator(const compressed_sparse_row_graph& graph,
williamr@2
   571
                edge_descriptor current_edge,
williamr@2
   572
                EdgeIndex end_of_this_vertex)
williamr@2
   573
    : rowstart_array(&graph.m_rowstart[0]), current_edge(current_edge),
williamr@2
   574
      end_of_this_vertex(end_of_this_vertex) {}
williamr@2
   575
williamr@2
   576
  // From InputIterator
williamr@2
   577
  reference operator*() const { return current_edge; }
williamr@2
   578
  pointer operator->() const { return &current_edge; }
williamr@2
   579
williamr@2
   580
  bool operator==(const edge_iterator& o) const {
williamr@2
   581
    return current_edge == o.current_edge;
williamr@2
   582
  }
williamr@2
   583
  bool operator!=(const edge_iterator& o) const {
williamr@2
   584
    return current_edge != o.current_edge;
williamr@2
   585
  }
williamr@2
   586
williamr@2
   587
  edge_iterator& operator++() {
williamr@2
   588
    ++current_edge.idx;
williamr@2
   589
    while (current_edge.idx == end_of_this_vertex) {
williamr@2
   590
      ++current_edge.src;
williamr@2
   591
      end_of_this_vertex = rowstart_array[current_edge.src + 1];
williamr@2
   592
    }
williamr@2
   593
    return *this;
williamr@2
   594
  }
williamr@2
   595
williamr@2
   596
  edge_iterator operator++(int) {
williamr@2
   597
    edge_iterator temp = *this;
williamr@2
   598
    ++*this;
williamr@2
   599
    return temp;
williamr@2
   600
  }
williamr@2
   601
williamr@2
   602
 private:
williamr@2
   603
  const EdgeIndex* rowstart_array;
williamr@2
   604
  edge_descriptor current_edge;
williamr@2
   605
  EdgeIndex end_of_this_vertex;
williamr@2
   606
};
williamr@2
   607
williamr@2
   608
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   609
inline EdgeIndex
williamr@2
   610
num_edges(const BOOST_CSR_GRAPH_TYPE& g)
williamr@2
   611
{
williamr@2
   612
  return g.m_column.size();
williamr@2
   613
}
williamr@2
   614
williamr@2
   615
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   616
std::pair<typename BOOST_CSR_GRAPH_TYPE::edge_iterator,
williamr@2
   617
          typename BOOST_CSR_GRAPH_TYPE::edge_iterator>
williamr@2
   618
edges(const BOOST_CSR_GRAPH_TYPE& g)
williamr@2
   619
{
williamr@2
   620
  typedef typename BOOST_CSR_GRAPH_TYPE::edge_iterator ei;
williamr@2
   621
  typedef typename BOOST_CSR_GRAPH_TYPE::edge_descriptor edgedesc;
williamr@2
   622
  if (g.m_rowstart.size() == 1 || g.m_column.empty()) {
williamr@2
   623
    return std::make_pair(ei(), ei());
williamr@2
   624
  } else {
williamr@2
   625
    // Find the first vertex that has outgoing edges
williamr@2
   626
    Vertex src = 0;
williamr@2
   627
    while (g.m_rowstart[src + 1] == 0) ++src;
williamr@2
   628
    return std::make_pair(ei(g, edgedesc(src, 0), g.m_rowstart[src + 1]),
williamr@2
   629
                          ei(g, edgedesc(num_vertices(g), g.m_column.size()), 0));
williamr@2
   630
  }
williamr@2
   631
}
williamr@2
   632
williamr@2
   633
// For Property Graph
williamr@2
   634
williamr@2
   635
// Graph properties
williamr@2
   636
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, class Tag, class Value>
williamr@2
   637
inline void
williamr@2
   638
set_property(BOOST_CSR_GRAPH_TYPE& g, Tag, const Value& value)
williamr@2
   639
{
williamr@2
   640
  get_property_value(g.m_property, Tag()) = value;
williamr@2
   641
}
williamr@2
   642
williamr@2
   643
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, class Tag>
williamr@2
   644
inline
williamr@2
   645
typename graph_property<BOOST_CSR_GRAPH_TYPE, Tag>::type&
williamr@2
   646
get_property(BOOST_CSR_GRAPH_TYPE& g, Tag)
williamr@2
   647
{
williamr@2
   648
  return get_property_value(g.m_property, Tag());
williamr@2
   649
}
williamr@2
   650
williamr@2
   651
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, class Tag>
williamr@2
   652
inline
williamr@2
   653
const
williamr@2
   654
typename graph_property<BOOST_CSR_GRAPH_TYPE, Tag>::type&
williamr@2
   655
get_property(const BOOST_CSR_GRAPH_TYPE& g, Tag)
williamr@2
   656
{
williamr@2
   657
  return get_property_value(g.m_property, Tag());
williamr@2
   658
}
williamr@2
   659
williamr@2
   660
// Add edge_index property map
williamr@2
   661
template<typename Index, typename Descriptor>
williamr@2
   662
struct csr_edge_index_map
williamr@2
   663
{
williamr@2
   664
  typedef Index                     value_type;
williamr@2
   665
  typedef Index                     reference;
williamr@2
   666
  typedef Descriptor                key_type;
williamr@2
   667
  typedef readable_property_map_tag category;
williamr@2
   668
};
williamr@2
   669
williamr@2
   670
template<typename Index, typename Descriptor>
williamr@2
   671
inline Index
williamr@2
   672
get(const csr_edge_index_map<Index, Descriptor>&,
williamr@2
   673
    const typename csr_edge_index_map<Index, Descriptor>::key_type& key)
williamr@2
   674
{
williamr@2
   675
  return key.idx;
williamr@2
   676
}
williamr@2
   677
williamr@2
   678
// Doing the right thing here (by unifying with vertex_index_t and
williamr@2
   679
// edge_index_t) breaks GCC.
williamr@2
   680
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename Tag>
williamr@2
   681
struct property_map<BOOST_CSR_GRAPH_TYPE, Tag>
williamr@2
   682
{
williamr@2
   683
private:
williamr@2
   684
  typedef identity_property_map vertex_index_type;
williamr@2
   685
  typedef typename graph_traits<BOOST_CSR_GRAPH_TYPE>::edge_descriptor
williamr@2
   686
    edge_descriptor;
williamr@2
   687
  typedef csr_edge_index_map<EdgeIndex, edge_descriptor> edge_index_type;
williamr@2
   688
williamr@2
   689
  typedef typename mpl::if_<is_same<Tag, edge_index_t>,
williamr@2
   690
                            edge_index_type,
williamr@2
   691
                            detail::error_property_not_found>::type
williamr@2
   692
    edge_or_none;
williamr@2
   693
williamr@2
   694
public:
williamr@2
   695
  typedef typename mpl::if_<is_same<Tag, vertex_index_t>,
williamr@2
   696
                            vertex_index_type,
williamr@2
   697
                            edge_or_none>::type type;
williamr@2
   698
williamr@2
   699
  typedef type const_type;
williamr@2
   700
};
williamr@2
   701
williamr@2
   702
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   703
inline identity_property_map
williamr@2
   704
get(vertex_index_t, const BOOST_CSR_GRAPH_TYPE&)
williamr@2
   705
{
williamr@2
   706
  return identity_property_map();
williamr@2
   707
}
williamr@2
   708
williamr@2
   709
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   710
inline Vertex
williamr@2
   711
get(vertex_index_t,
williamr@2
   712
    const BOOST_CSR_GRAPH_TYPE&, Vertex v)
williamr@2
   713
{
williamr@2
   714
  return v;
williamr@2
   715
}
williamr@2
   716
williamr@2
   717
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   718
inline typename property_map<BOOST_CSR_GRAPH_TYPE, edge_index_t>::const_type
williamr@2
   719
get(edge_index_t, const BOOST_CSR_GRAPH_TYPE&)
williamr@2
   720
{
williamr@2
   721
  typedef typename property_map<BOOST_CSR_GRAPH_TYPE, edge_index_t>::const_type
williamr@2
   722
    result_type;
williamr@2
   723
  return result_type();
williamr@2
   724
}
williamr@2
   725
williamr@2
   726
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
williamr@2
   727
inline EdgeIndex
williamr@2
   728
get(edge_index_t, const BOOST_CSR_GRAPH_TYPE&,
williamr@2
   729
    typename BOOST_CSR_GRAPH_TYPE::edge_descriptor e)
williamr@2
   730
{
williamr@2
   731
  return e.idx;
williamr@2
   732
}
williamr@2
   733
williamr@2
   734
// Support for bundled properties
williamr@2
   735
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename T, typename Bundle>
williamr@2
   736
struct property_map<BOOST_CSR_GRAPH_TYPE, T Bundle::*>
williamr@2
   737
{
williamr@2
   738
private:
williamr@2
   739
  typedef graph_traits<BOOST_CSR_GRAPH_TYPE> traits;
williamr@2
   740
  typedef VertexProperty vertex_bundled;
williamr@2
   741
  typedef EdgeProperty edge_bundled;
williamr@2
   742
  typedef typename ct_if<(detail::is_vertex_bundle<vertex_bundled, edge_bundled, Bundle>::value),
williamr@2
   743
                     typename traits::vertex_descriptor,
williamr@2
   744
                     typename traits::edge_descriptor>::type
williamr@2
   745
    descriptor;
williamr@2
   746
williamr@2
   747
public:
williamr@2
   748
  typedef bundle_property_map<BOOST_CSR_GRAPH_TYPE, descriptor, Bundle, T>
williamr@2
   749
    type;
williamr@2
   750
  typedef bundle_property_map<const BOOST_CSR_GRAPH_TYPE, descriptor, Bundle,
williamr@2
   751
                              const T> const_type;
williamr@2
   752
};
williamr@2
   753
williamr@2
   754
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename T, typename Bundle>
williamr@2
   755
inline
williamr@2
   756
typename property_map<BOOST_CSR_GRAPH_TYPE, T Bundle::*>::type
williamr@2
   757
get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE& g)
williamr@2
   758
{
williamr@2
   759
  typedef typename property_map<BOOST_CSR_GRAPH_TYPE,
williamr@2
   760
                                T Bundle::*>::type
williamr@2
   761
    result_type;
williamr@2
   762
  return result_type(&g, p);
williamr@2
   763
}
williamr@2
   764
williamr@2
   765
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename T, typename Bundle>
williamr@2
   766
inline
williamr@2
   767
typename property_map<BOOST_CSR_GRAPH_TYPE, T Bundle::*>::const_type
williamr@2
   768
get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE const & g)
williamr@2
   769
{
williamr@2
   770
  typedef typename property_map<BOOST_CSR_GRAPH_TYPE,
williamr@2
   771
                                T Bundle::*>::const_type
williamr@2
   772
    result_type;
williamr@2
   773
  return result_type(&g, p);
williamr@2
   774
}
williamr@2
   775
williamr@2
   776
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename T, typename Bundle,
williamr@2
   777
         typename Key>
williamr@2
   778
inline T
williamr@2
   779
get(T Bundle::* p, BOOST_CSR_GRAPH_TYPE const & g,
williamr@2
   780
    const Key& key)
williamr@2
   781
{
williamr@2
   782
  return get(get(p, g), key);
williamr@2
   783
}
williamr@2
   784
williamr@2
   785
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename T, typename Bundle,
williamr@2
   786
         typename Key>
williamr@2
   787
inline void
williamr@2
   788
put(T Bundle::* p, BOOST_CSR_GRAPH_TYPE& g,
williamr@2
   789
    const Key& key, const T& value)
williamr@2
   790
{
williamr@2
   791
  put(get(p, g), key, value);
williamr@2
   792
}
williamr@2
   793
williamr@2
   794
#undef BOOST_CSR_GRAPH_TYPE
williamr@2
   795
#undef BOOST_CSR_GRAPH_TEMPLATE_PARMS
williamr@2
   796
williamr@2
   797
} // end namespace boost
williamr@2
   798
williamr@2
   799
#endif // BOOST_GRAPH_COMPRESSED_SPARSE_ROW_GRAPH_HPP