Skip to content

Add pow and root functions #106

@porky11

Description

@porky11

These should be easy to implement.

I created some implementations, but I don't want to check, which of them should be functions, methods or trait implementations.
I made all of them trait implementations for now.
If the value can not

Here are the implementations:

// Pow by ratio
// I only tested this function; I use it in my code
fn pow_ratio<I: PrimInt + Roots>(a: Ratio<I>, b: Ratio<u32>) -> Option<Ratio<I>> {
    let (an, ad) = a.into();
    let (bn, bd) = b.into();

    let pown = an.pow(bn);
    let powd = ad.pow(bn);

    let n = pown.nth_root(bd);
    let d = powd.nth_root(bd);

    // If there does not exist a rational power, return none
    if n.pow(bd) != pown || d.pow(bd) != powd {
        None
    } else {
        Some(Ratio::new(n, d))
    }
}

// Pow by integer
fn pow_integer<I: PrimInt>(a: Ratio<I>, b: u32) -> Ratio<I> {
    let (an, ad) = a.into();

    let pown = an.pow(b);
    let powd = ad.pow(b);

    Ratio::new(n, d)
}

// Root by integer
fn root_integer<I: PrimInt + Roots>(a: Ratio<I>, b: u32) -> Option<Ratio<I>> {
    // add checks if b is zero and either return none or some result for more expressiveness

    let (an, ad) = a.into();

    let n = an.nth_root(b);
    let d = ad.nth_root(b);

    // If there does not exist a rational root, return none
    if n.pow(b) != pown || d.pow(b) != powd {
        None
    } else {
        Some(Ratio::new(n, d))
    }
}

// Root by ratio
fn root_ratio<I: PrimInt + Roots>(a: Ratio<I>, b: Ratio<u32>) -> Option<Ratio<I>> {
    // add checks if b is zero and either return none or some result for more expressiveness

    pow_ratio(a, b.inv())
}

// Square root
fn sqrt<I: PrimInt + Roots>(a: Ratio<I>, b: Ratio<u32>) -> Option<Ratio<I>> {
    // use a version of this function without the zero check for argument b
    root_integer(a, 2)
}

// Cubic root
fn cbrt<I: PrimInt + Roots>(a: Ratio<I>, b: Ratio<u32>) -> Option<Ratio<I>> {
    // use a version of this function without the zero check for argument b
    root_integer(a, 3)
}

pow_integerand root_integer could be implemented using pow_ratio and root_ratio by supplying constant values.
The compiler should be able to optimize, at least if the functions are declared as inline.

Should all of these functions be added anyway?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions