Skip to content

Commit 7b4e798

Browse files
committed
Switch to using ConstructionBase
1 parent 468892e commit 7b4e798

File tree

6 files changed

+35
-25
lines changed

6 files changed

+35
-25
lines changed

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ version = "0.7.5"
55

66
[deps]
77
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
8+
ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
89
PackageExtensionCompat = "65ce6f38-6b18-4e1d-a461-8949797d7930"
910
Tricks = "410a4b4d-49e4-4fbc-ab6d-cb71b17b3775"
1011

@@ -22,6 +23,7 @@ DynamicQuantitiesUnitfulExt = "Unitful"
2223

2324
[compat]
2425
Compat = "3.42, 4"
26+
ConstructionBase = "1"
2527
Measurements = "2"
2628
PackageExtensionCompat = "1.0.2"
2729
ScientificTypes = "3"

src/arrays.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ struct QuantityArray{T,N,D<:AbstractDimensions,Q<:AbstractUnionQuantity{T,D},V<:
3131
dimensions::D
3232

3333
function QuantityArray(v::_V, d::_D, ::Type{_Q}) where {_T,_N,_D<:AbstractDimensions,_Q<:AbstractUnionQuantity,_V<:AbstractArray{_T,_N}}
34-
Q_out = constructor_of(_Q){_T,_D}
34+
Q_out = constructorof(_Q){_T,_D}
3535
return new{_T,_N,_D,Q_out,_V}(v, d)
3636
end
3737
end
@@ -74,7 +74,7 @@ function Base.convert(::Type{QA1}, A::QA2) where {QA1<:QuantityArray,QA2<:Quanti
7474
N = ndims(QA1)
7575

7676
raw_array = Base.Fix1(convert, Q).(A)
77-
output = QuantityArray(convert(constructor_of(V){Q,N}, raw_array))
77+
output = QuantityArray(convert(constructorof(V){Q,N}, raw_array))
7878
# TODO: This will mess with static arrays
7979

8080
return output::QA1

src/symbolic_dimensions.jl

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import ConstructionBase: constructorof
2+
import Tricks: static_fieldnames
3+
14
import .Units: UNIT_SYMBOLS, UNIT_MAPPING, UNIT_VALUES
25
import .Constants: CONSTANT_SYMBOLS, CONSTANT_MAPPING, CONSTANT_VALUES
36

@@ -53,7 +56,7 @@ function Base.getproperty(d::SymbolicDimensions{R}, s::Symbol) where {R}
5356
end
5457
Base.propertynames(::SymbolicDimensions) = ALL_SYMBOLS
5558
Base.getindex(d::SymbolicDimensions, k::Symbol) = getproperty(d, k)
56-
constructor_of(::Type{<:SymbolicDimensions}) = SymbolicDimensions
59+
constructorof(::Type{<:SymbolicDimensions}) = SymbolicDimensions
5760

5861
SymbolicDimensions{R}(d::SymbolicDimensions) where {R} = SymbolicDimensions{R}(getfield(d, :nzdims), convert(Vector{R}, getfield(d, :nzvals)))
5962
SymbolicDimensions(; kws...) = SymbolicDimensions{DEFAULT_DIM_BASE_TYPE}(; kws...)
@@ -71,7 +74,7 @@ end
7174
for (type, _) in ABSTRACT_QUANTITY_TYPES
7275
@eval begin
7376
function Base.convert(::Type{Q}, q::AbstractUnionQuantity{<:Any,<:Dimensions}) where {T,Q<:$type{T,SymbolicDimensions}}
74-
return convert(constructor_of(Q){T,SymbolicDimensions{DEFAULT_DIM_BASE_TYPE}}, q)
77+
return convert(constructorof(Q){T,SymbolicDimensions{DEFAULT_DIM_BASE_TYPE}}, q)
7578
end
7679
function Base.convert(::Type{Q}, q::AbstractUnionQuantity{<:Any,<:Dimensions}) where {T,R,Q<:$type{T,SymbolicDimensions{R}}}
7780
syms = (:m, :kg, :s, :A, :K, :cd, :mol)
@@ -82,14 +85,14 @@ for (type, _) in ABSTRACT_QUANTITY_TYPES
8285
permute!(I, p)
8386
permute!(V, p)
8487
dims = SymbolicDimensions{R}(I, V)
85-
return constructor_of(Q)(convert(T, ustrip(q)), dims)
88+
return constructorof(Q)(convert(T, ustrip(q)), dims)
8689
end
8790
function Base.convert(::Type{Q}, q::AbstractUnionQuantity{<:Any,<:SymbolicDimensions}) where {T,D<:Dimensions,Q<:$type{T,D}}
88-
result = constructor_of(Q)(T(ustrip(q)), D())
91+
result = constructorof(Q)(T(ustrip(q)), D())
8992
d = dimension(q)
9093
for (idx, value) in zip(getfield(d, :nzdims), getfield(d, :nzvals))
9194
if !iszero(value)
92-
result = result * convert(constructor_of(Q){T,D}, ALL_VALUES[idx]) ^ value
95+
result = result * convert(constructorof(Q){T,D}, ALL_VALUES[idx]) ^ value
9396
end
9497
end
9598
return result
@@ -108,7 +111,7 @@ for converting to specific symbolic units, or `convert(Quantity{<:Any,<:Symbolic
108111
for assuming SI units as the output symbols.
109112
"""
110113
function uexpand(q::Q) where {T,R,D<:SymbolicDimensions{R},Q<:AbstractQuantity{T,D}}
111-
return convert(constructor_of(Q){T,Dimensions{R}}, q)
114+
return convert(constructorof(Q){T,Dimensions{R}}, q)
112115
end
113116
uexpand(q::QuantityArray) = uexpand.(q)
114117
# TODO: Make the array-based one more efficient

src/types.jl

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import ConstructionBase: constructorof
12
import Tricks: static_fieldnames, static_fieldtypes
23

34
const DEFAULT_DIM_BASE_TYPE = FixedRational{DEFAULT_NUMERATOR_TYPE,DEFAULT_DENOM}
@@ -17,7 +18,7 @@ the need to define many other functions.
1718
The key function that one could wish to overload is
1819
`DynamicQuantities.dimension_name(::AbstractDimensions, k::Symbol)` for mapping from a field name
1920
to a base unit (e.g., `length` by default maps to `m`). You may also need to overload
20-
`DynamicQuantities.constructor_of(::Type{T})` in case of non-standard construction.
21+
`ConstructionBase.constructorof(::Type{T})` in case of non-standard construction.
2122
"""
2223
abstract type AbstractDimensions{R} end
2324

@@ -87,8 +88,8 @@ struct Dimensions{R<:Real} <: AbstractDimensions{R}
8788
amount::R
8889
end
8990

90-
(::Type{D})(::Type{R}; kws...) where {R,D<:AbstractDimensions} = constructor_of(D){R}((tryrationalize(R, get(kws, k, zero(R))) for k in static_fieldnames(D))...)
91-
(::Type{D})(; kws...) where {R,D<:AbstractDimensions{R}} = constructor_of(D)(R; kws...)
91+
(::Type{D})(::Type{R}; kws...) where {R,D<:AbstractDimensions} = constructorof(D){R}((tryrationalize(R, get(kws, k, zero(R))) for k in static_fieldnames(D))...)
92+
(::Type{D})(; kws...) where {R,D<:AbstractDimensions{R}} = constructorof(D)(R; kws...)
9293
(::Type{D})(; kws...) where {D<:AbstractDimensions} = D(DEFAULT_DIM_BASE_TYPE; kws...)
9394
function (::Type{D})(d::D2) where {R,D<:AbstractDimensions{R},D2<:AbstractDimensions}
9495
issetequal(static_fieldnames(D), static_fieldnames(D2)) ||
@@ -151,28 +152,31 @@ end
151152

152153
for (type, base_type) in ABSTRACT_QUANTITY_TYPES
153154
@eval begin
154-
(::Type{Q})(x::T, ::Type{D}; kws...) where {D<:AbstractDimensions,T<:$base_type,T2,Q<:$type{T2}} = constructor_of(Q)(convert(T2, x), D(; kws...))
155-
(::Type{Q})(x::$base_type, ::Type{D}; kws...) where {D<:AbstractDimensions,Q<:$type} = constructor_of(Q)(x, D(; kws...))
156-
(::Type{Q})(x::T; kws...) where {T<:$base_type,T2,Q<:$type{T2}} = constructor_of(Q)(convert(T2, x), dim_type(Q)(; kws...))
157-
(::Type{Q})(x::$base_type; kws...) where {Q<:$type} = constructor_of(Q)(x, dim_type(Q)(; kws...))
155+
(::Type{Q})(x::T, ::Type{D}; kws...) where {D<:AbstractDimensions,T<:$base_type,T2,Q<:$type{T2}} = constructorof(Q)(convert(T2, x), D(; kws...))
156+
(::Type{Q})(x::$base_type, ::Type{D}; kws...) where {D<:AbstractDimensions,Q<:$type} = constructorof(Q)(x, D(; kws...))
157+
(::Type{Q})(x::T; kws...) where {T<:$base_type,T2,Q<:$type{T2}} = constructorof(Q)(convert(T2, x), dim_type(Q)(; kws...))
158+
(::Type{Q})(x::$base_type; kws...) where {Q<:$type} = constructorof(Q)(x, dim_type(Q)(; kws...))
158159
end
159160
for (type2, _) in ABSTRACT_QUANTITY_TYPES
160161
@eval begin
161-
(::Type{Q})(q::$type2) where {T,D<:AbstractDimensions,Q<:$type{T,D}} = constructor_of(Q)(convert(T, ustrip(q)), convert(D, dimension(q)))
162-
(::Type{Q})(q::$type2) where {T,Q<:$type{T}} = constructor_of(Q)(convert(T, ustrip(q)), dimension(q))
163-
(::Type{Q})(q::$type2) where {Q<:$type} = constructor_of(Q)(ustrip(q), dimension(q))
162+
(::Type{Q})(q::$type2) where {T,D<:AbstractDimensions,Q<:$type{T,D}} = constructorof(Q)(convert(T, ustrip(q)), convert(D, dimension(q)))
163+
(::Type{Q})(q::$type2) where {T,Q<:$type{T}} = constructorof(Q)(convert(T, ustrip(q)), dimension(q))
164+
(::Type{Q})(q::$type2) where {Q<:$type} = constructorof(Q)(ustrip(q), dimension(q))
164165
end
165166
end
166167
end
167168

168169
const DEFAULT_QUANTITY_TYPE = Quantity{DEFAULT_VALUE_TYPE, DEFAULT_DIM_TYPE}
169170

170-
new_dimensions(::Type{D}, dims...) where {D<:AbstractDimensions} = constructor_of(D)(dims...)
171-
new_quantity(::Type{Q}, l, r) where {Q<:AbstractUnionQuantity} = constructor_of(Q)(l, r)
171+
new_dimensions(::Type{D}, dims...) where {D<:AbstractDimensions} = constructorof(D)(dims...)
172+
new_quantity(::Type{Q}, l, r) where {Q<:AbstractUnionQuantity} = constructorof(Q)(l, r)
172173

173174
dim_type(::Type{Q}) where {T,D<:AbstractDimensions,Q<:AbstractUnionQuantity{T,D}} = D
174175
dim_type(::Type{<:AbstractUnionQuantity}) = DEFAULT_DIM_TYPE
175-
constructor_of(::Type{T}) where {T} = Base.typename(T).wrapper
176+
177+
constructorof(::Type{<:Dimensions}) = Dimensions
178+
constructorof(::Type{<:Quantity}) = Quantity
179+
constructorof(::Type{<:GenericQuantity}) = GenericQuantity
176180

177181
struct DimensionError{Q1,Q2} <: Exception
178182
q1::Q1

src/utils.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import Tricks: static_fieldnames
21
import Compat: allequal
2+
import ConstructionBase: constructorof
3+
import Tricks: static_fieldnames
34

45
function map_dimensions(f::F, args::AbstractDimensions...) where {F<:Function}
56
dimension_type = promote_type(typeof(args).parameters...)
@@ -116,8 +117,8 @@ end
116117
for f in (:one, :typemin, :typemax)
117118
@eval begin
118119
Base.$f(::Type{Q}) where {T,D,Q<:AbstractUnionQuantity{T,D}} = new_quantity(Q, $f(T), D)
119-
Base.$f(::Type{Q}) where {T,Q<:AbstractUnionQuantity{T}} = $f(constructor_of(Q){T, DEFAULT_DIM_TYPE})
120-
Base.$f(::Type{Q}) where {Q<:AbstractUnionQuantity} = $f(Q{DEFAULT_VALUE_TYPE, DEFAULT_DIM_TYPE})
120+
Base.$f(::Type{Q}) where {T,Q<:AbstractUnionQuantity{T}} = $f(constructorof(Q){T, DEFAULT_DIM_TYPE})
121+
Base.$f(::Type{Q}) where {Q<:AbstractUnionQuantity} = $f(constructorof(Q){DEFAULT_VALUE_TYPE, DEFAULT_DIM_TYPE})
121122
end
122123
if f == :one # Return empty dimensions, as should be multiplicative identity.
123124
@eval Base.$f(q::Q) where {Q<:AbstractUnionQuantity} = new_quantity(Q, $f(ustrip(q)), one(dimension(q)))

test/unittests.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ end
534534
end
535535

536536
# Internal constructor
537-
@test DynamicQuantities.constructor_of(typeof(sym)) === SymbolicDimensions
537+
@test DynamicQuantities.constructorof(typeof(sym)) === SymbolicDimensions
538538

539539
# Equality comparisons
540540
@test sym == sym

0 commit comments

Comments
 (0)