diff --git a/src/FixedPointNumbers.jl b/src/FixedPointNumbers.jl index 970cd8cb..c37baec4 100644 --- a/src/FixedPointNumbers.jl +++ b/src/FixedPointNumbers.jl @@ -12,7 +12,7 @@ import Base: ==, <, <=, -, +, *, /, ~, isapprox, import Statistics # for _mean_promote import Random: Random, AbstractRNG, SamplerType, rand! -import Base.Checked: checked_neg, checked_add, checked_sub, checked_div +import Base.Checked: checked_neg, checked_add, checked_sub, checked_mul, checked_div using Base: @pure @@ -36,8 +36,8 @@ export # Q and N typealiases are exported in separate source files # Functions scaledual, - wrapping_neg, wrapping_add, wrapping_sub, - saturating_neg, saturating_add, saturating_sub + wrapping_neg, wrapping_add, wrapping_sub, wrapping_mul, + saturating_neg, saturating_add, saturating_sub, saturating_mul include("utilities.jl") @@ -56,6 +56,9 @@ nbitsint(::Type{X}) where {X <: FixedPoint} = bitwidth(X) - nbitsfrac(X) - signb # construction using the (approximate) intended value, i.e., N0f8 *(x::Real, ::Type{X}) where {X <: FixedPoint} = _convert(X, x) +wrapping_mul(x::Real, ::Type{X}) where {X <: FixedPoint} = x % X +saturating_mul(x::Real, ::Type{X}) where {X <: FixedPoint} = clamp(x, X) +checked_mul(x::Real, ::Type{X}) where {X <: FixedPoint} = _convert(X, x) # constructor-style conversions (::Type{X})(x::X) where {X <: FixedPoint} = x diff --git a/test/fixed.jl b/test/fixed.jl index 251934b8..c50a82ef 100644 --- a/test/fixed.jl +++ b/test/fixed.jl @@ -64,6 +64,23 @@ end @test_throws DomainError zero(Fixed{Int16,17}) end +@testset "construction using type suffix" begin + @test 0.635Q0f7 === Q0f7(0.635) + @test 0.635Q5f10 === Q5f10(0.635) + @test 0.635Q3f12 === Q3f12(0.635) + @test 0.635Q1f14 === Q1f14(0.635) + @test 0.635Q0f15 === Q0f15(0.635) + + @test_throws ArgumentError 1.1Q0f7 + + @test wrapping_mul(0.635, Q0f7) === Q0f7(0.635) + @test wrapping_mul(1.635, Q0f7) === Q0f7(-0.365) + @test saturating_mul(0.635, Q0f7) === Q0f7(0.635) + @test saturating_mul(1.635, Q0f7) === Q0f7(0.992) + @test checked_mul(0.635, Q0f7) === Q0f7(0.635) + @test_throws ArgumentError checked_mul(1.635, Q0f7) +end + @testset "reinterpret/bitstring" begin @test reinterpret(Q0f7, signed(0xa2)) === -0.734375Q0f7 @test reinterpret(Q5f10, signed(0x00a2)) === 0.158203125Q5f10 diff --git a/test/normed.jl b/test/normed.jl index 6c751724..4a5b59ec 100644 --- a/test/normed.jl +++ b/test/normed.jl @@ -12,6 +12,23 @@ end @test_throws DomainError zero(Normed{UInt16,17}) end +@testset "construction using type suffix" begin + @test 0.635N0f8 === N0f8(0.635) + @test 0.635N6f10 === N6f10(0.635) + @test 0.635N4f12 === N4f12(0.635) + @test 0.635N2f14 === N2f14(0.635) + @test 0.635N0f16 === N0f16(0.635) + + @test_throws ArgumentError 1.1N0f8 + + @test wrapping_mul(0.635, N0f8) === N0f8(0.635) + @test wrapping_mul(1.635, N0f8) === N0f8((1.635 * 255 - 256) / 255) + @test saturating_mul(0.635, N0f8) === N0f8(0.635) + @test saturating_mul(1.635, N0f8) === N0f8(1.0) + @test checked_mul(0.635, N0f8) === N0f8(0.635) + @test_throws ArgumentError checked_mul(1.635, N0f8) +end + @testset "reinterpret/bitstring" begin @test reinterpret(N0f8, 0xa2).i === 0xa2 @test reinterpret(N6f10, 0x1fa2).i === 0x1fa2 @@ -30,12 +47,6 @@ end @test bitstring(reinterpret(N0f8, 0xa2)) === "10100010" @test bitstring(reinterpret(N6f10, 0x00a2)) === "0000000010100010" - @test 0.635N0f8 == N0f8(0.635) - @test 0.635N6f10 == N6f10(0.635) - @test 0.635N4f12 == N4f12(0.635) - @test 0.635N2f14 == N2f14(0.635) - @test 0.635N0f16 == N0f16(0.635) - @test N0f8(1.0) == reinterpret(N0f8, 0xff) @test N0f8(0.5) == reinterpret(N0f8, 0x80) @test N2f14(1.0) == reinterpret(N2f14, 0x3fff)