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
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 79327c9edd590f2a006eb29d8b148919d913c9a4
4
+ data.tar.gz: d5b7e817ffe55271c3a473d3b1679b3abaa929ee
5
+ SHA512:
6
+ metadata.gz: 5716ffe76bc6e49af3ef2560920cebc20845b01ec1be35ca6b46a4a454530b1582a9820add4c6a2b0a29bfc84e26751133faea9c5c277c19fd1f5f9b8c8c842b
7
+ data.tar.gz: f5dd91eb57c7ac6d6a3dd8a8318b98953295d4de7fb67c530fad3c040b351e225c1a79da03fe4bbb51110545a572fb8ba194de715a34f8ce96a1d6b627c7e4bd
data/.pryrc ADDED
@@ -0,0 +1,2 @@
1
+ require 'dydx'
2
+ include Dydx
@@ -0,0 +1,25 @@
1
+ Eval:
2
+ Enabled: false
3
+
4
+ LineLength:
5
+ Enabled: false
6
+
7
+ # Configuration parameters: AllowedVariables.
8
+ GlobalVars:
9
+ Enabled: false
10
+
11
+ # Configuration parameters: EnforcedStyle, SupportedStyles.
12
+ MethodName:
13
+ Enabled: false
14
+
15
+ OpMethod:
16
+ Enabled: false
17
+
18
+ Void:
19
+ Enabled: false
20
+
21
+ SpaceInsideParens:
22
+ Enabled: false
23
+
24
+ SpaceAroundOperators:
25
+ Enabled: false
data/Gemfile CHANGED
@@ -1,5 +1,8 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in dydx.gemspec
4
+ gem 'rubocop'
4
5
  gem 'pry'
6
+ gem 'pry-coolline'
7
+ # gem 'pry-debugger'
5
8
  gemspec
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Dydx is new math DSL in Ruby
1
+ # Dydx is new MATH Language on Ruby.
2
2
 
3
3
  ### Since you report a bug, I will fix it within 24 hours.
4
4
 
@@ -8,6 +8,8 @@ we can handle math in the same sense sense of the math on paper.
8
8
 
9
9
  ex. limit, trigonometric functions and logarithmic.
10
10
 
11
+ ## We should enjoy MATH even using PC.
12
+ (to say nothing of using pen.)
11
13
 
12
14
  After `inlcude Dydx` , ruby become like other language.
13
15
 
@@ -17,29 +19,31 @@ require 'dydx'
17
19
  include Dydx
18
20
 
19
21
  # Define the function. syntax is not good enough...
20
- f(x) <= x ^ 2
22
+ f(x, y) <= x + x*y + y
21
23
 
22
- f(3)
23
- => 9
24
+ # simplify
25
+ f(x, y) == x * (1 + y) + y
26
+ => true
24
27
 
25
- f(x).to_s
26
- => "( x ^ 2 )"
28
+ #part substitution
29
+ f(a, 2) == 3*a + 2
30
+ => true
27
31
 
28
- f(x) == eval('f(x).to_s')
32
+ f(1, a + b) == 1 + 2 * ( a + b )
29
33
  => true
30
34
 
35
+
31
36
  # Differentiate
32
- g(x) <= d/dx(f(x))
37
+ d/dx(f(x, y)) == 1 + y
38
+ => true
33
39
 
34
- g(3)
35
- => 6
40
+ g(x) <= sin(x)
36
41
 
37
- g(x).to_s
38
- => '2 * x'
42
+ d/dx(g(x)) == cos(x)
39
43
 
40
44
  # Integrate
41
- S(f(x), dx)[0, 1]
42
- => 0.3333333333333334
45
+ S(g(x), dx)[0, pi/2]
46
+ => 1.0
43
47
  ```
44
48
 
45
49
 
@@ -50,57 +54,21 @@ f(z) <= log(z)
50
54
  S(f(z), dz)[0,1]
51
55
  => -Infinity
52
56
 
53
- ( d/dx(log(x)) ).to_s
54
- => "( 1 / x )"
55
-
56
- ( d/dx(cos(x)) ).to_s
57
- => "( - sin( x ) )"
57
+ d/dx(log(x)) == 1 / x
58
+ => true
58
59
 
59
- ( d/dx(e ^ x) ).to_s
60
- => "( e ^ x )"
60
+ d/dx(cos(x)) == -cos(x)
61
+ => true
61
62
 
62
- f(x) <= sin(x)
63
- S(f(x), dx)[0, Math::PI/2]
64
- => 1.000000000021139
63
+ d/dx(e ** x) == e ** x
64
+ => true
65
65
 
66
66
  # standard normal distribution;
67
- f(x) <= (1.0 / ( ( 2.0 * pi ) ^ 0.5 ) ) * ( e ^ (- (x ^ 2) / 2) )
67
+ f(x) <= (1.0 / ( 2.0 * pi ) ** 0.5) * e ** (- x ** 2 / 2)
68
68
  S(f(x), dx)[-oo, oo]
69
- => 0.9952054164466917
69
+ => 1.0
70
70
  ```
71
71
 
72
- #### it's like a magic...
73
-
74
- ```ruby:
75
- f(x) <= x ^ 2
76
-
77
- f(a + b).to_s
78
- => "( ( a + b ) ^ 2 )"
79
-
80
- #↓it"s magic!!!
81
- g(a, b) <= f(a + b)
82
-
83
- g(a, b).to_s
84
- => "( ( a + b ) ^ 2 )"
85
-
86
- g(2, 2)
87
- => 16
88
-
89
- ( d/da(g(a, b)) ).to_s
90
- => "( 2 * ( a + b ) )"
91
-
92
- # simplify
93
- ((x * y) + (z * x)).to_s
94
- => "( x * ( y + z ) )"
95
-
96
- ((x ^ y) / (x ^ z)).to_s
97
- => "( x ^ ( y - z ) )"
98
-
99
- (x + x).to_s
100
- => "( 2 * x )"
101
- ```
102
-
103
-
104
72
  ## Documents
105
73
  I'm going to write now...cominng soon....
106
74
 
@@ -109,14 +77,11 @@ I'm going to write now...cominng soon....
109
77
  ```
110
78
  Dydx
111
79
  |- Algebra
112
- | |- Set
113
- | | |- Num
114
- | | |- ....
115
- | |
116
80
  | |- Operator
117
81
  | | |- Interface
118
82
  | | |- ....
119
83
  | |
84
+ | |- Set
120
85
  | |- Formula
121
86
  | |- inverse
122
87
  |
@@ -156,6 +121,6 @@ Or install it yourself as:
156
121
  run `bundle exec rake spec`
157
122
 
158
123
  ```
159
- Finished in 3.23 seconds
160
- 309 examples, 0 failures
124
+ Finished in 3.76 seconds
125
+ 325 examples, 0 failures
161
126
  ```
data/Rakefile CHANGED
@@ -1,13 +1,10 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
3
  require 'bundler/setup'
4
4
 
5
- desc "run spec"
5
+ desc 'run spec'
6
6
 
7
- #do `rake spec`
8
- RSpec::Core::RakeTask.new(:spec) do |t|
9
- t.rspec_opts = ["-c", "-fs"]
10
- end
7
+ # do `rake spec`
8
+ RSpec::Core::RakeTask.new(:spec)
11
9
 
12
10
  task default: :spec
13
-
@@ -4,22 +4,22 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'dydx/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "dydx"
7
+ spec.name = 'dydx'
8
8
  spec.version = Dydx::VERSION
9
- spec.authors = ["gogotanaka"]
10
- spec.email = ["qlli.illb@gmail.com"]
11
- spec.homepage = "https://github.com/gogotanaka"
12
- spec.summary = %q{We can enjoy the math.}
13
- spec.description = %q{Dydx is new math DSL in Ruby. The most important thing in this DSL is we can handle math in the same sense sense of the math on paper.}
9
+ spec.authors = ['gogotanaka']
10
+ spec.email = ['qlli.illb@gmail.com']
11
+ spec.homepage = 'https://github.com/gogotanaka'
12
+ spec.summary = %q(We can enjoy the math.)
13
+ spec.description = %q(Dydx is new math DSL in Ruby. The most important thing in this DSL is we can handle math in the same sense sense of the math on paper.)
14
14
 
15
- spec.license = "MIT"
15
+ spec.license = 'MIT'
16
16
 
17
17
  spec.files = `git ls-files -z`.split("\x0")
18
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
20
- spec.require_paths = ["lib"]
18
+ spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
19
+ spec.test_files = spec.files.grep(/^(test|spec|features)\//)
20
+ spec.require_paths = ['lib']
21
21
 
22
- spec.add_development_dependency "bundler", "~> 1.6"
23
- spec.add_development_dependency "rake"
24
- spec.add_development_dependency "rspec"
22
+ spec.add_development_dependency 'bundler', '~> 1.6'
23
+ spec.add_development_dependency 'rake'
24
+ spec.add_development_dependency 'rspec'
25
25
  end
@@ -6,18 +6,20 @@ require 'dydx/integrand'
6
6
 
7
7
  module Dydx
8
8
  include Algebra
9
- %w(f g h).each do |functioner|
9
+ %w(f g h temp_cal_f).each do |functioner|
10
10
  define_method(functioner) do |*vars|
11
11
  function = eval("$#{functioner}")
12
12
  return eval("$#{functioner} = Function.new(*vars)") unless function
13
13
 
14
- raise ArgumentError, "invalid number of values (#{vars.count} for #{function.vars.count})" unless function.vars.count == vars.count
15
- return function if function.vars == vars
16
- return function unless function.algebra
14
+ fail ArgumentError, "invalid number of values (#{vars.count} for #{function.vars.count})" unless function.vars.count == vars.count
15
+ return function if function.vars == vars || !function.algebra
17
16
 
18
- string = substitute(vars, function)
19
- string = rename_for_calc(string) if all_vars_num?(vars)
20
- eval(string)
17
+ subst_hash = Hash[*[function.vars, vars].transpose.flatten]
18
+ begin
19
+ function.algebra.subst(subst_hash).to_f
20
+ rescue ArgumentError
21
+ eval(function.algebra.subst(subst_hash).to_s)
22
+ end
21
23
  end
22
24
  end
23
25
 
@@ -33,6 +35,17 @@ module Dydx
33
35
  $f, $g, $h = nil, nil, nil
34
36
  end
35
37
 
38
+ def _(*args)
39
+ case args.count
40
+ when 1
41
+ num = args.first
42
+ Num.new(num)
43
+ when 3
44
+ ltr, op, rtr = args
45
+ ltr.send(op, rtr)
46
+ end
47
+ end
48
+
36
49
  def method_missing(method, *args, &block)
37
50
  method_name = method.to_s
38
51
  if method_name =~ /^d.$/
@@ -43,26 +56,4 @@ module Dydx
43
56
  super
44
57
  end
45
58
  end
46
-
47
- private
48
-
49
- def substitute(vars, function)
50
- string = function.algebra.to_s
51
- function.vars.each_with_index { |var, i| string.gsub!(var.to_s, vars[i].to_s) }
52
- string
53
- end
54
-
55
- def all_vars_num?(vars)
56
- vars.all? { |v| v.is_a?(Numeric) }
57
- end
58
-
59
- def rename_for_calc(string)
60
- # TODO: need more refactoring...
61
- string.gsub!('cos', 'Math.cos')
62
- string.gsub!('sin', 'Math.sin')
63
- string.gsub!('log', 'Math.log')
64
- string.gsub!(' e ', ' Math::E ')
65
- string.gsub!('pi', 'Math::PI')
66
- string
67
- end
68
59
  end
@@ -1,89 +1,21 @@
1
- require 'dydx/algebra/formula'
2
- require 'dydx/algebra/inverse'
3
-
4
1
  require 'dydx/algebra/set'
5
2
 
6
- require 'dydx/algebra/operator/inverse'
7
- require 'dydx/algebra/operator/formula'
8
- require 'dydx/algebra/operator/symbol'
9
- require 'dydx/algebra/operator/num'
10
- require 'dydx/algebra/operator/general'
11
-
12
3
  module Dydx
13
4
  module Algebra
14
5
  include Set
15
- module Set
16
- # TODO: Refactor
17
- Symbol.class_eval{ include Operator::Symbol }
18
- Fixnum.class_eval do
19
- alias_method :addition, :+
20
- alias_method :subtraction, :-
21
- alias_method :multiplication, :*
22
- alias_method :division, :/
23
- alias_method :exponentiation, :**
24
- ope_to_str = {
25
- addition: :+,
26
- subtraction: :-,
27
- multiplication: :*,
28
- division: :/,
29
- exponentiation: :^
30
- }
31
- %w(+ - * / ^).each do |operator|
32
- define_method(operator) do |g|
33
- if g.is_a?(Symbol) ||
34
- g.is_a?(Formula) ||
35
- g.is_a?(Base)
36
-
37
- Num.new(self).send(operator.to_sym, g)
38
- else
39
- send(ope_to_str.key(operator.to_sym), g)
40
- end
41
- end
42
- end
43
- end
44
6
 
45
- Float.class_eval do
46
- alias_method :addition, :+
47
- alias_method :subtraction, :-
48
- alias_method :multiplication, :*
49
- alias_method :division, :/
50
- alias_method :exponentiation, :**
51
- ope_to_str = {
52
- addition: :+,
53
- subtraction: :-,
54
- multiplication: :*,
55
- division: :/,
56
- exponentiation: :^
57
- }
58
- %w(+ - * / ^).each do |operator|
59
- define_method(operator) do |g|
60
- if g.is_a?(Symbol) ||
61
- g.is_a?(Formula) ||
62
- g.is_a?(Base)
63
-
64
- Num.new(self).send(operator.to_sym, g)
65
- else
66
- send(ope_to_str.key(operator.to_sym), g)
67
- end
68
- end
69
- end
70
- end
71
- class Num; include Operator::Num; end
72
- class E; include Operator::General; end
73
- class Pi; include Operator::General; end
74
- class Log; include Operator::General; end
75
- class Sin; include Operator::General; end
76
- class Cos; include Operator::General; end
77
- class Tan; include Operator::General; end
78
- end
79
7
  class Formula; include Operator::Formula; end
80
8
  class Inverse; include Operator::Inverse; end
81
9
 
10
+ # TODO: Cyclomatic complexity for inverse is too high. [7/6]
82
11
  def inverse(x, operator)
83
- if operator == :+ && x.is_0?
84
- e0
85
- elsif operator == :* && x.is_1?
86
- e1
12
+ if x.num?
13
+ x = x.to_numeric
14
+ if operator == :+
15
+ _(- x)
16
+ else
17
+ _(Rational(1, x))
18
+ end
87
19
  elsif x.is_a?(Inverse) && x.operator == operator
88
20
  x.x
89
21
  else
@@ -2,23 +2,44 @@ module Dydx
2
2
  module Algebra
3
3
  class Formula
4
4
  include Helper
5
- attr_accessor :f, :operator, :g
5
+ attr_accessor :operator, :terms
6
6
 
7
- def initialize(f, g, operator)
8
- g, f = f, g if g.is_num? && operator.commutative?
9
- @f, @g, @operator = f, g, operator
7
+ def initialize(operator, *terms)
8
+ @operator, @terms = operator, terms
9
+ commutate! if (terms[1].num? && operator.commutative?)
10
10
  end
11
11
 
12
- def differentiate(sym=:x)
12
+ def f
13
+ @terms[0]
14
+ end
15
+
16
+ def g
17
+ @terms[1]
18
+ end
19
+
20
+ def f=(x)
21
+ @terms[0] = x
22
+ end
23
+
24
+ def g=(x)
25
+ @terms[1] = x
26
+ end
27
+
28
+ def trs
29
+ terms
30
+ end
31
+
32
+ # TODO: Cylomatic complexity for differentiate is too high. [7/6]
33
+ def differentiate(sym = :x)
13
34
  case @operator
14
35
  when :+ then f.d(sym) + g.d(sym)
15
36
  when :* then (f.d(sym) * g) + (f * g.d(sym))
16
- when :^
37
+ when :**
17
38
  # TODO:
18
- if g.is_num?
19
- f.d(sym) * g * (f ^ (g - 1) )
39
+ if g.num?
40
+ f.d(sym) * g * (f ** (g - 1))
20
41
  elsif f == sym
21
- g * (f ^ (g - 1))
42
+ g * (f ** (g - 1))
22
43
  elsif f == e
23
44
  g.d(sym) * self
24
45
  else
@@ -29,17 +50,29 @@ module Dydx
29
50
  alias_method :d, :differentiate
30
51
 
31
52
  def to_s
32
- if (formula?(:*) && (f.is_minus1? || g.is_minus1?) )
33
- "( - #{g.to_s} )"
53
+ if formula?(:*) && (f.minus1? || g.minus1?)
54
+ "( - #{g} )"
34
55
  elsif g.inverse?(operator)
35
- "( #{f.to_s} #{inverse_ope(operator)} #{g.x.to_s} )"
56
+ "( #{f} #{operator.inv} #{g.x} )"
36
57
  elsif f.inverse?(operator)
37
- "( #{g.to_s} #{inverse_ope(operator)} #{f.x.to_s} )"
58
+ "( #{g} #{operator.inv} #{f.x} )"
59
+ elsif formula?(:*) && !rationals.empty?
60
+ terms = [f, g]
61
+ terms.delete(rationals.first)
62
+ "( #{(terms.first * rationals.first.n.numerator)} / #{rationals.first.n.denominator} )"
38
63
  else
39
- "( #{f.to_s} #{operator} #{g.to_s} )"
64
+ "( #{f} #{operator} #{g} )"
40
65
  end
41
66
  end
42
67
 
68
+ def subst(hash = {})
69
+ f.subst(hash).send(operator, g.subst(hash))
70
+ end
71
+
72
+ def to_f
73
+ f.to_f.send(operator, g.to_f)
74
+ end
75
+
43
76
  def include?(x)
44
77
  f == x || g == x
45
78
  end
@@ -49,28 +82,33 @@ module Dydx
49
82
  (f.combinable?(x, operator) || g.combinable?(x, operator))
50
83
  end
51
84
 
52
- # TODO: interchangeable
85
+ def rationals
86
+ [f, g].select{ |term| term.num? && term.n.is_a?(Rational) }
87
+ end
88
+
53
89
  def ==(x)
54
- to_s == x.to_s
55
- end
56
-
57
- def common_factors(formula)
58
- nil unless formula.is_a?(Formula)
59
- if f == formula.f
60
- [:f, :f]
61
- elsif g == formula.g
62
- [:g, :g]
63
- elsif f == formula.g
64
- [:f, :g]
65
- elsif g == formula.f
66
- [:g, :f]
90
+ if to_s == x.to_s
91
+ true
92
+ else
93
+ result = commutate!.to_s == x.to_s
94
+ commutate!
95
+ result
67
96
  end
68
97
  end
69
98
 
70
99
  def commutate!
71
- @f, @g = @g, @f
100
+ @terms.reverse!
72
101
  self
73
102
  end
103
+
104
+ def index(tr)
105
+ trs.index(tr)
106
+ end
107
+
108
+ def delete(tr)
109
+ trs.delete(tr)
110
+ trs.count.one? ? trs.first : self
111
+ end
74
112
  end
75
113
  end
76
114
  end