From 8e8b3830586d5c9095a1c559b9630f807de59e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20Baru=C4=8Di=C4=87?= Date: Wed, 16 Oct 2024 21:19:10 +0200 Subject: [PATCH] Initial hashing support The performance can be improved but this already works. --- src/decimal.jl | 23 +++++++++++++++++++++++ test/test_decimal.jl | 18 ++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/src/decimal.jl b/src/decimal.jl index 11da6ca..addba64 100644 --- a/src/decimal.jl +++ b/src/decimal.jl @@ -77,3 +77,26 @@ end # sign Base.signbit(x::Decimal) = x.s +function isdivisible(x::BigInt, n::Int) + return x % n == 0 +end + +function Base.decompose(x::Decimal) + if iszero(x) + return (big(0), 0, big((-1)^x.s)) + end + + coef = (-1)^x.s * x.c + + if x.q ≥ 0 + return (coef * big(5)^x.q, x.q, big(1)) + else + q = -x.q + while q > 0 && isdivisible(coef, 5) + coef = coef ÷ 5 + q -= 1 + end + return (coef, x.q, big(5) ^ q) + end +end + diff --git a/test/test_decimal.jl b/test/test_decimal.jl index 57c7c3c..716ccc4 100644 --- a/test/test_decimal.jl +++ b/test/test_decimal.jl @@ -80,4 +80,22 @@ end @test string(number(Decimal(false, 543, -1))) == "54.3" end +@testset "Hashing" begin + @test hash(Decimal(0.)) == hash(0.) + @test hash(Decimal(-0.)) == hash(-0.) + @test hash(Decimal(3)) == hash(3) + @test hash(Decimal(0.09375)) == hash(0.09375) + @test hash(Decimal(-3)) == hash(-3) + @test hash(Decimal(-0.09375)) == hash(-0.09375) + + # Equality implies same hash + @test hash(Decimal(0, 100, 0)) == hash(Decimal(0, 10, 1)) + @test hash(Decimal(0, 100, 0)) == hash(Decimal(0, 1, 2)) + @test hash(Decimal(1, 100, 0)) == hash(Decimal(1, 10, 1)) + @test hash(Decimal(1, 100, 0)) == hash(Decimal(1, 1, 2)) + + @test hash(Decimal(0, 310, -2)) == hash(Decimal(0, 31, -1)) end + +end +