Skip to content

Commit

Permalink
Fix type instability (#125)
Browse files Browse the repository at this point in the history
  • Loading branch information
t-bltg authored Dec 14, 2021
1 parent b2c8065 commit 383d532
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 28 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "PlotUtils"
uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043"
version = "1.1.0"
version = "1.1.1"

[deps]
ColorSchemes = "35d6a980-a343-548e-a6ea-1d62b119f2f4"
Expand Down
60 changes: 33 additions & 27 deletions src/ticks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ const _logScaleBases = Dict(:ln => ℯ, :log2 => 2.0, :log10 => 10.0)
# Find the smallest order of magnitude that is larger than xspan This is a
# little opaque because I want to avoid assuming the log function is defined
# over typeof(xspan)
function bounding_order_of_magnitude(xspan::T, base) where T
function bounding_order_of_magnitude(xspan::T, base::T) where T
a = 1
step = 1
while xspan < T(base^a)
while xspan < base^a
a -= step
end

b = 1
step = 1
while xspan > T(base^b)
while xspan > base^b
b += step
end

while a + 1 < b
c = div(a + b, 2)
if xspan < T(base^c)
if xspan < base^c
b = c
else
a = c
Expand All @@ -31,8 +31,8 @@ function bounding_order_of_magnitude(xspan::T, base) where T
return b
end

const float_digit_range = floor(Int,log10(floatmin())):ceil(Int,log10(floatmax()))
postdecimal_digits(x) = first(i for i in float_digit_range if x==floor(x; digits=i))
float_digit_range(T) = floor(Int, log10(floatmin(T))):ceil(Int, log10(floatmax(T)))
postdecimal_digits(x) = first(i for i in float_digit_range(typeof(x)) if x == floor(x; digits=i))

fallback_ticks(x_min::T, x_max::T, k_min, k_max) where T = collect(T, range(x_min, x_max; length=k_min)), x_min, x_max

Expand Down Expand Up @@ -129,25 +129,25 @@ and the variables here are:
* `v`: 1 if label range includes 0, 0 otherwise.
"""
function optimize_ticks(x_min::T, x_max::T; extend_ticks::Bool=false,
Q=[(1., 1.), (5., .9), (2., .7), (2.5, .5), (3., .2)],
k_min::Int=2, k_max::Int=10, k_ideal::Int=5,
granularity_weight::Float64=1/4, simplicity_weight::Float64=1/6,
coverage_weight::Float64=1/3, niceness_weight::Float64=1/4,
strict_span=true, span_buffer=nothing, scale=nothing) where T
Q=[(1., 1.), (5., .9), (2., .7), (2.5, .5), (3., .2)],
k_min::Int=2, k_max::Int=10, k_ideal::Int=5,
granularity_weight::Float64=1/4, simplicity_weight::Float64=1/6,
coverage_weight::Float64=1/3, niceness_weight::Float64=1/4,
strict_span=true, span_buffer=nothing, scale=nothing) where T

Qv = [(Float64(q[1]), Float64(q[2])) for q in Q]
optimize_ticks_typed(x_min, x_max, extend_ticks, Qv, k_min, k_max, k_ideal,
granularity_weight, simplicity_weight,
coverage_weight, niceness_weight, strict_span, span_buffer, scale)
F = float(T)
Qv = [(F(q[1]), F(q[2])) for q in Q]
optimize_ticks_typed(F(x_min), F(x_max), extend_ticks, Qv, k_min, k_max, k_ideal,
F(granularity_weight), F(simplicity_weight),
F(coverage_weight), F(niceness_weight), strict_span, span_buffer, scale)
end

function optimize_ticks_typed(x_min::T, x_max::T, extend_ticks,
Q::Vector{Tuple{Float64,Float64}}, k_min, k_max, k_ideal,
granularity_weight::Float64, simplicity_weight::Float64,
coverage_weight::Float64, niceness_weight::Float64,
strict_span, span_buffer, scale) where T

F = float(T)
function optimize_ticks_typed(x_min::F, x_max::F, extend_ticks,
Q::AbstractVector, k_min, k_max, k_ideal,
granularity_weight::F, simplicity_weight::F,
coverage_weight::F, niceness_weight::F,
strict_span, span_buffer, scale) where F

if (xspan = x_max - x_min) < eps(F)
return fallback_ticks(x_min, x_max, k_min, k_max)
end
Expand Down Expand Up @@ -193,8 +193,8 @@ function optimize_ticks_typed(x_min::T, x_max::T, extend_ticks,
isfinite(r) || continue
r = ceil(Int, r)

# try to favor integer exponents for log scales
if is_log_scale && !isinteger(tickspan)
# try to favor integer exponents for log scales
nice_scale = false
qscore = 0
else
Expand Down Expand Up @@ -243,18 +243,24 @@ function optimize_ticks_typed(x_min::T, x_max::T, extend_ticks,
S = view(S, 1:counter)
end

len_S = length(S)

# evaluate quality of ticks
has_zero = r <= 0 && abs(r) < k

# simplicity
s = has_zero && nice_scale ? 1 : 0

# granularity
g = 0 < length(S) < 2k_ideal ? 1 - abs(length(S) - k_ideal) / k_ideal : 0
g = 0 < len_S < 2k_ideal ? 1 - abs(len_S - k_ideal) / k_ideal : F(0)

# coverage
effective_span = (length(S) - 1) * tickspan
c = abs(effective_span) > eps(F) ? 1.5xspan / effective_span : 0
c = if len_S > 1
effective_span = (len_S - 1) * tickspan
1.5xspan / effective_span
else
F(0)
end

score = granularity_weight * g +
simplicity_weight * s +
Expand All @@ -269,7 +275,7 @@ function optimize_ticks_typed(x_min::T, x_max::T, extend_ticks,
score -= 1000
end

if score > high_score && (k_min <= length(S) <= k_max)
if score > high_score && (k_min <= len_S <= k_max)
if strict_span
# make S a copy because it is a view and
# could otherwise be mutated in the next runs
Expand Down

2 comments on commit 383d532

@t-bltg
Copy link
Member Author

@t-bltg t-bltg commented on 383d532 Dec 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/50574

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.1.1 -m "<description of version>" 383d5321e9a4ccb9d21c6561719c4479c7b697d7
git push origin v1.1.1

Please sign in to comment.