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