ragni-cas 0.2.2 → 0.2.3
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/functions/fnc-base.rb +660 -0
- data/lib/functions/fnc-box-conditions.rb +316 -0
- data/lib/functions/fnc-conditions.rb +365 -0
- data/lib/functions/fnc-piecewise.rb +186 -0
- data/lib/functions/fnc-trig.rb +487 -0
- data/lib/functions/fnc-trsc.rb +196 -0
- data/lib/numbers/constants.rb +358 -0
- data/lib/numbers/variables.rb +211 -0
- data/lib/operators/bary-op.rb +185 -0
- data/lib/operators/nary-op.rb +175 -0
- data/lib/operators/op.rb +285 -0
- data/lib/overloading/fixnum.rb +61 -0
- data/lib/overloading/float.rb +61 -0
- data/lib/ragni-cas.rb +23 -187
- data/lib/version.rb +7 -1
- data.tar.gz.sig +0 -0
- metadata +15 -8
- metadata.gz.sig +0 -0
- data/lib/fnc-base.rb +0 -560
- data/lib/fnc-branch.rb +0 -388
- data/lib/fnc-trig.rb +0 -336
- data/lib/fnc-trsc.rb +0 -126
- data/lib/numbers.rb +0 -390
- data/lib/op.rb +0 -454
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f5aedceb3a3141a14a807fdbbac42e5bc66fd85
|
4
|
+
data.tar.gz: caa36f84a6e77cac0f1a6c5410c63cd2940297bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9a56cda36bc0ac20cb444e1ad663b29c4ddeaac92e97239edfbc8631ef7ec054bc4d626919ed7efbf7200898f62bd7e731380f708bb0631345e60677eba684c2
|
7
|
+
data.tar.gz: 7c9ac6f8cb07d8a0a967b8afd655790a4d8d147fbcf4c2f9d939d763427e2e18405513c24b1bd0a4eb1bd72cee11d4c8ef710ed8c47e775afdda49ce3a12a606
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
@@ -0,0 +1,660 @@
|
|
1
|
+
#!/usr/vin/env ruby
|
2
|
+
|
3
|
+
module CAS
|
4
|
+
# ___
|
5
|
+
# / __|_ _ _ __
|
6
|
+
# \__ \ || | ' \
|
7
|
+
# |___/\_,_|_|_|_|
|
8
|
+
|
9
|
+
##
|
10
|
+
# **Sum basic operation**. As for now it is implemented as a simple
|
11
|
+
# binary operation. It will be implemented as n-ary op.
|
12
|
+
class Sum < CAS::BinaryOp
|
13
|
+
# Performs the sum between two `CAS::Op`
|
14
|
+
#
|
15
|
+
# ```
|
16
|
+
# d
|
17
|
+
# ---- (f(x) + g(x)) = f'(x) + g'(x)
|
18
|
+
# dx
|
19
|
+
# ```
|
20
|
+
#
|
21
|
+
# * **argument**: `CAS::Op` argument of derivative
|
22
|
+
# * **returns**: `CAS::Op` derivative
|
23
|
+
def diff(v)
|
24
|
+
left, right = super v
|
25
|
+
|
26
|
+
return left if right == CAS::Zero
|
27
|
+
return right if left == CAS::Zero
|
28
|
+
left + right
|
29
|
+
end
|
30
|
+
|
31
|
+
# Call resolves the operation tree in a `Numeric` (if `Fixnum`)
|
32
|
+
# or `Float` (depends upon promotions).
|
33
|
+
# As input, it requires an hash with `CAS::Variable` or `CAS::Variable#name`
|
34
|
+
# as keys, and a `Numeric` as a value. In this case it will call
|
35
|
+
# the `Fixnum#overloaded_plus`, that is the old plus function.
|
36
|
+
#
|
37
|
+
# * **argument**: `Hash` with feed dictionary
|
38
|
+
# * **returns**: `Numeric`
|
39
|
+
def call(f)
|
40
|
+
CAS::Help.assert(f, Hash)
|
41
|
+
return @x.call(f).overloaded_plus(@y.call(f))
|
42
|
+
end
|
43
|
+
|
44
|
+
# Convert expression to string
|
45
|
+
#
|
46
|
+
# * **returns**: `String` to print on screen
|
47
|
+
def to_s
|
48
|
+
"(#{@x} + #{@y})"
|
49
|
+
end
|
50
|
+
|
51
|
+
# Same as `CAS::Op`
|
52
|
+
#
|
53
|
+
# Simplifcation engine supports:
|
54
|
+
#
|
55
|
+
# * x + 0 = x
|
56
|
+
# * 0 + y = y
|
57
|
+
# * x + x = 2 x
|
58
|
+
# * x + (-x) = 0
|
59
|
+
# * x + (-y) = x - y
|
60
|
+
# * 1 + 2 = 3 (constants reduction)
|
61
|
+
#
|
62
|
+
# * **returns**: `CAS::Op` simplified version
|
63
|
+
def simplify
|
64
|
+
super
|
65
|
+
return @y if @x == CAS::Zero
|
66
|
+
return @x if @y == CAS::Zero
|
67
|
+
return @x * 2.0 if @x == @y
|
68
|
+
return CAS::Zero if @x == -@y or -@x == @y
|
69
|
+
return (@x - @y.x) if @y.is_a? CAS::Invert
|
70
|
+
return CAS.const(self.call({})) if (@x.is_a? CAS::Constant and @y.is_a? CAS::Constant)
|
71
|
+
return self
|
72
|
+
end
|
73
|
+
|
74
|
+
# Convert expression to code (internal, for `CAS::Op#to_proc` method)
|
75
|
+
#
|
76
|
+
# * **returns**: `String` that represent Ruby code to be parsed in `CAS::Op#to_proc`
|
77
|
+
def to_code
|
78
|
+
"(#{@x.to_code} + #{@y.to_code})"
|
79
|
+
end
|
80
|
+
end # Sum
|
81
|
+
CAS::Sum.init_simplify_dict
|
82
|
+
|
83
|
+
# ___ _ __ __
|
84
|
+
# | \(_)/ _|/ _|
|
85
|
+
# | |) | | _| _/
|
86
|
+
# |___/|_|_| |_|
|
87
|
+
|
88
|
+
##
|
89
|
+
# **Difference basic operation**. It's a binary operation. This cannot
|
90
|
+
# be implemented as a n-ary op, thus will not be changed
|
91
|
+
class Diff < CAS::BinaryOp
|
92
|
+
# Performs the difference between two `CAS::Op`s
|
93
|
+
#
|
94
|
+
# ```
|
95
|
+
# d
|
96
|
+
# ---- (f(x) - g(x)) = f'(x) - g'(x)
|
97
|
+
# dx
|
98
|
+
# ```
|
99
|
+
#
|
100
|
+
# * **argument**: `CAS::Op` argument of derivative
|
101
|
+
# * **returns**: `CAS::Op` derivative
|
102
|
+
def diff(v)
|
103
|
+
left, right = super v
|
104
|
+
return left if right == CAS::Zero
|
105
|
+
return CAS::Invert.new(right) if left == CAS::Zero
|
106
|
+
left - right
|
107
|
+
end
|
108
|
+
|
109
|
+
# Same as `CAS::Op`
|
110
|
+
def call(f)
|
111
|
+
CAS::Help.assert(f, Hash)
|
112
|
+
|
113
|
+
return @x.call(f).overloaded_minus(@y.call(f))
|
114
|
+
end
|
115
|
+
|
116
|
+
# Same as `CAS::Op`
|
117
|
+
def to_s
|
118
|
+
"(#{@x} - #{@y})"
|
119
|
+
end
|
120
|
+
|
121
|
+
# Same as `CAS::Op`
|
122
|
+
#
|
123
|
+
# Simplifcation engine supports:
|
124
|
+
#
|
125
|
+
# * 0 - y = -y
|
126
|
+
# * x - 0 = x
|
127
|
+
# * a - b = c (constants reduction)
|
128
|
+
# * x - x = 0
|
129
|
+
# * x - (-y) = x + y
|
130
|
+
#
|
131
|
+
# * **returns**: `CAS::Op` simplified version
|
132
|
+
def simplify
|
133
|
+
super
|
134
|
+
return CAS.invert(@y) if @x == CAS::Zero
|
135
|
+
return @x if @y == CAS::Zero
|
136
|
+
return CAS::Zero if @x == @y
|
137
|
+
return CAS.const(self.call({})) if (@x.is_a? CAS::Constant and @y.is_a? CAS::Constant)
|
138
|
+
return @x + @y.x if @y.is_a? CAS::Invert
|
139
|
+
return -(@x.x + @y) if @x.is_a? CAS::Invert
|
140
|
+
return self
|
141
|
+
end
|
142
|
+
|
143
|
+
# Convert expression to code (internal, for `CAS::Op#to_proc` method)
|
144
|
+
#
|
145
|
+
# * **returns**: `String` that represent Ruby code to be parsed in `CAS::Op#to_proc`
|
146
|
+
def to_code
|
147
|
+
"(#{@x.to_code} - #{@y.to_code})"
|
148
|
+
end
|
149
|
+
end # Difference
|
150
|
+
CAS::Diff.init_simplify_dict
|
151
|
+
|
152
|
+
# ___ _
|
153
|
+
# | _ \_ _ ___ __| |
|
154
|
+
# | _/ '_/ _ \/ _` |
|
155
|
+
# |_| |_| \___/\__,_|
|
156
|
+
|
157
|
+
##
|
158
|
+
# Product class. Performs the product between two elements.
|
159
|
+
# This class will be soon modified as an n-ary operator.
|
160
|
+
class Prod < CAS::BinaryOp
|
161
|
+
# Performs the product between two `CAS::Op`
|
162
|
+
#
|
163
|
+
# ```
|
164
|
+
# d
|
165
|
+
# ---- (f(x) * g(x)) = f'(x) * g(x) + f(x) * g'(x)
|
166
|
+
# dx
|
167
|
+
# ```
|
168
|
+
#
|
169
|
+
# * **argument**: `CAS::Op` argument of derivative
|
170
|
+
# * **returns**: `CAS::Op` derivative
|
171
|
+
def diff(v)
|
172
|
+
left, right = super v
|
173
|
+
return left * @y if right == CAS::Zero
|
174
|
+
return right * @x if left == CAS::Zero
|
175
|
+
(left * @y) + (right * @x)
|
176
|
+
end
|
177
|
+
|
178
|
+
# Call resolves the operation tree in a `Numeric` (if `Fixnum`)
|
179
|
+
# or `Float` (depends upon promotions).
|
180
|
+
# As input, it requires an hash with `CAS::Variable` or `CAS::Variable#name`
|
181
|
+
# as keys, and a `Numeric` as a value. In this case it will call
|
182
|
+
# the `Fixnum#overloaded_plus`, that is the old plus function.
|
183
|
+
#
|
184
|
+
# * **argument**: `Hash` with feed dictionary
|
185
|
+
# * **returns**: `Numeric`
|
186
|
+
def call(f)
|
187
|
+
CAS::Help.assert(f, Hash)
|
188
|
+
|
189
|
+
return @x.call(f).overloaded_mul(@y.call(f))
|
190
|
+
end
|
191
|
+
|
192
|
+
# Convert expression to string
|
193
|
+
#
|
194
|
+
# * **returns**: `String` to print on screen
|
195
|
+
def to_s
|
196
|
+
"(#{@x} * #{@y})"
|
197
|
+
end
|
198
|
+
|
199
|
+
# Same as `CAS::Op`
|
200
|
+
#
|
201
|
+
# Simplifcation engine supports:
|
202
|
+
#
|
203
|
+
# * x * 0 = x * y = 0
|
204
|
+
# * 1 * y = y
|
205
|
+
# * x * 1 = x
|
206
|
+
# * x * x = x²
|
207
|
+
# * a * b = c (constants reduction)
|
208
|
+
#
|
209
|
+
# * **returns**: `CAS::Op` simplified version
|
210
|
+
def simplify
|
211
|
+
super
|
212
|
+
return CAS::Zero if (@x == CAS::Zero or @y == CAS::Zero)
|
213
|
+
return @y if @x == CAS::One
|
214
|
+
return @x if @y == CAS::One
|
215
|
+
return @x ** 2.0 if @x == @y
|
216
|
+
return CAS.const(self.call({})) if @x.is_a? CAS::Constant and @y.is_a? CAS::Constant
|
217
|
+
return self
|
218
|
+
end
|
219
|
+
|
220
|
+
# Convert expression to code (internal, for `CAS::Op#to_proc` method)
|
221
|
+
#
|
222
|
+
# * **returns**: `String` that represent Ruby code to be parsed in `CAS::Op#to_proc`
|
223
|
+
def to_code
|
224
|
+
"(#{@x.to_code} * #{@y.to_code})"
|
225
|
+
end
|
226
|
+
end # Prod
|
227
|
+
CAS::Prod.init_simplify_dict
|
228
|
+
|
229
|
+
# ___
|
230
|
+
# | _ \_____ __ __
|
231
|
+
# | _/ _ \ V V /
|
232
|
+
# |_| \___/\_/\_/
|
233
|
+
|
234
|
+
##
|
235
|
+
# Power function.
|
236
|
+
class Pow < CAS::BinaryOp
|
237
|
+
# Performs the power between two `CAS::Op`
|
238
|
+
#
|
239
|
+
# ```
|
240
|
+
# d
|
241
|
+
# ---- (f(x)^a) = f(x)^(a - 1) * a * f'(x)
|
242
|
+
# dx
|
243
|
+
#
|
244
|
+
# d
|
245
|
+
# ---- (a^f(x)) = a^f(x) * f'(x) * ln a
|
246
|
+
# dx
|
247
|
+
#
|
248
|
+
# d
|
249
|
+
# ---- (f(x)^g(x)) = (f(x)^g(x)) * (g'(x) * ln f(x) + g(x) * f'(x) / f(x))
|
250
|
+
# dx
|
251
|
+
# ```
|
252
|
+
#
|
253
|
+
# * **argument**: `CAS::Op` argument of derivative
|
254
|
+
# * **returns**: `CAS::Op` derivative
|
255
|
+
def diff(v)
|
256
|
+
diff_x, diff_y = super v
|
257
|
+
if diff_y == CAS::Zero
|
258
|
+
return ((@x ** (@y - 1.0)) * @y * diff_x)
|
259
|
+
elsif diff_x == CAS::Zero
|
260
|
+
return (@x ** @y) * diff_y * CAS.ln(@x)
|
261
|
+
else
|
262
|
+
return (@x ** @y) * ((diff_y * CAS.ln(@x)) + (@y * diff_x / @x))
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
# Call resolves the operation tree in a `Numeric` (if `Fixnum`)
|
267
|
+
# or `Float` (depends upon promotions).
|
268
|
+
# As input, it requires an hash with `CAS::Variable` or `CAS::Variable#name`
|
269
|
+
# as keys, and a `Numeric` as a value. In this case it will call
|
270
|
+
# the `Fixnum#overloaded_plus`, that is the old plus function.
|
271
|
+
#
|
272
|
+
# * **argument**: `Hash` with feed dictionary
|
273
|
+
# * **returns**: `Numeric`
|
274
|
+
def call(f)
|
275
|
+
CAS::Help.assert(f, Hash)
|
276
|
+
@x.call(f).overloaded_pow(@y.call(f))
|
277
|
+
end
|
278
|
+
|
279
|
+
# Convert expression to string
|
280
|
+
#
|
281
|
+
# * **returns**: `String` to print on screen
|
282
|
+
def to_s
|
283
|
+
"(#{@x})^(#{@y})"
|
284
|
+
end
|
285
|
+
|
286
|
+
# Same as `CAS::Op`
|
287
|
+
#
|
288
|
+
# Simplifcation engine supports:
|
289
|
+
#
|
290
|
+
# * 0 ^ y = 0
|
291
|
+
# * x ^ 0 = 1
|
292
|
+
# * a ^ b = c (constants reduction)
|
293
|
+
# * x ^ 1 = x
|
294
|
+
# * 1 ^ y = 1
|
295
|
+
#
|
296
|
+
# * **returns**: `CAS::Op` simplified version
|
297
|
+
def simplify
|
298
|
+
super
|
299
|
+
return CAS::Zero if @x == CAS::Zero
|
300
|
+
return CAS::One if @x == CAS::One
|
301
|
+
return @x if @y == CAS::One
|
302
|
+
return CAS::One if @y == CAS::Zero
|
303
|
+
return CAS.const(self.call({})) if (@x.is_a? CAS::Constant and @y.is_a? CAS::Constant)
|
304
|
+
return self
|
305
|
+
end
|
306
|
+
|
307
|
+
# Convert expression to code (internal, for `CAS::Op#to_proc` method)
|
308
|
+
#
|
309
|
+
# * **returns**: `String` that represent Ruby code to be parsed in `CAS::Op#to_proc`
|
310
|
+
def to_code
|
311
|
+
"(#{@x.to_code} ** #{@y.to_code})"
|
312
|
+
end
|
313
|
+
end # Pow
|
314
|
+
CAS::Pow.init_simplify_dict
|
315
|
+
|
316
|
+
# Shortcut for `CAS::Pow` initializer
|
317
|
+
#
|
318
|
+
# * **argument**: `CAS::Op` base
|
319
|
+
# * **argument**: `CAS::Op` exponent
|
320
|
+
# * **returns**: `CAS::Pow` new instance
|
321
|
+
def self.pow(x, y)
|
322
|
+
CAS::Pow.new x, y
|
323
|
+
end
|
324
|
+
|
325
|
+
# ___ _
|
326
|
+
# | \(_)_ __
|
327
|
+
# | |) | \ V /
|
328
|
+
# |___/|_|\_/
|
329
|
+
|
330
|
+
##
|
331
|
+
# Division between two functions. A function divided by zero it is considered
|
332
|
+
# as an Infinity.
|
333
|
+
class Div < CAS::BinaryOp
|
334
|
+
# Performs the division between two `CAS::Op`
|
335
|
+
#
|
336
|
+
# ```
|
337
|
+
# d
|
338
|
+
# ---- (f(x) / g(x)) = (f'(x) * g(x) - f(x) * g'(x))/(g(x)^2)
|
339
|
+
# dx
|
340
|
+
# ```
|
341
|
+
#
|
342
|
+
# * **argument**: `CAS::Op` argument of derivative
|
343
|
+
# * **returns**: `CAS::Op` derivative
|
344
|
+
def diff(v)
|
345
|
+
diff_x, diff_y = super v
|
346
|
+
if diff_y == CAS::Zero
|
347
|
+
return (diff_x/@y)
|
348
|
+
elsif diff_x == CAS::Zero
|
349
|
+
return CAS.invert(@x * diff_y / CAS.pow(@y, CAS.const(2.0)))
|
350
|
+
else
|
351
|
+
return ((diff_x * @y) - (diff_y * @x))/CAS.pow(@y, CAS.const(2.0))
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
# Call resolves the operation tree in a `Numeric` (if `Fixnum`)
|
356
|
+
# or `Float` (depends upon promotions).
|
357
|
+
# As input, it requires an hash with `CAS::Variable` or `CAS::Variable#name`
|
358
|
+
# as keys, and a `Numeric` as a value. In this case it will call
|
359
|
+
# the `Fixnum#overloaded_plus`, that is the old plus function.
|
360
|
+
#
|
361
|
+
# * **argument**: `Hash` with feed dictionary
|
362
|
+
# * **returns**: `Numeric`
|
363
|
+
def call(f)
|
364
|
+
CAS::Help.assert(f, Hash)
|
365
|
+
|
366
|
+
@x.call(f).overloaded_div(@y.call(f))
|
367
|
+
end
|
368
|
+
|
369
|
+
# Convert expression to string
|
370
|
+
#
|
371
|
+
# * **returns**: `String` to print on screen
|
372
|
+
def to_s
|
373
|
+
"(#{@x}) / (#{@y})"
|
374
|
+
end
|
375
|
+
|
376
|
+
# Same as `CAS::Op`
|
377
|
+
#
|
378
|
+
# Simplifcation engine supports:
|
379
|
+
#
|
380
|
+
# * 0 / y = 0
|
381
|
+
# * x / 0 = Inf
|
382
|
+
# * x / 1 = x
|
383
|
+
# * x / Inf = 0
|
384
|
+
# * a / b = c (constants reduction)
|
385
|
+
#
|
386
|
+
# * **returns**: `CAS::Op` simplified version
|
387
|
+
def simplify
|
388
|
+
super
|
389
|
+
return CAS::Zero if @x == CAS::Zero
|
390
|
+
return CAS::Infinity if @y == CAS::Zero
|
391
|
+
return @x if @y == CAS::One
|
392
|
+
return CAS::Zero if @y == CAS::Infinity
|
393
|
+
return CAS.const(self.call({})) if (@x.is_a? CAS::Constant and @y.is_a? CAS::Constant)
|
394
|
+
return self
|
395
|
+
end
|
396
|
+
|
397
|
+
# Convert expression to code (internal, for `CAS::Op#to_proc` method)
|
398
|
+
#
|
399
|
+
# * **returns**: `String` that represent Ruby code to be parsed in `CAS::Op#to_proc`
|
400
|
+
def to_code
|
401
|
+
"(#{@x.to_code} / #{@y.to_code})"
|
402
|
+
end
|
403
|
+
end # Div
|
404
|
+
CAS::Div.init_simplify_dict
|
405
|
+
|
406
|
+
# ___ _
|
407
|
+
# / __| __ _ _ _| |_
|
408
|
+
# \__ \/ _` | '_| _|
|
409
|
+
# |___/\__, |_| \__|
|
410
|
+
# |_|
|
411
|
+
|
412
|
+
##
|
413
|
+
# Square Root of a function. Even if it can be implemented as a power function,
|
414
|
+
# it is a separated class.
|
415
|
+
class Sqrt < CAS::Op
|
416
|
+
# Performs the square root between two `CAS::Op`
|
417
|
+
#
|
418
|
+
# ```
|
419
|
+
# d
|
420
|
+
# ---- √f(x) = 1/2 * f'(x) * √f(x)
|
421
|
+
# dx
|
422
|
+
# ```
|
423
|
+
#
|
424
|
+
# * **argument**: `CAS::Op` argument of derivative
|
425
|
+
# * **returns**: `CAS::Op` derivative
|
426
|
+
def diff(v)
|
427
|
+
if @x.depend? v
|
428
|
+
return (@x.diff(v) / (CAS.const(2.0) * CAS.sqrt(@x)))
|
429
|
+
else
|
430
|
+
return CAS::Zero
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
# Call resolves the operation tree in a `Numeric` (if `Fixnum`)
|
435
|
+
# or `Float` (depends upon promotions).
|
436
|
+
# As input, it requires an hash with `CAS::Variable` or `CAS::Variable#name`
|
437
|
+
# as keys, and a `Numeric` as a value. In this case it will call
|
438
|
+
# the `Fixnum#overloaded_plus`, that is the old plus function.
|
439
|
+
#
|
440
|
+
# * **argument**: `Hash` with feed dictionary
|
441
|
+
# * **returns**: `Numeric`
|
442
|
+
def call(f)
|
443
|
+
CAS::Help.assert(f, Hash)
|
444
|
+
|
445
|
+
Math::sqrt @x.call(f)
|
446
|
+
end
|
447
|
+
|
448
|
+
# Convert expression to string
|
449
|
+
#
|
450
|
+
# * **returns**: `String` to print on screen
|
451
|
+
def to_s
|
452
|
+
"√(#{@x})"
|
453
|
+
end
|
454
|
+
|
455
|
+
# Same as `CAS::Op`
|
456
|
+
#
|
457
|
+
# Simplifcation engine supports:
|
458
|
+
#
|
459
|
+
# * √(x^z) = x^(z - 1/2)
|
460
|
+
# * √x = 0
|
461
|
+
# * √x = 1
|
462
|
+
# * √a = b (constants reduction)
|
463
|
+
#
|
464
|
+
# * **returns**: `CAS::Op` simplified version
|
465
|
+
def simplify
|
466
|
+
super
|
467
|
+
return CAS.pow(@x.x, @y - 0.5) if @x.is_a? CAS::Pow
|
468
|
+
return CAS::Zero if @x == CAS::Zero
|
469
|
+
return CAS::One if @x == CAS::One
|
470
|
+
return CAS.const(self.call({})) if (@x.is_a? CAS::Constant and @y.is_a? CAS::Constant)
|
471
|
+
return self
|
472
|
+
end
|
473
|
+
|
474
|
+
# Convert expression to code (internal, for `CAS::Op#to_proc` method)
|
475
|
+
#
|
476
|
+
# * **returns**: `String` that represent Ruby code to be parsed in `CAS::Op#to_proc`
|
477
|
+
def to_code
|
478
|
+
"Math::sqrt(#{@x.to_code})"
|
479
|
+
end
|
480
|
+
end # Sqrt
|
481
|
+
CAS::Sqrt.init_simplify_dict
|
482
|
+
|
483
|
+
# Shortcut for `CAS::Sqrt` initializer
|
484
|
+
#
|
485
|
+
# * **argument**: `CAS::Op` argument of square root
|
486
|
+
# * **returns**: `CAS::Sqrt` new instance
|
487
|
+
def self.sqrt(x)
|
488
|
+
CAS::Sqrt.new x
|
489
|
+
end
|
490
|
+
|
491
|
+
# ___ _
|
492
|
+
# |_ _|_ ___ _____ _ _| |_
|
493
|
+
# | || ' \ V / -_) '_| _|
|
494
|
+
# |___|_||_\_/\___|_| \__|
|
495
|
+
|
496
|
+
##
|
497
|
+
# Invert is the same as multiply by `-1` a function.
|
498
|
+
# `Invert(x)` is equal to `-x`
|
499
|
+
class Invert < CAS::Op
|
500
|
+
# Performs the inversion of a `CAS::Op`
|
501
|
+
#
|
502
|
+
# ```
|
503
|
+
# d
|
504
|
+
# ---- (-f(x)) = -f'(x)
|
505
|
+
# dx
|
506
|
+
# ```
|
507
|
+
#
|
508
|
+
# * **argument**: `CAS::Op` argument of derivative
|
509
|
+
# * **returns**: `CAS::Op` derivative
|
510
|
+
def diff(v)
|
511
|
+
if @x.depend? v
|
512
|
+
CAS::const(-1.0) * @x.diff(v)
|
513
|
+
else
|
514
|
+
CAS::Zero
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
# Call resolves the operation tree in a `Numeric` (if `Fixnum`)
|
519
|
+
# or `Float` (depends upon promotions).
|
520
|
+
# As input, it requires an hash with `CAS::Variable` or `CAS::Variable#name`
|
521
|
+
# as keys, and a `Numeric` as a value. In this case it will call
|
522
|
+
# the `Fixnum#overloaded_plus`, that is the old plus function.
|
523
|
+
#
|
524
|
+
# * **argument**: `Hash` with feed dictionary
|
525
|
+
# * **returns**: `Numeric`
|
526
|
+
def call(f)
|
527
|
+
CAS::Help.assert(f, Hash)
|
528
|
+
|
529
|
+
-1.0 * @x.call(f)
|
530
|
+
end
|
531
|
+
|
532
|
+
# Convert expression to string
|
533
|
+
#
|
534
|
+
# * **returns**: `String` to print on screen
|
535
|
+
def to_s
|
536
|
+
"-#{@x}"
|
537
|
+
end
|
538
|
+
|
539
|
+
# Same as `CAS::Op`
|
540
|
+
#
|
541
|
+
# Simplifcation engine supports:
|
542
|
+
#
|
543
|
+
# * -(-x) = x
|
544
|
+
# * -0 = 0
|
545
|
+
#
|
546
|
+
# * **returns**: `CAS::Op` simplified version
|
547
|
+
def simplify
|
548
|
+
super
|
549
|
+
return @x.x if @x.is_a? CAS::Invert
|
550
|
+
return self.simplify_dictionary
|
551
|
+
end
|
552
|
+
|
553
|
+
def self.init_simplify_dict
|
554
|
+
@simplify_dict = {
|
555
|
+
CAS::Zero => CAS::Zero
|
556
|
+
}
|
557
|
+
end
|
558
|
+
|
559
|
+
# Convert expression to code (internal, for `CAS::Op#to_proc` method)
|
560
|
+
#
|
561
|
+
# * **returns**: `String` that represent Ruby code to be parsed in `CAS::Op#to_proc`
|
562
|
+
def to_code
|
563
|
+
"(-#{@x.to_code})"
|
564
|
+
end
|
565
|
+
end # Invert
|
566
|
+
CAS::Invert.init_simplify_dict
|
567
|
+
|
568
|
+
# Shortcut for `CAs::Invert` initializer
|
569
|
+
#
|
570
|
+
# * **argument**: `CAs::Op` argument of the inversion
|
571
|
+
# * **returns**: `CAS::Invert` new instance
|
572
|
+
def self.invert(x)
|
573
|
+
CAS::Invert.new x
|
574
|
+
end
|
575
|
+
|
576
|
+
# _ _
|
577
|
+
# /_\ | |__ ___
|
578
|
+
# / _ \| '_ (_-<
|
579
|
+
# /_/ \_\_.__/__/
|
580
|
+
|
581
|
+
##
|
582
|
+
# Absolute value of a function. It can be also implemented as a Piecewise function.
|
583
|
+
class Abs < CAS::Op
|
584
|
+
# Performs the absolute value of a `CAS::Op`
|
585
|
+
#
|
586
|
+
# ```
|
587
|
+
# d
|
588
|
+
# ---- |f(x)| = f'(x) * (f(x) / |f(x)|)
|
589
|
+
# dx
|
590
|
+
# ```
|
591
|
+
#
|
592
|
+
# * **argument**: `CAS::Op` argument of derivative
|
593
|
+
# * **returns**: `CAS::Op` derivative
|
594
|
+
def diff(v)
|
595
|
+
if @x.depend? v
|
596
|
+
return @x.diff(x) * (@x/CAS.abs(@x))
|
597
|
+
else
|
598
|
+
return CAS::Zero
|
599
|
+
end
|
600
|
+
end
|
601
|
+
|
602
|
+
# Call resolves the operation tree in a `Numeric` (if `Fixnum`)
|
603
|
+
# or `Float` (depends upon promotions).
|
604
|
+
# As input, it requires an hash with `CAS::Variable` or `CAS::Variable#name`
|
605
|
+
# as keys, and a `Numeric` as a value. In this case it will call
|
606
|
+
# the `Fixnum#overloaded_plus`, that is the old plus function.
|
607
|
+
#
|
608
|
+
# * **argument**: `Hash` with feed dictionary
|
609
|
+
# * **returns**: `Numeric`
|
610
|
+
def call(f)
|
611
|
+
CAS::Help.assert(f, Hash)
|
612
|
+
|
613
|
+
s = (@x.call(f) >= 0 ? 1 : -1)
|
614
|
+
return s * @x.call(f)
|
615
|
+
end
|
616
|
+
|
617
|
+
# Convert expression to string
|
618
|
+
#
|
619
|
+
# * **returns**: `String` to print on screen
|
620
|
+
def to_s
|
621
|
+
"|#{@x}|"
|
622
|
+
end
|
623
|
+
|
624
|
+
# Same as `CAS::Op`
|
625
|
+
#
|
626
|
+
# Simplifcation engine supports:
|
627
|
+
#
|
628
|
+
# * |-x| = x
|
629
|
+
# * |0| = 0
|
630
|
+
#
|
631
|
+
# * **returns**: `CAS::Op` simplified version
|
632
|
+
def simplify
|
633
|
+
super
|
634
|
+
return CAS.abs(@x.x) if @x.is_a? CAS::Invert
|
635
|
+
return self.simplify_dictionary
|
636
|
+
end
|
637
|
+
|
638
|
+
def self.init_simplify_dict
|
639
|
+
@simplify_dict = {
|
640
|
+
CAS::Zero => CAS::Zero
|
641
|
+
}
|
642
|
+
end
|
643
|
+
|
644
|
+
# Convert expression to code (internal, for `CAS::Op#to_proc` method)
|
645
|
+
#
|
646
|
+
# * **returns**: `String` that represent Ruby code to be parsed in `CAS::Op#to_proc`
|
647
|
+
def to_code
|
648
|
+
"(#{@x.to_code}).abs"
|
649
|
+
end
|
650
|
+
end # Abs
|
651
|
+
CAS::Abs.init_simplify_dict
|
652
|
+
|
653
|
+
# Shortcut for `CAs::Abs` initializer
|
654
|
+
#
|
655
|
+
# * **argument**: `CAs::Op` argument of absolute value
|
656
|
+
# * **returns**: `CAS::Abs` new instance
|
657
|
+
def self.abs(x)
|
658
|
+
CAS::Abs.new x
|
659
|
+
end
|
660
|
+
end
|