Skip to content

Commit d2edc82

Browse files
author
Rogerluo
authored
add Aqua test & fix all ambiguities and unbound args (#115)
* 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
1 parent c79947c commit d2edc82

File tree

8 files changed

+72
-9
lines changed

8 files changed

+72
-9
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
.vscode
12
*.swp
23
*.jl.cov
34
*.jl.*.cov

Project.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@ Requires = "0.5.0, 1"
1717
julia = "1"
1818

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

2627
[targets]
27-
test = ["QuadGK", "SpecialFunctions", "Statistics", "Test", "Unitful"]
28+
test = ["Aqua", "QuadGK", "SpecialFunctions", "Statistics", "Test", "Unitful"]

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Measurements.jl
22

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

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

220220
[codecov-img]: https://codecov.io/gh/JuliaPhysics/Measurements.jl/branch/master/graph/badge.svg
221221
[codecov-url]: https://codecov.io/gh/JuliaPhysics/Measurements.jl
222+
223+
[aqua-img]: https://raw.githubusercontent.com/JuliaTesting/Aqua.jl/master/badge.svg
224+
[aqua-url]: https://github.com/JuliaTesting/Aqua.jl

src/Measurements.jl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,18 @@ function Measurement(val::V, err::E, tag::UInt64,
6060
return Measurement(T(val), T(err), tag, Derivatives{T}(der))
6161
end
6262
Measurement{T}(x::Measurement{S}) where {T,S} = convert(Measurement{T}, x)
63-
Measurement{T}(x::S) where {T,S} = convert(Measurement{T}, x)
64-
Measurement{T}(x::S) where {T,S<:Rational} = convert(Measurement{T}, x)
63+
Measurement{T}(x::S) where {T,S <: Real} = convert(Measurement{T}, x)
64+
65+
# disambiguities
66+
Measurement{T}(x::S) where {T, S<:Rational} = convert(Measurement{T}, x)
67+
Measurement{T}(x::S) where {T, S<:Complex} = convert(Measurement{T}, x)
68+
Measurement{T}(x::S) where {T, S<:Base.TwicePrecision} = convert(Measurement{T}, x)
69+
Measurement{T}(x::S) where {P, T, S<:Rational{P}} = convert(Measurement{T}, x)
70+
Measurement{T}(x::S) where {T, S <: AbstractChar} = convert(Measurement{T}, x)
71+
72+
function Measurement{T}(::S) where {T, S}
73+
throw(ArgumentError("cannot convert `$S` to `Measurement{$T}`"))
74+
end
6575

6676
# Functions to quickly create an empty Derivatives object.
6777
@generated empty_der1(x::Measurement{T}) where {T<:AbstractFloat} = Derivatives{T}()

src/comparisons-tests.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,11 @@ Base.:(==)(a::Measurement, b::Measurement) = (a.val==b.val && a.err==b.err)
2525
Base.:(==)(a::Measurement, b::Irrational) = false
2626
Base.:(==)(a::Measurement, b::Rational) = (a.val==b && iszero(a.err))
2727
Base.:(==)(a::Measurement, b::Real) = (a.val==b && iszero(a.err))
28+
Base.:(==)(a::Measurement, b::AbstractIrrational) = (a.val==b && iszero(b.err))
2829
Base.:(==)(a::Irrational, b::Measurement) = false
2930
Base.:(==)(a::Rational, b::Measurement) = (a==b.val && iszero(b.err))
3031
Base.:(==)(a::Real, b::Measurement) = (a==b.val && iszero(b.err))
32+
Base.:(==)(a::AbstractIrrational, b::Measurement) = (a==b.val && iszero(b.err))
3133

3234
# Create a hashing function that matches the same behaviour as `==`: only the
3335
# `val` and `err` fields matter.
@@ -39,8 +41,10 @@ for cmp in (:<, :<=)
3941
Base.$cmp(a::Measurement, b::Measurement) = ($cmp)(a.val, b.val)
4042
Base.$cmp(a::Measurement, b::Rational) = ($cmp)(a.val, b)
4143
Base.$cmp(a::Measurement, b::Real) = ($cmp)(a.val, b)
44+
Base.$cmp(a::Measurement, b::AbstractIrrational) = ($cmp)(a.val, b)
4245
Base.$cmp(a::Rational, b::Measurement) = ($cmp)(a, b.val)
4346
Base.$cmp(a::Real, b::Measurement) = ($cmp)(a, b.val)
47+
Base.$cmp(a::AbstractIrrational, b::Measurement) = ($cmp)(a, b.val)
4448
end
4549
end
4650

src/conversions.jl

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@ Base.convert(::Type{Measurement{T}}, a::Rational{<:Integer}) where {T<:AbstractF
2222
measurement(T(a))::Measurement{T}
2323
Base.convert(::Type{Measurement{T}}, a::Real) where {T<:AbstractFloat} =
2424
measurement(T(a))::Measurement{T}
25+
Base.convert(::Type{Measurement{T}}, a::Base.TwicePrecision) where {T<:AbstractFloat} =
26+
measurement(T(a))::Measurement{T}
27+
Base.convert(::Type{Measurement{T}}, a::AbstractChar) where {T<:AbstractFloat} =
28+
measurement(T(a))::Measurement{T}
29+
30+
function Base.convert(::Type{Measurement{T}}, a::Complex) where {T}
31+
if isreal(a)
32+
measurement(T(real(a)))
33+
else
34+
throw(InexactError(:convert, Measurement{T}, a))
35+
end
36+
end
2537

2638
Base.convert(::Type{Measurement{T}}, a::Measurement{T}) where {T<:AbstractFloat} = a
2739
function Base.convert(::Type{Measurement{T}},

src/math.jl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ end
5656
# Get the common type parameter of a collection of Measurement objects. The first two
5757
# methods are for the trivial cases of homogeneous tuples and arrays, the last, inefficient,
5858
# method is for inhomogeneous collections (probably the least common case).
59-
gettype(::Tuple{Vararg{Measurement{T}}}) where {T<:AbstractFloat} = T
59+
gettype(::Tuple{Measurement{T}, Vararg{Measurement{T}}}) where {T<:AbstractFloat} = T
6060
gettype(::AbstractArray{Measurement{T}}) where {T<:AbstractFloat} = T
6161
_eltype(::Measurement{T}) where {T<:AbstractFloat} = T
6262
gettype(collection) = promote_type(_eltype.(collection)...)
@@ -174,6 +174,7 @@ end
174174
# Addition: +
175175
Base.:+(a::Measurement, b::Measurement) = result(a.val + b.val, (1, 1), (a, b))
176176
Base.:+(a::Real, b::Measurement) = result(a + b.val, 1, b)
177+
Base.:+(a::Bool, b::Measurement) = result(a + b.val, 1, b)
177178
Base.:+(a::Measurement, b::Bool) = result(a.val + b, 1, a)
178179
Base.:+(a::Measurement, b::Real) = result(a.val + b, 1, a)
179180

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

686687
Base.copysign(a::Measurement, b::Measurement) = ifelse(signbit(a)!=signbit(b), -a, a)
687688
Base.copysign(a::Measurement, b::Real) = ifelse(signbit(a)!=signbit(b), -a, a)
689+
Base.copysign(a::Measurement, b::Unsigned) = ifelse(signbit(a)!=signbit(b), -a, a)
690+
688691
Base.flipsign(a::Measurement, b::Measurement) = ifelse(signbit(b), -a, a)
689692
Base.flipsign(a::Measurement, b::Real) = ifelse(signbit(b), -a, a)
690-
for T in (Signed, Rational, Float32, Float64, Real)
693+
Base.flipsign(a::Measurement, b::Unsigned) = ifelse(signbit(b), -a, a)
694+
for T in (Signed, Unsigned, Rational, Float32, Float64, Real)
691695
@eval Base.copysign(a::$T, b::Measurement) = copysign(a, b.val)
692696
@eval Base.flipsign(a::$T, b::Measurement) = flipsign(a, b.val)
693697
end
@@ -734,6 +738,15 @@ Base.round(a::Measurement, r::RoundingMode=RoundNearest; kwargs...) =
734738
measurement(round(value(a), r; kwargs...), round(uncertainty(a); kwargs...))
735739
Base.round(::Type{T}, a::Measurement, r::RoundingMode=RoundNearest) where {T<:Integer} =
736740
round(T, a.val, r)
741+
742+
# disambiguities
743+
Base.round(a::Measurement, r::RoundingMode{:NearestTiesAway}; kwargs...) =
744+
measurement(round(value(a), r; kwargs...), round(uncertainty(a), r; kwargs...))
745+
Base.round(a::Measurement, r::RoundingMode{:NearestTiesUp}; kwargs...) =
746+
measurement(round(value(a), r; kwargs...), round(uncertainty(a), r; kwargs...))
747+
Base.round(::Type{T}, a::Measurement, r::RoundingMode{:ToZero}) where {T<:Integer} =
748+
measurement(round(T, value(a), r), round(uncertainty(a), r))
749+
737750
Base.floor(a::Measurement) = measurement(floor(a.val))
738751
Base.floor(::Type{T}, a::Measurement) where {T<:Integer} = floor(T, a.val)
739752
Base.ceil(a::Measurement) = measurement(ceil(a.val))

test/runtests.jl

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Measurements, SpecialFunctions, QuadGK, Calculus
2-
using Test, LinearAlgebra, Statistics, Unitful, Printf
2+
using Test, LinearAlgebra, Statistics, Unitful, Printf, Aqua
3+
Aqua.test_all(Measurements)
34

45
import Base: isapprox
56
import Measurements: value, uncertainty
@@ -46,6 +47,14 @@ end
4647
@test x != pi != y
4748
end
4849

50+
@testset "constructors" begin
51+
@test Measurement{Float64}(1.0 + 0im) 1.0 ± 0.0
52+
@test Measurement{Float64}(1//2) 0.5 ± 0.0
53+
@test Measurement{Float64}((1:1e-2:2).step) 1e-2±0.0
54+
@test Measurement{Float64}('a') Float64('a') ± 0.0
55+
@test_throws ArgumentError Measurement{Float64}("aaa")
56+
end
57+
4958
@testset "missing values" begin
5059
@test measurement(missing) === missing
5160
@test measurement(missing, .1) === missing
@@ -104,6 +113,11 @@ end
104113
Measurement{Float64}
105114
@test promote_type(Measurement{BigFloat}, Measurement{Float64}) ==
106115
Measurement{BigFloat}
116+
117+
@test convert(Measurement{Float64}, 1+0im) 1.0±0.0
118+
@test_throws InexactError convert(Measurement{Float64}, 1+1im)
119+
@test convert(Measurement{Float64}, Base.TwicePrecision(1.0, 0.0)) 1.0±0.0
120+
@test convert(Measurement{Float64}, 'a') Float64('a') ± 0.0
107121
end
108122

109123
@testset "Comparisons and Tests" begin
@@ -136,6 +150,8 @@ end
136150
@test isone(one(Measurement))
137151
@test !isone(1 ± 1)
138152
@test !isone(0 ± 0)
153+
@test 1//2 ± 0.0 == 1//2
154+
@test 1//2 == 1//2 ± 0.0
139155
end
140156

141157
@testset "Hashing and dictionaries" begin
@@ -562,6 +578,9 @@ end
562578
@test @inferred(rem2pi(a, r)) rem(a, 2pi, r)
563579
@test rem2pi(a, r) a - 2pi * round(a / (2pi), r)
564580
end
581+
582+
@test round(3.141234±0.1, RoundNearestTiesAway) 3.0±0.0
583+
@test round(3.141234±0.1, RoundNearestTiesUp) 3.0±0.0
565584
end
566585

567586
@testset "Machine precision" begin

0 commit comments

Comments
 (0)