dydx 0.0.9 → 0.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d8ca3c4000aeec1a5bf45fd3c7ed3fbd406d6617
4
- data.tar.gz: 5de895a80ebd9d7684f0ef0544709979709293fc
3
+ metadata.gz: 6de4b80471ef9ac33664da33ff3f4a17a4c02714
4
+ data.tar.gz: e367d55b3bd7f8a59c1f7a0168f5a37e4d4c4881
5
5
  SHA512:
6
- metadata.gz: dc98862c3a69ffc14d6ace6ebe15dcf41d1ce7559e5ab52713c9f48394ebb1fb7b18fbb0ccbcaf06dab58eadd1c8bf31acb2fa15ccca07f3563375cd7936df1e
7
- data.tar.gz: ff75009f67db271fe0b7e25ed08d8e15bd724b1544b86b668e79c5e5b2a4b623de758a94d390e95da0e7deac2e7a5328f2477306e2521b5fd322362483e80da9
6
+ metadata.gz: ff580a632c292dc3bed05f880fc641d2308d96237e5c268d6d8a2f2353c0c7c520dc5422e810a39d572bd8ef33374d75f34a1f4615a32d393754a5cd0e108995
7
+ data.tar.gz: 8fcfb84b585244622fa596cdb08c2e0419af96d8e5bc384be9a3793e24ace35ad13474edc57301bbb53f7fd5664e0fe8226fd17f59cf20e5368bb1f443c14b3d
data/README.md CHANGED
@@ -1,50 +1,84 @@
1
1
  # Dydx
2
- It always happens you want to differentiate with ruby. right?
3
-
4
- Dydx will eliminate this. Like this
2
+ It always happens you want to differentiate some formulas with ruby. right?.....
5
3
 
4
+ After `inlcude Dydx` , ruby become like other language.
6
5
 
7
6
  ```
8
- ( d/dx(:x ^ 2) ).to_s
7
+ require 'dydx'
8
+ include Dydx
9
+
10
+ # There are three types of differential interface
11
+
12
+ ( d/dx(x^2) ).to_s
9
13
  => "( 2 * x )"
10
14
 
11
- # pretermit '#to_s'
15
+ log(z).d(z).to_s
16
+ => "( 1 / z )"
12
17
 
13
- d/dx(e ^ :x)
18
+ $y = e ^ x
19
+ (dy/dx).to_s
14
20
  => "( e ^ x )"
15
21
 
16
- d/dz(log(:z))
17
- => "( 1 / z )"
22
+ ```
18
23
 
19
- d/dx(:x^:n)
20
- => "( n * ( x ^ ( n - 1 ) ) )"
24
+ You may wonder why undefined `x` , `e` and `z` are handleable?
25
+
26
+ `method_missing` solve this problem by converting undefine variable into internal class object.
27
+
28
+ Like this.
29
+
30
+ ```
31
+ x + x
32
+ => #<Dydx::Algebra::Formula:0x007fb0a4039fb0 @f=#<Dydx::Algebra::Set::Num:0x007fb0a48169e0 @n=2>, @operator=:*, @g=:x>
33
+
34
+ e
35
+ => #<Dydx::Algebra::Set::E:0x007fb0a383e9f0>
36
+
37
+ log(sin(x))
38
+ => #<Dydx::Algebra::Set::Log:0x007fe7cd971528 @f=#<Dydx::Algebra::Set::Sin:0x007fe7cd971550 @x=:x>>
39
+ ```
40
+
41
+ And this DSL has strong simplify.
42
+
43
+ ```
44
+ ((x * y) + (z * x)).to_s
45
+ => "( x * ( y + z ) )"
21
46
 
47
+ ((x ^ y) / (x ^ z)).to_s
48
+ => "( x ^ ( y - z ) )"
49
+
50
+ (x + x).to_s
51
+ => "( 2 * x )"
22
52
  ```
23
53
 
24
- you can do like ``` dy/dx ```, if you use global var.
54
+ I show some differential calculus.
25
55
 
26
56
  ```
27
- $y = cos(:x)
57
+ # pretermit '#to_s'
58
+
59
+ d/dz(log(z))
60
+ => "( 1 / z )"
61
+
62
+ d/dx(x^n)
63
+ => "( n * ( x ^ ( n - 1 ) ) )"
64
+
65
+ $y = cos(x)
28
66
  dy/dx
29
67
  => "( - sin( x ) )"
30
68
 
31
- $x = :a * ( (:t ^ 2) / 2 )
69
+ $x = a * ( (t ^ 2) / 2 )
32
70
  dx/dt
33
71
  => "( a * t )"
34
72
 
35
73
  d/dt(dx/dt)
36
74
  =>"a"
37
75
 
38
- ```
39
-
40
- you can use method chaining.
41
-
42
- ```
43
- ((:x ^ 2) * :y).d(:x)
76
+ ((x ^ 2) * y).d(x)
44
77
  => "( ( 2 * x ) * y )"
45
78
 
46
- ((:x ^ 2) * :y).d(:x).d(:y)
79
+ ((x ^ 2) * y).d(x).d(y)
47
80
  => "( 2 * x )"
81
+
48
82
  ```
49
83
 
50
84
 
@@ -70,8 +104,17 @@ Or install it yourself as:
70
104
 
71
105
  ## Contributing
72
106
 
73
- 1. Fork it ( https://github.com/[my-github-username]/dydx/fork )
107
+ 1. Fork it ( https://github.com/gogotanaka/dydx/fork )
74
108
  2. Create your feature branch (`git checkout -b my-new-feature`)
75
109
  3. Commit your changes (`git commit -am 'Add some feature'`)
76
110
  4. Push to the branch (`git push origin my-new-feature`)
77
111
  5. Create a new Pull Request
112
+
113
+ ## Test
114
+
115
+ run `bundle exec rake spec`
116
+
117
+ ```
118
+ Finished in 0.11282 seconds
119
+ 231 examples, 0 failures
120
+ ```
data/lib/dydx.rb CHANGED
@@ -1,28 +1,49 @@
1
1
  require 'dydx/helper'
2
2
  require 'dydx/algebra'
3
+ require 'dydx/delta'
4
+ require 'dydx/function'
5
+ require 'dydx/integrand'
3
6
 
4
7
  module Dydx
5
8
  include Algebra
6
- class Delta
7
- attr_accessor :var, :function
8
- def initialize(var, function)
9
- @var = var
10
- @function = function
11
- end
12
-
13
- def /(delta)
14
- if var
15
- eval("$#{var}").differentiate(delta.var)
16
- elsif delta.function
17
- delta.function.differentiate(delta.var)
9
+ # TODO: Refactor
10
+ %w(f g h).each do |functioner|
11
+ define_method(functioner) do |*vars|
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
+ string = function.algebra.to_s
17
+ .gsub('cos', 'Math.cos')
18
+ .gsub('sin', 'Math.sin')
19
+ .gsub('log', 'Math.log')
20
+ .gsub('e', 'Math::E')
21
+ .gsub('pi', 'Math::Pi')
22
+ function.vars.each_with_index do |var, i|
23
+ string.gsub!(var.to_s, vars[i].to_s)
24
+ end
25
+ eval(string)
26
+ else
27
+ function
28
+ end
29
+ else
30
+ eval("$#{functioner} = Function.new(*vars)")
18
31
  end
19
32
  end
20
33
  end
21
34
 
35
+ def S(function, delta)
36
+ Integrand.new(function, delta.var)
37
+ end
38
+
39
+ def d
40
+ Delta.new
41
+ end
42
+
22
43
  def method_missing(method, *args, &block)
23
44
  method_name = method.to_s
24
- if method_name =~ /^d.?$/
25
- Delta.new(method_name[1] ? method_name[1].to_sym : nil, args.first)
45
+ if method_name =~ /^d.$/
46
+ Delta.new(method_name[1].to_sym, args.first)
26
47
  elsif method_name =~ /^[a-z]$/
27
48
  method_name.to_sym
28
49
  else
data/lib/dydx/algebra.rb CHANGED
@@ -13,6 +13,7 @@ module Dydx
13
13
  module Algebra
14
14
  include Set
15
15
  module Set
16
+ # TODO: Refactor
16
17
  Symbol.class_eval{ include Operator::Symbol }
17
18
  Fixnum.class_eval do
18
19
  %w(+ - * / ^).each do |operator|
@@ -22,16 +23,29 @@ module Dydx
22
23
  g.is_a?(Base)
23
24
 
24
25
  Num.new(self).send(operator.to_sym, g)
25
- elsif operator == '^' && g.is_a?(Fixnum)
26
- result = 1
27
- g.times{ result *= self }
28
- result
26
+ elsif operator == '^' && g.is_a?(Fixnum) || g.is_a?(Float)
27
+ self ** g
28
+ elsif operator == '^' && g.is_a?(Num)
29
+ self ** g.n
29
30
  else
30
31
  (to_f.send(operator.to_sym, g)).to_i
31
32
  end
32
33
  end
33
34
  end
34
35
  end
36
+ Float.class_eval do
37
+ %w(^).each do |operator|
38
+ define_method(operator) do |g|
39
+ if g.is_a?(Fixnum) || g.is_a?(Float)
40
+ self ** g
41
+ elsif g.is_a?(Num)
42
+ self ** g.n
43
+ else
44
+ Num.new(self).send(operator.to_sym, g)
45
+ end
46
+ end
47
+ end
48
+ end
35
49
  class Num; include Operator::Num; end
36
50
  class E; include Operator::General; end
37
51
  class Pi; include Operator::General; end
@@ -54,5 +68,9 @@ module Dydx
54
68
  Inverse.new(x, operator)
55
69
  end
56
70
  end
71
+
72
+ def -@
73
+ inverse(self, :+)
74
+ end
57
75
  end
58
76
  end
@@ -2,7 +2,7 @@ module Dydx
2
2
  module Algebra
3
3
  class Formula
4
4
  include Helper
5
- attr_accessor :f, :g, :operator
5
+ attr_accessor :f, :operator, :g
6
6
 
7
7
  def initialize(f, g, operator)
8
8
  @f, @g, @operator = f, g, operator
@@ -16,7 +16,9 @@ module Dydx
16
16
  (f.d(sym) * g) + (f * g.d(sym))
17
17
  when :^
18
18
  # TODO:
19
- if f == sym
19
+ if g.is_num?
20
+ f.d(sym) * g * (f ^ (g - 1) )
21
+ elsif f == sym
20
22
  g * (f ^ (g - 1))
21
23
  elsif f == e
22
24
  g.d(sym) * self
@@ -27,7 +27,7 @@ module Dydx
27
27
  e0
28
28
  elsif operator == :* && inverse?(:*, x)
29
29
  e1
30
- elsif [:+, :*].include?(operator) && x.send("#{to_str(operator)}?")
30
+ elsif [:+, :*].include?(operator) && x.formula?(operator)
31
31
  if combinable?(x.f, operator)
32
32
  send(operator, x.f).send(operator, x.g)
33
33
  elsif combinable?(x.g, operator)
@@ -35,7 +35,7 @@ module Dydx
35
35
  else
36
36
  super(x)
37
37
  end
38
- elsif x.is_a?(Inverse) && x.operator == operator && x.x.send("#{to_str(operator)}?")
38
+ elsif x.is_a?(Inverse) && x.operator == operator && x.x.formula?(operator)
39
39
  if combinable?(x.x.f, operator)
40
40
  send(operator, inverse(x.x.f, operator)).send(operator, inverse(x.x.g, operator))
41
41
  elsif combinable?(x.x.g, operator)
@@ -1,6 +1,7 @@
1
1
  require 'dydx/algebra/set/base'
2
2
  require 'dydx/algebra/set/num'
3
3
  require 'dydx/algebra/set/fixnum'
4
+ require 'dydx/algebra/set/float'
4
5
  require 'dydx/algebra/set/symbol'
5
6
  require 'dydx/algebra/set/e'
6
7
  require 'dydx/algebra/set/pi'
@@ -0,0 +1,14 @@
1
+ module Dydx
2
+ module Algebra
3
+ module Set
4
+ Float.class_eval do
5
+ include Helper
6
+
7
+ def differentiate(sym=:x)
8
+ e0
9
+ end
10
+ alias_method :d, :differentiate
11
+ end
12
+ end
13
+ end
14
+ end
data/lib/dydx/delta.rb ADDED
@@ -0,0 +1,17 @@
1
+ module Dydx
2
+ class Delta
3
+ attr_accessor :var, :function
4
+ def initialize(var=nil, function=nil)
5
+ @var = var
6
+ @function = function
7
+ end
8
+
9
+ def /(delta)
10
+ if var
11
+ eval("$#{var}").differentiate(delta.var)
12
+ elsif delta.function
13
+ delta.function.differentiate(delta.var)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ module Dydx
2
+ class Function
3
+ attr_accessor :algebra, :vars
4
+ def initialize(*vars)
5
+ @vars = vars
6
+ end
7
+
8
+ def <=(algebra)
9
+ @algebra = algebra
10
+ self
11
+ end
12
+
13
+ def differentiate(sym=:x)
14
+ @algebra.differentiate(sym)
15
+ end
16
+ alias_method :d, :differentiate
17
+
18
+ def to_s
19
+ algebra.to_s
20
+ end
21
+
22
+ def ==(function)
23
+ to_s == function.to_s
24
+ end
25
+ end
26
+ end
data/lib/dydx/helper.rb CHANGED
@@ -39,11 +39,11 @@ module Dydx
39
39
  end
40
40
 
41
41
  def is_num?
42
- (is_a?(Num) || is_a?(Fixnum)) || (is_a?(Inverse) && x.is_num?)
42
+ (is_a?(Num) || is_a?(Fixnum) || is_a?(Float)) || (is_a?(Inverse) && x.is_num?)
43
43
  end
44
44
 
45
45
  def is_0?
46
- self == 0 || (is_a?(Num) && n == 0)
46
+ [0, 0.0].include?(self) || (is_a?(Num) && n.is_0?)
47
47
  end
48
48
 
49
49
  def is_1?
@@ -96,21 +96,6 @@ module Dydx
96
96
  end
97
97
  end
98
98
 
99
- def to_str(sym)
100
- OP_SYM_STR.key(sym)
101
- end
102
-
103
- def str_to_sym(str)
104
- OP_SYM_STR[str]
105
- end
106
-
107
- def to_str_inv(operator)
108
- {
109
- subtrahend: :+,
110
- divisor: :*
111
- }.key(operator)
112
- end
113
-
114
99
  def rest(f_or_g)
115
100
  ([:f, :g] - [f_or_g]).first
116
101
  end
@@ -0,0 +1,22 @@
1
+ module Dydx
2
+ class Integrand
3
+ attr_accessor :function, :var
4
+ def initialize(function, var)
5
+ @function = function
6
+ @var = var
7
+ end
8
+
9
+ def [](a, b, n = 100)
10
+ f = function
11
+ a, b = [a, b].map(&:to_f)
12
+ raise ArgumentError, 'b should be greater than a' if a > b
13
+ h = (b - a) / n
14
+ sum = 0.0
15
+ xi = ->(i){ a + h * i }
16
+ n.to_i.times do |i|
17
+ sum += ( f(xi.(i)) + 4.0 * f(xi.(i) + h / 2.0 ) + f(xi.(i) + h) ) rescue binding.pry
18
+ end
19
+ ( h * sum ) / 6.0
20
+ end
21
+ end
22
+ end
data/lib/dydx/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Dydx
2
- VERSION = "0.0.9"
2
+ VERSION = "0.1.0"
3
3
  end
data/spec/dydx_spec.rb CHANGED
@@ -30,17 +30,9 @@ describe Dydx do
30
30
  end
31
31
 
32
32
  context 'ex4' do
33
- $f = 2 * (e ^ (2 * :z))
34
- let(:d1){ df/dz }
35
- let(:d2){ d/dz($f) }
36
- it{ expect(d1.to_s).to eq('( 4 * ( e ^ ( 2 * z ) ) )') }
37
- it{ expect(d2.to_s).to eq('( 4 * ( e ^ ( 2 * z ) ) )') }
38
- end
39
-
40
- context 'ex5' do
41
- $f = 2 * (e ^ (2 * z))
42
- let(:d1){ df/dz }
43
- let(:d2){ d/dz($f) }
33
+ $i = 2 * (e ^ (2 * :z))
34
+ let(:d1){ di/dz }
35
+ let(:d2){ d/dz($i) }
44
36
  it{ expect(d1.to_s).to eq('( 4 * ( e ^ ( 2 * z ) ) )') }
45
37
  it{ expect(d2.to_s).to eq('( 4 * ( e ^ ( 2 * z ) ) )') }
46
38
  end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dydx:Delta do
4
+ it{ expect(d.class).to eq(Delta) }
5
+ it{ expect(dx.class).to eq(Delta) }
6
+ it{ expect(dx.var).to eq(:x) }
7
+ it{ expect(dx(y).class).to eq(Delta) }
8
+ it{ expect(dx(y).var).to eq(:x) }
9
+ it{ expect(dx(y).function).to eq(:y) }
10
+ it{ expect{dxy}.to raise_error(NameError) }
11
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dydx:Function do
4
+ # TODO: refactor
5
+ it{ expect(f(x, y)).to eq(f(x, y)) }
6
+ it{ expect(f(x, y)).to eq($f) }
7
+ it{ expect(f(x, y).algebra).to be_nil }
8
+ it{ expect(f(x, y).vars).to eq([:x, :y]) }
9
+ it{ expect{f(x, y, z)}.to raise_error(ArgumentError) }
10
+ it{ expect{f(x)}.to raise_error(ArgumentError) }
11
+ it{ expect(f(x, y) <= x * y ).to eq(f(x, y)) }
12
+ it{ expect(f(x, y)).to eq(f(x, y)) }
13
+ it{ expect(f(x, y)).to eq($f) }
14
+ it{ expect(f(x, y).algebra).to eq(x * y) }
15
+ it{ expect(f(x, y)).to eq(x * y) }
16
+ it{ expect(eval(f(x, y).to_s)).to eq(f(x, y)) }
17
+ it{ expect(f(x, y)).to eq(eval(f(x, y).to_s)) }
18
+ it{ expect(f(a, b)).to eq(a * b) }
19
+ it{ expect(f(2, 3)).to eq(6) }
20
+ it{ expect(f(a + b, c)).to eq((a + b) * c) }
21
+ it{ expect(d/dx(f(x, y))).to eq(y) }
22
+ it{ expect(d/dy(f(x, y))).to eq(x) }
23
+ it{ expect(d/dz(f(x, y))).to eq(0) }
24
+
25
+ it{ expect(g(a, b) <= f(a + b, b)).to eq(g(a, b)) }
26
+ it{ expect(g(a, b)).to eq($g) }
27
+ it{ expect(g(2, 3)).to eq(15) }
28
+
29
+ it{ expect(h(a, b, c) <= d/db(g(a, b))).to eq(h(a, b, c)) }
30
+ it{ expect(h(a, b, c) <= d/db(g(a, b))).to eq($h) }
31
+ it{ expect(h(a, b, c)).to eq(( ( 2 * b ) + a )) }
32
+ it{ expect(h(a, b, c).algebra).to eq(( ( 2 * b ) + a )) }
33
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe Dydx:Integrand do
4
+ it 'ex1' do
5
+ f(x, y) <= x * y
6
+ integrand = S(f(x, y), dx)
7
+ expect(integrand.function).to eq(f(x, y))
8
+ expect(integrand.var).to eq(:x)
9
+ expect{integrand[4, 3]}.to raise_error(ArgumentError)
10
+ end
11
+
12
+ it 'ex2' do
13
+ $f = nil
14
+ f(x) <= x * x
15
+ expect(S(f(x), dx)[0, 1]).to eq(0.3333333333333334)
16
+ end
17
+
18
+ it 'ex3' do
19
+ $f = nil
20
+ f(x) <= sin(x)
21
+ expect(S(f(x), dx)[0, Math::PI/2]).to eq(1.000000000021139)
22
+ end
23
+
24
+ it 'ex4' do
25
+ $f = nil
26
+ f(x) <= cos(x)
27
+ expect(S(f(x), dx)[0, Math::PI]).to eq(7.440786129085082e-17)
28
+ end
29
+
30
+ it 'ex5' do
31
+ $f = nil
32
+ f(x) <= log(x)
33
+ expect(S(f(x), dx)[0, 1]).to eq(- Float::INFINITY)
34
+ end
35
+
36
+ # TODO
37
+ it 'ex6' do
38
+ $f = nil
39
+ f(x) <= e ^ (- (x^2))
40
+ expect(S(f(x), dx)[-100, 100]).to eq(1.672428604536991)
41
+ end
42
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dydx
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - gogotanaka
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-21 00:00:00.000000000 Z
11
+ date: 2014-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -90,13 +90,17 @@ files:
90
90
  - lib/dydx/algebra/set/cos.rb
91
91
  - lib/dydx/algebra/set/e.rb
92
92
  - lib/dydx/algebra/set/fixnum.rb
93
+ - lib/dydx/algebra/set/float.rb
93
94
  - lib/dydx/algebra/set/log.rb
94
95
  - lib/dydx/algebra/set/num.rb
95
96
  - lib/dydx/algebra/set/pi.rb
96
97
  - lib/dydx/algebra/set/sin.rb
97
98
  - lib/dydx/algebra/set/symbol.rb
98
99
  - lib/dydx/algebra/set/tan.rb
100
+ - lib/dydx/delta.rb
101
+ - lib/dydx/function.rb
99
102
  - lib/dydx/helper.rb
103
+ - lib/dydx/integrand.rb
100
104
  - lib/dydx/version.rb
101
105
  - spec/dydx_spec.rb
102
106
  - spec/lib/algebra/formula_spec.rb
@@ -112,7 +116,10 @@ files:
112
116
  - spec/lib/algebra/set/sin_spec.rb
113
117
  - spec/lib/algebra/set/symbol_spec.rb
114
118
  - spec/lib/algebra/set/tan_spec.rb
119
+ - spec/lib/delta_spec.rb
120
+ - spec/lib/function_spec.rb
115
121
  - spec/lib/helper_spec.rb
122
+ - spec/lib/integrand_spec.rb
116
123
  - spec/spec_helper.rb
117
124
  homepage: https://github.com/gogotanaka
118
125
  licenses:
@@ -153,5 +160,8 @@ test_files:
153
160
  - spec/lib/algebra/set/sin_spec.rb
154
161
  - spec/lib/algebra/set/symbol_spec.rb
155
162
  - spec/lib/algebra/set/tan_spec.rb
163
+ - spec/lib/delta_spec.rb
164
+ - spec/lib/function_spec.rb
156
165
  - spec/lib/helper_spec.rb
166
+ - spec/lib/integrand_spec.rb
157
167
  - spec/spec_helper.rb