ragni-cas 0.1.7 → 0.1.8

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: 4f98cf94916ce493037fae540da85b571d677a72
4
- data.tar.gz: 80e70754e06f40feb3f3ea8ef63bcf77824a77fc
3
+ metadata.gz: d1727dd0447e3614d413bf740c0e2012a032d8f3
4
+ data.tar.gz: b3470c930416120a63e903934b39c738797ec0e2
5
5
  SHA512:
6
- metadata.gz: 08cc60ffe01d6b41c85e45d9e76dc89dc4ffeb01fafbf005df1ed9c68247944f9b635806c346ca6d3f196cc8964dbb04e06177ce1bd64da0dfef4d356929068b
7
- data.tar.gz: 4c10e0659a2651b0c6d5919845ee1670a515f4218fb1445d978c4dfe161aa38bea057bb4d7335975afd50eb08e3f71fc2b27ae22104cb502f66d25e5cfecc115
6
+ metadata.gz: 1ff61d15cb0576883729cf5faaca1a04ceee6f05d5206fb0ac379300be89c7e584c38ee0c95c8b70665879cc426d3a3e28bd5b2b23a9ac85c5f43bee9d059802
7
+ data.tar.gz: 6a97d066096a1a0d3d991474bf076b3b215f8fa14262bbd41931c86fff1b168c84914171d376d01070dc0cf06bde9c7784f1720c2cf39942c6bf09b6f143ca99
checksums.yaml.gz.sig CHANGED
@@ -1,2 +1,2 @@
1
- ��ZQz�^?�.�����`�j�ރ�=�����x�@��(�R�Hv|���C)/`&2T�r.� w��7W��o�Ȁ��L��pA쾷�*��K+��GZ GU�IIGKF��ݢgA}&�4%(bbGN+�)3�m�?PL�(�C�u56'!�‚�V��(;T���hI7bA���nX�j�ʈz?��I����UV��pt���W�X���[0r+d��^����@u;�ku��
2
- �x=��
1
+ '.��C��q������ϢH@���9��@*�<�0��N_�����лB�S��W��ӉԖ����'~�]��~Ȱ��f�͋5uv�����`����H�g/֨�����q[m��S�� ̄��amx'Z��W�~��� 7\]�ֽW=ϗ79=z�b���� i�M��<���.� m/��X��54�/��0 7:�,jXO~�cJ>�"}H��,I�7lvr��bO?Xv�^EV��
2
+ ��Q����3�X'k�{����<<
data/lib/fnc-base.rb CHANGED
@@ -6,21 +6,34 @@ module CAS
6
6
  # \__ \ || | ' \
7
7
  # |___/\_,_|_|_|_|
8
8
  class Sum < CAS::BinaryOp
9
+ # Performs the sum between two `CAS::Op`
10
+ #
11
+ # ```
12
+ # d
13
+ # ---- (f(x) + g(x)) = f'(x) + g'(x)
14
+ # dx
15
+ # ```
9
16
  def diff(v)
10
17
  left, right = super v
11
- return left if (right == nil or right == CAS::Zero)
12
- return right if (left == nil or left == CAS::Zero)
18
+
19
+ return left if right == CAS::Zero
20
+ return right if left == CAS::Zero
13
21
  left + right
14
22
  end
15
23
 
24
+ # Same as `CAS::Op`
16
25
  def call(f)
26
+ CAS::Help.assert(f, Hash)
27
+
17
28
  return @x.call(f) + @y.call(f)
18
29
  end
19
30
 
31
+ # Same as `CAS::Op`
20
32
  def to_s
21
33
  "(#{@x} + #{@y})"
22
34
  end
23
35
 
36
+ # Same as `CAS::Op`
24
37
  def simplify
25
38
  super
26
39
  if @x == CAS::Zero
@@ -34,17 +47,21 @@ module CAS
34
47
  end
35
48
  if @x == -@y or -@x == @y
36
49
  return CAS::Zero
37
- end
50
+ end
38
51
  if @x.is_a? CAS::Constant and @y.is_a? CAS::Constant
39
52
  return CAS.const(self.call({}))
40
53
  end
41
54
  return self
42
55
  end
43
56
 
57
+ # Same as `CAS::Op`
44
58
  def ==(op)
59
+ CAS::Help.assert(op, CAS::Op)
60
+
45
61
  self.class == op.class and ((@x == op.x and @y == op.y) or (@y == op.x and @x == op.y))
46
62
  end
47
63
 
64
+ # Same as `CAS::Op`
48
65
  def to_code
49
66
  "(#{@x.to_code} + #{@y.to_code})"
50
67
  end
@@ -55,21 +72,33 @@ module CAS
55
72
  # | |) | | _| _/
56
73
  # |___/|_|_| |_|
57
74
  class Diff < CAS::BinaryOp
75
+ # Performs the difference between two `CAS::Op`s
76
+ #
77
+ # ```
78
+ # d
79
+ # ---- (f(x) - g(x)) = f'(x) - g'(x)
80
+ # dx
81
+ # ```
58
82
  def diff(v)
59
83
  left, right = super v
60
- return left if (right == nil or right == CAS::Zero)
61
- return CAS::Invert.new(right) if (left == nil or left == CAS::Zero)
84
+ return left if right == CAS::Zero
85
+ return CAS::Invert.new(right) if left == CAS::Zero
62
86
  left - right
63
87
  end
64
88
 
89
+ # Same as `CAS::Op`
65
90
  def call(f)
91
+ CAS::Help.assert(f, Hash)
92
+
66
93
  return @x.call(f) - @y.call(f)
67
94
  end
68
95
 
96
+ # Same as `CAS::Op`
69
97
  def to_s
70
98
  "(#{@x} - #{@y})"
71
99
  end
72
100
 
101
+ # Same as `CAS::Op`
73
102
  def simplify
74
103
  super
75
104
  if @x == CAS::Zero
@@ -87,10 +116,13 @@ module CAS
87
116
  return self
88
117
  end
89
118
 
119
+ # Same as `CAS::Op`
90
120
  def ==(op)
121
+ CAS::Help.assert(op, CAS::Op)
91
122
  self.class == op.class and ((@x == op.x and @y == op.y) or (@y == op.x and @x == op.y))
92
123
  end
93
124
 
125
+ # Same as `CAS::Op`
94
126
  def to_code
95
127
  "(#{@x.to_code} - #{@y.to_code})"
96
128
  end
@@ -101,21 +133,33 @@ module CAS
101
133
  # | _/ '_/ _ \/ _` |
102
134
  # |_| |_| \___/\__,_|
103
135
  class Prod < CAS::BinaryOp
136
+ # Performs the product between two `CAS::Op`
137
+ #
138
+ # ```
139
+ # d
140
+ # ---- (f(x) * g(x)) = f'(x) * g(x) + f(x) * g'(x)
141
+ # dx
142
+ # ```
104
143
  def diff(v)
105
144
  left, right = super v
106
- return left * @y if (right == nil or right == CAS::Zero)
107
- return right * @x if (left == nil or left == CAS::Zero)
145
+ return left * @y if right == CAS::Zero
146
+ return right * @x if left == CAS::Zero
108
147
  (left * @y) + (right * @x)
109
148
  end
110
149
 
150
+ # Same as `CAS::Op`
111
151
  def call(f)
152
+ CAS::Help.assert(f, Hash)
153
+
112
154
  return @x.call(f) * @y.call(f)
113
155
  end
114
156
 
157
+ # Same as `CAS::Op`
115
158
  def to_s
116
159
  "(#{@x} * #{@y})"
117
160
  end
118
161
 
162
+ # Same as `CAS::Op`
119
163
  def simplify
120
164
  super
121
165
  if @x == CAS::Zero or @y == CAS::Zero
@@ -136,10 +180,14 @@ module CAS
136
180
  return self
137
181
  end
138
182
 
183
+ # Same as `CAS::Op`
139
184
  def ==(op)
185
+ CAS::Help.assert(op, CAS::Op)
186
+
140
187
  self.class == op.class and ((@x == op.x and @y == op.y) or (@y == op.x and @x == op.y))
141
188
  end
142
189
 
190
+ # Same as `CAS::Op`
143
191
  def to_code
144
192
  "(#{@x.to_code} * #{@y.to_code})"
145
193
  end
@@ -150,25 +198,45 @@ module CAS
150
198
  # | _/ _ \ V V /
151
199
  # |_| \___/\_/\_/
152
200
  class Pow < CAS::BinaryOp
201
+ # Performs the power between two `CAS::Op`
202
+ #
203
+ # ```
204
+ # d
205
+ # ---- (f(x)^a) = f(x)^(a - 1) * a * f'(x)
206
+ # dx
207
+ #
208
+ # d
209
+ # ---- (a^f(x)) = a^f(x) * f'(x) * ln a
210
+ # dx
211
+ #
212
+ # d
213
+ # ---- (f(x)^g(x)) = (f(x)^g(x)) * (g'(x) * ln f(x) + g(x) * f'(x) / f(x))
214
+ # dx
215
+ # ```
153
216
  def diff(v)
154
217
  diff_x, diff_y = super v
155
- if diff_y == nil or diff_y == CAS::Zero
218
+ if diff_y == CAS::Zero
156
219
  return ((@x ** (@y - 1.0)) * @y * diff_x)
157
- elsif diff_x == nil or diff_x == CAS::Zero
220
+ elsif diff_x == CAS::Zero
158
221
  return (@x ** @y) * diff_y * CAS.ln(@x)
159
222
  else
160
223
  return (@x ** @y) * ((diff_y * CAS.ln(@x)) + (@y * diff_x / @x))
161
224
  end
162
225
  end
163
226
 
227
+ # Same as `CAS::Op`
164
228
  def call(f)
229
+ CAS::Help.assert(f, Hash)
230
+
165
231
  @x.call(f) ** @y.call(f)
166
232
  end
167
233
 
234
+ # Same as `CAS::Op`
168
235
  def to_s
169
236
  "#{@x}^#{@y}"
170
237
  end
171
238
 
239
+ # Same as `CAS::Op`
172
240
  def simplify
173
241
  super
174
242
  if @x == CAS::Zero
@@ -189,6 +257,7 @@ module CAS
189
257
  return self
190
258
  end
191
259
 
260
+ # Same as `CAS::Op`
192
261
  def to_code
193
262
  "(#{@x.to_code} ** #{@y.to_code})"
194
263
  end
@@ -203,25 +272,37 @@ module CAS
203
272
  # | |) | \ V /
204
273
  # |___/|_|\_/
205
274
  class Div < CAS::BinaryOp
275
+ # Performs the division between two `CAS::Op`
276
+ #
277
+ # ```
278
+ # d
279
+ # ---- (f(x) / g(x)) = (f'(x) * g(x) - f(x) * g'(x))/(g(x)^2)
280
+ # dx
281
+ # ```
206
282
  def diff(v)
207
283
  diff_x, diff_y = super v
208
- if diff_y == nil or diff_y == CAS::Zero
284
+ if diff_y == CAS::Zero
209
285
  return (diff_x/@y)
210
- elsif diff_x == nil or diff_x == CAS::Zero
286
+ elsif diff_x == CAS::Zero
211
287
  return CAS.invert(@x * diff_y / CAS.pow(@y, CAS.const(2.0)))
212
288
  else
213
289
  return ((diff_x * @y) - (diff_y * @x))/CAS.pow(@y, CAS.const(2.0))
214
290
  end
215
291
  end
216
292
 
293
+ # Same as `CAS::Op`
217
294
  def call(f)
295
+ CAS::Help.assert(f, Hash)
296
+
218
297
  @x.call(f)/@y.call(f)
219
298
  end
220
299
 
300
+ # Same as `CAS::Op`
221
301
  def to_s
222
302
  "(#{@x}) / (#{@y})"
223
303
  end
224
304
 
305
+ # Same as `CAS::Op`
225
306
  def simplify
226
307
  super
227
308
  if @x == CAS::Zero
@@ -242,6 +323,7 @@ module CAS
242
323
  return self
243
324
  end
244
325
 
326
+ # Same as `CAS::Op`
245
327
  def to_code
246
328
  "(#{@x.to_code} / #{@y.to_code})"
247
329
  end
@@ -253,6 +335,13 @@ module CAS
253
335
  # |___/\__, |_| \__|
254
336
  # |_|
255
337
  class Sqrt < CAS::Op
338
+ # Performs the square root between two `CAS::Op`
339
+ #
340
+ # ```
341
+ # d
342
+ # ---- √f(x) = 1/2 * f'(x) * √f(x)
343
+ # dx
344
+ # ```
256
345
  def diff(v)
257
346
  if @x.depend? v
258
347
  return (@x.diff(v) / (CAS.const(2.0) * CAS.sqrt(@x)))
@@ -261,14 +350,19 @@ module CAS
261
350
  end
262
351
  end
263
352
 
353
+ # Same as `CAS::Op`
264
354
  def call(f)
355
+ CAS::Help.assert(f, Hash)
356
+
265
357
  Math::sqrt @x.call(f)
266
358
  end
267
359
 
360
+ # Same as `CAS::Op`
268
361
  def to_s
269
362
  "√(#{@x})"
270
363
  end
271
364
 
365
+ # Same as `CAS::Op`
272
366
  def simplify
273
367
  super
274
368
  if @x.is_a? CAS::Pow
@@ -286,6 +380,7 @@ module CAS
286
380
  return self
287
381
  end
288
382
 
383
+ # Same as `CAS::Op`
289
384
  def to_code
290
385
  "Math::sqrt(#{@x.to_code})"
291
386
  end
@@ -300,22 +395,34 @@ module CAS
300
395
  # | || ' \ V / -_) '_| _|
301
396
  # |___|_||_\_/\___|_| \__|
302
397
  class Invert < CAS::Op
398
+ # Performs the inversion of a `CAS::Op`
399
+ #
400
+ # ```
401
+ # d
402
+ # ---- (-f(x)) = -f'(x)
403
+ # dx
404
+ # ```
303
405
  def diff(v)
304
406
  if @x.depend? v
305
- CAS::const(-1.0) * @x.diff
407
+ CAS::const(-1.0) * @x.diff(v)
306
408
  else
307
409
  CAS::Zero
308
410
  end
309
411
  end
310
412
 
413
+ # Same as `CAS::Op`
311
414
  def call(f)
415
+ CAS::Help.assert(f, Hash)
416
+
312
417
  -1.0 * @x.call(f)
313
418
  end
314
419
 
420
+ # Same as `CAS::Op`
315
421
  def to_s
316
422
  "-#{@x}"
317
423
  end
318
424
 
425
+ # Same as `CAS::Op`
319
426
  def simplify
320
427
  super
321
428
  if @x == CAS::Zero
@@ -327,6 +434,7 @@ module CAS
327
434
  return self
328
435
  end
329
436
 
437
+ # Same as `CAS::Op`
330
438
  def to_code
331
439
  "(-#{@x.to_code})"
332
440
  end
@@ -341,6 +449,13 @@ module CAS
341
449
  # / _ \| '_ (_-<
342
450
  # /_/ \_\_.__/__/
343
451
  class Abs < CAS::Op
452
+ # Performs the absolute value of a `CAS::Op`
453
+ #
454
+ # ```
455
+ # d
456
+ # ---- |f(x)| = f'(x) * (f(x) / |f(x)|)
457
+ # dx
458
+ # ```
344
459
  def diff(v)
345
460
  if @x.depend? v
346
461
  return @x.diff * (@x/CAS.abs(@x))
@@ -349,15 +464,20 @@ module CAS
349
464
  end
350
465
  end
351
466
 
467
+ # Same as `CAS::Op`
352
468
  def call(f)
469
+ CAS::Help.assert(f, Hash)
470
+
353
471
  s = (@x.call(f) >= 0 ? 1 : -1)
354
472
  return s * @x.call(f)
355
473
  end
356
474
 
475
+ # Same as `CAS::Op`
357
476
  def to_s
358
477
  "|#{@x}|"
359
478
  end
360
479
 
480
+ # Same as `CAS::Op`
361
481
  def simplify
362
482
  super
363
483
  if @x == CAS::Zero
@@ -369,6 +489,7 @@ module CAS
369
489
  return self
370
490
  end
371
491
 
492
+ # Same as `CAS::Op`
372
493
  def to_code
373
494
  "(#{@x.to_code}).abs"
374
495
  end
data/lib/fnc-branch.rb ADDED
@@ -0,0 +1,198 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module CAS
4
+ class Piecewise < CAS::BinaryOp
5
+ attr_reader :condition
6
+
7
+ def initialize(x, y, condition)
8
+ CAS::Help.assert(condition, CAS::Condition)
9
+
10
+ super(x, y)
11
+ @condition = condition
12
+ end
13
+
14
+ def diff(v)
15
+ CAS::Help.assert(v, CAS::Op)
16
+
17
+ return CAS::Piecewise.new(@x.diff(v).simplify, @y.diff(v).simplify, condition)
18
+ end
19
+
20
+ def call(fd)
21
+ CAS::Help.assert(fd, Hash)
22
+
23
+ (@condition.call(fd) ? @x.call(fd) : @y.call(fd))
24
+ end
25
+
26
+ def ==(op)
27
+ CAS::Help.assert(op, CAS::Op)
28
+
29
+ if self.class != op.class
30
+ return false
31
+ else
32
+ return ((@x == op.x) and (@y == op.y) and (@condition == op.condition))
33
+ end
34
+ end
35
+
36
+ def to_code
37
+ "(#{@condition.to_code} ? (#{@x.to_code}) : (#{@y.to_code}))"
38
+ end
39
+
40
+ def to_s
41
+ "(#{@condition} ? #{@x} : #{@y})"
42
+ end
43
+
44
+ def dot_graph(node)
45
+ cls = "#{self.class.to_s.gsub("CAS::", "")}_#{self.object_id}"
46
+ "#{cls} -> #{@x.dot_graph node}\n #{cls} -> #{@y.dot_graph node}\n #{cls} -> #{@condition.dot_graph node}"
47
+ end
48
+ end
49
+
50
+
51
+ def self.max(x, y)
52
+ CAS::Piecewise.new(x, y, CAS::greater_equal(x, y))
53
+ end
54
+
55
+ def self.min(x, y)
56
+ CAS::Piecewise.new(x, y, CAS::smaller_equal(x, y))
57
+ end
58
+
59
+ class Condition
60
+ attr_reader :x, :y, :type
61
+
62
+ def initialize(type, x, y)
63
+ CAS::Help.assert(type, Symbol)
64
+
65
+ @x = x
66
+ @y = y
67
+ case type
68
+ when :eq
69
+ @type = "=="
70
+ self.define_singleton_method("call") do |fd|
71
+ @x.call(fd) == @y.call(fd)
72
+ end
73
+ when :gt
74
+ @type = ">"
75
+ self.define_singleton_method("call") do |fd|
76
+ @x.call(fd) > @y.call(fd)
77
+ end
78
+ when :lt
79
+ @type = "<"
80
+ self.define_singleton_method("call") do |fd|
81
+ @x.call(fd) < @y.call(fd)
82
+ end
83
+ when :geq
84
+ @type = "≥"
85
+ self.define_singleton_method("call") do |fd|
86
+ @x.call(fd) >= @y.call(fd)
87
+ end
88
+ when :leq
89
+ @type = "≤"
90
+ self.define_singleton_method("call") do |fd|
91
+ @x.call(fd) <= @y.call(fd)
92
+ end
93
+ else
94
+ raise CASError, "Unknown condition #{@type}"
95
+ end
96
+ end
97
+
98
+ def inspect
99
+ "#{@x.inspect} #{@type} #{@y.inspect}"
100
+ end
101
+
102
+ def to_s
103
+ "#{@x} #{@type} #{@y}"
104
+ end
105
+
106
+ def to_code
107
+ "#{@x}.call(fd) #{@type} #{@y}.call(fd)"
108
+ end
109
+
110
+ def args
111
+ (@x.args + @y.args).uniq
112
+ end
113
+
114
+ def diff(v)
115
+ @x.diff(v)
116
+ @y.diff(v)
117
+ self.simplify
118
+ end
119
+
120
+ def depend?(v)
121
+ @x.depend?(v) or @y.depend?(v)
122
+ end
123
+
124
+ def ==(op)
125
+ CAS::Help.assert(op, CAS::Op)
126
+ condA = (@x == op.x) and (@y == op.y)
127
+ condB = (@x == op.y) and (@y == op.x)
128
+ condC = condA or condB
129
+ return (condC and (self.class == op.class) and (@type == op.type))
130
+ end
131
+
132
+ def !=(op)
133
+ not self == op
134
+ end
135
+
136
+ def simplify
137
+ @x.simplify
138
+ @y.simplify
139
+ return self
140
+ end
141
+
142
+ def subs(fd)
143
+ CAS::Help.assert(fd, Hash)
144
+ @x.subs(fd)
145
+ @y.subs(fd)
146
+ return self
147
+ end
148
+
149
+ def dot_graph(node)
150
+ cls = "#{self.class.to_s.gsub("CAS::", "")}_#{self.object_id}"
151
+ "#{cls} -> #{@x.dot_graph node}\n #{cls} -> #{@y.dot_graph node}"
152
+ end
153
+ end
154
+
155
+ class Equal < CAS::Condition
156
+ def initialize(x, y)
157
+ super(:eq, x, y)
158
+ end
159
+ end
160
+
161
+ class Greater < CAS::Condition
162
+ def initialize(x, y)
163
+ super(:gt, x, y)
164
+ end
165
+ end
166
+
167
+ class GreaterEqual < CAS::Condition
168
+ def initialize(x, y)
169
+ super(:geq, x, y)
170
+ end
171
+ end
172
+
173
+ class Smaller < CAS::Condition
174
+ def initialize(x, y)
175
+ super(:lt, x, y)
176
+ end
177
+ end
178
+
179
+ class SmallerEqual < CAS::Condition
180
+ def initialize(x, y)
181
+ super(:leq, x, y)
182
+ end
183
+ end
184
+
185
+ def self.equal(x, y); CAS::Equal.new(x, y); end
186
+ def self.greater(x, y); CAS::Greater.new(x, y); end
187
+ def self.greater_equal(x, y); CAS::GreaterEqual.new(x, y); end
188
+ def self.smaller(x, y); CAS::Smaller.new(x, y); end
189
+ def self.smaller_equal(x, y); CAS::SmallerEqual.new(x, y); end
190
+
191
+ class Op
192
+ def equal(v); CAS.equal(self, v); end
193
+ def greater(v); CAS.greater(self, v); end
194
+ def smaller(v); CAS.smaller(self, v); end
195
+ def greater_equal(v); CAS.greater_equal(self, v); end
196
+ def smaller_equal(v); CAS.smaller_equal(self, v); end
197
+ end
198
+ end