Skip to content

Commit bec43b6

Browse files
lukebemishsostockgiordano
authored
Attempt to allow preferunits to work with non-pure units (#478)
* 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 <giordano@users.noreply.github.com> * 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 <giordano@users.noreply.github.com>
1 parent b17b1c5 commit bec43b6

File tree

4 files changed

+36
-4
lines changed

4 files changed

+36
-4
lines changed

β€Žsrc/Unitful.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ end
5353
const basefactors = _basefactors(Unitful)
5454

5555
include("types.jl")
56-
const promotion = Dict{Symbol,Unit}()
56+
const promotion = Dict{Symbol,FreeUnits}()
5757

5858
include("user.jl")
5959
include("utils.jl")

β€Žsrc/units.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,6 @@ factory defaults, this function will return a product of powers of base SI units
302302
(as [`Unitful.FreeUnits`](@ref)).
303303
"""
304304
@generated function upreferred(x::Dimensions{D}) where {D}
305-
u = *(FreeUnits{((Unitful.promotion[name(z)]^z.power for z in D)...,),()}())
305+
u = prod((NoUnits, (promotion[name(z)]^z.power for z in D)...))
306306
:($u)
307307
end

β€Žsrc/user.jl

+22-1
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,28 @@ function preferunits(u0::Units, u::Units...)
310310
"For instance, it should not be used with units of dimension 𝐋^2.")
311311
end
312312
y = typeof(dim).parameters[1][1]
313-
promotion[name(y)] = typeof(unit).parameters[1][1]
313+
promotion[name(y)] = unit
314+
end
315+
316+
# Let's run a quick check for anything where, for instance, current was defined is C/ms and time
317+
# was defined in ns. We'll give a warning if this is the case so the user knows they may get
318+
# unexpected (though still correct) results. There may be cases where people would want to do this,
319+
# so we won't stop them, just let them know they're doing it.
320+
ulist = (typeof(i[2]).parameters[1] for i in promotion)
321+
check = Dict{Dimensions, Unit}()
322+
for a in ulist
323+
ulistA = (i^(1/i.power) for i in a)
324+
for i in ulistA
325+
k = dimension(i)
326+
if haskey(check, k)
327+
if i!=check[k]
328+
@warn "Preferred units contain complex units based on units of the same dimension but different scales: "*string(i)*" and "*string(check[k])*
329+
"\nThis may be intentional, but otherwise could lead to redundant units, such as ms/s or kg/g"
330+
end
331+
else
332+
check[k] = i
333+
end
334+
end
314335
end
315336

316337
nothing

β€Žtest/runtests.jl

+12-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import Unitful:
1414
J, A, N, mol, V,
1515
mW, W,
1616
dB, dB_rp, dB_p, dBm, dBV, dBSPL, Decibel,
17-
Np, Np_rp, Np_p, Neper
17+
Np, Np_rp, Np_p, Neper,
18+
C
1819

1920
import Unitful: 𝐋, 𝐓, 𝐍, 𝚯
2021

@@ -320,6 +321,16 @@ Unitful.uconvert(U::Unitful.Units, q::QQQ) = uconvert(U, Quantity(q.val, cm))
320321

321322
@testset "Promotion" begin
322323
@testset "> Unit preferences" begin
324+
# Should warn on possible redundant units issue (ms and s)
325+
@test_logs (:warn, r"^Preferred units contain complex units") Unitful.preferunits(C/ms)
326+
# Test for wacky prefered units functionality
327+
Unitful.preferunits(C/s)
328+
@test @inferred(upreferred(V/m)) == kg*m*C^-1*s^-2
329+
@test dimension(upreferred(V/m)) == dimension(V/m)
330+
# Reset preferred units to default, except for units of dimension 𝐋*𝐌*𝐈^-1*𝐓^-3,
331+
# because upreferred has already been called for that dimension
332+
Unitful.preferunits(A)
333+
323334
# Only because we favor SI, we have the following:
324335
@test @inferred(upreferred(N)) === kg*m/s^2
325336
@test @inferred(upreferred(dimension(N))) === kg*m/s^2

0 commit comments

Comments
Β (0)