Skip to content

Commit 2f9710b

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 8ed5bc3 commit 2f9710b

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
@@ -153,10 +153,18 @@ function checked_mul(x::F, y::F) where {T <: Union{Int8,Int16,Int32,Int64}, f, F
153153
F(div_2f(z, Val(Int(f))) % T, 0)
154154
end
155155

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

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

test/fixed.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,13 @@ end
409409
@test all(((x, y),) -> !(typemin(F) <= fmul(x, y) <= typemax(F)) ||
410410
wrapping_mul(x, y) === checked_mul(x, y), xys)
411411
end
412+
413+
FixedPointNumbers.mul_with_rounding(1.5Q6f1, 0.5Q6f1, RoundNearest) === 1.0Q6f1
414+
FixedPointNumbers.mul_with_rounding(1.5Q6f1, -0.5Q6f1, RoundNearest) === -1.0Q6f1
415+
FixedPointNumbers.mul_with_rounding(1.5Q6f1, 0.5Q6f1, RoundNearestTiesUp) === 1.0Q6f1
416+
FixedPointNumbers.mul_with_rounding(1.5Q6f1, -0.5Q6f1, RoundNearestTiesUp) === -0.5Q6f1
417+
FixedPointNumbers.mul_with_rounding(1.5Q6f1, 0.5Q6f1, RoundDown) === 0.5Q6f1
418+
FixedPointNumbers.mul_with_rounding(1.5Q6f1, -0.5Q6f1, RoundDown) === -1.0Q6f1
412419
end
413420

414421
@testset "rounding" begin

0 commit comments

Comments
 (0)