ragni-cas 0.2.5 → 0.2.6
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.tar.gz.sig +1 -2
- data/lib/{ragni-cas.rb → Mr.CAS.rb} +3 -2
- data/lib/Mr.CAS/auto-diff.rb +129 -0
- data/lib/Mr.CAS/c-opt.rb +225 -0
- data/lib/Mr.CAS/c.rb +126 -0
- data/lib/{ragni-cas/plugins → Mr.CAS}/graphviz.rb +0 -0
- data/lib/{ragni-cas/plugins → Mr.CAS}/latex.rb +0 -0
- data/lib/Mr.CAS/matlab.rb +81 -0
- data/lib/functions/fnc-base.rb +1 -157
- data/lib/functions/fnc-prod.rb +102 -0
- data/lib/functions/fnc-sum.rb +151 -0
- data/lib/numbers/functions.rb +27 -18
- data/lib/operators/bary-op.rb +14 -13
- data/lib/operators/nary-op.rb +66 -7
- data/lib/operators/op.rb +8 -7
- data/lib/version.rb +1 -2
- metadata +13 -7
- metadata.gz.sig +0 -0
data/lib/numbers/functions.rb
CHANGED
@@ -61,9 +61,9 @@ module CAS
|
|
61
61
|
xs.flatten!
|
62
62
|
CAS::Help.assert_name name
|
63
63
|
xs.each do |x|
|
64
|
-
CAS::Help.assert x, CAS::
|
64
|
+
CAS::Help.assert x, CAS::Op
|
65
65
|
end
|
66
|
-
raise CASError, "Function #{name} already exists" if CAS::Function.exist? name
|
66
|
+
# raise CASError, "Function #{name} already exists" if CAS::Function.exist? name
|
67
67
|
|
68
68
|
@x = xs.uniq
|
69
69
|
@name = name
|
@@ -78,19 +78,31 @@ module CAS
|
|
78
78
|
def Function.new(name, *xs)
|
79
79
|
xs.flatten!
|
80
80
|
if @@container[name]
|
81
|
-
return @@container[name] if (@@container[name].
|
81
|
+
# return @@container[name] if (@@container[name].x.uniq - xs.uniq == [] or xs.size == 0)
|
82
|
+
return @@container[name] if (@@container[name].x.uniq.map(&:to_s).sort == xs.uniq.map(&:to_s).sort or xs.size == 0)
|
82
83
|
raise CASError, "Function #{name} already defined with different arguments!"
|
83
84
|
end
|
84
85
|
super
|
85
86
|
end
|
86
87
|
|
87
88
|
# Returns an array containing `CAS::Variable`s argument of the function
|
89
|
+
# Plese note that sub Op will return their args.
|
88
90
|
#
|
89
|
-
# * **returns**: `Array` containing `CAs
|
91
|
+
# * **returns**: `Array` containing `CAs::Variable`
|
90
92
|
def args
|
91
|
-
|
93
|
+
ret = []
|
94
|
+
@x.each do |e|
|
95
|
+
ret << e.args
|
96
|
+
end
|
97
|
+
ret.flatten.uniq
|
92
98
|
end
|
93
99
|
|
100
|
+
# Get an element in a particular position of the argument
|
101
|
+
#
|
102
|
+
# * **requires**: an iterator
|
103
|
+
# * **returns**: element of the argument `CAS::Op` or `NilClass`
|
104
|
+
def [](i); @x[i]; end
|
105
|
+
|
94
106
|
# Simplifications cannot be performed on anonymous function, thus it will always return
|
95
107
|
# the `self` `CAS::Function` object
|
96
108
|
#
|
@@ -117,14 +129,7 @@ module CAS
|
|
117
129
|
# * **returns**: a `CAS::Function` with modified argument list
|
118
130
|
# * **raises**: `CASError` if something different with resppect to a `CAS::Variable` is a active substitution
|
119
131
|
def subs(s)
|
120
|
-
|
121
|
-
next unless self.depend? k
|
122
|
-
if v.is_a? CAS::Variable
|
123
|
-
(@x.collect! { |e| (e == k) ? v : e }).uniq!
|
124
|
-
next
|
125
|
-
end
|
126
|
-
raise CASError, "Cannot perform a substitution in #{self.class}"
|
127
|
-
end
|
132
|
+
@x.each { |e| e.subs(s) }
|
128
133
|
self
|
129
134
|
end
|
130
135
|
|
@@ -134,11 +139,15 @@ module CAS
|
|
134
139
|
# * **requires**: a `CAS::Variable` for derivative
|
135
140
|
# * **returns**: the `CAS::Variable` derivated function
|
136
141
|
def diff(v)
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
142
|
+
# return CAS.declare :"d#{@name}[#{v}]", @x
|
143
|
+
ret = []
|
144
|
+
@x.each_with_index do |x, k|
|
145
|
+
dx = (x.depend?(v) ? x.diff(v) : CAS::Zero)
|
146
|
+
dfx = CAS.declare :"D#{@name}[#{k}]", @x
|
147
|
+
ret << dx * dfx
|
141
148
|
end
|
149
|
+
return CAS::Zero if ret == []
|
150
|
+
return ret.inject { |d, e| d += e }
|
142
151
|
end
|
143
152
|
|
144
153
|
# Trying to call a `CAS::Function` will always return a `CAS::Error`
|
@@ -166,7 +175,7 @@ module CAS
|
|
166
175
|
# * **returns**: `TrueClass` if functions are equal, `FalseClass` if not equal
|
167
176
|
def ==(op)
|
168
177
|
return false if not self.class == op.class
|
169
|
-
return false if not (@name == op.name and @x == op.
|
178
|
+
return false if not (@name == op.name and @x.uniq == op.x.uniq)
|
170
179
|
true
|
171
180
|
end
|
172
181
|
end # Function
|
data/lib/operators/bary-op.rb
CHANGED
@@ -79,14 +79,14 @@ module CAS
|
|
79
79
|
# * **returns**: `CAS::BinaryOp`, in practice `self`
|
80
80
|
def subs_lhs(dt)
|
81
81
|
CAS::Help.assert(dt, Hash)
|
82
|
-
|
83
|
-
if
|
84
|
-
if dt[
|
85
|
-
@x = dt[
|
86
|
-
elsif dt[
|
87
|
-
@x = CAS::const dt[
|
82
|
+
sub = dt.keys.select { |e| e == @x }[0]
|
83
|
+
if sub
|
84
|
+
if dt[sub].is_a? CAS::Op
|
85
|
+
@x = dt[sub]
|
86
|
+
elsif dt[sub].is_a? Numeric
|
87
|
+
@x = CAS::const dt[sub]
|
88
88
|
else
|
89
|
-
raise CASError, "Impossible subs. Received a #{dt[
|
89
|
+
raise CASError, "Impossible subs. Received a #{dt[sub].class} = #{dt[sub]}"
|
90
90
|
end
|
91
91
|
else
|
92
92
|
@x.subs(dt)
|
@@ -100,13 +100,14 @@ module CAS
|
|
100
100
|
# * **returns**: `CAS::BinaryOp`, in practice `self`
|
101
101
|
def subs_rhs(dt)
|
102
102
|
CAS::Help.assert(dt, Hash)
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
103
|
+
sub = dt.keys.select { |e| e == @y }[0]
|
104
|
+
if sub
|
105
|
+
if dt[sub].is_a? CAS::Op
|
106
|
+
@y = dt[sub]
|
107
|
+
elsif dt[sub].is_a? Numeric
|
108
|
+
@y = CAS::const dt[sub]
|
108
109
|
else
|
109
|
-
raise CASError, "Impossible subs. Received a #{dt[
|
110
|
+
raise CASError, "Impossible subs. Received a #{dt[sub].class} = #{dt[sub]}"
|
110
111
|
end
|
111
112
|
else
|
112
113
|
@y.subs(dt)
|
data/lib/operators/nary-op.rb
CHANGED
@@ -17,7 +17,7 @@ module CAS
|
|
17
17
|
# * **returns**: `CAS::NaryOp` instance
|
18
18
|
def initialize(*xs)
|
19
19
|
@x = []
|
20
|
-
xs.each do |x|
|
20
|
+
xs.flatten.each do |x|
|
21
21
|
if x.is_a? Numeric
|
22
22
|
x = Op.numeric_to_const x
|
23
23
|
end
|
@@ -93,14 +93,16 @@ module CAS
|
|
93
93
|
# * **returns**: `CAS::NaryOp` (`self`) with substitution performed
|
94
94
|
def subs(dt)
|
95
95
|
CAS::Help.assert(dt, Hash)
|
96
|
+
@x = @x.map { |z| z.subs(dt) || z }
|
96
97
|
@x.each_with_index do |x, k|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
98
|
+
sub = dt.keys.select { |e| e == x }[0]
|
99
|
+
if sub
|
100
|
+
if dt[sub].is_a? CAS::Op
|
101
|
+
@x[k] = dt[sub]
|
102
|
+
elsif dt[sub].is_a? Numeric
|
103
|
+
@x[k] = CAS::const dt[sub]
|
102
104
|
else
|
103
|
-
raise CAS::CASError, "Impossible subs. Received a #{dt[
|
105
|
+
raise CAS::CASError, "Impossible subs. Received a #{dt[sub].class} = #{dt[sub]}"
|
104
106
|
end
|
105
107
|
end
|
106
108
|
end
|
@@ -168,6 +170,63 @@ module CAS
|
|
168
170
|
@x.each { |x| r += x.args }
|
169
171
|
return r.uniq
|
170
172
|
end
|
173
|
+
|
174
|
+
# Reduce multeplicity will scan for elements that are equal in the definition
|
175
|
+
# of the sum and will reduce their multeplicity. A block can be used to do something
|
176
|
+
# different. For example in nary-product we use it like this:
|
177
|
+
#
|
178
|
+
# ``` ruby
|
179
|
+
# @x = self.__reduce_multeplicity(@x) do |count, op|
|
180
|
+
# count > 1 ? (op ** count) : op
|
181
|
+
# end
|
182
|
+
# ```
|
183
|
+
#
|
184
|
+
# In general it works like that:
|
185
|
+
#
|
186
|
+
# ```
|
187
|
+
# a + a + b + c => 2 * a + b + c
|
188
|
+
# a * a * b * a => (a ** b) * b
|
189
|
+
# ```
|
190
|
+
# But operates only on Array level! This is an internal function
|
191
|
+
# and should never be used
|
192
|
+
#
|
193
|
+
# * **requires**: An `Array`
|
194
|
+
# * **returns**: An `Array` with multeplicity reduced
|
195
|
+
# * **block**: yields the count and the op. Get the value to insert in a new
|
196
|
+
# `Array` that is the returned `Array`
|
197
|
+
def __reduce_multeplicity(xs)
|
198
|
+
count = Hash.new(0)
|
199
|
+
xs.each do |x|
|
200
|
+
e = x
|
201
|
+
count.keys.each { |d| e = d if x == d }
|
202
|
+
count[e] += 1
|
203
|
+
end
|
204
|
+
count.map do |k, v|
|
205
|
+
if block_given?
|
206
|
+
yield(k, v)
|
207
|
+
else
|
208
|
+
v > 1 ? CAS.const(v) * k : k
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
# Collects all the constants and tries to reduce them to a single constant.
|
214
|
+
# Requires a block to understand what it should do with the constants
|
215
|
+
#
|
216
|
+
# * **requires**: input `Array` of `CAS::Op`
|
217
|
+
# * **returns**: new `Array` of `CAS::Op`
|
218
|
+
# * **block**: yields an `Array` of `CAS::Constant` and an `Array` of others `CAS::Op`,
|
219
|
+
# requires an `Array` back
|
220
|
+
def __reduce_constants(xs)
|
221
|
+
const = []
|
222
|
+
xs.each { |x| const << x if x.is_a? CAS::Constant }
|
223
|
+
if const.size > 0
|
224
|
+
yield const, (xs - const)
|
225
|
+
else
|
226
|
+
xs
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
171
230
|
end # NaryOp
|
172
231
|
CAS::NaryOp.init_simplify_dict
|
173
232
|
end
|
data/lib/operators/op.rb
CHANGED
@@ -107,11 +107,12 @@ module CAS
|
|
107
107
|
# * **returns**: `CAS::Op` (`self`) with substitution performed
|
108
108
|
def subs(dt)
|
109
109
|
CAS::Help.assert(dt, Hash)
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
110
|
+
sub = dt.keys.select { |e| e == @x }[0]
|
111
|
+
if sub
|
112
|
+
if dt[sub].is_a? CAS::Op
|
113
|
+
@x = dt[sub]
|
114
|
+
elsif dt[sub].is_a? Numeric
|
115
|
+
@x = CAS::const dt[sub]
|
115
116
|
else
|
116
117
|
raise CAS::CASError, "Impossible subs. Received a #{dt[@x].class} = #{dt[@x]}"
|
117
118
|
end
|
@@ -140,7 +141,7 @@ module CAS
|
|
140
141
|
# * **argument**: `CAS::Op` tree
|
141
142
|
# * **returns**: `CAS::Op` new object
|
142
143
|
def +(op)
|
143
|
-
CAS::Sum.new self, op
|
144
|
+
CAS::Sum.new [self, op]
|
144
145
|
end
|
145
146
|
|
146
147
|
# Returns a difference of two `CAS::Op`s
|
@@ -156,7 +157,7 @@ module CAS
|
|
156
157
|
# * **argument**: `CAS::Op` tree
|
157
158
|
# * **returns**: `CAS::Op` new object
|
158
159
|
def *(op)
|
159
|
-
CAS::Prod.new self, op
|
160
|
+
CAS::Prod.new [self, op]
|
160
161
|
end
|
161
162
|
|
162
163
|
# Returns a division of two `CAS::Op`s
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ragni-cas
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matteo Ragni
|
@@ -29,7 +29,7 @@ cert_chain:
|
|
29
29
|
XorZtzkkLImvKFj35xKLFfVkv0Vd8tGQoiL8vdmQNJjAjtE+C+Y7OI4dpiZPKO4G
|
30
30
|
R/8JOvUuk9jPbyLxjQH/sFaFqqYGX2xo1zk2CRy/A0WhJrSaXVw1r5lEi7b0W5gg
|
31
31
|
-----END CERTIFICATE-----
|
32
|
-
date: 2016-
|
32
|
+
date: 2016-11-28 00:00:00.000000000 Z
|
33
33
|
dependencies: []
|
34
34
|
description:
|
35
35
|
email: info@ragni.me
|
@@ -37,10 +37,19 @@ executables: []
|
|
37
37
|
extensions: []
|
38
38
|
extra_rdoc_files: []
|
39
39
|
files:
|
40
|
+
- lib/Mr.CAS.rb
|
41
|
+
- lib/Mr.CAS/auto-diff.rb
|
42
|
+
- lib/Mr.CAS/c-opt.rb
|
43
|
+
- lib/Mr.CAS/c.rb
|
44
|
+
- lib/Mr.CAS/graphviz.rb
|
45
|
+
- lib/Mr.CAS/latex.rb
|
46
|
+
- lib/Mr.CAS/matlab.rb
|
40
47
|
- lib/functions/fnc-base.rb
|
41
48
|
- lib/functions/fnc-box-conditions.rb
|
42
49
|
- lib/functions/fnc-conditions.rb
|
43
50
|
- lib/functions/fnc-piecewise.rb
|
51
|
+
- lib/functions/fnc-prod.rb
|
52
|
+
- lib/functions/fnc-sum.rb
|
44
53
|
- lib/functions/fnc-trig.rb
|
45
54
|
- lib/functions/fnc-trsc.rb
|
46
55
|
- lib/numbers/constants.rb
|
@@ -51,9 +60,6 @@ files:
|
|
51
60
|
- lib/operators/op.rb
|
52
61
|
- lib/overloading/fixnum.rb
|
53
62
|
- lib/overloading/float.rb
|
54
|
-
- lib/ragni-cas.rb
|
55
|
-
- lib/ragni-cas/plugins/graphviz.rb
|
56
|
-
- lib/ragni-cas/plugins/latex.rb
|
57
63
|
- lib/version.rb
|
58
64
|
homepage: https://github.com/MatteoRagni/cas-rb
|
59
65
|
licenses:
|
@@ -75,8 +81,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
81
|
version: '0'
|
76
82
|
requirements: []
|
77
83
|
rubyforge_project:
|
78
|
-
rubygems_version: 2.5.
|
84
|
+
rubygems_version: 2.5.2
|
79
85
|
signing_key:
|
80
86
|
specification_version: 4
|
81
|
-
summary:
|
87
|
+
summary: 'THIS IS OUTDATED! PLEASE CHECK: https://rubygems.org/gems/Mr.CAS'
|
82
88
|
test_files: []
|
metadata.gz.sig
CHANGED
Binary file
|