Skip to content

Commit ee6e656

Browse files
committed
Merge pull request #61 from bluss/eq-unroll
Unroll loop in equality (PartialEq) impl
2 parents bff4689 + 4809b97 commit ee6e656

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

src/arraytraits.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ use super::{
2222
NdIndex,
2323
};
2424

25+
use numeric_util;
26+
2527
#[cold]
2628
#[inline(never)]
2729
fn array_out_of_bounds() -> ! {
@@ -72,7 +74,7 @@ impl<S, S2, D> PartialEq<ArrayBase<S2, D>> for ArrayBase<S, D>
7274
}
7375
if let Some(self_s) = self.as_slice() {
7476
if let Some(rhs_s) = rhs.as_slice() {
75-
return self_s == rhs_s;
77+
return numeric_util::unrolled_eq(self_s, rhs_s);
7678
}
7779
}
7880
self.iter().zip(rhs.iter()).all(|(a, b)| a == b)

src/numeric_util.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,37 @@ pub fn unrolled_dot<A>(xs: &[A], ys: &[A]) -> A
4545
}
4646
sum
4747
}
48+
49+
/// Compute pairwise equality
50+
///
51+
/// `xs` and `ys` must be the same length
52+
pub fn unrolled_eq<A>(xs: &[A], ys: &[A]) -> bool
53+
where A: PartialEq
54+
{
55+
debug_assert_eq!(xs.len(), ys.len());
56+
// eightfold unrolled for performance (this is not done by llvm automatically)
57+
let len = cmp::min(xs.len(), ys.len());
58+
let mut xs = &xs[..len];
59+
let mut ys = &ys[..len];
60+
61+
while xs.len() >= 8 {
62+
if (xs[0] != ys[0])
63+
| (xs[1] != ys[1])
64+
| (xs[2] != ys[2])
65+
| (xs[3] != ys[3])
66+
| (xs[4] != ys[4])
67+
| (xs[5] != ys[5])
68+
| (xs[6] != ys[6])
69+
| (xs[7] != ys[7]) { return false; }
70+
xs = &xs[8..];
71+
ys = &ys[8..];
72+
}
73+
74+
for i in 0..xs.len() {
75+
if xs[i] != ys[i] {
76+
return false;
77+
}
78+
}
79+
80+
return true;
81+
}

0 commit comments

Comments
 (0)