Skip to content

Commit

Permalink
add Aqua test & fix all ambiguities and unbound args (#115)
Browse files Browse the repository at this point in the history
* add Aqua test & fix all ambiguities and unbound args

* add badge

* Fix 1.0 ambiguities

* allow converting real Complex number to measurement

* add tests for conversion

* make general case error and AbstractChar work

* add more tests for constructors

* fix tests

* fix tests

* fix round forwarding & add more tests
  • Loading branch information
Roger-luo authored Mar 1, 2022
1 parent c79947c commit d2edc82
Show file tree
Hide file tree
Showing 8 changed files with 72 additions and 9 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.vscode
*.swp
*.jl.cov
*.jl.*.cov
Expand Down
3 changes: 2 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ Requires = "0.5.0, 1"
julia = "1"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
QuadGK = "1fd47b50-473d-5c70-9696-f719f8f3bcdc"
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d"

[targets]
test = ["QuadGK", "SpecialFunctions", "Statistics", "Test", "Unitful"]
test = ["Aqua", "QuadGK", "SpecialFunctions", "Statistics", "Test", "Unitful"]
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Measurements.jl

| **Documentation** | **Build Status** | **Code Coverage** |
|:---------------------------------------:|:-----------------------------------:|:-------------------------------:|
| [![][docs-stable-img]][docs-stable-url] | [![Build Status][gha-img]][gha-url] | [![][coveral-img]][coveral-url] |
| **Documentation** | **Build Status** | **Code Coverage** | **Quality** |
|:---------------------------------------:|:-----------------------------------:|:-------------------------------:|:-----------:|
| [![][docs-stable-img]][docs-stable-url] | [![Build Status][gha-img]][gha-url] | [![][coveral-img]][coveral-url] |[![Aqua QA][aqua-img]](aqua-url)|
| [![][docs-latest-img]][docs-latest-url] | | [![][codecov-img]][codecov-url] |

Introduction
Expand Down Expand Up @@ -219,3 +219,6 @@ is provided in the [`CITATION.bib`](CITATION.bib) file.

[codecov-img]: https://codecov.io/gh/JuliaPhysics/Measurements.jl/branch/master/graph/badge.svg
[codecov-url]: https://codecov.io/gh/JuliaPhysics/Measurements.jl

[aqua-img]: https://raw.githubusercontent.com/JuliaTesting/Aqua.jl/master/badge.svg
[aqua-url]: https://github.com/JuliaTesting/Aqua.jl
14 changes: 12 additions & 2 deletions src/Measurements.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,18 @@ function Measurement(val::V, err::E, tag::UInt64,
return Measurement(T(val), T(err), tag, Derivatives{T}(der))
end
Measurement{T}(x::Measurement{S}) where {T,S} = convert(Measurement{T}, x)
Measurement{T}(x::S) where {T,S} = convert(Measurement{T}, x)
Measurement{T}(x::S) where {T,S<:Rational} = convert(Measurement{T}, x)
Measurement{T}(x::S) where {T,S <: Real} = convert(Measurement{T}, x)

# disambiguities
Measurement{T}(x::S) where {T, S<:Rational} = convert(Measurement{T}, x)
Measurement{T}(x::S) where {T, S<:Complex} = convert(Measurement{T}, x)
Measurement{T}(x::S) where {T, S<:Base.TwicePrecision} = convert(Measurement{T}, x)
Measurement{T}(x::S) where {P, T, S<:Rational{P}} = convert(Measurement{T}, x)
Measurement{T}(x::S) where {T, S <: AbstractChar} = convert(Measurement{T}, x)

function Measurement{T}(::S) where {T, S}
throw(ArgumentError("cannot convert `$S` to `Measurement{$T}`"))
end

# Functions to quickly create an empty Derivatives object.
@generated empty_der1(x::Measurement{T}) where {T<:AbstractFloat} = Derivatives{T}()
Expand Down
4 changes: 4 additions & 0 deletions src/comparisons-tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ Base.:(==)(a::Measurement, b::Measurement) = (a.val==b.val && a.err==b.err)
Base.:(==)(a::Measurement, b::Irrational) = false
Base.:(==)(a::Measurement, b::Rational) = (a.val==b && iszero(a.err))
Base.:(==)(a::Measurement, b::Real) = (a.val==b && iszero(a.err))
Base.:(==)(a::Measurement, b::AbstractIrrational) = (a.val==b && iszero(b.err))
Base.:(==)(a::Irrational, b::Measurement) = false
Base.:(==)(a::Rational, b::Measurement) = (a==b.val && iszero(b.err))
Base.:(==)(a::Real, b::Measurement) = (a==b.val && iszero(b.err))
Base.:(==)(a::AbstractIrrational, b::Measurement) = (a==b.val && iszero(b.err))

# Create a hashing function that matches the same behaviour as `==`: only the
# `val` and `err` fields matter.
Expand All @@ -39,8 +41,10 @@ for cmp in (:<, :<=)
Base.$cmp(a::Measurement, b::Measurement) = ($cmp)(a.val, b.val)
Base.$cmp(a::Measurement, b::Rational) = ($cmp)(a.val, b)
Base.$cmp(a::Measurement, b::Real) = ($cmp)(a.val, b)
Base.$cmp(a::Measurement, b::AbstractIrrational) = ($cmp)(a.val, b)
Base.$cmp(a::Rational, b::Measurement) = ($cmp)(a, b.val)
Base.$cmp(a::Real, b::Measurement) = ($cmp)(a, b.val)
Base.$cmp(a::AbstractIrrational, b::Measurement) = ($cmp)(a, b.val)
end
end

Expand Down
12 changes: 12 additions & 0 deletions src/conversions.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ Base.convert(::Type{Measurement{T}}, a::Rational{<:Integer}) where {T<:AbstractF
measurement(T(a))::Measurement{T}
Base.convert(::Type{Measurement{T}}, a::Real) where {T<:AbstractFloat} =
measurement(T(a))::Measurement{T}
Base.convert(::Type{Measurement{T}}, a::Base.TwicePrecision) where {T<:AbstractFloat} =
measurement(T(a))::Measurement{T}
Base.convert(::Type{Measurement{T}}, a::AbstractChar) where {T<:AbstractFloat} =
measurement(T(a))::Measurement{T}

function Base.convert(::Type{Measurement{T}}, a::Complex) where {T}
if isreal(a)
measurement(T(real(a)))
else
throw(InexactError(:convert, Measurement{T}, a))
end
end

Base.convert(::Type{Measurement{T}}, a::Measurement{T}) where {T<:AbstractFloat} = a
function Base.convert(::Type{Measurement{T}},
Expand Down
17 changes: 15 additions & 2 deletions src/math.jl
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ end
# Get the common type parameter of a collection of Measurement objects. The first two
# methods are for the trivial cases of homogeneous tuples and arrays, the last, inefficient,
# method is for inhomogeneous collections (probably the least common case).
gettype(::Tuple{Vararg{Measurement{T}}}) where {T<:AbstractFloat} = T
gettype(::Tuple{Measurement{T}, Vararg{Measurement{T}}}) where {T<:AbstractFloat} = T
gettype(::AbstractArray{Measurement{T}}) where {T<:AbstractFloat} = T
_eltype(::Measurement{T}) where {T<:AbstractFloat} = T
gettype(collection) = promote_type(_eltype.(collection)...)
Expand Down Expand Up @@ -174,6 +174,7 @@ end
# Addition: +
Base.:+(a::Measurement, b::Measurement) = result(a.val + b.val, (1, 1), (a, b))
Base.:+(a::Real, b::Measurement) = result(a + b.val, 1, b)
Base.:+(a::Bool, b::Measurement) = result(a + b.val, 1, b)
Base.:+(a::Measurement, b::Bool) = result(a.val + b, 1, a)
Base.:+(a::Measurement, b::Real) = result(a.val + b, 1, a)

Expand Down Expand Up @@ -685,9 +686,12 @@ Base.sign(a::Measurement) = result(sign(a.val), 0, a)

Base.copysign(a::Measurement, b::Measurement) = ifelse(signbit(a)!=signbit(b), -a, a)
Base.copysign(a::Measurement, b::Real) = ifelse(signbit(a)!=signbit(b), -a, a)
Base.copysign(a::Measurement, b::Unsigned) = ifelse(signbit(a)!=signbit(b), -a, a)

Base.flipsign(a::Measurement, b::Measurement) = ifelse(signbit(b), -a, a)
Base.flipsign(a::Measurement, b::Real) = ifelse(signbit(b), -a, a)
for T in (Signed, Rational, Float32, Float64, Real)
Base.flipsign(a::Measurement, b::Unsigned) = ifelse(signbit(b), -a, a)
for T in (Signed, Unsigned, Rational, Float32, Float64, Real)
@eval Base.copysign(a::$T, b::Measurement) = copysign(a, b.val)
@eval Base.flipsign(a::$T, b::Measurement) = flipsign(a, b.val)
end
Expand Down Expand Up @@ -734,6 +738,15 @@ Base.round(a::Measurement, r::RoundingMode=RoundNearest; kwargs...) =
measurement(round(value(a), r; kwargs...), round(uncertainty(a); kwargs...))
Base.round(::Type{T}, a::Measurement, r::RoundingMode=RoundNearest) where {T<:Integer} =
round(T, a.val, r)

# disambiguities
Base.round(a::Measurement, r::RoundingMode{:NearestTiesAway}; kwargs...) =
measurement(round(value(a), r; kwargs...), round(uncertainty(a), r; kwargs...))
Base.round(a::Measurement, r::RoundingMode{:NearestTiesUp}; kwargs...) =
measurement(round(value(a), r; kwargs...), round(uncertainty(a), r; kwargs...))
Base.round(::Type{T}, a::Measurement, r::RoundingMode{:ToZero}) where {T<:Integer} =
measurement(round(T, value(a), r), round(uncertainty(a), r))

Base.floor(a::Measurement) = measurement(floor(a.val))
Base.floor(::Type{T}, a::Measurement) where {T<:Integer} = floor(T, a.val)
Base.ceil(a::Measurement) = measurement(ceil(a.val))
Expand Down
21 changes: 20 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Measurements, SpecialFunctions, QuadGK, Calculus
using Test, LinearAlgebra, Statistics, Unitful, Printf
using Test, LinearAlgebra, Statistics, Unitful, Printf, Aqua
Aqua.test_all(Measurements)

import Base: isapprox
import Measurements: value, uncertainty
Expand Down Expand Up @@ -46,6 +47,14 @@ end
@test x != pi != y
end

@testset "constructors" begin
@test Measurement{Float64}(1.0 + 0im) 1.0 ± 0.0
@test Measurement{Float64}(1//2) 0.5 ± 0.0
@test Measurement{Float64}((1:1e-2:2).step) 1e-2±0.0
@test Measurement{Float64}('a') Float64('a') ± 0.0
@test_throws ArgumentError Measurement{Float64}("aaa")
end

@testset "missing values" begin
@test measurement(missing) === missing
@test measurement(missing, .1) === missing
Expand Down Expand Up @@ -104,6 +113,11 @@ end
Measurement{Float64}
@test promote_type(Measurement{BigFloat}, Measurement{Float64}) ==
Measurement{BigFloat}

@test convert(Measurement{Float64}, 1+0im) 1.0±0.0
@test_throws InexactError convert(Measurement{Float64}, 1+1im)
@test convert(Measurement{Float64}, Base.TwicePrecision(1.0, 0.0)) 1.0±0.0
@test convert(Measurement{Float64}, 'a') Float64('a') ± 0.0
end

@testset "Comparisons and Tests" begin
Expand Down Expand Up @@ -136,6 +150,8 @@ end
@test isone(one(Measurement))
@test !isone(1 ± 1)
@test !isone(0 ± 0)
@test 1//2 ± 0.0 == 1//2
@test 1//2 == 1//2 ± 0.0
end

@testset "Hashing and dictionaries" begin
Expand Down Expand Up @@ -562,6 +578,9 @@ end
@test @inferred(rem2pi(a, r)) rem(a, 2pi, r)
@test rem2pi(a, r) a - 2pi * round(a / (2pi), r)
end

@test round(3.141234±0.1, RoundNearestTiesAway) 3.0±0.0
@test round(3.141234±0.1, RoundNearestTiesUp) 3.0±0.0
end

@testset "Machine precision" begin
Expand Down

0 comments on commit d2edc82

Please sign in to comment.