Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: FoldAdd and FoldMul #209

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ against this Rust version.
- [removed] Remove `force_unix_path_separator` feature, make it the default
- [added] docs.rs metadata and cfg options
- [added] Playground metadata
- [added] `FoldAdd` and `FoldMul` to get the sum/product of an array

### 1.16.0 (2022-12-05)
- [added] `const INT` field to the `ToInt` trait.
Expand Down
54 changes: 54 additions & 0 deletions src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,60 @@ where
}
}

// ---------------------------------------------------------------------------------------
// FoldAdd

/// Hide our `Null` type
const _: () = {
/// A type which contributes nothing when adding (i.e. a zero)
pub struct Null;
impl<T> Add<T> for Null {
type Output = T;
fn add(self, rhs: T) -> Self::Output {
rhs
}
}

impl FoldAdd for ATerm {
type Output = Null;
}
};

impl<V, A> FoldAdd for TArr<V, A>
where
A: FoldAdd,
FoldSum<A>: Add<V>,
{
type Output = Sum<FoldSum<A>, V>;
}

// ---------------------------------------------------------------------------------------
// FoldMul

/// Hide our `Null` type
const _: () = {
/// A type which contributes nothing when multiplying (i.e. a one)
pub struct Null;
impl<T> Mul<T> for Null {
type Output = T;
fn mul(self, rhs: T) -> Self::Output {
rhs
}
}

impl FoldMul for ATerm {
type Output = Null;
}
};

impl<V, A> FoldMul for TArr<V, A>
where
A: FoldMul,
FoldProd<A>: Mul<V>,
{
type Output = Prod<FoldProd<A>, V>;
}

// ---------------------------------------------------------------------------------------
// Add arrays
// Note that two arrays are only addable if they are the same length.
Expand Down
8 changes: 7 additions & 1 deletion src/operator_aliases.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

// Aliases!!!
use crate::type_operators::{
Abs, Cmp, Gcd, Len, Logarithm2, Max, Min, PartialDiv, Pow, SquareRoot,
Abs, Cmp, FoldAdd, FoldMul, Gcd, Len, Logarithm2, Max, Min, PartialDiv, Pow, SquareRoot,
};
use core::ops::{Add, BitAnd, BitOr, BitXor, Div, Mul, Neg, Rem, Shl, Shr, Sub};

Expand Down Expand Up @@ -83,6 +83,12 @@ pub type Compare<A, B> = <A as Cmp<B>>::Output;
/// Alias for the associated type of `Len`: `Length<A> = <A as Len>::Output`
pub type Length<T> = <T as Len>::Output;

/// Alias for the associated type of `FoldAdd`: `FoldSum<A> = <A as FoldAdd>::Output`
pub type FoldSum<A> = <A as FoldAdd>::Output;

/// Alias for the associated type of `FoldMul`: `FoldProd<A> = <A as FoldMul>::Output`
pub type FoldProd<A> = <A as FoldMul>::Output;

/// Alias for the associated type of `Min`: `Minimum<A, B> = <A as Min<B>>::Output`
pub type Minimum<A, B> = <A as Min<B>>::Output;

Expand Down
19 changes: 19 additions & 0 deletions src/type_operators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,25 @@ pub trait Len {
fn len(&self) -> Self::Output;
}

/// A **type operator** that gives the sum of all elements of an `Array`.
pub trait FoldAdd {
/// The type of the result of the sum
type Output;
}

/// A **type operator** that gives the product of all elements of an `Array`.
pub trait FoldMul {
/// The type of the result of the product
type Output;
}

#[test]
fn fold_test() {
use crate::*;
assert_eq!(10, <FoldSum::<tarr![U2, U3, U5]>>::to_u32());
assert_eq!(30, <FoldProd::<tarr![U2, U3, U5]>>::to_u32());
}

/// Division as a partial function. This **type operator** performs division just as `Div`, but is
/// only defined when the result is an integer (i.e. there is no remainder).
pub trait PartialDiv<Rhs = Self> {
Expand Down