Skip to content

Add rustfmt to the CI pipeline #31

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,16 @@ before_cache: |
if [[ "$TRAVIS_RUST_VERSION" == nightly ]]; then
RUSTFLAGS="--cfg procmacro2_semver_exempt" cargo install cargo-tarpaulin
fi
script:
- cargo clean
- cargo build
- cargo test
before_script:
- rustup component add rustfmt
# As a result of https://github.com/travis-ci/travis-ci/issues/1066, we run
# everything in one large command instead of multiple commands.
# In this way, the build stops immediately if one of the commands fails.
script: |
cargo clean &&
cargo fmt --all -- --check &&
cargo build &&
cargo test
after_success: |
if [[ "$TRAVIS_RUST_VERSION" == nightly ]]; then
cargo tarpaulin --out Xml
Expand Down
96 changes: 41 additions & 55 deletions src/correlation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,15 @@ where
{
let observation_axis = Axis(1);
let n_observations = A::from_usize(self.len_of(observation_axis)).unwrap();
let dof =
if ddof >= n_observations {
panic!("`ddof` needs to be strictly smaller than the \
number of observations provided for each \
random variable!")
} else {
n_observations - ddof
};
let dof = if ddof >= n_observations {
panic!(
"`ddof` needs to be strictly smaller than the \
number of observations provided for each \
random variable!"
)
} else {
n_observations - ddof
};
let mean = self.mean_axis(observation_axis);
let denoised = self - &mean.insert_axis(observation_axis);
let covariance = denoised.dot(&denoised.t());
Expand All @@ -156,7 +157,9 @@ where
// observation per random variable (or no observations at all)
let ddof = -A::one();
let cov = self.cov(ddof);
let std = self.std_axis(observation_axis, ddof).insert_axis(observation_axis);
let std = self
.std_axis(observation_axis, ddof)
.insert_axis(observation_axis);
let std_matrix = std.dot(&std.t());
// element-wise division
cov / std_matrix
Expand All @@ -167,10 +170,10 @@ where
mod cov_tests {
use super::*;
use ndarray::array;
use ndarray_rand::RandomExt;
use quickcheck::quickcheck;
use rand;
use rand::distributions::Uniform;
use ndarray_rand::RandomExt;

quickcheck! {
fn constant_random_variables_have_zero_covariance_matrix(value: f64) -> bool {
Expand Down Expand Up @@ -200,10 +203,7 @@ mod cov_tests {
fn test_invalid_ddof() {
let n_random_variables = 3;
let n_observations = 4;
let a = Array::random(
(n_random_variables, n_observations),
Uniform::new(0., 10.)
);
let a = Array::random((n_random_variables, n_observations), Uniform::new(0., 10.));
let invalid_ddof = (n_observations as f64) + rand::random::<f64>().abs();
a.cov(invalid_ddof);
}
Expand Down Expand Up @@ -235,55 +235,46 @@ mod cov_tests {
#[test]
fn test_covariance_for_random_array() {
let a = array![
[ 0.72009497, 0.12568055, 0.55705966, 0.5959984 , 0.69471457],
[ 0.56717131, 0.47619486, 0.21526298, 0.88915366, 0.91971245],
[ 0.59044195, 0.10720363, 0.76573717, 0.54693675, 0.95923036],
[ 0.24102952, 0.131347, 0.11118028, 0.21451351, 0.30515539],
[ 0.26952473, 0.93079841, 0.8080893 , 0.42814155, 0.24642258]
[0.72009497, 0.12568055, 0.55705966, 0.5959984, 0.69471457],
[0.56717131, 0.47619486, 0.21526298, 0.88915366, 0.91971245],
[0.59044195, 0.10720363, 0.76573717, 0.54693675, 0.95923036],
[0.24102952, 0.131347, 0.11118028, 0.21451351, 0.30515539],
[0.26952473, 0.93079841, 0.8080893, 0.42814155, 0.24642258]
];
let numpy_covariance = array![
[ 0.05786248, 0.02614063, 0.06446215, 0.01285105, -0.06443992],
[ 0.02614063, 0.08733569, 0.02436933, 0.01977437, -0.06715555],
[ 0.06446215, 0.02436933, 0.10052129, 0.01393589, -0.06129912],
[ 0.01285105, 0.01977437, 0.01393589, 0.00638795, -0.02355557],
[-0.06443992, -0.06715555, -0.06129912, -0.02355557, 0.09909855]
[0.05786248, 0.02614063, 0.06446215, 0.01285105, -0.06443992],
[0.02614063, 0.08733569, 0.02436933, 0.01977437, -0.06715555],
[0.06446215, 0.02436933, 0.10052129, 0.01393589, -0.06129912],
[0.01285105, 0.01977437, 0.01393589, 0.00638795, -0.02355557],
[
-0.06443992,
-0.06715555,
-0.06129912,
-0.02355557,
0.09909855
]
];
assert_eq!(a.ndim(), 2);
assert!(
a.cov(1.).all_close(
&numpy_covariance,
1e-8
)
);
assert!(a.cov(1.).all_close(&numpy_covariance, 1e-8));
}

#[test]
#[should_panic]
// We lose precision, hence the failing assert
fn test_covariance_for_badly_conditioned_array() {
let a: Array2<f64> = array![
[ 1e12 + 1., 1e12 - 1.],
[ 1e-6 + 1e-12, 1e-6 - 1e-12],
];
let expected_covariance = array![
[2., 2e-12], [2e-12, 2e-24]
];
assert!(
a.cov(1.).all_close(
&expected_covariance,
1e-24
)
);
let a: Array2<f64> = array![[1e12 + 1., 1e12 - 1.], [1e-6 + 1e-12, 1e-6 - 1e-12],];
let expected_covariance = array![[2., 2e-12], [2e-12, 2e-24]];
assert!(a.cov(1.).all_close(&expected_covariance, 1e-24));
}
}

#[cfg(test)]
mod pearson_correlation_tests {
use super::*;
use ndarray::array;
use ndarray_rand::RandomExt;
use quickcheck::quickcheck;
use rand::distributions::Uniform;
use ndarray_rand::RandomExt;

quickcheck! {
fn output_matrix_is_symmetric(bound: f64) -> bool {
Expand Down Expand Up @@ -337,19 +328,14 @@ mod pearson_correlation_tests {
[0.26979716, 0.20887228, 0.95454999, 0.96290785]
];
let numpy_corrcoeff = array![
[ 1. , 0.38089376, 0.08122504, -0.59931623, 0.1365648 ],
[ 0.38089376, 1. , 0.80918429, -0.52615195, 0.38954398],
[ 0.08122504, 0.80918429, 1. , 0.07134906, -0.17324776],
[-0.59931623, -0.52615195, 0.07134906, 1. , -0.8743213 ],
[ 0.1365648 , 0.38954398, -0.17324776, -0.8743213 , 1. ]
[1., 0.38089376, 0.08122504, -0.59931623, 0.1365648],
[0.38089376, 1., 0.80918429, -0.52615195, 0.38954398],
[0.08122504, 0.80918429, 1., 0.07134906, -0.17324776],
[-0.59931623, -0.52615195, 0.07134906, 1., -0.8743213],
[0.1365648, 0.38954398, -0.17324776, -0.8743213, 1.]
];
assert_eq!(a.ndim(), 2);
assert!(
a.pearson_correlation().all_close(
&numpy_corrcoeff,
1e-7
)
);
assert!(a.pearson_correlation().all_close(&numpy_corrcoeff, 1e-7));
}

}
35 changes: 14 additions & 21 deletions src/histogram/bins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ pub struct Edges<A: Ord> {
}

impl<A: Ord> From<Vec<A>> for Edges<A> {

/// Get an `Edges` instance from a `Vec<A>`:
/// the vector will be sorted in increasing order
/// using an unstable sorting algorithm and duplicates
Expand Down Expand Up @@ -89,7 +88,7 @@ impl<A: Ord + Clone> From<Array1<A>> for Edges<A> {
}
}

impl<A: Ord> Index<usize> for Edges<A>{
impl<A: Ord> Index<usize> for Edges<A> {
type Output = A;

/// Get the `i`-th edge.
Expand Down Expand Up @@ -182,13 +181,11 @@ impl<A: Ord> Edges<A> {
match self.edges.binary_search(value) {
Ok(i) if i == n_edges - 1 => None,
Ok(i) => Some((i, i + 1)),
Err(i) => {
match i {
0 => None,
j if j == n_edges => None,
j => Some((j - 1, j)),
}
}
Err(i) => match i {
0 => None,
j if j == n_edges => None,
j => Some((j - 1, j)),
},
}
}

Expand Down Expand Up @@ -309,18 +306,14 @@ impl<A: Ord> Bins<A> {
/// );
/// ```
pub fn range_of(&self, value: &A) -> Option<Range<A>>
where
A: Clone,
where
A: Clone,
{
let edges_indexes = self.edges.indices_of(value);
edges_indexes.map(
|(left, right)| {
Range {
start: self.edges[left].clone(),
end: self.edges[right].clone(),
}
}
)
edges_indexes.map(|(left, right)| Range {
start: self.edges[left].clone(),
end: self.edges[right].clone(),
})
}

/// Get the `i`-th bin.
Expand All @@ -341,7 +334,7 @@ impl<A: Ord> Bins<A> {
/// );
/// ```
pub fn index(&self, index: usize) -> Range<A>
where
where
A: Clone,
{
// It was not possible to implement this functionality
Expand All @@ -350,7 +343,7 @@ impl<A: Ord> Bins<A> {
// Index, in fact, forces you to return a reference.
Range {
start: self.edges[index].clone(),
end: self.edges[index+1].clone(),
end: self.edges[index + 1].clone(),
}
}
}
Expand Down
29 changes: 19 additions & 10 deletions src/histogram/grid.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use super::bins::Bins;
use super::strategies::BinsBuildingStrategy;
use std::ops::Range;
use itertools::izip;
use ndarray::{ArrayBase, Data, Ix1, Ix2, Axis};
use ndarray::{ArrayBase, Axis, Data, Ix1, Ix2};
use std::ops::Range;

/// A `Grid` is a partition of a rectangular region of an *n*-dimensional
/// space—e.g. [*a*<sub>0</sub>, *b*<sub>0</sub>) × ⋯ × [*a*<sub>*n*−1</sub>,
Expand Down Expand Up @@ -72,7 +72,6 @@ pub struct Grid<A: Ord> {
}

impl<A: Ord> From<Vec<Bins<A>>> for Grid<A> {

/// Get a `Grid` instance from a `Vec<Bins<A>>`.
///
/// The `i`-th element in `Vec<Bins<A>>` represents the 1-dimensional
Expand Down Expand Up @@ -113,9 +112,14 @@ impl<A: Ord> Grid<A> {
where
S: Data<Elem = A>,
{
assert_eq!(point.len(), self.ndim(),
"Dimension mismatch: the point has {:?} dimensions, the grid \
expected {:?} dimensions.", point.len(), self.ndim());
assert_eq!(
point.len(),
self.ndim(),
"Dimension mismatch: the point has {:?} dimensions, the grid \
expected {:?} dimensions.",
point.len(),
self.ndim()
);
point
.iter()
.zip(self.projections.iter())
Expand All @@ -132,9 +136,14 @@ impl<A: Ord + Clone> Grid<A> {
/// **Panics** if at least one among `(i_0, ..., i_{n-1})` is out of bounds on the respective
/// coordinate axis - i.e. if there exists `j` such that `i_j >= self.projections[j].len()`.
pub fn index(&self, index: &[usize]) -> Vec<Range<A>> {
assert_eq!(index.len(), self.ndim(),
"Dimension mismatch: the index has {0:?} dimensions, the grid \
expected {1:?} dimensions.", index.len(), self.ndim());
assert_eq!(
index.len(),
self.ndim(),
"Dimension mismatch: the index has {0:?} dimensions, the grid \
expected {1:?} dimensions.",
index.len(),
self.ndim()
);
izip!(&self.projections, index)
.map(|(bins, &i)| bins.index(i))
.collect()
Expand Down Expand Up @@ -164,7 +173,7 @@ where
/// [`strategy`]: strategies/index.html
pub fn from_array<S>(array: &ArrayBase<S, Ix2>) -> Self
where
S: Data<Elem=A>,
S: Data<Elem = A>,
{
let bin_builders = array
.axis_iter(Axis(1))
Expand Down
25 changes: 12 additions & 13 deletions src/histogram/histograms.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::errors::BinNotFound;
use super::grid::Grid;
use ndarray::prelude::*;
use ndarray::Data;
use super::grid::Grid;
use super::errors::BinNotFound;

/// Histogram data structure.
pub struct Histogram<A: Ord> {
Expand Down Expand Up @@ -58,8 +58,8 @@ impl<A: Ord> Histogram<A> {
Some(bin_index) => {
self.counts[&*bin_index] += 1;
Ok(())
},
None => Err(BinNotFound)
}
None => Err(BinNotFound),
}
}

Expand All @@ -82,8 +82,8 @@ impl<A: Ord> Histogram<A> {

/// Extension trait for `ArrayBase` providing methods to compute histograms.
pub trait HistogramExt<A, S>
where
S: Data<Elem = A>,
where
S: Data<Elem = A>,
{
/// Returns the [histogram](https://en.wikipedia.org/wiki/Histogram)
/// for a 2-dimensional array of points `M`.
Expand Down Expand Up @@ -145,17 +145,16 @@ pub trait HistogramExt<A, S>
/// # }
/// ```
fn histogram(&self, grid: Grid<A>) -> Histogram<A>
where
A: Ord;
where
A: Ord;
}

impl<A, S> HistogramExt<A, S> for ArrayBase<S, Ix2>
where
S: Data<Elem = A>,
A: Ord,
where
S: Data<Elem = A>,
A: Ord,
{
fn histogram(&self, grid: Grid<A>) -> Histogram<A>
{
fn histogram(&self, grid: Grid<A>) -> Histogram<A> {
let mut histogram = Histogram::new(grid);
for point in self.axis_iter(Axis(0)) {
let _ = histogram.add_observation(&point);
Expand Down
10 changes: 5 additions & 5 deletions src/histogram/mod.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//! Histogram functionalities.
pub use self::histograms::{Histogram, HistogramExt};
pub use self::bins::{Edges, Bins};
pub use self::bins::{Bins, Edges};
pub use self::grid::{Grid, GridBuilder};
pub use self::histograms::{Histogram, HistogramExt};

mod histograms;
mod bins;
pub mod strategies;
mod grid;
pub mod errors;
mod grid;
mod histograms;
pub mod strategies;
Loading