Skip to content

Commit

Permalink
ManagedDecimalSigned operators
Browse files Browse the repository at this point in the history
  • Loading branch information
andrei-marinica committed Jun 27, 2024
1 parent 7b87b90 commit 4f69193
Show file tree
Hide file tree
Showing 7 changed files with 291 additions and 9 deletions.
4 changes: 4 additions & 0 deletions framework/base/src/types/managed/wrapped/managed_decimal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ mod decimals;
mod managed_decimal_cmp;
mod managed_decimal_macros;
mod managed_decimal_op_add;
mod managed_decimal_op_add_signed;
mod managed_decimal_op_div;
mod managed_decimal_op_div_signed;
mod managed_decimal_op_mul;
mod managed_decimal_op_mul_signed;
mod managed_decimal_op_sub;
mod managed_decimal_op_sub_signed;
mod managed_decimal_signed;

pub use decimals::{ConstDecimals, Decimals, NumDecimals};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use crate::{
api::ManagedTypeApi,
types::{ConstDecimals, Decimals, ManagedDecimalSigned, NumDecimals},
};

use core::ops::{Add, AddAssign};

impl<M: ManagedTypeApi, D1: Decimals, D2: Decimals> AddAssign<&ManagedDecimalSigned<M, D2>>
for ManagedDecimalSigned<M, D1>
{
fn add_assign(&mut self, rhs: &ManagedDecimalSigned<M, D2>) {
let scaled_data = rhs.rescale_data(self.scale().num_decimals());
self.data += scaled_data;
}
}

impl<M: ManagedTypeApi, D1: Decimals, D2: Decimals> AddAssign<ManagedDecimalSigned<M, D2>>
for ManagedDecimalSigned<M, D1>
{
#[inline]
fn add_assign(&mut self, rhs: ManagedDecimalSigned<M, D2>) {
self.add_assign(&rhs);
}
}

// const + const
impl<M: ManagedTypeApi, const DECIMALS: NumDecimals>
Add<ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>>
for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
{
type Output = Self;

fn add(mut self, rhs: ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>) -> Self::Output {
self.data += rhs.data;
self
}
}

// var + var
impl<M: ManagedTypeApi> Add<ManagedDecimalSigned<M, NumDecimals>>
for ManagedDecimalSigned<M, NumDecimals>
{
type Output = Self;

fn add(mut self, rhs: ManagedDecimalSigned<M, NumDecimals>) -> Self::Output {
match self.decimals.cmp(&rhs.decimals) {
core::cmp::Ordering::Less => {
self = self.rescale(rhs.decimals);
self.data += rhs.data;
},
core::cmp::Ordering::Equal => self.data += rhs.data,
core::cmp::Ordering::Greater => {
let rhs_data = rhs.rescale_data(self.decimals);
self.data += rhs_data;
},
}
self
}
}

// var + const
impl<const DECIMALS: usize, M: ManagedTypeApi> Add<ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>>
for ManagedDecimalSigned<M, NumDecimals>
{
type Output = ManagedDecimalSigned<M, NumDecimals>;

fn add(self, rhs: ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>) -> Self::Output {
self + rhs.into_var_decimals()
}
}

// const + var
impl<const DECIMALS: usize, M: ManagedTypeApi> Add<ManagedDecimalSigned<M, NumDecimals>>
for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
{
type Output = ManagedDecimalSigned<M, NumDecimals>;

fn add(self, rhs: ManagedDecimalSigned<M, NumDecimals>) -> Self::Output {
self.into_var_decimals() + rhs
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ where
{
type Output = ManagedDecimal<M, <D1 as Sub<D2>>::Output>;

// maybe rescale to highest first
fn div(self, other: ManagedDecimal<M, D2>) -> Self::Output {
ManagedDecimal {
data: self.data / other.data,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
use crate::{
api::ManagedTypeApi,
types::{BigUint, Decimals, ManagedDecimalSigned, NumDecimals},
};

use core::ops::{Div, DivAssign, Sub};

impl<M: ManagedTypeApi, D1: Decimals, D2: Decimals> DivAssign<&ManagedDecimalSigned<M, D2>>
for ManagedDecimalSigned<M, D1>
{
fn div_assign(&mut self, rhs: &ManagedDecimalSigned<M, D2>) {
self.data *= rhs.scaling_factor().as_big_int();
self.data /= &rhs.data;
}
}

impl<M: ManagedTypeApi, D1: Decimals, D2: Decimals> DivAssign<ManagedDecimalSigned<M, D2>>
for ManagedDecimalSigned<M, D1>
{
#[inline]
fn div_assign(&mut self, rhs: ManagedDecimalSigned<M, D2>) {
self.div_assign(&rhs);
}
}

impl<M: ManagedTypeApi, D: Decimals> Div<NumDecimals> for ManagedDecimalSigned<M, D> {
type Output = Self;

fn div(self, other: NumDecimals) -> Self::Output {
ManagedDecimalSigned {
data: self.data / BigUint::from(other),
decimals: self.decimals,
}
}
}

impl<M: ManagedTypeApi, D1: Decimals, D2: Decimals> Div<ManagedDecimalSigned<M, D2>>
for ManagedDecimalSigned<M, D1>
where
D1: Sub<D2>,
<D1 as Sub<D2>>::Output: Decimals,
{
type Output = ManagedDecimalSigned<M, <D1 as Sub<D2>>::Output>;

fn div(self, other: ManagedDecimalSigned<M, D2>) -> Self::Output {
ManagedDecimalSigned {
data: self.data / other.data,
decimals: self.decimals - other.decimals,
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use crate::{
api::ManagedTypeApi,
types::{Decimals, ManagedDecimalSigned},
};

use core::ops::{Add, Mul, MulAssign};

impl<M: ManagedTypeApi, D1: Decimals, D2: Decimals> MulAssign<&ManagedDecimalSigned<M, D2>>
for ManagedDecimalSigned<M, D1>
{
fn mul_assign(&mut self, rhs: &ManagedDecimalSigned<M, D2>) {
self.data *= &rhs.data;
self.data /= rhs.scaling_factor().as_big_int();
}
}

impl<M: ManagedTypeApi, D1: Decimals, D2: Decimals> MulAssign<ManagedDecimalSigned<M, D2>>
for ManagedDecimalSigned<M, D1>
{
#[inline]
fn mul_assign(&mut self, rhs: ManagedDecimalSigned<M, D2>) {
self.mul_assign(&rhs);
}
}

impl<M: ManagedTypeApi, D1: Decimals, D2: Decimals> Mul<ManagedDecimalSigned<M, D2>>
for ManagedDecimalSigned<M, D1>
where
D1: Add<D2>,
<D1 as Add<D2>>::Output: Decimals,
{
type Output = ManagedDecimalSigned<M, <D1 as Add<D2>>::Output>;

fn mul(self, other: ManagedDecimalSigned<M, D2>) -> Self::Output {
ManagedDecimalSigned {
data: self.data * other.data,
decimals: self.decimals + other.decimals,
}
}
}

impl<M: ManagedTypeApi, D1: Decimals> ManagedDecimalSigned<M, D1> {
pub fn mul_with_precision<D2: Decimals, T: Decimals>(
self,
other: ManagedDecimalSigned<M, D2>,
precision: T,
) -> ManagedDecimalSigned<M, T> {
let result = ManagedDecimalSigned {
data: self.data * other.data,
decimals: self.decimals.num_decimals() + other.decimals.num_decimals(),
};
result.rescale(precision)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use crate::{
api::ManagedTypeApi,
types::{ConstDecimals, Decimals, ManagedDecimalSigned, NumDecimals},
};

use core::ops::{Sub, SubAssign};

impl<M: ManagedTypeApi, D1: Decimals, D2: Decimals> SubAssign<&ManagedDecimalSigned<M, D2>>
for ManagedDecimalSigned<M, D1>
{
fn sub_assign(&mut self, rhs: &ManagedDecimalSigned<M, D2>) {
let scaled_data = rhs.rescale_data(self.scale().num_decimals());
self.data -= scaled_data;
}
}

impl<M: ManagedTypeApi, D1: Decimals, D2: Decimals> SubAssign<ManagedDecimalSigned<M, D2>>
for ManagedDecimalSigned<M, D1>
{
#[inline]
fn sub_assign(&mut self, rhs: ManagedDecimalSigned<M, D2>) {
self.sub_assign(&rhs);
}
}

// const + const
impl<M: ManagedTypeApi, const DECIMALS: NumDecimals>
Sub<ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>>
for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
{
type Output = Self;

fn sub(mut self, rhs: ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>) -> Self::Output {
self.data -= rhs.data;
self
}
}

// var + var
impl<M: ManagedTypeApi> Sub<ManagedDecimalSigned<M, NumDecimals>>
for ManagedDecimalSigned<M, NumDecimals>
{
type Output = Self;

fn sub(mut self, rhs: ManagedDecimalSigned<M, NumDecimals>) -> Self::Output {
match self.decimals.cmp(&rhs.decimals) {
core::cmp::Ordering::Less => {
self = self.rescale(rhs.decimals);
self.data -= rhs.data;
},
core::cmp::Ordering::Equal => self.data -= rhs.data,
core::cmp::Ordering::Greater => {
let rhs_data = rhs.rescale_data(self.decimals);
self.data -= rhs_data;
},
}
self
}
}

// var + const
impl<const DECIMALS: usize, M: ManagedTypeApi> Sub<ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>>
for ManagedDecimalSigned<M, NumDecimals>
{
type Output = ManagedDecimalSigned<M, NumDecimals>;

fn sub(self, rhs: ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>) -> Self::Output {
self - rhs.into_var_decimals()
}
}

// const + var
impl<const DECIMALS: usize, M: ManagedTypeApi> Sub<ManagedDecimalSigned<M, NumDecimals>>
for ManagedDecimalSigned<M, ConstDecimals<DECIMALS>>
{
type Output = ManagedDecimalSigned<M, NumDecimals>;

fn sub(self, rhs: ManagedDecimalSigned<M, NumDecimals>) -> Self::Output {
self.into_var_decimals() - rhs
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,28 +46,32 @@ impl<M: ManagedTypeApi, D: Decimals> ManagedDecimalSigned<M, D> {
self.decimals.scaling_factor()
}

pub fn rescale<T: Decimals>(&self, scale_to: T) -> ManagedDecimalSigned<M, T>
where
M: ManagedTypeApi,
{
pub(crate) fn rescale_data(&self, scale_to_num_decimals: NumDecimals) -> BigInt<M> {
let from_num_decimals = self.decimals.num_decimals();
let scale_to_num_decimals = scale_to.num_decimals();

match from_num_decimals.cmp(&scale_to_num_decimals) {
Ordering::Less => {
let delta_decimals = scale_to_num_decimals - from_num_decimals;
let scaling_factor: &BigUint<M> = &delta_decimals.scaling_factor();
ManagedDecimalSigned::from_raw_units(&self.data * scaling_factor, scale_to)
&self.data * &scaling_factor.value
},
Ordering::Equal => ManagedDecimalSigned::from_raw_units(self.data.clone(), scale_to),
Ordering::Equal => self.data.clone(),
Ordering::Greater => {
let delta_decimals = from_num_decimals - scale_to_num_decimals;
let scaling_factor: &BigUint<M> = &delta_decimals.scaling_factor();
ManagedDecimalSigned::from_raw_units(&self.data * scaling_factor, scale_to)
&self.data * &scaling_factor.value
},
}
}

pub fn rescale<T: Decimals>(&self, scale_to: T) -> ManagedDecimalSigned<M, T>
where
M: ManagedTypeApi,
{
let scale_to_num_decimals = scale_to.num_decimals();
ManagedDecimalSigned::from_raw_units(self.rescale_data(scale_to_num_decimals), scale_to)
}

pub fn to_big_float(&self) -> BigFloat<M> {
let result = BigFloat::from_big_int(&self.data);
let temp_handle: M::BigFloatHandle = use_raw_handle(const_handles::BIG_FLOAT_TEMPORARY);
Expand Down Expand Up @@ -100,6 +104,14 @@ impl<M: ManagedTypeApi, const DECIMALS: NumDecimals>
decimals: ConstDecimals,
}
}

/// Converts from constant (compile-time) number of decimals to a variable number of decimals.
pub fn into_var_decimals(self) -> ManagedDecimalSigned<M, NumDecimals> {
ManagedDecimalSigned {
data: self.data,
decimals: DECIMALS,
}
}
}

impl<M: ManagedTypeApi, const DECIMALS: NumDecimals> TopEncode
Expand Down

0 comments on commit 4f69193

Please sign in to comment.