dydx 0.1.3 → 0.1.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.
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