lib/hpsqrt.rb in hpsqrt-1.1.0 vs lib/hpsqrt.rb in hpsqrt-1.2.0

- old
+ new

@@ -1,7 +1,7 @@ require 'hpsqrt/inspect_mode' -require 'hpsqrt/value' +require 'hpsqrt/term' require 'hpsqrt/version' class HpSqrt < Numeric @@ -14,77 +14,77 @@ def self.inspect_mode=(v) @@inspect_mode = v end - attr_reader :values + attr_reader :terms - def initialize(values) - @values = values.freeze + def initialize(terms) + @terms = terms.freeze freeze end def -@ - values = self.values.map{|v,c| [v, -c]}.to_h - self.class.new(values) + terms = @terms.map{|t,c| [t, -c]}.to_h + self.class.new(terms) end def +(other) other = self.class.create(other) - values = @values.merge(other.values) {|v, c1, c2| + terms = @terms.merge(other.terms) {|t, c1, c2| c1 + c2 } - values.delete_if {|v,c| c==0} + terms.delete_if {|t,c| c==0} - self.class.new(values) + self.class.new(terms) end def -(other) other = self.class.create(other) - other_values = other.values.map{|v,c| [v, -c]}.to_h - values = @values.merge(other_values) {|v, c1, c2| + other_terms = other.terms.map{|t,c| [t, -c]}.to_h + terms = @terms.merge(other_terms) {|t, c1, c2| c1 + c2 } - values.delete_if {|v,c| v==0} + terms.delete_if {|t,c| c==0} - self.class.new(values) + self.class.new(terms) end def *(other) other = self.class.create(other) - values = {} - @values.each {|v1, c1| - other.values.each {|v2, c2| - v = v1 * v2 + terms = {} + @terms.each {|t1, c1| + other.terms.each {|t2, c2| + t = t1 * t2 c = c1 * c2 - values[v] ||= 0 - values[v] += c + terms[t] ||= 0 + terms[t] += c } } - values.delete_if {|v,c| c==0} + terms.delete_if {|t,c| c==0} - self.class.new(values) + self.class.new(terms) end def /(other) other = self.class.create(other) - other_inv = Value.new(number: Rational(1, other.value)) + other_inv = Term.new(number: Rational(1, other.to_c)) - values = {} - @values.each {|v, c| - v *= other_inv + terms = {} + @terms.each {|t, c| + t *= other_inv - values[v] ||= 0 - values[v] += c + terms[t] ||= 0 + terms[t] += c } - values.delete_if {|v,c| c==0} + terms.delete_if {|t,c| c==0} - self.class.new(values) + self.class.new(terms) end def **(other) other = self.class.create(other) @@ -97,40 +97,40 @@ if other_i<0 result = Rational(1, result) end result else - self.class.number(self.value ** other.value) + self.class.number(self.to_c ** other.to_c) end end def coerce(other) [self.class.create(other), self] end def ==(other) if self.class==other - self.value==other.value + self.to_c==other.to_c elsif Numeric===other - self.value==other + self.to_c==other else super.==(other) end end - def value - @values.map {|v, c| - v.number * Math.sqrt(Complex(v.sqrt)) * c - }.sum + def to_c + @terms.map {|t, c| + t.number * Math.sqrt(Complex(t.sqrt)) * c + }.sum.to_c end def real - value.real + to_c.real end def imag - Complex(value).imag + to_c.imag end def to_i c = to_c if c.imag.zero? @@ -147,35 +147,37 @@ else raise RangeError, "can't convert %s into Float" % c end end - def to_c - value.to_c - end - def to_r - value.to_r + c = to_c + if c.imag.zero? + Rational(c.real, 1) + else + raise RangeError, "can't convert %s into Rational" % c + end end def expr value_to_s = -> (v) { if Complex===v && v.imag.zero? v = v.real - elsif Rational===v + end + if Rational===v v = v.to_s.sub(/\/1$/, "") end v = v.to_s if v !~ /^[\d\.]+$/ v = "(%s)" % v end v } - result = @values.map {|v, c| - n = v.number * c - s = v.sqrt + result = @terms.map {|t, c| + n = t.number * c + s = t.sqrt if s!=1 if n==1 "\u221A%s" % value_to_s[s] elsif 0<n.real @@ -202,15 +204,15 @@ end def to_s case @@inspect_mode when INSPECT_MODE::VALUE - value.to_s + to_c.to_s when INSPECT_MODE::EXPR expr else - "#<%s:0x%016x value=(%s) expr=(%s)>" % [self.class.name, self.object_id, value, expr] + "#<%s:0x%016x value=(%s) expr=(%s)>" % [self.class.name, self.object_id, to_c, expr] end end def real? imag.zero? @@ -219,19 +221,17 @@ def imag? !real? end def int? - v = value - is_imag = Complex===v && !v.imag.zero? - !is_imag && v.real==v.real.to_i + c = to_c + c.imag.zero? && c.real==c.real.to_i end def float? - v = value - is_imag = Complex===v && !v.imag.zero? - !is_imag && Float===v.real && v.real!=v.real.to_i + c = to_c + c.imag.zero? && Float===c.real && c.real!=c.real.to_i end def self.create(v) if self===v v @@ -239,12 +239,27 @@ number(v) end end def self.number(v) - new({Value.new(number: v) => 1}) + if v!=0 + new({Term.new(number: v) => 1}) + else + zero + end end def self.sqrt(v) - new({Value.new(sqrt: v) => 1}) + if self===v + v = v.to_c + end + if v!=0 + new({Term.new(sqrt: v) => 1}) + else + zero + end + end + + def self.zero + new({}) end end