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

BinaryInteger/power(_:) #53

Closed
oscbyspro opened this issue Jul 30, 2024 · 2 comments
Closed

BinaryInteger/power(_:) #53

oscbyspro opened this issue Jul 30, 2024 · 2 comments
Labels
addition oh, so shiny!

Comments

@oscbyspro
Copy link
Owner

oscbyspro commented Jul 30, 2024

I'll add an exponentiation extension to BinaryInteger. It should wrap around and return an error indicator, making the result equivalent to repeated BinaryInteger/times(_:) calls. Negative and infinite exponents will be banned using Natural<T>.

extension BinaryInteger {

    /// Returns the `power` and `error` of `self` raised to `exponent`.
    ///
    /// ```swift
    /// U8(1).power(Natural(2)) // value: 001, error: false
    /// U8(2).power(Natural(3)) // value: 008, error: false
    /// U8(3).power(Natural(5)) // value: 243, error: false
    /// U8(5).power(Natural(7)) // value: 045, error: true 
    /// U8.exactly(00000078125) // value: 045, error: true
    /// ```
    ///
    /// - Note: Unsigned systems integers are always natural.
    ///
    @inlinable public borrowing func power(_ exponent: borrowing Natural<Self>) -> Fallible<Self> { ... }
}
@oscbyspro
Copy link
Owner Author

oscbyspro commented Aug 1, 2024

Clamping the exponent to UX in the arbitrary case seems like a decent way of reducing the cost of shifting, although shifting is relatively cheap. It works because the allocation limit is IX.max bits. It also works when |self| is 0 or 1. Edit: I suppose it isn't quite that simple, given that (-1)x is allocatable, yet it flips sign depending on whether the exponent is odd or even.

@oscbyspro
Copy link
Owner Author

oscbyspro commented Aug 1, 2024

Hm. I'm reluctant to allow signed exponents because I don't want to think about 0-x and the like. But, it turns out that infinite values just work. Most inputs with infinite exponents cannot be allocated, but that's equally true for big-but-finite exponents. So perhaps T.Magnitude is preferred over Natural<T>. I also don't need unsigned systems integer convenience methods if the exponent type is T.Magnitude.

oscbyspro added a commit that referenced this issue Aug 2, 2024
The exponent can be clamped to UX because the allocation limit is IX.max bits. Note that the clamped value must preserve the least significant bit of the original exponent in order to correctly toggle ~0. Also note that only 0, 1, and ~0 can be allocated when the exponent is greater than IX.max. This approach replaces arbitrary integer shifts with systems integer shifts.
oscbyspro added a commit that referenced this issue Aug 3, 2024
We only need to combine the multiplier's error indicator once at the end.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
addition oh, so shiny!
Projects
None yet
Development

No branches or pull requests

1 participant