Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

package modernization including better type stability #42

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

ExpandingMan
Copy link

Seemed like this package needed a bit of an overhaul as it appears to be basically the default arbitrary precision decimal arithmetic package. It still needs a ton of work, but I think this is a good start. The most significant improvement is in type stability as the fields of Decimal are now concrete types.

At first I was going to make Decimal parametric with a type parameter for the exponent, but ultimately I decided that the benefit if this was pretty dubious, so I set the exponent to simply be an Int. Because of this, these changes should be pretty much non-breaking.

@coveralls
Copy link

coveralls commented Nov 22, 2019

Pull Request Test Coverage Report for Build 113

  • 12 of 15 (80.0%) changed or added relevant lines in 4 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-2.6%) to 92.638%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/decimal.jl 6 9 66.67%
Totals Coverage Status
Change from base Build 111: -2.6%
Covered Lines: 302
Relevant Lines: 326

💛 - Coveralls

@codecov-io
Copy link

codecov-io commented Nov 22, 2019

Codecov Report

Merging #42 into master will decrease coverage by 2.55%.
The diff coverage is 80%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #42      +/-   ##
==========================================
- Coverage   95.28%   92.72%   -2.56%     
==========================================
  Files           6        6              
  Lines         106      110       +4     
==========================================
+ Hits          101      102       +1     
- Misses          5        8       +3
Impacted Files Coverage Δ
src/round.jl 91.66% <ø> (ø) ⬆️
src/arithmetic.jl 80% <100%> (ø) ⬆️
src/equals.jl 100% <100%> (ø) ⬆️
src/Decimals.jl 100% <100%> (ø) ⬆️
src/decimal.jl 90.47% <66.66%> (-6.9%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b7f569e...b684caf. Read the comment docs.

Copy link
Contributor

@iamed2 iamed2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks fine from my perspective (LibPQ)

end
# Numerical value: (-1)^s * c * 10^q
struct Decimal <: AbstractFloat
s::Bool # sign can be 0 (+) or 1 (-)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we roll this into c ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was actually wondering the same thing, I just didn't bother to change it. I only spent about half an hour on this PR, mostly for the sake of type stability. If the separate sign bit really is unnecessary, suggest somebody make another PR later to change it.

Copy link
Contributor

@hurak hurak Nov 25, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me add another input. It appears that there is no standard for arbitrary precision decimal arithmetics (there is only IEEE 754-2008 standard introducing 32, 64, and 64-bit precisions - decimal32, decimal64 and decimal128, respectively, and these are already implemented in Julia package called DecFP). Since Decimals.jl package aims at implementing arbitrary precision decimal arithmetics, it may enjoy freedom from official standards. Good. Nonetheless, there is General Decimal Arithmetic Specification by IBM, which sort of extends the IEEE 754-2008 towards arbitrary precision. Perhaps it does not have the same status of official IEEE standards, but apparently, the now built-in Python package decimal is implementing it. I tried to sketch these relationships at the bottom of the front page (README.md).

Now, although I was not involved in the Decimals.jl package development (I only joined very recently) my perception of the package is that it might aim at the same goal as the Python's decimal. If this goal is shared, I think it would be wise to keep the arithmetic model as close as possible.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't necessarily dispute any of that, but this PR was just a quick update mostly to get rid of the unnecessary type instability. This package clearly could use a lot of work, I'd like it if we could merge this to get in what improvement we can for now and work can continue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should move this discusion into #44

@oxinabox oxinabox mentioned this pull request Nov 25, 2019
end
c, q = parameters(('.' in str) ? split(str, '.') : str)
normalize(Decimal((str[1] == '-') ? 1 : 0, c, q))
normalize(Decimal((str[1] == '-'), c, q))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
normalize(Decimal((str[1] == '-'), c, q))
normalize(Decimal(str[1] == '-', c, q))

@@ -60,8 +62,10 @@ function Base.print(io::IO, x::Decimal)
end

# Zero/one value
Base.zero(::Type{Decimal}) = Decimal(0,0,0)
Base.one(::Type{Decimal}) = Decimal(0,1,0)
Base.zero(::Type{Decimal}) = Decimal(false,0,0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Base.zero(::Type{Decimal}) = Decimal(false,0,0)
Base.zero(::Type{Decimal}) = Decimal(false, 0, 0)

Base.zero(::Type{Decimal}) = Decimal(0,0,0)
Base.one(::Type{Decimal}) = Decimal(0,1,0)
Base.zero(::Type{Decimal}) = Decimal(false,0,0)
Base.one(::Type{Decimal}) = Decimal(false,1,0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Base.one(::Type{Decimal}) = Decimal(false,1,0)
Base.one(::Type{Decimal}) = Decimal(false, 1, 0)

Base.signbit(x::Decimal) = x.s != 0
Base.signbit(x::Decimal) = x.s

Base.show(io::IO, x::Decimal) = write(io, "decimal(\""*string(x)*"\")")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Base.show(io::IO, x::Decimal) = write(io, "decimal(\""*string(x)*"\")")
Base.show(io::IO, x::Decimal) = write(io, "decimal(\"$x\")")


# Multiplication
function *(x::Decimal, y::Decimal)
function Base.:(*)(x::Decimal, y::Decimal)
s = (x.s == y.s) ? 0 : 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
s = (x.s == y.s) ? 0 : 1
s = x.s != y.s

@@ -17,25 +17,25 @@ function +(x::Decimal, y::Decimal)
end

# Negation
-(x::Decimal) = Decimal((x.s == 1) ? 0 : 1, x.c, x.q)
Base.:(-)(x::Decimal) = Decimal((x.s == 1) ? 0 : 1, x.c, x.q)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Base.:(-)(x::Decimal) = Decimal((x.s == 1) ? 0 : 1, x.c, x.q)
Base.:(-)(x::Decimal) = Decimal(!x.s, x.c, x.q)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants