[ANN] Decimal 0.0 released

T

Tadashi Saito

Hello all,

I released Decimal 0.0 somehow, an arithmetic extension library for Ruby.

http://decimal.rubyforge.org/

Decimal is the multi-precision decimal arithmetic library, which designed to
be comfortable with the existing Numeric classes first. I'd like to make it
useful alike BigDecimal, that is in stdlib as you know.

My purpose of the release is "to release," so its tarball must contains many
bugs in contrast to full of NO documents. However, I guess you can use it
like BigDecimals and Floats, because most of the methods you need are already
implemented briefly.


....needs other explanations? Yep, I'll show you some commands and its
results, instead of detailed self-introduction.
(note that my product's name is shorter one)

$ cd ~/svn/ruby/trunk/ext/bigdecimal/
$ wc -c bigdecimal.[ch]
123348 bigdecimal.c
8031 bigdecimal.h
131379 total

$ cd ~/svn/decimal/trunk/
$ wc -c decimal.c
37997 decimal.c

$ time ruby -rbigdecimal -e 'BigDecimal("1.1") ** (2 ** 16)'

real 0m9.462s
user 0m9.433s
sys 0m0.008s

$ time ruby -rdecimal -e 'Decimal("1.1") ** (2 ** 16)'

real 0m0.338s
user 0m0.328s
sys 0m0.000s

$ cat mem.rb
def mem
File.read("/proc/#{$$}/status").grep(/VmSize/)
end

$ ruby -rmem -rbigdecimal -e 'GC.disable; d=BigDecimal("1"); 2_000_000.times {d+d}; puts mem'
VmSize: 129208 kB

$ ruby -rmem -rdecimal -e 'GC.disable; d=Decimal(1); 2_000_000.times {d+d}; puts mem'
VmSize: 82340 kB


These improved your image?

In addition, this is my first release of software products. I'm little
unsure of myself, so I welcome any comments from the community to a novice.

# I hope it will be included in Ruby trunk, before the 1.9.0xFF was released.
 
A

Alex Shulgin

Hello all,

I released Decimal 0.0 somehow, an arithmetic extension library for Ruby.

http://decimal.rubyforge.org/
....

$ time ruby -rbigdecimal -e 'BigDecimal("1.1") ** (2 ** 16)'

real 0m9.462s
user 0m9.433s
sys 0m0.008s

$ time ruby -rdecimal -e 'Decimal("1.1") ** (2 ** 16)'

real 0m0.338s
user 0m0.328s
sys 0m0.000s

$ cat mem.rb
def mem
File.read("/proc/#{$$}/status").grep(/VmSize/)
end

$ ruby -rmem -rbigdecimal -e 'GC.disable; d=BigDecimal("1"); 2_000_000.times {d+d}; puts mem'
VmSize: 129208 kB

$ ruby -rmem -rdecimal -e 'GC.disable; d=Decimal(1); 2_000_000.times {d+d}; puts mem'
VmSize: 82340 kB

These improved your image?

In addition, this is my first release of software products. I'm little
unsure of myself, so I welcome any comments from the community to a novice.

Very impressive! :)

IANAL, but you might want to add license notice to `decimal.c'. The
copyright line alone would mean no rights for users if they copy the
file out of the package (which includes the license text).

Just curious what made you develop another decimal library--is
BigDecimal unhackable or does your library uses totally different
approach, or something else? ;-)
 
S

Sam Smoot

Hello all,

I released Decimal 0.0 somehow, an arithmetic extension library for Ruby.

 http://decimal.rubyforge.org/

Decimal is the multi-precision decimal arithmetic library, which designed to
be comfortable with the existing Numeric classes first.  I'd like to make it
useful alike BigDecimal, that is in stdlib as you know.

My purpose of the release is "to release," so its tarball must contains many
bugs in contrast to full of NO documents.  However, I guess you can use it
like BigDecimals and Floats, because most of the methods you need are already
implemented briefly.

...needs other explanations?  Yep, I'll show you some commands and its
results, instead of detailed self-introduction.
(note that my product's name is shorter one)

$ cd ~/svn/ruby/trunk/ext/bigdecimal/
$ wc -c bigdecimal.[ch]
123348 bigdecimal.c
  8031 bigdecimal.h
131379 total

$ cd ~/svn/decimal/trunk/
$ wc -c decimal.c
 37997 decimal.c

$ time ruby -rbigdecimal -e 'BigDecimal("1.1") ** (2 ** 16)'

real    0m9.462s
user    0m9.433s
sys     0m0.008s

$ time ruby -rdecimal -e 'Decimal("1.1") ** (2 ** 16)'

real    0m0.338s
user    0m0.328s
sys     0m0.000s

$ cat mem.rb
def mem
  File.read("/proc/#{$$}/status").grep(/VmSize/)
end

$ ruby -rmem -rbigdecimal -e 'GC.disable; d=BigDecimal("1"); 2_000_000.times {d+d}; puts mem'
VmSize:   129208 kB

$ ruby -rmem -rdecimal -e 'GC.disable; d=Decimal(1); 2_000_000.times {d+d}; puts mem'
VmSize:    82340 kB

These improved your image?

In addition, this is my first release of software products.  I'm little
unsure of myself, so I welcome any comments from the community to a novice..

# I hope it will be included in Ruby trunk, before the 1.9.0xFF was released.

Very nice. I'd love to see this developed further. As a contributor to
DataMapper, one of the things I'm most interested in is faster/less-
memory-hungry "Primitive" types.

I could see a library like yours having a big impact... keep up the
good work, and please, let us know the moment you think it's ready for
wide-spread use! :)
 
T

Tadashi Saito

Hi,

Very impressive! :)

Thank you for your comment!
IANAL, but you might want to add license notice to `decimal.c'. The
copyright line alone would mean no rights for users if they copy the
file out of the package (which includes the license text).

Oh, you are right. I've been followed the style of the body's source code
too much ;) I added the notices to my source, and released as 0.0.1.
Thanks for pointing out.

http://decimal.rubyforge.org/
Just curious what made you develop another decimal library--is
BigDecimal unhackable or does your library uses totally different
approach, or something else? ;-)

There are two reason for reinventing.

The first is a note of discord in the interface of BigDecimal.
As the recent discussions in the ruby-dev, BigDecimal needs far different
usage than Numeric classes that have been built-in'ed and attached as the
stdlib, before the 1.8.

For instance, BigDecimal#{floor,round,ceil,truncate} returns a BigDecimal
object, not an Integer. I and some core developer thought this behavior can
confuse users who know about the same name methods in Float, but the author
didn't change the spec. i.e., "BigDecimal("1.1").truncate.to_s" returns
"0.1E1", not "1".

In other places, many odd behaviors are surveyed from my point of view:

- BigDecimal.mode is too complicated method only in BigDecimal, and
it's not MT-safe

- BigDecimal.limit is also non MT-safe, and you can't write like
"BigDecimal.limit = 10" as other library does.

- No one knows exact meaning of BigDecimal.new's second argument.

- BigDecimal#{add,sub,mult,div}(b, n) is also characteristic feature
only in BigDecimal, but it is only the alias of "a = b + c; a.round(n)"
except you cannot direct rounding mode each time.

- For the last reason, Numeric#div cannot behave like other Numerics;
user need to be remember that semantics of BigDecimal#div can change by
its arguments' number.

- BigDecimal#to_s() returns far different format than other's. My feeling
of wrongness is shared with Rails' implementation:
def to_s(format="F")
_original_to_s(format)
end

- As you see, BigDecimal#to_s can take one argument for formatting,
but the grammer is totaly unique so users cannot make good use of
their experiences.

- BigDecimal#inspect and #precs returns internal array size, but who
wants to know about private situations? Bignum never show it, accoding
to the principle of encapsulation.

- BigDecimal#sign is also original feature that can return "NaN" or
"Infinity", but I don't think these are "signs." I guess the spec
is introduced from the naked implementation, and I don't think it's the
right way to design the interfaces.

- BigDecimal#split is straight destructive interface for the OOP.

- We have BigDecimal#**, but why BigDecimal#power is exist? The method that
have such name is not exist in other's.

- You should write like "x.sqrt" not similar to other's style,
"Math.sqrt(x)" or "include Math; sqrt(x)".

- If you need to convert BigDecimals to other Numerics each other, you also
need to "require 'bigdecimal/util'" every time. In contrast,
Rational/Complex defines necessity methods automatically.

- etc, etc...

I may lose some reasons that needed to write here. But anyway, I decided
to redesign it.
(The features that lack in Decimal will be written from now on, of course!)


You may be already tired to read (sorry ;-), but I've never say about the
second reason. It is, to avoid the "maintaining of reinvention" anymore.
(Some person may call this "DRY principle")

As D. E. Knuth said is his book[1], it is very easy to implement multi-precision
decimal library if you have the library for the big integers. Most lines of
BigDecimal make effort to _reinvent_ multi-precision integers, but, as you know,
we _already_ have Bignums and it is exported as C API as rb_big_*().
Using this, I implemented nothing about complex problems as you see in decimal.c:
#define INUM_PLUS(a, b) (FIXNUM_P(a) ? fix_plus(a, b) : rb_big_plus(a, b))

You may feel this is "totally different approach" than BigDecimal's.

The code size of Decimal is over 3 times smaller than BigDecimal's one.
I believe the reinvention is worth enough if it contributes simplification.

In addition, we can receive benefits of Bignum's stability and optimization,
that are acquired in 13 years as Ruby's built-in library. There is FFT patch
for multiplication of huge value in ruby-dev already.

The summary of the second reason:

"There are two choices here. One is 13-years matured and well-used, another is
only 5 years old and used optionally. Which do you want?"

I chose the former.


[1] Donald E. Knuth: The Art of Computer Programming, Volume 2: Seminumerical
Algorithms (3rd Edition) [978-0201896848]
 
T

Tadashi Saito

Hello,

Very nice. I'd love to see this developed further. As a contributor to
DataMapper, one of the things I'm most interested in is faster/less-
memory-hungry "Primitive" types.

Thank you for your comment. My motivation of developing low-layer library
is to be used from high-layer common library like your DataMapper, and my
goal is to take *real* effect for high-layer programmer and the application
program user.
I could see a library like yours having a big impact... keep up the
good work, and please, let us know the moment you think it's ready for
wide-spread use! :)

If you are interested, the basic (or too much!) ideas are in [ruby-talk:291318].
In fact, the core part of my library is "Bignum" itself that is widely used
over 13 years, as you know.

Therefore, 90% of my brain power is used for interface design in reality.
Some bugs about counting decimal places or rounding will be discovered,
but maintaining complicated code, in bignum.c of Ruby's body, is not my job
but Matz's ;)
 
T

Tadashi Saito

- BigDecimal#inspect and #precs returns internal array size, but who
wants to know about private situations? Bignum never show it, accoding
to the principle of encapsulation.

Oops, I was wrong because Bignum#size is exist. If there're some resonable
comment I'll implement Decimal#size, but I still cannot hit on its usage.
 
A

Alex Shulgin

"There are two choices here. One is 13-years matured and well-used, another is
only 5 years old and used optionally. Which do you want?"

I chose the former.

OK, I see your point. As have no experience with BigDecimal, I just
wondered why people reinvent things--now I see there are perfectly
valid reasons. :)
 
W

Wilson Bilkovich

Hi,



Thank you for your comment!


Oh, you are right. I've been followed the style of the body's source code
too much ;) I added the notices to my source, and released as 0.0.1.
Thanks for pointing out.

http://decimal.rubyforge.org/

Thank you very much for implementing this.
I have been struggling with getting BigDecimal support into Rubinius,
and this has a much cleaner API.

--Wilson.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,439
Members
44,829
Latest member
PIXThurman

Latest Threads

Top