Skip to content

Commit 211f7df

Browse files
authored
Merge pull request #21 from bandprotocol/update-median
update median
2 parents 5050142 + 375bf98 commit 211f7df

File tree

3 files changed

+42
-22
lines changed

3 files changed

+42
-22
lines changed

packages/kit/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ license = "Apache-2.0"
66
name = "owasm-kit"
77
readme = "README.md"
88
repository = "https://github.com/bandprotocol/owasm/tree/master/packages/kit"
9-
version = "0.2.2"
9+
version = "0.2.3"
1010

1111
[dependencies]
12-
num = "0.2.1"
12+
num = "0.4.0"

packages/kit/src/ext/mod.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! # Owasm Standard Library
22
use crate::oei;
3+
34
pub mod cmp;
45
pub mod stats;
56

@@ -27,11 +28,19 @@ where
2728
}
2829

2930
/// Returns the median value of the given external ID, ignoring unsuccessful reports.
30-
pub fn load_median<T>(eid: i64) -> Option<T>
31+
pub fn load_median_integer<T>(eid: i64) -> Option<T>
32+
where
33+
T: std::str::FromStr + std::cmp::Ord + num::Num + num::NumCast,
34+
{
35+
stats::median_integer(load_input(eid).collect())
36+
}
37+
38+
/// Returns the median value of the given external ID, ignoring unsuccessful reports.
39+
pub fn load_median_float<T>(eid: i64) -> Option<T>
3140
where
32-
T: std::str::FromStr + std::cmp::Ord + num::Num,
41+
T: std::str::FromStr + num::Float + num::NumCast,
3342
{
34-
stats::median(load_input(eid).collect())
43+
stats::median_float(load_input(eid).collect())
3544
}
3645

3746
/// Returns the majority value of the given external ID, ignoring unsuccessful reports.

packages/kit/src/ext/stats.rs

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
use core::cmp::{Ord, Ordering, PartialEq};
2-
use num::Num;
2+
3+
use num::{Float, Num, NumCast};
4+
5+
use crate::ext::cmp;
36

47
/// Returns the average value of the given data set, or None if data is empty.
58
pub fn average<T>(data: Vec<T>) -> Option<T>
@@ -22,31 +25,40 @@ where
2225
/// Returns the median value using the given compare function, or None if data is empty.
2326
pub fn median_by<T, F>(mut data: Vec<T>, compare: F) -> Option<T>
2427
where
25-
T: Num,
28+
T: Num + NumCast,
2629
F: FnMut(&T, &T) -> Ordering,
2730
{
2831
if data.is_empty() {
2932
return None;
3033
}
34+
3135
data.sort_by(compare);
3236
let mid = data.len() / 2;
3337
if data.len() % 2 == 0 {
3438
let rhs = data.swap_remove(mid);
3539
let lhs = data.swap_remove(mid - 1);
36-
Some((lhs + rhs) / (T::one() + T::one()))
40+
Some((lhs + rhs) / NumCast::from(2).unwrap())
3741
} else {
3842
Some(data.swap_remove(mid))
3943
}
4044
}
4145

4246
/// Returns the median value of the given data set, or None if data is empty.
43-
pub fn median<T>(data: Vec<T>) -> Option<T>
47+
pub fn median_integer<T>(data: Vec<T>) -> Option<T>
4448
where
45-
T: Ord + Num,
49+
T: Ord + Num + NumCast,
4650
{
4751
median_by(data, T::cmp)
4852
}
4953

54+
/// Returns the median value of the given data set, or None if data is empty.
55+
pub fn median_float<T>(data: Vec<T>) -> Option<T>
56+
where
57+
T: Float + NumCast,
58+
{
59+
median_by(data, cmp::fcmp)
60+
}
61+
5062
/// Returns the majority value of the given data set, or None if there is no majority.
5163
pub fn majority<T>(mut data: Vec<T>) -> Option<T>
5264
where
@@ -87,7 +99,6 @@ where
8799
#[cfg(test)]
88100
mod tests {
89101
use super::*;
90-
use crate::ext::cmp;
91102

92103
#[test]
93104
fn test_average_empty() {
@@ -122,51 +133,51 @@ mod tests {
122133
#[test]
123134
fn test_median_odd_int() {
124135
let vals = vec![3, 2, 5, 7, 2, 9, 1];
125-
assert_eq!(median(vals), Some(3));
136+
assert_eq!(median_integer(vals), Some(3));
126137
}
127138

128139
#[test]
129140
fn test_median_single_int() {
130141
let vals = vec![3];
131-
assert_eq!(median(vals), Some(3));
142+
assert_eq!(median_integer(vals), Some(3));
132143
}
133144

134145
#[test]
135146
fn test_median_empty() {
136147
let vals: Vec<i64> = vec![];
137-
assert_eq!(median(vals), None);
148+
assert_eq!(median_integer(vals), None);
138149
}
139150

140151
#[test]
141152
fn test_median_even_int() {
142153
let vals = vec![3, 2, 5, 7, 2, 10, 32, 1];
143-
assert_eq!(median(vals), Some(4));
154+
assert_eq!(median_integer(vals), Some(4));
144155
let vals = vec![13, 36, 33, 45];
145-
assert_eq!(median(vals), Some(34));
156+
assert_eq!(median_integer(vals), Some(34));
146157
let vals = vec![13, 15];
147-
assert_eq!(median(vals), Some(14));
158+
assert_eq!(median_integer(vals), Some(14));
148159
}
149160

150161
#[test]
151162
fn test_median_odd_float() {
152163
let vals = vec![3.5, 2.7, 5.1, 7.4, 2.0, 9.1, 1.9];
153-
assert_eq!(median_by(vals, cmp::fcmp), Some(3.5));
164+
assert_eq!(median_float(vals), Some(3.5));
154165
}
155166

156167
#[test]
157168
fn test_median_single_float() {
158169
let vals = vec![3.0];
159-
assert_eq!(median_by(vals, cmp::fcmp), Some(3.0));
170+
assert_eq!(median_float(vals), Some(3.0));
160171
}
161172

162173
#[test]
163174
fn test_median_even_float() {
164175
let vals = vec![3.4, 2.0, 5.7, 7.1, 2.2, 10.1, 32.0, 1.8];
165-
assert_eq!(median_by(vals, cmp::fcmp), Some(4.55));
176+
assert_eq!(median_float(vals), Some(4.55));
166177
let vals = vec![13.0, 36.0, 45.0, 33.0];
167-
assert_eq!(median_by(vals, cmp::fcmp), Some(34.5));
178+
assert_eq!(median_float(vals), Some(34.5));
168179
let vals = vec![13.0, 36.2];
169-
assert_eq!(median_by(vals, cmp::fcmp), Some(24.6));
180+
assert_eq!(median_float(vals), Some(24.6));
170181
}
171182

172183
#[test]

0 commit comments

Comments
 (0)