diff options
author | knu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-02-05 14:11:08 +0000 |
---|---|---|
committer | knu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2010-02-05 14:11:08 +0000 |
commit | d2e30d50cf20a87f6d2e8a2cfd2b559af6da28bf (patch) | |
tree | 02c2fc5104feac11b2723360d56aa22a544d3a57 /ext/rational/rational.c | |
parent | 4abbe7814af053438de0c863b0e0803dae79804a (diff) |
* ext/rational/rational.c: Added to provide a fast implementation
of Fixnum#gcd (and maybe some others in the future) in C. The
base code was submitted by Kurt Stephens. [Feature #2561]
* ext/rational/lib/rational.rb: Moved from lib/rational.rb. Make
overall code optimization; submitted by Kurt Stephens.
[Feature #2561]
* test/rational/test_rational.rb, test/rational/test_rational2.rb:
Add tests for Rational, ported from trunk.
* test/rational/test_fixnum_gcd.rb: Add a test for Integer#gcd.
Case values are only provided for i386 and amd64 at the moment;
submitted by Kurt Stephens. [Feature #2561]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8@26581 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/rational/rational.c')
-rw-r--r-- | ext/rational/rational.c | 42 |
1 files changed, 42 insertions, 0 deletions
diff --git a/ext/rational/rational.c b/ext/rational/rational.c new file mode 100644 index 0000000000..18024e9497 --- /dev/null +++ b/ext/rational/rational.c @@ -0,0 +1,42 @@ +#include "ruby.h" + +/* + * call-seq: + * fixnum.gcd(fixnum) -> fixnum + * + * Fixnum-specific optimized version of Integer#gcd. Delegates to + * Integer#gcd as necessary. + */ +static VALUE +fix_gcd(self, other) + VALUE self, other; +{ + long a, b, min, max; + + /* + * Note: Cannot handle values <= FIXNUM_MIN here due to overflow during negation. + */ + if (!FIXNUM_P(other) || + (a = FIX2LONG(self)) <= FIXNUM_MIN || + (b = FIX2LONG(other)) <= FIXNUM_MIN ) { + /* Delegate to Integer#gcd */ + return rb_call_super(1, &other); + } + + min = a < 0 ? -a : a; + max = b < 0 ? -b : b; + + while (min > 0) { + long tmp = min; + min = max % min; + max = tmp; + } + + return LONG2FIX(max); +} + +void +Init_rational() +{ + rb_define_method(rb_cFixnum, "gcd", fix_gcd, 1); +} |