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
data/lib/operators/op.rb
ADDED
@@ -0,0 +1,285 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module CAS
|
4
|
+
class CASError < RuntimeError; end
|
5
|
+
|
6
|
+
# ___
|
7
|
+
# / _ \ _ __
|
8
|
+
# | (_) | '_ \
|
9
|
+
# \___/| .__/
|
10
|
+
# |_|
|
11
|
+
class Op
|
12
|
+
# Argument of the operation
|
13
|
+
attr_reader :x
|
14
|
+
|
15
|
+
# Initialize a new empty operation container. This is a virtual
|
16
|
+
# class and the other must inherit from this basic container.
|
17
|
+
# Some methods raise a `CAS::CASError` if called.
|
18
|
+
# The input element is a Numric, to create a constant.
|
19
|
+
# `CAS::Op` specifies operations with a single variable
|
20
|
+
#
|
21
|
+
# * **argument**: `Numeric` to be converted in `CAS::Constant` or `CAS::Op` child operation
|
22
|
+
# * **returns**: `CAS::Op` instance
|
23
|
+
def initialize(x)
|
24
|
+
if x.is_a? Numeric
|
25
|
+
x = Op.numeric_to_const x
|
26
|
+
end
|
27
|
+
CAS::Help.assert(x, CAS::Op)
|
28
|
+
|
29
|
+
@x = x
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.numeric_to_const(x)
|
33
|
+
if CAS::NumericToConst[x]
|
34
|
+
return CAS::NumericToConst[x]
|
35
|
+
else
|
36
|
+
return CAS::const x
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Return the dependencies of the operation. Requires a `CAS::Variable`
|
41
|
+
# and it is one of the recursve method (implicit tree resolution)
|
42
|
+
#
|
43
|
+
# * **argument**: `CAS::Variable` instance
|
44
|
+
# * **returns**: `TrueClass` if depends, `FalseClass` if not
|
45
|
+
def depend?(v)
|
46
|
+
CAS::Help.assert(v, CAS::Op)
|
47
|
+
|
48
|
+
@x.depend? v
|
49
|
+
end
|
50
|
+
|
51
|
+
# Return the derivative of the operation using the chain rule
|
52
|
+
# The input is a `CAS::Op` because it can handle derivatives
|
53
|
+
# with respect to functions. E.g.:
|
54
|
+
#
|
55
|
+
# ```
|
56
|
+
# f(x) = (ln(x))**2
|
57
|
+
# g(x) = ln(x)
|
58
|
+
#
|
59
|
+
# d f(x)
|
60
|
+
# ------ = 2 ln(x)
|
61
|
+
# d g(x)
|
62
|
+
# ```
|
63
|
+
#
|
64
|
+
# * **argument**: `CAS::Op` object of the derivative
|
65
|
+
# * **returns**: `CAS::Op` a derivated object, or `CAS::Zero` for constants
|
66
|
+
def diff(v)
|
67
|
+
CAS::Help.assert(v, CAS::Op)
|
68
|
+
|
69
|
+
if @x.depend? v
|
70
|
+
return @x.diff(v)
|
71
|
+
end
|
72
|
+
CAS::Zero
|
73
|
+
end
|
74
|
+
|
75
|
+
# Call resolves the operation tree in a `Numeric` (if `Fixnum`)
|
76
|
+
# or `Float` (depends upon promotions).
|
77
|
+
# As input, it requires an hash with `CAS::Variable` or `CAS::Variable#name`
|
78
|
+
# as keys, and a `Numeric` as a value
|
79
|
+
#
|
80
|
+
# ``` ruby
|
81
|
+
# x, y = CAS::vars :x, :y
|
82
|
+
# f = (x ** 2) + (y ** 2)
|
83
|
+
# f.call({x => 1, y => 2})
|
84
|
+
# # => 2
|
85
|
+
# ```
|
86
|
+
#
|
87
|
+
# * **argument**: `Hash` with feed dictionary
|
88
|
+
# * **returns**: `Numeric`
|
89
|
+
def call(f)
|
90
|
+
CAS::Help.assert(f, Hash)
|
91
|
+
|
92
|
+
@x.call(f)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Perform substitution of a part of the graph using a data table:
|
96
|
+
#
|
97
|
+
# ``` ruby
|
98
|
+
# x, y = CAS::vars :x, :y
|
99
|
+
# f = (x ** 2) + (y ** 2)
|
100
|
+
# puts f
|
101
|
+
# # => (x^2) + (y^2)
|
102
|
+
# puts f.subs({x => CAS::ln(y)})
|
103
|
+
# # => (ln(y)^2) + (y^2)
|
104
|
+
# ```
|
105
|
+
#
|
106
|
+
# * **argument**: `Hash` with substitution table
|
107
|
+
# * **returns**: `CAS::Op` (`self`) with substitution performed
|
108
|
+
def subs(dt)
|
109
|
+
CAS::Help.assert(dt, Hash)
|
110
|
+
if dt.keys.include? @x
|
111
|
+
if dt[@x].is_a? CAS::Op
|
112
|
+
@x = dt[@x]
|
113
|
+
elsif dt[@x].is_a? Numeric
|
114
|
+
@x = CAS::const dt[@x]
|
115
|
+
else
|
116
|
+
raise CAS::CASError, "Impossible subs. Received a #{dt[@x].class} = #{dt[@x]}"
|
117
|
+
end
|
118
|
+
else
|
119
|
+
@x.subs(dt)
|
120
|
+
end
|
121
|
+
return self
|
122
|
+
end
|
123
|
+
|
124
|
+
# Convert expression to string
|
125
|
+
#
|
126
|
+
# * **returns**: `String` to print on screen
|
127
|
+
def to_s
|
128
|
+
"#{@x}"
|
129
|
+
end
|
130
|
+
|
131
|
+
# Convert expression to code (internal, for `CAS::Op#to_proc` method)
|
132
|
+
#
|
133
|
+
# * **returns**: `String` that represent Ruby code to be parsed in `CAS::Op#to_proc`
|
134
|
+
def to_code
|
135
|
+
"#{@x}"
|
136
|
+
end
|
137
|
+
|
138
|
+
# Returns a sum of two `CAS::Op`s
|
139
|
+
#
|
140
|
+
# * **argument**: `CAS::Op` tree
|
141
|
+
# * **returns**: `CAS::Op` new object
|
142
|
+
def +(op)
|
143
|
+
CAS::Sum.new self, op
|
144
|
+
end
|
145
|
+
|
146
|
+
# Returns a difference of two `CAS::Op`s
|
147
|
+
#
|
148
|
+
# * **argument**: `CAS::Op` tree
|
149
|
+
# * **returns**: `CAS::Op` new object
|
150
|
+
def -(op)
|
151
|
+
CAS::Diff.new self, op
|
152
|
+
end
|
153
|
+
|
154
|
+
# Returns a product of two `CAS::Op`s
|
155
|
+
#
|
156
|
+
# * **argument**: `CAS::Op` tree
|
157
|
+
# * **returns**: `CAS::Op` new object
|
158
|
+
def *(op)
|
159
|
+
CAS::Prod.new self, op
|
160
|
+
end
|
161
|
+
|
162
|
+
# Returns a division of two `CAS::Op`s
|
163
|
+
#
|
164
|
+
# * **argument**: `CAS::Op` tree
|
165
|
+
# * **returns**: `CAS::Op` new object
|
166
|
+
def /(op)
|
167
|
+
CAS::Div.new self, op
|
168
|
+
end
|
169
|
+
|
170
|
+
# Returns the power of two `CAS::Op`s
|
171
|
+
#
|
172
|
+
# * **argument**: `CAS::Op` tree
|
173
|
+
# * **returns**: `CAS::Op` new object
|
174
|
+
def **(op)
|
175
|
+
CAS.pow(self, op)
|
176
|
+
end
|
177
|
+
|
178
|
+
# Unary operator for inversion of a `CAS::Op`
|
179
|
+
#
|
180
|
+
# * **returns**: `CAS::Op` new object
|
181
|
+
def -@
|
182
|
+
CAS.invert(self)
|
183
|
+
end
|
184
|
+
|
185
|
+
# Simplification callback. It simplify the subgraph of each node
|
186
|
+
# until all possible simplification are performed (thus the execution
|
187
|
+
# time is not deterministic).
|
188
|
+
#
|
189
|
+
# * **returns**: `CAS::Op` simplified version
|
190
|
+
def simplify
|
191
|
+
hash = @x.to_s
|
192
|
+
@x = @x.simplify
|
193
|
+
while @x.to_s != hash
|
194
|
+
hash = @x.to_s
|
195
|
+
@x = @x.simplify
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# Simplify dictionary performs a dictionary simplification
|
200
|
+
# that is the class variable `@@simplify_dict`
|
201
|
+
#
|
202
|
+
# * **returns**: `CAS::Op` self
|
203
|
+
def simplify_dictionary
|
204
|
+
if self.class.simplify_dict(@x)
|
205
|
+
return self.class.simplify_dict(@x)
|
206
|
+
else
|
207
|
+
return self
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# Initializes the simplification dictionary (one for each class)
|
212
|
+
#
|
213
|
+
# * **returns**: `Hash` with simplification dictionary
|
214
|
+
def self.init_simplify_dict
|
215
|
+
@simplify_dict = { }
|
216
|
+
end
|
217
|
+
|
218
|
+
# Returns an element of a
|
219
|
+
def self.simplify_dict(k)
|
220
|
+
@simplify_dict[k]
|
221
|
+
end
|
222
|
+
|
223
|
+
# Inspector for the current object
|
224
|
+
#
|
225
|
+
# * **returns**: `String`
|
226
|
+
def inspect
|
227
|
+
"#{self.class}(#{@x.inspect})"
|
228
|
+
end
|
229
|
+
|
230
|
+
# Equality operator, the standard operator is overloaded
|
231
|
+
# :warning: this operates on the graph, not on the math
|
232
|
+
# See `CAS::equal`, etc.
|
233
|
+
#
|
234
|
+
# * **argument**: `CAS::Op` to be tested against
|
235
|
+
# * **returns**: `TrueClass` if equal, `FalseClass` if differs
|
236
|
+
def ==(op)
|
237
|
+
# CAS::Help.assert(op, CAS::Op)
|
238
|
+
if op.is_a? CAS::Op
|
239
|
+
return false if op.is_a? CAS::BinaryOp
|
240
|
+
return (self.class == op.class and @x == op.x)
|
241
|
+
end
|
242
|
+
false
|
243
|
+
end
|
244
|
+
|
245
|
+
# Disequality operator, the standard operator is overloaded
|
246
|
+
# :warning: this operates on the graph, not on the math
|
247
|
+
# See `CAS::equal`, etc.
|
248
|
+
#
|
249
|
+
# * **argument**: `CAS::Op` to be tested against
|
250
|
+
# * **returns**: `FalseClass` if equal, `TrueClass` if differs
|
251
|
+
def !=(op)
|
252
|
+
not self.==(op)
|
253
|
+
end
|
254
|
+
|
255
|
+
# Evaluates the proc against a given context. It is like having a
|
256
|
+
# snapshot of the tree transformed in a callable object.
|
257
|
+
# Obviously **if the tree changes, the generated proc does notchanges**.
|
258
|
+
# The proc takes as input a feed dictionary in which each variable
|
259
|
+
# is identified through the `CAS::Variable#name` key.
|
260
|
+
#
|
261
|
+
# The proc is evaluated in the context devined by the input `Binding` object
|
262
|
+
# If `nil` is passed, the `eval` will run in this local context
|
263
|
+
#
|
264
|
+
# * **argument**: `Binding` or `NilClass` that is the context of the Ruby VM
|
265
|
+
# * **returns**: `Proc` object with a single argument as an `Hash`
|
266
|
+
def as_proc(bind=nil)
|
267
|
+
args_ext = self.args.map { |e| "#{e} = fd[\"#{e}\"];" }
|
268
|
+
code = "Proc.new do |fd|; #{args_ext.join " "} #{self.to_code}; end"
|
269
|
+
if bind # All objects have eval value, we bind when not nil
|
270
|
+
# CAS::Help.assert(bind, Binding)
|
271
|
+
bind.eval(code)
|
272
|
+
else
|
273
|
+
eval(code)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
# Returns a list of all `CAS::Variable`s of the current tree
|
278
|
+
#
|
279
|
+
# * **returns**: `Array` of `CAS::Variable`s
|
280
|
+
def args
|
281
|
+
@x.args.uniq
|
282
|
+
end
|
283
|
+
end # Op
|
284
|
+
CAS::Op.init_simplify_dict
|
285
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
##
|
4
|
+
# Overloading operators for Fixnum. Operations that are
|
5
|
+
# oveloaded are:
|
6
|
+
#
|
7
|
+
# * `overloaded_plus` for `+`
|
8
|
+
# * `overloaded_minus` for `-`
|
9
|
+
# * `overloaded_mul` for `*`
|
10
|
+
# * `overloaded_div` for `/`
|
11
|
+
# * `overloaded_pow` for `**`
|
12
|
+
class Fixnum
|
13
|
+
# Setting aliases
|
14
|
+
alias :overloaded_plus :+
|
15
|
+
alias :overloaded_minus :-
|
16
|
+
alias :overloaded_mul :*
|
17
|
+
alias :overloaded_div :/
|
18
|
+
alias :overloaded_pow :**
|
19
|
+
alias :dot_graph :to_s
|
20
|
+
|
21
|
+
##
|
22
|
+
# If `a` is a `CAS::Op` transform self in a `CAS::Const`
|
23
|
+
# and return a symbolic operation.
|
24
|
+
# If
|
25
|
+
def +(a)
|
26
|
+
return (CAS::const(self) + a) if a.is_a? CAS::Op
|
27
|
+
self.overloaded_plus a
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# If `a` is a `CAS::Op` transform self in a `CAS::Const`
|
32
|
+
# and return a symbolic operation
|
33
|
+
def -(a)
|
34
|
+
return (CAS::const(self) - a) if a.is_a? CAS::Op
|
35
|
+
self.overloaded_minus a
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# If `a` is a `CAS::Op` transform self in a `CAS::Const`
|
40
|
+
# and return a symbolic operation
|
41
|
+
def *(a)
|
42
|
+
return (CAS::const(self) * a) if a.is_a? CAS::Op
|
43
|
+
self.overloaded_mul a
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# If `a` is a `CAS::Op` transform self in a `CAS::Const`
|
48
|
+
# and return a symbolic operation
|
49
|
+
def /(a)
|
50
|
+
return (CAS::const(self) / a) if a.is_a? CAS::Op
|
51
|
+
self.overloaded_div a
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# If `a` is a `CAS::Op` transform self in a `CAS::Const`
|
56
|
+
# and return a symbolic operation
|
57
|
+
def **(a)
|
58
|
+
return (CAS::const(self) ** a) if a.is_a? CAS::Op
|
59
|
+
self.overloaded_pow a
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
##
|
4
|
+
# Overloading operators for Float. Operations that are
|
5
|
+
# oveloaded are:
|
6
|
+
#
|
7
|
+
# * `overloaded_plus` for `+`
|
8
|
+
# * `overloaded_minus` for `-`
|
9
|
+
# * `overloaded_mul` for `*`
|
10
|
+
# * `overloaded_div` for `/`
|
11
|
+
# * `overloaded_pow` for `**`
|
12
|
+
class Float
|
13
|
+
# Setting aliases
|
14
|
+
alias :overloaded_plus :+
|
15
|
+
alias :overloaded_minus :-
|
16
|
+
alias :overloaded_mul :*
|
17
|
+
alias :overloaded_div :/
|
18
|
+
alias :overloaded_pow :**
|
19
|
+
alias :dot_graph :to_s
|
20
|
+
|
21
|
+
##
|
22
|
+
# If `a` is a `CAS::Op` transform self in a `CAS::Const`
|
23
|
+
# and return a symbolic operation.
|
24
|
+
# If
|
25
|
+
def +(a)
|
26
|
+
return (CAS::const(self) + a) if a.is_a? CAS::Op
|
27
|
+
self.overloaded_plus a
|
28
|
+
end
|
29
|
+
|
30
|
+
##
|
31
|
+
# If `a` is a `CAS::Op` transform self in a `CAS::Const`
|
32
|
+
# and return a symbolic operation
|
33
|
+
def -(a)
|
34
|
+
return (CAS::const(self) - a) if a.is_a? CAS::Op
|
35
|
+
self.overloaded_minus a
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# If `a` is a `CAS::Op` transform self in a `CAS::Const`
|
40
|
+
# and return a symbolic operation
|
41
|
+
def *(a)
|
42
|
+
return (CAS::const(self) * a) if a.is_a? CAS::Op
|
43
|
+
self.overloaded_mul a
|
44
|
+
end
|
45
|
+
|
46
|
+
##
|
47
|
+
# If `a` is a `CAS::Op` transform self in a `CAS::Const`
|
48
|
+
# and return a symbolic operation
|
49
|
+
def /(a)
|
50
|
+
return (CAS::const(self) / a) if a.is_a? CAS::Op
|
51
|
+
self.overloaded_div a
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# If `a` is a `CAS::Op` transform self in a `CAS::Const`
|
56
|
+
# and return a symbolic operation
|
57
|
+
def **(a)
|
58
|
+
return (CAS::const(self) ** a) if a.is_a? CAS::Op
|
59
|
+
self.overloaded_pow a
|
60
|
+
end
|
61
|
+
end
|
data/lib/ragni-cas.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
##
|
3
4
|
# ragni-cas
|
4
5
|
# A very simple CAS engine with encapsuled graph
|
5
6
|
# representation. This will make impossible to
|
@@ -20,206 +21,41 @@
|
|
20
21
|
#
|
21
22
|
# Author:: Matteo Ragni (mailto:info@ragni.me)
|
22
23
|
# Copyright:: Copyright (c) 2016 Matteo Ragni
|
23
|
-
# License:: Distributed under MIT license
|
24
|
-
|
25
|
-
# ___ _
|
26
|
-
# | _ \___ __ _ _ _(_)_ _ ___ ___
|
27
|
-
# | / -_) _` | || | | '_/ -_|_-<
|
28
|
-
# |_|_\___\__, |\_,_|_|_| \___/__/
|
29
|
-
# |_|
|
30
|
-
|
31
|
-
%w|op.rb numbers.rb fnc-base.rb fnc-trig.rb fnc-trsc.rb fnc-branch.rb version.rb|.each do |r|
|
32
|
-
require File.expand_path(r, File.dirname(__FILE__))
|
33
|
-
end
|
34
|
-
|
24
|
+
# License:: Distributed under MIT license terms
|
35
25
|
module CAS
|
36
26
|
|
37
|
-
# Return a string representation of the graph that is
|
38
|
-
# a Graphviz tree. Requires a `CAS::Op` as argument.
|
39
|
-
# In the next releases probably it will be moved inside
|
40
|
-
# `CAS::Op`.
|
41
|
-
# <- `CAS::Op` instance
|
42
|
-
# -> `String`
|
43
|
-
def self.to_dot(op)
|
44
|
-
CAS::Help.assert(op, CAS::Op)
|
45
|
-
|
46
|
-
node = {}
|
47
|
-
string = op.dot_graph(node)
|
48
|
-
labels = ""
|
49
|
-
lab = {}
|
50
|
-
|
51
|
-
string.scan(/\w+\_\d+/) do |m|
|
52
|
-
if m =~ /(\w+)\_\d+/
|
53
|
-
case $1
|
54
|
-
when "Sum"
|
55
|
-
l = "+"
|
56
|
-
when "Diff"
|
57
|
-
l = "-"
|
58
|
-
when "Prod"
|
59
|
-
l = "×"
|
60
|
-
when "Div"
|
61
|
-
l = "÷"
|
62
|
-
when "Sqrt"
|
63
|
-
l = "√(∙)"
|
64
|
-
when "Abs"
|
65
|
-
l = "|∙|"
|
66
|
-
when "Invert"
|
67
|
-
l = "-(∙)"
|
68
|
-
when "Exp"
|
69
|
-
l = "exp(∙)"
|
70
|
-
when "Log"
|
71
|
-
l = "log(∙)"
|
72
|
-
when "Pow"
|
73
|
-
l = "(∙)^(∙)"
|
74
|
-
when "ZERO_CONSTANT"
|
75
|
-
l = "0"
|
76
|
-
when "ONE_CONSTANT"
|
77
|
-
l = "1"
|
78
|
-
when "TWO_CONSTANT"
|
79
|
-
l = "2"
|
80
|
-
when "PI_CONSTANT"
|
81
|
-
l= "π"
|
82
|
-
when "INFINITY_CONSTANT"
|
83
|
-
l = "∞"
|
84
|
-
when "E_CONSTANT"
|
85
|
-
l = "e"
|
86
|
-
when "MINUS_ONE_CONSTANT"
|
87
|
-
l = "-1"
|
88
|
-
else
|
89
|
-
l = $1
|
90
|
-
end
|
91
|
-
lab[m] = l
|
92
|
-
end
|
93
|
-
end
|
94
|
-
lab.each { |k, v| labels += " #{k} [label=\"#{v}\"]\n" }
|
95
|
-
|
96
|
-
return <<-EOG
|
97
|
-
digraph Op {
|
98
|
-
#{string}#{labels}}
|
99
|
-
EOG
|
100
|
-
end
|
101
|
-
|
102
|
-
# Export the input `CAS::Op` graphviz representation to a file.
|
103
|
-
# <- `String` with filename
|
104
|
-
# <- `CAS::Op` with the tree
|
105
|
-
# -> `CAS::Op` in input
|
106
|
-
def self.export_dot(fl, op)
|
107
|
-
CAS::Help.assert(fl, String)
|
108
|
-
CAS::Help.assert(op, CAS::Op)
|
109
|
-
|
110
|
-
File.open(fl, "w") do |f| f.puts CAS.to_dot(op) end
|
111
|
-
return op
|
112
|
-
end
|
113
|
-
|
114
|
-
|
115
27
|
# Support functions are in this separate Helper class
|
116
28
|
module Help
|
117
29
|
# Check input `obj.class` against a `type` class
|
118
30
|
# raises an ArgumentError if check fails
|
31
|
+
#
|
32
|
+
# * **argument**: object to be cecked
|
33
|
+
# * **argument**: type to be checked against
|
34
|
+
# * **returns**: `TrueClass`, or raises an `ArgumentError`
|
119
35
|
def self.assert(obj, type)
|
120
36
|
raise ArgumentError, "required #{type}, received #{obj.class}" unless obj.is_a? type
|
37
|
+
return true
|
121
38
|
end
|
122
39
|
end
|
123
40
|
end
|
124
41
|
|
42
|
+
# ___ _
|
43
|
+
# | _ \___ __ _ _ _(_)_ _ ___ ___
|
44
|
+
# | / -_) _` | || | | '_/ -_|_-<
|
45
|
+
# |_|_\___\__, |\_,_|_|_| \___/__/
|
46
|
+
# |_|
|
125
47
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
alias :overloaded_minus :-
|
134
|
-
alias :overloaded_mul :*
|
135
|
-
alias :overloaded_div :/
|
136
|
-
alias :overloaded_pow :**
|
137
|
-
|
138
|
-
def +(a)
|
139
|
-
if a.is_a? CAS::Op
|
140
|
-
CAS::const(self) + a
|
141
|
-
else
|
142
|
-
self.overloaded_plus a
|
143
|
-
end
|
144
|
-
end
|
145
|
-
|
146
|
-
def -(a)
|
147
|
-
if a.is_a? CAS::Op
|
148
|
-
CAS::const(self) - a
|
149
|
-
else
|
150
|
-
self.overloaded_minus a
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
def *(a)
|
155
|
-
if a.is_a? CAS::Op
|
156
|
-
CAS::const(self) * a
|
157
|
-
else
|
158
|
-
self.overloaded_mul a
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
def /(a)
|
163
|
-
if a.is_a? CAS::Op
|
164
|
-
CAS::const(self) / a
|
165
|
-
else
|
166
|
-
self.overloaded_div a
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
def **(a)
|
171
|
-
if a.is_a? CAS::Op
|
172
|
-
CAS::const(self) ** a
|
173
|
-
else
|
174
|
-
self.overloaded_pow a
|
175
|
-
end
|
176
|
-
end
|
48
|
+
%w|operators/op.rb operators/bary-op.rb operators/nary-op.rb
|
49
|
+
numbers/constants.rb numbers/variables.rb
|
50
|
+
functions/fnc-base.rb functions/fnc-trig.rb functions/fnc-trsc.rb
|
51
|
+
functions/fnc-conditions.rb functions/fnc-box-conditions.rb functions/fnc-piecewise.rb
|
52
|
+
overloading/fixnum.rb overloading/float.rb
|
53
|
+
version.rb|.each do |r|
|
54
|
+
require File.expand_path(r, File.dirname(__FILE__))
|
177
55
|
end
|
178
56
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
alias :overloaded_div :/
|
184
|
-
alias :overloaded_pow :**
|
185
|
-
|
186
|
-
def +(a)
|
187
|
-
if a.is_a? CAS::Op
|
188
|
-
CAS::const(self) + a
|
189
|
-
else
|
190
|
-
self.overloaded_plus a
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
def -(a)
|
195
|
-
if a.is_a? CAS::Op
|
196
|
-
CAS::const(self) - a
|
197
|
-
else
|
198
|
-
self.overloaded_minus a
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
def *(a)
|
203
|
-
if a.is_a? CAS::Op
|
204
|
-
CAS::const(self) * a
|
205
|
-
else
|
206
|
-
self.overloaded_mul a
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
def /(a)
|
211
|
-
if a.is_a? CAS::Op
|
212
|
-
CAS::const(self) / a
|
213
|
-
else
|
214
|
-
self.overloaded_div a
|
215
|
-
end
|
216
|
-
end
|
217
|
-
|
218
|
-
def **(a)
|
219
|
-
if a.is_a? CAS::Op
|
220
|
-
CAS::const(self) ** a
|
221
|
-
else
|
222
|
-
self.overloaded_pow a
|
223
|
-
end
|
224
|
-
end
|
57
|
+
module CAS
|
58
|
+
CAS::NumericToConst[-Math::PI] = (-CAS::Pi)
|
59
|
+
CAS::NumericToConst[-Math::E] = (-CAS::E)
|
60
|
+
CAS::NumericToConst[(-1.0/0.0)] = (CAS::NegInfinity)
|
225
61
|
end
|
data/lib/version.rb
CHANGED
data.tar.gz.sig
CHANGED
Binary file
|
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.3
|
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-10-07 00:00:00.000000000 Z
|
33
33
|
dependencies: []
|
34
34
|
description:
|
35
35
|
email: info@ragni.me
|
@@ -37,12 +37,19 @@ executables: []
|
|
37
37
|
extensions: []
|
38
38
|
extra_rdoc_files: []
|
39
39
|
files:
|
40
|
-
- lib/fnc-base.rb
|
41
|
-
- lib/fnc-
|
42
|
-
- lib/fnc-
|
43
|
-
- lib/fnc-
|
44
|
-
- lib/
|
45
|
-
- lib/
|
40
|
+
- lib/functions/fnc-base.rb
|
41
|
+
- lib/functions/fnc-box-conditions.rb
|
42
|
+
- lib/functions/fnc-conditions.rb
|
43
|
+
- lib/functions/fnc-piecewise.rb
|
44
|
+
- lib/functions/fnc-trig.rb
|
45
|
+
- lib/functions/fnc-trsc.rb
|
46
|
+
- lib/numbers/constants.rb
|
47
|
+
- lib/numbers/variables.rb
|
48
|
+
- lib/operators/bary-op.rb
|
49
|
+
- lib/operators/nary-op.rb
|
50
|
+
- lib/operators/op.rb
|
51
|
+
- lib/overloading/fixnum.rb
|
52
|
+
- lib/overloading/float.rb
|
46
53
|
- lib/ragni-cas.rb
|
47
54
|
- lib/version.rb
|
48
55
|
homepage: https://github.com/MatteoRagni/cas-rb
|
metadata.gz.sig
CHANGED
Binary file
|