A MyNumeric type object that inherits Numeric can be specified in the Ruby Complex class constructor.
However, when I specified a negative value of MyNumber type for the imaginary part, the imaginary part was replaced with a Float type.
Maybe I’m missing a usage of coerce() methods.
Please tell me how to use coerce correctly.
–(1) Example that worked as expected – “Complex<Rational,BigDecaimal.negative>>”;
p Complex(Rational(1,2), Rational(-34567890123456789,5))
# => ((1/2)-(34567890123456789/5)*i)
–(2) Example that worked as expected – “Complex<MyNumber,MyNumber.positive>>”,;
p y=Complex(MyNumeric.new(1,1,5), MyNumeric.new(3,1,7))
#=> ((1 + 1/2 + 5*√(3)/2)+(3 + 1/2 + 7*√(3)/2)*i)
p y.imag.class
#=> MyNumeric
– (3) Examples of unexpected behavior;
p z= y.conjugate, z.imag.class
#=> -((1 + 1/2 + 5*√(3)/2)-9.56217782649107i)
#=> Float <--- unexpected behavior;
p z=Complex(MyNumeric.new(1,1,5), MyNumeric.new(-9,1,7)), .class
#=> ((1 + 1/2 + 5*√(3)/2)-5.901923788646684i)
#=> (-9 + 1/2 + 3*√(3)/2)
#=> MyNumeric
p 0 - z.imag
#=> 5.901923788646684 <--- Integer.coerce (MyNumeric) -> Float ?
– The definition of MyNumeric is as follows;
class MyNumeric < Numeric
attr_accessor :num, :rt3h,:hf
CONST_Sqrt3H = Math.sqrt(3)/2
CONST_hf = 0.5
def initialize(a,b = 0,c = 0)
if a.is_a?(MyNumeric) && (b == 0) && (c == 0)
@num, @hf = a.num + (a.hf / 2), a.hf % 2
@rt3h = a.rt3h
elsif a.is_a?(Integer) && b.is_a?(Integer) && c.is_a?(Integer)
@num, @hf = a + (b / 2), b % 2
@rt3h = c
else
$stderr.puts("ERROR at MyNumeric")
end
end
def +(other)
if other.is_a?(MyNumeric)
return new MyNumeric(@num + other.num, @hf + other.hf, @rt3h + other.rt3 )
elsif other.is_a?(Integer)
return new MyNumeric(@num + other, @rt3h,@hf)
end
end
def -(other)
if other.is_a?(MyNumeric)
return new MyNumeric(@num - other.num, @hf - other.hf, @rt3h - other.rt3 )
elsif other.is_a?(Integer)
return new MyNumeric(@num - other, @rt3h,@hf)
end
end
def zero?()
@num.zero?() && @hf.zero?() && @rt3h.zero?
end
def ==(other)
if other.is_a?(MyNumeric)
return (@num == other.num) && (@rt3h == other.rt3h) && (@hf == other.hf )
elsif other.is_a?(Integer) && (@rt3h == 0) && (@hf == 0)
return @num == other
else
return false
end
end
def negative?()
self.to_f.negative?
end
def <=>(other)
return self.to_f() <=> other.to_f
end
def to_f()
return @num + @rt3h*CONST_Sqrt3H + @hf * CONST_hf
end
def inspect()
return "(" + [num != 0 ? num.to_s() : "0", @hf != 0 ? @hf.to_s() + "/2" : nil, @rt3h != 0 ? @rt3h.to_s() + "*√(3)/2" : nil].filter{|c| !c.nil?}.to_a.join(" + ") + ")"
end
def to_s()
return "(" + [num != 0 ? num.to_s() : "0", @hf != 0 ? @hf.to_s() + "/2" : nil, @rt3h != 0 ? @rt3h.to_s() + "*√(3)/2" : nil].filter{|c| !c.nil?}.to_a.join(" + ") + ")"
end
def coerce(other)
if other.is_a?(Numeric)
return [self.to_f, other]
else
super
end
end
end
# builtin coerce ???
def coerce(other)
if other.is_a?(Numeric)
return [self.to_f, other]
else
super
end
end
# end of builtin coerce ???