dydx 0.1.4 → 0.1.25

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 +4 -4
  2. data/Gemfile +0 -3
  3. data/README.md +124 -61
  4. data/Rakefile +8 -5
  5. data/dydx.gemspec +13 -13
  6. data/lib/dydx.rb +25 -23
  7. data/lib/dydx/algebra.rb +76 -8
  8. data/lib/dydx/algebra/formula.rb +38 -71
  9. data/lib/dydx/algebra/inverse.rb +12 -19
  10. data/lib/dydx/algebra/operator/common_parts.rb +3 -0
  11. data/lib/dydx/algebra/operator/formula.rb +4 -0
  12. data/lib/dydx/algebra/operator/general.rb +4 -0
  13. data/lib/dydx/algebra/operator/inverse.rb +4 -0
  14. data/lib/dydx/algebra/operator/num.rb +4 -0
  15. data/lib/dydx/algebra/operator/parts/base.rb +2 -2
  16. data/lib/dydx/algebra/operator/parts/formula.rb +38 -63
  17. data/lib/dydx/algebra/operator/parts/general.rb +31 -84
  18. data/lib/dydx/algebra/operator/parts/interface.rb +22 -0
  19. data/lib/dydx/algebra/operator/parts/inverse.rb +4 -4
  20. data/lib/dydx/algebra/operator/parts/num.rb +11 -16
  21. data/lib/dydx/algebra/operator/parts/symbol.rb +2 -2
  22. data/lib/dydx/algebra/operator/symbol.rb +15 -0
  23. data/lib/dydx/algebra/set.rb +34 -271
  24. data/lib/dydx/algebra/set/base.rb +9 -0
  25. data/lib/dydx/algebra/set/cos.rb +22 -0
  26. data/lib/dydx/algebra/set/e.rb +16 -0
  27. data/lib/dydx/algebra/set/fixnum.rb +14 -0
  28. data/lib/dydx/algebra/set/float.rb +14 -0
  29. data/lib/dydx/algebra/set/log.rb +22 -0
  30. data/lib/dydx/algebra/set/num.rb +26 -0
  31. data/lib/dydx/algebra/set/pi.rb +16 -0
  32. data/lib/dydx/algebra/set/sin.rb +21 -0
  33. data/lib/dydx/algebra/set/symbol.rb +14 -0
  34. data/lib/dydx/algebra/set/tan.rb +17 -0
  35. data/lib/dydx/delta.rb +1 -1
  36. data/lib/dydx/function.rb +1 -1
  37. data/lib/dydx/helper.rb +61 -55
  38. data/lib/dydx/integrand.rb +10 -22
  39. data/lib/dydx/version.rb +1 -1
  40. data/spec/dydx_spec.rb +29 -10
  41. data/spec/lib/algebra/formula_spec.rb +38 -44
  42. data/spec/lib/algebra/operator/parts/base_spec.rb +5 -5
  43. data/spec/lib/algebra/operator/parts/formula_spec.rb +50 -57
  44. data/spec/lib/algebra/operator/parts/inverse_spec.rb +8 -8
  45. data/spec/lib/algebra/set/cos_spec.rb +18 -0
  46. data/spec/lib/algebra/set/e_spec.rb +27 -0
  47. data/spec/lib/algebra/set/fixnum_spec.rb +65 -0
  48. data/spec/lib/algebra/set/float_spec.rb +65 -0
  49. data/spec/lib/algebra/set/log_spec.rb +15 -0
  50. data/spec/lib/algebra/set/num_spec.rb +23 -0
  51. data/spec/lib/algebra/set/pi_spec.rb +25 -0
  52. data/spec/lib/algebra/set/sin_spec.rb +14 -0
  53. data/spec/lib/algebra/set/symbol_spec.rb +22 -0
  54. data/spec/lib/algebra/set/tan_spec.rb +13 -0
  55. data/spec/lib/delta_spec.rb +8 -32
  56. data/spec/lib/function_spec.rb +34 -60
  57. data/spec/lib/helper_spec.rb +49 -47
  58. data/spec/lib/integrand_spec.rb +15 -13
  59. data/spec/spec_helper.rb +1 -2
  60. metadata +39 -9
  61. data/.pryrc +0 -2
  62. data/.rubocop.yml +0 -25
  63. data/spec/lib/algebra/set_spec.rb +0 -263
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 79327c9edd590f2a006eb29d8b148919d913c9a4
4
- data.tar.gz: d5b7e817ffe55271c3a473d3b1679b3abaa929ee
3
+ metadata.gz: 50e18dda6ca41f30bb45fdbc2f73c906c6e01c94
4
+ data.tar.gz: 14094dd2083a888d715e93eb0a1faa8aa6f9cf13
5
5
  SHA512:
6
- metadata.gz: 5716ffe76bc6e49af3ef2560920cebc20845b01ec1be35ca6b46a4a454530b1582a9820add4c6a2b0a29bfc84e26751133faea9c5c277c19fd1f5f9b8c8c842b
7
- data.tar.gz: f5dd91eb57c7ac6d6a3dd8a8318b98953295d4de7fb67c530fad3c040b351e225c1a79da03fe4bbb51110545a572fb8ba194de715a34f8ce96a1d6b627c7e4bd
6
+ metadata.gz: abbe8199d94ede3e5568aaf41c5d4dba0996af0b2da53e8313372d96d67c401c64e802f30777995f92fc966cb4e81740ffae5228ce352f711856793615435d3c
7
+ data.tar.gz: 12087ca360a5da0e9fa6c32ed5818d8b40c3044a1f9efa2da4bbf75772fad9794a5b7660eb6239009c051ebe30ac7f8ef293611caf16b3610c265709a6f5e7c8
data/Gemfile CHANGED
@@ -1,8 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in dydx.gemspec
4
- gem 'rubocop'
5
4
  gem 'pry'
6
- gem 'pry-coolline'
7
- # gem 'pry-debugger'
8
5
  gemspec
data/README.md CHANGED
@@ -1,94 +1,157 @@
1
- # Dydx is new MATH Language on Ruby.
1
+ # Dydx
2
+ It always happens you want to differentiate some formulas with ruby. right?.....
2
3
 
3
- ### Since you report a bug, I will fix it within 24 hours.
4
-
5
- The most important thing in this DSL is
4
+ After `inlcude Dydx` , ruby become like other language.
6
5
 
7
- we can handle math in the same sense sense of the math on paper.
6
+ ## Dydx is new math DSL in Ruby
8
7
 
9
- ex. limit, trigonometric functions and logarithmic.
8
+ I'm going to add for more explanation.
10
9
 
11
- ## We should enjoy MATH even using PC.
12
- (to say nothing of using pen.)
13
10
 
14
- After `inlcude Dydx` , ruby become like other language.
15
11
 
16
- ## Outline
17
12
  ```ruby:
18
13
  require 'dydx'
19
14
  include Dydx
20
15
 
21
- # Define the function. syntax is not good enough...
22
- f(x, y) <= x + x*y + y
16
+ f(x) <= x ^ 2
17
+
18
+ f(3)
19
+ # => 9
20
+
21
+ f(x).to_s
22
+ # => "( x ^ 2 )"
23
+
24
+ f(x) == eval('f(x).to_s')
25
+ # => true
23
26
 
24
- # simplify
25
- f(x, y) == x * (1 + y) + y
26
- => true
27
+ g(x) <= d/dx(f(x))
27
28
 
28
- #part substitution
29
- f(a, 2) == 3*a + 2
30
- => true
29
+ g(3)
30
+ # => 6
31
31
 
32
- f(1, a + b) == 1 + 2 * ( a + b )
33
- => true
32
+ # => '2 * x'
34
33
 
34
+ S(f(x), dx)[0, 1]
35
+ # => 0.3333333333333334
36
+
37
+ ( d/dx(log(x)) ).to_s
38
+ # => "( 1 / x )"
39
+
40
+ ( d/dx(cos(x)) ).to_s
41
+ # => "( - sin( x ) )"
42
+
43
+ ( d/dx(e ^ x) ).to_s
44
+ # => "( e ^ x )"
45
+
46
+ f(x) <= sin(x)
47
+ S(f(x), dx)[0, Math::PI/2]
48
+ # => 1.000000000021139
49
+
50
+ f(x) <= (1.0 / ( ( 2.0 * pi ) ^ 0.5 ) ) * ( e ^ (- (x ^ 2) / 2) )
51
+ S(f(x), dx)[-oo, oo]
52
+ # => 0.9952054164466917
35
53
 
36
- # Differentiate
37
- d/dx(f(x, y)) == 1 + y
38
- => true
54
+ f(x) <= x ^ 2
39
55
 
40
- g(x) <= sin(x)
56
+ f(a + b).to_s
57
+ # => "( ( a + b ) ^ 2 )"
41
58
 
42
- d/dx(g(x)) == cos(x)
59
+ g(a, b) <= f(a + b)
43
60
 
44
- # Integrate
45
- S(g(x), dx)[0, pi/2]
46
- => 1.0
61
+ g(a, b).to_s
62
+ # => "( ( a + b ) ^ 2 )"
63
+
64
+ g(2, 2)
65
+ # => 16
66
+
67
+ ( d/da(g(a, b)) ).to_s
68
+ => "( 2 * ( a + b ) )"
47
69
  ```
48
70
 
49
71
 
50
- #### limit, trigonometric functions and logarithmic.
51
- ```ruby:
52
72
 
53
- f(z) <= log(z)
54
- S(f(z), dz)[0,1]
55
- => -Infinity
56
73
 
57
- d/dx(log(x)) == 1 / x
58
- => true
59
74
 
60
- d/dx(cos(x)) == -cos(x)
61
- => true
75
+ ```
76
+ require 'dydx'
77
+ include Dydx
62
78
 
63
- d/dx(e ** x) == e ** x
64
- => true
79
+ # There are three types of differential interface
80
+
81
+ ( d/dx(x^2) ).to_s
82
+ => "( 2 * x )"
83
+
84
+ log(z).d(z).to_s
85
+ => "( 1 / z )"
86
+
87
+ $y = e ^ x
88
+ (dy/dx).to_s
89
+ => "( e ^ x )"
65
90
 
66
- # standard normal distribution;
67
- f(x) <= (1.0 / ( 2.0 * pi ) ** 0.5) * e ** (- x ** 2 / 2)
68
- S(f(x), dx)[-oo, oo]
69
- => 1.0
70
91
  ```
71
92
 
72
- ## Documents
73
- I'm going to write now...cominng soon....
93
+ You may wonder why undefined `x` , `e` and `z` are handleable?
94
+
95
+ `method_missing` solve this problem by converting undefine variable into internal class object.
74
96
 
75
- ### Module, class configuration
97
+ Like this.
76
98
 
77
99
  ```
78
- Dydx
79
- |- Algebra
80
- | |- Operator
81
- | | |- Interface
82
- | | |- ....
83
- | |
84
- | |- Set
85
- | |- Formula
86
- | |- inverse
87
- |
88
- |- Function
89
- |- Delta
90
- |- Integrand
100
+ x + x
101
+ => #<Dydx::Algebra::Formula:0x007fb0a4039fb0 @f=#<Dydx::Algebra::Set::Num:0x007fb0a48169e0 @n=2>, @operator=:*, @g=:x>
102
+
103
+ e
104
+ => #<Dydx::Algebra::Set::E:0x007fb0a383e9f0>
105
+
106
+ log(sin(x))
107
+ => #<Dydx::Algebra::Set::Log:0x007fe7cd971528 @f=#<Dydx::Algebra::Set::Sin:0x007fe7cd971550 @x=:x>>
108
+ ```
109
+
110
+ And this DSL has strong simplify.
111
+
112
+ ```
113
+ ((x * y) + (z * x)).to_s
114
+ => "( x * ( y + z ) )"
115
+
116
+ ((x ^ y) / (x ^ z)).to_s
117
+ => "( x ^ ( y - z ) )"
118
+
119
+ (x + x).to_s
120
+ => "( 2 * x )"
121
+ ```
122
+
123
+ I show some differential calculus.
124
+
91
125
  ```
126
+ # pretermit '#to_s'
127
+
128
+ d/dz(log(z))
129
+ => "( 1 / z )"
130
+
131
+ d/dx(x^n)
132
+ => "( n * ( x ^ ( n - 1 ) ) )"
133
+
134
+ $y = cos(x)
135
+ dy/dx
136
+ => "( - sin( x ) )"
137
+
138
+ $x = a * ( (t ^ 2) / 2 )
139
+ dx/dt
140
+ => "( a * t )"
141
+
142
+ d/dt(dx/dt)
143
+ =>"a"
144
+
145
+ ((x ^ 2) * y).d(x)
146
+ => "( ( 2 * x ) * y )"
147
+
148
+ ((x ^ 2) * y).d(x).d(y)
149
+ => "( 2 * x )"
150
+
151
+ ```
152
+
153
+
154
+ (That's wonderful!!!!! ..............)
92
155
 
93
156
  ## Installation
94
157
 
@@ -121,6 +184,6 @@ Or install it yourself as:
121
184
  run `bundle exec rake spec`
122
185
 
123
186
  ```
124
- Finished in 3.76 seconds
125
- 325 examples, 0 failures
187
+ Finished in 3.23 seconds
188
+ 309 examples, 0 failures
126
189
  ```
data/Rakefile CHANGED
@@ -1,10 +1,13 @@
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)
7
+ #do `rake spec`
8
+ RSpec::Core::RakeTask.new(:spec) do |t|
9
+ t.rspec_opts = ["-c", "-fs"]
10
+ end
9
11
 
10
12
  task default: :spec
13
+
data/dydx.gemspec CHANGED
@@ -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 derivative.}
13
+ spec.description = %q{It is possible to use the differential using the Symbol and Fixnum by including the Dydx. And, we can use the natural logarithm and log.}
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(/^bin\//) { |f| File.basename(f) }
19
- spec.test_files = spec.files.grep(/^(test|spec|features)\//)
20
- spec.require_paths = ['lib']
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"]
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
data/lib/dydx.rb CHANGED
@@ -6,19 +6,32 @@ require 'dydx/integrand'
6
6
 
7
7
  module Dydx
8
8
  include Algebra
9
- %w(f g h temp_cal_f).each do |functioner|
9
+ # TODO: Refactor
10
+ %w(f g h).each do |functioner|
10
11
  define_method(functioner) do |*vars|
11
- function = eval("$#{functioner}")
12
- return eval("$#{functioner} = Function.new(*vars)") unless function
13
-
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
16
-
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)
12
+ if function = eval("$#{functioner}")
13
+ raise ArgumentError, "invalid number of values (#{vars.count} for #{function.vars.count})" unless function.vars.count == vars.count
14
+ return function if function.vars == vars
15
+ if function.algebra
16
+ if vars.all?{|v| v.is_a?(Numeric)}
17
+ string = function.algebra.to_s
18
+ .gsub('cos', 'Math.cos')
19
+ .gsub('sin', 'Math.sin')
20
+ .gsub('log', 'Math.log')
21
+ .gsub('e', 'Math::E')
22
+ .gsub('pi', 'Math::PI')
23
+ else
24
+ string = function.algebra.to_s
25
+ end
26
+ function.vars.each_with_index do |var, i|
27
+ string.gsub!(var.to_s, vars[i].to_s)
28
+ end
29
+ eval(string)
30
+ else
31
+ function
32
+ end
33
+ else
34
+ eval("$#{functioner} = Function.new(*vars)")
22
35
  end
23
36
  end
24
37
  end
@@ -35,17 +48,6 @@ module Dydx
35
48
  $f, $g, $h = nil, nil, nil
36
49
  end
37
50
 
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
-
49
51
  def method_missing(method, *args, &block)
50
52
  method_name = method.to_s
51
53
  if method_name =~ /^d.$/
data/lib/dydx/algebra.rb CHANGED
@@ -1,21 +1,89 @@
1
+ require 'dydx/algebra/formula'
2
+ require 'dydx/algebra/inverse'
3
+
1
4
  require 'dydx/algebra/set'
2
5
 
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
+
3
12
  module Dydx
4
13
  module Algebra
5
14
  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
6
44
 
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
7
79
  class Formula; include Operator::Formula; end
8
80
  class Inverse; include Operator::Inverse; end
9
81
 
10
- # TODO: Cyclomatic complexity for inverse is too high. [7/6]
11
82
  def inverse(x, operator)
12
- if x.num?
13
- x = x.to_numeric
14
- if operator == :+
15
- _(- x)
16
- else
17
- _(Rational(1, x))
18
- end
83
+ if operator == :+ && x.is_0?
84
+ e0
85
+ elsif operator == :* && x.is_1?
86
+ e1
19
87
  elsif x.is_a?(Inverse) && x.operator == operator
20
88
  x.x
21
89
  else