From 8808219e6d51673e6fa582819703e6e5912439b0 Mon Sep 17 00:00:00 2001 From: Ukrainskiy Sergey Date: Thu, 9 Aug 2018 17:09:02 +0900 Subject: Initial suffix support --- mrbgems/mruby-rational/test/rational.rb | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 mrbgems/mruby-rational/test/rational.rb (limited to 'mrbgems/mruby-rational/test') diff --git a/mrbgems/mruby-rational/test/rational.rb b/mrbgems/mruby-rational/test/rational.rb new file mode 100644 index 000000000..6f20a6cd4 --- /dev/null +++ b/mrbgems/mruby-rational/test/rational.rb @@ -0,0 +1,3 @@ +assert 'Rational' do + assert_equal Rational, 0r.class +end \ No newline at end of file -- cgit v1.2.3 From d67d2ae8e88b93536e71dfa41a90721ce351da7c Mon Sep 17 00:00:00 2001 From: Ukrainskiy Sergey Date: Sun, 9 Sep 2018 11:57:16 +0900 Subject: Basic implementation of Complex and Rational classes --- mrbgems/default.gembox | 4 +- mrbgems/mruby-complex/mrbgem.rake | 4 + mrbgems/mruby-complex/mrblib/complex.rb | 155 ++++++++++++++++++++++-------- mrbgems/mruby-complex/test/complex.rb | 129 ++++++++++++++++++++++++- mrbgems/mruby-rational/mrbgem.rake | 3 + mrbgems/mruby-rational/mrblib/rational.rb | 100 +++++++++++++------ mrbgems/mruby-rational/test/rational.rb | 41 +++++++- 7 files changed, 363 insertions(+), 73 deletions(-) (limited to 'mrbgems/mruby-rational/test') diff --git a/mrbgems/default.gembox b/mrbgems/default.gembox index 501aee146..ae085309c 100644 --- a/mrbgems/default.gembox +++ b/mrbgems/default.gembox @@ -69,10 +69,10 @@ MRuby::GemBox.new do |conf| conf.gem :core => "mruby-enum-lazy" # Use Complex class - #conf.gem :core => "mruby-complex" + # conf.gem :core => "mruby-complex" # Use Rational class - #conf.gem :core => "mruby-rational" + # conf.gem :core => "mruby-rational" # Use toplevel object (main) methods extension conf.gem :core => "mruby-toplevel-ext" diff --git a/mrbgems/mruby-complex/mrbgem.rake b/mrbgems/mruby-complex/mrbgem.rake index f8f04d0b8..25b8966da 100644 --- a/mrbgems/mruby-complex/mrbgem.rake +++ b/mrbgems/mruby-complex/mrbgem.rake @@ -2,4 +2,8 @@ MRuby::Gem::Specification.new('mruby-complex') do |spec| spec.license = 'MIT' spec.author = 'mruby developers' spec.summary = 'Complex class' + + spec.add_dependency 'mruby-object-ext', core: 'mruby-object-ext' + spec.add_dependency 'mruby-numeric-ext', core: 'mruby-numeric-ext' + spec.add_dependency 'mruby-math', core: 'mruby-math' end diff --git a/mrbgems/mruby-complex/mrblib/complex.rb b/mrbgems/mruby-complex/mrblib/complex.rb index 0815c9a71..266c00c36 100644 --- a/mrbgems/mruby-complex/mrblib/complex.rb +++ b/mrbgems/mruby-complex/mrblib/complex.rb @@ -1,95 +1,168 @@ class Complex < Numeric - def initialize(real = 0, imaginary = 0) + def initialize(real, imaginary) + real = real.to_f unless real.is_a? Numeric + imaginary = imaginary.to_f unless imaginary.is_a? Numeric @real = real @imaginary = imaginary end + def self.polar(abs, arg = 0) + Complex(abs * Math.cos(arg), abs * Math.sin(arg)) + end + + def self.rectangular(real, imaginary = 0) + _new(real, imaginary) + end + def inspect "(#{to_s})" end def to_s - "#{real}#{'+'}#{imaginary}i" + "#{real}#{'+' unless imaginary.negative?}#{imaginary}i" end def +@ - Complex.new(real, imaginary) + Complex(real, imaginary) end def -@ - Complex.new(-real, -imaginary) + Complex(-real, -imaginary) end def +(rhs) if rhs.is_a? Complex - Complex.new(real + rhs.real, imaginary + rhs.imaginary) + Complex(real + rhs.real, imaginary + rhs.imaginary) elsif rhs.is_a? Numeric - Complex.new(real + rhs, imaginary) + Complex(real + rhs, imaginary) end end def -(rhs) if rhs.is_a? Complex - Complex.new(real - rhs.real, imaginary - rhs.imaginary) + Complex(real - rhs.real, imaginary - rhs.imaginary) elsif rhs.is_a? Numeric - Complex.new(real - rhs, imaginary) + Complex(real - rhs, imaginary) end end def *(rhs) if rhs.is_a? Complex - Complex.new(real * rhs.real - imaginary * rhs.imaginary, real * rhs.imaginary + rhs.real * imaginary) + Complex(real * rhs.real - imaginary * rhs.imaginary, real * rhs.imaginary + rhs.real * imaginary) elsif rhs.is_a? Numeric - Complex.new(real * rhs, imaginary * rhs) + Complex(real * rhs, imaginary * rhs) end end def /(rhs) if rhs.is_a? Complex div = rhs.real * rhs.real + rhs.imaginary * rhs.imaginary - Complex.new((real * rhs.real + imaginary * rhs.imaginary) / div, (rhs.real * imaginary - real * rhs.imaginary) / div) + Complex((real * rhs.real + imaginary * rhs.imaginary) / div, (rhs.real * imaginary - real * rhs.imaginary) / div) elsif rhs.is_a? Numeric - Complex.new(real / rhs, imaginary / rhs) + Complex(real / rhs, imaginary / rhs) end end + alias_method :quo, :/ - attr_reader :real, :imaginary -end + def ==(rhs) + if rhs.is_a? Complex + real == rhs.real && imaginary == rhs.imaginary + elsif rhs.is_a? Numeric + imaginary.zero? && real == rhs + end + end -def Complex(real = 0, imaginary = 0) - Complex.new(real, imaginary) -end + def abs + Math.sqrt(abs2) + end + alias_method :magnitude, :abs -module ForwardOperatorToComplex - def __forward_operator_to_complex(op, &b) - original_operator_name = "__original_operator_#{op}_complex" - alias_method original_operator_name, op - define_method op do |rhs| - if rhs.is_a? Complex - Complex.new(self).send(op, rhs) - else - send(original_operator_name, rhs) - end - end + def abs2 + real * real + imaginary * imaginary + end + + def arg + Math.atan2 imaginary, real + end + alias_method :angle, :arg + alias_method :phase, :arg + + def conjugate + Complex(real, -imaginary) + end + alias_method :conj, :conjugate + + def numerator + self + end + + def denominator + 1 + end + + def fdiv(numeric) + Complex(real.to_f / numeric, imaginary.to_f / numeric) + end + + def polar + [abs, arg] + end + + def real? + false end - def __forward_operators_to_complex - __forward_operator_to_complex :+ - __forward_operator_to_complex :- - __forward_operator_to_complex :* - __forward_operator_to_complex :/ + def rectangular + [real, imaginary] + end + alias_method :rect, :rectangular + + def to_c + self + end + + def to_f + raise RangeError.new "can't convert #{to_s} into Float" unless imaginary.zero? + real.to_f + end - singleton_class.undef_method :__forward_operator_to_complex - singleton_class.undef_method :__forward_operators_to_complex + def to_i + raise RangeError.new "can't convert #{to_s} into Integer" unless imaginary.zero? + real.to_i end + + def to_r + raise RangeError.new "can't convert #{to_s} into Rational" unless imaginary.zero? + Rational(real, 1) + end + + attr_reader :real, :imaginary + alias_method :imag, :imaginary +end + +class << Complex + alias_method :_new, :new + undef_method :new + + alias_method :rect, :rectangular end -class Fixnum - extend ForwardOperatorToComplex - __forward_operators_to_complex +def Complex(real, imaginary = 0) + Complex.rectangular(real, imaginary) end -class Float - extend ForwardOperatorToComplex - __forward_operators_to_complex +[Fixnum, Float].each do |cls| + [:+, :-, :*, :/, :==].each do |op| + cls.instance_exec do + original_operator_name = "__original_operator_#{op}_complex" + alias_method original_operator_name, op + define_method op do |rhs| + if rhs.is_a? Complex + Complex(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-complex/test/complex.rb b/mrbgems/mruby-complex/test/complex.rb index 890dd4ff1..ca58202c2 100644 --- a/mrbgems/mruby-complex/test/complex.rb +++ b/mrbgems/mruby-complex/test/complex.rb @@ -1,3 +1,130 @@ +def assert_complex(real, exp) + assert_float real.real, exp.real + assert_float real.imaginary, exp.imaginary +end + assert 'Complex' do - assert_equal Complex, 0i.class + c = 123i + assert_equal Complex, c.class + assert_equal [c.real, c.imaginary], [0, 123] + c = 123 + -1.23i + assert_equal Complex, c.class + assert_equal [c.real, c.imaginary], [123, -1.23] +end + +assert 'Complex::polar' do + assert_complex Complex.polar(3, 0), (3 + 0i) + assert_complex Complex.polar(3, Math::PI/2), (0 + 3i) + assert_complex Complex.polar(3, Math::PI), (-3 + 0i) + assert_complex Complex.polar(3, -Math::PI/2), (0 + -3i) +end + +assert 'Complex::rectangular' do + assert_complex Complex.rectangular(1, 2), (1 + 2i) +end + +assert 'Complex#*' do + assert_complex Complex(2, 3) * Complex(2, 3), (-5 + 12i) + assert_complex Complex(900) * Complex(1), (900 + 0i) + assert_complex Complex(-2, 9) * Complex(-9, 2), (0 - 85i) + assert_complex Complex(9, 8) * 4, (36 + 32i) + assert_complex Complex(20, 9) * 9.8, (196.0 + 88.2i) +end + +assert 'Complex#+' do + assert_complex Complex(2, 3) + Complex(2, 3) , (4 + 6i) + assert_complex Complex(900) + Complex(1) , (901 + 0i) + assert_complex Complex(-2, 9) + Complex(-9, 2), (-11 + 11i) + assert_complex Complex(9, 8) + 4 , (13 + 8i) + assert_complex Complex(20, 9) + 9.8 , (29.8 + 9i) +end + +assert 'Complex#-' do + assert_complex Complex(2, 3) - Complex(2, 3) , (0 + 0i) + assert_complex Complex(900) - Complex(1) , (899 + 0i) + assert_complex Complex(-2, 9) - Complex(-9, 2), (7 + 7i) + assert_complex Complex(9, 8) - 4 , (5 + 8i) + assert_complex Complex(20, 9) - 9.8 , (10.2 + 9i) +end + +assert 'Complex#-@' do + assert_complex -Complex(1, 2), (-1 - 2i) +end + +assert 'Complex#/' do + assert_complex Complex(2, 3) / Complex(2, 3) , (1 + 0i) + assert_complex Complex(900) / Complex(1) , (900 + 0i) + assert_complex Complex(-2, 9) / Complex(-9, 2), ((36 / 85) - (77i / 85)) + assert_complex Complex(9, 8) / 4 , ((9 / 4) + 2i) + assert_complex Complex(20, 9) / 9.8 , (2.0408163265306123 + 0.9183673469387754i) +end + +assert 'Complex#==' do + assert_true Complex(2, 3) == Complex(2, 3) + assert_true Complex(5) == 5 + assert_true Complex(0) == 0.0 + assert_false Complex('1/3') == 0.33 + assert_false Complex('1/2') == '1/2' +end + +assert 'Complex#abs' do + assert_float Complex(-1).abs, 1 + assert_float Complex(3.0, -4.0).abs, 5.0 +end + +assert 'Complex#abs2' do + assert_float Complex(-1).abs2, 1 + assert_float Complex(3.0, -4.0).abs2, 25.0 +end + +assert 'Complex#arg' do + assert_float Complex.polar(3, Math::PI/2).arg, 1.5707963267948966 +end + +assert 'Complex#conjugate' do + assert_complex Complex(1, 2).conjugate, (1 - 2i) +end + +assert 'Complex#fdiv' do + assert_complex Complex(11, 22).fdiv(3), (3.6666666666666665 + 7.333333333333333i) +end + +assert 'Complex#imaginary' do + assert_float Complex(7).imaginary , 0 + assert_float Complex(9, -4).imaginary, -4 +end + +assert 'Complex#polar' do + assert_equal Complex(1, 2).polar, [2.23606797749979, 1.1071487177940904] +end + +assert 'Complex#real' do + assert_float Complex(7).real, 7 + assert_float Complex(9, -4).real, 9 +end + +assert 'Complex#real?' do + assert_false Complex(1).real? +end + +assert 'Complex::rectangular' do + assert_equal Complex(1, 2).rectangular, [1, 2] +end + +assert 'Complex::to_c' do + assert_equal Complex(1, 2).to_c, Complex(1, 2) +end + +assert 'Complex::to_f' do + assert_float Complex(1, 0).to_f, 1.0 + assert_raise(RangeError) do + Complex(1, 2).to_f + end +end + +assert 'Complex::to_i' do + assert_equal Complex(1, 0).to_i, 1 + assert_raise(RangeError) do + Complex(1, 2).to_i + end end \ No newline at end of file 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 -- cgit v1.2.3 From fa45cc42726720b89732bf43d1bf433970007c89 Mon Sep 17 00:00:00 2001 From: Ukrainskiy Sergey Date: Sat, 22 Sep 2018 16:53:56 +0900 Subject: Fix dependencies --- mrbgems/default.gembox | 6 ------ mrbgems/mruby-complex/mrbgem.rake | 1 + mrbgems/mruby-rational/mrbgem.rake | 1 + mrbgems/mruby-rational/mrblib/rational.rb | 12 ++++++++++++ mrbgems/mruby-rational/test/rational.rb | 15 +++++++++++++++ 5 files changed, 29 insertions(+), 6 deletions(-) (limited to 'mrbgems/mruby-rational/test') diff --git a/mrbgems/default.gembox b/mrbgems/default.gembox index ae085309c..23e65fcee 100644 --- a/mrbgems/default.gembox +++ b/mrbgems/default.gembox @@ -68,12 +68,6 @@ MRuby::GemBox.new do |conf| # Use Enumerator::Lazy class (require mruby-enumerator) conf.gem :core => "mruby-enum-lazy" - # Use Complex class - # conf.gem :core => "mruby-complex" - - # Use Rational class - # conf.gem :core => "mruby-rational" - # Use toplevel object (main) methods extension conf.gem :core => "mruby-toplevel-ext" diff --git a/mrbgems/mruby-complex/mrbgem.rake b/mrbgems/mruby-complex/mrbgem.rake index 25b8966da..19612e74d 100644 --- a/mrbgems/mruby-complex/mrbgem.rake +++ b/mrbgems/mruby-complex/mrbgem.rake @@ -3,6 +3,7 @@ MRuby::Gem::Specification.new('mruby-complex') do |spec| spec.author = 'mruby developers' spec.summary = 'Complex class' + spec.add_dependency 'mruby-metaprog', core: 'mruby-metaprog' spec.add_dependency 'mruby-object-ext', core: 'mruby-object-ext' spec.add_dependency 'mruby-numeric-ext', core: 'mruby-numeric-ext' spec.add_dependency 'mruby-math', core: 'mruby-math' diff --git a/mrbgems/mruby-rational/mrbgem.rake b/mrbgems/mruby-rational/mrbgem.rake index 496082709..93f5b601c 100644 --- a/mrbgems/mruby-rational/mrbgem.rake +++ b/mrbgems/mruby-rational/mrbgem.rake @@ -3,6 +3,7 @@ MRuby::Gem::Specification.new('mruby-rational') do |spec| spec.author = 'mruby developers' spec.summary = 'Rational class' + spec.add_dependency 'mruby-metaprog', core: 'mruby-metaprog' 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 ffadd55eb..7d5b87362 100644 --- a/mrbgems/mruby-rational/mrblib/rational.rb +++ b/mrbgems/mruby-rational/mrblib/rational.rb @@ -10,6 +10,18 @@ class Rational < Numeric "(#{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 diff --git a/mrbgems/mruby-rational/test/rational.rb b/mrbgems/mruby-rational/test/rational.rb index a86f00690..85cebc316 100644 --- a/mrbgems/mruby-rational/test/rational.rb +++ b/mrbgems/mruby-rational/test/rational.rb @@ -9,6 +9,21 @@ assert 'Rational' do assert_equal [r.numerator, r.denominator], [5, 1] end +assert 'Rational#to_f' do + assert_float Rational(2).to_f, 2.0 + assert_float Rational(9, 4).to_f, 2.25 + assert_float Rational(-3, 4).to_f, -0.75 + assert_float Rational(20, 3).to_f, 6.666666666666667 +end + +assert 'Rational#to_i' do + assert_equal Rational(2, 3).to_i, 0 + assert_equal Rational(3).to_i, 3 + assert_equal Rational(300.6).to_i, 300 + assert_equal Rational(98, 71).to_i, 1 + assert_equal Rational(-30, 2).to_i, -15 +end + assert 'Rational#*' do assert_rational Rational(2, 3) * Rational(2, 3), Rational(4, 9) assert_rational Rational(900) * Rational(1), Rational(900, 1) -- cgit v1.2.3 From f5fb1307b017fb972c12b4ec4b1866d789b0ca09 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Thu, 16 May 2019 22:09:56 +0900 Subject: Fix `Rational#==` --- mrbgems/mruby-rational/mrbgem.rake | 1 - mrbgems/mruby-rational/mrblib/rational.rb | 29 +++++++++++++++--- mrbgems/mruby-rational/test/rational.rb | 49 +++++++++++++++++++++++++++++-- 3 files changed, 72 insertions(+), 7 deletions(-) (limited to 'mrbgems/mruby-rational/test') diff --git a/mrbgems/mruby-rational/mrbgem.rake b/mrbgems/mruby-rational/mrbgem.rake index 93f5b601c..496082709 100644 --- a/mrbgems/mruby-rational/mrbgem.rake +++ b/mrbgems/mruby-rational/mrbgem.rake @@ -3,7 +3,6 @@ MRuby::Gem::Specification.new('mruby-rational') do |spec| spec.author = 'mruby developers' spec.summary = 'Rational class' - spec.add_dependency 'mruby-metaprog', core: 'mruby-metaprog' 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 7d5b87362..dbc855af0 100644 --- a/mrbgems/mruby-rational/mrblib/rational.rb +++ b/mrbgems/mruby-rational/mrblib/rational.rb @@ -1,4 +1,7 @@ class Rational < Numeric + # Override #<, #<=, #>, #>= in Numeric + prepend Comparable + def initialize(numerator = 0, denominator = 1) @numerator = numerator @denominator = denominator @@ -66,6 +69,24 @@ class Rational < Numeric end end + def <=>(rhs) + case rhs + when Fixnum + return @numerator <=> rhs if @denominator == 1 + rhs = Rational(rhs) + when Float + return to_f <=> rhs + end + case rhs + when Rational + (@numerator * rhs.denominator - @denominator * rhs.numerator) <=> 0 + when Numeric + return rhs <=> self + else + nil + end + end + def negative? numerator.negative? end @@ -86,17 +107,17 @@ def Rational(numerator = 0, denominator = 1) end [Fixnum, Float].each do |cls| - [:+, :-, :*, :/, :==].each do |op| + [:+, :-, :*, :/, :<=>, :==, :<, :<=, :>, :>=].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) + Rational(self).__send__(op, rhs) else - send(original_operator_name, rhs) + __send__(original_operator_name, rhs) end end end end -end \ No newline at end of file +end diff --git a/mrbgems/mruby-rational/test/rational.rb b/mrbgems/mruby-rational/test/rational.rb index 85cebc316..4d3d36ccc 100644 --- a/mrbgems/mruby-rational/test/rational.rb +++ b/mrbgems/mruby-rational/test/rational.rb @@ -1,8 +1,18 @@ def assert_rational(real, exp) - assert_float real.numerator, exp.numerator + assert_float real.numerator, exp.numerator assert_float real.denominator, exp.denominator end +def assert_equal_rational(exp, r1, r2) + if exp + assert_operator(r1, :==, r2) + assert_not_operator(r1, :!=, r2) + else + assert_not_operator(r1, :==, r2) + assert_operator(r1, :!=, r2) + end +end + assert 'Rational' do r = 5r assert_equal Rational, r.class @@ -54,4 +64,39 @@ assert 'Rational#/' do 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 +end + +assert 'Rational#==, Rational#!=' do + assert_equal_rational(true, Rational(1,1), Rational(1)) + assert_equal_rational(true, Rational(-1,1), -1r) + assert_equal_rational(true, Rational(13,4), 3.25) + assert_equal_rational(true, Rational(13,3.25), Rational(4,1)) + assert_equal_rational(true, Rational(-3,-4), Rational(3,4)) + assert_equal_rational(true, Rational(-4,5), Rational(4,-5)) + assert_equal_rational(true, Rational(4,2), 2) + assert_equal_rational(true, Rational(-4,2), -2) + assert_equal_rational(true, Rational(4,-2), -2) + assert_equal_rational(true, Rational(4,2), 2.0) + assert_equal_rational(true, Rational(-4,2), -2.0) + assert_equal_rational(true, Rational(4,-2), -2.0) + assert_equal_rational(true, Rational(8,6), Rational(4,3)) + assert_equal_rational(false, Rational(13,4), 3) + assert_equal_rational(false, Rational(13,4), 3.3) + assert_equal_rational(false, Rational(2,1), 1r) + assert_equal_rational(false, Rational(1), nil) + assert_equal_rational(false, Rational(1), '') +end + +assert 'Fixnum#==(Rational), Fixnum#!=(Rational)' do + assert_equal_rational(true, 2, Rational(4,2)) + assert_equal_rational(true, -2, Rational(-4,2)) + assert_equal_rational(true, -2, Rational(4,-2)) + assert_equal_rational(false, 3, Rational(13,4)) +end + +assert 'Float#==(Rational), Float#!=(Rational)' do + assert_equal_rational(true, 2.0, Rational(4,2)) + assert_equal_rational(true, -2.0, Rational(-4,2)) + assert_equal_rational(true, -2.0, Rational(4,-2)) + assert_equal_rational(false, 3.3, Rational(13,4)) +end -- cgit v1.2.3 From aa41a5c9af4d8ee61867d4f0bfdaeab4deb7cf0e Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Fri, 17 May 2019 20:44:48 +0900 Subject: Drop dependency from `mruby-rational` to `mruby-numeric-ext` --- mrbgems/mruby-rational/mrbgem.rake | 1 - mrbgems/mruby-rational/mrblib/rational.rb | 2 +- mrbgems/mruby-rational/test/rational.rb | 7 +++++++ 3 files changed, 8 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-rational/test') diff --git a/mrbgems/mruby-rational/mrbgem.rake b/mrbgems/mruby-rational/mrbgem.rake index 496082709..15c3429f2 100644 --- a/mrbgems/mruby-rational/mrbgem.rake +++ b/mrbgems/mruby-rational/mrbgem.rake @@ -4,5 +4,4 @@ MRuby::Gem::Specification.new('mruby-rational') do |spec| 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 54324b05f..ccb67541f 100644 --- a/mrbgems/mruby-rational/mrblib/rational.rb +++ b/mrbgems/mruby-rational/mrblib/rational.rb @@ -83,7 +83,7 @@ end def Rational(numerator = 0, denominator = 1) a = numerator b = denominator - a, b = b, a % b until b.zero? + a, b = b, a % b until b == 0 Rational._new(numerator.div(a), denominator.div(a)) end diff --git a/mrbgems/mruby-rational/test/rational.rb b/mrbgems/mruby-rational/test/rational.rb index 4d3d36ccc..a65926bfb 100644 --- a/mrbgems/mruby-rational/test/rational.rb +++ b/mrbgems/mruby-rational/test/rational.rb @@ -100,3 +100,10 @@ assert 'Float#==(Rational), Float#!=(Rational)' do assert_equal_rational(true, -2.0, Rational(4,-2)) assert_equal_rational(false, 3.3, Rational(13,4)) end + +assert 'Rational#negative?' do + assert_predicate(Rational(-2,3), :negative?) + assert_predicate(Rational(2,-3), :negative?) + assert_not_predicate(Rational(2,3), :negative?) + assert_not_predicate(Rational(0), :negative?) +end -- cgit v1.2.3 From a6eb01837b5d18d0a9b6fd5e22ab7d99241a1e2a Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Sun, 19 May 2019 13:52:18 +0900 Subject: Fix `Rational#<=>(Numeric)` Reported by Sergey Ukrainskiy: https://github.com/mruby/mruby/commit/f5fb1307b017fb972c12b4ec4b1866d789b0ca09#r33590698 --- mrbgems/mruby-rational/mrblib/rational.rb | 3 +- mrbgems/mruby-rational/test/rational.rb | 168 +++++++++++++++++++++++++++++- 2 files changed, 165 insertions(+), 6 deletions(-) (limited to 'mrbgems/mruby-rational/test') diff --git a/mrbgems/mruby-rational/mrblib/rational.rb b/mrbgems/mruby-rational/mrblib/rational.rb index 19c6da9e7..ad1f3ab0f 100644 --- a/mrbgems/mruby-rational/mrblib/rational.rb +++ b/mrbgems/mruby-rational/mrblib/rational.rb @@ -58,11 +58,12 @@ class Rational < Numeric when Float return to_f <=> rhs end + case rhs when Rational (numerator * rhs.denominator - denominator * rhs.numerator) <=> 0 when Numeric - return rhs <=> self + (rhs <=> self)&.-@ else nil end diff --git a/mrbgems/mruby-rational/test/rational.rb b/mrbgems/mruby-rational/test/rational.rb index a65926bfb..1ff819090 100644 --- a/mrbgems/mruby-rational/test/rational.rb +++ b/mrbgems/mruby-rational/test/rational.rb @@ -3,13 +3,21 @@ def assert_rational(real, exp) assert_float real.denominator, exp.denominator end -def assert_equal_rational(exp, r1, r2) +def assert_equal_rational(exp, o1, o2) if exp - assert_operator(r1, :==, r2) - assert_not_operator(r1, :!=, r2) + assert_operator(o1, :==, o2) + assert_not_operator(o1, :!=, o2) else - assert_not_operator(r1, :==, r2) - assert_operator(r1, :!=, r2) + assert_not_operator(o1, :==, o2) + assert_operator(o1, :!=, o2) + end +end + +def assert_cmp(exp, o1, o2) + if exp == (o1 <=> o2) + pass + else + flunk "", " Expected #{o1.inspect} <=> #{o2.inspect} to be #{exp}" end end @@ -101,6 +109,156 @@ assert 'Float#==(Rational), Float#!=(Rational)' do assert_equal_rational(false, 3.3, Rational(13,4)) end +assert 'Rational#<=>' do + num = Class.new(Numeric) do + def initialize(n) + @n = n + end + + def <=>(rhs) + rhs = rhs.to_i + rhs < 0 ? nil : @n <=> rhs + end + + def inspect + "num(#{@n})" + end + end + + assert_cmp(-1, Rational(-1), Rational(0)) + assert_cmp(0, Rational(0), Rational(0)) + assert_cmp(1, Rational(1), Rational(0)) + assert_cmp(-1, Rational(-1), 0) + assert_cmp(0, Rational(0), 0) + assert_cmp(1, Rational(1), 0) + assert_cmp(-1, Rational(-1), 0.0) + assert_cmp(0, Rational(0), 0.0) + assert_cmp(1, Rational(1), 0.0) + assert_cmp(-1, Rational(1,2), Rational(2,3)) + assert_cmp(0, Rational(2,3), Rational(2,3)) + assert_cmp(1, Rational(2,3), Rational(1,2)) + assert_cmp(1, Rational(2,3), Rational(1,2)) + assert_cmp(1, Rational(0), Rational(-1)) + assert_cmp(-1, Rational(0), Rational(1)) + assert_cmp(1, Rational(2,3), Rational(1,2)) + assert_cmp(0, Rational(2,3), Rational(2,3)) + assert_cmp(-1, Rational(1,2), Rational(2,3)) + assert_cmp(-1, Rational(1,2), Rational(2,3)) + assert_cmp(nil, 3r, "3") + assert_cmp(1, 3r, num.new(2)) + assert_cmp(0, 3r, num.new(3)) + assert_cmp(-1, 3r, num.new(4)) + assert_cmp(nil, Rational(-3), num.new(5)) +end + +assert 'Fixnum#<=>(Rational)' do + assert_cmp(-1, -2, Rational(-9,5)) + assert_cmp(0, 5, 5r) + assert_cmp(1, 3, Rational(8,3)) +end + +assert 'Float#<=>(Rational)' do + assert_cmp(-1, -2.1, Rational(-9,5)) + assert_cmp(0, 5.0, 5r) + assert_cmp(1, 2.7, Rational(8,3)) +end + +assert 'Rational#<' do + assert_operator(Rational(1,2), :<, Rational(2,3)) + assert_not_operator(Rational(2,3), :<, Rational(2,3)) + assert_operator(Rational(2,3), :<, 1) + assert_not_operator(2r, :<, 2) + assert_not_operator(Rational(2,3), :<, -3) + assert_operator(Rational(-4,3), :<, -0.3) + assert_not_operator(Rational(13,4), :<, 3.25) + assert_not_operator(Rational(2,3), :<, 0.6) + assert_raise(ArgumentError) { 1r < "2" } +end + +assert 'Fixnum#<(Rational)' do + assert_not_operator(1, :<, Rational(2,3)) + assert_not_operator(2, :<, 2r) + assert_operator(-3, :<, Rational(2,3)) +end + +assert 'Float#<(Rational)' do + assert_not_operator(-0.3, :<, Rational(-4,3)) + assert_not_operator(3.25, :<, Rational(13,4)) + assert_operator(0.6, :<, Rational(2,3)) +end + +assert 'Rational#<=' do + assert_operator(Rational(1,2), :<=, Rational(2,3)) + assert_operator(Rational(2,3), :<=, Rational(2,3)) + assert_operator(Rational(2,3), :<=, 1) + assert_operator(2r, :<=, 2) + assert_not_operator(Rational(2,3), :<=, -3) + assert_operator(Rational(-4,3), :<=, -0.3) + assert_operator(Rational(13,4), :<=, 3.25) + assert_not_operator(Rational(2,3), :<=, 0.6) + assert_raise(ArgumentError) { 1r <= "2" } +end + +assert 'Fixnum#<=(Rational)' do + assert_not_operator(1, :<=, Rational(2,3)) + assert_operator(2, :<=, 2r) + assert_operator(-3, :<=, Rational(2,3)) +end + +assert 'Float#<=(Rational)' do + assert_not_operator(-0.3, :<=, Rational(-4,3)) + assert_operator(3.25, :<=, Rational(13,4)) + assert_operator(0.6, :<=, Rational(2,3)) +end + +assert 'Rational#>' do + assert_not_operator(Rational(1,2), :>, Rational(2,3)) + assert_not_operator(Rational(2,3), :>, Rational(2,3)) + assert_not_operator(Rational(2,3), :>, 1) + assert_not_operator(2r, :>, 2) + assert_operator(Rational(2,3), :>, -3) + assert_not_operator(Rational(-4,3), :>, -0.3) + assert_not_operator(Rational(13,4), :>, 3.25) + assert_operator(Rational(2,3), :>, 0.6) + assert_raise(ArgumentError) { 1r > "2" } +end + +assert 'Fixnum#>(Rational)' do + assert_operator(1, :>, Rational(2,3)) + assert_not_operator(2, :>, 2r) + assert_not_operator(-3, :>, Rational(2,3)) +end + +assert 'Float#>(Rational)' do + assert_operator(-0.3, :>, Rational(-4,3)) + assert_not_operator(3.25, :>, Rational(13,4)) + assert_not_operator(0.6, :>, Rational(2,3)) +end + +assert 'Rational#>=' do + assert_not_operator(Rational(1,2), :>=, Rational(2,3)) + assert_operator(Rational(2,3), :>=, Rational(2,3)) + assert_not_operator(Rational(2,3), :>=, 1) + assert_operator(2r, :>=, 2) + assert_operator(Rational(2,3), :>=, -3) + assert_not_operator(Rational(-4,3), :>=, -0.3) + assert_operator(Rational(13,4), :>=, 3.25) + assert_operator(Rational(2,3), :>=, 0.6) + assert_raise(ArgumentError) { 1r >= "2" } +end + +assert 'Fixnum#>=(Rational)' do + assert_operator(1, :>=, Rational(2,3)) + assert_operator(2, :>=, 2r) + assert_not_operator(-3, :>=, Rational(2,3)) +end + +assert 'Float#>=(Rational)' do + assert_operator(-0.3, :>=, Rational(-4,3)) + assert_operator(3.25, :>=, Rational(13,4)) + assert_not_operator(0.6, :>=, Rational(2,3)) +end + assert 'Rational#negative?' do assert_predicate(Rational(-2,3), :negative?) assert_predicate(Rational(2,-3), :negative?) -- cgit v1.2.3 From 97600ded8d7717f327a3bf00e904a7ebb38dbd64 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Mon, 20 May 2019 18:24:18 +0900 Subject: Change the order of "expected" and "actual" in `mruby-rational` test --- mrbgems/mruby-rational/test/rational.rb | 68 ++++++++++++++++----------------- 1 file changed, 34 insertions(+), 34 deletions(-) (limited to 'mrbgems/mruby-rational/test') diff --git a/mrbgems/mruby-rational/test/rational.rb b/mrbgems/mruby-rational/test/rational.rb index 1ff819090..5a1055ee7 100644 --- a/mrbgems/mruby-rational/test/rational.rb +++ b/mrbgems/mruby-rational/test/rational.rb @@ -1,6 +1,6 @@ -def assert_rational(real, exp) - assert_float real.numerator, exp.numerator - assert_float real.denominator, exp.denominator +def assert_rational(exp, real) + assert_float exp.numerator, real.numerator + assert_float exp.denominator, real.denominator end def assert_equal_rational(exp, o1, o2) @@ -23,55 +23,55 @@ end assert 'Rational' do r = 5r - assert_equal Rational, r.class - assert_equal [r.numerator, r.denominator], [5, 1] + assert_equal(r.class, Rational) + assert_equal([5, 1], [r.numerator, r.denominator]) end assert 'Rational#to_f' do - assert_float Rational(2).to_f, 2.0 - assert_float Rational(9, 4).to_f, 2.25 - assert_float Rational(-3, 4).to_f, -0.75 - assert_float Rational(20, 3).to_f, 6.666666666666667 + assert_float(2.0, Rational(2).to_f) + assert_float(2.25, Rational(9, 4).to_f) + assert_float(-0.75, Rational(-3, 4).to_f) + assert_float(6.666666666666667, Rational(20, 3).to_f) end assert 'Rational#to_i' do - assert_equal Rational(2, 3).to_i, 0 - assert_equal Rational(3).to_i, 3 - assert_equal Rational(300.6).to_i, 300 - assert_equal Rational(98, 71).to_i, 1 - assert_equal Rational(-30, 2).to_i, -15 + assert_equal(0, Rational(2, 3).to_i) + assert_equal(3, Rational(3).to_i) + assert_equal(300, Rational(300.6).to_i) + assert_equal(1, Rational(98, 71).to_i) + assert_equal(-15, Rational(-30, 2).to_i) 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 + assert_rational(Rational(4, 9), Rational(2, 3) * Rational(2, 3)) + assert_rational(Rational(900, 1), Rational(900) * Rational(1)) + assert_rational(Rational(1, 1), Rational(-2, 9) * Rational(-9, 2)) + assert_rational(Rational(9, 2), Rational(9, 8) * 4) + assert_float( 21.77777777777778, Rational(20, 9) * 9.8) 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 + assert_rational(Rational(4, 3), Rational(2, 3) + Rational(2, 3)) + assert_rational(Rational(901, 1), Rational(900) + Rational(1)) + assert_rational(Rational(-85, 18), Rational(-2, 9) + Rational(-9, 2)) + assert_rational(Rational(41, 8), Rational(9, 8) + 4) + assert_float( 12.022222222222222, Rational(20, 9) + 9.8) 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 + assert_rational(Rational(0, 1), Rational(2, 3) - Rational(2, 3)) + assert_rational(Rational(899, 1), Rational(900) - Rational(1)) + assert_rational(Rational(77, 18), Rational(-2, 9) - Rational(-9, 2)) + assert_rational(Rational(-23, 8), Rational(9, 8) - 4) + assert_float( -7.577777777777778, Rational(20, 9) - 9.8) 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 + assert_rational(Rational(1, 1), Rational(2, 3) / Rational(2, 3)) + assert_rational(Rational(900, 1), Rational(900) / Rational(1)) + assert_rational(Rational(4, 81), Rational(-2, 9) / Rational(-9, 2)) + assert_rational(Rational(9, 32), Rational(9, 8) / 4) + assert_float( 0.22675736961451246, Rational(20, 9) / 9.8) end assert 'Rational#==, Rational#!=' do -- cgit v1.2.3 From 5d6c1794ad8620279514f45770ab4e8eeb16c734 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Tue, 21 May 2019 09:31:06 +0900 Subject: Revert part of #4457 --- mrbgems/mruby-rational/test/rational.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-rational/test') diff --git a/mrbgems/mruby-rational/test/rational.rb b/mrbgems/mruby-rational/test/rational.rb index 5a1055ee7..ea55880fe 100644 --- a/mrbgems/mruby-rational/test/rational.rb +++ b/mrbgems/mruby-rational/test/rational.rb @@ -23,7 +23,7 @@ end assert 'Rational' do r = 5r - assert_equal(r.class, Rational) + assert_equal(Rational, r.class) assert_equal([5, 1], [r.numerator, r.denominator]) end -- cgit v1.2.3 From 8513abd40404ef8cb8340da906f2d15101536de1 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Wed, 22 May 2019 19:57:35 +0900 Subject: `Kernel#Rational` requires numerator --- mrbgems/mruby-rational/mrblib/rational.rb | 2 +- mrbgems/mruby-rational/test/rational.rb | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) (limited to 'mrbgems/mruby-rational/test') diff --git a/mrbgems/mruby-rational/mrblib/rational.rb b/mrbgems/mruby-rational/mrblib/rational.rb index c8614ecea..4936b1123 100644 --- a/mrbgems/mruby-rational/mrblib/rational.rb +++ b/mrbgems/mruby-rational/mrblib/rational.rb @@ -71,7 +71,7 @@ class Numeric end module Kernel - def Rational(numerator = 0, denominator = 1) + def Rational(numerator, denominator = 1) a = numerator b = denominator a, b = b, a % b until b == 0 diff --git a/mrbgems/mruby-rational/test/rational.rb b/mrbgems/mruby-rational/test/rational.rb index ea55880fe..914f8505e 100644 --- a/mrbgems/mruby-rational/test/rational.rb +++ b/mrbgems/mruby-rational/test/rational.rb @@ -27,6 +27,19 @@ assert 'Rational' do assert_equal([5, 1], [r.numerator, r.denominator]) end +assert 'Kernel#Rational' do + r = Rational(4,10) + assert_equal(2, r.numerator) + assert_equal(5, r.denominator) + + r = Rational(3) + assert_equal(3, r.numerator) + assert_equal(1, r.denominator) + + assert_raise(ArgumentError) { Rational() } + assert_raise(ArgumentError) { Rational(1,2,3) } +end + assert 'Rational#to_f' do assert_float(2.0, Rational(2).to_f) assert_float(2.25, Rational(9, 4).to_f) -- cgit v1.2.3 From 48903850e9041e74c526fef5e63857007d2cac38 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Thu, 23 May 2019 13:40:49 +0900 Subject: Freeze `Rational` and `Complex` objects --- mrbgems/mruby-complex/src/complex.c | 1 + mrbgems/mruby-complex/test/complex.rb | 8 +++++++- mrbgems/mruby-rational/src/rational.c | 1 + mrbgems/mruby-rational/test/rational.rb | 6 ++++++ 4 files changed, 15 insertions(+), 1 deletion(-) (limited to 'mrbgems/mruby-rational/test') diff --git a/mrbgems/mruby-complex/src/complex.c b/mrbgems/mruby-complex/src/complex.c index c6fb7a829..1b030c317 100644 --- a/mrbgems/mruby-complex/src/complex.c +++ b/mrbgems/mruby-complex/src/complex.c @@ -24,6 +24,7 @@ complex_new(mrb_state *mrb, mrb_float real, mrb_float imaginary) struct mrb_complex *p = complex_ptr(mrb, comp); p->real = real; p->imaginary = imaginary; + MRB_SET_FROZEN_FLAG(s); return comp; } diff --git a/mrbgems/mruby-complex/test/complex.rb b/mrbgems/mruby-complex/test/complex.rb index e7fcc7322..6996eb214 100644 --- a/mrbgems/mruby-complex/test/complex.rb +++ b/mrbgems/mruby-complex/test/complex.rb @@ -1,5 +1,5 @@ def assert_complex(real, exp) - assert_float real.real, exp.real + assert_float real.real, exp.real assert_float real.imaginary, exp.imaginary end @@ -126,3 +126,9 @@ assert 'Complex::to_i' do Complex(1, 2).to_i end end + +assert 'Complex#frozen?' do + assert_predicate(1i, :frozen?) + assert_predicate(Complex(2,3), :frozen?) + assert_predicate(4+5i, :frozen?) +end diff --git a/mrbgems/mruby-rational/src/rational.c b/mrbgems/mruby-rational/src/rational.c index 2a3f6df09..fa061c0b8 100644 --- a/mrbgems/mruby-rational/src/rational.c +++ b/mrbgems/mruby-rational/src/rational.c @@ -37,6 +37,7 @@ rational_new(mrb_state *mrb, mrb_int numerator, mrb_int denominator) struct mrb_rational *p = rational_ptr(rat); p->numerator = numerator; p->denominator = denominator; + MRB_SET_FROZEN_FLAG(s); return rat; } diff --git a/mrbgems/mruby-rational/test/rational.rb b/mrbgems/mruby-rational/test/rational.rb index 914f8505e..1ed3b3a07 100644 --- a/mrbgems/mruby-rational/test/rational.rb +++ b/mrbgems/mruby-rational/test/rational.rb @@ -278,3 +278,9 @@ assert 'Rational#negative?' do assert_not_predicate(Rational(2,3), :negative?) assert_not_predicate(Rational(0), :negative?) end + +assert 'Rational#frozen?' do + assert_predicate(1r, :frozen?) + assert_predicate(Rational(2,3), :frozen?) + assert_predicate(4/5r, :frozen?) +end -- cgit v1.2.3 From 902b2ce3c669d4e3b5c20b2c90a3b3982f17d820 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Mon, 27 May 2019 21:29:49 +0900 Subject: Fix `Rational#==(Complex)` Consider a Numreic class like `Complex` that does not have `<=>` but `==` works (`0i == 0r` is `true`). --- mrbgems/mruby-rational/mrblib/rational.rb | 13 +++++++ mrbgems/mruby-rational/test/rational.rb | 58 ++++++++++++++++++++----------- 2 files changed, 51 insertions(+), 20 deletions(-) (limited to 'mrbgems/mruby-rational/test') diff --git a/mrbgems/mruby-rational/mrblib/rational.rb b/mrbgems/mruby-rational/mrblib/rational.rb index 4936b1123..54d9a955f 100644 --- a/mrbgems/mruby-rational/mrblib/rational.rb +++ b/mrbgems/mruby-rational/mrblib/rational.rb @@ -62,6 +62,19 @@ class Rational < Numeric nil end end + + def ==(rhs) + if rhs.is_a?(Integral) + return numerator == rhs if denominator == 1 + rhs = Rational(rhs) + end + + if rhs.is_a?(Rational) + numerator * rhs.denominator == denominator * rhs.numerator + else + rhs == self + end + end end class Numeric diff --git a/mrbgems/mruby-rational/test/rational.rb b/mrbgems/mruby-rational/test/rational.rb index 1ed3b3a07..5e9d9ea48 100644 --- a/mrbgems/mruby-rational/test/rational.rb +++ b/mrbgems/mruby-rational/test/rational.rb @@ -1,3 +1,27 @@ +class UserDefinedNumeric < Numeric + def initialize(n) + @n = n + end + + def <=>(rhs) + return nil unless rhs.respond_to?(:to_i) + rhs = rhs.to_i + rhs < 0 ? nil : @n <=> rhs + end + + def inspect + "#{self.class}(#{@n})" + end +end + +class ComplexLikeNumeric < UserDefinedNumeric + def ==(rhs) + @n == 0 && rhs == 0 + end + + undef <=> +end + def assert_rational(exp, real) assert_float exp.numerator, real.numerator assert_float exp.denominator, real.denominator @@ -17,7 +41,7 @@ def assert_cmp(exp, o1, o2) if exp == (o1 <=> o2) pass else - flunk "", " Expected #{o1.inspect} <=> #{o2.inspect} to be #{exp}" + flunk "", " Expected #{o1.inspect} <=> #{o2.inspect} to be #{exp}." end end @@ -106,6 +130,13 @@ assert 'Rational#==, Rational#!=' do assert_equal_rational(false, Rational(2,1), 1r) assert_equal_rational(false, Rational(1), nil) assert_equal_rational(false, Rational(1), '') + assert_equal_rational(true, 0r, UserDefinedNumeric.new(0)) + assert_equal_rational(true, 1r, UserDefinedNumeric.new(1)) + assert_equal_rational(false, 1r, UserDefinedNumeric.new(2)) + assert_equal_rational(false, -1r, UserDefinedNumeric.new(-1)) + assert_equal_rational(true, 0r, ComplexLikeNumeric.new(0)) + assert_equal_rational(false, 1r, ComplexLikeNumeric.new(1)) + assert_equal_rational(false, 1r, ComplexLikeNumeric.new(2)) end assert 'Fixnum#==(Rational), Fixnum#!=(Rational)' do @@ -123,21 +154,6 @@ assert 'Float#==(Rational), Float#!=(Rational)' do end assert 'Rational#<=>' do - num = Class.new(Numeric) do - def initialize(n) - @n = n - end - - def <=>(rhs) - rhs = rhs.to_i - rhs < 0 ? nil : @n <=> rhs - end - - def inspect - "num(#{@n})" - end - end - assert_cmp(-1, Rational(-1), Rational(0)) assert_cmp(0, Rational(0), Rational(0)) assert_cmp(1, Rational(1), Rational(0)) @@ -158,10 +174,12 @@ assert 'Rational#<=>' do assert_cmp(-1, Rational(1,2), Rational(2,3)) assert_cmp(-1, Rational(1,2), Rational(2,3)) assert_cmp(nil, 3r, "3") - assert_cmp(1, 3r, num.new(2)) - assert_cmp(0, 3r, num.new(3)) - assert_cmp(-1, 3r, num.new(4)) - assert_cmp(nil, Rational(-3), num.new(5)) + assert_cmp(1, 3r, UserDefinedNumeric.new(2)) + assert_cmp(0, 3r, UserDefinedNumeric.new(3)) + assert_cmp(-1, 3r, UserDefinedNumeric.new(4)) + assert_cmp(nil, Rational(-3), UserDefinedNumeric.new(5)) + assert_raise(NoMethodError) { 0r <=> ComplexLikeNumeric.new(0) } + assert_raise(NoMethodError) { 1r <=> ComplexLikeNumeric.new(2) } end assert 'Fixnum#<=>(Rational)' do -- cgit v1.2.3 From a215292b6ad4315a5a0edef49a1df65e3f27b46a Mon Sep 17 00:00:00 2001 From: dearblue Date: Fri, 28 Jun 2019 23:13:29 +0900 Subject: Use nested `assert` --- mrbgems/mruby-bin-mruby/bintest/mruby.rb | 8 +++++--- mrbgems/mruby-complex/test/complex.rb | 6 ++++-- mrbgems/mruby-io/test/io.rb | 32 +++++++++++++++++--------------- mrbgems/mruby-pack/test/pack.rb | 6 ++++-- mrbgems/mruby-rational/test/rational.rb | 20 ++++++++++++-------- 5 files changed, 42 insertions(+), 30 deletions(-) (limited to 'mrbgems/mruby-rational/test') diff --git a/mrbgems/mruby-bin-mruby/bintest/mruby.rb b/mrbgems/mruby-bin-mruby/bintest/mruby.rb index 09350ff49..5dbbc5592 100644 --- a/mrbgems/mruby-bin-mruby/bintest/mruby.rb +++ b/mrbgems/mruby-bin-mruby/bintest/mruby.rb @@ -3,9 +3,11 @@ require 'open3' def assert_mruby(exp_out, exp_err, exp_success, args) out, err, stat = Open3.capture3(cmd("mruby"), *args) - assert_operator(exp_out, :===, out, "standard output") - assert_operator(exp_err, :===, err, "standard error") - assert_equal(exp_success, stat.success?, "exit success?") + assert do + assert_operator(exp_out, :===, out, "standard output") + assert_operator(exp_err, :===, err, "standard error") + assert_equal(exp_success, stat.success?, "exit success?") + end end assert('regression for #1564') do diff --git a/mrbgems/mruby-complex/test/complex.rb b/mrbgems/mruby-complex/test/complex.rb index 6996eb214..ab882664e 100644 --- a/mrbgems/mruby-complex/test/complex.rb +++ b/mrbgems/mruby-complex/test/complex.rb @@ -1,6 +1,8 @@ def assert_complex(real, exp) - assert_float real.real, exp.real - assert_float real.imaginary, exp.imaginary + assert do + assert_float real.real, exp.real + assert_float real.imaginary, exp.imaginary + end end assert 'Complex' do diff --git a/mrbgems/mruby-io/test/io.rb b/mrbgems/mruby-io/test/io.rb index ef0b49643..1491a4cfe 100644 --- a/mrbgems/mruby-io/test/io.rb +++ b/mrbgems/mruby-io/test/io.rb @@ -5,24 +5,26 @@ MRubyIOTestUtil.io_test_setup $cr, $crlf, $cmd = MRubyIOTestUtil.win? ? [1, "\r\n", "cmd /c "] : [0, "\n", ""] def assert_io_open(meth) - fd = IO.sysopen($mrbtest_io_rfname) - assert_equal Fixnum, fd.class - io1 = IO.__send__(meth, fd) - begin - assert_equal IO, io1.class - assert_equal $mrbtest_io_msg, io1.read - ensure - io1.close - end + assert do + fd = IO.sysopen($mrbtest_io_rfname) + assert_equal Fixnum, fd.class + io1 = IO.__send__(meth, fd) + begin + assert_equal IO, io1.class + assert_equal $mrbtest_io_msg, io1.read + ensure + io1.close + end - io2 = IO.__send__(meth, IO.sysopen($mrbtest_io_rfname))do |io| - if meth == :open - assert_equal $mrbtest_io_msg, io.read - else - flunk "IO.#{meth} does not take block" + io2 = IO.__send__(meth, IO.sysopen($mrbtest_io_rfname))do |io| + if meth == :open + assert_equal $mrbtest_io_msg, io.read + else + flunk "IO.#{meth} does not take block" + end end + io2.close unless meth == :open end - io2.close unless meth == :open end assert('IO.class', '15.2.20') do diff --git a/mrbgems/mruby-pack/test/pack.rb b/mrbgems/mruby-pack/test/pack.rb index 110aee5db..eb24e8d1f 100644 --- a/mrbgems/mruby-pack/test/pack.rb +++ b/mrbgems/mruby-pack/test/pack.rb @@ -2,8 +2,10 @@ PACK_IS_LITTLE_ENDIAN = "\x01\00".unpack('S')[0] == 0x01 def assert_pack tmpl, packed, unpacked t = tmpl.inspect - assert_equal packed, unpacked.pack(tmpl), "#{unpacked.inspect}.pack(#{t})" - assert_equal unpacked, packed.unpack(tmpl), "#{packed.inspect}.unpack(#{t})" + assert do + assert_equal packed, unpacked.pack(tmpl), "#{unpacked.inspect}.pack(#{t})" + assert_equal unpacked, packed.unpack(tmpl), "#{packed.inspect}.unpack(#{t})" + end end # pack & unpack 'm' (base64) diff --git a/mrbgems/mruby-rational/test/rational.rb b/mrbgems/mruby-rational/test/rational.rb index 5e9d9ea48..11737034b 100644 --- a/mrbgems/mruby-rational/test/rational.rb +++ b/mrbgems/mruby-rational/test/rational.rb @@ -23,17 +23,21 @@ class ComplexLikeNumeric < UserDefinedNumeric end def assert_rational(exp, real) - assert_float exp.numerator, real.numerator - assert_float exp.denominator, real.denominator + assert do + assert_float exp.numerator, real.numerator + assert_float exp.denominator, real.denominator + end end def assert_equal_rational(exp, o1, o2) - if exp - assert_operator(o1, :==, o2) - assert_not_operator(o1, :!=, o2) - else - assert_not_operator(o1, :==, o2) - assert_operator(o1, :!=, o2) + assert do + if exp + assert_operator(o1, :==, o2) + assert_not_operator(o1, :!=, o2) + else + assert_not_operator(o1, :==, o2) + assert_operator(o1, :!=, o2) + end end end -- cgit v1.2.3