# HG changeset patch
# User Nathann Cohen <nathann.cohen@gmail.com>
# Date 1351715654 -3600
# Node ID e587e8ffc4f77b0e87d6b9d5fa76911125a04632
# Parent  b5a9c110053dae0b2cf8d402fb25d10dec13c6bd
[mq]: ddddddddddddddd

diff --git a/sage/graphs/base/static_sparse_graph.pyx b/sage/graphs/base/static_sparse_graph.pyx
--- a/sage/graphs/base/static_sparse_graph.pyx
+++ b/sage/graphs/base/static_sparse_graph.pyx
@@ -474,3 +474,137 @@
     free_short_digraph(gr)
     return answer
 
+def girth(G):
+    r"""
+    Computes the girth of a graph.
+
+    The girth is the length of the shortest cycle in the graph. Graphs without
+    cycles have infinite girth.
+
+    .. SEEALSO:
+
+       * :meth:`sage.graphs.generic_graph.GenericGraph.girth`
+
+    EXAMPLES::
+
+        sage: from sage.graphs.base.static_sparse_graph import girth
+        sage: girth(graphs.PetersenGraph())
+    """
+    from sage.graphs.graph import Graph
+    if not isinstance(G, Graph):
+        raise ValueError("This function is only defined on Graph objects.")
+
+    # Stupid stuff
+    if G.size() == 0:
+        from sage.rings.infinity import Infinity
+        return Infinity
+
+    if G.has_loops():
+        return 1
+
+    cdef int n = G.order()
+
+    if G.has_multiple_edges():
+        return 2
+
+    # Turan's theorem
+    m = G.size()
+    n = G.order()
+    if m > (n>>1)*(n>>1) + (n>>1)*(n%1):
+        return 3
+
+    # End of stupid stuff
+    cdef short_digraph g
+    init_short_digraph(g, G)
+
+    # We do many BFS, one per vertex. At each step we go through the vertices at
+    # distance d from the source. Each of these classes we call a "layer".
+    cdef bitset_t current_layer, next_layer
+    bitset_init(current_layer, n)
+    bitset_init(next_layer, n)
+
+    # Vertices we have met during the current BFS
+    cdef bitset_t seen
+    bitset_init(seen, n)
+
+    # The queue we need for a BFS
+    cdef int* queue = <int *> sage_malloc(n*sizeof(int))
+
+    # The queue remembers the list of vertices we have to explore. The following
+    # two variables indicate the end of the list of vertices which belong to the
+    # current layer, and the end of the next layer.
+    cdef int current_layer_end, next_layer_end
+
+    cdef int source
+    cdef int i,u
+    cdef ushort * ptr_v
+
+    # The distance from the source
+    cdef int d
+    cdef int best_girth = n+1
+
+    for source in range(n):
+        i = 0
+        d = 0
+        current_layer_end = 1
+        next_layer_end = 1
+        queue[0] = source
+        bitset_set_first_n(seen, 0)
+        bitset_set_first_n(current_layer, 0)
+        bitset_set_first_n(next_layer, 0)
+        bitset_add(current_layer,source)
+        bitset_add(seen,source)
+
+        # While we have things to explore, while the current best girth found is
+        # smaller than what we have any hope to find by continuing to explore.
+        while i < current_layer_end and d < 2*best_girth+1:
+
+            while i < current_layer_end:
+
+                # Picking the next neighbor from the queue
+                u = queue[i]
+                ptr_v = g.neighbors[u]
+
+                # Iterating on u's neighbors
+                while ptr_v < g.neighbors[u+1]:
+
+                    # If we found a new vertex
+                    if not bitset_in(seen, ptr_v[0]):
+                        bitset_add(seen, ptr_v[0])
+                        bitset_add(next_layer, ptr_v[0])
+                        queue[next_layer_end] = ptr_v[0]
+                        next_layer_end += 1
+
+                    # If the neighbor is already in the next layer
+                    elif bitset_in(next_layer, ptr_v[0]):
+                        best_girth = min(best_girth,2*d+2)
+
+                    elif bitset_in(current_layer, ptr_v[0]):
+                        # Found a triangle
+                        if d == 1:
+                            bitset_free(next_layer)
+                            bitset_free(current_layer)
+                            bitset_free(seen)
+                            return 3
+                        # Otherwise
+                        else:
+                            best_girth = min(best_girth,2*d+1)
+
+                    ptr_v+=1
+                i+=1
+
+            # Changing layers
+            d += 1
+            bitset_copy(current_layer, next_layer)
+            bitset_set_first_n(next_layer, 0)
+            current_layer_end = next_layer_end
+
+    bitset_free(next_layer)
+    bitset_free(current_layer)
+    bitset_free(seen)
+
+    if best_girth == n+1:
+        from sage.rings.infinity import Infinity
+        return Infinity
+    else:
+        return best_girth
diff --git a/sage/graphs/generic_graph.py b/sage/graphs/generic_graph.py
--- a/sage/graphs/generic_graph.py
+++ b/sage/graphs/generic_graph.py
@@ -11968,7 +11968,6 @@
            sage: g.girth()
            2
         """
-
         # Cases where girth <= 2
         if self.has_loops():
             return 1
