1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//! The crate contains a binary indexed tree ([Fenwick tree](https://en.wikipedia.org/wiki/Fenwick_tree)) implementation and some of the extensions for it.
//!
//! The general idea of the Fenwick tree is that it allows for both queries and updates of partial
//! sums to be performed in _O_(log _n_) time.
//!
//! For more details, see [Explanation](#explanation) section.
//!
//! For tree API, see [`FenwickTree`] struct.
//!
//! # Examples
//!
//! Constructing a new tree that is equal to `[1, 2, 3]` array.
//!
//! ```
//! use fenwick_tree::FenwickTree;
//!
//! let mut tree = FenwickTree::<i32>::with_len(3);
//!
//! // `add` has time complexity O(log n).
//! tree.add(0, 1).unwrap(); // Adds `1` to element at `0`.
//! tree.add(1, 2).unwrap(); // Adds `2` to element at `1`.
//! tree.add(2, 3).unwrap(); // Adds `3` to element at `2`.
//! ```
//!
//! Calculating all possible partial sums of the tree above.
//!
//! ```
//! # use fenwick_tree::FenwickTree;
//! # let mut tree = FenwickTree::<i32>::with_len(3);
//! # tree.add(0, 1).unwrap(); // Adds `1` to element at `0`.
//! # tree.add(1, 2).unwrap(); // Adds `2` to element at `1`.
//! # tree.add(2, 3).unwrap(); // Adds `3` to element at `2`.
//! // `sum` has time complexity O(log n).
//! assert_eq!(tree.sum(0..1).unwrap(), 1);
//! assert_eq!(tree.sum(0..2).unwrap(), 3);
//! assert_eq!(tree.sum(0..3).unwrap(), 6);
//!
//! assert_eq!(tree.sum(1..2).unwrap(), 2);
//! assert_eq!(tree.sum(1..3).unwrap(), 5);
//!
//! assert_eq!(tree.sum(2..3).unwrap(), 3);
//! ```
//!
//! [`sum`](crate::FenwickTree::sum) accepts [`RangeBounds`](std::ops::RangeBounds), so actually you can use any syntax you'd like.
//!
//! ```
//! # use fenwick_tree::FenwickTree;
//! # let mut tree = FenwickTree::<i32>::with_len(3);
//! # tree.add(0, 1).unwrap(); // Adds `1` to element at `0`.
//! # tree.add(1, 2).unwrap(); // Adds `2` to element at `1`.
//! # tree.add(2, 3).unwrap(); // Adds `3` to element at `2`.
//! assert_eq!(tree.sum(..).unwrap(), 6);
//! assert_eq!(tree.sum(0..).unwrap(), 6);
//! assert_eq!(tree.sum(..3).unwrap(), 6);
//! assert_eq!(tree.sum(..=2).unwrap(), 6);
//! assert_eq!(tree.sum(0..=2).unwrap(), 6);
//! ```
//!
//! For error handling, see [`AddError`] and [`SumError`] structs.
//!
//! # Explanation
//!
//! In this section, an explanation about the tree implementation is provided.
//!
//! ## Indexing
//!
//! The easiest explanation considers that indexing of the array is one-based (as in the
//! [original paper](https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.14.8917)).
//!
//! Sums are stored in the array by the following rule: an item with index `i` stores a cumulative sum
//! of `[i - g(i), i]` range, where `g(i) = i & (-i)` or the size of the range covered by `i`.
//!
//! This looks a bit scary but the whole intuition behind Fenwick tree is very simple:
//! the position of the first `1` bit in the `i` defines the value of `g(i)`.
//! * `i = 4 = 100`, `g(i) = 100 (4)` or `[1, 4]` range (note one-based indexing)
//! * `i = 3 = 011`, `g(i) = 001 (1)` or `[3, 3]` range
//! * `i = 2 = 010`, `g(i) = 010 (2)` or `[1, 2]` range
//! * `i = 1 = 001`, `g(i) = 001 (1)` or `[1, 1]` range
//!
//! ## Querying
//!
//! Prefix sum of `n` items consists of sum of some number of ranges, depending on `n`.
//! * `n = 4` sum of `[1, 4]` (4 index)
//! * `n = 3` sum of `[3, 3]` (3 index) and `[1, 2]` (2 index)
//! * `n = 2` sum of `[1, 2]` (2 index)
//! * `n = 1` sum of `[1, 1]` (1 index)
//!
//! In order to calculate a prefix sum, we need to traverse the array from right
//! to left, decreasing `i` by `g(i)`.
//! * `i = 100 (4)`, `i - g(i) = 000 (0)`
//! * `i = 011 (3)`, `i - g(i) = 010 (2)`
//! * `i = 010 (2)`, `i - g(i) = 000 (0)`
//! * `i = 001 (1)`, `i - g(i) = 000 (0)`
//!
//! So, how `g(i)` is calculated? This can easily be done by using the
//! representation of negative numbers in two's complement systems, where `-i` means `!i + 1`.
//!
//! ```
//! # fn any_number() -> i32 { 3 }
//! let i = any_number();
//! assert_eq!(!i + 1, -i);
//! ```
//!
//! In binary, `!i` inverts all bits in the `i`, and `!i + 1` flips all bits up to first `0`.
//! * `i = 001`, `!i = 110`, `-i = 111`
//! * `i = 010`, `!i = 101`, `-i = 110`
//! * `i = 011`, `!i = 100`, `-i = 101`
//! * `i = 100`, `!i = 011`, `-i = 100`
//!
//! This means that `i` and `-i` have all bits different except the first `1` bit.
//! So, `g(i)` is as simple as `i & (-i)`.
//!
//! ## Updating
//!
//! Updating a value at `i` means traversing the array from left to right, updating
//! ranges that contain the value.
//!
//! Here similar logic applies as for querying: we need to increase `i` by `g(i)`.
//! * `i = 4 = 100`, `i + g(i) = 1000 (8)`
//! * `i = 3 = 011`, `i + g(i) = 0100 (4)`
//! * `i = 2 = 010`, `i + g(i) = 0100 (4)`
//! * `i = 1 = 001`, `i + g(i) = 0010 (2)`
//!
//! That's it!
//!
//! ## Notes
//!
//! The explanation above assumes one-based indexing, however, in Rust, as in most other programming
//! languages, indexing is zero-based. Thus, it's not that easy to calculate `i & (-i)` if `i` is
//! of `usize`.
//!
//! For the sake of code simplicity and performance, the following changes were made:
//! * querying is one-based:  `i & (i - 1)`
//! * updating is zero-based: `i | (i + 1)`
//!
//! # References
//! * [A New Data Structure for Cumulative Frequency Tables (1994)](https://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.14.8917)

#[cfg(test)]
mod tests;

mod errors;
mod tree;

pub use errors::{AddError, SumError};
pub use tree::FenwickTree;