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

Introduce flintify helper for "optimal" dispatch on integer and rational inputs #1867

Merged
merged 3 commits into from
Sep 26, 2024

Commits on Sep 26, 2024

  1. Introduce FlintInt and FlintRat helpers

    There are a bunch of FLINT function that come in multiple varieties.
    E.g. fmpz_add, fmpz_add_ui, fmpz_add_si all take one fmpz and one
    additional argument of type fmpz / UInt / Int, respectively.
    
    So naturally we define different `+` and `add!` methods in Julia using
    them. But which method to invoke when adding a `ZZRingElem` and a Julia
    integer of a type different from `UInt` and `Int`, such as e.g. `UInt32`
    ? In that case we currently always convert that into a `ZZRingElem`. But
    that's inefficient, it would be be better to convert that value to a
    `UInt` or `Int` value and then use the optimized `fmpz_add_ui/_si`
    method.
    
    Of course this can be done, but getting it right is tedious, repetitive
    and it is easy to overlook a case.
    
    This is where `FlintInt` comes in: this is defined as `Union{Int,
    ZZRingElem}`. We then provide constructors which convert any `Integer`
    to a `FlintInt` in an optimal way (at least for a bunch of built-in
    integer types).
    
    This then can be used to write optimal dispatch for Integer types
    like this:
    
        add!(x::ZRingElem, y::ZRingElem) = ...
        add!(x::ZRingElem, y::Int) = ...
        add!(x::ZRingElem, y::UInt) = ...
        # fallback code
        add!(x::ZRingElem, y::Integer) = add!(x, FlintInt(y))
    
    It also works for types that accept ZZRingElem and Int, but not UInt:
    
        add!(x::ZPolyRingElem, y::ZPolyRingElem) = ...
        add!(x::ZPolyRingElem, y::ZRingElem) = ...
        add!(x::ZPolyRingElem, y::Int) = ...
        # fallback code
        add!(x::ZPolyRingElem, y::Integer) = add!(x, FlintInt(y))
    
    Of course I might have missed optimal conversion for some `Integer`
    subtype. But then we can fix this by simply adding another `FlintInt`
    constructor in a single central place.
    
    Finally, the new type `FlintRat` plays a similar role for FLINT
    functions which also take a `QQFieldElem`. While `RationalUnion` is a
    counterpart to `IntegerUnion`.
    fingolfin committed Sep 26, 2024
    Configuration menu
    Copy the full SHA
    b8c8bfe View commit details
    Browse the repository at this point in the history
  2. Update src/flint/FlintTypes.jl

    Co-authored-by: Lars Göttgens <[email protected]>
    fingolfin and lgoettgens authored Sep 26, 2024
    Configuration menu
    Copy the full SHA
    18923be View commit details
    Browse the repository at this point in the history
  3. Rewrite to use flintify

    fingolfin committed Sep 26, 2024
    Configuration menu
    Copy the full SHA
    05d75a0 View commit details
    Browse the repository at this point in the history