Skip to content

Commit

Permalink
Merge pull request #174 from InjectiveLabs/f/round
Browse files Browse the repository at this point in the history
  • Loading branch information
gorgos authored Sep 14, 2023
2 parents 37f3da5 + 741ba12 commit fd10d48
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 5 deletions.
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/injective-math/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ license = "Apache-2.0"
name = "injective-math"
readme = "README.md"
repository = "https://github.com/InjectiveLabs/cw-injective/tree/master/packages/injective-math"
version = "0.1.20"
version = "0.1.21"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

Expand Down
7 changes: 6 additions & 1 deletion packages/injective-math/src/fp_decimal/from_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,12 @@ impl FromStr for FPDecimal {

impl FPDecimal {
pub fn must_from_str(input: &str) -> Self {
Self::from_str(input).unwrap()
let i = Self::from_str(input).unwrap();
// to handle must_from_str("-0")
if i.num == U256([0, 0, 0, 0]) {
return FPDecimal::ZERO;
}
i
}
}

Expand Down
3 changes: 3 additions & 0 deletions packages/injective-math/src/fp_decimal/round.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
use crate::fp_decimal::{FPDecimal, U256};
use std::iter;
use std::ops;
114 changes: 114 additions & 0 deletions packages/injective-math/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::FPDecimal;
use bigint::U256;
use cosmwasm_std::StdError;
use std::cmp::Ordering;
use std::{fmt::Display, str::FromStr};

#[derive(Default)]
Expand Down Expand Up @@ -75,6 +76,32 @@ pub fn div_dec(num: FPDecimal, denom: FPDecimal) -> FPDecimal {
}
}

pub fn floor(num: FPDecimal, min_tick: FPDecimal) -> FPDecimal {
// min_tick has to be a positive number
assert!(min_tick >= FPDecimal::ZERO);
if num.is_zero() {
return num;
}
let remainder = num % min_tick;
num - remainder
}

pub fn round(num: FPDecimal, min_tick: FPDecimal) -> FPDecimal {
let num_floor = floor(num, min_tick);
let diff = num - num_floor;
match diff.cmp(&(min_tick / FPDecimal::TWO)) {
Ordering::Less => num_floor,
Ordering::Equal => {
if num_floor / (min_tick * FPDecimal::TWO) == FPDecimal::ZERO {
num_floor
} else {
num_floor + min_tick
}
}
Ordering::Greater => num_floor + min_tick,
}
}

pub fn round_to_min_tick(num: FPDecimal, min_tick: FPDecimal) -> FPDecimal {
if num < min_tick {
FPDecimal::zero()
Expand Down Expand Up @@ -114,6 +141,93 @@ pub fn round_up_to_min_tick(num: FPDecimal, min_tick: FPDecimal) -> FPDecimal {
#[cfg(test)]
mod tests {
use super::*;
use crate::fp_decimal::scale::Scaled;

#[test]
fn test_floor() {
assert_eq!(floor(FPDecimal::must_from_str("0"), FPDecimal::must_from_str("0.1")), FPDecimal::ZERO);
assert_eq!(
floor(FPDecimal::must_from_str("0.13"), FPDecimal::must_from_str("0.1")),
FPDecimal::must_from_str("0.1")
);
assert_eq!(
floor(FPDecimal::must_from_str("0.19"), FPDecimal::must_from_str("0.1")),
FPDecimal::must_from_str("0.1")
);
assert_eq!(
floor(FPDecimal::must_from_str("1.19"), FPDecimal::must_from_str("0.1")),
FPDecimal::must_from_str("1.1")
);
assert_eq!(floor(FPDecimal::must_from_str("2.19"), FPDecimal::ONE), FPDecimal::TWO);

assert_eq!(floor(FPDecimal::must_from_str("-0"), FPDecimal::must_from_str("0.1")), FPDecimal::ZERO);
assert_eq!(
floor(FPDecimal::must_from_str("-0.13"), FPDecimal::must_from_str("0.1")),
FPDecimal::must_from_str("-0.2")
);
assert_eq!(
floor(FPDecimal::must_from_str("-0.19"), FPDecimal::must_from_str("0.1")),
FPDecimal::must_from_str("-0.2")
);
assert_eq!(
floor(FPDecimal::must_from_str("-1.19"), FPDecimal::must_from_str("0.1")),
FPDecimal::must_from_str("-1.2")
);
assert_eq!(
floor(FPDecimal::must_from_str("-2.19"), FPDecimal::must_from_str("0.1")),
FPDecimal::must_from_str("-2.2")
);

assert_eq!(floor(FPDecimal::must_from_str("-2.19"), FPDecimal::ONE), FPDecimal::must_from_str("-3"));
}

#[test]
fn test_round() {
assert_eq!(round(FPDecimal::must_from_str("0.13"), FPDecimal::ONE), FPDecimal::ZERO);
assert_eq!(round(FPDecimal::must_from_str("0.49"), FPDecimal::ONE), FPDecimal::ZERO);
assert_eq!(round(FPDecimal::must_from_str("0.5"), FPDecimal::ONE), FPDecimal::ZERO);
assert_eq!(round(FPDecimal::must_from_str("0.50009"), FPDecimal::ONE), FPDecimal::ONE);

assert_eq!(round(FPDecimal::must_from_str("-0.13"), FPDecimal::ONE), FPDecimal::ZERO);
assert_eq!(round(FPDecimal::must_from_str("-0.49"), FPDecimal::ONE), FPDecimal::ZERO);
assert_eq!(round(FPDecimal::must_from_str("-0.5"), FPDecimal::ONE), FPDecimal::ZERO);
assert_eq!(round(FPDecimal::must_from_str("-0.51"), FPDecimal::ONE), -FPDecimal::ONE);
assert_eq!(round(FPDecimal::must_from_str("-1.50009"), FPDecimal::ONE), -FPDecimal::TWO);
}

#[test]
fn test_round_with_scaled_numbers() {
assert_eq!(round(FPDecimal::must_from_str("0"), FPDecimal::must_from_str("0.1")), FPDecimal::ZERO);
assert_eq!(
round(FPDecimal::must_from_str("0.13"), FPDecimal::must_from_str("0.1")),
FPDecimal::must_from_str("0.1")
);
assert_eq!(
round(FPDecimal::must_from_str("0.50009"), FPDecimal::must_from_str("0.0001")),
FPDecimal::must_from_str("0.5001")
);

assert_eq!(round(FPDecimal::must_from_str("-0"), FPDecimal::must_from_str("0.1")), FPDecimal::ZERO);
assert_eq!(
round(FPDecimal::must_from_str("-0.13"), FPDecimal::must_from_str("0.1")),
FPDecimal::must_from_str("-0.1")
);
assert_eq!(
round(FPDecimal::must_from_str("-0.50009"), FPDecimal::must_from_str("0.0001")),
FPDecimal::must_from_str("-0.5001")
);

assert_eq!(round(FPDecimal::must_from_str("-1.50009"), FPDecimal::ONE.scaled(1)), FPDecimal::ZERO);
assert_eq!(
round(FPDecimal::must_from_str("-1.50009").scaled(1), FPDecimal::ONE.scaled(1)),
-FPDecimal::TWO.scaled(1)
);
assert_eq!(round(FPDecimal::must_from_str("-1.50009"), FPDecimal::ONE.scaled(1)), FPDecimal::ZERO);
assert_eq!(
round(FPDecimal::must_from_str("-1.50009").scaled(1), FPDecimal::ONE.scaled(1)),
-FPDecimal::TWO.scaled(1)
);
}

#[test]
fn test_div_dec() {
Expand Down

0 comments on commit fd10d48

Please sign in to comment.