-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathDynamicQuantitiesUnitfulExt.jl
71 lines (61 loc) · 2.38 KB
/
DynamicQuantitiesUnitfulExt.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
module DynamicQuantitiesUnitfulExt
if isdefined(Base, :get_extension)
import DynamicQuantities
import Unitful
import Unitful: @u_str
else
import ..DynamicQuantities
import ..Unitful
import ..Unitful: @u_str
end
# This lets the user override the preferred units:
const UNITFUL_EQUIVALENCIES = let basic = (length=u"m", mass=u"kg", time=u"s", current=u"A", temperature=u"K", luminosity=u"cd", amount=u"mol")
NamedTuple((k => Unitful.upreferred(basic[k]) for k in keys(basic)))
end
Base.convert(::Type{Unitful.Quantity}, x::DynamicQuantities.Quantity) =
let
cumulator = DynamicQuantities.ustrip(x)
dims = DynamicQuantities.dimension(x)
for dim in keys(dims)
value = dims[dim]
iszero(value) && continue
cumulator *= UNITFUL_EQUIVALENCIES[dim]^value
end
cumulator
end
Base.convert(::Type{DynamicQuantities.Quantity}, x::Unitful.Quantity) =
let
value = Unitful.ustrip(Unitful.upreferred(x))
dimension = convert(DynamicQuantities.Dimensions, Unitful.dimension(x))
return DynamicQuantities.Quantity(value, dimension)
end
Base.convert(::Type{DynamicQuantities.Quantity}, x::Unitful.FreeUnits) =
let
convert(DynamicQuantities.Quantity, 1.0 * x)
end
Base.convert(::Type{DynamicQuantities.Dimensions}, d::Unitful.Dimensions{D}) where {D} =
let
cumulator = DynamicQuantities.Dimensions()
for dim in D
dim_symbol = _map_dim_name_to_dynamic_units(typeof(dim))
dim_power = dim.power
cumulator *= DynamicQuantities.Dimensions(; dim_symbol => dim_power)
end
cumulator
end
Base.convert(::Type{DynamicQuantities.Dimensions}, x::Unitful.FreeUnits) =
let
DynamicQuantities.dimension(convert(DynamicQuantities.Quantity, x))
end
function _map_dim_name_to_dynamic_units(::Type{Unitful.Dimension{D}}) where {D}
# (We could do this automatically, but it's more obvious what we are doing this way.)
D == :Length && return :length
D == :Mass && return :mass
D == :Time && return :time
D == :Current && return :current
D == :Temperature && return :temperature
D == :Luminosity && return :luminosity
D == :Amount && return :amount
throw(error("Unknown dimension: $D. Valid dimensions are: (:Length, :Mass, :Time, :Current, :Temperature, :Luminosity, :Amount)."))
end
end