-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
replace O(n^2) LOC with constant-prop in Dates #46036
Conversation
LilithHafner
commented
Jul 14, 2022
stdlib/Dates/src/periods.jl
Outdated
@@ -170,7 +131,7 @@ struct CompoundPeriod <: AbstractTime | |||
function CompoundPeriod(p::Vector{Period}) | |||
n = length(p) | |||
if n > 1 | |||
sort!(p, rev=true, lt=periodisless) | |||
sort!(p, rev = true, by = days ∘ oneunit) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm, what's going on here? Can you explain the magic?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure!
We sort periods in decreasing order (rev = true
) according to the length of the period (e.g Week(1)
before Hour(240)
). There are many ways to get the length of a period p
and days(oneunit(p))
seems like a reasonable choice. How many days is one Second
/Week
/Year
? This is sometimes a Flaot64
and sometimes an Int64
but we already don't have type stability because we are working with Vector{Period}
and this constant folds once the type is known.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That explanation feels a bit long to include as a comment, but we could if you think it is appropriate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah adding a comment on how this works is probably a good idea, specially given that the code it replaces is pretty obvious in how it works
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this explain it adequitely?
# We sort periods in decreasing order (rev = true) according to the length of
# the period's type (by = days ∘ oneunit). We sort by type, not value, so that
# we can merge equal types.
#
# This works by computing how many days are in a single period, and then sorting
# by that. For example, (days ∘ oneunit)(Week(10)) = days(oneunit(Week(10))) =
# days(Week(1)) = 7, which is less than (days ∘ oneunit)(Month(-2)) = 30.436875
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if this is less obvious, I think its a worthwhile change because it takes the number of new methods to be implemented for a new Period
type to support CompundPeriod
s down from O(n) to 0.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That sounds quite clear 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
To distinguish small period types from each other. This avoids JuliaLang#46150 and, more importantly, fixes: ```julia julia> Dates.days(Millisecond(1)) 0 julia> Dates.days(Second(1)) 0 ```