Class: Symbolic::Factors

Inherits:
Expression show all
Defined in:
lib/symbolic/factors.rb

Instance Attribute Summary

Attributes inherited from Expression

#numeric, #symbolic

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Expression

#==, convert, #initialize, numeric, one, simple?, unite, unite_numeric, unite_symbolic, #variables

Methods included from Symbolic

#*, #**, #+, #+@, #-, #-@, #/, #coerce, #inspect, #operations

Constructor Details

This class inherits a constructor from Symbolic::Expression

Class Method Details

.add(var1, var2) ⇒ Object



25
26
27
28
29
30
31
32
33
# File 'lib/symbolic/factors.rb', line 25

def add(var1, var2)
  if distributable? var1, var2
    distribute(var1, var2)
  elsif distributable? var2, var1
    distribute(var2, var1)
  else
    super
  end
end

.distributable?(var1, var2) ⇒ Boolean

Returns:

  • (Boolean)


40
41
42
# File 'lib/symbolic/factors.rb', line 40

def distributable?(var1, var2)
  simple?(var1) && var2.is_a?(Summands)
end

.distribute(var1, var2) ⇒ Object



44
45
46
47
48
# File 'lib/symbolic/factors.rb', line 44

def distribute(var1, var2)
  var2.symbolic.map {|k,v| k*v }.inject(var2.numeric*var1) do |sum, it|
    sum + it*var1
  end
end

.factors(factors) ⇒ Object



16
17
18
# File 'lib/symbolic/factors.rb', line 16

def factors(factors)
  factors
end

.identity_elementObject



8
9
10
# File 'lib/symbolic/factors.rb', line 8

def identity_element
  1
end

.operationObject



4
5
6
# File 'lib/symbolic/factors.rb', line 4

def operation
  '*'
end

.power(base, exponent) ⇒ Object



20
21
22
23
# File 'lib/symbolic/factors.rb', line 20

def power(base, exponent)
  simplify_expression! factors = unite_exponents(base, exponent)
  simplify(*factors) || new(*factors)
end

.simplify(numeric, symbolic) ⇒ Object



55
56
57
58
59
60
61
# File 'lib/symbolic/factors.rb', line 55

def simplify(numeric, symbolic)
  if numeric == 0 || symbolic.empty?
    (numeric.round == numeric) ? numeric.to_i : numeric.to_f
  elsif numeric == identity_element && symbolic.size == 1 && symbolic.values.first == 1
    symbolic.keys.first
  end
end

.simplify_expression!(factors) ⇒ Object



50
51
52
53
# File 'lib/symbolic/factors.rb', line 50

def simplify_expression!(factors)
  factors[1].delete_if {|base, exp| (base == identity_element) || (exp == 0) }
  factors[0] = 0 if factors[1].any? {|base, exp| base == 0 }
end

.subtract(var1, var2) ⇒ Object



35
36
37
38
# File 'lib/symbolic/factors.rb', line 35

def subtract(var1, var2)
  simplify_expression! factors = unite(convert(var1), convert(var2).reverse)
  simplify(*factors) || new(*factors)
end

.summands(summands) ⇒ Object



12
13
14
# File 'lib/symbolic/factors.rb', line 12

def summands(summands)
  one summands
end

.unite_exponents(base, exponent) ⇒ Object



63
64
65
66
67
68
69
# File 'lib/symbolic/factors.rb', line 63

def unite_exponents(base, exponent)
  if base.is_a? Factors
    return base.numeric**exponent, Hash[*base.symbolic.map {|base,exp| [base,exp*exponent] }.flatten]
  else
    [identity_element, { base => exponent }]
  end
end

Instance Method Details

#brackets(var) ⇒ Object



94
95
96
# File 'lib/symbolic/factors.rb', line 94

def brackets(var)
  [Numeric, Symbolic::Variable].any? {|klass| var.is_a? klass } ? var : "(#{var})"
end

#coefficient_to_string(numeric) ⇒ Object



86
87
88
# File 'lib/symbolic/factors.rb', line 86

def coefficient_to_string(numeric)
  "#{'-' if numeric < 0}#{"#{rational_to_string numeric.abs}*" if numeric.abs != 1}"
end

#exponent_to_string(base, exponent) ⇒ Object



90
91
92
# File 'lib/symbolic/factors.rb', line 90

def exponent_to_string(base, exponent)
  "#{brackets base}#{"**#{brackets exponent}" if exponent != 1}"
end

#output(factors) ⇒ Object



107
108
109
110
# File 'lib/symbolic/factors.rb', line 107

def output(factors)
  coefficient_to_string(factors[0]) <<
  factors[1].map {|base,exp| exponent_to_string base,exp }.join('*')
end

#rational_to_string(numeric) ⇒ Object



117
118
119
# File 'lib/symbolic/factors.rb', line 117

def rational_to_string(numeric)
  ((numeric.round == numeric) ? numeric.to_i : numeric.to_f).to_s
end

#reverseObject



72
73
74
# File 'lib/symbolic/factors.rb', line 72

def reverse
  self.class.new numeric**-1, Hash[*symbolic.map {|k,v| [k,-v]}.flatten]
end

#reversed_output(factors) ⇒ Object



112
113
114
115
# File 'lib/symbolic/factors.rb', line 112

def reversed_output(factors)
  result = output [factors[0], Hash[*factors[1].map {|b,e| [b,-e] }.flatten]]
  (factors[1].length > 1) ? "(#{result})" : result
end

#simplify_outputObject



98
99
100
101
102
103
104
105
# File 'lib/symbolic/factors.rb', line 98

def simplify_output
  groups = @symbolic.group_by {|b,e| e.is_a?(Numeric) && e < 0 }
  reversed_factors = groups[true] ? [1, Hash[*groups[true].flatten] ] : nil
  factors = groups[false] ? [@numeric, Hash[*groups[false].flatten] ] : nil
  output = '' << (factors ? output(factors) : rational_to_string(@numeric))
  output << "/#{reversed_output reversed_factors}" if reversed_factors
  output
end

#to_sObject



82
83
84
# File 'lib/symbolic/factors.rb', line 82

def to_s
  simplify_output
end

#valueObject



76
77
78
79
80
# File 'lib/symbolic/factors.rb', line 76

def value
  if variables.all? &:value
    @symbolic.inject(numeric) {|value, (base, exp)| value * base.value ** exp.value }
  end
end