diff --git a/.travis.yml b/.travis.yml index 188f1c6..3fe8186 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,10 +2,9 @@ language: julia os: - linux - - osx julia: - - 0.5 - - 0.6 + - 0.7 + - 1.0 - nightly notifications: email: false diff --git a/REQUIRE b/REQUIRE index 1924a34..909c7f5 100644 --- a/REQUIRE +++ b/REQUIRE @@ -1,3 +1,3 @@ -julia 0.5 -Unitful 0.1.5 -QuadGK 0.1.1 +julia 0.7 +Unitful 0.11.0 +QuadGK 2.0.0 diff --git a/appveyor.yml b/appveyor.yml index 111c8f7..c2588f1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,9 +1,18 @@ environment: matrix: - - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.5/julia-0.5-latest-win32.exe" - - JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.5/julia-0.5-latest-win64.exe" - - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x86/julia-latest-win32.exe" - - JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe" + - julia_version: 0.7 + - julia_version: 1 + - julia_version: nightly + +platform: + - x86 # 32-bit + - x64 # 64-bit + +# # Uncomment the following lines to allow failures on nightly julia +# # (tests will run but not make your overall status red) +# matrix: +# allow_failures: +# - julia_version: nightly branches: only: @@ -17,19 +26,18 @@ notifications: on_build_status_changed: false install: - - ps: "[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12" -# Download most recent Julia Windows binary - - ps: (new-object net.webclient).DownloadFile( - $env:JULIA_URL, - "C:\projects\julia-binary.exe") -# Run installer silently, output to C:\projects\julia - - C:\projects\julia-binary.exe /S /D=C:\projects\julia + - ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/JuliaCI/Appveyor.jl/version-1/bin/install.ps1")) build_script: -# Need to convert from shallow to complete for Pkg.clone to work - - IF EXIST .git\shallow (git fetch --unshallow) - - C:\projects\julia\bin\julia -e "versioninfo(); - Pkg.clone(pwd(), \"UnitfulIntegration\"); Pkg.build(\"UnitfulIntegration\")" + - echo "%JL_BUILD_SCRIPT%" + - C:\julia\bin\julia -e "%JL_BUILD_SCRIPT%" test_script: - - C:\projects\julia\bin\julia -e "Pkg.test(\"UnitfulIntegration\")" + - echo "%JL_TEST_SCRIPT%" + - C:\julia\bin\julia -e "%JL_TEST_SCRIPT%" + +# # Uncomment to support code coverage upload. Should only be enabled for packages +# # which would have coverage gaps without running on Windows +# on_success: +# - echo "%JL_CODECOV_SCRIPT%" +# - C:\julia\bin\julia -e "%JL_CODECOV_SCRIPT%" diff --git a/src/UnitfulIntegration.jl b/src/UnitfulIntegration.jl index 8e034d9..313090f 100644 --- a/src/UnitfulIntegration.jl +++ b/src/UnitfulIntegration.jl @@ -4,6 +4,7 @@ module UnitfulIntegration using Unitful import Unitful: DimensionError import QuadGK +import LinearAlgebra function QuadGK.quadgk(f, a::Quantity, b::Quantity, c::Quantity...; kws...) d = dimension(a) @@ -14,29 +15,29 @@ function QuadGK.quadgk(f, a::Quantity, b::Quantity, c::Quantity...; kws...) QuadGK.quadgk(f, promote(a,b,c...)...; kws...) end -function QuadGK.quadgk{T<:AbstractFloat,D,U}(f, a::Quantity{T,D,U}, - b::Quantity{T,D,U}, c::Quantity{T,D,U}...; abstol=NaN, reltol=sqrt(eps(T)), - maxevals=10^7, order=7, norm=vecnorm) - if isnan(abstol) - error("must provide an explicit abstol keyword argument, e.g. ", +function QuadGK.quadgk(f, a::Quantity{T,D,U}, b::Quantity{T,D,U}, c::Quantity{T,D,U}...; + atol=missing, rtol=sqrt(eps(T)), maxevals=10^7, order=7, norm=LinearAlgebra.norm) where + {T<:AbstractFloat,D,U} + if ismissing(atol) + error("must provide an explicit atol keyword argument, e.g. ", "`zero(f(a)*a)` supposing f is defined at a.") end - _do_quadgk(f, [a, b, c...], order, T, abstol, reltol, maxevals, norm) + _do_quadgk(f, [a, b, c...], order, T, atol, rtol, maxevals, norm) end -function QuadGK.quadgk{T<:AbstractFloat,D,U}(f, a::Quantity{Complex{T},D,U}, - b::Quantity{Complex{T},D,U}, c::Quantity{Complex{T},D,U}...; abstol=NaN, - reltol=sqrt(eps(T)), maxevals=10^7, order=7, norm=vecnorm) - if isnan(abstol) - error("must provide an explicit abstol keyword argument, e.g. ", +function QuadGK.quadgk(f, a::Quantity{Complex{T},D,U}, b::Quantity{Complex{T},D,U}, + c::Quantity{Complex{T},D,U}...; atol=missing, rtol=sqrt(eps(T)), maxevals=10^7, + order=7, norm=LinearAlgebra.norm) where {T<:AbstractFloat,D,U} + if ismissing(atol) + error("must provide an explicit atol keyword argument, e.g. ", "`zero(f(a)*a)` supposing f is defined at a.") end - _do_quadgk(f, [a, b, c...], order, T, abstol, reltol, maxevals, norm) + _do_quadgk(f, [a, b, c...], order, T, atol, rtol, maxevals, norm) end # Necessary with infinite or semi-infinite intervals since quantities !<: Real -function _do_quadgk{Tw,T<:Real,D,U}(f, s::Array{Quantity{T,D,U},1}, n, ::Type{Tw}, - abstol, reltol, maxevals, nrm) +function _do_quadgk(f, s::Array{Quantity{T,D,U},1}, n, ::Type{Tw}, atol, rtol, + maxevals, nrm) where {Tw,T<:Real,D,U} s_no_u = reinterpret(T, s) s1 = s_no_u[1]; s2 = s_no_u[end]; inf1 = isinf(s1); inf2 = isinf(s2) @@ -46,25 +47,25 @@ function _do_quadgk{Tw,T<:Real,D,U}(f, s::Array{Quantity{T,D,U},1}, n, ::Type{Tw f(t*den*U())*U() * (1+t2)*den*den; end, map(x -> isinf(x) ? copysign(one(x), x) : 2x / (1+hypot(1,2x)), s_no_u), - n, T, abstol, reltol, maxevals, nrm) + n, T, atol, rtol, maxevals, nrm) end s0,si = inf1 ? (s2,s1) : (s1,s2) if si < 0 # x = s0 - t/(1-t) return QuadGK.do_quadgk(t -> begin den = 1 / (1 - t); f((s0 - t*den)*U())*U() * den*den; end, reverse!(map(x -> 1 / (1 + 1 / (s0 - x)), s_no_u)), - n, T, abstol, reltol, maxevals, nrm) + n, T, atol, rtol, maxevals, nrm) else # x = s0 + t/(1-t) return QuadGK.do_quadgk(t -> begin den = 1 / (1 - t); f((s0 + t*den)*U())*U() * den*den; end, map(x -> 1 / (1 + 1 / (x - s0)), s_no_u), - n, T, abstol, reltol, maxevals, nrm) + n, T, atol, rtol, maxevals, nrm) end end - QuadGK.do_quadgk(f, s, n, Tw, abstol, reltol, maxevals, nrm) + QuadGK.do_quadgk(f, s, n, Tw, atol, rtol, maxevals, nrm) end -_do_quadgk{Tw}(f, s, n, ::Type{Tw}, abstol, reltol, maxevals, nrm) = - QuadGK.do_quadgk(f, s, n, Tw, abstol, reltol, maxevals, nrm) +_do_quadgk(f, s, n, ::Type{Tw}, atol, rtol, maxevals, nrm) where {Tw} = + QuadGK.do_quadgk(f, s, n, Tw, atol, rtol, maxevals, nrm) end # module diff --git a/test/runtests.jl b/test/runtests.jl index c7b48fd..c98e393 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,29 +1,29 @@ using UnitfulIntegration -using Base.Test +using Test import QuadGK using Unitful import Unitful: m, s, DimensionError # Test physical quantity-valued functions -@test QuadGK.quadgk(x->x*m, 0.0, 1.0, abstol=0.0m)[1] ≈ 0.5m +@test QuadGK.quadgk(x->x*m, 0.0, 1.0, atol=0.0m)[1] ≈ 0.5m # Test integration over an axis with units -@test QuadGK.quadgk(ustrip, 0.0m, 1.0m, abstol=0.0m)[1] ≈ 0.5m +@test QuadGK.quadgk(ustrip, 0.0m, 1.0m, atol=0.0m)[1] ≈ 0.5m # Test integration where the unitful domain is infinite or semi-infinite -@test QuadGK.quadgk(x->exp(-x/(1.0m)), 0.0m, Inf*m, abstol=0.0m)[1] ≈ 1.0m -@test QuadGK.quadgk(x->exp(x/(1.0m)), -Inf*m, 0.0m, abstol=0.0m)[1] ≈ 1.0m +@test QuadGK.quadgk(x->exp(-x/(1.0m)), 0.0m, Inf*m, atol=0.0m)[1] ≈ 1.0m +@test QuadGK.quadgk(x->exp(x/(1.0m)), -Inf*m, 0.0m, atol=0.0m)[1] ≈ 1.0m @test QuadGK.quadgk(x->exp(-abs(x/(1.0m))), - -Inf*m, Inf*m, abstol=0.0m)[1] ≈ 2.0m + -Inf*m, Inf*m, atol=0.0m)[1] ≈ 2.0m # Test mixed case (physical quantity-valued f and unitful domain) -@test QuadGK.quadgk(t->ustrip(t)*m/s, 0.0s, 2.0s, abstol=0.0m)[1] ≈ 2.0m +@test QuadGK.quadgk(t->ustrip(t)*m/s, 0.0s, 2.0s, atol=0.0m)[1] ≈ 2.0m # Test that errors are thrown when dimensionally unsound @test_throws DimensionError QuadGK.quadgk(ustrip, 0.0m, 1.0s)[1] @test_throws DimensionError QuadGK.quadgk(ustrip, 0.0, 1.0m)[1] -# Test that we throw an error when abstol is not specified (at present +# Test that we throw an error when atol is not specified (at present # I believe it is only possible to check when the domain is unitful) @test_throws ErrorException QuadGK.quadgk(ustrip, 0.0m, 1.0m)