-
Notifications
You must be signed in to change notification settings - Fork 15
/
register_units.jl
72 lines (59 loc) · 1.85 KB
/
register_units.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
72
import .Units: UNIT_MAPPING, UNIT_SYMBOLS, UNIT_VALUES, _lazy_register_unit
import .SymbolicUnits: update_external_symbolic_unit_value
# Update the unit collections
const UNIT_UPDATE_LOCK = Threads.SpinLock()
function update_all_values(name_symbol, unit)
lock(UNIT_UPDATE_LOCK) do
push!(ALL_SYMBOLS, name_symbol)
push!(ALL_VALUES, unit)
i = lastindex(ALL_VALUES)
ALL_MAPPING[name_symbol] = i
UNIT_MAPPING[name_symbol] = i
update_external_symbolic_unit_value(name_symbol)
end
end
"""
@register_unit symbol value
Register a new unit under the given symbol to have
a particular value.
# Example
```julia
julia> @register_unit MyVolt 1.5u"V"
```
This will register a new unit `MyVolt` with a value of `1.5u"V"`.
You can then use this unit in your calculations:
```julia
julia> x = 20us"MyVolt^2"
20.0 MyVolt²
julia> y = 2.5us"A"
2.5 A
julia> x * y^2 |> us"W^2"
281.25 W²
julia> x * y^2 |> us"W^2" |> sqrt |> uexpand
16.77050983124842 m² kg s⁻³
```
"""
macro register_unit(symbol, value)
return esc(_register_unit(symbol, value))
end
function _register_unit(name::Symbol, value)
name_symbol = Meta.quot(name)
index = get(ALL_MAPPING, name, INDEX_TYPE(0))
if !iszero(index)
unit = ALL_VALUES[index]
# When a utility function to expand `value` to its final form becomes
# available, enable the following check. This will avoid throwing an error
# if user is trying to register an existing unit with matching values.
# unit.value != value && throw("Unit $name is already defined as $unit")
error("Unit `$name` is already defined as `$unit`")
end
reg_expr = _lazy_register_unit(name, value)
push!(
reg_expr.args,
quote
$update_all_values($name_symbol, $value)
nothing
end
)
return reg_expr
end