Skip to content

Commit 078e3e1

Browse files
committed
Documenting panics
1 parent 0d83d5e commit 078e3e1

File tree

7 files changed

+77
-26
lines changed

7 files changed

+77
-26
lines changed

src/arq_tree.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ where
6060
}
6161
}
6262

63-
/// Performs the endomorphism f on all entries from l to r, inclusive.
63+
/// Applies the endomorphism f to all entries from l to r, inclusive.
6464
pub fn modify(&mut self, mut l: usize, mut r: usize, f: &T::F) {
6565
l += self.d.len();
6666
r += self.d.len();
@@ -113,9 +113,9 @@ pub trait ArqSpec {
113113
fn compose(f: &Self::F, g: &Self::F) -> Self::F;
114114
/// Require for all f,a,b: apply(f, op(a, b)) = op(apply(f, a), apply(f, b))
115115
fn apply(f: &Self::F, a: &Self::M) -> Self::M;
116-
/// Require for alla,b,c: op(a, op(b, c)) = op(op(a, b), c)
116+
/// Require for all a,b,c: op(a, op(b, c)) = op(op(a, b), c)
117117
fn op(a: &Self::M, b: &Self::M) -> Self::M;
118-
/// Require all a: op(a, identity()) = op(identity(), a) = a
118+
/// Require for all a: op(a, identity()) = op(identity(), a) = a
119119
fn identity() -> Self::M;
120120
}
121121

@@ -128,6 +128,10 @@ pub trait ArqSpec {
128128
/// of a_i. Now check that f_c((a, s)) = (c*s, s) is indeed an endomorphism:
129129
/// f_c((a,s)+(b,t)) = f_c((a+b,s+t)) = (c*(s+t),s+t) = (c*s,s)+(c*t,t) =
130130
/// f_c((a,s)) + f_c((b,t)).
131+
///
132+
/// # Panics
133+
///
134+
/// Associated functions will panic on overflow.
131135
pub struct AssignAdd;
132136

133137
impl ArqSpec for AssignAdd {

src/graph/connectivity.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,25 @@ use std::cmp::min;
99
/// - 2-edge-connected components (2ECC),
1010
/// - 2-vertex-connected components (2VCC)
1111
///
12-
/// Multiple-edges and self-loops should be correctly handled.
12+
/// Multiple-edges and self-loops are correctly handled.
1313
pub struct ConnectivityGraph<'a> {
14-
pub graph: &'a Graph, // Immutable graph, frozen for lifetime of this obj.
15-
pub cc: Vec<usize>, // Stores id of a vertex's CC, SCC or 2ECC.
16-
pub vcc: Vec<usize>, // Stores id of an edge's 2VCC.
14+
// Immutable graph, frozen for the lifetime of the ConnectivityGraph object.
15+
pub graph: &'a Graph,
16+
/// ID of a vertex's CC, SCC or 2ECC (new() documents when each applies).
17+
pub cc: Vec<usize>,
18+
/// ID of an edge's 2VCC, where applicable.
19+
pub vcc: Vec<usize>,
20+
/// Total number of CCs, SCCs or 2ECCs, whichever applies.
1721
pub num_cc: usize,
22+
/// Total number of 2VCCs, where applicable.
1823
pub num_vcc: usize,
1924
}
2025

2126
impl<'a> ConnectivityGraph<'a> {
2227
/// Computes the SCCs of a directed graph in reverse topological order, or
2328
/// the 2ECCs/2VCCS of an undirected graph. Can also get CCs by passing an
24-
/// undirected graph using `is_directed == true`.
29+
/// undirected graph using `is_directed == true`. Undefined behavior if
30+
/// passing a directed graph using `is_directed == false`.
2531
pub fn new(graph: &'a Graph, is_directed: bool) -> Self {
2632
let mut connect = Self {
2733
graph: graph,
@@ -102,7 +108,8 @@ impl<'a> ConnectivityGraph<'a> {
102108
.collect()
103109
}
104110

105-
/// Gets the vertices of a directed acyclic graph (DAG) in topological order.
111+
/// Gets the vertices of a directed acyclic graph (DAG) in topological
112+
/// order. Undefined behavior if the graph is not a DAG.
106113
pub fn topological_sort(&self) -> Vec<usize> {
107114
let mut vertices = (0..self.graph.num_v()).collect::<Vec<_>>();
108115
vertices.sort_by_key(|&u| self.num_cc - self.cc[u]);

src/graph/flow.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
//! Maximum flows and minimum cuts.
1+
//! Maximum flows, matchings, and minimum cuts.
22
use graph::{Graph, AdjListIterator};
33
use std::cmp::min;
44
const INF: i64 = 0x3f3f3f3f;
55

66
/// Representation of a network flow problem with (optional) costs.
77
pub struct FlowGraph {
8-
pub graph: Graph, // Owned graph, controlled by this FlowGraph object.
8+
/// Owned graph, managed by this FlowGraph object.
9+
pub graph: Graph,
10+
/// Edge capacities.
911
pub cap: Vec<i64>,
12+
/// Edge cost per unit flow.
1013
pub cost: Vec<i64>,
1114
}
1215

@@ -30,9 +33,14 @@ impl FlowGraph {
3033
self.graph.add_undirected_edge(u, v);
3134
}
3235

33-
/// Dinic's maximum flow / Hopcroft-Karp maximum bipartite matching:
36+
/// Dinic's algorithm to find the maximum flow from s to t where s != t.
37+
/// Generalizes the Hopcroft-Karp maximum bipartite matching algorithm.
3438
/// V^2E in general, min(V^(2/3),sqrt(E))E when all edges are unit capacity,
3539
/// sqrt(V)E when all vertices are unit capacity as in bipartite graphs.
40+
///
41+
/// # Panics
42+
///
43+
/// Panics if the maximum flow is 2^63 or larger.
3644
pub fn dinic(&self, s: usize, t: usize) -> i64 {
3745
let mut flow = vec![0; self.graph.num_e()];
3846
let mut max_flow = 0;
@@ -110,7 +118,12 @@ impl FlowGraph {
110118
.collect()
111119
}
112120

113-
/// Minimum cost maximum flow, assuming no negative-cost cycles.
121+
/// Among all s-t maximum flows, finds one with minimum cost, assuming
122+
/// s != t and no negative-cost cycles.
123+
///
124+
/// # Panics
125+
///
126+
/// Panics if the flow or cost overflow a 64-bit signed integer.
114127
pub fn mcf(&self, s: usize, t: usize) -> (i64, i64) {
115128
let mut pot = vec![0; self.graph.num_v()];
116129

@@ -139,8 +152,8 @@ impl FlowGraph {
139152
(min_cost, max_flow)
140153
}
141154

142-
// Maintains Johnson's potentials to prevent negative-weight residual edges.
143-
// This enables running Dijkstra instead of the slower Bellman-Ford.
155+
// Maintains Johnson's potentials to prevent negative-cost residual edges.
156+
// This allows running Dijkstra instead of the slower Bellman-Ford.
144157
fn mcf_search(&self, s: usize, flow: &[i64], pot: &mut [i64]) -> Vec<Option<usize>> {
145158
let mut vis = vec![false; self.graph.num_v()];
146159
let mut dist = vec![INF; self.graph.num_v()];

src/graph/mod.rs

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
//! Basic graph library without explicit support for deletion.
1+
//! Basic graph module without explicit support for deletion.
2+
//!
3+
//! # Panics
4+
//!
5+
//! All methods will panic if given an out-of-bounds element index.
26
pub mod flow;
37
pub mod connectivity;
48

@@ -76,9 +80,10 @@ impl Graph {
7680
self.add_edge(v, u);
7781
}
7882

79-
/// If we think of each even-numbered vertex as a variable, and its successor
80-
/// as its negation, then we can build the implication graph corresponding
81-
/// to any 2-CNF formula. Note that u||v == !u -> v == !v -> u.
83+
/// If we think of each even-numbered vertex as a variable, and its
84+
/// odd-numbered successor as its negation, then we can build the
85+
/// implication graph corresponding to any 2-CNF formula.
86+
/// Note that u||v == !u -> v == !v -> u.
8287
pub fn add_two_sat_clause(&mut self, u: usize, v: usize) {
8388
self.add_edge(u ^ 1, v);
8489
self.add_edge(v ^ 1, u);
@@ -92,9 +97,10 @@ impl Graph {
9297
}
9398
}
9499

95-
/// Finds the sequence of edges in an Euler path starting from u, assuming it
96-
/// exists and that the graph is directed. To extend this to undirected
97-
/// graphs, keep track of a visited array to skip the reverse edge.
100+
/// Finds the sequence of edges in an Euler path starting from u, assuming
101+
/// it exists and that the graph is directed. Undefined behavior if this
102+
/// precondition is violated. To extend this to undirected graphs, maintain
103+
/// a visited array to skip the reverse edge.
98104
pub fn euler_path(&self, u: usize) -> Vec<usize> {
99105
let mut adj_iters = (0..self.num_v())
100106
.map(|u| self.adj_list(u))
@@ -105,8 +111,8 @@ impl Graph {
105111
edges
106112
}
107113

108-
// Helper function used by euler_path. Note that we can't consume the
109-
// adjacency list in a for loop because recursive calls may need it.
114+
// Helper function used by euler_path. Note that we can't use a for-loop
115+
// that would consume the adjacency list as recursive calls may need it.
110116
fn euler_recurse(&self, u: usize, adj: &mut [AdjListIterator], edges: &mut Vec<usize>) {
111117
while let Some((e, v)) = adj[u].next() {
112118
self.euler_recurse(v, adj, edges);

src/math.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
//! Number-theoretic utilities for contest problems.
22
33
/// Modular exponentiation by repeated squaring: returns base^exp % m.
4-
pub fn mod_pow(mut base: i64, mut exp: i64, m: i64) -> i64 {
4+
///
5+
/// # Panics
6+
///
7+
/// Panics if m == 0. May panic on overflow if m * m > 2^63.
8+
pub fn mod_pow(mut base: i64, mut exp: u32, m: u32) -> i64 {
9+
let m = m as i64;
510
let mut result = 1 % m;
611
while exp > 0 {
712
if exp % 2 == 1 {
@@ -24,6 +29,10 @@ pub fn extended_gcd(a: i64, b: i64) -> (i64, i64, i64) {
2429
}
2530

2631
/// Assuming a != 0, finds smallest y >= 0 such that ax + by = c.
32+
///
33+
/// # Panics
34+
///
35+
/// Panics if a == 0.
2736
pub fn canon_egcd(a: i64, b: i64, c: i64) -> Option<(i64, i64, i64)> {
2837
let (d, _, yy) = extended_gcd(a, b);
2938
if c % d == 0 {
@@ -46,7 +55,7 @@ mod test {
4655
let base = 31;
4756

4857
let base_inv = mod_pow(base, p - 2, p);
49-
let identity = (base * base_inv) % p;
58+
let identity = (base * base_inv) % p as i64;
5059

5160
assert_eq!(identity, 1);
5261
}

src/scanner.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ impl<B: io::BufRead> Scanner<B> {
1717
}
1818

1919
/// Use "turbofish" syntax next::<T>() to select data type of next token.
20+
///
21+
/// # Panics
22+
///
23+
/// Panics if there's an I/O error or if the token cannot be parsed as T.
2024
pub fn next<T: ::std::str::FromStr>(&mut self) -> T
2125
where
2226
T::Err: ::std::fmt::Debug,

src/string_proc.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ pub struct Matcher<'a> {
88

99
impl<'a> Matcher<'a> {
1010
/// Sets fail[i] = length of longest proper prefix-suffix of pattern[0...i].
11+
///
12+
/// # Panics
13+
///
14+
/// Panics if pattern is empty.
1115
pub fn new(pattern: &'a [u8]) -> Self {
1216
let mut fail = Vec::with_capacity(pattern.len());
1317
fail.push(0);
@@ -51,6 +55,10 @@ impl<'a> Matcher<'a> {
5155
/// Manacher's algorithm for computing palindrome substrings in linear time.
5256
/// len[2*i] = odd length of palindrome centred at text[i].
5357
/// len[2*i+1] = even length of palindrome centred at text[i+0.5].
58+
///
59+
/// # Panics
60+
///
61+
/// Panics if text is empty.
5462
pub fn palindromes(text: &[u8]) -> Vec<usize> {
5563
let mut len = Vec::with_capacity(2 * text.len() - 1);
5664
len.push(1);

0 commit comments

Comments
 (0)