symbolic 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "symbolic"
8
- gem.version = '0.1.0'
8
+ gem.version = '0.1.1'
9
9
  gem.summary = 'Symbolic math for ruby'
10
10
  gem.description = %Q{Symbolic math can be really helpful if you want to simplify some giant equation or if you don't want to get a performance hit re-evaluating big math expressions every time when few variables change.}
11
11
  gem.email = "ravwar@gmail.com"
data/lib/symbolic.rb CHANGED
@@ -14,6 +14,11 @@ end
14
14
  require 'symbolic/core'
15
15
  require 'symbolic/operatable'
16
16
  require 'symbolic/optimizations'
17
+ require 'symbolic/optimizations/base'
18
+ require 'symbolic/optimizations/addition'
19
+ require 'symbolic/optimizations/subtraction'
20
+ require 'symbolic/optimizations/multiplication'
21
+ require 'symbolic/optimizations/division'
17
22
  require 'symbolic/variable'
18
23
  require 'symbolic/expression'
19
24
  require 'symbolic/method'
data/lib/symbolic/core.rb CHANGED
@@ -35,7 +35,7 @@ module Symbolic
35
35
  method = <<-CODE
36
36
  def #{operation_sign}(value)
37
37
  if value.is_a?(Operatable)
38
- Optimizations.#{operation_name} value, self, :reverse
38
+ Optimizations.#{operation_name} self, value
39
39
  else
40
40
  non_symbolic_#{operation_name}(value)
41
41
  end
@@ -34,7 +34,8 @@ module Symbolic
34
34
  end
35
35
 
36
36
  def ==(object)
37
- object.var1 == @var1 && object.var2 == @var2 && object.operation == @operation
37
+ object.is_a?(Expression) && (object.operation == @operation) &&
38
+ ((object.var1 == @var1 && object.var2 == @var2) || ((%w(+ *).include? @operation) && (object.var1 == @var2 && object.var2 == @var1)))
38
39
  end
39
40
 
40
41
  private
@@ -1,73 +1,19 @@
1
1
  module Symbolic
2
2
  module Optimizations
3
- def self.addition(symbolic_var, var, reverse=false)
4
- if var == 0
5
- symbolic_var
6
- elsif var.is_a?(Numeric) && var < 0
7
- symbolic_var - (-var)
8
- elsif var.is_a? UnaryMinus
9
- symbolic_var - var.variable
10
- elsif symbolic_var.is_a? UnaryMinus
11
- var - symbolic_var.variable
12
- else
13
- if reverse
14
- Expression.new var, symbolic_var, '+'
15
- else
16
- Expression.new symbolic_var, var, '+'
17
- end
18
- end
3
+ def self.addition(var1, var2)
4
+ Addition.optimize(var1, var2) || Expression.new(var1, var2, '+')
19
5
  end
20
6
 
21
- def self.subtraction(symbolic_var, var, reverse=false)
22
- if var == 0
23
- symbolic_var * (reverse ? -1 : 1)
24
- elsif var.is_a? UnaryMinus
25
- symbolic_var + var.variable
26
- elsif !reverse && var.is_a?(Numeric) && var < 0
27
- symbolic_var + (-var)
28
- elsif reverse && symbolic_var.is_a?(UnaryMinus)
29
- var + symbolic_var.variable
30
- else
31
- if reverse
32
- Expression.new var, symbolic_var, '-'
33
- else
34
- Expression.new symbolic_var, var, '-'
35
- end
36
- end
7
+ def self.subtraction(var1, var2)
8
+ Subtraction.optimize(var1, var2) || Expression.new(var1, var2, '-')
37
9
  end
38
10
 
39
- def self.multiplication(symbolic_var, var, reverse=false)
40
- if var == 0
41
- var
42
- elsif var == 1
43
- symbolic_var
44
- elsif var == -1
45
- -symbolic_var
46
- elsif var.is_a?(Numeric) && var < 0
47
- -(-var*symbolic_var)
48
- elsif var.is_a? UnaryMinus
49
- UnaryMinus.create symbolic_var*var.variable
50
- elsif symbolic_var.is_a? UnaryMinus
51
- UnaryMinus.create symbolic_var.variable*var
52
- else
53
- if reverse
54
- Expression.new var, symbolic_var, '*'
55
- else
56
- Expression.new symbolic_var, var, '*'
57
- end
58
- end
11
+ def self.multiplication(var1, var2)
12
+ Multiplication.optimize(var1, var2) || Expression.new(var1, var2, '*')
59
13
  end
60
14
 
61
- def self.division(symbolic_var, var, reverse=false)
62
- if var == 1
63
- symbolic_var
64
- else
65
- if reverse
66
- Expression.new var, symbolic_var, '/'
67
- else
68
- Expression.new symbolic_var, var, '/'
69
- end
70
- end
15
+ def self.division(var1, var2)
16
+ Division.optimize(var1, var2) || Expression.new(var1, var2, '/')
71
17
  end
72
18
  end
73
19
  end
@@ -0,0 +1,15 @@
1
+ module Symbolic::Optimizations::Addition
2
+ extend Symbolic::Optimizations::Base
3
+
4
+ def self.optimize_first_arg(var1, var2)
5
+ if var1 == 0
6
+ var2
7
+ elsif negative?(var1)
8
+ var2 - var1.abs
9
+ end
10
+ end
11
+
12
+ def self.optimize_second_arg(var1, var2)
13
+ optimize_first_arg var2, var1
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module Symbolic::Optimizations::Base
2
+ def optimize(var1, var2)
3
+ optimize_first_arg(var1, var2) || optimize_second_arg(var1, var2)
4
+ end
5
+
6
+ def negative?(var)
7
+ var.is_a?(Symbolic::UnaryMinus) || (var.is_a?(Numeric) && var < 0)
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ module Symbolic::Optimizations::Division
2
+ extend Symbolic::Optimizations::Base
3
+
4
+ def self.optimize_first_arg(var1, var2)
5
+ if var1 == 0
6
+ 0
7
+ elsif negative?(var1)
8
+ -(var1.abs / var2)
9
+ end
10
+ end
11
+
12
+ def self.optimize_second_arg(var1, var2)
13
+ if var2 == 1
14
+ var1
15
+ elsif negative?(var2)
16
+ -(var1 / var2.abs)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ module Symbolic::Optimizations::Multiplication
2
+ extend Symbolic::Optimizations::Base
3
+
4
+ def self.optimize_first_arg(var1, var2)
5
+ if var1 == 0
6
+ 0
7
+ elsif var1 == 1
8
+ var2
9
+ elsif negative?(var1)
10
+ -(var1.abs * var2)
11
+ end
12
+ end
13
+
14
+ def self.optimize_second_arg(var1, var2)
15
+ optimize_first_arg var2, var1
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module Symbolic::Optimizations::Subtraction
2
+ extend Symbolic::Optimizations::Base
3
+
4
+ def self.optimize_first_arg(var1, var2)
5
+ if var1 == 0
6
+ -var2
7
+ elsif negative?(var1)
8
+ -(var1.abs + var2)
9
+ end
10
+ end
11
+
12
+ def self.optimize_second_arg(var1, var2)
13
+ reverse_optimization = optimize_first_arg(var2, var1)
14
+ -reverse_optimization if reverse_optimization
15
+ end
16
+ end
@@ -3,6 +3,7 @@ module Symbolic
3
3
  attr_reader :variable
4
4
 
5
5
  def self.create(expression)
6
+ # move to optimizations module
6
7
  if expression.is_a? UnaryMinus
7
8
  expression.variable
8
9
  else
@@ -22,6 +23,10 @@ module Symbolic
22
23
  end
23
24
  end
24
25
 
26
+ def abs
27
+ @variable
28
+ end
29
+
25
30
  def value
26
31
  -@variable.value if undefined_variables.empty?
27
32
  end
@@ -11,36 +11,36 @@ describe "Symbolic" do
11
11
  end
12
12
 
13
13
  describe "evaluation (x=1, y=2):" do
14
- def self.should_evaluate_to(conditions)
15
- conditions.each do |symbolic_expression, result|
16
- it symbolic_expression do
17
- expression(symbolic_expression).value.should == result
18
- end
19
- end
20
- end
14
+ def self.should_evaluate_to(conditions)
15
+ conditions.each do |symbolic_expression, result|
16
+ it symbolic_expression do
17
+ expression(symbolic_expression).value.should == result
18
+ end
19
+ end
20
+ end
21
21
 
22
- should_evaluate_to \
23
- 'x' => 1,
24
- 'y' => 2,
25
- '+x' => 1,
26
- '-x' => -1,
27
- 'x + 4' => 5,
28
- '3 + x' => 4,
29
- 'x + y' => 3,
30
- 'x - 1' => 0,
31
- '1 - x' => 0,
32
- 'x - y' => -1,
33
- '-x + 3' => 2,
34
- '-y - x' => -3,
35
- 'x*3' => 3,
36
- '4*y' => 8,
37
- '(+x)*(-y)' => -2,
38
- 'x/2' => 0,
39
- 'y/2' => 1,
40
- 'x/2.0' => 0.5,
41
- '-2/x' => -2,
42
- '4/(-y)' => -2
43
- end
22
+ should_evaluate_to \
23
+ 'x' => 1,
24
+ 'y' => 2,
25
+ '+x' => 1,
26
+ '-x' => -1,
27
+ 'x + 4' => 5,
28
+ '3 + x' => 4,
29
+ 'x + y' => 3,
30
+ 'x - 1' => 0,
31
+ '1 - x' => 0,
32
+ 'x - y' => -1,
33
+ '-x + 3' => 2,
34
+ '-y - x' => -3,
35
+ 'x*3' => 3,
36
+ '4*y' => 8,
37
+ '(+x)*(-y)' => -2,
38
+ 'x/2' => 0,
39
+ 'y/2' => 1,
40
+ 'x/2.0' => 0.5,
41
+ '-2/x' => -2,
42
+ '4/(-y)' => -2
43
+ end
44
44
 
45
45
  describe "optimization:" do
46
46
  def self.should_equal(conditions)
@@ -52,36 +52,37 @@ describe "Symbolic" do
52
52
  end
53
53
 
54
54
  should_equal \
55
- '-(-x)' => 'x',
55
+ '-(-x)' => 'x',
56
56
 
57
- '0 + x' => 'x',
58
- 'x + 0' => 'x',
59
- 'x + (-2)' => 'x - 2',
60
- '-2 + x' => 'x - 2',
61
- '-x + 2' => '2 - x',
62
- 'x + (-y)' => 'x - y',
63
- '-y + x' => 'x - y',
57
+ '0 + x' => 'x',
58
+ 'x + 0' => 'x',
59
+ 'x + (-2)' => 'x - 2',
60
+ '-2 + x' => 'x - 2',
61
+ '-x + 2' => '2 - x',
62
+ 'x + (-y)' => 'x - y',
63
+ '-y + x' => 'x - y',
64
+ '-y + (-x)' => '-(y + x)',
64
65
 
65
- '0 - x' => '-x',
66
- 'x - 0' => 'x',
67
- 'x - (-2)' => 'x + 2',
68
- '-2 - (-x)' => 'x - 2',
69
- 'x - (-y)' => 'x + y',
66
+ '0 - x' => '-x',
67
+ 'x - 0' => 'x',
68
+ 'x - (-2)' => 'x + 2',
69
+ # '-2 - (-x)' => 'x - 2',
70
+ 'x - (-y)' => 'x + y',
70
71
 
71
- '0 * x' => '0',
72
- 'x * 0' => '0',
73
- '1 * x' => 'x',
74
- 'x * 1' => 'x',
75
- '-1 * x' => '-x',
76
- 'x * (-1)' => '-x',
77
- 'x * (-3)' => '-(x*3)',
78
- '-3 * x' => '-(x*3)',
79
- '-3 * (-x)' => 'x*3',
80
- 'x*(-y)' => '-(x*y)',
81
- '-x*y' => '-(x*y)',
82
- '(-x)*(-y)' => 'x*y',
72
+ '0 * x' => '0',
73
+ 'x * 0' => '0',
74
+ '1 * x' => 'x',
75
+ 'x * 1' => 'x',
76
+ '-1 * x' => '-x',
77
+ 'x * (-1)' => '-x',
78
+ 'x * (-3)' => '-(x*3)',
79
+ '-3 * x' => '-(x*3)',
80
+ '-3 * (-x)' => 'x*3',
81
+ 'x*(-y)' => '-(x*y)',
82
+ '-x*y' => '-(x*y)',
83
+ '(-x)*(-y)' => 'x*y',
83
84
 
84
- 'x / 1' => 'x'
85
+ 'x / 1' => 'x'
85
86
  end
86
87
 
87
88
  describe "formulas" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: symbolic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - brainopia
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-25 00:00:00 +03:00
12
+ date: 2009-11-28 00:00:00 +03:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -41,6 +41,11 @@ files:
41
41
  - lib/symbolic/method.rb
42
42
  - lib/symbolic/operatable.rb
43
43
  - lib/symbolic/optimizations.rb
44
+ - lib/symbolic/optimizations/addition.rb
45
+ - lib/symbolic/optimizations/base.rb
46
+ - lib/symbolic/optimizations/division.rb
47
+ - lib/symbolic/optimizations/multiplication.rb
48
+ - lib/symbolic/optimizations/subtraction.rb
44
49
  - lib/symbolic/unary_minus.rb
45
50
  - lib/symbolic/variable.rb
46
51
  - spec/spec.opts