Skip to content

Commit ae6285f

Browse files
committed
Add with_type_parameters function for configurable type changes
1 parent 4ea8ed5 commit ae6285f

File tree

4 files changed

+25
-7
lines changed

4 files changed

+25
-7
lines changed

src/arrays.jl

Lines changed: 1 addition & 1 deletion
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 = constructorof(_Q){_T,_D}
34+
Q_out = with_type_parameters(_Q, _T, _D)
3535
return new{_T,_N,_D,Q_out,_V}(v, d)
3636
end
3737
end

src/symbolic_dimensions.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@ function Base.getproperty(d::SymbolicDimensions{R}, s::Symbol) where {R}
5555
end
5656
Base.propertynames(::SymbolicDimensions) = ALL_SYMBOLS
5757
Base.getindex(d::SymbolicDimensions, k::Symbol) = getproperty(d, k)
58+
5859
constructorof(::Type{<:SymbolicDimensions}) = SymbolicDimensions
60+
with_type_parameters(::Type{<:SymbolicDimensions}, ::Type{R}) where {R} = SymbolicDimensions{R}
5961

6062
SymbolicDimensions{R}(d::SymbolicDimensions) where {R} = SymbolicDimensions{R}(getfield(d, :nzdims), convert(Vector{R}, getfield(d, :nzvals)))
6163
SymbolicDimensions(; kws...) = SymbolicDimensions{DEFAULT_DIM_BASE_TYPE}(; kws...)
@@ -73,7 +75,7 @@ end
7375
for (type, _) in ABSTRACT_QUANTITY_TYPES
7476
@eval begin
7577
function Base.convert(::Type{Q}, q::AbstractUnionQuantity{<:Any,<:Dimensions}) where {T,Q<:$type{T,SymbolicDimensions}}
76-
return convert(constructorof(Q){T,SymbolicDimensions{DEFAULT_DIM_BASE_TYPE}}, q)
78+
return convert(with_type_parameters(Q, T,SymbolicDimensions{DEFAULT_DIM_BASE_TYPE}), q)
7779
end
7880
function Base.convert(::Type{Q}, q::AbstractUnionQuantity{<:Any,<:Dimensions}) where {T,R,Q<:$type{T,SymbolicDimensions{R}}}
7981
syms = (:m, :kg, :s, :A, :K, :cd, :mol)
@@ -91,7 +93,7 @@ for (type, _) in ABSTRACT_QUANTITY_TYPES
9193
d = dimension(q)
9294
for (idx, value) in zip(getfield(d, :nzdims), getfield(d, :nzvals))
9395
if !iszero(value)
94-
result = result * convert(constructorof(Q){T,D}, ALL_VALUES[idx]) ^ value
96+
result = result * convert(with_type_parameters(Q, T, D), ALL_VALUES[idx]) ^ value
9597
end
9698
end
9799
return result
@@ -110,7 +112,7 @@ for converting to specific symbolic units, or `convert(Quantity{<:Any,<:Symbolic
110112
for assuming SI units as the output symbols.
111113
"""
112114
function uexpand(q::Q) where {T,R,D<:SymbolicDimensions{R},Q<:AbstractQuantity{T,D}}
113-
return convert(constructorof(Q){T,Dimensions{R}}, q)
115+
return convert(with_type_parameters(Q, T, Dimensions{R}), q)
114116
end
115117
uexpand(q::QuantityArray) = uexpand.(q)
116118
# TODO: Make the array-based one more efficient

src/types.jl

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ struct Dimensions{R<:Real} <: AbstractDimensions{R}
8787
amount::R
8888
end
8989

90-
(::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))...)
90+
(::Type{D})(::Type{R}; kws...) where {R,D<:AbstractDimensions} = with_type_parameters(D, R)((tryrationalize(R, get(kws, k, zero(R))) for k in static_fieldnames(D))...)
9191
(::Type{D})(; kws...) where {R,D<:AbstractDimensions{R}} = constructorof(D)(R; kws...)
9292
(::Type{D})(; kws...) where {D<:AbstractDimensions} = D(DEFAULT_DIM_BASE_TYPE; kws...)
9393
function (::Type{D})(d::D2) where {R,D<:AbstractDimensions{R},D2<:AbstractDimensions}
@@ -177,10 +177,26 @@ constructorof(::Type{<:Dimensions}) = Dimensions
177177
constructorof(::Type{<:Quantity}) = Quantity
178178
constructorof(::Type{<:GenericQuantity}) = GenericQuantity
179179

180+
function with_type_parameters(::Type{<:Dimensions}, ::Type{R}) where {R}
181+
return Dimensions{R}
182+
end
183+
function with_type_parameters(::Type{<:Quantity}, ::Type{T}, ::Type{D}) where {T,D}
184+
return Quantity{T,D}
185+
end
186+
function with_type_parameters(::Type{<:GenericQuantity}, ::Type{T}, ::Type{D}) where {T,D}
187+
return GenericQuantity{T,D}
188+
end
189+
180190
# The following functions should be overloaded for special types
181191
function constructorof(::Type{T}) where {T}
182192
return Base.typename(T).wrapper
183193
end
194+
function with_type_parameters(::Type{D}, ::Type{R}) where {D<:AbstractDimensions,R}
195+
return constructorof(D){R}
196+
end
197+
function with_type_parameters(::Type{Q}, ::Type{T}, ::Type{D}) where {Q<:AbstractUnionQuantity,T,D}
198+
return constructorof(Q){T,D}
199+
end
184200

185201
struct DimensionError{Q1,Q2} <: Exception
186202
q1::Q1

src/utils.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,8 @@ end
116116
for f in (:one, :typemin, :typemax)
117117
@eval begin
118118
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(constructorof(Q){T, DEFAULT_DIM_TYPE})
120-
Base.$f(::Type{Q}) where {Q<:AbstractUnionQuantity} = $f(constructorof(Q){DEFAULT_VALUE_TYPE, DEFAULT_DIM_TYPE})
119+
Base.$f(::Type{Q}) where {T,Q<:AbstractUnionQuantity{T}} = $f(with_type_parameters(Q, T, DEFAULT_DIM_TYPE))
120+
Base.$f(::Type{Q}) where {Q<:AbstractUnionQuantity} = $f(with_type_parameters(Q, DEFAULT_VALUE_TYPE, DEFAULT_DIM_TYPE))
121121
end
122122
if f == :one # Return empty dimensions, as should be multiplicative identity.
123123
@eval Base.$f(q::Q) where {Q<:AbstractUnionQuantity} = new_quantity(Q, $f(ustrip(q)), one(dimension(q)))

0 commit comments

Comments
 (0)