oscbyspro / Ultimathnum

Binary arithmetic reimagined in Swift
Apache License 2.0
4 stars 1 forks source link

Finite<T> and Natural<T> trusted inputs #11

Closed oscbyspro closed 4 weeks ago

oscbyspro commented 4 weeks ago

I have settled on hoisting the GCD and XGCD preconditions (#9) via the Trusted Input :tm: pattern to enable recovery. As an example, the XGCD algorithms should extend all unsigned integers and they only fail when the arguments are infinite. I cannot limit these algorithms to a finite integer types because that makes them unavailable to InfiniInt\<T>. So, instead, I'll just require that the inputs are of the Finite\<T> type:

extension BinaryInteger {
    @inlinable public static func euclidean(
        _ lhs: consuming Finite<Self>,
        _ rhs: consuming Finite<Self>
    ) -> Magnitude

    @inlinable public static func euclidean1(
    _ lhs: consuming Finite<Self>,
    _ rhs: consuming Finite<Self>
    ) -> XGCD1 where Self: UnsignedInteger

    @inlinable public static func euclidean2(
    _ lhs: consuming Finite<Self>,
    _ rhs: consuming Finite<Self>
    ) -> XGCD2 where Self: UnsignedInteger
}

Some convenience methods can then be written as finite integer extensions:

extension FiniteInteger {
    @inlinable public consuming func euclidean(_ other: consuming Self) -> Magnitude {
        Self.euclidean (Finite(unchecked: self), Finite(unchecked: other))
    }

    @inlinable public consuming func euclidean1(_ other: consuming Self) -> XGCD1 where Self: UnsignedInteger {
        Self.euclidean1(Finite(unchecked: self), Finite(unchecked: other))
    }

    @inlinable public consuming func euclidean2(_ other: consuming Self) -> XGCD2 where Self: UnsignedInteger {
        Self.euclidean2(Finite(unchecked: self), Finite(unchecked: other))
    }
}

The current use case does not need Natural\<T> but I imagine that it is of similar importance.