From 3ec4b020f43dc16ba2b368c174db56040f0701cd Mon Sep 17 00:00:00 2001 From: Dilum Aluthge Date: Mon, 31 May 2021 17:10:12 -0400 Subject: [PATCH 01/34] Use the `:fancy_exponent` IO context property to override the behavior of fancy exponents (#446) --- Project.toml | 2 +- docs/src/display.md | 3 ++- src/display.jl | 32 +++++++++++++++++++++++--------- test/runtests.jl | 4 ++++ 4 files changed, 30 insertions(+), 11 deletions(-) diff --git a/Project.toml b/Project.toml index cfb4ee66..e8be0cf1 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Unitful" uuid = "1986cc42-f94f-5a68-af5c-568840ba703d" -version = "1.7.0" +version = "1.8.0" [deps] ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9" diff --git a/docs/src/display.md b/docs/src/display.md index 57d7c0c9..a1f016d8 100644 --- a/docs/src/display.md +++ b/docs/src/display.md @@ -3,7 +3,8 @@ By default, exponents on units or dimensions are indicated using Unicode superscripts on macOS and without superscripts on other operating systems. You can set the environment variable `UNITFUL_FANCY_EXPONENTS` to either `true` or `false` to force using or not using -the exponents. +the exponents. You can also set the `:fancy_exponent` IO context property to either `true` +or `false` to force using or not using the exponents. ```@docs Unitful.BracketStyle diff --git a/src/display.jl b/src/display.jl index e51ae640..249ad93f 100644 --- a/src/display.jl +++ b/src/display.jl @@ -183,7 +183,7 @@ formatted by [`Unitful.superscript`](@ref). function showrep(io::IO, x::Unit) print(io, prefix(x)) print(io, abbr(x)) - print(io, (power(x) == 1//1 ? "" : superscript(power(x)))) + print(io, (power(x) == 1//1 ? "" : superscript(power(x); io=io))) nothing end @@ -194,18 +194,32 @@ Show the dimension, appending any exponent as formatted by """ function showrep(io::IO, x::Dimension) print(io, abbr(x)) - print(io, (power(x) == 1//1 ? "" : superscript(power(x)))) + print(io, (power(x) == 1//1 ? "" : superscript(power(x); io=io))) end """ - superscript(i::Rational) -Prints exponents. + superscript(i::Rational; io::Union{IO, Nothing} = nothing) +Returns exponents as a string. + +This function returns the value as a string. It does not print to `io`. `io` is +only used for IO context values. If `io` contains the `:fancy_exponent` +property and the value is a `Bool`, this value will override the behavior of +fancy exponents. """ -function superscript(i::Rational) - v = get(ENV, "UNITFUL_FANCY_EXPONENTS", Sys.isapple() ? "true" : "false") - t = tryparse(Bool, lowercase(v)) - k = (t === nothing) ? false : t - if k +function superscript(i::Rational; io::Union{IO, Nothing} = nothing) + if io === nothing + iocontext_value = nothing + else + iocontext_value = get(io, :fancy_exponent, nothing) + end + if iocontext_value isa Bool + fancy_exponent = iocontext_value + else + v = get(ENV, "UNITFUL_FANCY_EXPONENTS", Sys.isapple() ? "true" : "false") + t = tryparse(Bool, lowercase(v)) + fancy_exponent = (t === nothing) ? false : t + end + if fancy_exponent return i.den == 1 ? superscript(i.num) : string(superscript(i.num), '\u141F', superscript(i.den)) else i.den == 1 ? "^" * string(i.num) : "^" * replace(string(i), "//" => "/") diff --git a/test/runtests.jl b/test/runtests.jl index aec5a66f..c0803185 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1299,6 +1299,10 @@ end @test string(dimension(1u"m/s")) == "𝐋 𝐓^-1" @test string(NoDims) == "NoDims" end + @testset ":fancy_exponent IOContext property" begin + @test sprint(io -> show(IOContext(io, :fancy_exponent => true), u"m/s")) == "m s⁻¹" + @test sprint(io -> show(IOContext(io, :fancy_exponent => false), u"m/s")) == "m s^-1" + end end struct Foo <: Number end From 9b7723517cdb1ce2091d8b5f865b086a2878bd1e Mon Sep 17 00:00:00 2001 From: KronosTheLate <61620837+KronosTheLate@users.noreply.github.com> Date: Fri, 4 Jun 2021 17:45:58 +0200 Subject: [PATCH 02/34] Showing how to manually cancel units (#451) * Showing how to manually cancel units * Update conversion.md added the statement that `m/m` is automatically canceled * Remove contrived examples, fixed typo * More clear example This commit changes the expression from which units are shortened to 1km/2.5m, to make clear that the denomenator is part of the expression. It also fixed a typo (`NoUnit -> NoUnits`) * Shorten example It seems like some of the examples did not sit well with some of the contributers. I see their point completely, and in this PR I have made the example minimal and clearer. #LessIsMore * Added @ref, and more interesting example I added a reference to the NoUnits type (hopefully - I don't know how to chech that the reference actually works as expected). I also changed the example to the more complicated one, to make it less trivial and hopefully better showcase the usefullness. * Update docs/src/conversion.md Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * As per the latest review, which got outdated Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> --- docs/src/conversion.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/src/conversion.md b/docs/src/conversion.md index 84e59dc4..2c2e56c9 100644 --- a/docs/src/conversion.md +++ b/docs/src/conversion.md @@ -299,3 +299,11 @@ For multiplication and division, note that powers-of-ten prefixes are significan in unit cancellation. For instance, `mV/V` is not simplified, although `V/V` is. Also, `N*m/J` is not simplified: there is currently no logic to decide whether or not units on a dimensionless quantity seem "intentional" or not. +It is however possible to cancel units manually, by passing the dimensionless +quantity to the [`NoUnits`](@ref) constructor. This takes into account different SI-prefixes: +```jldoctest +julia> using Unitful + +julia> julia> 1u"kN*m"/4u"J" |> NoUnits +250.0 +``` From 1e78e6b036144d70039b536de747dc1e83355997 Mon Sep 17 00:00:00 2001 From: Jeff Fessler Date: Fri, 4 Jun 2021 11:46:20 -0400 Subject: [PATCH 03/34] fix example `isa(1m, Length)` (#454) `isa(1m, Length)` did not work after `using Unitful` but the corrected version works. --- docs/src/types.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/types.md b/docs/src/types.md index 1be64886..c3d05f20 100644 --- a/docs/src/types.md +++ b/docs/src/types.md @@ -31,7 +31,7 @@ Finally, we define physical quantity types as [`Quantity{T<:Number, D, U}`](@ref quantity, staged functions can be used to offload as much of the unit computation to compile-time as is possible. By also having the dimensions explicitly in the type signature, dispatch can be done on dimensions: -`isa(1m, Length) == true`. This works because `Length` is a type alias for +`isa(1u"m", Unitful.Length) == true`. This works because `Length` is a type alias for some subset of `Unitful.Quantity` subtypes. ## API From 2f4cfa29b3c7455693a27c1457757fbc73707855 Mon Sep 17 00:00:00 2001 From: Jeff Fessler Date: Thu, 17 Jun 2021 07:45:56 -0400 Subject: [PATCH 04/34] Elaborate on UnitfulRecipes in readme (#456) If I had known this would support plot axes with units, I would not have started down the road to #455. Maybe this elaboration will help someone else. [skip ci] --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d2fc52c6..670d8079 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ mathematical operations and collections that are found in Julia base. ### Feature additions -- [UnitfulRecipes.jl](https://github.com/jw3126/UnitfulRecipes.jl): Adds automatic labels for [Plots.jl](https://github.com/JuliaPlots/Plots.jl). +- [UnitfulRecipes.jl](https://github.com/jw3126/UnitfulRecipes.jl): Adds automatic labels for [Plots.jl](https://github.com/JuliaPlots/Plots.jl) and supports plot axes with units. - [UnitfulIntegration.jl](https://github.com/PainterQubits/UnitfulIntegration.jl): Enables use of Unitful quantities with [QuadGK.jl](https://github.com/JuliaMath/QuadGK.jl). PRs for other integration packages are welcome. - [UnitfulEquivalences.jl](https://github.com/sostock/UnitfulEquivalences.jl): Enables conversion between equivalent quantities of different dimensions, e.g. between energy and wavelength of a photon. - [UnitfulLatexify.jl](https://github.com/gustaphe/UnitfulLatexify.jl): Pretty print units and quantities in LaTeX format. From bab37352344d8c5fb063c6088d29c2ceeeafd102 Mon Sep 17 00:00:00 2001 From: Ricardo Rosa Date: Sat, 10 Jul 2021 19:48:22 -0300 Subject: [PATCH 05/34] Add link to UnitfulBuckinghamPi in README (#442) I just registered the [UnitfulBuckinghamPi.jl](https://github.com/rmsrosa/UnitfulBuckinghamPi.jl) package. It solves for the adimensional groups in a list of Unitful parameters (quantities, units, dimensions, or combinations thereof). This PR adds a link to the package in the README. [skip ci] --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 670d8079..db2c15a4 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ mathematical operations and collections that are found in Julia base. - [UnitfulIntegration.jl](https://github.com/PainterQubits/UnitfulIntegration.jl): Enables use of Unitful quantities with [QuadGK.jl](https://github.com/JuliaMath/QuadGK.jl). PRs for other integration packages are welcome. - [UnitfulEquivalences.jl](https://github.com/sostock/UnitfulEquivalences.jl): Enables conversion between equivalent quantities of different dimensions, e.g. between energy and wavelength of a photon. - [UnitfulLatexify.jl](https://github.com/gustaphe/UnitfulLatexify.jl): Pretty print units and quantities in LaTeX format. +- [UnitfulBuckinghamPi.jl](https://github.com/rmsrosa/UnitfulBuckinghamPi.jl): Solves for the adimensional Pi groups in a list of Unitful parameters, according to the Buckingham-Pi Theorem. ## Related packages From 8d0db2aded6eaf892262aea7d9a78b028f1f69f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Sun, 11 Jul 2021 00:32:25 +0100 Subject: [PATCH 06/34] Fix doctests (#464) --- docs/Project.toml | 2 +- docs/src/conversion.md | 10 +++++----- docs/src/highlights.md | 9 +++------ docs/src/newunits.md | 2 +- src/user.jl | 2 +- src/utils.jl | 10 +++++----- 6 files changed, 16 insertions(+), 19 deletions(-) diff --git a/docs/Project.toml b/docs/Project.toml index 6128171d..ff62cc79 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -5,5 +5,5 @@ Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316" Markdown = "d6f4376e-aef5-505a-96c1-9c027394607a" [compat] -Documenter = "0.24" +Documenter = "0.27" Latexify = "0.13" diff --git a/docs/src/conversion.md b/docs/src/conversion.md index 2c2e56c9..44356109 100644 --- a/docs/src/conversion.md +++ b/docs/src/conversion.md @@ -136,17 +136,17 @@ the following three cases: ```jldoctest julia> [1.0u"m", 2.0u"m"] -2-element Array{Quantity{Float64,𝐋,Unitful.FreeUnits{(m,),𝐋,nothing}},1}: +2-element Vector{Quantity{Float64, 𝐋, Unitful.FreeUnits{(m,), 𝐋, nothing}}}: 1.0 m 2.0 m julia> [1.0u"m", 2.0u"cm"] -2-element Array{Quantity{Float64,𝐋,Unitful.FreeUnits{(m,),𝐋,nothing}},1}: +2-element Vector{Quantity{Float64, 𝐋, Unitful.FreeUnits{(m,), 𝐋, nothing}}}: 1.0 m 0.02 m julia> [1.0u"m", 2.0] -2-element Array{Quantity{Float64,D,U} where U where D,1}: +2-element Vector{Quantity{Float64, D, U} where {D, U}}: 1.0 m 2.0 ``` @@ -166,7 +166,7 @@ julia> f([1.0u"m", 2.0u"cm"]) 1.02 m julia> f([1.0u"g", 2.0u"cm"]) -ERROR: MethodError: no method matching f(::Array{Quantity{Float64,D,U} where U where D,1}) +ERROR: MethodError: no method matching f(::Vector{Quantity{Float64, D, U} where {D, U}}) [...] ``` @@ -304,6 +304,6 @@ quantity to the [`NoUnits`](@ref) constructor. This takes into account different ```jldoctest julia> using Unitful -julia> julia> 1u"kN*m"/4u"J" |> NoUnits +julia> 1u"kN*m"/4u"J" |> NoUnits 250.0 ``` diff --git a/docs/src/highlights.md b/docs/src/highlights.md index fb02d52b..c8a94908 100644 --- a/docs/src/highlights.md +++ b/docs/src/highlights.md @@ -72,12 +72,9 @@ in toy calculations for where some conventions yield matrices with mixed dimensions: ```jldoctest -julia> Diagonal([-1.0u"c^2", 1.0, 1.0, 1.0]) -4Γ—4 Diagonal{Unitful.Quantity{Float64,D,U}}: - -1.0 c^2 β‹… β‹… β‹… - β‹… 1.0 β‹… β‹… - β‹… β‹… 1.0 β‹… - β‹… β‹… β‹… 1.0 +julia> using LinearAlgebra + +julia> Diagonal([-1.0u"c^2", 1.0, 1.0, 1.0]); ``` ## Logarithmic units diff --git a/docs/src/newunits.md b/docs/src/newunits.md index 7d1b528c..f2d4593f 100644 --- a/docs/src/newunits.md +++ b/docs/src/newunits.md @@ -27,7 +27,7 @@ MyUnits julia> using Unitful julia> u"myMeter" -ERROR: LoadError: ArgumentError: Symbol myMeter could not be found in unit modules Module[Unitful] +ERROR: LoadError: [...] julia> Unitful.register(MyUnits); diff --git a/src/user.jl b/src/user.jl index f68617bf..50a62783 100644 --- a/src/user.jl +++ b/src/user.jl @@ -494,7 +494,7 @@ julia> u"m,kg,s" (m, kg, s) julia> typeof(1.0u"m/s") -Quantity{Float64,𝐋 𝐓^-1,Unitful.FreeUnits{(m, s^-1),𝐋 𝐓^-1,nothing}} +Quantity{Float64, 𝐋 𝐓^-1, Unitful.FreeUnits{(m, s^-1), 𝐋 𝐓^-1, nothing}} julia> u"Δ§" 1.0545718176461565e-34 J s diff --git a/src/utils.jl b/src/utils.jl index 53f12b95..0f343342 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -60,17 +60,17 @@ the result to PyPlot, for example. ```jldoctest julia> a = [1u"m", 2u"m"] -2-element Array{Quantity{Int64,𝐋,Unitful.FreeUnits{(m,),𝐋,nothing}},1}: +2-element Vector{Quantity{Int64, 𝐋, Unitful.FreeUnits{(m,), 𝐋, nothing}}}: 1 m 2 m julia> b = ustrip(a) -2-element reinterpret(Int64, ::Array{Quantity{Int64,𝐋,Unitful.FreeUnits{(m,),𝐋,nothing}},1}): +2-element reinterpret(Int64, ::Vector{Quantity{Int64, 𝐋, Unitful.FreeUnits{(m,), 𝐋, nothing}}}): 1 2 julia> a[1] = 3u"m"; b -2-element reinterpret(Int64, ::Array{Quantity{Int64,𝐋,Unitful.FreeUnits{(m,),𝐋,nothing}},1}): +2-element reinterpret(Int64, ::Vector{Quantity{Int64, 𝐋, Unitful.FreeUnits{(m,), 𝐋, nothing}}}): 3 2 ``` @@ -120,10 +120,10 @@ Examples: ```jldoctest julia> typeof(unit(1.0)) -Unitful.FreeUnits{(),NoDims,nothing} +Unitful.FreeUnits{(), NoDims, nothing} julia> typeof(unit(Float64)) -Unitful.FreeUnits{(),NoDims,nothing} +Unitful.FreeUnits{(), NoDims, nothing} julia> unit(1.0) == NoUnits true From 492c4756e2b2c0668f7693bc786b121ba318b085 Mon Sep 17 00:00:00 2001 From: Jeff Fessler Date: Fri, 16 Jul 2021 16:44:39 -0400 Subject: [PATCH 07/34] deg2rad and rad2deg with "units" (#459) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deg2rad and rad2deg * v1.9 * Update src/pkgdefaults.jl Co-authored-by: MosΓ¨ Giordano Co-authored-by: MosΓ¨ Giordano --- Project.toml | 2 +- src/pkgdefaults.jl | 5 +++++ test/runtests.jl | 4 ++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index e8be0cf1..dbf1c033 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Unitful" uuid = "1986cc42-f94f-5a68-af5c-568840ba703d" -version = "1.8.0" +version = "1.9.0" [deps] ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9" diff --git a/src/pkgdefaults.jl b/src/pkgdefaults.jl index 5d30aa57..56a1dbfd 100644 --- a/src/pkgdefaults.jl +++ b/src/pkgdefaults.jl @@ -73,6 +73,11 @@ for (_x,_y) in ((:sin,:sind), (:cos,:cosd), (:tan,:tand), @eval ($_y)(x::Quantity{T, NoDims, typeof(Β°)}) where {T} = ($_y)(ustrip(x)) end +# conversion between degrees and radians +import Base: deg2rad, rad2deg +deg2rad(d::Quantity{T, NoDims, typeof(Β°)}) where {T} = deg2rad(ustrip(Β°, d))u"rad" +rad2deg(r::Quantity{T, NoDims, typeof(rad)}) where {T} = rad2deg(ustrip(rad, r))u"Β°" + # SI and related units @unit Hz "Hz" Hertz 1/s true @unit N "N" Newton 1kg*m/s^2 true diff --git a/test/runtests.jl b/test/runtests.jl index c0803185..3e96550c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -193,6 +193,10 @@ end @test 1u"rps" == 2Ο€/s @test 1u"rpm" == 360Β°/minute @test 1u"rpm" == 2Ο€/minute + + # Issue 458: + @test deg2rad(360Β°) β‰ˆ 2Ο€ * rad + @test rad2deg(2Ο€ * rad) β‰ˆ 360Β° end end end From b3f0f9e3645206fa4a32f5ca040431852e6ba008 Mon Sep 17 00:00:00 2001 From: Mo8it <76752051+Mo8it@users.noreply.github.com> Date: Tue, 14 Sep 2021 19:23:13 +0200 Subject: [PATCH 08/34] Update README.md Mentioned NaturallyUnitful.jl --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index db2c15a4..1d4aa656 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,7 @@ mathematical operations and collections that are found in Julia base. - [UnitfulEquivalences.jl](https://github.com/sostock/UnitfulEquivalences.jl): Enables conversion between equivalent quantities of different dimensions, e.g. between energy and wavelength of a photon. - [UnitfulLatexify.jl](https://github.com/gustaphe/UnitfulLatexify.jl): Pretty print units and quantities in LaTeX format. - [UnitfulBuckinghamPi.jl](https://github.com/rmsrosa/UnitfulBuckinghamPi.jl): Solves for the adimensional Pi groups in a list of Unitful parameters, according to the Buckingham-Pi Theorem. +- [NaturallyUnitful.jl](https://github.com/MasonProtter/NaturallyUnitful.jl): Convert to and from natural units in physics. ## Related packages From 877bc5185a7a81cab147cd66664348aed98fad8d Mon Sep 17 00:00:00 2001 From: Mo8it <76752051+Mo8it@users.noreply.github.com> Date: Wed, 13 Oct 2021 17:49:28 +0000 Subject: [PATCH 09/34] Update .gitignore (#482) * Update .gitignore * Update .gitignore Removed binary stuff [skip ci] --- .gitignore | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index bbf2a6de..1cf5616e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,18 @@ -Manifest.toml +# Files generated by invoking Julia with --code-coverage *.jl.cov *.jl.*.cov + +# Files generated by invoking Julia with --track-allocation *.jl.mem -deps/ + +# Build artifacts for creating documentation generated by the Documenter package docs/build/ -docs/Manifest.toml +docs/site/ + +# File generated by Pkg, the package manager, based on a corresponding Project.toml +# It records a fixed state of all packages used by the project. As such, it should not be +# committed for packages, but should be committed for applications that require a static +# environment. +Manifest.toml + *~ From b471e0db3d4076c1036b13e15ffc2949ff30ad8f Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Wed, 13 Oct 2021 20:22:58 +0200 Subject: [PATCH 10/34] Use aggressive constprop for `^(::AbstractQuantity, ::Rational)` (#487) --- src/quantities.jl | 6 +++++- test/runtests.jl | 10 ++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/quantities.jl b/src/quantities.jl index ecda9443..a25863d4 100644 --- a/src/quantities.jl +++ b/src/quantities.jl @@ -470,7 +470,11 @@ Base.literal_pow(::typeof(^), x::AbstractQuantity, ::Val{v}) where {v} = # All of these are needed for ambiguity resolution ^(x::AbstractQuantity, y::Integer) = Quantity((x.val)^y, unit(x)^y) -^(x::AbstractQuantity, y::Rational) = Quantity((x.val)^y, unit(x)^y) +@static if VERSION β‰₯ v"1.8.0-DEV.501" + Base.@constprop(:aggressive, ^(x::AbstractQuantity, y::Rational) = Quantity((x.val)^y, unit(x)^y)) +else + ^(x::AbstractQuantity, y::Rational) = Quantity((x.val)^y, unit(x)^y) +end ^(x::AbstractQuantity, y::Real) = Quantity((x.val)^y, unit(x)^y) Base.rand(r::Random.AbstractRNG, ::Random.SamplerType{<:AbstractQuantity{T,D,U}}) where {T,D,U} = diff --git a/test/runtests.jl b/test/runtests.jl index 3e96550c..e044a2e3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -632,15 +632,17 @@ end @test (8m)^(1//3) === 2.0*m^(1//3) @test @inferred(cis(90Β°)) β‰ˆ im - # Test inferrability of integer literal powers + # Test inferrability of literal powers _pow_m3(x) = x^-3 _pow_0(x) = x^0 _pow_3(x) = x^3 _pow_2_3(x) = x^(2//3) - @test_throws ErrorException @inferred(_pow_2_3(m)) - @test_throws ErrorException @inferred(_pow_2_3(𝐋)) - @test_throws ErrorException @inferred(_pow_2_3(1.0m)) + @static if VERSION β‰₯ v"1.8.0-DEV.501" + @test @inferred(_pow_2_3(m)) == m^(2//3) + @test @inferred(_pow_2_3(𝐋)) == 𝐋^(2//3) + @test @inferred(_pow_2_3(1.0m)) == 1.0m^(2//3) + end @test @inferred(_pow_m3(m)) == m^-3 @test @inferred(_pow_0(m)) == NoUnits From d67368ad4fef4a31d4541ae78d9257d132e00b4a Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Wed, 13 Oct 2021 20:23:14 +0200 Subject: [PATCH 11/34] Calculate correct `eltype` when multiplying `StepRangeLen` by `Units`. (#485) * Prevent promotion of StepRangeLen eltype when multiplying by unit * Release 1.9.1 --- Project.toml | 2 +- src/range.jl | 3 ++- test/runtests.jl | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Project.toml b/Project.toml index dbf1c033..eeccec02 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Unitful" uuid = "1986cc42-f94f-5a68-af5c-568840ba703d" -version = "1.9.0" +version = "1.9.1" [deps] ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9" diff --git a/src/range.jl b/src/range.jl index ff0d89fc..a964d165 100644 --- a/src/range.jl +++ b/src/range.jl @@ -88,7 +88,8 @@ end # No need to confuse things by changing the type once units are on there, # if we can help it. -*(r::StepRangeLen, y::Units) = StepRangeLen(r.ref*y, r.step*y, length(r), r.offset) +*(r::StepRangeLen, y::Units) = + StepRangeLen{typeof(zero(eltype(r))*y)}(r.ref*y, r.step*y, length(r), r.offset) *(r::LinRange, y::Units) = LinRange(r.start*y, r.stop*y, length(r)) *(r::StepRange, y::Units) = StepRange(r.start*y, r.step*y, r.stop*y) function /(x::Base.TwicePrecision, v::Quantity) diff --git a/test/runtests.jl b/test/runtests.jl index e044a2e3..6c0a8c54 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1156,6 +1156,7 @@ end @test r[3] === 0.3s @test *(1:5, mm, s^-1) === 1mm*s^-1:1mm*s^-1:5mm*s^-1 @test *(1:5, mm, s^-1, mol^-1) === 1mm*s^-1*mol^-1:1mm*s^-1*mol^-1:5mm*s^-1*mol^-1 + @test @inferred((0:2) * 3f0m) === StepRangeLen{typeof(0f0m)}(0.0m, 3.0m, 3) # issue #477 end end @testset "> Arrays" begin From a5298618013554b7018a112819aff0fb530acd1c Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Wed, 20 Oct 2021 15:08:57 +0200 Subject: [PATCH 12/34] Fix multiplication of range and quantity (#489) --- src/range.jl | 13 +++++++++++++ test/runtests.jl | 2 ++ 2 files changed, 15 insertions(+) diff --git a/src/range.jl b/src/range.jl index a964d165..fb864cc1 100644 --- a/src/range.jl +++ b/src/range.jl @@ -2,6 +2,7 @@ const colon = Base.:(:) import Base: ArithmeticRounds import Base: OrderStyle, Ordered, ArithmeticStyle, ArithmeticWraps +import Base.Broadcast: DefaultArrayStyle, broadcasted *(y::Units, r::AbstractRange) = *(r,y) *(r::AbstractRange, y::Units, z::Units...) = *(r, *(y,z...)) @@ -95,3 +96,15 @@ end function /(x::Base.TwicePrecision, v::Quantity) x / Base.TwicePrecision(oftype(ustrip(x.hi)/ustrip(v)*unit(v), v)) end + +# These can be removed (I think) if `range_start_step_length()` returns a `StepRangeLen` for +# non-floats, cf. https://github.com/JuliaLang/julia/issues/40672 +broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::AbstractRange, x::AbstractQuantity) = + broadcasted(DefaultArrayStyle{1}(), *, r, ustrip(x)) * unit(x) +broadcasted(::DefaultArrayStyle{1}, ::typeof(*), x::AbstractQuantity, r::AbstractRange) = + broadcasted(DefaultArrayStyle{1}(), *, ustrip(x), r) * unit(x) +# for ambiguity resolution +broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::StepRangeLen{T}, x::AbstractQuantity) where T = + broadcasted(DefaultArrayStyle{1}(), *, r, ustrip(x)) * unit(x) +broadcasted(::DefaultArrayStyle{1}, ::typeof(*), x::AbstractQuantity, r::StepRangeLen{T}) where T = + broadcasted(DefaultArrayStyle{1}(), *, ustrip(x), r) * unit(x) diff --git a/test/runtests.jl b/test/runtests.jl index 6c0a8c54..d2012bc6 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1157,6 +1157,8 @@ end @test *(1:5, mm, s^-1) === 1mm*s^-1:1mm*s^-1:5mm*s^-1 @test *(1:5, mm, s^-1, mol^-1) === 1mm*s^-1*mol^-1:1mm*s^-1*mol^-1:5mm*s^-1*mol^-1 @test @inferred((0:2) * 3f0m) === StepRangeLen{typeof(0f0m)}(0.0m, 3.0m, 3) # issue #477 + @test @inferred(3f0m * (0:2)) === StepRangeLen{typeof(0f0m)}(0.0m, 3.0m, 3) # issue #477 + @test @inferred(1.0s * range(0.1, step=0.1, length=3)) === @inferred(range(0.1, step=0.1, length=3) * 1.0s) end end @testset "> Arrays" begin From 7a36d7b1fd71ea6269ee7dfe7db975bbc46b5cba Mon Sep 17 00:00:00 2001 From: Samuel Buercklin Date: Sat, 23 Oct 2021 03:26:38 -0400 Subject: [PATCH 13/34] Remove unnecessary Bool-AbstractQuantity multiplication methods (#491) * made Bool-Quantity multiplication symmetric * added tests for Bool-Quantity multiplication * Remove unnecessary multiplication methods for Bool, AbstractQuantity Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Remove comment from previous Bool, AbstractQuantity methods Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Add NaN, -Inf tests for multiplication by false Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> --- src/quantities.jl | 5 ----- test/runtests.jl | 6 ++++++ 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/quantities.jl b/src/quantities.jl index a25863d4..7fde2b46 100644 --- a/src/quantities.jl +++ b/src/quantities.jl @@ -29,11 +29,6 @@ Quantity(x::Number, y::Units{()}) = x *(x::AbstractQuantity, y::Units, z::Units...) = Quantity(x.val, *(unit(x),y,z...)) *(x::AbstractQuantity, y::AbstractQuantity) = Quantity(x.val*y.val, unit(x)*unit(y)) -# Next two lines resolves some method ambiguity: -*(x::Bool, y::T) where {T <: AbstractQuantity} = - ifelse(x, y, ifelse(signbit(y), -zero(y), zero(y))) -*(x::AbstractQuantity, y::Bool) = Quantity(x.val*y, unit(x)) - *(y::Number, x::AbstractQuantity) = *(x,y) function *(x::AbstractQuantity, y::Number) x isa AffineQuantity && diff --git a/test/runtests.jl b/test/runtests.jl index d2012bc6..9cd426a3 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -586,6 +586,12 @@ end @test @inferred((3m)*m) === 3*(m*m) # Associative multiplication @test @inferred(true*1kg) === 1kg # Boolean multiplication (T) @test @inferred(false*1kg) === 0kg # Boolean multiplication (F) + @test @inferred(true*(1+im)kg) === (1+im)kg # Boolean-complex multiplication (T) + @test @inferred(false*(1+im)kg) === (0+0im)kg # Boolean-complex multiplication (F) + @test @inferred((1+im)kg*true) === (1+im)kg # Complex-boolean multiplication (T) + @test @inferred((1+im)kg*false) === (0+0im)kg # Complex-boolean multiplication (F) + @test @inferred((NaN*kg)*false) === 0.0kg # `false` acts as "strong zero" + @test @inferred(false*(-Inf*kg)) === -0.0kg # `false` acts as "strong zero" @test typeof(one(eltype([1.0s, 1kg]))) <: Float64 # issue 159, multiplicative identity end @testset "> Division" begin From 1e3b270fc050aa1d43e119ab8d60d645b5fce01a Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Mon, 25 Oct 2021 16:45:51 +0200 Subject: [PATCH 14/34] Resolve method ambiguity (#495) --- src/range.jl | 4 ++++ test/runtests.jl | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/src/range.jl b/src/range.jl index fb864cc1..b42dffe7 100644 --- a/src/range.jl +++ b/src/range.jl @@ -108,3 +108,7 @@ broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::StepRangeLen{T}, x::Abstract broadcasted(DefaultArrayStyle{1}(), *, r, ustrip(x)) * unit(x) broadcasted(::DefaultArrayStyle{1}, ::typeof(*), x::AbstractQuantity, r::StepRangeLen{T}) where T = broadcasted(DefaultArrayStyle{1}(), *, ustrip(x), r) * unit(x) +broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::LinRange, x::AbstractQuantity) = + LinRange(r.start*x, r.stop*x, r.len) +broadcasted(::DefaultArrayStyle{1}, ::typeof(*), x::AbstractQuantity, r::LinRange) = + LinRange(x*r.start, x*r.stop, r.len) diff --git a/test/runtests.jl b/test/runtests.jl index 9cd426a3..602840e5 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1164,6 +1164,10 @@ end @test *(1:5, mm, s^-1, mol^-1) === 1mm*s^-1*mol^-1:1mm*s^-1*mol^-1:5mm*s^-1*mol^-1 @test @inferred((0:2) * 3f0m) === StepRangeLen{typeof(0f0m)}(0.0m, 3.0m, 3) # issue #477 @test @inferred(3f0m * (0:2)) === StepRangeLen{typeof(0f0m)}(0.0m, 3.0m, 3) # issue #477 + @test @inferred((0f0:2f0) * 3f0m) === 0f0m:3f0m:6f0m + @test @inferred(3f0m * (0.0:2.0)) === 0.0m:3.0m:6.0m + @test @inferred(LinRange(0f0, 1f0, 3) * 3f0m) === LinRange(0f0m, 3f0m, 3) + @test @inferred(3f0m * LinRange(0.0, 1.0, 3)) === LinRange(0.0m, 3.0m, 3) @test @inferred(1.0s * range(0.1, step=0.1, length=3)) === @inferred(range(0.1, step=0.1, length=3) * 1.0s) end end From 955fc05fe049a12c15b1372a16eb7d8685a8bd50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Mon, 8 Nov 2021 18:36:13 +0000 Subject: [PATCH 15/34] Fix fastmath trig functions (#497) --- Project.toml | 2 +- src/fastmath.jl | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Project.toml b/Project.toml index eeccec02..faa4d8f1 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Unitful" uuid = "1986cc42-f94f-5a68-af5c-568840ba703d" -version = "1.9.1" +version = "1.9.2" [deps] ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9" diff --git a/src/fastmath.jl b/src/fastmath.jl index c3da5865..f5d23780 100644 --- a/src/fastmath.jl +++ b/src/fastmath.jl @@ -28,6 +28,9 @@ import Base.FastMath: @fastmath, le_fast, pow_fast, sqrt_fast, + cos_fast, + sin_fast, + tan_fast, atan_fast, hypot_fast, max_fast, @@ -35,8 +38,7 @@ import Base.FastMath: @fastmath, minmax_fast, cis_fast, angle_fast, - fast_op, - libm + fast_op sub_fast(x::Quantity{T}) where {T <: FloatTypes} = typeof(x)(neg_float_fast(x.val)) @@ -166,10 +168,8 @@ sqrt_fast(x::Quantity{T}) where {T <: FloatTypes} = for f in (:cos, :sin, :tan) f_fast = fast_op[f] @eval begin - $f_fast(x::DimensionlessQuantity{Float32,U}) where {U} = - ccall(($(string(f,"f")),libm), Float32, (Float32,), uconvert(x,NoUnits)) - $f_fast(x::DimensionlessQuantity{Float64,U}) where {U} = - ccall(($(string(f)),libm), Float64, (Float64,), uconvert(x,NoUnits)) + $(f_fast)(x::DimensionlessQuantity{<:Union{Float32,Float64}}) = + $(f_fast)(uconvert(NoUnits, x)) end end From 496b898e378c273a0e59a00e03fab8c0ce717eb7 Mon Sep 17 00:00:00 2001 From: Oscar Smith Date: Mon, 29 Nov 2021 17:57:28 -0500 Subject: [PATCH 16/34] make `norm` use `norm` rather than `abs` (#500) * make `norm` use `norm` rather than `abs` --- src/quantities.jl | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/quantities.jl b/src/quantities.jl index 7fde2b46..96d3b7f7 100644 --- a/src/quantities.jl +++ b/src/quantities.jl @@ -405,8 +405,7 @@ real(x::AbstractQuantity) = Quantity(real(x.val), unit(x)) imag(x::AbstractQuantity) = Quantity(imag(x.val), unit(x)) conj(x::AbstractQuantity) = Quantity(conj(x.val), unit(x)) -@inline norm(x::AbstractQuantity, p::Real=2) = - p == 0 ? (x==zero(x) ? typeof(abs(x))(0) : typeof(abs(x))(1)) : abs(x) +@inline norm(x::AbstractQuantity, p::Real=2) = Quantity(norm(x.val, p), unit(x)) """ sign(x::AbstractQuantity) From b17b1c54630095b135181baab7436ca72baabdb1 Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 30 Nov 2021 02:12:45 +0300 Subject: [PATCH 17/34] support broadcasting on ranges (#501) --- src/range.jl | 11 +++++++++++ test/runtests.jl | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/range.jl b/src/range.jl index b42dffe7..e65882b6 100644 --- a/src/range.jl +++ b/src/range.jl @@ -81,6 +81,8 @@ _colon(::Any, ::Any, start::T, step, stop::T) where {T} = # Opt into TwicePrecision functionality *(x::Base.TwicePrecision, y::Units) = Base.TwicePrecision(x.hi*y, x.lo*y) *(x::Base.TwicePrecision, y::Quantity) = (x * ustrip(y)) * unit(y) +uconvert(y, x::Base.TwicePrecision) = Base.TwicePrecision(uconvert(y, x.hi), uconvert(y, x.lo)) + function colon(start::T, step::T, stop::T) where (T<:Quantity{S} where S<:Union{Float16,Float32,Float64}) # This will always return a StepRangeLen @@ -103,6 +105,15 @@ broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::AbstractRange, x::AbstractQu broadcasted(DefaultArrayStyle{1}(), *, r, ustrip(x)) * unit(x) broadcasted(::DefaultArrayStyle{1}, ::typeof(*), x::AbstractQuantity, r::AbstractRange) = broadcasted(DefaultArrayStyle{1}(), *, ustrip(x), r) * unit(x) + +const BCAST_PROPAGATE_CALLS = Union{typeof(upreferred), typeof(ustrip), Units} +broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::AbstractRange, x::Ref{<:Units}) = r * x[] +broadcasted(::DefaultArrayStyle{1}, ::typeof(*), x::Ref{<:Units}, r::AbstractRange) = x[] * r +broadcasted(::DefaultArrayStyle{1}, x::BCAST_PROPAGATE_CALLS, r::StepRangeLen) = StepRangeLen(x(r.ref), x(r.step), r.len, r.offset) +broadcasted(::DefaultArrayStyle{1}, x::BCAST_PROPAGATE_CALLS, r::StepRange) = StepRange(x(r.start), x(r.step), x(r.stop)) +broadcasted(::DefaultArrayStyle{1}, x::BCAST_PROPAGATE_CALLS, r::LinRange) = LinRange(x(r.start), x(r.stop), r.len) +broadcasted(::DefaultArrayStyle{1}, ::typeof(|>), r::AbstractRange, x::Ref{<:BCAST_PROPAGATE_CALLS}) = broadcasted(DefaultArrayStyle{1}(), x[], r) + # for ambiguity resolution broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::StepRangeLen{T}, x::AbstractQuantity) where T = broadcasted(DefaultArrayStyle{1}(), *, r, ustrip(x)) * unit(x) diff --git a/test/runtests.jl b/test/runtests.jl index 602840e5..d1f21eab 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1170,6 +1170,26 @@ end @test @inferred(3f0m * LinRange(0.0, 1.0, 3)) === LinRange(0.0m, 3.0m, 3) @test @inferred(1.0s * range(0.1, step=0.1, length=3)) === @inferred(range(0.1, step=0.1, length=3) * 1.0s) end + @testset ">> broadcasting" begin + @test @inferred((1:5) .* mm) === 1mm:1mm:5mm + @test @inferred(mm .* (1:5)) === 1mm:1mm:5mm + @test @inferred((1:2:5) .* mm) === 1mm:2mm:5mm + @test @inferred((1.0:2.0:5.01) .* mm) === 1.0mm:2.0mm:5.0mm + r = @inferred(range(0.1, step=0.1, length=3) .* 1.0s) + @test r[3] === 0.3s + @test @inferred((0:2) .* 3f0m) === StepRangeLen{typeof(0f0m)}(0.0m, 3.0m, 3) # issue #477 + @test @inferred(3f0m .* (0:2)) === StepRangeLen{typeof(0f0m)}(0.0m, 3.0m, 3) # issue #477 + @test @inferred((0f0:2f0) .* 3f0m) === 0f0m:3f0m:6f0m + @test @inferred(3f0m .* (0.0:2.0)) === 0.0m:3.0m:6.0m + @test @inferred(LinRange(0f0, 1f0, 3) .* 3f0m) === LinRange(0f0m, 3f0m, 3) + @test @inferred(3f0m .* LinRange(0.0, 1.0, 3)) === LinRange(0.0m, 3.0m, 3) + @test @inferred(1.0s .* range(0.1, step=0.1, length=3)) === @inferred(range(0.1, step=0.1, length=3) * 1.0s) + + @test @inferred((1:2:5) .* cm .|> mm) === 10mm:20mm:50mm + @test mm.((1:2:5) .* cm) === 10mm:20mm:50mm + @test @inferred((1:2:5) .* km .|> upreferred) === 1000m:2000m:5000m + @test @inferred((1:2:5) .* cm .|> mm .|> ustrip) === 10:20:50 + end end @testset "> Arrays" begin @testset ">> Array multiplication" begin From bec43b6ffe782aac5cd49f03e6e1ad4c76433d5a Mon Sep 17 00:00:00 2001 From: Luke Bemish Date: Mon, 29 Nov 2021 17:26:02 -0600 Subject: [PATCH 18/34] Attempt to allow preferunits to work with non-pure units (#478) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Attempt to allow preferunits to work with non-pure units Should fix #457. Prior to this change, attempts to use something that looked like "preferunits(C/ms)" would result in strange behavior, without throwing any sort of errors. Now, that should work nicely. * Warn user when preferunits causes redundant units Issue a warning when preferunits creates redundant units, which could stop it from sucessfully simplifying certain quantities. * Fix new upreferred behavior for non-dimensional quantities * Add tests for preferunits changes * Update test/runtests.jl Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Fix preferunits tests * Apply suggestions from code review Co-authored-by: MosΓ¨ Giordano * Fix issues added by removing excess arrays * No longer use string for key while checking for units of different scales * Update test/runtests.jl Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Update runtests.jl Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> Co-authored-by: MosΓ¨ Giordano --- src/Unitful.jl | 2 +- src/units.jl | 2 +- src/user.jl | 23 ++++++++++++++++++++++- test/runtests.jl | 13 ++++++++++++- 4 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/Unitful.jl b/src/Unitful.jl index 343f49b6..dac82934 100644 --- a/src/Unitful.jl +++ b/src/Unitful.jl @@ -53,7 +53,7 @@ end const basefactors = _basefactors(Unitful) include("types.jl") -const promotion = Dict{Symbol,Unit}() +const promotion = Dict{Symbol,FreeUnits}() include("user.jl") include("utils.jl") diff --git a/src/units.jl b/src/units.jl index d0aed6f9..a66a047d 100644 --- a/src/units.jl +++ b/src/units.jl @@ -302,6 +302,6 @@ factory defaults, this function will return a product of powers of base SI units (as [`Unitful.FreeUnits`](@ref)). """ @generated function upreferred(x::Dimensions{D}) where {D} - u = *(FreeUnits{((Unitful.promotion[name(z)]^z.power for z in D)...,),()}()) + u = prod((NoUnits, (promotion[name(z)]^z.power for z in D)...)) :($u) end diff --git a/src/user.jl b/src/user.jl index 50a62783..e3fb21a2 100644 --- a/src/user.jl +++ b/src/user.jl @@ -310,7 +310,28 @@ function preferunits(u0::Units, u::Units...) "For instance, it should not be used with units of dimension 𝐋^2.") end y = typeof(dim).parameters[1][1] - promotion[name(y)] = typeof(unit).parameters[1][1] + promotion[name(y)] = unit + end + + # Let's run a quick check for anything where, for instance, current was defined is C/ms and time + # was defined in ns. We'll give a warning if this is the case so the user knows they may get + # unexpected (though still correct) results. There may be cases where people would want to do this, + # so we won't stop them, just let them know they're doing it. + ulist = (typeof(i[2]).parameters[1] for i in promotion) + check = Dict{Dimensions, Unit}() + for a in ulist + ulistA = (i^(1/i.power) for i in a) + for i in ulistA + k = dimension(i) + if haskey(check, k) + if i!=check[k] + @warn "Preferred units contain complex units based on units of the same dimension but different scales: "*string(i)*" and "*string(check[k])* + "\nThis may be intentional, but otherwise could lead to redundant units, such as ms/s or kg/g" + end + else + check[k] = i + end + end end nothing diff --git a/test/runtests.jl b/test/runtests.jl index d1f21eab..59b226ea 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -14,7 +14,8 @@ import Unitful: J, A, N, mol, V, mW, W, dB, dB_rp, dB_p, dBm, dBV, dBSPL, Decibel, - Np, Np_rp, Np_p, Neper + Np, Np_rp, Np_p, Neper, + C import Unitful: 𝐋, 𝐓, 𝐍, 𝚯 @@ -320,6 +321,16 @@ Unitful.uconvert(U::Unitful.Units, q::QQQ) = uconvert(U, Quantity(q.val, cm)) @testset "Promotion" begin @testset "> Unit preferences" begin + # Should warn on possible redundant units issue (ms and s) + @test_logs (:warn, r"^Preferred units contain complex units") Unitful.preferunits(C/ms) + # Test for wacky prefered units functionality + Unitful.preferunits(C/s) + @test @inferred(upreferred(V/m)) == kg*m*C^-1*s^-2 + @test dimension(upreferred(V/m)) == dimension(V/m) + # Reset preferred units to default, except for units of dimension 𝐋*𝐌*𝐈^-1*𝐓^-3, + # because upreferred has already been called for that dimension + Unitful.preferunits(A) + # Only because we favor SI, we have the following: @test @inferred(upreferred(N)) === kg*m/s^2 @test @inferred(upreferred(dimension(N))) === kg*m/s^2 From 2a3308eabd23bd5d936d284576991b163ee9fbdd Mon Sep 17 00:00:00 2001 From: Luke Bemish Date: Mon, 29 Nov 2021 17:26:59 -0600 Subject: [PATCH 19/34] Unit construction macro now defines docs for units (#476) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Unit construction macro now defines docs for units See #436 * Add documentation capabilities to most defined macros This lets all unit and dimension definition macros repect doc strings set in unit definition. Additionally, it automatically defines documentation for derived units using power-of-ten prefixes. * Add documentation for some units in pkgdefaults Documentation has been added for all base units and many other SI units, as well as adding a special case to the documentation so that kg and documented as being the SI base unit. * Allow documentation for log scales and units * Rewrite documentation format for all units through "Liter" Additionally, changed how the prefixed unit documentation is written; this now means that prefixed units made by other modules should be properly documented (tested with UnitfulAstro). * Added documentation for all remaining units Documentation is still required for log scales * Update src/pkgdefaults.jl Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Update src/pkgdefaults.jl Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Update src/pkgdefaults.jl Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Update src/pkgdefaults.jl Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Apply suggestions from code review Added descriptions of why certain alternate symbols are used (q for electron charge, minute for minutes) Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Remove excess newlines; add names to docstrings * Add NoDims documentation * Standardized number and equation format among quantity and unit docs * Standardize format of dimensions in unit docs * Apply suggestions from code review Various minor fixes and changes, mostly typos and format changes. Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Switch from inline to block code blocks in new docstrings. Also standardize docstrings to `2Ο€` for 2 pi. * Add automatic documentation for everything defined by the dimension macro Also removed documentation from the pieces of log units that currently don't have any sort of automatic documentation generation system in place. * Fix documentation issues with two different symbols for vacuum permittivity constant. * Minor formatting fixes * Use block quotes for prefixed units' doc strings * Update src/types.jl Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Make automatic documentation optional Also (optionally) generate automatic documentation for derived dimensions. * Add dimension info in automatic prefixed unit docs. * Change method for adding dimensions to prefixed unit documentation Now no longer tries to `eval` stuff while running the macro. * Fixes to documentation and code structure for autodocs for various macros * Apply suggestions from code review Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Various format fixes and liters documentation changes. * Fix missing optional argument causing test failure * Remove no-longer-necessary NullLogger for liter and kilogram docs * Remove unnecessary autodocs arguments for non-SI-prefixed units * Apply suggestions from code review Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Fix invalid links being created in non-Unitful documentation * Add spaced out column for autogen parameter where possible * Apply suggestions from code review Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Update src/user.jl Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * Add tests for autodocs * Add test for prefixed reference units * Hopefully fix docstrings and docstring tests on Julia-1.0 * Apply suggestions from code review Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * More documentation changes from code review Also removed documentation ability for logunit and logscale (as these should be another pull request) * Apply suggestions from code review Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> --- src/pkgdefaults.jl | 642 ++++++++++++++++++++++++++++++++++++++------- src/types.jl | 2 + src/user.jl | 161 ++++++++++-- test/runtests.jl | 92 +++++++ 4 files changed, 784 insertions(+), 113 deletions(-) diff --git a/src/pkgdefaults.jl b/src/pkgdefaults.jl index 56a1dbfd..09a38d47 100644 --- a/src/pkgdefaults.jl +++ b/src/pkgdefaults.jl @@ -2,68 +2,110 @@ # The dimension symbols are generated by tab completion: \bfL is 𝐋, etc. # At the expense of easy typing, this gives a visual cue to distinguish # dimensions from units, and also helps prevent common namespace collisions. -@dimension 𝐋 "𝐋" Length -@dimension 𝐌 "𝐌" Mass -@dimension 𝐓 "𝐓" Time -@dimension 𝐈 "𝐈" Current -@dimension 𝚯 "𝚯" Temperature # This one is \bfTheta -@dimension 𝐉 "𝐉" Luminosity -@dimension 𝐍 "𝐍" Amount +" Unitful.𝐋 +\nA dimension representing length." +@dimension 𝐋 "𝐋" Length true +" Unitful.𝐌 +\nA dimension representing mass." +@dimension 𝐌 "𝐌" Mass true +" Unitful.𝐓 +\nA dimension representing time." +@dimension 𝐓 "𝐓" Time true +" Unitful.𝐈 +\nA dimension representing electric current." +@dimension 𝐈 "𝐈" Current true +" Unitful.𝚯 +\nA dimension representing thermodynamic temperature." +@dimension 𝚯 "𝚯" Temperature true # This one is \bfTheta +" Unitful.𝐉 +\nA dimension representing luminous intensity." +@dimension 𝐉 "𝐉" Luminosity true +" Unitful.𝐍 +\nA dimension representing amount of substance." +@dimension 𝐍 "𝐍" Amount true const RelativeScaleTemperature = Quantity{T, 𝚯, <:AffineUnits} where T const AbsoluteScaleTemperature = Quantity{T, 𝚯, <:ScalarUnits} where T # Define derived dimensions. -@derived_dimension Area 𝐋^2 -@derived_dimension Volume 𝐋^3 -@derived_dimension Density 𝐌/𝐋^3 -@derived_dimension Frequency inv(𝐓) -@derived_dimension Velocity 𝐋/𝐓 -@derived_dimension Acceleration 𝐋/𝐓^2 -@derived_dimension Force 𝐌*𝐋/𝐓^2 -@derived_dimension Pressure 𝐌*𝐋^-1*𝐓^-2 -@derived_dimension Energy 𝐌*𝐋^2/𝐓^2 -@derived_dimension Momentum 𝐌*𝐋/𝐓 -@derived_dimension Power 𝐋^2*𝐌*𝐓^-3 -@derived_dimension Charge 𝐈*𝐓 -@derived_dimension Voltage 𝐈^-1*𝐋^2*𝐌*𝐓^-3 -@derived_dimension ElectricalResistance 𝐈^-2*𝐋^2*𝐌*𝐓^-3 -@derived_dimension ElectricalResistivity 𝐈^-2*𝐋^3*𝐌*𝐓^-3 -@derived_dimension ElectricalConductance 𝐈^2*𝐋^-2*𝐌^-1*𝐓^3 -@derived_dimension ElectricalConductivity 𝐈^2*𝐋^-3*𝐌^-1*𝐓^3 -@derived_dimension Capacitance 𝐈^2*𝐋^-2*𝐌^-1*𝐓^4 -@derived_dimension Inductance 𝐈^-2*𝐋^2*𝐌*𝐓^-2 -@derived_dimension MagneticFlux 𝐈^-1*𝐋^2*𝐌*𝐓^-2 -@derived_dimension DField 𝐈*𝐓/𝐋^2 -@derived_dimension EField 𝐋*𝐌*𝐓^-3*𝐈^-1 -@derived_dimension HField 𝐈/𝐋 -@derived_dimension BField 𝐈^-1*𝐌*𝐓^-2 -@derived_dimension Action 𝐋^2*𝐌*𝐓^-1 -@derived_dimension DynamicViscosity 𝐌*𝐋^-1*𝐓^-1 -@derived_dimension KinematicViscosity 𝐋^2*𝐓^-1 -@derived_dimension Wavenumber inv(𝐋) -@derived_dimension ElectricDipoleMoment 𝐋*𝐓*𝐈 -@derived_dimension ElectricQuadrupoleMoment 𝐋^2*𝐓*𝐈 -@derived_dimension MagneticDipoleMoment 𝐋^2*𝐈 -@derived_dimension Molarity 𝐍/𝐋^3 -@derived_dimension Molality 𝐍/𝐌 -@derived_dimension MassFlow 𝐌/𝐓 -@derived_dimension MolarFlow 𝐍/𝐓 -@derived_dimension VolumeFlow 𝐋^3/𝐓 +@derived_dimension Area 𝐋^2 true +@derived_dimension Volume 𝐋^3 true +@derived_dimension Density 𝐌/𝐋^3 true +@derived_dimension Frequency inv(𝐓) true +@derived_dimension Velocity 𝐋/𝐓 true +@derived_dimension Acceleration 𝐋/𝐓^2 true +@derived_dimension Force 𝐌*𝐋/𝐓^2 true +@derived_dimension Pressure 𝐌*𝐋^-1*𝐓^-2 true +@derived_dimension Energy 𝐌*𝐋^2/𝐓^2 true +@derived_dimension Momentum 𝐌*𝐋/𝐓 true +@derived_dimension Power 𝐋^2*𝐌*𝐓^-3 true +@derived_dimension Charge 𝐈*𝐓 true +@derived_dimension Voltage 𝐈^-1*𝐋^2*𝐌*𝐓^-3 true +@derived_dimension ElectricalResistance 𝐈^-2*𝐋^2*𝐌*𝐓^-3 true +@derived_dimension ElectricalResistivity 𝐈^-2*𝐋^3*𝐌*𝐓^-3 true +@derived_dimension ElectricalConductance 𝐈^2*𝐋^-2*𝐌^-1*𝐓^3 true +@derived_dimension ElectricalConductivity 𝐈^2*𝐋^-3*𝐌^-1*𝐓^3 true +@derived_dimension Capacitance 𝐈^2*𝐋^-2*𝐌^-1*𝐓^4 true +@derived_dimension Inductance 𝐈^-2*𝐋^2*𝐌*𝐓^-2 true +@derived_dimension MagneticFlux 𝐈^-1*𝐋^2*𝐌*𝐓^-2 true +@derived_dimension DField 𝐈*𝐓/𝐋^2 true +@derived_dimension EField 𝐋*𝐌*𝐓^-3*𝐈^-1 true +@derived_dimension HField 𝐈/𝐋 true +@derived_dimension BField 𝐈^-1*𝐌*𝐓^-2 true +@derived_dimension Action 𝐋^2*𝐌*𝐓^-1 true +@derived_dimension DynamicViscosity 𝐌*𝐋^-1*𝐓^-1 true +@derived_dimension KinematicViscosity 𝐋^2*𝐓^-1 true +@derived_dimension Wavenumber inv(𝐋) true +@derived_dimension ElectricDipoleMoment 𝐋*𝐓*𝐈 true +@derived_dimension ElectricQuadrupoleMoment 𝐋^2*𝐓*𝐈 true +@derived_dimension MagneticDipoleMoment 𝐋^2*𝐈 true +@derived_dimension Molarity 𝐍/𝐋^3 true +@derived_dimension Molality 𝐍/𝐌 true +@derived_dimension MassFlow 𝐌/𝐓 true +@derived_dimension MolarFlow 𝐍/𝐓 true +@derived_dimension VolumeFlow 𝐋^3/𝐓 true # Define base units. This is not to imply g is the base SI unit instead of kg. # See the documentation for further details. # #key: Symbol Display Name Dimension Prefixes? -@refunit m "m" Meter 𝐋 true -@refunit s "s" Second 𝐓 true -@refunit A "A" Ampere 𝐈 true -@refunit K "K" Kelvin 𝚯 true -@refunit cd "cd" Candela 𝐉 true +" Unitful.m +\nThe meter, the SI base unit of length. +\nDimension: [`Unitful.𝐋`](@ref)." +@refunit m "m" Meter 𝐋 true true +" Unitful.s +\nThe second, the SI base unit of time. +\nDimension: [`Unitful.𝐓`](@ref)." +@refunit s "s" Second 𝐓 true true +" Unitful.A +\nThe ampere, the SI base unit of electric current. +\nDimension: [`Unitful.𝐈`](@ref)." +@refunit A "A" Ampere 𝐈 true true +" Unitful.K +\nThe kelvin, the SI base unit of thermodynamic temperature. +\nDimension: [`Unitful.𝚯`](@ref)." +@refunit K "K" Kelvin 𝚯 true true +" Unitful.cd +\nThe candela, the SI base unit of luminous intensity. +\nDimension: [`Unitful.𝐉`](@ref)." +@refunit cd "cd" Candela 𝐉 true true +# the docs for all gram-based units are defined later, to ensure kg is the base unit. @refunit g "g" Gram 𝐌 true -@refunit mol "mol" Mole 𝐍 true +" Unitful.mol +\nThe mole, the SI base unit for amount of substance. +\nDimension: [`Unitful.𝐍`](@ref)." +@refunit mol "mol" Mole 𝐍 true true # Angles and solid angles -@unit sr "sr" Steradian 1 true -@unit rad "rad" Radian 1 true +" Unitful.sr +\nThe steradian, a unit of spherical angle. There are 4Ο€ sr in a sphere. +\nDimension: [`Unitful.NoDims`](@ref)." +@unit sr "sr" Steradian 1 true true +" Unitful.rad +\nThe radian, a unit of angle. There are 2Ο€ rad in a circle. +\nDimension: [`Unitful.NoDims`](@ref)." +@unit rad "rad" Radian 1 true true +" Unitful.Β° +\nThe degree, a unit of angle. There are 360Β° in a circle. +\nDimension: [`Unitful.NoDims`](@ref)." @unit Β° "Β°" Degree pi/180 false # For numerical accuracy, specific to the degree import Base: sind, cosd, tand, secd, cscd, cotd @@ -79,107 +121,435 @@ deg2rad(d::Quantity{T, NoDims, typeof(Β°)}) where {T} = deg2rad(ustrip(Β°, d))u" rad2deg(r::Quantity{T, NoDims, typeof(rad)}) where {T} = rad2deg(ustrip(rad, r))u"Β°" # SI and related units -@unit Hz "Hz" Hertz 1/s true -@unit N "N" Newton 1kg*m/s^2 true -@unit Pa "Pa" Pascal 1N/m^2 true -@unit J "J" Joule 1N*m true -@unit W "W" Watt 1J/s true -@unit C "C" Coulomb 1A*s true -@unit V "V" Volt 1W/A true -@unit Ξ© "Ξ©" Ohm 1V/A true -@unit S "S" Siemens 1/Ξ© true -@unit F "F" Farad 1s^4*A^2/(kg*m^2) true -@unit H "H" Henry 1J/(A^2) true -@unit T "T" Tesla 1kg/(A*s^2) true -@unit Wb "Wb" Weber 1kg*m^2/(A*s^2) true -@unit lm "lm" Lumen 1cd*sr true -@unit lx "lx" Lux 1lm/m^2 true -@unit Bq "Bq" Becquerel 1/s true -@unit Gy "Gy" Gray 1J/kg true -@unit Sv "Sv" Sievert 1J/kg true -@unit kat "kat" Katal 1mol/s true +" Unitful.Hz +\nThe hertz, an SI unit of frequency, defined as 1 s^-1. +\nDimension: 𝐓^-1. +\nSee also: [`Unitful.s`](@ref)." +@unit Hz "Hz" Hertz 1/s true true +" Unitful.N +\nThe newton, an SI unit of force, defined as 1 kg Γ— m / s^2. +\nDimension: 𝐋 𝐌 𝐓^-2. +\nSee also: [`Unitful.kg`](@ref), [`Unitful.m`](@ref), [`Unitful.s`](@ref)." +@unit N "N" Newton 1kg*m/s^2 true true +" Unitful.Pa +\nThe pascal, an SI unit of pressure, defined as 1 N / m^2. +\nDimension: 𝐌 𝐋^-1 𝐓^-2. +\nSee also: [`Unitful.N`](@ref), [`Unitful.m`](@ref)." +@unit Pa "Pa" Pascal 1N/m^2 true true +" Unitful.J +\nThe joule, an SI unit of energy, defined as 1 N Γ— m. +\nDimension: 𝐋^2 𝐌 𝐓^-2. +\nSee also: [`Unitful.N`](@ref), [`Unitful.m`](@ref)." +@unit J "J" Joule 1N*m true true +" Unitful.W +\nThe watt, an SI unit of power, defined as 1 J / s. +\nDimension: 𝐋^2 𝐌 𝐓^-3. +\nSee also: [`Unitful.J`](@ref), [`Unitful.s`](@ref)." +@unit W "W" Watt 1J/s true true +" Unitful.C +\nThe coulomb, an SI unit of electric charge, defined as 1 A Γ— s. +\nDimension: 𝐈 𝐓. +\nSee also: [`Unitful.A`](@ref), [`Unitful.s`](@ref)." +@unit C "C" Coulomb 1A*s true true +" Unitful.V +\nThe volt, an SI unit of electric potential, defined as 1 W / A. +\nDimension: 𝐋^2 𝐌 𝐈^-1 𝐓^-3. +\nSee also: [`Unitful.W`](@ref), [`Unitful.A`](@ref)" +@unit V "V" Volt 1W/A true true +" Unitful.Ω +\nThe ohm, an SI unit of electrical resistance, defined as 1 V / A. +\nDimension: 𝐋^2 𝐌 𝐈^-2 𝐓^-3. +\nSee also: [`Unitful.V`](@ref), [`Unitful.A`](@ref)." +@unit Ξ© "Ξ©" Ohm 1V/A true true +" Unitful.S +\nThe siemens, an SI unit of electrical conductance, defined as 1 Ξ©^-1. +\nDimension: 𝐈^2 𝐓^3 𝐋^-2 𝐌^-1. +\nSee also: [`Unitful.Ξ©`](@ref)" +@unit S "S" Siemens 1/Ξ© true true +" Unitful.F +\nThe farad, an SI unit of electrical capacitance, defined as 1 s^4 Γ— A^2 / (kg Γ— m^2). +\nDimension: 𝐈^2 𝐓^4 𝐋^-2 𝐌^-1. +\nSee also: [`Unitful.s`](@ref), [`Unitful.A`](@ref), [`Unitful.kg`](@ref), [`Unitful.m`](@ref)." +@unit F "F" Farad 1s^4*A^2/(kg*m^2) true true +" Unitful.H +\nThe henry, an SI unit of electrical inductance, defined as 1 J / A^2. +\nDimension: 𝐋^2 𝐌 𝐈^-2 𝐓^-2. +\nSee also: [`Unitful.J`](@ref), [`Unitful.A`](@ref)." +@unit H "H" Henry 1J/(A^2) true true +" Unitful.T +\nThe tesla, an SI unit of magnetic B-field strength, defined as 1 kg / (A Γ— s^2). +\nDimension: 𝐌 𝐈^-1 𝐓^-2. +\nSee also: [`Unitful.kg`](@ref), [`Unitful.A`](@ref), [`Unitful.s`](@ref)." +@unit T "T" Tesla 1kg/(A*s^2) true true +" Unitful.Wb +\nThe weber, an SI unit of magnetic flux, defined as 1 kg Γ— m^2 / (A Γ— s^2). +\nDimension: 𝐋^2 𝐌 𝐈^-1 𝐓^-2. +\nSee also: [`Unitful.kg`](@ref), [`Unitful.m`](@ref), [`Unitful.A`](@ref), [`Unitful.s`](@ref)." +@unit Wb "Wb" Weber 1kg*m^2/(A*s^2) true true +" Unitful.lm +\nThe lumen, an SI unit of luminous flux, defined as 1 cd Γ— sr. +\nDimension: [`Unitful.𝐉`](@ref). +\nSee also: [`Unitful.cd`](@ref), [`Unitful.sr`](@ref)." +@unit lm "lm" Lumen 1cd*sr true true +" Unitful.lx +\nThe lux, an SI unit of illuminance, defined as 1 lm / m^2. +\nDimension: 𝐉 𝐋^-2. +\nSee also: [`Unitful.lm`](@ref), [`Unitful.m`](@ref)." +@unit lx "lx" Lux 1lm/m^2 true true +" Unitful.Bq +\nThe becquerel, an SI unit of radioactivity, defined as 1 nuclear decay per s. +\nDimension: 𝐓^-1. +\nSee also: [`Unitful.s`](@ref)." +@unit Bq "Bq" Becquerel 1/s true true +" Unitful.Gy +\nThe gray, an SI unit of ionizing radiation dose, defined as the absorbtion of 1 J per kg of matter. +\nDimension: 𝐋^2 𝐓^-2. +\nSee also: [`Unitful.lm`](@ref), [`Unitful.m`](@ref)." +@unit Gy "Gy" Gray 1J/kg true true +" Unitful.Sv +\nThe sievert, an SI unit of the biological effect of an ionizing radiation dose. +Defined as the health effect of 1 Gy of radiation, scaled by a quality factor. +\nDimension: 𝐋^2 𝐓^-2. +\nSee also: [`Unitful.Gy`](@ref)." +@unit Sv "Sv" Sievert 1J/kg true true +" Unitful.kat +\nThe katal, an SI unit of catalytic activity, defined as 1 mol of catalyzed +substrate per s. +\nDimension: 𝐍 𝐓^-1. +\nSee also: [`Unitful.mol`](@ref), [`Unitful.s`](@ref)." +@unit kat "kat" Katal 1mol/s true true +" Unitful.percent +\nPercent, a unit meaning parts per hundred. Printed as \"%\". +\nDimension: [`Unitful.NoDims`](@ref)." @unit percent "%" Percent 1//100 false +" Unitful.permille +\nPermille, a unit meaning parts per thousand. Printed as \"‰\". +\nDimension: [`Unitful.NoDims`](@ref)." @unit permille "‰" Permille 1//1000 false +" Unitful.pertenthousand +\nPermyriad, a unit meaning parts per ten thousand. Printed as \"β€±\". +\nDimension: [`Unitful.NoDims`](@ref)." @unit pertenthousand "β€±" Pertenthousand 1//10000 false # Temperature +" Unitful.Β°C +\nThe degree Celsius, an SI unit of temperature, defined such that 0 Β°C = 273.15 K. +\nDimension: [`Unitful.𝚯`](@ref). +\nSee also: [`Unitful.K`](@ref)." @affineunit Β°C "Β°C" (27315//100)K # Common units of time +" Unitful.minute +\nThe minute, a unit of time defined as 60 s. The full name `minute` is used instead of the symbol `min` +to avoid confusion with the Julia function `min`. +\nDimension: [`Unitful.𝐓`](@ref). +\nSee Also: [`Unitful.s`](@ref)." @unit minute "minute" Minute 60s false +" Unitful.hr +\nThe hour, a unit of time defined as 60 minutes. +\nDimension: [`Unitful.𝐓`](@ref). +\nSee Also: [`Unitful.minute`](@ref)." @unit hr "hr" Hour 3600s false +" Unitful.d +\nThe day, a unit of time defined as 24 hr. +\nDimension: [`Unitful.𝐓`](@ref). +\nSee Also: [`Unitful.hr`](@ref)." @unit d "d" Day 86400s false +" Unitful.wk +\nThe week, a unit of time, defined as 7 d. +\nDimension: [`Unitful.𝐓`](@ref). +\nSee Also: [`Unitful.d`](@ref)." @unit wk "wk" Week 604800s false -@unit yr "yr" Year 31557600s true +" Unitful.yr +\nThe year, a unit of time, defined as 365.25 d. +\nDimension: [`Unitful.𝐓`](@ref). +\nSee Also: [`Unitful.hr`](@ref)." +@unit yr "yr" Year 31557600s true true +" Unitful.rps +\nRevolutions per second, a unit of rotational speed, defined as 2Ο€ rad / s. +\nDimension: 𝐓^-1. +\nSee Also: [`Unitful.rad`](@ref), [`Unitful.s`](@ref)." @unit rps "rps" RevolutionsPerSecond 2Ο€*rad/s false +" Unitful.rpm +\nRevolutions per minute, a unit of rotational speed, defined as 2Ο€ rad / minute. +\nDimension: 𝐓^-1. +\nSee Also: [`Unitful.minute`](@ref), [`Unitful.rad`](@ref)." @unit rpm "rpm" RevolutionsPerMinute 2Ο€*rad/minute false # Area # The hectare is used more frequently than any other power-of-ten of an are. +" Unitful.a +\nThe are, a metric unit of area, defined as 100 m^2. +\nDimension: 𝐋^2. +\nSee Also: [`Unitful.m`](@ref)." @unit a "a" Are 100m^2 false +" Unitful.ha +\nThe hectare, a metric unit of area, defined as 100 a. +\nDimension: 𝐋^2. +\nSee Also: [`Unitful.a`](@ref)." const ha = Unitful.FreeUnits{(Unitful.Unit{:Are, 𝐋^2}(2, 1//1),), 𝐋^2}() -@unit b "b" Barn 100fm^2 true +" Unitful.b +\nThe barn, a metric unit of area, defined as 100 fm^2. +\nDimension: 𝐋^2. +\nSee Also: [`Unitful.fm`](@ref)." +@unit b "b" Barn 100fm^2 true true # Volume # `l` is also an acceptable symbol for liters +" Unitful.L + Unitful.l +\nThe liter, a metric unit of volume, defined as 1000 cm^3. +\nDimension: 𝐋^3. +\nSee Also: [`Unitful.cm`](@ref)." @unit L "L" Liter m^3//1000 true for p in (:y, :z, :a, :f, :p, :n, :ΞΌ, :Β΅, :m, :c, :d, Symbol(""), :da, :h, :k, :M, :G, :T, :P, :E, :Z, :Y) Core.eval(Unitful, :(const $(Symbol(p,:l)) = $(Symbol(p,:L)))) end +@doc @doc(L) l +for (k,v) in prefixdict + if k != 0 + sym_L = Symbol(v,:L) + sym_l = Symbol(v,:l) + docstring = """ + Unitful.$sym_L + Unitful.$sym_l + + A prefixed unit, equal to 10^$k L. + + Dimension: 𝐋^3. + + See also: [`Unitful.L`](@ref). + """ + run = quote @doc $docstring $sym_l; @doc $docstring $sym_L end + eval(run) + end +end # Molarity -@unit M "M" Molar 1mol/L true +" Unitful.M +\nA unit for measuring molar concentration, equal to 1 mol/L. +\nDimension: 𝐍 𝐋^-3. +\nSee Also: [`Unitful.L`](@ref), [`Unitful.mol`](@ref)." +@unit M "M" Molar 1mol/L true true # Energy +" Unitful.q +\nA quantity equal to the elementary charge, the charge of a single electron, +with a value of exactly 1.602,176,634 Γ— 10^-19 C. The letter `q` is used instead of `e` to avoid +confusion with Euler's number. +\nDimension: 𝐈 𝐓. +\nSee Also: [`Unitful.C`](@ref)." const q = 1.602_176_634e-19*C # CODATA 2018; `e` means 2.718... -@unit eV "eV" eV q*V true +" Unitful.eV +\nThe electron-volt, a unit of energy, defined as q*V. +\nDimension: 𝐋^2 𝐌 𝐓^-2. +\nSee also: [`Unitful.q`](@ref), [`Unitful.V`](@ref)." +@unit eV "eV" eV q*V true true # For convenience -@unit Hz2Ο€ "Hz2Ο€" AngHertz 2Ο€/s true -@unit bar "bar" Bar 100000Pa true +" Unitful.Hz2Ο€ +\nA unit for convenience in angular frequency, equal to 2Ο€ Hz. +\nDimension: 𝐓^-1. +\nSee also: [`Unitful.Hz`](@ref)." +@unit Hz2Ο€ "Hz2Ο€" AngHertz 2Ο€/s true true +" Unitful.bar +\nThe bar, a metric unit of pressure, defined as 100 kPa. +\nDimension: 𝐌 𝐋^-1 𝐓^-2. +\nSee also: [`Unitful.kPa`](@ref)." +@unit bar "bar" Bar 100000Pa true true +" Unitful.atm +\nThe standard atmosphere, a unit of pressure, defined as 101,325 Pa. +\nDimension: 𝐌 𝐋^-1 𝐓^-2. +\nSee also: [`Unitful.Pa`](@ref)." @unit atm "atm" Atmosphere 101325Pa false -@unit Torr "Torr" Torr 101325Pa//760 true +" Unitful.Torr +\nThe torr, a unit of pressure, defined as 1/760 atm. +\nDimension: 𝐌 𝐋^-1 𝐓^-2. +\nSee also: [`Unitful.atm`](@ref)." +@unit Torr "Torr" Torr 101325Pa//760 true true # Constants (2018 CODATA values) (uncertainties in final digits) +" Unitful.c0 +\nA quantity representing the speed of light in a vacuum, defined as exactly +2.997,924,58 Γ— 10^8 m/s. +\n`Unitful.c0` is a quantity (with units `m/s`) whereas [`Unitful.c`](@ref) is a unit equal to `c0`. +\nDimension: 𝐋 𝐓^-1. +\nSee also: [`Unitful.m`](@ref), [`Unitful.s`](@ref)." const c0 = 299_792_458*m/s # exact +" Unitful.c +\nThe speed of light in a vacuum, a unit of speed, defined as exactly +2.997,924,58 Γ— 10^8 m/s. +\n[`Unitful.c0`](@ref) is a quantity (with units `m/s`) whereas `Unitful.c` is a unit equal to `c0`. +\nDimension: 𝐋 𝐓^-1. +\nSee also: [`Unitful.m`](@ref), [`Unitful.s`](@ref)." @unit c "c" SpeedOfLight 1c0 false +" Unitful.ΞΌ0 +\nA quantity representing the vacuum permeability constant, defined as 4Ο€ Γ— 10^-7 H / m. +\nDimension: 𝐋 𝐌 𝐈^-2 𝐓^-2. +\nSee also: [`Unitful.H`](@ref), [`Unitful.m`](@ref)." const ΞΌ0 = 4Ο€*(1//10)^7*H/m # exact (but gets promoted to Float64...) const Β΅0 = ΞΌ0 # magnetic constant +" Unitful.Ξ΅0 + Unitful.Ο΅0 +\nA quantity representing the vacuum permittivity constant, defined as 1 / (ΞΌ0 Γ— c^2). +\nDimension: 𝐈^2 𝐓^4 𝐋^-3 𝐌^-1. +\nSee also: [`Unitful.ΞΌ0`](@ref), [`Unitful.c`](@ref)." const Ι›0 = 1/(ΞΌ0*c^2) # exact, electric constant; changes here may affect -const Ο΅0 = Ι›0 # test of issue 79. +@doc @doc(Ι›0) const Ο΅0 = Ι›0 # test of issue 79. +" Unitful.Z0 +\nA quantity representing the impedance of free space, a constant defined as ΞΌ0 Γ— c. +\nDimension: 𝐋^2 𝐌 𝐈^-2 𝐓^-3. +\nSee also: [`Unitful.ΞΌ0`](@ref), [`Unitful.c`](@ref)." const Z0 = ΞΌ0*c # exact, impedance of free space +" Unitful.G +\nA quantity representing the universal gravitational constant, equal to +6.674,30 Γ— 10^-11 m^3 / (kg Γ— s^2) (the CODATA 2018 recommended value). +\nDimension: 𝐋^3 𝐌^-1 𝐓^-2. +\nSee also: [`Unitful.m`](@ref), [`Unitful.kg`](@ref), [`Unitful.s`](@ref)." const G = 6.674_30e-11*m^3/kg/s^2 # (15) gravitational constant +" Unitful.gn +\nA quantity representing the nominal acceleration due to gravity in a vacuum +near the surface of the earth, defined by standard to be exactly 9.806,65 m / s^2. +\n`Unitful.gn` is a quantity (with units `m/s^2`) whereas [`Unitful.ge`](@ref) is a unit equal to `gn`. +\nDimension: 𝐋 𝐓^-2. +\nSee also: [`Unitful.m`](@ref), [`Unitful.s`](@ref)." const gn = 9.80665*m/s^2 # exact, standard acceleration of gravity +" Unitful.h +\nA quantity representing Planck's constant, defined as exactly +6.626,070,15 Γ— 10^-34 J Γ— s. +\nDimension: 𝐋^2 𝐌 𝐓^-1. +\nSee also: [`Unitful.J`](@ref), [`Unitful.s`](@ref)." const h = 6.626_070_15e-34*J*s # exact, Planck constant +" Unitful.Δ§ +\nA quantity representing the reduced Planck constant, defined as h / 2Ο€. +\nDimension: 𝐋^2 𝐌 𝐓^-1. +\nSee also: [`Unitful.h`](@ref)." const Δ§ = h/2Ο€ # hbar +" Unitful.Ξ¦0 +\nA quantity representing the superconducting magnetic flux quantum, defined as +h / (2 Γ— q). +\nDimension: 𝐋^2 𝐌 𝐈^-1 𝐓^-2. +\nSee also: [`Unitful.h`](@ref), [`Unitful.q`](@ref)." const Ξ¦0 = h/(2q) # Superconducting magnetic flux quantum +" Unitful.me +\nA quantity representing the rest mass of an electron, equal to 9.109,383,7015 +Γ— 10^-31 kg (the CODATA 2018 recommended value). +\nDimension: [`Unitful.𝐌`](@ref). +\nSee also: [`Unitful.kg`](@ref)." const me = 9.109_383_7015e-31*kg # (28) electron rest mass +" Unitful.mn +\nA quantity representing the rest mass of a neutron, equal to 1.674,927,498,04 +Γ— 10^-27 kg (the CODATA 2018 recommended value). +\nDimension: [`Unitful.𝐌`](@ref). +\nSee also: [`Unitful.kg`](@ref)." const mn = 1.674_927_498_04e-27*kg # (95) neutron rest mass +" Unitful.mp +\nA quantity representing the rest mass of a proton, equal to 1.672,621,923,69 +Γ— 10^-27 kg (the CODATA 2018 recommended value). +\nDimension: [`Unitful.𝐌`](@ref). +\nSee also: [`Unitful.kg`](@ref)." const mp = 1.672_621_923_69e-27*kg # (51) proton rest mass +" Unitful.ΞΌB +\nA quantity representing the Bohr magneton, equal to q Γ— Δ§ / (2 Γ— me). +\nDimension: 𝐈 𝐋^2. +\nSee also: [`Unitful.q`](@ref), [`Unitful.Δ§`](@ref), [`Unitful.me`](@ref)." const ΞΌB = q*Δ§/(2*me) # Bohr magneton const Β΅B = ΞΌB +" Unitful.Na +\nA quantity representing Avogadro's constant, defined as exactly +6.022,140,76 Γ— 10^23 / mol. +\nDimension: 𝐍^-1. +\nSee also: [`Unitful.mol`](@ref)." const Na = 6.022_140_76e23/mol # exact, Avogadro constant +" Unitful.k +\nA quantity representing the Boltzmann constant, defined as exactly +1.380,649 Γ— 10^-23 J / K. +\nDimension: 𝐋^2 𝐌 𝚯^-1 𝐓^-2. +\nSee also: [`Unitful.J`](@ref), [`Unitful.K`](@ref)." const k = 1.380_649e-23*(J/K) # exact, Boltzmann constant +" Unitful.R +\nA quantity representing the molar gas constant, defined as +Na Γ— k. +\nDimension: 𝐋^2 𝐌 𝐍^-1 𝚯^-1 𝐓^-2. +\nSee also: [`Unitful.Na`](@ref), [`Unitful.k`](@ref)." const R = Na*k # molar gas constant +" Unitful.Οƒ +\nA quantity representing the Stefan-Boltzmann constant, defined as +Ο€^2 Γ— k^4 / (60 Γ— Δ§^3 Γ— c^2). +\nDimension: 𝐌 𝚯^-4 𝐓^-3. +\nSee also: [`Unitful.k`](@ref), [`Unitful.Δ§`](@ref), [`Unitful.c`](@ref)." const Οƒ = Ο€^2*k^4/(60*Δ§^3*c^2) # Stefan-Boltzmann constant +" Unitful.R∞ +\nA quantity representing the Rydberg constant, equal to 1.097,373,156,8160 Γ— 10^-7 / m +(the CODATA 2018 recommended value). +\nDimension: 𝐋^-1. +\nSee also: [`Unitful.m`](@ref)." const R∞ = 10_973_731.568_160/m # (21) Rydberg constant +" Unitful.u +\nThe unified atomic mass unit, or dalton, a unit of mass defined as 1/12 the +mass of an unbound neutral atom of carbon-12, equal to 1.660,539,066,60 Γ— 10^-27 kg +(the CODATA 2018 recommended value). +\nDimension: [`Unitful.𝐌`](@ref). +\nSee Also: [`Unitful.kg`](@ref)." @unit u "u" UnifiedAtomicMassUnit 1.660_539_066_60e-27*kg false # (50) # Acceleration +" Unitful.ge +\nThe nominal acceleration due to gravity in a vacuum near the surface of the +earth, a unit of acceleration, defined by standard to be exactly 9.806,65 m / s^2. +\n[`Unitful.gn`](@ref) is a quantity (with units `m/s^2`) whereas `Unitful.ge` is a unit equal to `gn`. +\nDimension: 𝐋 𝐓^-2. +\nSee also: [`Unitful.m`](@ref), [`Unitful.s`](@ref)." @unit ge "ge" EarthGravity gn false # CGS units -@unit Gal "Gal" Gal 1cm/s^2 true -@unit dyn "dyn" Dyne 1g*cm/s^2 true -@unit erg "erg" Erg 1g*cm^2/s^2 true -@unit Ba "Ba" Barye 1g/cm/s^2 true -@unit P "P" Poise 1g/cm/s true -@unit St "St" Stokes 1cm^2/s true -@unit Gauss "Gauss" Gauss (1//10_000)*T true -@unit Oe "Oe" Oersted (1_000/4Ο€)*A/m true -@unit Mx "Mx" Maxwell (1//100_000_000)*Wb true +" Unitful.Gal +\nThe gal, a CGS unit of acceleration, defined as 1 cm / s^2. +\nDimension: 𝐋 𝐓^-2. +\nSee also: [`Unitful.cm`](@ref), [`Unitful.s`](@ref)." +@unit Gal "Gal" Gal 1cm/s^2 true true +" Unitful.dyn +\nThe dyne, a CGS unit of force, defined as 1 g Γ— cm / s^2. +\nDimension: 𝐋 𝐌 𝐓^-2. +\nSee also: [`Unitful.cm`](@ref), [`Unitful.s`](@ref), [`Unitful.g`](@ref)." +@unit dyn "dyn" Dyne 1g*cm/s^2 true true +" Unitful.erg +\nThe erg, a CGS unit of energy, defined as 1 dyn Γ— cm. +\nDimension: 𝐋^2 𝐌 𝐓^-2. +\nSee also: [`Unitful.cm`](@ref), [`Unitful.dyn`](@ref)" +@unit erg "erg" Erg 1g*cm^2/s^2 true true +" Unitful.Ba +\nThe barye, a CGS unit of pressure, defined as 1 dyn / cm^2. +\nDimension: 𝐌 𝐋^-1 𝐓^-2. +\nSee also: [`Unitful.cm`](@ref), [`Unitful.dyn`](@ref)" +@unit Ba "Ba" Barye 1g/cm/s^2 true true +" Unitful.P +\nThe poise, a CGS unit of dynamic viscosity, defined as 1 dyn Γ— s / cm^2. +\nDimension: 𝐌 𝐋^-1 𝐓^-1. +\nSee also: [`Unitful.cm`](@ref), [`Unitful.dyn`](@ref), [`Unitful.s`](@ref)" +@unit P "P" Poise 1g/cm/s true true +" Unitful.St +\nThe stokes, a CGS unit of kinematic viscosity, defined as 1 cm^2 / s. +\nDimension: 𝐌^2 𝐓^-1. +\nSee also: [`Unitful.cm`](@ref), [`Unitful.s`](@ref)" +@unit St "St" Stokes 1cm^2/s true true +" Unitful.Gauss +\nThe gauss, a CGS unit of magnetic B-field strength, defined as 1 Mx / cm^2. +\nDimension: 𝐌 𝐈^-1 𝐓^-2. +\nSee also: [`Unitful.cm`](@ref), [`Unitful.Mx`](@ref)" +@unit Gauss "Gauss" Gauss (1//10_000)*T true true +" Unitful.Oe +\nThe oersted, a CGS unit of magnetic H-field strength, defined as 1000 A / (4Ο€ Γ— m). +\nDimension: 𝐈 𝐋^-1. +\nSee also: [`Unitful.A`](@ref), [`Unitful.m`](@ref)" +@unit Oe "Oe" Oersted (1_000/4Ο€)*A/m true true +" Unitful.Mx +\nThe maxwell, a CGS unit of magnetic flux, defined as 1 Gauss Γ— cm^2. +\nDimension: 𝐋^2 𝐌 𝐈^-1 𝐓^-2. +\nSee also: [`Unitful.cm`](@ref), [`Unitful.Gauss`](@ref)" +@unit Mx "Mx" Maxwell (1//100_000_000)*Wb true true ######### @@ -187,38 +557,111 @@ const R∞ = 10_973_731.568_160/m # (21) Rydberg constant # Length #key: Symbol Display Name Equivalent to 10^n prefixes? +" Unitful.inch +\nThe inch, a US customary unit of length defined as 2.54 cm. +\nDimension: [`Unitful.𝐋`](@ref). +\nSee Also: [`Unitful.cm`](@ref)." @unit inch "inch" Inch (254//10000)*m false +" Unitful.mil +\nThe mil, a US customary unit of length defined as 1/1000 inch. +\nDimension: [`Unitful.𝐋`](@ref). +\nSee Also: [`Unitful.inch`](@ref)." @unit mil "mil" Mil (1//1000)*inch false +" Unitful.ft +\nThe foot, a US customary unit of length defined as 12 inch. +\nDimension: [`Unitful.𝐋`](@ref). +\nSee Also: [`Unitful.inch`](@ref)." @unit ft "ft" Foot 12inch false +" Unitful.yd +\nThe yard, a US customary unit of length defined as 3 ft. +\nDimension: [`Unitful.𝐋`](@ref). +\nSee Also: [`Unitful.ft`](@ref)." @unit yd "yd" Yard 3ft false +" Unitful.mi +\nThe mile, a US customary unit of length defined as 1760 yd. +\nDimension: [`Unitful.𝐋`](@ref). +\nSee Also: [`Unitful.yd`](@ref)." @unit mi "mi" Mile 1760yd false +" Unitful.angstrom + Unitful.β„« +\nThe angstrom, a metric unit of length defined as 1/10 nm. +\nDimension: [`Unitful.𝐋`](@ref). +\nSee Also: [`Unitful.nm`](@ref)." @unit angstrom "β„«" Angstrom (1//10)*nm false # U+00c5 (opt-shift-A on macOS) and U+212b ('\Angstrom' in REPL) look identical: -const Γ… = β„« = angstrom +@doc @doc(angstrom) const Γ… = β„« = angstrom # Area +" Unitful.ac +\nThe acre, a US customary unit of area defined as 4840 yd^2. +\nDimension: 𝐋^2. +\nSee Also: [`Unitful.yd`](@ref)." @unit ac "ac" Acre (316160658//78125)*m^2 false # Temperatures +" Unitful.Ra +\nThe rankine, a US customary unit of temperature defined as 5/9 K. +\nDimension: [`Unitful.𝚯`](@ref). +\nSee Also: [`Unitful.K`](@ref)." @unit Ra "Ra" Rankine (5//9)*K false +" Unitful.Β°F +\nThe degree Fahrenheit, a US customary unit of temperature, defined such that 0 Β°F = 459.67 Ra. +\nDimension: [`Unitful.𝚯`](@ref). +\nSee also: [`Unitful.Ra`](@ref)." @affineunit Β°F "Β°F" (45967//100)Ra # Masses +" Unitful.lb +\nThe pound-mass, a US customary unit of mass defined as exactly 0.453,592,37 kg. +\nDimension: [`Unitful.𝐌`](@ref). +\nSee Also: [`Unitful.kg`](@ref)." @unit lb "lb" Pound 0.45359237kg false # is exact +" Unitful.oz +\nThe ounce, a US customary unit of mass defined as 1/16 lb. +\nDimension: [`Unitful.𝐌`](@ref). +\nSee Also: [`Unitful.lb`](@ref)." @unit oz "oz" Ounce lb//16 false +" Unitful.slug +\nThe slug, a US customary unit of mass defined as 1 lbf Γ— s^2 / ft. +\nDimension: [`Unitful.𝐌`](@ref). +\nSee Also: [`Unitful.lbf`](@ref), [`Unitful.s`](@ref), [`Unitful.ft`](@ref)." @unit slug "slug" Slug 1lb*ge*s^2/ft false +" Unitful.dr +\nThe dram, a US customary unit of mass defined as 1/16 oz. +\nDimension: [`Unitful.𝐌`](@ref). +\nSee Also: [`Unitful.oz`](@ref)." @unit dr "dr" Dram oz//16 false +" Unitful.gr +\nThe grain, a US customary unit of mass defined as 1/7000 lb. +\nDimension: [`Unitful.𝐌`](@ref). +\nSee Also: [`Unitful.lb`](@ref)." @unit gr "gr" Grain (32//875)*dr false # Force +" Unitful.lbf +\nThe pound-force, a US customary unit of force defined as 1 lb Γ— ge. +\nDimension: 𝐋 𝐌 𝐓^-2. +\nSee Also: [`Unitful.lb`](@ref), [`Unitful.ge`](@ref)." @unit lbf "lbf" PoundsForce 1lb*ge false # Energy # Use ISO 31-4 for BTU definition -@unit cal "cal" Calorie 4.184J true +" Unitful.cal +\nThe calorie, a unit of energy defined as exactly 4.184 J. +\nDimension: 𝐋^2 𝐌 𝐓^-2. +\nSee Also: [`Unitful.J`](@ref)." +@unit cal "cal" Calorie 4.184J true true +" Unitful.btu +\nThe British thermal unit, a US customary unit of heat defined by ISO 31-4 as exactly 1055.06 J. +\nDimension: 𝐋^2 𝐌 𝐓^-2. +\nSee Also: [`Unitful.J`](@ref)." @unit btu "btu" BritishThermalUnit 1055.06J false # Pressure +" Unitful.psi +\nPounds per square inch, a US customary unit of pressure defined as 1 lbf / inch^2. +\nDimension: 𝐌 𝐋^-1 𝐓^-2. +\nSee Also: [`Unitful.lbf`](@ref), [`Unitful.inch`](@ref)." @unit psi "psi" PoundsPerSquareInch 1lbf/inch^2 false ######### @@ -295,6 +738,27 @@ end ######### preferunits(kg) # others done in @refunit +# Fix documentation for all kg based units +for (k,v) in prefixdict + if k != 3 + sym = Symbol(v,:g) + docstring = """ + Unitful.$sym + + A prefixed unit, equal to 10^$(k-3) kg. Note that `kg`, not `g`, is the base unit. + + Dimension: [`Unitful.𝐌`](@ref). + + See also: [`Unitful.kg`](@ref). + """ + run = quote @doc $docstring $sym end + eval(run) + end +end +@doc " Unitful.kg +\nThe kilogram, the SI base unit of mass. +Note that `kg`, not `g`, is the base unit. +\nDimension: [`Unitful.𝐌`](@ref)." kg """ Unitful.promote_to_derived() diff --git a/src/types.jl b/src/types.jl index 05b76f61..bfff4d46 100644 --- a/src/types.jl +++ b/src/types.jl @@ -27,6 +27,8 @@ end Instances of this object represent dimensions, possibly combinations thereof. """ struct Dimensions{N} <: Unitlike end +" Unitful.NoDims +\nA dimension representing quantities without dimensions." const NoDims = Dimensions{()}() """ diff --git a/src/user.jl b/src/user.jl index e3fb21a2..78c6c8fc 100644 --- a/src/user.jl +++ b/src/user.jl @@ -26,7 +26,7 @@ function register(unit_module::Module) end """ - @dimension(symb, abbr, name) + @dimension(symb, abbr, name, autodocs=false) Creates new dimensions. `name` will be used like an identifier in the type parameter for a [`Unitful.Dimension`](@ref) object. `symb` will be a symbol defined in the namespace from which this macro is called that is bound to a @@ -43,6 +43,12 @@ of the newly defined dimension. The type alias for quantities or levels is simpl `name`, and the type alias for units is given by `name*"Units"`, e.g. `LengthUnits`. Note that there is also `LengthFreeUnits`, for example, which is an alias for dispatching on `FreeUnits` with length dimensions. The aliases are not exported. +If `autodocs == true`, docstrings will be automatically generated for these aliases. + +!!! compat "Unitful 1.10" + Documenting the resulting dimension symbol by adding a docstring before the `@dimension` + call requires Unitful 1.10 or later. The `autodocs` argument also requires Unitful 1.10 + or later. Finally, if you define new dimensions with [`@dimension`](@ref) you will need to specify a preferred unit for that dimension with [`Unitful.preferunits`](@ref), @@ -53,28 +59,64 @@ Returns the `Dimensions` object to which `symb` is bound. Usage example from `src/pkgdefaults.jl`: `@dimension 𝐋 "𝐋" Length` """ -macro dimension(symb, abbr, name) +macro dimension(symb, abbr, name, autodocs=false) s = Symbol(symb) x = Expr(:quote, name) uname = Symbol(name,"Units") funame = Symbol(name,"FreeUnits") + name_links = __module__ == Unitful ? "[`Unitful.Quantity`](@ref), [`Unitful.Level`](@ref)" : "`Unitful.Quantity`, `Unitful.Level`" + unit_links = __module__ == Unitful ? "[`Unitful.Units`](@ref)" : "`Unitful.Units`" + funit_links = __module__ == Unitful ? "[`Unitful.FreeUnits`](@ref)" : "`Unitful.FreeUnits`" + name_doc = """ + $__module__.$name{T, U} + + A supertype for quantities and levels of dimension [`$__module__.$s`](@ref) with a value + of type `T` and units `U`. + + See also: [`$__module__.$s`](@ref), $name_links. + """ + unit_doc = """ + $__module__.$uname{U} + + A supertype for units of dimension [`$__module__.$s`](@ref). Equivalent to + `Unitful.Units{U, $__module__.$s}`. + + See also: [`$__module__.$s`](@ref), $unit_links. + """ + funit_doc = """ + $__module__.$funame{U} + + A supertype for $funit_links of dimension [`$__module__.$s`](@ref). Equivalent to + `Unitful.FreeUnits{U, $__module__.$s}`. + + See also: [`$__module__.$s`](@ref). + """ esc(quote $Unitful.abbr(::$Dimension{$x}) = $abbr - const global $s = $Dimensions{($Dimension{$x}(1),)}() + Base.@__doc__ const global $s = $Dimensions{($Dimension{$x}(1),)}() const global ($name){T,U} = Union{ $Quantity{T,$s,U}, $Level{L,S,$Quantity{T,$s,U}} where {L,S}} const global ($uname){U} = $Units{U,$s} const global ($funame){U} = $FreeUnits{U,$s} + if $autodocs + @doc $name_doc $name + @doc $unit_doc $uname + @doc $funit_doc $funame + end $s end) end """ - @derived_dimension(name, dims) + @derived_dimension(name, dims, autodocs=false) Creates type aliases to allow dispatch on [`Unitful.Quantity`](@ref), [`Unitful.Level`](@ref), and [`Unitful.Units`](@ref) objects of a derived dimension, like area, which is just length squared. The type aliases are not exported. +If `autodocs == true`, docstrings will be automatically generated for these aliases. + +!!! compat "Unitful 1.10" + The `autodocs` argument requires Unitful 1.10 or later. `dims` is a [`Unitful.Dimensions`](@ref) object. @@ -85,22 +127,51 @@ Usage examples: - `@derived_dimension Area 𝐋^2` gives `Area` and `AreaUnit` type aliases - `@derived_dimension Speed 𝐋/𝐓` gives `Speed` and `SpeedUnit` type aliases """ -macro derived_dimension(name, dims) +macro derived_dimension(name, dims, autodocs=false) uname = Symbol(name,"Units") funame = Symbol(name,"FreeUnits") + name_links = __module__ == Unitful ? "[`Unitful.Quantity`](@ref), [`Unitful.Level`](@ref)" : "`Unitful.Quantity`, `Unitful.Level`" + unit_links = __module__ == Unitful ? "[`Unitful.Units`](@ref)" : "`Unitful.Units`" + funit_links = __module__ == Unitful ? "[`Unitful.FreeUnits`](@ref)" : "`Unitful.FreeUnits`" + name_doc = """ + $__module__.$name{T, U} + + A supertype for quantities and levels of dimension `$dims` with a value of type `T` and + units `U`. + + See also: $name_links. + """ + unit_doc = """ + $__module__.$uname{U} + + A supertype for units of dimension `$dims`. Equivalent to `Unitful.Units{U, $dims}`. + + See also: $unit_links. + """ + funit_doc = """ + $__module__.$funame{U} + + A supertype for $funit_links of dimension `$dims`. Equivalent to + `Unitful.FreeUnits{U, $dims}`. + """ esc(quote const global ($name){T,U} = Union{ $Quantity{T,$dims,U}, $Level{L,S,$Quantity{T,$dims,U}} where {L,S}} const global ($uname){U} = $Units{U,$dims} const global ($funame){U} = $FreeUnits{U,$dims} + if $autodocs + @doc $name_doc $name + @doc $unit_doc $uname + @doc $funit_doc $funame + end nothing end) end """ - @refunit(symb, name, abbr, dimension, tf) + @refunit(symb, name, abbr, dimension, tf, autodocs=false) Define a reference unit, typically SI. Rather than define conversion factors between each and every unit of a given dimension, conversion factors are given between each unit and a reference unit, defined by this macro. @@ -109,7 +180,12 @@ This macro extends [`Unitful.abbr`](@ref) so that the reference unit can be displayed in an abbreviated format. If `tf == true`, this macro generates symbols for every power of ten of the unit, using the standard SI prefixes. A `dimension` must be given ([`Unitful.Dimensions`](@ref) object) that specifies the dimension -of the reference unit. +of the reference unit. If `autodocs == true`, autogenerated docstrings for +SI-prefixed units will be added. This option has no effect when 'tf == false'. + +!!! compat "Unitful 1.10" + Documenting the resulting unit by adding a docstring before the `@refunit` call requires + Unitful 1.10 or later. The `autodocs` argument also requires Unitful 1.10 or later. In principle, users can use this macro, but it probably does not make much sense to do so. If you define a new (probably unphysical) dimension using @@ -128,7 +204,7 @@ Usage example: `@refunit m "m" Meter 𝐋 true` This example, found in `src/pkgdefaults.jl`, generates `km`, `m`, `cm`, ... """ -macro refunit(symb, abbr, name, dimension, tf) +macro refunit(symb, abbr, name, dimension, tf, autodocs=false) expr = Expr(:block) n = Meta.quot(Symbol(name)) @@ -138,11 +214,11 @@ macro refunit(symb, abbr, name, dimension, tf) if tf push!(expr.args, quote - $Unitful.@prefixed_unit_symbols $symb $name $dimension (1.0, 1) + Base.@__doc__ $Unitful.@prefixed_unit_symbols $symb $name $dimension (1.0, 1) $autodocs end) else push!(expr.args, quote - $Unitful.@unit_symbols $symb $name $dimension (1.0, 1) + Base.@__doc__ $Unitful.@unit_symbols $symb $name $dimension (1.0, 1) end) end @@ -155,10 +231,16 @@ macro refunit(symb, abbr, name, dimension, tf) end """ - @unit(symb,abbr,name,equals,tf) + @unit(symb,abbr,name,equals,tf,autodocs=false) Define a unit. Rather than specifying a dimension like in [`@refunit`](@ref), `equals` should be a [`Unitful.Quantity`](@ref) equal to one of the unit being defined. If `tf == true`, symbols will be made for each power-of-ten prefix. +If `autodocs == true`, autogenerated docstrings for SI-prefixed units will be added. +This option has no effect when `tf == false`. + +!!! compat "Unitful 1.10" + Documenting the resulting unit by adding a docstring before the `@unit` call requires + Unitful 1.10 or later. The `autodocs` argument also requires Unitful 1.10 or later. Returns the [`Unitful.FreeUnits`](@ref) object to which `symb` is bound. @@ -166,7 +248,7 @@ Usage example: `@unit mi "mi" Mile (201168//125)*m false` This example will *not* generate `kmi` (kilomiles). """ -macro unit(symb,abbr,name,equals,tf) +macro unit(symb,abbr,name,equals,tf,autodocs=false) expr = Expr(:block) n = Meta.quot(Symbol(name)) @@ -180,11 +262,11 @@ macro unit(symb,abbr,name,equals,tf) if tf push!(expr.args, quote - $Unitful.@prefixed_unit_symbols $symb $name $d $basef + Base.@__doc__ $Unitful.@prefixed_unit_symbols $symb $name $d $basef $autodocs end) else push!(expr.args, quote - $Unitful.@unit_symbols $symb $name $d $basef + Base.@__doc__ $Unitful.@unit_symbols $symb $name $d $basef end) end @@ -200,11 +282,15 @@ end Macro for easily defining affine units. `offset` gives the zero of the relative scale in terms of an absolute scale; the scaling is the same as the absolute scale. Example: `@affineunit Β°C "Β°C" (27315//100)K` is used internally to define degrees Celsius. + +!!! compat "Unitful 1.10" + Documenting the resulting unit by adding a docstring before the `@affineunit` call + requires Unitful 1.10 or later. """ macro affineunit(symb, abbr, offset) s = Symbol(symb) return esc(quote - const global $s = $affineunit($offset) + Base.@__doc__ const global $s = $affineunit($offset) $Base.show(io::$IO, ::$genericunit($s)) = $print(io, $abbr) end) end @@ -224,23 +310,46 @@ function basefactors_expr(m::Module, n, basefactor) end """ - @prefixed_unit_symbols(symb,name,dimension,basefactor) + @prefixed_unit_symbols(symb,name,dimension,basefactor,autodocs=false) Not called directly by the user. Given a unit symbol and a unit's name, -will define units for each possible SI power-of-ten prefix on that unit. +will define units for each possible SI power-of-ten prefix on that unit. If +`autodocs == true`, it will automatically generate docstrings for these units. -Example: `@prefixed_unit_symbols m Meter 𝐋 (1.0,1)` results in `nm`, `cm`, `m`, `km`, ... -all getting defined in the calling namespace. +!!! compat "Unitful 1.10" + Documenting the resulting unit by adding a docstring before the `@prefixed_unit_symbols` + call requires Unitful 1.10 or later. The `autodocs` argument also requires Unitful 1.10 + or later. + +Example: `@prefixed_unit_symbols m Meter 𝐋 (1.0,1) true` results in `nm`, `cm`, `m`, `km`, ... +all getting defined in the calling namespace, with docstrings automatically defined for SI-prefixed units. """ -macro prefixed_unit_symbols(symb,name,user_dimension,basefactor) +macro prefixed_unit_symbols(symb,name,user_dimension,basefactor,autodocs=false) expr = Expr(:block) n = Meta.quot(Symbol(name)) for (k,v) in prefixdict s = Symbol(v,symb) u = :($Unit{$n, $user_dimension}($k,1//1)) - ea = quote - $(basefactors_expr(__module__, n, basefactor)) - const global $s = $FreeUnits{($u,), $dimension($u), $nothing}() + if k == 0 + ea = quote + $(basefactors_expr(__module__, n, basefactor)) + Base.@__doc__ const global $s = $FreeUnits{($u,), $dimension($u), $nothing}() + end + else + docstring1 = """ + $__module__.$s + + A prefixed unit, equal to 10^$k $symb. + + Dimension: """ + docstring2 = "\n\nSee also: [`$__module__.$symb`](@ref)." + ea = quote + $(basefactors_expr(__module__, n, basefactor)) + const global $s = $FreeUnits{($u,), $dimension($u), $nothing}() + if $autodocs + @doc $docstring1*string($user_dimension)*$docstring2 $s + end + end end push!(expr.args, ea) end @@ -261,6 +370,10 @@ end Not called directly by the user. Given a unit symbol and a unit's name, will define units without SI power-of-ten prefixes. +!!! compat "Unitful 1.10" + Documenting the resulting unit by adding a docstring before the `@unit_symbols` call + requires Unitful 1.10 or later. + Example: `@unit_symbols ft Foot 𝐋` results in `ft` getting defined but not `kft`. """ macro unit_symbols(symb,name,user_dimension,basefactor) @@ -269,7 +382,7 @@ macro unit_symbols(symb,name,user_dimension,basefactor) u = :($Unit{$n, $user_dimension}(0,1//1)) esc(quote $(basefactors_expr(__module__, n, basefactor)) - const global $s = $FreeUnits{($u,), $dimension($u), $nothing}() + Base.@__doc__ const global $s = $FreeUnits{($u,), $dimension($u), $nothing}() end) end diff --git a/test/runtests.jl b/test/runtests.jl index 59b226ea..281fa8ce 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1843,6 +1843,98 @@ end end end +module DocUnits + using Unitful + using Unitful: 𝐋 + "dimension docs" + @dimension 𝐃 "𝐃" DocDimension true + @derived_dimension DerivedDocDimension 𝐃*𝐋 true + "refunit docs" + @refunit dRefFoo "dRefFoo" DRefFoo 𝐃 true true + "unit docs" + @unit dFoo "dFoo" DFoo 1*dRefFoo*u"m" true true +end + +@testset "Docs" begin + @test string(@doc DocUnits.𝐃) == "dimension docs\n" + @test string(@doc DocUnits.dRefFoo) == "refunit docs\n" + @test string(@doc DocUnits.dFoo) == "unit docs\n" + @test string(@doc DocUnits.DocDimension) == """ + ``` + $(@__MODULE__).DocUnits.DocDimension{T, U} + ``` + + A supertype for quantities and levels of dimension [`$(@__MODULE__).DocUnits.𝐃`](@ref) with a value of type `T` and units `U`. + + See also: [`$(@__MODULE__).DocUnits.𝐃`](@ref), `Unitful.Quantity`, `Unitful.Level`. + """ + @test string(@doc DocUnits.DocDimensionUnits) == """ + ``` + $(@__MODULE__).DocUnits.DocDimensionUnits{U} + ``` + + A supertype for units of dimension [`$(@__MODULE__).DocUnits.𝐃`](@ref). Equivalent to `Unitful.Units{U, $(@__MODULE__).DocUnits.𝐃}`. + + See also: [`$(@__MODULE__).DocUnits.𝐃`](@ref), `Unitful.Units`. + """ + @test string(@doc DocUnits.DocDimensionFreeUnits) == """ + ``` + $(@__MODULE__).DocUnits.DocDimensionFreeUnits{U} + ``` + + A supertype for `Unitful.FreeUnits` of dimension [`$(@__MODULE__).DocUnits.𝐃`](@ref). Equivalent to `Unitful.FreeUnits{U, $(@__MODULE__).DocUnits.𝐃}`. + + See also: [`$(@__MODULE__).DocUnits.𝐃`](@ref). + """ + @test string(@doc DocUnits.DerivedDocDimension) == """ + ``` + $(@__MODULE__).DocUnits.DerivedDocDimension{T, U} + ``` + + A supertype for quantities and levels of dimension `𝐃 * 𝐋` with a value of type `T` and units `U`. + + See also: `Unitful.Quantity`, `Unitful.Level`. + """ + @test string(@doc DocUnits.DerivedDocDimensionUnits) == """ + ``` + $(@__MODULE__).DocUnits.DerivedDocDimensionUnits{U} + ``` + + A supertype for units of dimension `𝐃 * 𝐋`. Equivalent to `Unitful.Units{U, 𝐃 * 𝐋}`. + + See also: `Unitful.Units`. + """ + @test string(@doc DocUnits.DerivedDocDimensionFreeUnits) == """ + ``` + $(@__MODULE__).DocUnits.DerivedDocDimensionFreeUnits{U} + ``` + + A supertype for `Unitful.FreeUnits` of dimension `𝐃 * 𝐋`. Equivalent to `Unitful.FreeUnits{U, 𝐃 * 𝐋}`. + """ + @test string(@doc DocUnits.kdFoo) == """ + ``` + $(@__MODULE__).DocUnits.kdFoo + ``` + + A prefixed unit, equal to 10^3 dFoo. + + Dimension: 𝐃 𝐋 + + See also: [`$(@__MODULE__).DocUnits.dFoo`](@ref). + """ + @test string(@doc DocUnits.kdRefFoo) == """ + ``` + $(@__MODULE__).DocUnits.kdRefFoo + ``` + + A prefixed unit, equal to 10^3 dRefFoo. + + Dimension: 𝐃 + + See also: [`$(@__MODULE__).DocUnits.dRefFoo`](@ref). + """ +end + # Test precompiled Unitful extension modules load_path = mktempdir() load_cache_path = mktempdir() From c504c5f5acdd529184a9426644876158350330d0 Mon Sep 17 00:00:00 2001 From: Alexander Date: Wed, 1 Dec 2021 19:34:24 +0300 Subject: [PATCH 20/34] fix range eltype (#503) --- src/range.jl | 2 +- test/runtests.jl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/range.jl b/src/range.jl index e65882b6..354f1de7 100644 --- a/src/range.jl +++ b/src/range.jl @@ -109,7 +109,7 @@ broadcasted(::DefaultArrayStyle{1}, ::typeof(*), x::AbstractQuantity, r::Abstrac const BCAST_PROPAGATE_CALLS = Union{typeof(upreferred), typeof(ustrip), Units} broadcasted(::DefaultArrayStyle{1}, ::typeof(*), r::AbstractRange, x::Ref{<:Units}) = r * x[] broadcasted(::DefaultArrayStyle{1}, ::typeof(*), x::Ref{<:Units}, r::AbstractRange) = x[] * r -broadcasted(::DefaultArrayStyle{1}, x::BCAST_PROPAGATE_CALLS, r::StepRangeLen) = StepRangeLen(x(r.ref), x(r.step), r.len, r.offset) +broadcasted(::DefaultArrayStyle{1}, x::BCAST_PROPAGATE_CALLS, r::StepRangeLen) = StepRangeLen{typeof(x(zero(eltype(r))))}(x(r.ref), x(r.step), r.len, r.offset) broadcasted(::DefaultArrayStyle{1}, x::BCAST_PROPAGATE_CALLS, r::StepRange) = StepRange(x(r.start), x(r.step), x(r.stop)) broadcasted(::DefaultArrayStyle{1}, x::BCAST_PROPAGATE_CALLS, r::LinRange) = LinRange(x(r.start), x(r.stop), r.len) broadcasted(::DefaultArrayStyle{1}, ::typeof(|>), r::AbstractRange, x::Ref{<:BCAST_PROPAGATE_CALLS}) = broadcasted(DefaultArrayStyle{1}(), x[], r) diff --git a/test/runtests.jl b/test/runtests.jl index 281fa8ce..3c33fb6f 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1200,6 +1200,7 @@ end @test mm.((1:2:5) .* cm) === 10mm:20mm:50mm @test @inferred((1:2:5) .* km .|> upreferred) === 1000m:2000m:5000m @test @inferred((1:2:5) .* cm .|> mm .|> ustrip) === 10:20:50 + @test @inferred((1f0:2f0:5f0) .* cm .|> mm .|> ustrip) === 10f0:20f0:50f0 end end @testset "> Arrays" begin From 0d3b586a0b9999d8491c5c59bcd691b77eccd512 Mon Sep 17 00:00:00 2001 From: Christopher Rackauckas Date: Mon, 27 Dec 2021 06:19:03 -0500 Subject: [PATCH 21/34] Fix some major invalidations to improve compile times (#509) * Fix some major invalidations to improve compile times Unitful.jl was flagged as a major invalidator of compilation downstream. Test: ```julia # From: https://timholy.github.io/SnoopCompile.jl/stable/snoopr/ using SnoopCompile invalidations = @snoopr begin using DifferentialEquations function lorenz(du,u,p,t) du[1] = 10.0(u[2]-u[1]) du[2] = u[1]*(28.0-u[3]) - u[2] du[3] = u[1]*u[2] - (8/3)*u[3] end u0 = [1.0;0.0;0.0] tspan = (0.0,100.0) prob = ODEProblem(lorenz,u0,tspan) alg = Rodas5() tinf = solve(prob,alg) end; trees = SnoopCompile.invalidation_trees(invalidations); @show length(SnoopCompile.uinvalidated(invalidations)) # show total invalidations show(trees[end]) # show the most invalidated method ``` This method won the prize for the absolute most invalidations :tada:. But I think the bigger issue is that it simply doesn't follow Julia semantics. It fixes the types for issue https://github.com/PainterQubits/Unitful.jl/issues/127 in a way that gives a stricter type than Julia would do in the normal cases (which is why the invalidation occurs). After this PR, heterogeneous arrays of numbers with Quantity in there act normally, and compile times are back to normal. Here's a showcase of it being normal: ```julia using Unitful, Test m = u"m" cm = u"cm" b = Union{Complex,Float64}[0 + 0im, 0.0] @test b + b == b @test b .+ b == b @test eltype(b+b) === Number b = Number[0 + 0im, 0.0] @test b + b == b @test b .+ b == b @test eltype(b+b) === Number b = [0.0, 0.0m] @test b + b == b @test b .+ b == b @test eltype(b+b) === Number ``` * Update promotion.jl --- src/promotion.jl | 2 -- test/runtests.jl | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/promotion.jl b/src/promotion.jl index 0395e3e8..71e0f066 100644 --- a/src/promotion.jl +++ b/src/promotion.jl @@ -115,5 +115,3 @@ Base.promote_rule(::Type{Quantity{T}}, ::Type{Quantity{S,D,U}}) where {T,S,D,U} Base.promote_rule(::Type{Quantity{S,D,U}}, ::Type{Quantity{T}}) where {T,S,D,U} = Quantity{promote_type(T,S)} - -Base.promote_typejoin(::Type{T}, ::Type{Quantity{T,D,U}}) where {T,D,U} = Quantity{T} diff --git a/test/runtests.jl b/test/runtests.jl index 3c33fb6f..e8f1cc82 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1263,7 +1263,7 @@ end b = [0.0, 0.0m] @test b + b == b @test b .+ b == b - @test eltype(b+b) === Quantity{Float64} + @test eltype(b+b) === Number # Dimensionless quantities @test @inferred([1mm/m] + [1.0cm/m]) == [0.011] From 548aa14665b7d200e5cdfcbda6d53e9bfa5a4b81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Mon, 27 Dec 2021 16:14:31 +0000 Subject: [PATCH 22/34] Release v1.10.0 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index faa4d8f1..9bc27980 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Unitful" uuid = "1986cc42-f94f-5a68-af5c-568840ba703d" -version = "1.9.2" +version = "1.10.0" [deps] ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9" From 75f222be21d851970cc178d62110c22bef0ac4ad Mon Sep 17 00:00:00 2001 From: Jeff Fessler Date: Sun, 2 Jan 2022 10:13:06 -0500 Subject: [PATCH 23/34] Fix #465 for isapprox with complex arrays (#468) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * deg2rad and rad2deg * v1.9 * Update src/pkgdefaults.jl Co-authored-by: MosΓ¨ Giordano * fix #465 * test, v1.9.1 * Update src/quantities.jl Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> * positive test * Update test/runtests.jl Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> Co-authored-by: MosΓ¨ Giordano Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> --- Project.toml | 2 +- src/quantities.jl | 26 +++++++++++++++++++++----- test/runtests.jl | 5 +++++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/Project.toml b/Project.toml index 9bc27980..cb530324 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Unitful" uuid = "1986cc42-f94f-5a68-af5c-568840ba703d" -version = "1.10.0" +version = "1.10.1" [deps] ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9" diff --git a/src/quantities.jl b/src/quantities.jl index 96d3b7f7..9e44f568 100644 --- a/src/quantities.jl +++ b/src/quantities.jl @@ -270,18 +270,31 @@ for (i,j) in zip((:<, :isless), (:_lt, :_isless)) end Base.rtoldefault(::Type{<:AbstractQuantity{T,D,U}}) where {T,D,U} = Base.rtoldefault(T) -isapprox(x::AbstractQuantity{T,D,U}, y::AbstractQuantity{T,D,U}; atol=zero(Quantity{real(T),D,U}), kwargs...) where {T,D,U} = - isapprox(x.val, y.val; atol=uconvert(unit(y), atol).val, kwargs...) + +function isapprox( + x::AbstractQuantity{T,D,U}, + y::AbstractQuantity{T,D,U}; + atol = zero(Quantity{real(T),D,U}), + kwargs..., +) where {T,D,U} + return isapprox(x.val, y.val; atol=ustrip(unit(y), atol), kwargs...) +end + function isapprox(x::AbstractQuantity, y::AbstractQuantity; kwargs...) dimension(x) != dimension(y) && return false return isapprox(promote(x,y)...; kwargs...) end + isapprox(x::AbstractQuantity, y::Number; kwargs...) = isapprox(promote(x,y)...; kwargs...) isapprox(x::Number, y::AbstractQuantity; kwargs...) = isapprox(y, x; kwargs...) -function isapprox(x::AbstractArray{<:AbstractQuantity{T1,D,U1}}, - y::AbstractArray{<:AbstractQuantity{T2,D,U2}}; rtol::Real=Base.rtoldefault(T1,T2,0), - atol=zero(Quantity{T1,D,U1}), norm::Function=norm) where {T1,D,U1,T2,U2} +function isapprox( + x::AbstractArray{<:AbstractQuantity{T1,D,U1}}, + y::AbstractArray{<:AbstractQuantity{T2,D,U2}}; + rtol::Real=Base.rtoldefault(T1,T2,0), + atol=zero(Quantity{real(T1),D,U1}), + norm::Function=norm, +) where {T1,D,U1,T2,U2} d = norm(x - y) if isfinite(d) @@ -291,8 +304,10 @@ function isapprox(x::AbstractArray{<:AbstractQuantity{T1,D,U1}}, return all(ab -> isapprox(ab[1], ab[2]; rtol=rtol, atol=atol), zip(x, y)) end end + isapprox(x::AbstractArray{S}, y::AbstractArray{T}; kwargs...) where {S <: AbstractQuantity,T <: AbstractQuantity} = false + function isapprox(x::AbstractArray{S}, y::AbstractArray{N}; kwargs...) where {S <: AbstractQuantity,N <: Number} if dimension(N) == dimension(S) @@ -301,6 +316,7 @@ function isapprox(x::AbstractArray{S}, y::AbstractArray{N}; false end end + isapprox(y::AbstractArray{N}, x::AbstractArray{S}; kwargs...) where {S <: AbstractQuantity,N <: Number} = isapprox(x,y; kwargs...) diff --git a/test/runtests.jl b/test/runtests.jl index e8f1cc82..eb30904a 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -760,6 +760,11 @@ end @test isapprox(1.0u"m", 1.1u"m"; rtol=0.2) @test !isapprox(1.0u"m", 1.1u"m"; rtol=0.05) + # Issue 465: + z = fill((1+im)m, 2, 3) + @test !isapprox(z, 2z) + @test isapprox(z, z * (1 + 1e-15)) + # Test eps @test eps(1.0u"s") == eps(1.0)u"s" @test eps(typeof(1.0u"s")) == eps(Float64) From 46cd2ae0800643fffccbe997c0b9625b00e95551 Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Wed, 26 Jan 2022 14:46:28 +0100 Subject: [PATCH 24/34] Fix `range` implementation on Julia master and resolve method ambiguities (#514) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * _range(start, ::Nothing, ::Nothing, len) * _range(::Nothing, ::Nothing, stop, len) * Add tests for ranges with complex elements * Use modern syntax * Remove unnecessary `<:Real` * Fix range(start::Quantity{BigFloat}; step::Quantity{BigFloat}; length) * Fix for missing _rangestyle on 1.8 * Remove `real` * Use `step` everywhere (instead of `st`) * Fix range(;step, stop, len) on Julia master * Fix range(;stop, step, length) for mixed number/quantity * Add some newlines and comments * Rename _range_step_stop_length β†’ _unitful_step_stop_length To avoid confusion with Base.range_step_stop_length * Refactor _range(start, ::Nothing, stop, length) * Rename 3-arg `Base._range` β†’ `_unitful_start_stop_length` (`Base._range` always has 4 arguments) * Move promotion to `_unitful_start_stop_length` * Refactor _range(start, step, ::Nothing, length) * Resolve method ambiguity on Julia β‰₯ 1.7 * Simplify implementation * Use modern `where` syntax for `colon` * Add two-argument colon for dimensionless quantities --- src/range.jl | 124 ++++++++++++++++++++++++++++++++--------------- test/runtests.jl | 67 +++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 40 deletions(-) diff --git a/src/range.jl b/src/range.jl index 354f1de7..cbdeef8b 100644 --- a/src/range.jl +++ b/src/range.jl @@ -7,46 +7,79 @@ import Base.Broadcast: DefaultArrayStyle, broadcasted *(y::Units, r::AbstractRange) = *(r,y) *(r::AbstractRange, y::Units, z::Units...) = *(r, *(y,z...)) -Base._range(start::Quantity{<:Real}, ::Nothing, stop, len::Integer) = - _range(promote(start, stop)..., len) -Base._range(start, ::Nothing, stop::Quantity{<:Real}, len::Integer) = - _range(promote(start, stop)..., len) -Base._range(start::Quantity{<:Real}, ::Nothing, stop::Quantity{<:Real}, len::Integer) = - _range(promote(start, stop)..., len) -(Base._range(start::T, ::Nothing, stop::T, len::Integer) where (T<:Quantity{<:Real})) = - LinRange{T}(start, stop, len) -(Base._range(start::T, ::Nothing, stop::T, len::Integer) where (T<:Quantity{<:Integer})) = - Base._linspace(Float64, ustrip(start), ustrip(stop), len, 1)*unit(T) -function Base._range(start::T, ::Nothing, stop::T, len::Integer) where (T<:Quantity{S} - where S<:Union{Float16,Float32,Float64}) - range(ustrip(start), stop=ustrip(stop), length=len) * unit(T) -end -function _range(start::Quantity{T}, stop::Quantity{T}, len::Integer) where {T} +# start, stop, length +Base._range(start::Quantity, ::Nothing, stop, len::Integer) = + _unitful_start_stop_length(start, stop, len) +Base._range(start, ::Nothing, stop::Quantity, len::Integer) = + _unitful_start_stop_length(start, stop, len) +Base._range(start::Quantity, ::Nothing, stop::Quantity, len::Integer) = + _unitful_start_stop_length(start, stop, len) +function _unitful_start_stop_length(start, stop, len) dimension(start) != dimension(stop) && throw(DimensionError(start, stop)) - Base._range(start, nothing, stop, len) + a, b = promote(start, stop) + Base._range(a, nothing, b, len) end -function Base._range(a::T, st::T, ::Nothing, len::Integer) where (T<:Quantity{S} - where S<:Union{Float16,Float32,Float64}) - return Base._range(ustrip(a), ustrip(st), nothing, len) * unit(T) +Base._range(start::T, ::Nothing, stop::T, len::Integer) where {T<:Quantity} = + LinRange{T}(start, stop, len) +Base._range(start::T, ::Nothing, stop::T, len::Integer) where {T<:Quantity{<:Integer}} = + Base._linspace(Float64, ustrip(start), ustrip(stop), len, 1)*unit(T) +Base._range(start::T, ::Nothing, stop::T, len::Integer) where {T<:Quantity{<:Base.IEEEFloat}} = + Base._range(ustrip(start), nothing, ustrip(stop), len) * unit(T) + +# start, step, length +Base._range(a::T, step::T, ::Nothing, len::Integer) where {T<:Quantity{<:Base.IEEEFloat}} = + Base._range(ustrip(a), ustrip(step), nothing, len) * unit(T) +Base._range(a::T, step::T, ::Nothing, len::Integer) where {T<:Quantity{<:AbstractFloat}} = + StepRangeLen{typeof(step*len),typeof(a),typeof(step)}(a, step, len) +Base._range(a::T, step::T, ::Nothing, len::Integer) where {T<:Quantity} = + @static if VERSION β‰₯ v"1.8.0-DEV" + Base.range_start_step_length(a, step, len) + else + Base._rangestyle(OrderStyle(a), ArithmeticStyle(a), a, step, len) + end +Base._range(a::Quantity{<:Real}, step::Quantity{<:AbstractFloat}, ::Nothing, len::Integer) = + _unitful_start_step_length(float(a), step, len) +Base._range(a::Quantity{<:AbstractFloat}, step::Quantity{<:Real}, ::Nothing, len::Integer) = + _unitful_start_step_length(a, float(step), len) +Base._range(a::Quantity{<:AbstractFloat}, step::Quantity{<:AbstractFloat}, ::Nothing, len::Integer) = + _unitful_start_step_length(a, step, len) +Base._range(a, step::Quantity, ::Nothing, len::Integer) = + _unitful_start_step_length(a, step, len) +Base._range(a::Quantity, step, ::Nothing, len::Integer) = + _unitful_start_step_length(a, step, len) +Base._range(a::Quantity, step::Quantity, ::Nothing, len::Integer) = + _unitful_start_step_length(a, step, len) +function _unitful_start_step_length(start, step, len) + dimension(start) != dimension(step) && throw(DimensionError(start,step)) + Base._range(promote(start, uconvert(unit(start), step))..., nothing, len) end -Base._range(a::Quantity{<:Real}, st::Quantity{<:AbstractFloat}, ::Nothing, len::Integer) = - Base._range(float(a), st, nothing, len) -Base._range(a::Quantity{<:AbstractFloat}, st::Quantity{<:Real}, ::Nothing, len::Integer) = - Base._range(a, float(st), nothing, len) -function Base._range(a::Quantity{<:AbstractFloat}, st::Quantity{<:AbstractFloat}, ::Nothing, len::Integer) - dimension(a) != dimension(st) && throw(DimensionError(a, st)) - Base._range(promote(a, uconvert(unit(a), st))..., nothing, len) + +# start, length (step defaults to 1) +Base._range(a::Quantity, ::Nothing, ::Nothing, len::Integer) = + Base._range(a, one(a), nothing, len) + +# step, stop, length +@static if VERSION β‰₯ v"1.7" + Base._range(::Nothing, step, stop::Quantity, len::Integer) = + _unitful_step_stop_length(step, stop, len) + Base._range(::Nothing, step::Quantity, stop, len::Integer) = + _unitful_step_stop_length(step, stop, len) + Base._range(::Nothing, step::Quantity, stop::Quantity, len::Integer) = + _unitful_step_stop_length(step, stop, len) + Base._range(::Nothing, step::Quantity, ::Nothing, len::Integer) = + Base.range_error(nothing, step, nothing, len) + function _unitful_step_stop_length(step, stop, len) + dimension(stop) != dimension(step) && throw(DimensionError(stop,step)) + Base.range_step_stop_length(promote(uconvert(unit(stop), step), stop)..., len) + end end -Base._range(a::Quantity, st::Real, ::Nothing, len::Integer) = - Base._range(promote(a, uconvert(unit(a), st))..., nothing, len) -Base._range(a::Real, st::Quantity, ::Nothing, len::Integer) = - Base._range(promote(a, uconvert(unit(a), st))..., nothing, len) -# the following is needed to give sane error messages when doing e.g. range(1Β°, 2V, 5) -function Base._range(a::Quantity, step, ::Nothing, len::Integer) - dimension(a) != dimension(step) && throw(DimensionError(a,step)) - _a, _step = promote(a, uconvert(unit(a), step)) - return Base._rangestyle(OrderStyle(_a), ArithmeticStyle(_a), _a, _step, len) + +# stop, length (step defaults to 1) +@static if VERSION β‰₯ v"1.7" + Base._range(::Nothing, ::Nothing, stop::Quantity, len::Integer) = + Base._range(nothing, one(stop), stop, len) end + *(r::AbstractRange, y::Units) = range(first(r)*y, step=step(r)*y, length=length(r)) # first promote start and stop, leaving step alone @@ -70,7 +103,7 @@ end OrderStyle(::Type{<:AbstractQuantity{T}}) where T = OrderStyle(T) ArithmeticStyle(::Type{<:AbstractQuantity{T}}) where T = ArithmeticStyle(T) -(colon(start::T, step::T, stop::T) where T <: Quantity{<:Real}) = +colon(start::T, step::T, stop::T) where {T<:Quantity{<:Real}} = _colon(OrderStyle(T), ArithmeticStyle(T), start, step, stop) _colon(::Ordered, ::Any, start::T, step, stop::T) where {T} = StepRange(start, step, stop) _colon(::Ordered, ::ArithmeticRounds, start::T, step, stop::T) where {T} = @@ -83,10 +116,20 @@ _colon(::Any, ::Any, start::T, step, stop::T) where {T} = *(x::Base.TwicePrecision, y::Quantity) = (x * ustrip(y)) * unit(y) uconvert(y, x::Base.TwicePrecision) = Base.TwicePrecision(uconvert(y, x.hi), uconvert(y, x.lo)) -function colon(start::T, step::T, stop::T) where (T<:Quantity{S} - where S<:Union{Float16,Float32,Float64}) - # This will always return a StepRangeLen - return colon(ustrip(start), ustrip(step), ustrip(stop)) * unit(T) +colon(start::T, step::T, stop::T) where {T<:Quantity{<:Base.IEEEFloat}} = + colon(ustrip(start), ustrip(step), ustrip(stop)) * unit(T) # This will always return a StepRangeLen + +# two-argument colon +colon(start, stop::Quantity) = _unitful_start_stop(start, stop) +colon(start::Quantity, stop) = _unitful_start_stop(start, stop) +colon(start::Quantity, stop::Quantity) = _unitful_start_stop(start, stop) +function _unitful_start_stop(start, stop) + dimension(start) != dimension(stop) && throw(DimensionError(start, stop)) + colon(promote(start, stop)...) +end +function colon(start::T, stop::T) where {T<:Quantity} + step = uconvert(unit(start), one(start)) + colon(promote(start, step, stop)...) end # No need to confuse things by changing the type once units are on there, @@ -95,6 +138,7 @@ end StepRangeLen{typeof(zero(eltype(r))*y)}(r.ref*y, r.step*y, length(r), r.offset) *(r::LinRange, y::Units) = LinRange(r.start*y, r.stop*y, length(r)) *(r::StepRange, y::Units) = StepRange(r.start*y, r.step*y, r.stop*y) +*(r::AbstractUnitRange, y::Units) = StepRange(first(r)*y, oneunit(first(r))*y, last(r)*y) function /(x::Base.TwicePrecision, v::Quantity) x / Base.TwicePrecision(oftype(ustrip(x.hi)/ustrip(v)*unit(v), v)) end diff --git a/test/runtests.jl b/test/runtests.jl index eb30904a..b667079d 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1146,6 +1146,7 @@ end @test (-2.0Hz:1.0Hz:2.0Hz)/1.0Hz == -2.0:1.0:2.0 # issue 160 @test (range(0, stop=2, length=5) * u"Β°")[2:end] == range(0.5, stop=2, length=4) * u"Β°" # issue 241 + @test range(big(1.0)m, step=big(1.0)m, length=5) == (big(1.0):big(1.0):big(5.0))*m end @testset ">> LinSpace" begin # Not using Compat.range for these because kw args don't infer in julia 0.6.2 @@ -1207,6 +1208,72 @@ end @test @inferred((1:2:5) .* cm .|> mm .|> ustrip) === 10:20:50 @test @inferred((1f0:2f0:5f0) .* cm .|> mm .|> ustrip) === 10f0:20f0:50f0 end + @testset ">> quantities and non-quantities" begin + @test range(1, step=1m/mm, length=5) == 1:1000:4001 + @test range(1, step=1mm/m, length=5) == (1//1):(1//1000):(251//250) + @test eltype(range(1, step=1m/mm, length=5)) == Int + @test eltype(range(1, step=1mm/m, length=5)) == Rational{Int} + @test range(1m/mm, step=1, length=5) == ((1//1):(1//1000):(251//250)) * m/mm + @test range(1mm/m, step=1, length=5) == (1:1000:4001) * mm/m + @test eltype(range(1m/mm, step=1, length=5)) == typeof((1//1)m/mm) + @test eltype(range(1mm/m, step=1, length=5)) == typeof(1mm/m) + end + @testset ">> complex" begin + @test range((1+2im)m, step=(1+2im)m, length=5) == range(1+2im, step=1+2im, length=5) * m + @test range((1+2im)m, step=(1+2im)mm, length=5) == range(1//1+(2//1)im, step=1//1000+(1//500)im, length=5) * m + @test range((1.0+2.0im)m, stop=(3.0+4.0im)m, length=5) == LinRange(1.0+2.0im, 3.0+4.0im, 5) * m + @test range((1.0+2.0im)mm, stop=(3.0+4.0im)m, length=3) == LinRange(0.001+0.002im, 3.0+4.0im, 3) * m + end + @testset ">> step defaults to 1" begin + @test range(1.0mm/m, length=5) == (1.0mm/m):(1000.0mm/m):(4001.0mm/m) + @test range((1+2im)mm/m, length=5) == range(1+2im, step=1000, length=5)*mm/m + @test_throws DimensionError range(1.0m, length=5) + @test_throws DimensionError range((1+2im)m, length=5) + @test (1mm/m):(5001mm/m) == (1:1000:5001) * mm/m + @test (1m/mm):(5m/mm) == (1//1:1//1000:5//1) * m/mm + @test (1mm/m):(1m/mm) == 1//1000:999001//1000 + @test (1m/mm):(1mm/m) == 1000//1:999//1 + @test (1.0mm/m):(5001mm/m) == (1.0:1000.0:5001.0) * mm/m + @test (1m/mm):(5.0m/mm) == (1.0:0.001:5.0) * m/mm + @test (1.0mm/m):(1m/mm) == 0.001:999.001 + @test (1m/mm):(1.0mm/m) == 1000.0:1.0:999.0 + @test_throws DimensionError (1m):(1m) + @test_throws DimensionError (1m):(1000cm) + @test_throws DimensionError (1m):(1s) + @test (1m/cm):1 == 100:99 + @test (1m/cm):1000 == 100:1000 + @test (1m/cm):1.0 == 100.0:99.0 + @test (1.0m/cm):1000 == 100.0:1000.0 + @test_throws DimensionError (1m):1 + @test 1:(1m/mm) == 1:1000 + @test 1000:(1m/mm) == 1000:1000 + @test 1.0:(1m/mm) == 1.0:1000.0 + @test 1000:(1.0m/mm) == 1000.0:1000.0 + @test_throws DimensionError 1:(1m) + end + @static if VERSION β‰₯ v"1.7" + @testset ">> no start argument" begin + @test range(stop=1.0m, step=2.0m, length=5) == -7.0m:2.0m:1.0m + @test range(stop=1.0mm, step=1.0m, length=5) == -3999.0mm:1000.0mm:1.0mm + @test range(stop=(1.0+2.0im)mm, step=(1.0+1.0im)m, length=5) == range(stop=1.0+2.0im, step=(1000+1000im), length=5)*mm + @test range(stop=1.0mm/m, length=5) == (-3999.0mm/m):(1000.0mm/m):(1.0mm/m) + @test range(stop=(1+2im)mm/m, length=5) == range(stop=1+2im, step=1000, length=5)*mm/m + @test range(stop=1.0mm/m, step=1, length=5) == (-3999.0mm/m):(1000.0mm/m):(1.0mm/m) + @test_throws DimensionError range(stop=1.0m, step=1V, length=5) + @test_throws DimensionError range(stop=(1+2im)m, step=1V, length=5) + @test_throws DimensionError range(stop=1.0m, length=5) + @test_throws DimensionError range(stop=(1+2im)m, length=5) + @test range(stop=1, step=1m/mm, length=5) == -3999:1000:1 + @test range(stop=1, step=1mm/m, length=5) == (249//250):(1//1000):(1//1) + @test eltype(range(stop=1, step=1m/mm, length=5)) == Int + @test eltype(range(stop=1, step=1mm/m, length=5)) == Rational{Int} + @test range(stop=1m/mm, step=1, length=5) == ((249//250):(1//1000):(1//1)) * m/mm + @test range(stop=1mm/m, step=1, length=5) == (-3999:1000:1) * mm/m + @test eltype(range(stop=1m/mm, step=1, length=5)) == typeof((1//1)m/mm) + @test eltype(range(stop=1mm/m, step=1, length=5)) == typeof(1mm/m) + @test_throws ArgumentError range(step=1m, length=5) + end + end end @testset "> Arrays" begin @testset ">> Array multiplication" begin From 6ca16b6f86e5dc308bc509139d31de8d510e510d Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Wed, 26 Jan 2022 15:02:23 +0100 Subject: [PATCH 25/34] =?UTF-8?q?Remove=20unnecessary=20code=20related=20t?= =?UTF-8?q?o=20encoding=20of=20=CE=BC=20(#511)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add tests for encoding of ΞΌ * Remove unnecessary code * Use U+03BC everywhere * Same changes for U+025B/U+03B5 --- src/display.jl | 2 +- src/pkgdefaults.jl | 15 +++++---------- src/units.jl | 6 +++--- src/user.jl | 8 -------- test/runtests.jl | 23 +++++++++++++++++++++-- 5 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/display.jl b/src/display.jl index 249ad93f..5dfc27f2 100644 --- a/src/display.jl +++ b/src/display.jl @@ -6,7 +6,7 @@ const prefixdict = Dict( -15 => "f", -12 => "p", -9 => "n", - -6 => "ΞΌ", # tab-complete \mu, not option-m on a Mac! + -6 => "ΞΌ", -3 => "m", -2 => "c", -1 => "d", diff --git a/src/pkgdefaults.jl b/src/pkgdefaults.jl index 09a38d47..cb1788a0 100644 --- a/src/pkgdefaults.jl +++ b/src/pkgdefaults.jl @@ -302,7 +302,7 @@ const ha = Unitful.FreeUnits{(Unitful.Unit{:Are, 𝐋^2}(2, 1//1),), 𝐋^2}() \nDimension: 𝐋^3. \nSee Also: [`Unitful.cm`](@ref)." @unit L "L" Liter m^3//1000 true -for p in (:y, :z, :a, :f, :p, :n, :ΞΌ, :Β΅, :m, :c, :d, +for p in (:y, :z, :a, :f, :p, :n, :ΞΌ, :m, :c, :d, Symbol(""), :da, :h, :k, :M, :G, :T, :P, :E, :Z, :Y) Core.eval(Unitful, :(const $(Symbol(p,:l)) = $(Symbol(p,:L)))) end @@ -388,15 +388,14 @@ const c0 = 299_792_458*m/s # exact \nA quantity representing the vacuum permeability constant, defined as 4Ο€ Γ— 10^-7 H / m. \nDimension: 𝐋 𝐌 𝐈^-2 𝐓^-2. \nSee also: [`Unitful.H`](@ref), [`Unitful.m`](@ref)." -const ΞΌ0 = 4Ο€*(1//10)^7*H/m # exact (but gets promoted to Float64...) -const Β΅0 = ΞΌ0 # magnetic constant +const ΞΌ0 = 4Ο€*(1//10)^7*H/m # exact (but gets promoted to Float64...), magnetic constant " Unitful.Ξ΅0 Unitful.Ο΅0 \nA quantity representing the vacuum permittivity constant, defined as 1 / (ΞΌ0 Γ— c^2). \nDimension: 𝐈^2 𝐓^4 𝐋^-3 𝐌^-1. \nSee also: [`Unitful.ΞΌ0`](@ref), [`Unitful.c`](@ref)." -const Ι›0 = 1/(ΞΌ0*c^2) # exact, electric constant; changes here may affect -@doc @doc(Ι›0) const Ο΅0 = Ι›0 # test of issue 79. +const Ξ΅0 = 1/(ΞΌ0*c^2) # exact, electric constant; changes here may affect +@doc @doc(Ξ΅0) const Ο΅0 = Ξ΅0 # test of issue 79. " Unitful.Z0 \nA quantity representing the impedance of free space, a constant defined as ΞΌ0 Γ— c. \nDimension: 𝐋^2 𝐌 𝐈^-2 𝐓^-3. @@ -455,7 +454,6 @@ const mp = 1.672_621_923_69e-27*kg # (51) proton rest mass \nDimension: 𝐈 𝐋^2. \nSee also: [`Unitful.q`](@ref), [`Unitful.Δ§`](@ref), [`Unitful.me`](@ref)." const ΞΌB = q*Δ§/(2*me) # Bohr magneton -const Β΅B = ΞΌB " Unitful.Na \nA quantity representing Avogadro's constant, defined as exactly 6.022,140,76 Γ— 10^23 / mol. @@ -682,8 +680,6 @@ earth, a unit of acceleration, defined by standard to be exactly 9.806,65 m / s^ @logunit dBΞ© "dBΞ©" Decibel 1Ξ© @logunit dBS "dBS" Decibel 1S -const dBΒ΅V = dBΞΌV # different character encoding of ΞΌ - # TODO: some more dimensions? isrootpower_dim(::typeof(dimension(W))) = false isrootpower_dim(::typeof(dimension(V))) = true @@ -706,8 +702,7 @@ isrootpower_dim(::typeof(dimension(J))) = false # - Candela conflicts with `Base.cd` so it is not brought in (issue #102) # - Degrees: Β° -# The following line has two different character encodings for ΞΌ -const si_prefixes = (:y, :z, :a, :f, :p, :n, :ΞΌ, :Β΅, :m, :c, :d, +const si_prefixes = (:y, :z, :a, :f, :p, :n, :ΞΌ, :m, :c, :d, Symbol(""), :da, :h, :k, :M, :G, :T, :P, :E, :Z, :Y) const si_no_prefix = (:m, :s, :A, :K, :g, :mol, :rad, :sr, :Hz, :N, :Pa, #:cd, diff --git a/src/units.jl b/src/units.jl index a66a047d..f6a3f89a 100644 --- a/src/units.jl +++ b/src/units.jl @@ -18,9 +18,9 @@ sort!(linunits, by=x->tens(x)) sort!(linunits, by=x->name(x)) - # [m,m,cm,cm^2,cm^3,nm,m^4,Β΅s,Β΅s^2,s] + # [m,m,cm,cm^2,cm^3,nm,m^4,ΞΌs,ΞΌs^2,s] # reordered as: - # [nm,cm,cm^2,cm^3,m,m,m^4,Β΅s,Β΅s^2,s] + # [nm,cm,cm^2,cm^3,m,m,m^4,ΞΌs,ΞΌs^2,s] # Collect powers of a given unit into `c` c = Vector{Unit}() @@ -46,7 +46,7 @@ end end # results in: - # [nm,cm^6,m^6,Β΅s^3,s] + # [nm,cm^6,m^6,ΞΌs^3,s] d = (c...,) f = mapreduce(dimension, *, d; init=NoDims) diff --git a/src/user.jl b/src/user.jl index 78c6c8fc..bf58373f 100644 --- a/src/user.jl +++ b/src/user.jl @@ -354,14 +354,6 @@ macro prefixed_unit_symbols(symb,name,user_dimension,basefactor,autodocs=false) push!(expr.args, ea) end - # These lines allow for ΞΌ to be typed with option-m on a Mac. - s = Symbol(:Β΅, symb) - u = :($Unit{$n, $user_dimension}(-6,1//1)) - push!(expr.args, quote - $(basefactors_expr(__module__, n, basefactor)) - const global $s = $FreeUnits{($u,), $dimension($u), $nothing}() - end) - esc(expr) end diff --git a/test/runtests.jl b/test/runtests.jl index b667079d..405167fa 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -188,7 +188,7 @@ end @test uconvert(g, 1*FixedUnits(kg)) == 1000g # manual conversion okay @test (1kg, 2g, 3mg, missing) .|> g === (1000g, 2g, (3//1000)g, missing) # Issue 79: - @test isapprox(upreferred(Unitful.Ι›0), 8.85e-12u"F/m", atol=0.01e-12u"F/m") + @test isapprox(upreferred(Unitful.Ξ΅0), 8.85e-12u"F/m", atol=0.01e-12u"F/m") # Issue 261: @test 1u"rps" == 360Β°/s @test 1u"rps" == 2Ο€/s @@ -695,7 +695,7 @@ end @test @inferred(sinh(0.0rad)) == 0.0 @test @inferred(sinh(1J/N/m) + cosh(1rad)) β‰ˆ MathConstants.e - @test @inferred(tanh(1m/1Β΅m)) == 1 + @test @inferred(tanh(1m/1ΞΌm)) == 1 @test @inferred(csch(0.0Β°)) == Inf @test @inferred(sech(0K/Ra)) == 1 @test @inferred(coth(1e3m*mm^-1)) == 1 @@ -1916,6 +1916,25 @@ end end end +@testset "Encoding" begin + # Julia treats Β΅ (U+00B5) and ΞΌ (U+03BC) as the same + @test Unitful.Β΅0 === Unitful.ΞΌ0 + @test Unitful.Β΅m === Unitful.ΞΌm + @test Unitful.dBΒ΅V === Unitful.dBΞΌV + @test u"Β΅0" === u"ΞΌ0" + @test u"Β΅m" === u"ΞΌm" + @test u"dBΒ΅V" === u"dBΞΌV" + @test uparse("Β΅0") === uparse("ΞΌ0") + @test uparse("Β΅m") === uparse("ΞΌm") + @test uparse("dBΒ΅V") === uparse("dBΞΌV") + @test @doc(Unitful.Β΅m) == @doc(Unitful.ΞΌm) + # Julia treats Ι› (U+025B) and Ξ΅ (U+03B5) as the same + @test Unitful.Ι›0 === Unitful.Ξ΅0 + @test u"Ι›0" === u"Ξ΅0" + @test uparse("Ι›0") === uparse("Ξ΅0") + @test @doc(Unitful.Ι›0) == @doc(Unitful.Ξ΅0) +end + module DocUnits using Unitful using Unitful: 𝐋 From 1f19b8fd41aed3b24dda074bd10fab3c81085df2 Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Wed, 26 Jan 2022 17:03:54 +0100 Subject: [PATCH 26/34] Fix printing of `StepRangeLen` with complex elements (#513) --- src/display.jl | 12 +++++++++++- test/runtests.jl | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/display.jl b/src/display.jl index 5dfc27f2..274f555e 100644 --- a/src/display.jl +++ b/src/display.jl @@ -131,7 +131,7 @@ function show(io::IO, mime::MIME"text/plain", x::Quantity) end end -function show(io::IO, r::Union{StepRange{T},StepRangeLen{T}}) where T<:Quantity +function show(io::IO, r::StepRange{T}) where T<:Quantity a,s,b = first(r), step(r), last(r) U = unit(a) print(io, '(') @@ -145,6 +145,16 @@ function show(io::IO, r::Union{StepRange{T},StepRangeLen{T}}) where T<:Quantity show(io, U) end +function show(io::IO, r::StepRangeLen{T}) where T<:Quantity + a,s,b = first(r), step(r), last(r) + U = unit(a) + print(io, '(') + show(io, StepRangeLen(ustrip(U, a), ustrip(U, s), length(r))) + print(io, ')') + has_unit_spacing(U) && print(io,' ') + show(io, U) +end + function show(io::IO, x::typeof(NoDims)) print(io, "NoDims") end diff --git a/test/runtests.jl b/test/runtests.jl index 405167fa..f68ebd12 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1451,6 +1451,8 @@ Base.show(io::IO, ::MIME"text/plain", ::Foo) = print(io, "42.0") @test repr((1:10)*u"kg/m^3") == "(1:10) kg m^-3" @test repr((1.0:0.1:10.0)*u"kg/m^3") == "(1.0:0.1:10.0) kg m^-3" @test repr((1:10)*Β°) == "(1:10)Β°" + @test repr(range(1.0+2.0im, length=5)*u"m") == "(1.0 + 2.0im:1.0 + 0.0im:5.0 + 2.0im) m" + @test repr(range(1+2im, step=1+1im, length=5)*u"m") == "(1 + 2im:1 + 1im:5 + 6im) m" end withenv("UNITFUL_FANCY_EXPONENTS" => true) do @test repr(1.0 * u"m * s * kg^(-1//2)") == "1.0 m s kg⁻¹ᐟ²" From fc081187d65f736a1a35d9d9fcdc164ab8c0d36b Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Wed, 2 Feb 2022 19:20:44 +0100 Subject: [PATCH 27/34] Enable `zero` for arrays with non-concrete eltype (#516) --- src/quantities.jl | 24 ++++++++++++++++++++++++ test/runtests.jl | 22 ++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/quantities.jl b/src/quantities.jl index 9e44f568..b99340ff 100644 --- a/src/quantities.jl +++ b/src/quantities.jl @@ -388,6 +388,30 @@ zero(x::Type{<:AbstractQuantity{T,D}}) where {T,D} = zero(T) * upreferred(D) zero(x::Type{<:AbstractQuantity{T,D,U}}) where {T,D,U<:ScalarUnits} = zero(T)*U() zero(x::Type{<:AbstractQuantity{T,D,U}}) where {T,D,U<:AffineUnits} = zero(T)*absoluteunit(U()) +function zero(x::AbstractArray{T}) where T<:AbstractQuantity + if isconcretetype(T) + z = zero(T) + fill!(similar(x, typeof(z)), z) + else + dest = similar(x) + for i = eachindex(x) + if isassigned(x, i...) + dest[i] = zero(x[i]) + else + dest[i] = zero(T) + end + end + dest + end +end +@static if VERSION < v"1.8.0-DEV.107" + function zero(x::AbstractArray{Union{T,Missing}}) where T<:AbstractQuantity # only matches _concrete_ T ... + @assert isconcretetype(T) # ... but check anyway + z = zero(T) + fill!(similar(x, typeof(z)), z) + end +end + one(x::AbstractQuantity) = one(x.val) one(x::AffineQuantity) = throw(AffineError("no multiplicative identity for affine quantity $x.")) diff --git a/test/runtests.jl b/test/runtests.jl index f68ebd12..b6481012 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1400,8 +1400,26 @@ end @test size(rand(Q, 2)) == (2,) @test size(rand(Q, 2, 3)) == (2,3) @test eltype(@inferred(rand(Q, 2))) == Q - @test_throws ArgumentError zero([1u"m", 1u"s"]) - @test zero(Quantity{Int,𝐋}[1u"m", 1u"mm"]) == [0, 0]u"m" + @test zero([1m, 2m]) == [0m, 0m] + @test zero(Quantity{Int,𝐋}[1m, 1mm]) == [0m, 0mm] + @test zero(Quantity{Int}[1m, 1s]) == [0m, 0s] + @test zero(Quantity[1m, 1s]) == [0m, 0s] + @test zero([1mm, missing]) == [0mm, 0mm] + @test zero(Union{typeof(0.0s),Missing}[missing]) == [0.0s] + @test_broken zero(Union{Quantity{Int,𝐋},Missing}[1mm, missing]) == [0mm, 0m] + @test_broken zero(Union{Quantity{Float64,𝐋},Missing}[1.0mm, missing]) == [0.0mm, 0.0m] + @test_broken zero(Union{Quantity,Missing}[1m, 1mm]) == [0m, 0mm] + @test zero([1Β°C, 2Β°C]) == [0K, 0K] + @test zero(Quantity[1Β°C, 2Β°F]) == [0K, 0K] + @test zero(Union{typeof(0Β°C),Missing}[missing]) == [0K] + @test_broken zero(Union{Quantity{Int,𝚯},Missing}[1Β°C, 2Β°F, missing]) == [0K, 0K, 0K] + @test zero(Vector{typeof(big(1)mm)}(undef, 1)) == [big(0)mm] + @test zero(Vector{Union{typeof(big(1)mm),Missing}}(undef, 1)) == [big(0)mm] + @test zero(Vector{Quantity{Float64,𝐋}}(undef, 1)) == [0.0m] + @test_broken zero(Vector{Union{Quantity{Float64,𝐋},Missing}}(undef, 1)) == [0.0m] + @test_throws MethodError zero(Union{Quantity,Missing}[1m, 1s, missing]) + @test_throws MethodError zero(Vector{Quantity}(undef, 1)) + @test_throws MethodError zero(Vector{Union{Quantity,Missing}}(undef, 1)) end end end From f9992c08c5917f0cb6402bce26cd0a71a61ceb97 Mon Sep 17 00:00:00 2001 From: Sebastian Stock <42280794+sostock@users.noreply.github.com> Date: Thu, 10 Feb 2022 09:14:59 +0100 Subject: [PATCH 28/34] Release 1.11.0 (#519) --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index cb530324..d6669729 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Unitful" uuid = "1986cc42-f94f-5a68-af5c-568840ba703d" -version = "1.10.1" +version = "1.11.0" [deps] ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9" From 665dc5aa05e7078ade955dc52161aa63759d2b90 Mon Sep 17 00:00:00 2001 From: adkabo <61999878+adkabo@users.noreply.github.com> Date: Tue, 19 Apr 2022 12:26:59 -0700 Subject: [PATCH 29/34] Delete export of `convertr`, `convertrp` (#530) * Delete export of `convertr` There is no `convertr`, so don't export it. * Don't export convertrp It's not defined --- src/Unitful.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Unitful.jl b/src/Unitful.jl index dac82934..614a9982 100644 --- a/src/Unitful.jl +++ b/src/Unitful.jl @@ -31,7 +31,7 @@ export logunit, unit, absoluteunit, dimension, uconvert, ustrip, upreferred export @dimension, @derived_dimension, @refunit, @unit, @affineunit, @u_str export Quantity, DimensionlessQuantity, NoUnits, NoDims -export uconvertp, uconvertrp, convertr, convertrp, reflevel, linear +export uconvertp, uconvertrp, reflevel, linear export @logscale, @logunit, @dB, @B, @cNp, @Np export Level, Gain export uparse From 960e09ef518b0d3ff54747460b9c3872c08df0d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mos=C3=A8=20Giordano?= Date: Sat, 30 Apr 2022 20:49:55 +0100 Subject: [PATCH 30/34] Add `cispi` and `sincospi` (#533) --- src/quantities.jl | 6 ++++-- test/runtests.jl | 6 ++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/quantities.jl b/src/quantities.jl index b99340ff..b6b4a422 100644 --- a/src/quantities.jl +++ b/src/quantities.jl @@ -206,8 +206,10 @@ sqrt(x::AbstractQuantity) = Quantity(sqrt(x.val), sqrt(unit(x))) cbrt(x::AbstractQuantity) = Quantity(cbrt(x.val), cbrt(unit(x))) for _y in (:sin, :cos, :tan, :asin, :acos, :atan, :sinh, :cosh, :tanh, :asinh, :acosh, :atanh, - :sinpi, :cospi, :sinc, :cosc, :cis) - @eval ($_y)(x::DimensionlessQuantity) = ($_y)(uconvert(NoUnits, x)) + :sinpi, :cospi, :sinc, :cosc, :cis, :cispi, :sincospi) + if isdefined(Base, _y) + @eval Base.$(_y)(x::DimensionlessQuantity) = Base.$(_y)(uconvert(NoUnits, x)) + end end atan(y::AbstractQuantity{T1,D,U1}, x::AbstractQuantity{T2,D,U2}) where {T1,T2,D,U1,U2} = diff --git a/test/runtests.jl b/test/runtests.jl index b6481012..b3afd6c9 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -710,6 +710,12 @@ end @test @inferred(cospi(1rad)) == -1 @test @inferred(sinc(1rad)) === 0 @test @inferred(cosc(1ft/3inch)) === 0.25 + if isdefined(Base, :cispi) + @test @inferred(cispi(rad/2)) === complex(0.0, 1.0) + end + if isdefined(Base, :sincospi) + @test @inferred(sincospi(rad/2)) === (1.0, 0.0) + end @test @inferred(atan(m*sqrt(3),1m)) β‰ˆ 60Β° @test @inferred(atan(m*sqrt(3),1.0m)) β‰ˆ 60Β° From 7f5bf1f3588cebf27a34005ee3f220f57b66febf Mon Sep 17 00:00:00 2001 From: Rashid Rafeek Date: Sat, 4 Jun 2022 04:57:26 +0530 Subject: [PATCH 31/34] Add `modf` (#539) * Add `modf` for dimensionless quantities * Add tests for `modf` Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com> --- src/quantities.jl | 1 + test/runtests.jl | 3 +++ 2 files changed, 4 insertions(+) diff --git a/src/quantities.jl b/src/quantities.jl index b6b4a422..cfd2a863 100644 --- a/src/quantities.jl +++ b/src/quantities.jl @@ -119,6 +119,7 @@ end Base.mod2pi(x::DimensionlessQuantity) = mod2pi(uconvert(NoUnits, x)) Base.mod2pi(x::AbstractQuantity{S, NoDims, <:Units{(Unitful.Unit{:Degree, NoDims}(0, 1//1),), NoDims}}) where S = mod(x, 360Β°) +Base.modf(x::DimensionlessQuantity) = modf(uconvert(NoUnits, x)) # Addition / subtraction for op in [:+, :-] diff --git a/test/runtests.jl b/test/runtests.jl index b3afd6c9..89c42243 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -630,6 +630,9 @@ end @test mod(1hr+3minute+5s, 24s) == 17s @test mod2pi(360Β°) === 0Β° # 2pi is 360Β° @test mod2pi(0.5pi*u"m/dm") β‰ˆ pi # just testing the dimensionless fallback + @test modf(2.5rad) === (0.5, 2.0) + @test modf(-250cm/m) === (-1//2, -2//1) + @test_throws MethodError modf(1m) @test @inferred(inv(s)) === s^-1 @test inv(ContextUnits(m,km)) === ContextUnits(m^-1,km^-1) @test inv(FixedUnits(m)) === FixedUnits(m^-1) From adf24e7b09e13c403a37e4f486d38e0eaf79e2a9 Mon Sep 17 00:00:00 2001 From: Sam Buercklin Date: Fri, 24 Jun 2022 16:04:34 -0400 Subject: [PATCH 32/34] Add link to UnitfulChainRules.jl to README (#542) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 1d4aa656..18c62139 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ mathematical operations and collections that are found in Julia base. - [UnitfulLatexify.jl](https://github.com/gustaphe/UnitfulLatexify.jl): Pretty print units and quantities in LaTeX format. - [UnitfulBuckinghamPi.jl](https://github.com/rmsrosa/UnitfulBuckinghamPi.jl): Solves for the adimensional Pi groups in a list of Unitful parameters, according to the Buckingham-Pi Theorem. - [NaturallyUnitful.jl](https://github.com/MasonProtter/NaturallyUnitful.jl): Convert to and from natural units in physics. +- [UnitfulChainRules.jl](https://github.com/SBuercklin/UnitfulChainRules.jl): Enables use of Unitful quantities with [ChainRules.jl](https://github.com/JuliaDiff/ChainRules.jl)-compatible autodifferentiation systems ## Related packages From d536695afff30bb3d962081404f03460a17aa5fe Mon Sep 17 00:00:00 2001 From: hustf Date: Thu, 1 Sep 2022 10:40:53 +0200 Subject: [PATCH 33/34] modified: Project.toml v1.10.1 reflect Unitful, add ConstructionBase modified: src/pkgdefaults.jl Use new macros, deg rad change modified: test/runtests.jl Add ConstructionBase --- Project.toml | 2 +- src/pkgdefaults.jl | 14 +++++++------- test/runtests.jl | 47 +++++++++++++++++++++++++++------------------- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/Project.toml b/Project.toml index 186bce33..009f2692 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Unitfu" uuid = "5ee08b94-2369-4f4a-b8c7-99333ba35fb0" -version = "1.8.17" +version = "1.10.1" [deps] ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9" diff --git a/src/pkgdefaults.jl b/src/pkgdefaults.jl index 19fab520..72d93ecd 100644 --- a/src/pkgdefaults.jl +++ b/src/pkgdefaults.jl @@ -6,25 +6,25 @@ # dimensions from units, and also helps prevent common namespace collisions. " Unitfu.α΄Έ \nA dimension representing length." -@dimension α΄Έ "α΄Έ" Length true +@dimension α΄Έ " α΄Έ" Length true " Unitfu.α΄Ή \nA dimension representing mass." -@dimension α΄Ή "α΄Ή" Mass true +@dimension α΄Ή " α΄Ή" Mass true " Unitfu.α΅€ \nA dimension representing time." -@dimension α΅€ "α΅€" Time true +@dimension α΅€ " α΅€" Time true " Unitfu.α΄΅ \nA dimension representing electric current." -@dimension α΄΅ "α΄΅" Current true +@dimension α΄΅ " α΄΅" Current true " Unitfu.αΆΏ \nA dimension representing thermodynamic temperature." -@dimension αΆΏ "αΆΏ" Temperature true # This one is \bfTheta +@dimension αΆΏ " αΆΏ" Temperature true # This one is \bfTheta " Unitfu.α΄Ά \nA dimension representing luminous intensity." -@dimension α΄Ά "α΄Ά" Luminosity true +@dimension α΄Ά " α΄Ά" Luminosity true " Unitfu.α΄Ί \nA dimension representing amount of substance." -@dimension α΄Ί "α΄Ί" Amount true +@dimension α΄Ί " α΄Ί" Amount true const RelativeScaleTemperature = Quantity{T, αΆΏ, <:AffineUnits} where T const AbsoluteScaleTemperature = Quantity{T, αΆΏ, <:ScalarUnits} where T diff --git a/test/runtests.jl b/test/runtests.jl index d849a007..5d364f86 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,5 +1,5 @@ using Unitfu -using Test, LinearAlgebra, Random # ConstructionBase TODO merge construction. +using Test, LinearAlgebra, Random, ConstructionBase import Unitfu: DimensionError, AffineError import Unitfu: LogScaled, LogInfo, Level, Gain, MixedUnits, Decibel import Unitfu: FreeUnits, ContextUnits, FixedUnits, AffineUnits, AffineQuantity @@ -45,7 +45,7 @@ using Dates: CompoundPeriod const colon = Base.:(:) -#= + @testset "Construction" begin @test isa(NoUnits, FreeUnits) @test typeof(α΄Έ) === Unitfu.Dimensions{(Unitfu.Dimension{:Length}(1),)} @@ -337,6 +337,7 @@ include("dates.jl") end end end + # preferred units work on AbstractQuantity struct QQQ <: Unitfu.AbstractQuantity{Float64, α΄Έ,typeof(cm)} val::Float64 @@ -412,7 +413,7 @@ Unitfu.uconvert(U::Unitfu.Units, q::QQQ) = uconvert(U, Quantity(q.val, cm)) @test @inferred(promote(1g, 1.0kg)) === (0.001kg, 1.0kg) @test @inferred(promote(1.0m, 1kg)) === (1.0m, 1.0kg) @test @inferred(promote(1kg, 1.0m)) === (1.0kg, 1.0m) - @test_broken @inferred(promote(1.0m, 1)) === (1.0m, 1.0) # issue 52 + @test @inferred(promote(1.0m, 1)) == (1.0m, 1.0) # issue 52 @test @inferred(promote(Ο€, 180Β°)) === (float(Ο€), float(Ο€)) # issue 168 @test @inferred(promote(180Β°, Ο€)) === (float(Ο€), float(Ο€)) # issue 168 @@ -840,6 +841,7 @@ end @test_throws ErrorException isapprox(1.0*FixedUnits(u"m"), 1000.0*FixedUnits(u"mm")) end end + @testset "Fast mathematics" begin @testset "> fma and muladd" begin m2cm = ContextUnits(m,cm) @@ -1138,7 +1140,6 @@ end @test @inferred(rand(MersenneTwister(0), typeof(1u"m"))) isa typeof(1u"m") end - @testset "Collections" begin @testset "> Ranges" begin @testset ">> Some of test/ranges.jl, with units" begin @@ -1542,6 +1543,7 @@ end end @testset ">> Array initialization" begin + Q = typeof(1u"m") Q = typeof(1u"m") @test @inferred(zeros(Q, 2)) == [0, 0]u"m" @test @inferred(zeros(Q, (2,))) == [0, 0]u"m" @@ -1554,12 +1556,26 @@ end @test size(rand(Q, 2)) == (2,) @test size(rand(Q, 2, 3)) == (2,3) @test eltype(@inferred(rand(Q, 2))) == Q - @test @inferred(zero([1.0u"m", 2.0u"m"])) == [0.0u"m", 0.0u"m"] - @test @inferred(zero([1.0u"m", 1.0u"s"])) == [0.0, 0.0] - @test @inferred(zero([1u"m", 1u"s"])) == [0, 0] - @test zero(Quantity{Int,α΄Έ}[1u"m", 1u"mm"]) == [0, 0]u"m" - r0 = [1.0km, 2km, 3m/s, 4m/s] - @test @inferred(zero(r0)) == [0.0, 0.0, 0.0, 0.0] + @test zero([1m, 2m]) == [0m, 0m] + @test zero(Quantity{Int,α΄Έ}[1m, 1mm]) == [0m, 0mm] + @test zero(Quantity{Int}[1m, 1s]) == [0m, 0s] + @test zero(Quantity[1m, 1s]) == [0m, 0s] + @test zero([1mm, missing]) == [0mm, 0mm] + @test zero(Union{typeof(0.0s),Missing}[missing]) == [0.0s] + @test_broken zero(Union{Quantity{Int,α΄Έ},Missing}[1mm, missing]) == [0mm, 0m] + @test_broken zero(Union{Quantity{Float64,α΄Έ},Missing}[1.0mm, missing]) == [0.0mm, 0.0m] + @test_broken zero(Union{Quantity,Missing}[1m, 1mm]) == [0m, 0mm] + @test zero([1Β°C, 2Β°C]) == [0K, 0K] + @test zero(Quantity[1Β°C, 2Β°F]) == [0K, 0K] + @test zero(Union{typeof(0Β°C),Missing}[missing]) == [0K] + @test_broken zero(Union{Quantity{Int,αΆΏ},Missing}[1Β°C, 2Β°F, missing]) == [0K, 0K, 0K] + @test zero(Vector{typeof(big(1)mm)}(undef, 1)) == [big(0)mm] + @test zero(Vector{Union{typeof(big(1)mm),Missing}}(undef, 1)) == [big(0)mm] + @test zero(Vector{Quantity{Float64,α΄Έ}}(undef, 1)) == [0.0m] + @test_broken zero(Vector{Union{Quantity{Float64,α΄Έ},Missing}}(undef, 1)) == [0.0m] + @test_throws MethodError zero(Union{Quantity,Missing}[1m, 1s, missing]) + @test_throws MethodError zero(Vector{Quantity}(undef, 1)) + @test_throws MethodError zero(Vector{Union{Quantity,Missing}}(undef, 1)) end @testset ">> Tuple addition" begin # Dimensionless quantities @@ -1618,19 +1634,13 @@ end end -=# @static if VERSION >= VersionNumber("1.5.0-rc1") - @testset "Display" begin + @testset "Display no fancy exponents" begin withenv("UNITFUL_FANCY_EXPONENTS" => false) do @test string(typeof(1.0m/s)) == "Quantity{Float64, α΄Έβˆ™ α΅€^-1, FreeUnits{(m, s^-1), α΄Έβˆ™ α΅€^-1, nothing}}" || string(typeof(1.0m/s)) == "Quantity{Float64, α΄Έβˆ™ α΅€^-1,FreeUnits{(m, s^-1), α΄Έβˆ™ α΅€^-1,nothing}}" - -J1.8 v1.8.15: "Quantity{Float64, α΄Έβˆ™ α΅€^-1, FreeUnits{(m, s^-1), α΄Έβˆ™ α΅€^-1, nothing}}" -J1.7 dev "Quantity{Float64, α΄Έβˆ™α΅€^-1, FreeUnits{(m, s^-1), α΄Έβˆ™α΅€^-1, nothing}}" - "Quantity{Float64, α΄Έβˆ™α΅€^-1, FreeUnits{(m, s^-1), α΄Έβˆ™α΅€^-1, nothing}}" - @test string(typeof(m/s)) == "FreeUnits{(m, s^-1), α΄Έβˆ™ α΅€^-1, nothing}" || string(typeof(m/s)) == @@ -1765,7 +1775,7 @@ end end end end -#= + @testset "DimensionError message" begin function errorstr(e) @@ -2250,4 +2260,3 @@ finally rm(load_path, recursive=true) rm(load_cache_path, recursive=true) end -=# \ No newline at end of file From 1043eae05c60b0d0d81a5758aeb1a99221417bec Mon Sep 17 00:00:00 2001 From: hustf Date: Thu, 1 Sep 2022 11:10:30 +0200 Subject: [PATCH 34/34] modified: Project.toml v1.11.0 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 009f2692..f0f8e2c4 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "Unitfu" uuid = "5ee08b94-2369-4f4a-b8c7-99333ba35fb0" -version = "1.10.1" +version = "1.11.0" [deps] ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9"