|
|
@@ -27,17 +27,17 @@ pub struct Price(NonZeroI64);
|
|
|
|
|
|
impl Price {
|
|
|
pub fn from_integer(value: i64, exponent: i16) -> Result<Price, PriceError> {
|
|
|
- let value = match ExponentFactor::get(exponent).ok_or(PriceError::Overflow)? {
|
|
|
+ let mantissa = match ExponentFactor::get(exponent).ok_or(PriceError::Overflow)? {
|
|
|
ExponentFactor::Mul(coef) => value.checked_mul(coef).ok_or(PriceError::Overflow)?,
|
|
|
ExponentFactor::Div(coef) => value.checked_div(coef).ok_or(PriceError::Overflow)?,
|
|
|
};
|
|
|
- let value = NonZeroI64::new(value).ok_or(PriceError::ZeroPriceUnsupported)?;
|
|
|
- Ok(Self(value))
|
|
|
+ let mantissa = NonZeroI64::new(mantissa).ok_or(PriceError::ZeroPriceUnsupported)?;
|
|
|
+ Ok(Self(mantissa))
|
|
|
}
|
|
|
|
|
|
pub fn parse_str(value: &str, exponent: i16) -> Result<Price, PriceError> {
|
|
|
let value: Decimal = value.parse()?;
|
|
|
- let value = match ExponentFactor::get(exponent).ok_or(PriceError::Overflow)? {
|
|
|
+ let mantissa = match ExponentFactor::get(exponent).ok_or(PriceError::Overflow)? {
|
|
|
ExponentFactor::Mul(coef) => value
|
|
|
.checked_mul(Decimal::from_i64(coef).ok_or(PriceError::Overflow)?)
|
|
|
.ok_or(PriceError::Overflow)?,
|
|
|
@@ -45,12 +45,12 @@ impl Price {
|
|
|
.checked_div(Decimal::from_i64(coef).ok_or(PriceError::Overflow)?)
|
|
|
.ok_or(PriceError::Overflow)?,
|
|
|
};
|
|
|
- if !value.is_integer() {
|
|
|
+ if !mantissa.is_integer() {
|
|
|
return Err(PriceError::TooPrecise);
|
|
|
}
|
|
|
- let value: i64 = value.try_into().map_err(|_| PriceError::Overflow)?;
|
|
|
- let value = NonZeroI64::new(value).ok_or(PriceError::Overflow)?;
|
|
|
- Ok(Self(value))
|
|
|
+ let mantissa: i64 = mantissa.try_into().map_err(|_| PriceError::Overflow)?;
|
|
|
+ let mantissa = NonZeroI64::new(mantissa).ok_or(PriceError::Overflow)?;
|
|
|
+ Ok(Self(mantissa))
|
|
|
}
|
|
|
|
|
|
pub const fn from_nonzero_mantissa(mantissa: NonZeroI64) -> Self {
|
|
|
@@ -58,8 +58,8 @@ impl Price {
|
|
|
}
|
|
|
|
|
|
pub const fn from_mantissa(mantissa: i64) -> Result<Self, PriceError> {
|
|
|
- if let Some(value) = NonZeroI64::new(mantissa) {
|
|
|
- Ok(Self(value))
|
|
|
+ if let Some(mantissa) = NonZeroI64::new(mantissa) {
|
|
|
+ Ok(Self(mantissa))
|
|
|
} else {
|
|
|
Err(PriceError::ZeroPriceUnsupported)
|
|
|
}
|
|
|
@@ -75,7 +75,7 @@ impl Price {
|
|
|
|
|
|
pub fn to_f64(self, exponent: i16) -> Result<f64, PriceError> {
|
|
|
match ExponentFactor::get(exponent).ok_or(PriceError::Overflow)? {
|
|
|
- // Mul/div is reversed for this conversion
|
|
|
+ // Mul/div is reversed for converting mantissa to value
|
|
|
ExponentFactor::Mul(coef) => Ok(self.0.get() as f64 / coef as f64),
|
|
|
ExponentFactor::Div(coef) => Ok(self.0.get() as f64 * coef as f64),
|
|
|
}
|
|
|
@@ -83,7 +83,7 @@ impl Price {
|
|
|
|
|
|
pub fn from_f64(value: f64, exponent: i16) -> Result<Self, PriceError> {
|
|
|
let value = Decimal::from_f64(value).ok_or(PriceError::Overflow)?;
|
|
|
- let value = match ExponentFactor::get(exponent).ok_or(PriceError::Overflow)? {
|
|
|
+ let mantissa = match ExponentFactor::get(exponent).ok_or(PriceError::Overflow)? {
|
|
|
ExponentFactor::Mul(coef) => value
|
|
|
.checked_mul(Decimal::from_i64(coef).ok_or(PriceError::Overflow)?)
|
|
|
.ok_or(PriceError::Overflow)?,
|
|
|
@@ -91,65 +91,70 @@ impl Price {
|
|
|
.checked_div(Decimal::from_i64(coef).ok_or(PriceError::Overflow)?)
|
|
|
.ok_or(PriceError::Overflow)?,
|
|
|
};
|
|
|
- let value: i64 = value.try_into().map_err(|_| PriceError::Overflow)?;
|
|
|
+ let mantissa: i64 = mantissa.try_into().map_err(|_| PriceError::Overflow)?;
|
|
|
Ok(Self(
|
|
|
- NonZeroI64::new(value).ok_or(PriceError::ZeroPriceUnsupported)?,
|
|
|
+ NonZeroI64::new(mantissa).ok_or(PriceError::ZeroPriceUnsupported)?,
|
|
|
))
|
|
|
}
|
|
|
|
|
|
- pub fn add_with_same_mantissa(self, other: Price) -> Result<Self, PriceError> {
|
|
|
- let value = self
|
|
|
+ pub fn add_with_same_exponent(self, other: Price) -> Result<Self, PriceError> {
|
|
|
+ let mantissa = self
|
|
|
.0
|
|
|
.get()
|
|
|
.checked_add(other.0.get())
|
|
|
.ok_or(PriceError::Overflow)?;
|
|
|
- Self::from_mantissa(value).map_err(|_| PriceError::ZeroPriceUnsupported)
|
|
|
+ Self::from_mantissa(mantissa).map_err(|_| PriceError::ZeroPriceUnsupported)
|
|
|
}
|
|
|
|
|
|
- pub fn sub_with_same_mantissa(self, other: Price) -> Result<Self, PriceError> {
|
|
|
- let value = self
|
|
|
+ pub fn sub_with_same_exponent(self, other: Price) -> Result<Self, PriceError> {
|
|
|
+ let mantissa = self
|
|
|
.0
|
|
|
.get()
|
|
|
.checked_sub(other.0.get())
|
|
|
.ok_or(PriceError::Overflow)?;
|
|
|
- Self::from_mantissa(value).map_err(|_| PriceError::ZeroPriceUnsupported)
|
|
|
+ Self::from_mantissa(mantissa).map_err(|_| PriceError::ZeroPriceUnsupported)
|
|
|
}
|
|
|
|
|
|
pub fn mul_integer(self, factor: i64) -> Result<Self, PriceError> {
|
|
|
- let value = self
|
|
|
+ let mantissa = self
|
|
|
.0
|
|
|
.get()
|
|
|
.checked_mul(factor)
|
|
|
.ok_or(PriceError::Overflow)?;
|
|
|
- Self::from_mantissa(value).map_err(|_| PriceError::ZeroPriceUnsupported)
|
|
|
+ Self::from_mantissa(mantissa).map_err(|_| PriceError::ZeroPriceUnsupported)
|
|
|
}
|
|
|
|
|
|
pub fn div_integer(self, factor: i64) -> Result<Self, PriceError> {
|
|
|
- let value = self
|
|
|
+ let mantissa = self
|
|
|
.0
|
|
|
.get()
|
|
|
.checked_div(factor)
|
|
|
.ok_or(PriceError::Overflow)?;
|
|
|
- Self::from_mantissa(value).map_err(|_| PriceError::ZeroPriceUnsupported)
|
|
|
+ Self::from_mantissa(mantissa).map_err(|_| PriceError::ZeroPriceUnsupported)
|
|
|
}
|
|
|
|
|
|
- pub fn mul_decimal(self, mantissa: i64, rhs_exponent: i16) -> Result<Self, PriceError> {
|
|
|
- let left_value = i128::from(self.0.get());
|
|
|
- let right_value = i128::from(mantissa);
|
|
|
+ pub fn mul_decimal(self, mantissa: i64, exponent: i16) -> Result<Self, PriceError> {
|
|
|
+ let left_mantissa = i128::from(self.0.get());
|
|
|
+ let right_mantissa = i128::from(mantissa);
|
|
|
|
|
|
- let value = left_value
|
|
|
- .checked_mul(right_value)
|
|
|
+ // multiplied_mantissas = left_mantissa * right_mantissa
|
|
|
+ let multiplied_mantissas = left_mantissa
|
|
|
+ .checked_mul(right_mantissa)
|
|
|
.ok_or(PriceError::Overflow)?;
|
|
|
|
|
|
- let value = match ExponentFactor::get(rhs_exponent).ok_or(PriceError::Overflow)? {
|
|
|
- ExponentFactor::Mul(coef) => {
|
|
|
- value.checked_div(coef.into()).ok_or(PriceError::Overflow)?
|
|
|
- }
|
|
|
- ExponentFactor::Div(coef) => {
|
|
|
- value.checked_mul(coef.into()).ok_or(PriceError::Overflow)?
|
|
|
- }
|
|
|
+ // result_mantissa = left_mantissa * right_mantissa * 10^exponent
|
|
|
+ // Mul/div is reversed for multiplying 10^exponent
|
|
|
+ let result_mantissa = match ExponentFactor::get(exponent).ok_or(PriceError::Overflow)? {
|
|
|
+ ExponentFactor::Mul(coef) => multiplied_mantissas
|
|
|
+ .checked_div(coef.into())
|
|
|
+ .ok_or(PriceError::Overflow)?,
|
|
|
+ ExponentFactor::Div(coef) => multiplied_mantissas
|
|
|
+ .checked_mul(coef.into())
|
|
|
+ .ok_or(PriceError::Overflow)?,
|
|
|
};
|
|
|
- let value: i64 = value.try_into().map_err(|_| PriceError::Overflow)?;
|
|
|
- Self::from_mantissa(value).map_err(|_| PriceError::ZeroPriceUnsupported)
|
|
|
+ let result_mantissa: i64 = result_mantissa
|
|
|
+ .try_into()
|
|
|
+ .map_err(|_| PriceError::Overflow)?;
|
|
|
+ Self::from_mantissa(result_mantissa).map_err(|_| PriceError::ZeroPriceUnsupported)
|
|
|
}
|
|
|
}
|