Skip to content

Commit f3fe3d4

Browse files
committed
Add many more functions
1 parent 6769df1 commit f3fe3d4

File tree

3 files changed

+107
-6
lines changed

3 files changed

+107
-6
lines changed

src/math.jl

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ for op in (:*, :/, :+, :-),
5050
@eval Base.$op(l::$t1, r::$t2) = $op(promote(l, r)...)
5151
end
5252

53+
function Base.div(x::UnionAbstractQuantity, y::UnionAbstractQuantity, r::RoundingMode=RoundToZero)
54+
x, y = promote(x, y)
55+
return new_quantity(typeof(x), div(ustrip(x), ustrip(y), r), dimension(x) / dimension(y))
56+
end
57+
function Base.div(x::UnionAbstractQuantity, y, r::RoundingMode=RoundToZero)
58+
return new_quantity(typeof(x), div(ustrip(x), y, r), dimension(x))
59+
end
60+
function Base.div(x, y::UnionAbstractQuantity, r::RoundingMode=RoundToZero)
61+
return new_quantity(typeof(y), div(x, ustrip(y), r), inv(dimension(y)))
62+
end
63+
5364
# We don't promote on the dimension types:
5465
function Base.:^(l::AbstractDimensions{R}, r::Integer) where {R}
5566
return map_dimensions(Base.Fix1(*, r), l)
@@ -97,6 +108,93 @@ Base.sqrt(q::UnionAbstractQuantity) = new_quantity(typeof(q), sqrt(ustrip(q)), s
97108
Base.cbrt(d::AbstractDimensions{R}) where {R} = d^inv(convert(R, 3))
98109
Base.cbrt(q::UnionAbstractQuantity) = new_quantity(typeof(q), cbrt(ustrip(q)), cbrt(dimension(q)))
99110

100-
Base.abs(q::UnionAbstractQuantity) = new_quantity(typeof(q), abs(ustrip(q)), dimension(q))
101111
Base.abs2(q::UnionAbstractQuantity) = new_quantity(typeof(q), abs2(ustrip(q)), dimension(q)^2)
102112
Base.angle(q::UnionAbstractQuantity{T}) where {T<:Complex} = angle(ustrip(q))
113+
114+
############################## Require dimensionless input ##############################
115+
# Note that :clamp, :cmp, :sign already work
116+
for f in (
117+
:sin, :cos, :tan, :sinh, :cosh, :tanh, :asin, :acos,
118+
:asinh, :acosh, :atanh, :sec, :csc, :cot, :asec, :acsc, :acot, :sech, :csch,
119+
:coth, :asech, :acsch, :acoth, :sinc, :cosc, :cosd, :cotd, :cscd, :secd,
120+
:sind, :tand, :acosd, :acotd, :acscd, :asecd, :asind, :rad2deg, :deg2rad,
121+
:log, :log2, :log10, :log1p, :exp, :exp2, :expm1, :frexp,
122+
:sinpi, :cospi, :exp10, :transpose, :exponent,
123+
)
124+
@eval function Base.$f(q::UnionAbstractQuantity)
125+
iszero(dimension(q)) || throw(DimensionError(q))
126+
return $f(ustrip(q))
127+
end
128+
end
129+
130+
for f in (:atan, :atand)
131+
@eval begin
132+
function Base.$f(x::UnionAbstractQuantity)
133+
iszero(dimension(x)) || throw(DimensionError(x))
134+
return $f(ustrip(x))
135+
end
136+
function Base.$f(y::UnionAbstractQuantity, x::UnionAbstractQuantity)
137+
dimension(y) == dimension(x) || throw(DimensionError(y, x))
138+
y, x = promote(y, x)
139+
return $f(ustrip(y), ustrip(x))
140+
end
141+
function Base.$f(y::UnionAbstractQuantity, x)
142+
iszero(dimension(y)) || throw(DimensionError(y))
143+
return $f(ustrip(y), x)
144+
end
145+
function Base.$f(y, x::UnionAbstractQuantity)
146+
iszero(dimension(x)) || throw(DimensionError(x))
147+
return $f(y, ustrip(x))
148+
end
149+
end
150+
end
151+
#########################################################################################
152+
153+
############################## Same dimension as input ##################################
154+
for f in (
155+
:abs, :real, :imag, :conj, :adjoint, :unsigned, :nextfloat, :prevfloat, :identity,
156+
)
157+
@eval function Base.$f(q::UnionAbstractQuantity)
158+
return new_quantity(typeof(q), $f(ustrip(q)), dimension(q))
159+
end
160+
end
161+
for f in (:copysign, :flipsign, :mod)
162+
# These treat the x as the magnitude, so we take the dimensions from there,
163+
# and ignore any dimensions on y
164+
@eval begin
165+
function Base.$f(x::UnionAbstractQuantity, y::UnionAbstractQuantity)
166+
Q = promote_type(typeof(x), typeof(y))
167+
return new_quantity(Q, $f(ustrip(x), ustrip(y)), dimension(x))
168+
end
169+
function Base.$f(x::UnionAbstractQuantity, y)
170+
return new_quantity(typeof(x), $f(ustrip(x), y), dimension(x))
171+
end
172+
function Base.$f(x, y::UnionAbstractQuantity)
173+
return $f(x, ustrip(y))
174+
end
175+
end
176+
end
177+
function Base.ldexp(x::UnionAbstractQuantity, n::Integer)
178+
return new_quantity(typeof(x), ldexp(ustrip(x), n), dimension(x))
179+
end
180+
function Base.round(q::UnionAbstractQuantity, r::RoundingMode=RoundNearest)
181+
return new_quantity(typeof(q), round(ustrip(q), r), dimension(q))
182+
end
183+
function Base.round(::Type{Ti}, q::UnionAbstractQuantity, r::RoundingMode=RoundNearest) where {Ti<:Integer}
184+
return new_quantity(typeof(q), round(Ti, ustrip(q), r), dimension(q))
185+
end
186+
for f in (:floor, :trunc, :ceil, :significand)
187+
@eval begin
188+
function Base.$f(q::UnionAbstractQuantity)
189+
return new_quantity(typeof(q), $f(ustrip(q)), dimension(q))
190+
end
191+
function Base.$f(::Type{Ti}, q::UnionAbstractQuantity) where {Ti<:Integer}
192+
return new_quantity(typeof(q), $f(Ti, ustrip(q)), dimension(q))
193+
end
194+
end
195+
end
196+
function Base.modf(q::UnionAbstractQuantity)
197+
output = modf(ustrip(q))
198+
return ntuple(i -> new_quantity(typeof(q), output[i], dimension(q)), Val(2))
199+
end
200+
#########################################################################################

src/types.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,4 +252,7 @@ end
252252
struct DimensionError{Q1,Q2} <: Exception
253253
q1::Q1
254254
q2::Q2
255+
256+
DimensionError(q1, q2) = new{typeof(q1),typeof(q2)}(q1, q2)
257+
DimensionError(q1) = DimensionError(q1, nothing)
255258
end

src/utils.jl

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,14 +107,13 @@ function Base.isless(l::Number, r::UnionAbstractQuantity)
107107
end
108108

109109
# Simple flags:
110-
for f in (:iszero, :isfinite, :isinf, :isnan, :isreal)
110+
# :iseven, :ispow2, :isfinite, :isinf, :isodd, :isinteger, :isreal,
111+
# :isnan, :isempty, :iszero
112+
for f in (:iszero, :isfinite, :isinf, :isnan, :isreal, :signbit)
111113
@eval Base.$f(q::UnionAbstractQuantity) = $f(ustrip(q))
112114
end
115+
Base.isempty(q::AbstractGenericQuantity) = isempty(ustrip(q))
113116

114-
# Simple operations which return a full quantity (same dimensions)
115-
for f in (:real, :imag, :conj, :adjoint, :unsigned, :nextfloat, :prevfloat)
116-
@eval Base.$f(q::UnionAbstractQuantity) = new_quantity(typeof(q), $f(ustrip(q)), dimension(q))
117-
end
118117

119118
# Base.one, typemin, typemax
120119
for f in (:one, :typemin, :typemax)
@@ -172,6 +171,7 @@ tryrationalize(::Type{R}, x::Union{Rational,Integer}) where {R} = convert(R, x)
172171
tryrationalize(::Type{R}, x) where {R} = isinteger(x) ? convert(R, round(Int, x)) : convert(R, rationalize(Int, x))
173172

174173
Base.showerror(io::IO, e::DimensionError) = print(io, "DimensionError: ", e.q1, " and ", e.q2, " have incompatible dimensions")
174+
Base.showerror(io::IO, e::DimensionError{<:Any,Nothing}) = print(io, "DimensionError: ", e.q1, " is not dimensionless")
175175

176176
Base.convert(::Type{Q}, q::UnionAbstractQuantity) where {Q<:UnionAbstractQuantity} = q
177177
Base.convert(::Type{Q}, q::UnionAbstractQuantity) where {T,Q<:UnionAbstractQuantity{T}} = new_quantity(Q, convert(T, ustrip(q)), dimension(q))

0 commit comments

Comments
 (0)