symbolic 0.0.3 → 0.0.4

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/README.rdoc CHANGED
@@ -1,12 +1,14 @@
1
1
  Symbolic math for ruby.
2
2
 
3
+ Installation: gem install symbolic
4
+
3
5
  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.
4
6
 
5
7
  Currently I've implemented only naive optimizations to simplify math expressions, but it's pretty simple to add your own - see Symbolic::Optimizations module for examples.
6
8
 
7
- Available as gem from gemcutter: gem install symbolic
8
-
9
9
  Simple example:
10
+ require 'rubygems'
11
+ require 'symbolic'
10
12
 
11
13
  Symbolic.enabled = true
12
14
 
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.0.3'
8
+ gem.version = '0.0.4'
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"
@@ -0,0 +1,11 @@
1
+ module Kernel
2
+ def var(options={})
3
+ Symbolic::Variable.new options
4
+ end
5
+
6
+ def symbolic
7
+ Symbolic.enabled = true
8
+ yield
9
+ Symbolic.enabled = false
10
+ end
11
+ end
data/lib/symbolic.rb CHANGED
@@ -1,3 +1,11 @@
1
+ require 'symbolic/operatable'
2
+ require 'symbolic/optimizations'
3
+ require 'symbolic/variable'
4
+ require 'symbolic/expression'
5
+ require 'symbolic/method'
6
+ require 'symbolic/unary_minus'
7
+ require 'extensions/kernel'
8
+
1
9
  module Symbolic
2
10
  @enabled = false
3
11
  class << self
@@ -100,212 +108,4 @@ module Symbolic
100
108
  end
101
109
  end # disable
102
110
  end # class << self
103
-
104
- class Operatable
105
- def -@
106
- UnaryMinus.create self
107
- end
108
-
109
- def *(value)
110
- Optimizations.multiply self, value
111
- end
112
-
113
- def +(value)
114
- Optimizations.plus self, value
115
- end
116
-
117
- def -(value)
118
- Optimizations.minus self, value
119
- end
120
- end # Operations
121
-
122
- module Optimizations
123
- def self.plus(symbolic_var, var, reverse=false)
124
- if var == 0
125
- symbolic_var
126
- elsif var.is_a? UnaryMinus
127
- symbolic_var - var.variable
128
- elsif reverse && symbolic_var.is_a?(UnaryMinus)
129
- var - symbolic_var.variable
130
- else
131
- if reverse
132
- Expression.new var, symbolic_var, '+'
133
- else
134
- Expression.new symbolic_var, var, '+'
135
- end
136
- end
137
- end
138
-
139
- def self.minus(symbolic_var, var, reverse=false)
140
- if var == 0
141
- symbolic_var
142
- elsif var.is_a? UnaryMinus
143
- symbolic_var + var.variable
144
- elsif reverse && symbolic_var.is_a?(UnaryMinus)
145
- var + symbolic_var.variable
146
- else
147
- if reverse
148
- Expression.new var, symbolic_var, '-'
149
- else
150
- Expression.new symbolic_var, var, '-'
151
- end
152
- end
153
- end
154
-
155
- def self.multiply(symbolic_var, var, reverse=false)
156
- if var == 0
157
- var
158
- elsif var == 1
159
- symbolic_var
160
- elsif var == -1
161
- -symbolic_var
162
- elsif var.is_a?(Numeric) && var < 0
163
- -(-var*symbolic_var)
164
- elsif var.is_a? UnaryMinus
165
- UnaryMinus.create symbolic_var*var.variable
166
- elsif symbolic_var.is_a? UnaryMinus
167
- UnaryMinus.create symbolic_var.variable*var
168
- else
169
- if reverse
170
- Expression.new var, symbolic_var, '*'
171
- else
172
- Expression.new symbolic_var, var, '*'
173
- end
174
- end
175
- end
176
- end
177
-
178
- class Variable < Operatable
179
- attr_accessor :value, :name
180
-
181
- @@index = 0
182
-
183
- def initialize(options)
184
- unless @name = options[:name]
185
- @@index += 1
186
- @name = "var#{@@index}"
187
- end
188
-
189
- @value = options[:value]
190
- end
191
-
192
- def to_s
193
- @name
194
- end
195
-
196
- def undefined_variables
197
- @value ? [] : [self]
198
- end
199
- end
200
-
201
- class Expression < Operatable
202
- def initialize(var1, var2, operation)
203
- var1, var2 = var2, var1 if operation == '*' && var2.is_a?(Numeric)
204
- @var1, @var2, @operation = var1, var2, operation
205
- end
206
-
207
- def to_s
208
- var1 = "#{@var1}"
209
- var2 = "#{@var2}"
210
- if @operation == '*'
211
- var1 = "(#{@var1})" if @var1.is_a?(Expression) && (@var1.plus? || @var1.minus?)
212
- var2 = "(#{@var2})" if @var2.is_a?(Expression) && (@var2.plus? || @var1.minus?)
213
- end
214
- "#{var1}#{@operation}#{var2}"
215
- end
216
-
217
- def plus?
218
- @operation == '+'
219
- end
220
-
221
- def minus?
222
- @operation == '-'
223
- end
224
-
225
- def multiply?
226
- @operation == '*'
227
- end
228
-
229
- def value
230
- if undefined_variables.empty?
231
- value_of(@var1).send @operation, value_of(@var2)
232
- end
233
- end
234
-
235
- def undefined_variables
236
- (undefined_variables_of(@var1) + undefined_variables_of(@var2)).uniq
237
- end
238
-
239
- private
240
-
241
- def undefined_variables_of(variable)
242
- variable.is_a?(Operatable) ? variable.undefined_variables : []
243
- end
244
-
245
- def value_of(variable)
246
- variable.is_a?(Operatable) ? variable.value : variable
247
- end
248
- end
249
-
250
- class Method < Operatable
251
- def initialize(variable, operation)
252
- @variable, @operation = variable, operation
253
- end
254
-
255
- def to_s
256
- "#{@operation}(#{@variable})"
257
- end
258
-
259
- def value
260
- Math.send @operation, @variable.value if undefined_variables.empty?
261
- end
262
-
263
- def undefined_variables
264
- @variable.undefined_variables
265
- end
266
- end
267
-
268
- class UnaryMinus < Operatable
269
- attr_reader :variable
270
-
271
- def self.create(expression)
272
- if expression.is_a? UnaryMinus
273
- expression.variable
274
- else
275
- new expression
276
- end
277
- end
278
-
279
- def initialize(variable)
280
- @variable = variable
281
- end
282
-
283
- def to_s
284
- if @variable.is_a? Variable
285
- "-#{@variable}"
286
- else
287
- "(-#{@variable})"
288
- end
289
- end
290
-
291
- def value
292
- -@variable.value if undefined_variables.empty?
293
- end
294
-
295
- def undefined_variables
296
- @variable.undefined_variables
297
- end
298
- end
299
- end
300
-
301
- module Kernel
302
- def var(options={})
303
- Symbolic::Variable.new options
304
- end
305
-
306
- def symbolic
307
- Symbolic.enabled = true
308
- yield
309
- Symbolic.enabled = false
310
- end
311
111
  end
@@ -0,0 +1,50 @@
1
+ module Symbolic
2
+ class Expression < Operatable
3
+ def initialize(var1, var2, operation)
4
+ var1, var2 = var2, var1 if operation == '*' && var2.is_a?(Numeric)
5
+ @var1, @var2, @operation = var1, var2, operation
6
+ end
7
+
8
+ def to_s
9
+ var1 = "#{@var1}"
10
+ var2 = "#{@var2}"
11
+ if @operation == '*'
12
+ var1 = "(#{@var1})" if @var1.is_a?(Expression) && (@var1.plus? || @var1.minus?)
13
+ var2 = "(#{@var2})" if @var2.is_a?(Expression) && (@var2.plus? || @var1.minus?)
14
+ end
15
+ "#{var1}#{@operation}#{var2}"
16
+ end
17
+
18
+ def plus?
19
+ @operation == '+'
20
+ end
21
+
22
+ def minus?
23
+ @operation == '-'
24
+ end
25
+
26
+ def multiply?
27
+ @operation == '*'
28
+ end
29
+
30
+ def value
31
+ if undefined_variables.empty?
32
+ value_of(@var1).send @operation, value_of(@var2)
33
+ end
34
+ end
35
+
36
+ def undefined_variables
37
+ (undefined_variables_of(@var1) + undefined_variables_of(@var2)).uniq
38
+ end
39
+
40
+ private
41
+
42
+ def undefined_variables_of(variable)
43
+ variable.is_a?(Operatable) ? variable.undefined_variables : []
44
+ end
45
+
46
+ def value_of(variable)
47
+ variable.is_a?(Operatable) ? variable.value : variable
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,19 @@
1
+ module Symbolic
2
+ class Method < Operatable
3
+ def initialize(variable, operation)
4
+ @variable, @operation = variable, operation
5
+ end
6
+
7
+ def to_s
8
+ "#{@operation}(#{@variable})"
9
+ end
10
+
11
+ def value
12
+ Math.send @operation, @variable.value if undefined_variables.empty?
13
+ end
14
+
15
+ def undefined_variables
16
+ @variable.undefined_variables
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module Symbolic
2
+ class Operatable
3
+ def -@
4
+ UnaryMinus.create self
5
+ end
6
+
7
+ def *(value)
8
+ Optimizations.multiply self, value
9
+ end
10
+
11
+ def +(value)
12
+ Optimizations.plus self, value
13
+ end
14
+
15
+ def -(value)
16
+ Optimizations.minus self, value
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,57 @@
1
+ module Symbolic
2
+ module Optimizations
3
+ def self.plus(symbolic_var, var, reverse=false)
4
+ if var == 0
5
+ symbolic_var
6
+ elsif var.is_a? UnaryMinus
7
+ symbolic_var - var.variable
8
+ elsif reverse && symbolic_var.is_a?(UnaryMinus)
9
+ var - symbolic_var.variable
10
+ else
11
+ if reverse
12
+ Expression.new var, symbolic_var, '+'
13
+ else
14
+ Expression.new symbolic_var, var, '+'
15
+ end
16
+ end
17
+ end
18
+
19
+ def self.minus(symbolic_var, var, reverse=false)
20
+ if var == 0
21
+ symbolic_var
22
+ elsif var.is_a? UnaryMinus
23
+ symbolic_var + var.variable
24
+ elsif reverse && symbolic_var.is_a?(UnaryMinus)
25
+ var + symbolic_var.variable
26
+ else
27
+ if reverse
28
+ Expression.new var, symbolic_var, '-'
29
+ else
30
+ Expression.new symbolic_var, var, '-'
31
+ end
32
+ end
33
+ end
34
+
35
+ def self.multiply(symbolic_var, var, reverse=false)
36
+ if var == 0
37
+ var
38
+ elsif var == 1
39
+ symbolic_var
40
+ elsif var == -1
41
+ -symbolic_var
42
+ elsif var.is_a?(Numeric) && var < 0
43
+ -(-var*symbolic_var)
44
+ elsif var.is_a? UnaryMinus
45
+ UnaryMinus.create symbolic_var*var.variable
46
+ elsif symbolic_var.is_a? UnaryMinus
47
+ UnaryMinus.create symbolic_var.variable*var
48
+ else
49
+ if reverse
50
+ Expression.new var, symbolic_var, '*'
51
+ else
52
+ Expression.new symbolic_var, var, '*'
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,33 @@
1
+ module Symbolic
2
+ class UnaryMinus < Operatable
3
+ attr_reader :variable
4
+
5
+ def self.create(expression)
6
+ if expression.is_a? UnaryMinus
7
+ expression.variable
8
+ else
9
+ new expression
10
+ end
11
+ end
12
+
13
+ def initialize(variable)
14
+ @variable = variable
15
+ end
16
+
17
+ def to_s
18
+ if @variable.is_a? Variable
19
+ "-#{@variable}"
20
+ else
21
+ "(-#{@variable})"
22
+ end
23
+ end
24
+
25
+ def value
26
+ -@variable.value if undefined_variables.empty?
27
+ end
28
+
29
+ def undefined_variables
30
+ @variable.undefined_variables
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,24 @@
1
+ module Symbolic
2
+ class Variable < Operatable
3
+ attr_accessor :value, :name
4
+
5
+ @@index = 0
6
+
7
+ def initialize(options)
8
+ unless @name = options[:name]
9
+ @@index += 1
10
+ @name = "var#{@@index}"
11
+ end
12
+
13
+ @value = options[:value]
14
+ end
15
+
16
+ def to_s
17
+ @name
18
+ end
19
+
20
+ def undefined_variables
21
+ @value ? [] : [self]
22
+ end
23
+ end
24
+ end
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.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - brainopia
@@ -34,7 +34,14 @@ files:
34
34
  - .gitignore
35
35
  - README.rdoc
36
36
  - Rakefile
37
+ - lib/extensions/kernel.rb
37
38
  - lib/symbolic.rb
39
+ - lib/symbolic/expression.rb
40
+ - lib/symbolic/method.rb
41
+ - lib/symbolic/operatable.rb
42
+ - lib/symbolic/optimizations.rb
43
+ - lib/symbolic/unary_minus.rb
44
+ - lib/symbolic/variable.rb
38
45
  - spec/spec.opts
39
46
  - spec/spec_helper.rb
40
47
  - spec/symbolic_spec.rb