-
Notifications
You must be signed in to change notification settings - Fork 22
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
Add loglogistic
, logitexp
, log1mlogistic
and logit1mexp
#82
Changes from 25 commits
8fa3801
218d508
f89c9c5
33e6677
51b9a5b
9f24823
a7f9cdd
223327d
27322fc
716b886
3da3f8a
8ee3db1
c9ab3f3
ac17f3c
16d6c9c
0d65559
5d84266
86ac5f5
eb1633a
46c0e60
18a58ef
519a6a4
716b671
58133ad
1b0f914
2aa9f44
177cebb
0d60abd
15cb4ef
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -468,3 +468,93 @@ end | |
@test cexpexp(-Inf) == 0.0 | ||
@test cexpexp(0) == (ℯ - 1) / ℯ | ||
end | ||
|
||
@testset "loglogistic: $T" for T in (Float16, Float32, Float64) | ||
lim1 = T === Float16 ? -14.0 : -50.0 | ||
lim2 = T === Float16 ? -10.0 : -37.0 | ||
xs = T[Inf, -Inf, 0.0, lim1, lim2] | ||
for x in xs | ||
@test loglogistic(x) == log(logistic(x)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we test multiple types There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Makes sense. Comprehensive return type tests have been added for the 4 functions included in this PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Anything else, @devmotion? |
||
end | ||
|
||
ϵ = eps(T) | ||
xs = T[ϵ, 1.0, 18.0, 33.3, 50.0] | ||
for x in xs | ||
lhs = loglogistic(x) | ||
rhs = log(logistic(x)) | ||
@test abs(lhs - rhs) < ϵ | ||
end | ||
|
||
# misc | ||
@test loglogistic(T(Inf)) == -zero(T) | ||
@test loglogistic(-T(Inf)) == -T(Inf) | ||
@test loglogistic(-T(103.0)) == -T(103.0) | ||
@test abs(loglogistic(T(35.0))) < 3eps(T) | ||
@test abs(loglogistic(T(103.0))) < eps(T) | ||
@test isfinite(loglogistic(-T(745.0))) | ||
@test isfinite(loglogistic(T(50.0))) | ||
@test isfinite(loglogistic(T(745.0))) | ||
end | ||
|
||
|
||
@testset "logitexp: $T" for T in (Float16, Float32, Float64) | ||
ϵ = eps(T) | ||
xs = T[ϵ, √ϵ, 0.2, 0.4, 0.8, 1.0 - √ϵ, 1.0 - ϵ] | ||
neg_xs = -xs | ||
for x in xs | ||
@test abs(logitexp(loglogistic(x)) - x) <= ϵ | ||
end | ||
for x in neg_xs | ||
@test abs(logitexp(loglogistic(x)) - x) <= 2ϵ | ||
end | ||
xs = T[-Inf, 0.0, Inf] | ||
for x in xs | ||
@test logitexp(loglogistic(x)) == x | ||
end | ||
end | ||
|
||
@testset "log1mlogistic: $T" for T in (Float16, Float32, Float64) | ||
@test log1mlogistic(T(Inf)) == -T(Inf) | ||
@test log1mlogistic(-T(Inf)) == -zero(T) | ||
@test log1mlogistic(-T(103.0)) < eps(T) | ||
@test abs(log1mlogistic(T(35.0))) == T(35.0) | ||
@test abs(log1mlogistic(T(103.0))) == T(103.0) | ||
@test isfinite(log1mlogistic(-T(745.0))) | ||
@test isfinite(log1mlogistic(T(50.0))) | ||
@test isfinite(log1mlogistic(T(745.0))) | ||
end | ||
|
||
|
||
@testset "logit1mexp: $T" for T in (Float16, Float32, Float64) | ||
ϵ = eps(T) | ||
xs = T[ϵ, √ϵ, 0.2, 0.4, 0.8, 1.0 - √ϵ, 1.0 - ϵ] | ||
neg_xs = -xs | ||
for x in xs | ||
@test abs(logit1mexp(log1mlogistic(x)) - x) <= 2ϵ | ||
end | ||
for x in neg_xs | ||
@test abs(logit1mexp(log1mlogistic(x)) - x) <= ϵ | ||
end | ||
xs = T[-Inf, 0.0, Inf] | ||
for x in xs | ||
@test logit1mexp(log1mlogistic(x)) == x | ||
end | ||
end | ||
|
||
@testset "correctness wrt Unsigned, Rational" begin | ||
@test loglogistic(UInt64(5)) == loglogistic(5.0) | ||
@test log1mlogistic(UInt64(5)) == log1mlogistic(5.0) | ||
|
||
@test loglogistic(0x01//0x02) == loglogistic(0.5) | ||
@test log1mlogistic(0x01//0x02) == log1mlogistic(0.5) | ||
end | ||
|
||
@testset "correctness wrt Integer edge case" begin | ||
# If not handled, these will be zero | ||
@test loglogistic(typemin(Int)) == loglogistic(float(typemin(Int))) | ||
@test log1mlogistic(typemin(Int)) == log1mlogistic(float(typemin(Int))) | ||
|
||
# If not handled, these would throw since negation at typemin is a round-trip | ||
@test logitexp(typemin(Int)) == logitexp(float(typemin(Int))) | ||
@test logit1mexp(typemin(Int)) == logit1mexp(float(typemin(Int))) | ||
end |
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.
IMO these are not needed - AD handles the functions already fine since rules for
log1pexp
etc. are defined.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.
As directed, these definitions have been removed.
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.
Looking through the issues, #36 seems to indicate that these functions should support
ChainRulesCore
forward and reverse rules.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.
No, that's just not correct. These new functions are supported by ChainRulesCore-based AD systems just fine without any additional definitions. See https://juliadiff.org/ChainRulesCore.jl/stable/rule_author/which_functions_need_rules.html for some additional information on this matter.