dydx 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/.pryrc +2 -0
  3. data/.rubocop.yml +25 -0
  4. data/Gemfile +3 -0
  5. data/README.md +29 -64
  6. data/Rakefile +5 -8
  7. data/dydx.gemspec +13 -13
  8. data/lib/dydx.rb +20 -29
  9. data/lib/dydx/algebra.rb +8 -76
  10. data/lib/dydx/algebra/formula.rb +67 -29
  11. data/lib/dydx/algebra/inverse.rb +16 -2
  12. data/lib/dydx/algebra/operator/formula.rb +0 -4
  13. data/lib/dydx/algebra/operator/general.rb +0 -4
  14. data/lib/dydx/algebra/operator/inverse.rb +0 -4
  15. data/lib/dydx/algebra/operator/num.rb +0 -4
  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 -30
  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 +271 -34
  23. data/lib/dydx/delta.rb +1 -1
  24. data/lib/dydx/function.rb +1 -1
  25. data/lib/dydx/helper.rb +53 -67
  26. data/lib/dydx/integrand.rb +22 -10
  27. data/lib/dydx/version.rb +1 -1
  28. data/spec/dydx_spec.rb +10 -29
  29. data/spec/lib/algebra/formula_spec.rb +44 -38
  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 +263 -0
  34. data/spec/lib/delta_spec.rb +32 -8
  35. data/spec/lib/function_spec.rb +60 -34
  36. data/spec/lib/helper_spec.rb +44 -51
  37. data/spec/lib/integrand_spec.rb +13 -15
  38. data/spec/spec_helper.rb +2 -1
  39. metadata +20 -64
  40. data/lib/dydx/algebra/operator/common_parts.rb +0 -3
  41. data/lib/dydx/algebra/operator/parts/interface.rb +0 -22
  42. data/lib/dydx/algebra/operator/symbol.rb +0 -15
  43. data/lib/dydx/algebra/set/base.rb +0 -9
  44. data/lib/dydx/algebra/set/cos.rb +0 -22
  45. data/lib/dydx/algebra/set/e.rb +0 -16
  46. data/lib/dydx/algebra/set/fixnum.rb +0 -14
  47. data/lib/dydx/algebra/set/float.rb +0 -14
  48. data/lib/dydx/algebra/set/log.rb +0 -22
  49. data/lib/dydx/algebra/set/num.rb +0 -22
  50. data/lib/dydx/algebra/set/pi.rb +0 -16
  51. data/lib/dydx/algebra/set/sin.rb +0 -22
  52. data/lib/dydx/algebra/set/symbol.rb +0 -14
  53. data/lib/dydx/algebra/set/tan.rb +0 -17
  54. data/spec/lib/algebra/set/cos_spec.rb +0 -18
  55. data/spec/lib/algebra/set/e_spec.rb +0 -27
  56. data/spec/lib/algebra/set/fixnum_spec.rb +0 -65
  57. data/spec/lib/algebra/set/float_spec.rb +0 -65
  58. data/spec/lib/algebra/set/log_spec.rb +0 -15
  59. data/spec/lib/algebra/set/num_spec.rb +0 -23
  60. data/spec/lib/algebra/set/pi_spec.rb +0 -25
  61. data/spec/lib/algebra/set/sin_spec.rb +0 -14
  62. data/spec/lib/algebra/set/symbol_spec.rb +0 -22
  63. data/spec/lib/algebra/set/tan_spec.rb +0 -13
@@ -15,12 +15,26 @@ module Dydx
15
15
  end
16
16
  end
17
17
 
18
- def differentiate(sym=:x)
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 ^ 2, :*), :+)
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(+ * ^).map(&:to_sym).each do |operator|
6
+ %w(+ * **).map(&:to_sym).each do |operator|
7
7
  define_method(operator) do |x|
8
- ::Algebra::Formula.new(self, x, operator.to_sym)
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 |operator|
7
- define_method(operator) do |x|
8
- if self.operator == operator
9
- if f.combinable?(x, operator)
10
- f.send(operator, x).send(operator, g)
11
- elsif g.combinable?(x, operator)
12
- g.send(operator, x).send(operator, f)
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(x)
18
+ super(rtr)
15
19
  end
16
- elsif formula?(sub_ope(operator)) && openable?(operator, x)
17
- f.send(operator, x).send(sub_ope(operator), g.send(operator, x))
18
- elsif formula?(super_ope(operator)) && x.formula?(super_ope(operator))
19
- w1, w2 = common_factors(x)
20
- return super(x) unless (w1 && w2) && (super_ope(operator).commutative? || w1 == w2)
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
- case operator
23
- when :+
24
- send(w1).send(super_ope(operator), send(rest(w1)).send(operator, x.send(rest(w2))))
25
- when :*
26
- case w1
27
- when :f
28
- send(w1).send(super_ope(operator), send(rest(w1)).send(sub_ope(operator), x.send(rest(w2))))
29
- when :g
30
- send(w1).send(super_ope(operator), send(rest(w1)).send(operator, x.send(rest(w2)))).commutate!
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?(super_ope(operator)) && x.inverse?(operator) && x.x.formula?(super_ope(operator))
34
- w1, w2 = common_factors(x.x)
35
- return super(x) unless (w1 && w2) && (super_ope(operator).commutative? || w1 == w2)
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
- case operator
38
- when :+
39
- send(w1).send(super_ope(operator), send(rest(w1)).send(inverse_ope(operator), x.x.send(rest(w2))))
40
- when :*
41
- case w1
42
- when :f
43
- send(w1).send(super_ope(operator), send(rest(w1)).send(inverse_ope(sub_ope(operator)), x.x.send(rest(w2))))
44
- when :g
45
- send(w1).send(super_ope(operator), send(rest(w1)).send(inverse_ope(operator), x.x.send(rest(w2)))).commutate!
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(x)
68
+ super(rtr)
50
69
  end
51
70
  end
52
71
  end
53
72
 
54
- %w(^).map(&:to_sym).each do |operator|
55
- define_method(operator) do |x|
56
- if formula?(sub_ope(operator)) && openable?(operator, x)
57
- f.send(operator, x).send(sub_ope(operator), g.send(operator, x))
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(x)
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 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 x.is_a?(Inverse) && x.operator == operator && x.x.formula?(operator)
39
- if combinable?(x.x.f, operator)
40
- send(operator, inverse(x.x.f, operator)).send(operator, inverse(x.x.g, 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
- 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?(:+)
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(+ * ^).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,33 +1,210 @@
1
- require 'dydx/algebra/set/base'
2
- require 'dydx/algebra/set/num'
3
- require 'dydx/algebra/set/fixnum'
4
- require 'dydx/algebra/set/float'
5
- require 'dydx/algebra/set/symbol'
6
- require 'dydx/algebra/set/e'
7
- require 'dydx/algebra/set/pi'
8
- require 'dydx/algebra/set/log'
9
- require 'dydx/algebra/set/sin'
10
- require 'dydx/algebra/set/cos'
11
- require 'dydx/algebra/set/tan'
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
- def e0
17
- eval("$e0 ||= Num.new(0)")
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
- def e1
21
- eval("$e1 ||= Num.new(1)")
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
- def _(num)
24
- if num >= 0
25
- eval("$p#{num} ||= Num.new(num)")
26
- else
27
- eval("$n#{-1 * num} ||= Num.new(num)")
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.multiplication?
222
+ if formula.formula?(:*)
45
223
  f, g = formula.f, formula.g
46
224
  log(f) + log(g)
47
- elsif formula.exponentiation?
225
+ elsif formula.formula?(:**)
48
226
  f, g = formula.f, formula.g
49
227
  g * log(f)
50
- elsif formula.is_1?
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 sin(x)
60
- multiplier = x.is_multiple_of(pi)
61
- if multiplier.is_a?(Num)
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
- Sin.new(x)
252
+ Log2.new(formula)
65
253
  end
66
254
  end
67
255
 
68
- def cos(x)
69
- multiplier = x.is_multiple_of(pi)
70
- if multiplier.is_a?(Num) && multiplier.n % 2 == 0
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
- Cos.new(x)
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
- Tan.new(x)
313
+ if x == 0
314
+ 0
315
+ else
316
+ Tan.new(x)
317
+ end
81
318
  end
82
319
  end
83
320
  end