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-complex/mrbgem.rake | 5 ++ mrbgems/mruby-complex/mrblib/complex.rb | 95 +++++++++++++++++++++++++++++++++ mrbgems/mruby-complex/test/complex.rb | 3 ++ 3 files changed, 103 insertions(+) create mode 100644 mrbgems/mruby-complex/mrbgem.rake create mode 100644 mrbgems/mruby-complex/mrblib/complex.rb create mode 100644 mrbgems/mruby-complex/test/complex.rb (limited to 'mrbgems/mruby-complex') diff --git a/mrbgems/mruby-complex/mrbgem.rake b/mrbgems/mruby-complex/mrbgem.rake new file mode 100644 index 000000000..f8f04d0b8 --- /dev/null +++ b/mrbgems/mruby-complex/mrbgem.rake @@ -0,0 +1,5 @@ +MRuby::Gem::Specification.new('mruby-complex') do |spec| + spec.license = 'MIT' + spec.author = 'mruby developers' + spec.summary = 'Complex class' +end diff --git a/mrbgems/mruby-complex/mrblib/complex.rb b/mrbgems/mruby-complex/mrblib/complex.rb new file mode 100644 index 000000000..0815c9a71 --- /dev/null +++ b/mrbgems/mruby-complex/mrblib/complex.rb @@ -0,0 +1,95 @@ +class Complex < Numeric + def initialize(real = 0, imaginary = 0) + @real = real + @imaginary = imaginary + end + + def inspect + "(#{to_s})" + end + + def to_s + "#{real}#{'+'}#{imaginary}i" + end + + def +@ + Complex.new(real, imaginary) + end + + def -@ + Complex.new(-real, -imaginary) + end + + def +(rhs) + if rhs.is_a? Complex + Complex.new(real + rhs.real, imaginary + rhs.imaginary) + elsif rhs.is_a? Numeric + Complex.new(real + rhs, imaginary) + end + end + + def -(rhs) + if rhs.is_a? Complex + Complex.new(real - rhs.real, imaginary - rhs.imaginary) + elsif rhs.is_a? Numeric + Complex.new(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) + elsif rhs.is_a? Numeric + Complex.new(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) + elsif rhs.is_a? Numeric + Complex.new(real / rhs, imaginary / rhs) + end + end + + attr_reader :real, :imaginary +end + +def Complex(real = 0, imaginary = 0) + Complex.new(real, imaginary) +end + +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 + end + + def __forward_operators_to_complex + __forward_operator_to_complex :+ + __forward_operator_to_complex :- + __forward_operator_to_complex :* + __forward_operator_to_complex :/ + + singleton_class.undef_method :__forward_operator_to_complex + singleton_class.undef_method :__forward_operators_to_complex + end +end + +class Fixnum + extend ForwardOperatorToComplex + __forward_operators_to_complex +end + +class Float + extend ForwardOperatorToComplex + __forward_operators_to_complex +end \ No newline at end of file diff --git a/mrbgems/mruby-complex/test/complex.rb b/mrbgems/mruby-complex/test/complex.rb new file mode 100644 index 000000000..890dd4ff1 --- /dev/null +++ b/mrbgems/mruby-complex/test/complex.rb @@ -0,0 +1,3 @@ +assert 'Complex' do + assert_equal Complex, 0i.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-complex') 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-complex') 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 6c9c189e4b9b5a340e220b333bc5f975fdb65adc Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Sat, 18 May 2019 18:31:55 +0900 Subject: Move `Object#(Rational|Complex)` to `Kernel` --- mrbgems/mruby-complex/mrblib/complex.rb | 10 ++++++---- mrbgems/mruby-rational/mrblib/rational.rb | 12 +++++++----- 2 files changed, 13 insertions(+), 9 deletions(-) (limited to 'mrbgems/mruby-complex') diff --git a/mrbgems/mruby-complex/mrblib/complex.rb b/mrbgems/mruby-complex/mrblib/complex.rb index 266c00c36..8ae743e77 100644 --- a/mrbgems/mruby-complex/mrblib/complex.rb +++ b/mrbgems/mruby-complex/mrblib/complex.rb @@ -107,7 +107,7 @@ class Complex < Numeric def polar [abs, arg] end - + def real? false end @@ -147,8 +147,10 @@ class << Complex alias_method :rect, :rectangular end -def Complex(real, imaginary = 0) - Complex.rectangular(real, imaginary) +module Kernel + def Complex(real, imaginary = 0) + Complex.rectangular(real, imaginary) + end end [Fixnum, Float].each do |cls| @@ -165,4 +167,4 @@ end end end end -end \ No newline at end of file +end diff --git a/mrbgems/mruby-rational/mrblib/rational.rb b/mrbgems/mruby-rational/mrblib/rational.rb index 870c12242..19c6da9e7 100644 --- a/mrbgems/mruby-rational/mrblib/rational.rb +++ b/mrbgems/mruby-rational/mrblib/rational.rb @@ -75,11 +75,13 @@ class Numeric end end -def Rational(numerator = 0, denominator = 1) - a = numerator - b = denominator - a, b = b, a % b until b == 0 - Rational._new(numerator.div(a), denominator.div(a)) +module Kernel + def Rational(numerator = 0, denominator = 1) + a = numerator + b = denominator + a, b = b, a % b until b == 0 + Rational._new(numerator.div(a), denominator.div(a)) + end end [:+, :-, :*, :/, :<=>, :==, :<, :<=, :>, :>=].each do |op| -- cgit v1.2.3 From f6e4145ad960d9bc748f9c91fd4c5db5afeebbd0 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 21 May 2019 16:06:37 +0900 Subject: Remove `Complex(string)` complex generation. It should raise an error. --- mrbgems/mruby-complex/test/complex.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'mrbgems/mruby-complex') diff --git a/mrbgems/mruby-complex/test/complex.rb b/mrbgems/mruby-complex/test/complex.rb index ca58202c2..e7fcc7322 100644 --- a/mrbgems/mruby-complex/test/complex.rb +++ b/mrbgems/mruby-complex/test/complex.rb @@ -63,8 +63,6 @@ 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 @@ -127,4 +125,4 @@ assert 'Complex::to_i' do assert_raise(RangeError) do Complex(1, 2).to_i end -end \ No newline at end of file +end -- cgit v1.2.3 From fccec8964a1b30cef8ff9d97e0e01f3a348e318b Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 21 May 2019 16:11:25 +0900 Subject: Implements part of `Complex` class in C. --- mrbgems/mruby-complex/mrblib/complex.rb | 50 +++----------- mrbgems/mruby-complex/src/complex.c | 116 ++++++++++++++++++++++++++++++++ mrbgems/mruby-rational/src/rational.c | 2 +- 3 files changed, 127 insertions(+), 41 deletions(-) create mode 100644 mrbgems/mruby-complex/src/complex.c (limited to 'mrbgems/mruby-complex') diff --git a/mrbgems/mruby-complex/mrblib/complex.rb b/mrbgems/mruby-complex/mrblib/complex.rb index 8ae743e77..4c0c19c70 100644 --- a/mrbgems/mruby-complex/mrblib/complex.rb +++ b/mrbgems/mruby-complex/mrblib/complex.rb @@ -23,43 +23,43 @@ class Complex < Numeric end def +@ - Complex(real, imaginary) + Complex._new(real, imaginary) end def -@ - Complex(-real, -imaginary) + Complex._new(-real, -imaginary) end def +(rhs) if rhs.is_a? Complex - Complex(real + rhs.real, imaginary + rhs.imaginary) + Complex._new(real + rhs.real, imaginary + rhs.imaginary) elsif rhs.is_a? Numeric - Complex(real + rhs, imaginary) + Complex._new(real + rhs, imaginary) end end def -(rhs) if rhs.is_a? Complex - Complex(real - rhs.real, imaginary - rhs.imaginary) + Complex._new(real - rhs.real, imaginary - rhs.imaginary) elsif rhs.is_a? Numeric - Complex(real - rhs, imaginary) + Complex._new(real - rhs, imaginary) end end def *(rhs) if rhs.is_a? Complex - Complex(real * rhs.real - imaginary * rhs.imaginary, real * rhs.imaginary + rhs.real * imaginary) + Complex._new(real * rhs.real - imaginary * rhs.imaginary, real * rhs.imaginary + rhs.real * imaginary) elsif rhs.is_a? Numeric - Complex(real * rhs, imaginary * rhs) + Complex._new(real * rhs, imaginary * rhs) end end def /(rhs) if rhs.is_a? Complex div = rhs.real * rhs.real + rhs.imaginary * rhs.imaginary - Complex((real * rhs.real + imaginary * rhs.imaginary) / div, (rhs.real * imaginary - real * rhs.imaginary) / div) + Complex._new((real * rhs.real + imaginary * rhs.imaginary) / div, (rhs.real * imaginary - real * rhs.imaginary) / div) elsif rhs.is_a? Numeric - Complex(real / rhs, imaginary / rhs) + Complex._new(real / rhs, imaginary / rhs) end end alias_method :quo, :/ @@ -92,14 +92,6 @@ class Complex < Numeric 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 @@ -117,36 +109,14 @@ class Complex < Numeric 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 - - 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 - module Kernel def Complex(real, imaginary = 0) Complex.rectangular(real, imaginary) diff --git a/mrbgems/mruby-complex/src/complex.c b/mrbgems/mruby-complex/src/complex.c new file mode 100644 index 000000000..5de0ae9a4 --- /dev/null +++ b/mrbgems/mruby-complex/src/complex.c @@ -0,0 +1,116 @@ +#include +#include +#include + +struct mrb_complex { + mrb_float real; + mrb_float imaginary; +}; + +#include + +static const struct mrb_data_type mrb_complex_type = {"Complex", mrb_free}; + +static mrb_value +complex_new(mrb_state *mrb, mrb_float real, mrb_float imaginary) +{ + struct RClass *c = mrb_class_get(mrb, "Complex"); + struct mrb_complex *p; + + p = (struct mrb_complex*)mrb_malloc(mrb, sizeof(struct mrb_complex)); + p->real = real; + p->imaginary = imaginary; + + return mrb_obj_value(Data_Wrap_Struct(mrb, c, &mrb_complex_type, p)); +} + +static struct mrb_complex* +complex_ptr(mrb_state *mrb, mrb_value v) +{ + struct mrb_complex *p; + + p = DATA_GET_PTR(mrb, v, &mrb_complex_type, struct mrb_complex); + if (!p) { + mrb_raise(mrb, E_ARGUMENT_ERROR, "uninitialized complex"); + } + return p; +} + +static mrb_value +complex_real(mrb_state *mrb, mrb_value self) +{ + struct mrb_complex *p = complex_ptr(mrb, self); + return mrb_float_value(mrb, p->real); +} + +static mrb_value +complex_imaginary(mrb_state *mrb, mrb_value self) +{ + struct mrb_complex *p = complex_ptr(mrb, self); + return mrb_float_value(mrb, p->imaginary); +} + +static mrb_value +complex_s_new(mrb_state *mrb, mrb_value self) +{ + mrb_float real, imaginary; + + mrb_get_args(mrb, "ff", &real, &imaginary); + return complex_new(mrb, real, imaginary); +} + +#ifndef MRB_WITHOUT_FLOAT +static mrb_value +complex_to_f(mrb_state *mrb, mrb_value self) +{ + struct mrb_complex *p = complex_ptr(mrb, self); + + if (p->imaginary != 0) { + mrb_raisef(mrb, E_RANGE_ERROR, "can't convert %S into Float", self); + } + + return mrb_float_value(mrb, p->real); +} +#endif + +static mrb_value +complex_to_i(mrb_state *mrb, mrb_value self) +{ + struct mrb_complex *p = complex_ptr(mrb, self); + + if (p->imaginary != 0) { + mrb_raisef(mrb, E_RANGE_ERROR, "can't convert %S into Float", self); + } + return mrb_int_value(mrb, p->real); +} + +static mrb_value +complex_to_c(mrb_state *mrb, mrb_value self) +{ + return self; +} + +void mrb_mruby_complex_gem_init(mrb_state *mrb) +{ + struct RClass *comp; + +#ifdef COMPLEX_USE_ISTRUCT + mrb_assert(sizeof(struct mrb_complex) < ISTRUCT_DATA_SIZE); +#endif + comp = mrb_define_class(mrb, "Complex", mrb_class_get(mrb, "Numeric")); + //MRB_SET_INSTANCE_TT(comp, MRB_TT_ISTRUCT); + mrb_undef_class_method(mrb, comp, "new"); + mrb_define_class_method(mrb, comp, "_new", complex_s_new, MRB_ARGS_REQ(2)); + mrb_define_method(mrb, comp, "real", complex_real, MRB_ARGS_NONE()); + mrb_define_method(mrb, comp, "imaginary", complex_imaginary, MRB_ARGS_NONE()); +#ifndef MRB_WITHOUT_FLOAT + mrb_define_method(mrb, comp, "to_f", complex_to_f, MRB_ARGS_NONE()); +#endif + mrb_define_method(mrb, comp, "to_i", complex_to_i, MRB_ARGS_NONE()); + mrb_define_method(mrb, comp, "to_c", complex_to_c, MRB_ARGS_NONE()); +} + +void +mrb_mruby_complex_gem_final(mrb_state* mrb) +{ +} diff --git a/mrbgems/mruby-rational/src/rational.c b/mrbgems/mruby-rational/src/rational.c index 549715e7d..2a3f6df09 100644 --- a/mrbgems/mruby-rational/src/rational.c +++ b/mrbgems/mruby-rational/src/rational.c @@ -37,7 +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; - return mrb_obj_value(s); + return rat; } static mrb_value -- cgit v1.2.3 From c02e63eb77b68377239287acccf371516177a8b9 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 21 May 2019 16:17:21 +0900 Subject: Use `MRB_TT_ISTRUCT` for `Complex` numbers if possible. --- mrbgems/mruby-complex/src/complex.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'mrbgems/mruby-complex') diff --git a/mrbgems/mruby-complex/src/complex.c b/mrbgems/mruby-complex/src/complex.c index 5de0ae9a4..c6fb7a829 100644 --- a/mrbgems/mruby-complex/src/complex.c +++ b/mrbgems/mruby-complex/src/complex.c @@ -7,6 +7,29 @@ struct mrb_complex { mrb_float imaginary; }; +#if defined(MRB_64BIT) || defined(MRB_USE_FLOAT) + +#define COMPLEX_USE_ISTRUCT +/* use TT_ISTRUCT */ +#include + +#define complex_ptr(mrb, v) (struct mrb_complex*)mrb_istruct_ptr(v) + +static mrb_value +complex_new(mrb_state *mrb, mrb_float real, mrb_float imaginary) +{ + struct RClass *c = mrb_class_get(mrb, "Complex"); + struct RIStruct *s = (struct RIStruct*)mrb_obj_alloc(mrb, MRB_TT_ISTRUCT, c); + mrb_value comp = mrb_obj_value(s); + struct mrb_complex *p = complex_ptr(mrb, comp); + p->real = real; + p->imaginary = imaginary; + + return comp; +} + +#else +/* use TT_DATA */ #include static const struct mrb_data_type mrb_complex_type = {"Complex", mrb_free}; @@ -35,6 +58,7 @@ complex_ptr(mrb_state *mrb, mrb_value v) } return p; } +#endif static mrb_value complex_real(mrb_state *mrb, mrb_value self) -- 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-complex') 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 4261ba944330f27dcb80e5e4580f73bd6b3a7106 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Fri, 24 May 2019 13:15:26 +0900 Subject: Remove some overhead from methods defined in Ruby in Complex. --- mrbgems/mruby-complex/mrblib/complex.rb | 37 +++++++++------------------------ mrbgems/mruby-complex/src/complex.c | 9 ++++---- 2 files changed, 15 insertions(+), 31 deletions(-) (limited to 'mrbgems/mruby-complex') diff --git a/mrbgems/mruby-complex/mrblib/complex.rb b/mrbgems/mruby-complex/mrblib/complex.rb index 4c0c19c70..0299e7675 100644 --- a/mrbgems/mruby-complex/mrblib/complex.rb +++ b/mrbgems/mruby-complex/mrblib/complex.rb @@ -1,19 +1,8 @@ class Complex < Numeric - 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 @@ -23,43 +12,43 @@ class Complex < Numeric 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, :/ @@ -117,12 +106,6 @@ class Complex < Numeric alias_method :imag, :imaginary end -module Kernel - def Complex(real, imaginary = 0) - Complex.rectangular(real, imaginary) - end -end - [Fixnum, Float].each do |cls| [:+, :-, :*, :/, :==].each do |op| cls.instance_exec do diff --git a/mrbgems/mruby-complex/src/complex.c b/mrbgems/mruby-complex/src/complex.c index 1b030c317..0678d4b26 100644 --- a/mrbgems/mruby-complex/src/complex.c +++ b/mrbgems/mruby-complex/src/complex.c @@ -76,11 +76,11 @@ complex_imaginary(mrb_state *mrb, mrb_value self) } static mrb_value -complex_s_new(mrb_state *mrb, mrb_value self) +complex_s_rect(mrb_state *mrb, mrb_value self) { - mrb_float real, imaginary; + mrb_float real, imaginary = 0.0; - mrb_get_args(mrb, "ff", &real, &imaginary); + mrb_get_args(mrb, "f|f", &real, &imaginary); return complex_new(mrb, real, imaginary); } @@ -125,7 +125,8 @@ void mrb_mruby_complex_gem_init(mrb_state *mrb) comp = mrb_define_class(mrb, "Complex", mrb_class_get(mrb, "Numeric")); //MRB_SET_INSTANCE_TT(comp, MRB_TT_ISTRUCT); mrb_undef_class_method(mrb, comp, "new"); - mrb_define_class_method(mrb, comp, "_new", complex_s_new, MRB_ARGS_REQ(2)); + mrb_define_class_method(mrb, comp, "rectangular", complex_s_rect, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); + mrb_define_method(mrb, mrb->kernel_module, "Complex", complex_s_rect, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); mrb_define_method(mrb, comp, "real", complex_real, MRB_ARGS_NONE()); mrb_define_method(mrb, comp, "imaginary", complex_imaginary, MRB_ARGS_NONE()); #ifndef MRB_WITHOUT_FLOAT -- cgit v1.2.3 From 0bdb185a6fc1a6440b90b015bdb9d137db57ab77 Mon Sep 17 00:00:00 2001 From: KOBAYASHI Shuji Date: Sun, 26 May 2019 20:17:03 +0900 Subject: Add `Complex.rect` --- mrbgems/mruby-complex/src/complex.c | 1 + 1 file changed, 1 insertion(+) (limited to 'mrbgems/mruby-complex') diff --git a/mrbgems/mruby-complex/src/complex.c b/mrbgems/mruby-complex/src/complex.c index 0678d4b26..5371332cd 100644 --- a/mrbgems/mruby-complex/src/complex.c +++ b/mrbgems/mruby-complex/src/complex.c @@ -126,6 +126,7 @@ void mrb_mruby_complex_gem_init(mrb_state *mrb) //MRB_SET_INSTANCE_TT(comp, MRB_TT_ISTRUCT); mrb_undef_class_method(mrb, comp, "new"); mrb_define_class_method(mrb, comp, "rectangular", complex_s_rect, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); + mrb_define_class_method(mrb, comp, "rect", complex_s_rect, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); mrb_define_method(mrb, mrb->kernel_module, "Complex", complex_s_rect, MRB_ARGS_REQ(1)|MRB_ARGS_OPT(1)); mrb_define_method(mrb, comp, "real", complex_real, MRB_ARGS_NONE()); mrb_define_method(mrb, comp, "imaginary", complex_imaginary, MRB_ARGS_NONE()); -- cgit v1.2.3 From 97e999c409fbbe46fd4154e4be292f182f42b771 Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 2 Jun 2019 10:43:54 +0900 Subject: Fix memory leak in `Complex` method by `RData` If `Data_Wrap_Struct()` raises a `NoMemoryError` exception, it will leak memory if it does `mrb_malloc()` first. --- mrbgems/mruby-complex/src/complex.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'mrbgems/mruby-complex') diff --git a/mrbgems/mruby-complex/src/complex.c b/mrbgems/mruby-complex/src/complex.c index 5371332cd..a727eb604 100644 --- a/mrbgems/mruby-complex/src/complex.c +++ b/mrbgems/mruby-complex/src/complex.c @@ -40,12 +40,13 @@ complex_new(mrb_state *mrb, mrb_float real, mrb_float imaginary) { struct RClass *c = mrb_class_get(mrb, "Complex"); struct mrb_complex *p; + struct RData *d; - p = (struct mrb_complex*)mrb_malloc(mrb, sizeof(struct mrb_complex)); + Data_Make_Struct(mrb, c, struct mrb_complex, &mrb_complex_type, p, d); p->real = real; p->imaginary = imaginary; - return mrb_obj_value(Data_Wrap_Struct(mrb, c, &mrb_complex_type, p)); + return mrb_obj_value(d); } static struct mrb_complex* -- cgit v1.2.3 From 82831c6acd116852e918094e940266152897056e Mon Sep 17 00:00:00 2001 From: dearblue Date: Sun, 2 Jun 2019 11:05:53 +0900 Subject: Fix not frozen in `Complex` method by `RData` Object allocation was separated, and initialization was made common. --- mrbgems/mruby-complex/src/complex.c | 42 +++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 18 deletions(-) (limited to 'mrbgems/mruby-complex') diff --git a/mrbgems/mruby-complex/src/complex.c b/mrbgems/mruby-complex/src/complex.c index a727eb604..8a0569d68 100644 --- a/mrbgems/mruby-complex/src/complex.c +++ b/mrbgems/mruby-complex/src/complex.c @@ -15,18 +15,15 @@ struct mrb_complex { #define complex_ptr(mrb, v) (struct mrb_complex*)mrb_istruct_ptr(v) -static mrb_value -complex_new(mrb_state *mrb, mrb_float real, mrb_float imaginary) +static struct RBasic* +complex_alloc(mrb_state *mrb, struct RClass *c, struct mrb_complex **p) { - struct RClass *c = mrb_class_get(mrb, "Complex"); - struct RIStruct *s = (struct RIStruct*)mrb_obj_alloc(mrb, MRB_TT_ISTRUCT, c); - mrb_value comp = mrb_obj_value(s); - struct mrb_complex *p = complex_ptr(mrb, comp); - p->real = real; - p->imaginary = imaginary; - MRB_SET_FROZEN_FLAG(s); + struct RIStruct *s; + + s = (struct RIStruct*)mrb_obj_alloc(mrb, MRB_TT_ISTRUCT, c); + *p = (struct mrb_complex*)s->inline_data; - return comp; + return (struct RBasic*)s; } #else @@ -35,18 +32,14 @@ complex_new(mrb_state *mrb, mrb_float real, mrb_float imaginary) static const struct mrb_data_type mrb_complex_type = {"Complex", mrb_free}; -static mrb_value -complex_new(mrb_state *mrb, mrb_float real, mrb_float imaginary) +static struct RBasic* +complex_alloc(mrb_state *mrb, struct RClass *c, struct mrb_complex **p) { - struct RClass *c = mrb_class_get(mrb, "Complex"); - struct mrb_complex *p; struct RData *d; - Data_Make_Struct(mrb, c, struct mrb_complex, &mrb_complex_type, p, d); - p->real = real; - p->imaginary = imaginary; + Data_Make_Struct(mrb, c, struct mrb_complex, &mrb_complex_type, *p, d); - return mrb_obj_value(d); + return (struct RBasic*)d; } static struct mrb_complex* @@ -62,6 +55,19 @@ complex_ptr(mrb_state *mrb, mrb_value v) } #endif +static mrb_value +complex_new(mrb_state *mrb, mrb_float real, mrb_float imaginary) +{ + struct RClass *c = mrb_class_get(mrb, "Complex"); + struct mrb_complex *p; + struct RBasic *comp = complex_alloc(mrb, c, &p); + p->real = real; + p->imaginary = imaginary; + MRB_SET_FROZEN_FLAG(comp); + + return mrb_obj_value(comp); +} + static mrb_value complex_real(mrb_state *mrb, mrb_value self) { -- 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-complex') 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 From a9fd2e646492699894d33eaf3de7336356ce6726 Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Sat, 13 Jul 2019 13:16:30 +0900 Subject: Resolve ambiguous argument warning. --- mrbgems/mruby-complex/test/complex.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'mrbgems/mruby-complex') diff --git a/mrbgems/mruby-complex/test/complex.rb b/mrbgems/mruby-complex/test/complex.rb index ab882664e..5b7c3bfa4 100644 --- a/mrbgems/mruby-complex/test/complex.rb +++ b/mrbgems/mruby-complex/test/complex.rb @@ -50,7 +50,7 @@ assert 'Complex#-' do end assert 'Complex#-@' do - assert_complex -Complex(1, 2), (-1 - 2i) + assert_complex(-Complex(1, 2), (-1 - 2i)) end assert 'Complex#/' do -- cgit v1.2.3