dydx 0.1.314 → 0.1.412

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +25 -0
  3. data/.travis.yml +3 -1
  4. data/Gemfile +1 -0
  5. data/README.md +4 -2
  6. data/Rakefile +5 -8
  7. data/dydx.gemspec +13 -13
  8. data/lib/dydx.rb +20 -27
  9. data/lib/dydx/algebra.rb +8 -6
  10. data/lib/dydx/algebra/formula.rb +53 -28
  11. data/lib/dydx/algebra/inverse.rb +2 -2
  12. data/lib/dydx/algebra/operator/formula.rb +0 -1
  13. data/lib/dydx/algebra/operator/general.rb +0 -1
  14. data/lib/dydx/algebra/operator/inverse.rb +0 -1
  15. data/lib/dydx/algebra/operator/num.rb +0 -1
  16. data/lib/dydx/algebra/operator/parts/base.rb +2 -2
  17. data/lib/dydx/algebra/operator/parts/formula.rb +61 -40
  18. data/lib/dydx/algebra/operator/parts/general.rb +83 -32
  19. data/lib/dydx/algebra/operator/parts/inverse.rb +4 -4
  20. data/lib/dydx/algebra/operator/parts/num.rb +16 -11
  21. data/lib/dydx/algebra/operator/parts/symbol.rb +2 -2
  22. data/lib/dydx/algebra/set.rb +82 -122
  23. data/lib/dydx/delta.rb +1 -1
  24. data/lib/dydx/function.rb +1 -1
  25. data/lib/dydx/helper.rb +43 -66
  26. data/lib/dydx/integrand.rb +7 -6
  27. data/lib/dydx/version.rb +1 -1
  28. data/spec/dydx_spec.rb +3 -3
  29. data/spec/lib/algebra/formula_spec.rb +41 -41
  30. data/spec/lib/algebra/operator/parts/base_spec.rb +5 -5
  31. data/spec/lib/algebra/operator/parts/formula_spec.rb +57 -57
  32. data/spec/lib/algebra/operator/parts/inverse_spec.rb +8 -8
  33. data/spec/lib/algebra/set_spec.rb +193 -150
  34. data/spec/lib/delta_spec.rb +23 -25
  35. data/spec/lib/function_spec.rb +4 -6
  36. data/spec/lib/helper_spec.rb +44 -51
  37. data/spec/lib/integrand_spec.rb +12 -10
  38. data/spec/spec_helper.rb +2 -1
  39. metadata +6 -7
  40. data/lib/dydx/algebra/operator/parts.rb +0 -6
  41. data/lib/dydx/algebra/operator/parts/interface.rb +0 -22
@@ -2,50 +2,94 @@ module Dydx
2
2
  module Algebra
3
3
  module Operator
4
4
  module Parts
5
- module General
6
- %w(+ * ^).map(&:to_sym).each do |operator|
5
+ module Interface
6
+ %w(+ - * / ** %).map(&:to_sym).each do |operator|
7
+ define_method(operator) do |x|
8
+ x = _(x) if x.is_a?(Numeric)
9
+ if operator == :/ && x.zero?
10
+ fail ZeroDivisionError
11
+ elsif [:-, :/].include?(operator)
12
+ send(operator.inv, inverse(x, operator.inv))
13
+ else
14
+ super(x)
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ module Associative
21
+ %w(+ * **).map(&:to_sym).each do |operator|
22
+ define_method(operator) do |x|
23
+ if operator.associative?
24
+ if x.formula?(operator)
25
+ if combinable?(x.f, operator)
26
+ send(operator, x.f).send(operator, x.g)
27
+ elsif combinable?(x.g, operator)
28
+ send(operator, x.g).send(operator, x.f)
29
+ else
30
+ super(x)
31
+ end
32
+ elsif x.is_a?(Inverse) && x.operator == operator && x.x.formula?(operator)
33
+ if combinable?(x.x.f, operator)
34
+ send(operator, inverse(x.x.f, operator)).send(operator, inverse(x.x.g, operator))
35
+ elsif combinable?(x.x.g, operator)
36
+ send(operator, inverse(x.x.g, operator)).send(operator, inverse(x.x.f, operator))
37
+ else
38
+ super(x)
39
+ end
40
+ else
41
+ super(x)
42
+ end
43
+ else
44
+ super(x)
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ module General1
51
+ %w(+ * **).map(&:to_sym).each do |operator|
7
52
  define_method(operator) do |x|
8
- if x.is_0?
53
+ if x.zero?
9
54
  case operator
10
- when :+ then self
11
- when :* then x
12
- when :^ then e1
55
+ when :+ then self
56
+ when :* then x
57
+ when :** then e1
13
58
  end
14
- elsif x.is_1?
59
+ elsif x.one?
15
60
  case operator
16
- when :+ then super(x)
17
- when :* then self
18
- when :^ then self
61
+ when :+ then super(x)
62
+ when :* then self
63
+ when :** then self
19
64
  end
20
65
  elsif self == x
21
66
  case operator
22
- when :+ then _(2) * self
23
- when :* then self ^ _(2)
24
- when :^ then super(x)
67
+ when :+ then _(2) * self
68
+ when :* then self ** _(2)
69
+ when :** then super(x)
25
70
  end
26
- elsif operator == :+ && inverse?(:+, x)
27
- e0
28
- elsif operator == :* && inverse?(:*, x)
29
- e1
30
- elsif [:+, :*].include?(operator) && x.formula?(operator)
31
- if combinable?(x.f, operator)
32
- send(operator, x.f).send(operator, x.g)
33
- elsif combinable?(x.g, operator)
34
- send(operator, x.g).send(operator, x.f)
35
- else
36
- super(x)
71
+ elsif inverse?(operator, x)
72
+ case operator
73
+ when :+ then e0
74
+ when :* then e1
37
75
  end
38
- elsif [:+, :*].include?(operator) && x.formula?(operator.super) && self == x.f
39
- send(operator.super, (1 + x.g))
40
- elsif x.is_a?(Inverse) && x.operator == operator && x.x.formula?(operator)
41
- if combinable?(x.x.f, operator)
42
- send(operator, inverse(x.x.f, operator)).send(operator, inverse(x.x.g, operator))
43
- elsif combinable?(x.x.g, operator)
44
- send(operator, inverse(x.x.g, operator)).send(operator, inverse(x.x.f, operator))
76
+ elsif [:+, :*].include?(operator)
77
+ if x.formula?(operator.super) && self == x.f
78
+ send(operator.super, (1 + x.g))
45
79
  else
46
80
  super(x)
47
81
  end
48
- elsif operator == :* && x.inverse?(:+)
82
+ else
83
+ super(x)
84
+ end
85
+ end
86
+ end
87
+ end
88
+
89
+ module General2
90
+ %w(+ * **).map(&:to_sym).each do |operator|
91
+ define_method(operator) do |x|
92
+ if operator == :* && x.inverse?(:+)
49
93
  -(self * x.x)
50
94
  else
51
95
  super(x)
@@ -53,6 +97,13 @@ module Dydx
53
97
  end
54
98
  end
55
99
  end
100
+
101
+ module General
102
+ include General2
103
+ include General1
104
+ include Associative
105
+ include Interface
106
+ end
56
107
  end
57
108
  end
58
109
  end
@@ -3,17 +3,17 @@ module Dydx
3
3
  module Operator
4
4
  module Parts
5
5
  module Inverse
6
- %w(+ * ^).map(&:to_sym).each do |operator|
6
+ %w(+ * **).map(&:to_sym).each do |operator|
7
7
  define_method(operator) do |x|
8
8
  if inverse?(operator, x)
9
9
  case operator
10
10
  when :+ then e0
11
11
  when :* then e1
12
12
  end
13
- elsif !x.is_a?(Inverse) && operator == :+
13
+ elsif operator.eql?(:+) && !x.is_a?(Inverse)
14
14
  x + self
15
- elsif self.operator == :* && operator == :^
16
- inverse(self.x ^ x, :*)
15
+ elsif operator.eql?(:**) && self.operator.eql?(:*)
16
+ inverse(self.x ** x, :*)
17
17
  else
18
18
  super(x)
19
19
  end
@@ -3,31 +3,36 @@ module Dydx
3
3
  module Operator
4
4
  module Parts
5
5
  module Num
6
- %w(+ * ^).map(&:to_sym).each do |operator|
6
+ %w(+ * **).map(&:to_sym).each do |operator|
7
7
  define_method(operator) do |x|
8
- if is_0?
8
+ if x.is_a?(Num)
9
+ _(n.send(operator, x.n))
10
+ elsif operator == :+ && x.inverse?(:+) && x.x.is_a?(Num)
11
+ _(n - x.x.n)
12
+ elsif operator == :* && x.inverse?(:*) && x.x.is_a?(Num) && n % x.x.n == 0
13
+ _(n / x.x.n)
14
+ elsif zero?
9
15
  case operator
10
16
  when :+ then x
11
17
  when :* then e0
12
- when :^ then e0
18
+ when :** then e0
13
19
  end
14
- elsif is_1?
20
+ elsif one?
15
21
  case operator
16
22
  when :+ then super(x)
17
23
  when :* then x
18
- when :^ then e1
24
+ when :** then e1
19
25
  end
20
- elsif x.is_a?(Num)
21
- _(n.send(operator, x.n))
22
- elsif operator == :+ && x.inverse?(:+) && x.x.is_a?(Num)
23
- _(n - x.x.n)
24
- elsif operator == :* && x.inverse?(:*) && x.x.is_a?(Num)
25
- _(n / x.x.n)
26
26
  else
27
27
  super(x)
28
28
  end
29
29
  end
30
30
  end
31
+
32
+ def %(num)
33
+ fail ArgumentError, "#{num} should be Num class object" unless num.is_a?(Num)
34
+ _(n % num.n)
35
+ end
31
36
  end
32
37
  end
33
38
  end
@@ -4,10 +4,10 @@ module Dydx
4
4
  module Parts
5
5
  module Symbol
6
6
  def *(x)
7
- if x.formula?(:^) &&
7
+ if x.formula?(:**) &&
8
8
  self == x.f
9
9
 
10
- self ^ (1 + x.g)
10
+ self ** (1 + x.g)
11
11
  else
12
12
  super(x)
13
13
  end
@@ -1,9 +1,17 @@
1
- require 'dydx/algebra/operator/parts'
1
+ require 'dydx/algebra/operator/parts/base'
2
+ require 'dydx/algebra/operator/parts/general'
3
+ require 'dydx/algebra/operator/parts/formula'
4
+ require 'dydx/algebra/operator/parts/inverse'
5
+ require 'dydx/algebra/operator/parts/num'
6
+
2
7
  require 'dydx/algebra/operator/inverse'
3
8
  require 'dydx/algebra/operator/formula'
4
9
  require 'dydx/algebra/operator/num'
5
10
  require 'dydx/algebra/operator/general'
6
11
 
12
+ require 'dydx/algebra/formula'
13
+ require 'dydx/algebra/inverse'
14
+
7
15
  module Dydx
8
16
  module Algebra
9
17
  module Set
@@ -11,12 +19,12 @@ module Dydx
11
19
  include Helper
12
20
 
13
21
  # TODO: Pi should not have attr_accessor
14
- def self.included(klass)
22
+ def self.included(_klass)
15
23
  attr_accessor :n, :x
16
24
  alias_method :d, :differentiate
17
25
  end
18
26
 
19
- def initialize(x=nil)
27
+ def initialize(x = nil)
20
28
  case self
21
29
  when Num
22
30
  @n = x
@@ -30,12 +38,12 @@ module Dydx
30
38
  when Num then n.to_s
31
39
  when Pi then 'pi'
32
40
  when E then 'e'
33
- when Sin then "sin( #{x.to_s} )"
34
- when Cos then "cos( #{x.to_s} )"
35
- when Tan then "tan( #{x.to_s} )"
36
- when Log then "log( #{x.to_s} )"
37
- when Log10 then "log10( #{x.to_s} )"
38
- when Log2 then "log2( #{x.to_s} )"
41
+ when Sin then "sin( #{x} )"
42
+ when Cos then "cos( #{x} )"
43
+ when Tan then "tan( #{x} )"
44
+ when Log then "log( #{x} )"
45
+ when Log10 then "log10( #{x} )"
46
+ when Log2 then "log2( #{x} )"
39
47
  end
40
48
  end
41
49
 
@@ -44,7 +52,7 @@ module Dydx
44
52
  when Num then n.to_f
45
53
  when Pi then Math::PI
46
54
  when E then Math::E
47
- when Symbol then raise ArgumentError
55
+ when Symbol then fail ArgumentError
48
56
  when Sin then Math.sin(x.to_f)
49
57
  when Cos then Math.cos(x.to_f)
50
58
  when Tan then Math.tan(x.to_f)
@@ -86,6 +94,12 @@ module Dydx
86
94
  class Num
87
95
  include Base
88
96
  include Operator::Num
97
+ %w(> >= < <=).each do |operator|
98
+ define_method(operator) do |x|
99
+ x = x.n if x.is_a?(Num)
100
+ n.send(operator, x)
101
+ end
102
+ end
89
103
  end
90
104
 
91
105
  class Pi
@@ -133,15 +147,14 @@ module Dydx
133
147
  include Operator::General
134
148
  end
135
149
 
136
- # FIX: Numeric
137
- Fixnum.class_eval do
150
+ numeric_proc = Proc.new do
138
151
  include Helper
139
152
 
140
- def subst(hash = {})
153
+ def subst(_hash = {})
141
154
  self
142
155
  end
143
156
 
144
- def differentiate(sym=:x)
157
+ def differentiate(_sym = :x)
145
158
  e0
146
159
  end
147
160
  alias_method :d, :differentiate
@@ -151,113 +164,42 @@ module Dydx
151
164
  alias_method :multiplication, :*
152
165
  alias_method :division, :/
153
166
  alias_method :exponentiation, :**
154
- ope_to_str = {
155
- addition: :+,
156
- subtraction: :-,
157
- multiplication: :*,
158
- division: :/,
159
- exponentiation: :^
160
- }
161
- %w(+ - * / ^).each do |operator|
162
- define_method(operator) do |g|
163
- if g.is_a?(Symbol) ||
164
- g.is_a?(Formula) ||
165
- g.is_a?(Base)
166
-
167
- Num.new(self).send(operator.to_sym, g)
168
- else
169
- send(ope_to_str.key(operator.to_sym), g)
170
- end
171
- end
172
- end
173
- end
167
+ alias_method :modulation, :%
174
168
 
175
- Float.class_eval do
176
- include Helper
177
-
178
- def subst(hash = {})
179
- self
180
- end
181
-
182
- def differentiate(sym=:x)
183
- e0
184
- end
185
- alias_method :d, :differentiate
186
-
187
- alias_method :addition, :+
188
- alias_method :subtraction, :-
189
- alias_method :multiplication, :*
190
- alias_method :division, :/
191
- alias_method :exponentiation, :**
192
169
  ope_to_str = {
193
170
  addition: :+,
194
171
  subtraction: :-,
195
172
  multiplication: :*,
196
173
  division: :/,
197
- exponentiation: :^
174
+ exponentiation: :**,
175
+ modulation: :%
198
176
  }
199
- %w(+ - * / ^).each do |operator|
177
+ %w(+ - * / ** %).each do |operator|
200
178
  define_method(operator) do |g|
201
- if g.is_a?(Symbol) ||
202
- g.is_a?(Formula) ||
203
- g.is_a?(Base)
204
-
205
- Num.new(self).send(operator.to_sym, g)
206
- else
179
+ if g.is_a?(Numeric)
207
180
  send(ope_to_str.key(operator.to_sym), g)
181
+ else
182
+ _(self).send(operator, g)
208
183
  end
209
184
  end
210
185
  end
211
- end
212
-
213
- Rational.class_eval do
214
- include Helper
215
-
216
- def subst(hash = {})
217
- self
218
- end
219
-
220
- def differentiate(sym=:x)
221
- e0
222
- end
223
- alias_method :d, :differentiate
224
-
225
- alias_method :addition, :+
226
- alias_method :subtraction, :-
227
- alias_method :multiplication, :*
228
- alias_method :division, :/
229
- alias_method :exponentiation, :**
230
- ope_to_str = {
231
- addition: :+,
232
- subtraction: :-,
233
- multiplication: :*,
234
- division: :/,
235
- exponentiation: :^
236
- }
237
- %w(+ - * / ^).each do |operator|
238
- define_method(operator) do |g|
239
- if g.is_a?(Symbol) ||
240
- g.is_a?(Formula) ||
241
- g.is_a?(Base)
242
-
243
- Num.new(self).send(operator.to_sym, g)
244
- else
245
- send(ope_to_str.key(operator.to_sym), g)
246
- end
186
+ if self == Rational
187
+ def to_s
188
+ "( #{numerator} / #{denominator} )"
247
189
  end
248
190
  end
249
191
  end
250
192
 
193
+ Float.class_eval(&numeric_proc)
194
+ Fixnum.class_eval(&numeric_proc)
195
+ Rational.class_eval(&numeric_proc)
196
+
251
197
  def e0
252
- eval("$e0 ||= Num.new(0)")
198
+ eval('$e0 ||= _(0)')
253
199
  end
254
200
 
255
201
  def e1
256
- eval("$e1 ||= Num.new(1)")
257
- end
258
-
259
- def _(num)
260
- Num.new(num)
202
+ eval('$e1 ||= _(1)')
261
203
  end
262
204
 
263
205
  def pi
@@ -272,14 +214,15 @@ module Dydx
272
214
  Float::INFINITY
273
215
  end
274
216
 
217
+ # TODO: Method has too many lines. [13/10]
275
218
  def log(formula)
276
- if formula.multiplication?
219
+ if formula.formula?(:*)
277
220
  f, g = formula.f, formula.g
278
221
  log(f) + log(g)
279
- elsif formula.exponentiation?
222
+ elsif formula.formula?(:**)
280
223
  f, g = formula.f, formula.g
281
224
  g * log(f)
282
- elsif formula.is_1?
225
+ elsif formula.one?
283
226
  e0
284
227
  elsif formula.is_a?(E)
285
228
  e1
@@ -290,13 +233,13 @@ module Dydx
290
233
 
291
234
  def log2(formula)
292
235
  # TODO: refactor with log function.
293
- if formula.multiplication?
236
+ if formula.formula?(:*)
294
237
  f, g = formula.f, formula.g
295
238
  log2(f) + log2(g)
296
- elsif formula.exponentiation?
239
+ elsif formula.formula?(:**)
297
240
  f, g = formula.f, formula.g
298
241
  g * log2(f)
299
- elsif formula.is_1?
242
+ elsif formula.one?
300
243
  e0
301
244
  elsif formula.is_a?(Num)
302
245
  (formula.n == 2) ? e1 : log2(formula.n)
@@ -309,13 +252,13 @@ module Dydx
309
252
 
310
253
  def log10(formula)
311
254
  # TODO: refactor with log function.
312
- if formula.multiplication?
255
+ if formula.formula?(:*)
313
256
  f, g = formula.f, formula.g
314
257
  log10(f) + log10(g)
315
- elsif formula.exponentiation?
258
+ elsif formula.formula?(:**)
316
259
  f, g = formula.f, formula.g
317
260
  g * log10(f)
318
- elsif formula.is_1?
261
+ elsif formula.one?
319
262
  e0
320
263
  elsif formula.is_a?(Num)
321
264
  (formula.n == 10) ? e1 : log10(formula.n)
@@ -326,23 +269,40 @@ module Dydx
326
269
  end
327
270
  end
328
271
 
272
+ # TODO: We should negative num
329
273
  def sin(x)
330
- multiplier = x.is_multiple_of(pi)
331
- if multiplier.is_a?(Num)
332
- e0
333
- else
334
- Sin.new(x)
274
+ return Sin.new(x) unless x.multiple_of?(pi) && (x / pi).num?
275
+
276
+ radn = (x / pi)
277
+ loop do
278
+ break if radn < 2
279
+ radn -= 2
280
+ end
281
+
282
+ case radn
283
+ when 0 then 0
284
+ when _(1) / 2 then 1
285
+ when 1 then 0
286
+ when _(3) / 2 then -1
287
+ else Sin.new(x)
335
288
  end
336
289
  end
337
290
 
338
291
  def cos(x)
339
- multiplier = x.is_multiple_of(pi)
340
- if multiplier.is_a?(Num) && multiplier.n % 2 == 0
341
- e1
342
- elsif multiplier.is_a?(Num) && multiplier.n % 2 == 1
343
- _(-1)
344
- else
345
- Cos.new(x)
292
+ return Cos.new(x) unless x.multiple_of?(pi) && (x / pi).num?
293
+
294
+ radn = (x / pi)
295
+ loop do
296
+ break if radn < 2
297
+ radn -= 2
298
+ end
299
+
300
+ case radn
301
+ when 0 then 1
302
+ when _(1) / 2 then 0
303
+ when 1 then -1
304
+ when _(3) / 2 then 0
305
+ else Cos.new(x)
346
306
  end
347
307
  end
348
308