module Dydx module Helper SUPER_OPE_RELATION = { :+ => :*, :- => :/, :* => :**, :/ => :| } INVERSE_OPE_RELATION = { :+ => :-, :- => :+, :* => :/, :/ => :*, :** => :|, :| => :** } def num? is_a?(Num) || is_a?(Numeric) end def to_numeric is_a?(Num) ? n : self end def zero? [0, 0.0].include?(self) || (is_a?(Num) && n.zero?) end def one? [1, 1.0].include?(self) || (is_a?(Num) && n.one?) end def minus1? [-1, -1.0].include?(self) || (is_a?(Num) && n.minus1?) end def negative? num? && self < 0 end def distributive?(ope1, ope2) [ope1.super, ope1.inv_super].include?(ope2) end # TODO: Cyclomatic complexity for combinable? is too high. [17/6] def combinable?(x, operator) case operator when :+ (num? && x.num?) || (formula?(:*) && (f.num? || g.num?)) && x.num? || like_term?(x) || inverse?(:+, x) when :* self == x || (num? && x.num?) || inverse?(:*, x) when :** (num? && x.num?) || zero? || one? end end # TODO: Cyclomatic complexity for combinable? is too high. [9/6] def like_term?(x) self == x || formula?(:*) && include?(x) || x.formula?(:*) && x.include?(self)|| (formula?(:*) && formula?(:*) && !([f, g] & [x.f, x.g]).empty?) end # TODO: Cyclomatic complexity for combinable? is too high. [7/6] def multiple_of?(x) zero? || self == x || (num? && x.num? && self % x == 0) || (formula?(:*) && (f == x || g == x)) end def rest(f_or_g) ([:f, :g] - [f_or_g]).first end def distributable?(_operator) end def inverse?(operator, x = nil) if is_a?(Algebra::Inverse) self.operator == operator && (self.x == x || x.nil?) elsif x.is_a?(Algebra::Inverse) self == x.x else false end end def formula?(operator) is_a?(Formula) && (@operator == operator) end Symbol.class_eval do def commutative? [:+, :*].include?(self) end def associative? [:+, :*].include?(self) end def super SUPER_OPE_RELATION[self] || self end def sub SUPER_OPE_RELATION.invert[self] || self end def inv INVERSE_OPE_RELATION[self] || self end def inv_super self.super.inv end end def ==(x) to_s == x.to_s end end end