From bb9eeb774366cfd4c66f873e9156d02fbd21adcb Mon Sep 17 00:00:00 2001 From: Bumblebee00 Date: Thu, 17 Jul 2025 18:35:52 +0200 Subject: [PATCH 1/4] added Logarithmic integral function --- docs/src/functions_list.md | 1 + docs/src/functions_overview.md | 1 + src/SpecialFunctions.jl | 1 + src/expint.jl | 29 +++++++++++++++++++++++++++++ 4 files changed, 32 insertions(+) diff --git a/docs/src/functions_list.md b/docs/src/functions_list.md index 5890373f..80716d7b 100644 --- a/docs/src/functions_list.md +++ b/docs/src/functions_list.md @@ -78,6 +78,7 @@ ncF expint expinti expintx +li sinint cosint ``` diff --git a/docs/src/functions_overview.md b/docs/src/functions_overview.md index 6cea9b02..6be48453 100644 --- a/docs/src/functions_overview.md +++ b/docs/src/functions_overview.md @@ -39,6 +39,7 @@ Here the *Special Functions* are listed according to the structure of [NIST Digi | [`expintx(x)`](@ref SpecialFunctions.expintx) | scaled [exponential integral](https://en.wikipedia.org/wiki/Exponential_integral) ``e^z \operatorname{E}_\nu(z)`` | | [`sinint(x)`](@ref SpecialFunctions.sinint) | [sine integral](https://en.wikipedia.org/wiki/Trigonometric_integral#Sine_integral) ``\operatorname{Si}(x)`` | | [`cosint(x)`](@ref SpecialFunctions.cosint) | [cosine integral](https://en.wikipedia.org/wiki/Trigonometric_integral#Cosine_integral) ``\operatorname{Ci}(x)`` | +| [`li(x)`](@ref SpecialFunctions.li) | [logarithmic integral function](https://en.wikipedia.org/wiki/Logarithmic_integral_function) ``\operatorname{li}(x)`` | ## Error Functions, Dawson’s and Fresnel Integrals diff --git a/src/SpecialFunctions.jl b/src/SpecialFunctions.jl index 0d296cc0..a0828c07 100644 --- a/src/SpecialFunctions.jl +++ b/src/SpecialFunctions.jl @@ -90,6 +90,7 @@ export expintx, sinint, cosint, + li, lbinomial include("bessel.jl") diff --git a/src/expint.jl b/src/expint.jl index 4e6af64a..38a61a13 100644 --- a/src/expint.jl +++ b/src/expint.jl @@ -610,3 +610,32 @@ function expinti(x::BigFloat) ccall((:mpfr_eint, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Base.MPFR.MPFRRoundingMode), z, x, Base.MPFR.ROUNDING_MODE[]) return z end + +############################################################################## +# Logarithmic integral function li + +@doc raw""" + expinti(x::Real) + +Computes the Logarithmic integral function +```math +\operatorname{li}(x) = \int_{0}^x \frac{1}{\ln{t}} \mathrm{d}t, +``` +which is equivalent to ``\operatorname{Ei}(\ln{x})`` where +``\operatorname{Ei}`` is the `expinti` function. + +External links: [Wikipedia](https://en.wikipedia.org/wiki/Logarithmic_integral_function) +""" +function li(x::Real) + if x < 0 + throw(DomainError(x, "negative argument, convert to complex first")) + elseif x == 0 + return 0 + elseif x == 1 + return -Inf + elseif x == Inf + return Inf + else + return expinti(log(x)) + end +end From 57883820fe3ad67acbc414f79d354805ce1a0718 Mon Sep 17 00:00:00 2001 From: Bumblebee00 Date: Fri, 18 Jul 2025 11:30:28 +0200 Subject: [PATCH 2/4] added tests for Logarithmic integral function --- test/expint.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/expint.jl b/test/expint.jl index d25e92a2..7de9f594 100644 --- a/test/expint.jl +++ b/test/expint.jl @@ -245,3 +245,10 @@ expinti_real(x) = invoke(expinti, Tuple{Real}, x) end end end + +@testset "Logarithmic integral function" begin + @test li(0.0) ≈ 0 + @test li(1.0) ≈ -Inf + @test li(Inf) === Inf + @test li(2) ≈ 1.0451637801174927 +end \ No newline at end of file From ff07c10b05b51b4ad79330d6ea9500322ddc85e2 Mon Sep 17 00:00:00 2001 From: Bumblebee00 Date: Sat, 19 Jul 2025 11:46:23 +0200 Subject: [PATCH 3/4] minor fixes --- src/expint.jl | 6 +----- test/expint.jl | 4 ++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/expint.jl b/src/expint.jl index 38a61a13..4dd7085d 100644 --- a/src/expint.jl +++ b/src/expint.jl @@ -615,7 +615,7 @@ end # Logarithmic integral function li @doc raw""" - expinti(x::Real) + li(x::Real) Computes the Logarithmic integral function ```math @@ -631,10 +631,6 @@ function li(x::Real) throw(DomainError(x, "negative argument, convert to complex first")) elseif x == 0 return 0 - elseif x == 1 - return -Inf - elseif x == Inf - return Inf else return expinti(log(x)) end diff --git a/test/expint.jl b/test/expint.jl index 7de9f594..994c5f67 100644 --- a/test/expint.jl +++ b/test/expint.jl @@ -247,8 +247,8 @@ expinti_real(x) = invoke(expinti, Tuple{Real}, x) end @testset "Logarithmic integral function" begin - @test li(0.0) ≈ 0 - @test li(1.0) ≈ -Inf + @test li(0.0) == 0 + @test li(1.0) == -Inf @test li(Inf) === Inf @test li(2) ≈ 1.0451637801174927 end \ No newline at end of file From bd3fe6e693948e6b6cd2f7279f9fed76975404b2 Mon Sep 17 00:00:00 2001 From: Bumblebee00 Date: Tue, 22 Jul 2025 19:21:17 +0200 Subject: [PATCH 4/4] review suggestions --- src/expint.jl | 2 +- test/expint.jl | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/expint.jl b/src/expint.jl index 4dd7085d..b21bcb0f 100644 --- a/src/expint.jl +++ b/src/expint.jl @@ -630,7 +630,7 @@ function li(x::Real) if x < 0 throw(DomainError(x, "negative argument, convert to complex first")) elseif x == 0 - return 0 + return zero(typeof(x)) else return expinti(log(x)) end diff --git a/test/expint.jl b/test/expint.jl index 994c5f67..40428001 100644 --- a/test/expint.jl +++ b/test/expint.jl @@ -247,8 +247,11 @@ expinti_real(x) = invoke(expinti, Tuple{Real}, x) end @testset "Logarithmic integral function" begin - @test li(0.0) == 0 - @test li(1.0) == -Inf - @test li(Inf) === Inf - @test li(2) ≈ 1.0451637801174927 + @test @inferred(li(0.0)) === 0.0 # float 64 + @test @inferred(li(0.0f0)) === 0.0f0 # float 32 + @test @inferred(li(Float16(0))) === Float16(0) # float 16 + + @test @inferred(li(1.0)) === -Inf + @test @inferred(li(Inf)) === Inf + @test @inferred(li(2)) ≈ 1.0451637801174927 # this errors idk why end \ No newline at end of file