Skip to content

Commit 0979015

Browse files
committed
Add mul_with_rounding for Fixed
This provides the multiplication compatible with v0.8 and earlier as `mul_with_rounding(x, y, RoundNearestTiesUp)`. This also provides the rounding-down version `mul_with_rounding(x, y, RoundDown)`. The function is informative and not exported.
1 parent 504b3ed commit 0979015

File tree

2 files changed

+19
-4
lines changed

2 files changed

+19
-4
lines changed

src/fixed.jl

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,18 @@ function checked_mul(x::F, y::F) where {T <: Union{Int8,Int16,Int32,Int64}, f, F
152152
F(div_2f(z, Val(Int(f))) % T, 0)
153153
end
154154

155-
# with truncation:
156-
#*(x::Fixed{T,f}, y::Fixed{T,f}) = Fixed{T,f}(Base.widemul(x.i,y.i)>>f,0)
157-
# with rounding up:
158-
#*(x::Fixed{T,f}, y::Fixed{T,f}) where {T,f} = Fixed{T,f}((Base.widemul(x.i,y.i) + (one(widen(T)) << (f-1)))>>f,0)
155+
function mul_with_rounding(x::F, y::F, ::RoundingMode{:Nearest}) where {F <: Fixed}
156+
wrapping_mul(x, y)
157+
end
158+
function mul_with_rounding(x::F, y::F, ::RoundingMode{:NearestTiesUp}) where
159+
{T <: Union{Int8,Int16,Int32,Int64}, f, F <: Fixed{T, f}}
160+
z = widemul(x.i, y.i)
161+
F(((z + (oftype(z, 1) << f >>> 1)) >> f) % T, 0)
162+
end
163+
function mul_with_rounding(x::F, y::F, ::RoundingMode{:Down}) where
164+
{T <: Union{Int8,Int16,Int32,Int64}, f, F <: Fixed{T, f}}
165+
F((widemul(x.i, y.i) >> f) % T, 0)
166+
end
159167

160168
/(x::Fixed{T,f}, y::Fixed{T,f}) where {T,f} = Fixed{T,f}(div(convert(widen(T), x.i) << f, y.i), 0)
161169

test/fixed.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,13 @@ end
389389
@test all(((x, y),) -> !(typemin(F) <= fmul(x, y) <= typemax(F)) ||
390390
wrapping_mul(x, y) === checked_mul(x, y), xys)
391391
end
392+
393+
FixedPointNumbers.mul_with_rounding(1.5Q6f1, 0.5Q6f1, RoundNearest) === 1.0Q6f1
394+
FixedPointNumbers.mul_with_rounding(1.5Q6f1, -0.5Q6f1, RoundNearest) === -1.0Q6f1
395+
FixedPointNumbers.mul_with_rounding(1.5Q6f1, 0.5Q6f1, RoundNearestTiesUp) === 1.0Q6f1
396+
FixedPointNumbers.mul_with_rounding(1.5Q6f1, -0.5Q6f1, RoundNearestTiesUp) === -0.5Q6f1
397+
FixedPointNumbers.mul_with_rounding(1.5Q6f1, 0.5Q6f1, RoundDown) === 0.5Q6f1
398+
FixedPointNumbers.mul_with_rounding(1.5Q6f1, -0.5Q6f1, RoundDown) === -1.0Q6f1
392399
end
393400

394401
@testset "rounding" begin

0 commit comments

Comments
 (0)