summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorYukihiro "Matz" Matsumoto <[email protected]>2019-05-17 16:37:34 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2019-05-17 16:37:34 +0900
commitb6e9fab64949b91f00d07c890935642f44147615 (patch)
tree13bfb6eb1889d82cdfb9d323b55293473cc9837c
parentcec92673ae9e24d73a6feb2d69602b5fa60dcddd (diff)
downloadmruby-b6e9fab64949b91f00d07c890935642f44147615.tar.gz
mruby-b6e9fab64949b91f00d07c890935642f44147615.zip
Implement part of `Rational` in C.
-rw-r--r--mrbgems/mruby-rational/mrblib/rational.rb43
-rw-r--r--mrbgems/mruby-rational/src/rational.c90
2 files changed, 102 insertions, 31 deletions
diff --git a/mrbgems/mruby-rational/mrblib/rational.rb b/mrbgems/mruby-rational/mrblib/rational.rb
index a38f71407..54324b05f 100644
--- a/mrbgems/mruby-rational/mrblib/rational.rb
+++ b/mrbgems/mruby-rational/mrblib/rational.rb
@@ -2,29 +2,10 @@ class Rational < Numeric
# Override #<, #<=, #>, #>= in Numeric
prepend Comparable
- def initialize(numerator = 0, denominator = 1)
- @numerator = numerator
- @denominator = denominator
-
- _simplify
- end
-
def inspect
"(#{to_s})"
end
- def to_f
- @numerator.to_f / @denominator.to_f
- end
-
- def to_i
- to_f.to_i
- end
-
- def to_r
- self
- end
-
def to_s
"#{numerator}/#{denominator}"
end
@@ -86,24 +67,24 @@ class Rational < Numeric
nil
end
end
+end
- def negative?
- numerator.negative?
- end
-
- def _simplify
- a = numerator
- b = denominator
- a, b = b, a % b until b.zero?
- @numerator = @numerator.div(a)
- @denominator = @denominator.div(a)
+class << Numeric
+ def to_r
+ Rational(self, 1)
end
+end
- attr_reader :numerator, :denominator
+class << Rational
+ alias_method :_new, :new
+ undef_method :new
end
def Rational(numerator = 0, denominator = 1)
- Rational.new(numerator, denominator)
+ a = numerator
+ b = denominator
+ a, b = b, a % b until b.zero?
+ Rational._new(numerator.div(a), denominator.div(a))
end
[:+, :-, :*, :/, :<=>, :==, :<, :<=, :>, :>=].each do |op|
diff --git a/mrbgems/mruby-rational/src/rational.c b/mrbgems/mruby-rational/src/rational.c
new file mode 100644
index 000000000..14a9b045d
--- /dev/null
+++ b/mrbgems/mruby-rational/src/rational.c
@@ -0,0 +1,90 @@
+#include <mruby.h>
+#include <mruby/class.h>
+#include <mruby/string.h>
+#include <mruby/istruct.h>
+
+struct mrb_rational {
+ mrb_int numerator;
+ mrb_int denominator;
+};
+
+static struct mrb_rational*
+rational_ptr(mrb_value v)
+{
+ return (struct mrb_rational*)mrb_istruct_ptr(v);
+}
+
+static mrb_value
+rational_numerator(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_rational *p = rational_ptr(self);
+ return mrb_fixnum_value(p->numerator);
+}
+
+static mrb_value
+rational_denominator(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_rational *p = rational_ptr(self);
+ return mrb_fixnum_value(p->denominator);
+}
+
+static mrb_value
+rational_initialize(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_rational *p = rational_ptr(self);
+ mrb_get_args(mrb, "ii", &p->numerator, &p->denominator);
+ return self;
+}
+
+static mrb_value
+rational_to_f(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_rational *p = rational_ptr(self);
+ mrb_float f = (mrb_float)p->numerator / (mrb_float)p->denominator;
+
+ return mrb_float_value(mrb, f);
+}
+
+static mrb_value
+rational_to_i(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_rational *p = rational_ptr(self);
+ return mrb_fixnum_value(p->numerator / p->denominator);
+}
+
+static mrb_value
+rational_to_r(mrb_state *mrb, mrb_value self)
+{
+ return self;
+}
+
+static mrb_value
+rational_negative_p(mrb_state *mrb, mrb_value self)
+{
+ struct mrb_rational *p = rational_ptr(self);
+ if (p->numerator < 0) {
+ return mrb_true_value();
+ }
+ return mrb_false_value();
+}
+
+void mrb_mruby_rational_gem_init(mrb_state *mrb)
+{
+ struct RClass *rat;
+
+ mrb_assert(sizeof(struct mrb_rational) < ISTRUCT_DATA_SIZE);
+ rat = mrb_define_class(mrb, "Rational", mrb_class_get(mrb, "Numeric"));
+ MRB_SET_INSTANCE_TT(rat, MRB_TT_ISTRUCT);
+ mrb_define_method(mrb, rat, "numerator", rational_numerator, MRB_ARGS_NONE());
+ mrb_define_method(mrb, rat, "denominator", rational_denominator, MRB_ARGS_NONE());
+ mrb_define_method(mrb, rat, "initialize", rational_initialize, MRB_ARGS_REQ(2));
+ mrb_define_method(mrb, rat, "to_f", rational_to_f, MRB_ARGS_NONE());
+ mrb_define_method(mrb, rat, "to_i", rational_to_i, MRB_ARGS_NONE());
+ mrb_define_method(mrb, rat, "to_r", rational_to_r, MRB_ARGS_NONE());
+ mrb_define_method(mrb, rat, "negative?", rational_negative_p, MRB_ARGS_NONE());
+}
+
+void
+mrb_mruby_rational_gem_final(mrb_state* mrb)
+{
+}