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

Update struct for Series #157

Merged
merged 2 commits into from
Aug 1, 2022
Merged

Update struct for Series #157

merged 2 commits into from
Aug 1, 2022

Conversation

Joel-Dahne
Copy link
Collaborator

@Joel-Dahne Joel-Dahne commented Jul 30, 2022

Here comes a more opinionated change where some input could be helpful.

This change originates from a problem I have, but it doesn't solve the problem. The problem is that I want ArbSeries (and AcbSeries) to satisfy the invariances

x::ArbSeries + zero(ArbSeries) == x
(x::ArbSeries) * one(ArbSeries) == x

At the moment this doesn't work because the type ArbSeries doesn't contain any information about the degree of the series. The only way I see to solve this issue is to parameterize the ArbSeries type on the degree, so it would become ArbSeries{N} where N is the degree. However, I'm afraid that would be too costly in terms of compilation since all methods would have to be compiled separately for each degree.

This PR doesn't solve the above problem, but moves one step towards some sort of solution. It changes the Series types so that the polynomial is stored separately from the degree. For methods that don't need the degree, but only act on the underlying polynomial, it is then possible to pass them just the polynomial. If we ever decide to parameterize the type (I'm not sure we'll) this would at least allow for having less of the code needing compilation based on the degree.

More precisely the PR changes the layout of the struct for ArbSeries and AcbSeries, for ArbSeries it changes from

struct ArbSeries <: Number
    arb_poly::arb_poly_struct
    degree::Int
    prec::Int
end

to

struct ArbSeries <: Number
    poly::ArbPoly
    degree::Int
end

It makes it possible to, given an ArbSeries, treat it as an ArbPoly for some computations, without having to allocate. At the moment there is no non-allocating constructor for ArbSeries, this could possibly be added in the future.

I can also note that I don't think there is any performance penalty for this change. The struct is immutable so everything seems to be stored inline anyway.

The ArbSeries type now stores an ArbPoly and AcbSeries stores and
AcbPoly. This allows for using the series as a polynomial without
allocations.
@kalmarek
Copy link
Owner

kalmarek commented Aug 1, 2022

I think this could be solved if zero(ArbSeries)/one(ArbSeries) created an exact object? (but is it possible?). Then x::ArbSeries + zero(ArbSeries) == x should follow from the definition of == (except when precision(x) < Arblib.DEFAULT_PRECISION[]).

A stop-gap solution would be to replace

Base.zero(::Type{T}) where {T<:Union{Poly,Series}} = T()

by

Base.zero(::Type{T}) where {T<: Poly} = T()
Base.zero(::Type{T}) where {T<: Series} = T(degree=DEFAULT_PRECISION[])

at the cost of making zero vastly more expensive. :P Btw. where does the zero(ArbSeries) in your computations come from?

I'm not a big fan of introducing degree to the type, but we could probably create a specialized version of ArbSeriesOfDeg{N} <: AbstractSeries for people who want just to compute at a given degree, that's another option.

@Joel-Dahne
Copy link
Collaborator Author

I have thought a bit about having some sort of flag indicating that the series is an exact constant and not truncated. I'm worried that it would require a lot of work to handle this properly everywhere. What is nice is that such a flag would in general propagate nicely through functions, for example exp(one(ArbSeries)) is still a constant.

The reason that I want this feature is that I want ArbSeries to work better in generic Julia code. For example a simple functions such as

function mysum(v::AbstractVector{T}) where {T}
  res = zero(T)
  for x in v
    res += x
  end
  return res
end

does not work properly for ArbSeries. In most cases it is very easy to rewrite the methods to work for ArbSeries, so for code that I control it is not really an issue. But for code other people have written I have sometimes encountered this issue.

For now I'll continue to think about if there is a good way to handle it, possibly through a is-constant flag or some sort of ArbSeriesOfDeg{N} type. I agree that adding the degree to the type would not be optimal.

The change I propose in this PR I think is a good idea though. It makes it easier when you sometimes want to treat a series just as a polynomial (something I do every once in a while) and I think the only cost is that of backwards compatibility (but only if they use the internal structure of the series).

@Joel-Dahne
Copy link
Collaborator Author

I think this would also be a good point to make a new release. I have some other changes on the way but they are about documentation so don't need a release, also I don't know how long it will take me to finish them.

@Joel-Dahne Joel-Dahne merged commit 11cf77b into master Aug 1, 2022
@Joel-Dahne Joel-Dahne deleted the update-series-struct branch August 1, 2022 19:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants