Hi,

On Sat, 16 Feb 2008 04:42:34 -0800 (PST)
Alex Shulgin <alex.shulgin / gmail.com> wrote:

> 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]
-- 
Tadashi Saito

# sorry for too long and broken english article :-p