summaryrefslogtreecommitdiffhomepage
path: root/mrbgems/mruby-rational
diff options
context:
space:
mode:
authorUkrainskiy Sergey <[email protected]>2018-09-09 11:57:16 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2019-05-15 16:57:21 +0900
commitd67d2ae8e88b93536e71dfa41a90721ce351da7c (patch)
tree25b8e534e0864817bf05dee8022004fa04e22fc7 /mrbgems/mruby-rational
parent79c3335e8d22ec76340b3028a7bbc658d631b17c (diff)
downloadmruby-d67d2ae8e88b93536e71dfa41a90721ce351da7c.tar.gz
mruby-d67d2ae8e88b93536e71dfa41a90721ce351da7c.zip
Basic implementation of Complex and Rational classes
Diffstat (limited to 'mrbgems/mruby-rational')
-rw-r--r--mrbgems/mruby-rational/mrbgem.rake3
-rw-r--r--mrbgems/mruby-rational/mrblib/rational.rb100
-rw-r--r--mrbgems/mruby-rational/test/rational.rb41
3 files changed, 115 insertions, 29 deletions
diff --git a/mrbgems/mruby-rational/mrbgem.rake b/mrbgems/mruby-rational/mrbgem.rake
index 4b540dec4..496082709 100644
--- a/mrbgems/mruby-rational/mrbgem.rake
+++ b/mrbgems/mruby-rational/mrbgem.rake
@@ -2,4 +2,7 @@ MRuby::Gem::Specification.new('mruby-rational') do |spec|
spec.license = 'MIT'
spec.author = 'mruby developers'
spec.summary = 'Rational class'
+
+ spec.add_dependency 'mruby-object-ext', core: 'mruby-object-ext'
+ spec.add_dependency 'mruby-numeric-ext', core: 'mruby-numeric-ext'
end
diff --git a/mrbgems/mruby-rational/mrblib/rational.rb b/mrbgems/mruby-rational/mrblib/rational.rb
index 457c0488a..ffadd55eb 100644
--- a/mrbgems/mruby-rational/mrblib/rational.rb
+++ b/mrbgems/mruby-rational/mrblib/rational.rb
@@ -2,45 +2,89 @@ class Rational < Numeric
def initialize(numerator = 0, denominator = 1)
@numerator = numerator
@denominator = denominator
+
+ _simplify
end
- attr_reader :numerator, :denominator
-end
+ def inspect
+ "(#{to_s})"
+ end
-def Rational(numerator = 0, denominator = 1)
- Rational.new(numerator, denominator)
-end
+ def to_s
+ "#{numerator}/#{denominator}"
+ end
-module ForwardOperatorToRational
- def __forward_operator_to_rational(op, &b)
- original_operator_name = "__original_operator_#{op}_rational"
- alias_method original_operator_name, op
- define_method op do |rhs|
- if rhs.is_a? Rational
- Rational.new(self).send(op, rhs)
- else
- send(original_operator_name, rhs)
- end
+ def *(rhs)
+ if rhs.is_a? Rational
+ Rational(numerator * rhs.numerator, denominator * rhs.denominator)
+ elsif rhs.is_a? Integer
+ Rational(numerator * rhs, denominator)
+ elsif rhs.is_a? Numeric
+ numerator * rhs / denominator
+ end
+ end
+
+ def +(rhs)
+ if rhs.is_a? Rational
+ Rational(numerator * rhs.denominator + rhs.numerator * denominator, denominator * rhs.denominator)
+ elsif rhs.is_a? Integer
+ Rational(numerator + rhs * denominator, denominator)
+ elsif rhs.is_a? Numeric
+ (numerator + rhs * denominator) / denominator
+ end
+ end
+
+ def -(rhs)
+ if rhs.is_a? Rational
+ Rational(numerator * rhs.denominator - rhs.numerator * denominator, denominator * rhs.denominator)
+ elsif rhs.is_a? Integer
+ Rational(numerator - rhs * denominator, denominator)
+ elsif rhs.is_a? Numeric
+ (numerator - rhs * denominator) / denominator
end
end
- def __forward_operators_to_rational
- __forward_operator_to_rational :+
- __forward_operator_to_rational :-
- __forward_operator_to_rational :*
- __forward_operator_to_rational :/
+ def /(rhs)
+ if rhs.is_a? Rational
+ Rational(numerator * rhs.denominator, denominator * rhs.numerator)
+ elsif rhs.is_a? Integer
+ Rational(numerator, denominator * rhs)
+ elsif rhs.is_a? Numeric
+ numerator / rhs / denominator
+ end
+ end
- singleton_class.undef_method :__forward_operator_to_rational
- singleton_class.undef_method :__forward_operators_to_rational
+ def negative?
+ numerator.negative?
end
+
+ def _simplify
+ a = numerator
+ b = denominator
+ a, b = b, a % b while !b.zero?
+ @numerator /= a
+ @denominator /= a
+ end
+
+ attr_reader :numerator, :denominator
end
-class Fixnum
- extend ForwardOperatorToRational
- __forward_operators_to_rational
+def Rational(numerator = 0, denominator = 1)
+ Rational.new(numerator, denominator)
end
-class Float
- extend ForwardOperatorToRational
- __forward_operators_to_rational
+[Fixnum, Float].each do |cls|
+ [:+, :-, :*, :/, :==].each do |op|
+ cls.instance_exec do
+ original_operator_name = "__original_operator_#{op}_rational"
+ alias_method original_operator_name, op
+ define_method op do |rhs|
+ if rhs.is_a? Rational
+ Rational(self).send(op, rhs)
+ else
+ send(original_operator_name, rhs)
+ end
+ end
+ end
+ end
end \ No newline at end of file
diff --git a/mrbgems/mruby-rational/test/rational.rb b/mrbgems/mruby-rational/test/rational.rb
index 6f20a6cd4..a86f00690 100644
--- a/mrbgems/mruby-rational/test/rational.rb
+++ b/mrbgems/mruby-rational/test/rational.rb
@@ -1,3 +1,42 @@
+def assert_rational(real, exp)
+ assert_float real.numerator, exp.numerator
+ assert_float real.denominator, exp.denominator
+end
+
assert 'Rational' do
- assert_equal Rational, 0r.class
+ r = 5r
+ assert_equal Rational, r.class
+ assert_equal [r.numerator, r.denominator], [5, 1]
+end
+
+assert 'Rational#*' do
+ assert_rational Rational(2, 3) * Rational(2, 3), Rational(4, 9)
+ assert_rational Rational(900) * Rational(1), Rational(900, 1)
+ assert_rational Rational(-2, 9) * Rational(-9, 2), Rational(1, 1)
+ assert_rational Rational(9, 8) * 4, Rational(9, 2)
+ assert_float Rational(20, 9) * 9.8, 21.77777777777778
+end
+
+assert 'Rational#+' do
+ assert_rational Rational(2, 3) + Rational(2, 3), Rational(4, 3)
+ assert_rational Rational(900) + Rational(1), Rational(901, 1)
+ assert_rational Rational(-2, 9) + Rational(-9, 2), Rational(-85, 18)
+ assert_rational Rational(9, 8) + 4, Rational(41, 8)
+ assert_float Rational(20, 9) + 9.8, 12.022222222222222
+end
+
+assert 'Rational#-' do
+ assert_rational Rational(2, 3) - Rational(2, 3), Rational(0, 1)
+ assert_rational Rational(900) - Rational(1), Rational(899, 1)
+ assert_rational Rational(-2, 9) - Rational(-9, 2), Rational(77, 18)
+ assert_rational Rational(9, 8) - 4, Rational(-23, 8)
+ assert_float Rational(20, 9) - 9.8, -7.577777777777778
+end
+
+assert 'Rational#/' do
+ assert_rational Rational(2, 3) / Rational(2, 3), Rational(1, 1)
+ assert_rational Rational(900) / Rational(1), Rational(900, 1)
+ assert_rational Rational(-2, 9) / Rational(-9, 2), Rational(4, 81)
+ assert_rational Rational(9, 8) / 4, Rational(9, 32)
+ assert_float Rational(20, 9) / 9.8, 0.22675736961451246
end \ No newline at end of file