Mr.CAS 0.2.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +1 -0
- data.tar.gz.sig +2 -0
- data/lib/Mr.CAS.rb +73 -0
- 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/Mr.CAS/graphviz.rb +132 -0
- data/lib/Mr.CAS/latex.rb +68 -0
- data/lib/Mr.CAS/matlab.rb +81 -0
- data/lib/functions/fnc-base.rb +515 -0
- data/lib/functions/fnc-box-conditions.rb +319 -0
- data/lib/functions/fnc-conditions.rb +365 -0
- data/lib/functions/fnc-piecewise.rb +186 -0
- data/lib/functions/fnc-prod.rb +102 -0
- data/lib/functions/fnc-sum.rb +151 -0
- data/lib/functions/fnc-trig.rb +489 -0
- data/lib/functions/fnc-trsc.rb +192 -0
- data/lib/numbers/constants.rb +350 -0
- data/lib/numbers/functions.rb +194 -0
- data/lib/numbers/variables.rb +202 -0
- data/lib/operators/bary-op.rb +186 -0
- data/lib/operators/nary-op.rb +232 -0
- data/lib/operators/op.rb +285 -0
- data/lib/overloading/fixnum.rb +61 -0
- data/lib/overloading/float.rb +61 -0
- data/lib/version.rb +12 -0
- metadata +88 -0
- metadata.gz.sig +2 -0
@@ -0,0 +1,319 @@
|
|
1
|
+
#!//usr/bin/env ruby
|
2
|
+
|
3
|
+
module CAS
|
4
|
+
# ___ ___ _ _ _ _
|
5
|
+
# | _ ) _____ __/ __|___ _ _ __| (_) |_(_)___ _ _
|
6
|
+
# | _ \/ _ \ \ / (__/ _ \ ' \/ _` | | _| / _ \ ' \
|
7
|
+
# |___/\___/_\_\\___\___/_||_\__,_|_|\__|_\___/_||_|
|
8
|
+
|
9
|
+
##
|
10
|
+
# BoxCondition class constructs a condition of the type:
|
11
|
+
#
|
12
|
+
# ```
|
13
|
+
# L < f(x) < U
|
14
|
+
# ```
|
15
|
+
#
|
16
|
+
# and this is a metaclass for different type of box conditions:
|
17
|
+
#
|
18
|
+
# * open: `a < f(x) < b`
|
19
|
+
# * lower closed: `a ≤ f(x) < b`
|
20
|
+
# * upper closed: `a < f(x) ≤ b`
|
21
|
+
# * closed: `a ≤ f(x) ≤ b`
|
22
|
+
class BoxCondition < CAS::Condition
|
23
|
+
# Contained operation
|
24
|
+
attr_reader :x
|
25
|
+
# Upper bound as `CAS::Constant`
|
26
|
+
attr_reader :lower
|
27
|
+
# Lower bound as `CAs::Constant`
|
28
|
+
attr_reader :upper
|
29
|
+
|
30
|
+
# Initializes a new box condition. A function is required as central term,
|
31
|
+
# while the second and the third elements are lower and upper bounds
|
32
|
+
# as `CAS::Constant`
|
33
|
+
#
|
34
|
+
# * **argument**: `CAS::Op` central term of the box condition
|
35
|
+
# * **argument**: `CAS::Constant` lower bound
|
36
|
+
# * **argument**: `CAS::Constant` upper bound
|
37
|
+
# * **returns**: `CAS::BoxCondition` new instance
|
38
|
+
def initialize(x, lower, upper)
|
39
|
+
if lower.is_a? Numeric
|
40
|
+
lower = CAS::const lower
|
41
|
+
end
|
42
|
+
if upper.is_a? Numeric
|
43
|
+
upper = CAS::const upper
|
44
|
+
end
|
45
|
+
CAS::Help.assert(lower, CAS::Constant)
|
46
|
+
CAS::Help.assert(upper, CAS::Constant)
|
47
|
+
|
48
|
+
CAS::Help.assert(x, CAS::Op)
|
49
|
+
|
50
|
+
lower, upper = upper, lower if lower.x > upper.x
|
51
|
+
|
52
|
+
@lower = lower
|
53
|
+
@upper = upper
|
54
|
+
@x = x
|
55
|
+
end
|
56
|
+
|
57
|
+
# Saves some required elements
|
58
|
+
def representative
|
59
|
+
@lower_cond = @upper_cond = "<"
|
60
|
+
@lower_str = @upper_str = "<"
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
# Returns true if one the central function depends upon the expression included
|
65
|
+
#
|
66
|
+
# * **argument**: `CAS::Op` operator to check against for dependencies
|
67
|
+
# * **returns**: `TrueClass` or `FalseClass`
|
68
|
+
def depend?(v)
|
69
|
+
@x.depend? v
|
70
|
+
end
|
71
|
+
|
72
|
+
# Simplify left and right term of the operator
|
73
|
+
#
|
74
|
+
# * **returns**: `CAS::BoxCondition`
|
75
|
+
def simplify
|
76
|
+
@x.simplify
|
77
|
+
return self
|
78
|
+
end
|
79
|
+
|
80
|
+
# Substitute in the central element using a dictionary
|
81
|
+
#
|
82
|
+
# * **returns**: `Hash` of substitutions
|
83
|
+
def subs(fd)
|
84
|
+
@x = @x.subs(fd)
|
85
|
+
return self
|
86
|
+
end
|
87
|
+
|
88
|
+
# Performs the derivative of the box condition. The derivative of
|
89
|
+
# a box condition is a `CAS::Equal` object (the derivative of a constant
|
90
|
+
# is zero):
|
91
|
+
#
|
92
|
+
# ```
|
93
|
+
# d
|
94
|
+
# -- [a < f(x) < b] = f'(x) == 0
|
95
|
+
# dx
|
96
|
+
# ```
|
97
|
+
#
|
98
|
+
# since between the two there is a difference relation.
|
99
|
+
#
|
100
|
+
# * **argument**: `CAS::Op` to perform the derivative
|
101
|
+
def diff(v)
|
102
|
+
CAS::equal(@x.diff(v).simplify, CAS::Zero)
|
103
|
+
end
|
104
|
+
|
105
|
+
# Returns an array of variables of the central function
|
106
|
+
#
|
107
|
+
# * **returns**: `Array` of `CAS::Variable`
|
108
|
+
def args
|
109
|
+
@x.args
|
110
|
+
end
|
111
|
+
|
112
|
+
# Return true if two BoxConditions are equal, false if different
|
113
|
+
#
|
114
|
+
# * **argument**: `CAS::Op` operator to check against for equality
|
115
|
+
# * **returns**: `TrueClass` or `FalseClass`
|
116
|
+
def ==(cond)
|
117
|
+
return false if not self.class != cond.class
|
118
|
+
return (@x == cond.x and @lower == cond.lower and @upper == cond.upper)
|
119
|
+
end
|
120
|
+
|
121
|
+
# Function call will evaluate left and right functions to solve the
|
122
|
+
# relation
|
123
|
+
#
|
124
|
+
# * **argument**: `Hash` with feed dictionary
|
125
|
+
# * **returns**: `Trueclass` or `Falseclass`
|
126
|
+
def call(_fd)
|
127
|
+
raise CAS::CASError, "This is a virtual method"
|
128
|
+
end
|
129
|
+
|
130
|
+
# Inspector for the class. It is class specific
|
131
|
+
#
|
132
|
+
# * **returns**: `String`
|
133
|
+
def inspect
|
134
|
+
"(#{@lower.inspect} #{@lower_cond} #{@x.inspect} #{@upper_cond} #{@upper.inspect})"
|
135
|
+
end
|
136
|
+
|
137
|
+
# Returns a string that represents the object to be printed
|
138
|
+
#
|
139
|
+
# `String`
|
140
|
+
def to_s
|
141
|
+
"#{@lower} #{@lower_str} #{@x} #{@upper_str} #{@upper}"
|
142
|
+
end
|
143
|
+
|
144
|
+
# Return the code that performs a condition evaluation
|
145
|
+
#
|
146
|
+
# * **returns**: `String`
|
147
|
+
def to_code
|
148
|
+
"((#{@lower.to_code} #{@lower_cond} (#{@x.to_code})) and ((#{@x.to_code}) #{@upper_cond} #{@upper.to_code}))"
|
149
|
+
end
|
150
|
+
end # BoxCondition
|
151
|
+
|
152
|
+
# ___ ___ _ _ _ _ ___
|
153
|
+
# | _ ) _____ __/ __|___ _ _ __| (_) |_(_)___ _ _ / _ \ _ __ ___ _ _
|
154
|
+
# | _ \/ _ \ \ / (__/ _ \ ' \/ _` | | _| / _ \ ' \ (_) | '_ \/ -_) ' \
|
155
|
+
# |___/\___/_\_\\___\___/_||_\__,_|_|\__|_\___/_||_\___/| .__/\___|_||_|
|
156
|
+
# |_|
|
157
|
+
|
158
|
+
##
|
159
|
+
# Implements the box condition with both bounds are open
|
160
|
+
#
|
161
|
+
# ```
|
162
|
+
# a < f(x) < b
|
163
|
+
# ```
|
164
|
+
class BoxConditionOpen < CAS::BoxCondition
|
165
|
+
# Saves some required elements
|
166
|
+
def representative
|
167
|
+
@lower_cond = @upper_cond = @lower_str = @upper_str = "<"
|
168
|
+
self
|
169
|
+
end
|
170
|
+
|
171
|
+
# Function call will evaluate box condition to evaluate
|
172
|
+
# relation
|
173
|
+
#
|
174
|
+
# * **argument**: `Hash` with feed dictionary
|
175
|
+
# * **returns**: `Trueclass` or `Falseclass`
|
176
|
+
def call(fd)
|
177
|
+
x_call = @x.call(fd)
|
178
|
+
return ((@lower.call(fd) < x_call) and (x_call < @upper))
|
179
|
+
end
|
180
|
+
end # BoxConditionOpen
|
181
|
+
|
182
|
+
# ___ ___ _ _ _ _ _ ___ _ _
|
183
|
+
# | _ ) _____ __/ __|___ _ _ __| (_) |_(_)___ _ _ | | _____ __ _____ _ _ / __| |___ ___ ___ __| |
|
184
|
+
# | _ \/ _ \ \ / (__/ _ \ ' \/ _` | | _| / _ \ ' \| |__/ _ \ V V / -_) '_| (__| / _ (_-</ -_) _` |
|
185
|
+
# |___/\___/_\_\\___\___/_||_\__,_|_|\__|_\___/_||_|____\___/\_/\_/\___|_| \___|_\___/__/\___\__,_|
|
186
|
+
|
187
|
+
##
|
188
|
+
# Implements the box condition with lower bound closed and upper open
|
189
|
+
#
|
190
|
+
# ```
|
191
|
+
# a ≤ f(x) < b
|
192
|
+
# ```
|
193
|
+
class BoxConditionLowerClosed < CAS::BoxCondition
|
194
|
+
# Saves some required elements
|
195
|
+
def representative
|
196
|
+
@lower_cond = "<="
|
197
|
+
@lower_str = "≤"
|
198
|
+
@upper_cond = @upper_str = "<"
|
199
|
+
self
|
200
|
+
end
|
201
|
+
|
202
|
+
# Function call will evaluate box condition to evaluate
|
203
|
+
# relation
|
204
|
+
#
|
205
|
+
# * **argument**: `Hash` with feed dictionary
|
206
|
+
# * **returns**: `Trueclass` or `Falseclass`
|
207
|
+
def call(fd)
|
208
|
+
x_call = @x.call(fd)
|
209
|
+
return ((@lower.call(fd) <= x_call) and (x_call < @upper))
|
210
|
+
end
|
211
|
+
end # BoxConditionLowerClosed
|
212
|
+
|
213
|
+
# ___ ___ _ _ _ _ _ _ ___ _ _
|
214
|
+
# | _ ) _____ __/ __|___ _ _ __| (_) |_(_)___ _ _| | | |_ __ _ __ ___ _ _ / __| |___ ___ ___ __| |
|
215
|
+
# | _ \/ _ \ \ / (__/ _ \ ' \/ _` | | _| / _ \ ' \ |_| | '_ \ '_ \/ -_) '_| (__| / _ (_-</ -_) _` |
|
216
|
+
# |___/\___/_\_\\___\___/_||_\__,_|_|\__|_\___/_||_\___/| .__/ .__/\___|_| \___|_\___/__/\___\__,_|
|
217
|
+
# |_| |_|
|
218
|
+
|
219
|
+
##
|
220
|
+
# Implements the box condition with lower bound open and upper closed
|
221
|
+
#
|
222
|
+
# ```
|
223
|
+
# a < f(x) ≤ b
|
224
|
+
# ```
|
225
|
+
class BoxConditionUpperClosed < CAS::BoxCondition
|
226
|
+
# Saves some required elements
|
227
|
+
def representative
|
228
|
+
@lower_cond = @lower_str = "<"
|
229
|
+
@upper_cond = "<="
|
230
|
+
@upper_str = "≤"
|
231
|
+
self
|
232
|
+
end
|
233
|
+
|
234
|
+
# Function call will evaluate box condition to evaluate
|
235
|
+
# relation
|
236
|
+
#
|
237
|
+
# * **argument**: `Hash` with feed dictionary
|
238
|
+
# * **returns**: `Trueclass` or `Falseclass`
|
239
|
+
def call(fd)
|
240
|
+
x_call = @x.call(fd)
|
241
|
+
return ((@lower.call(fd) < x_call) and (x_call <= @upper))
|
242
|
+
end
|
243
|
+
end # BoxConditionUpperClosed
|
244
|
+
|
245
|
+
# ___ ___ _ _ _ _ ___ _ _
|
246
|
+
# | _ ) _____ __/ __|___ _ _ __| (_) |_(_)___ _ _ / __| |___ ___ ___ __| |
|
247
|
+
# | _ \/ _ \ \ / (__/ _ \ ' \/ _` | | _| / _ \ ' \ (__| / _ (_-</ -_) _` |
|
248
|
+
# |___/\___/_\_\\___\___/_||_\__,_|_|\__|_\___/_||_\___|_\___/__/\___\__,_|
|
249
|
+
|
250
|
+
##
|
251
|
+
# Implements the box condition with both bounds closed
|
252
|
+
#
|
253
|
+
# ```
|
254
|
+
# a ≤ f(x) ≤ b
|
255
|
+
# ```
|
256
|
+
class BoxConditionClosed < CAS::BoxCondition
|
257
|
+
# Saves some required elements
|
258
|
+
def representative
|
259
|
+
@lower_cond = @upper_cond = "<="
|
260
|
+
@lower_str = @upper_str = "≤"
|
261
|
+
self
|
262
|
+
end
|
263
|
+
|
264
|
+
# Function call will evaluate box condition to evaluate
|
265
|
+
# relation
|
266
|
+
#
|
267
|
+
# * **argument**: `Hash` with feed dictionary
|
268
|
+
# * **returns**: `Trueclass` or `Falseclass`
|
269
|
+
def call(fd)
|
270
|
+
x_call = @x.call(fd)
|
271
|
+
return ((@lower.call(fd) <= x_call) and (x_call <= @upper))
|
272
|
+
end
|
273
|
+
end # BoxConditionUpperClosed
|
274
|
+
|
275
|
+
class << self
|
276
|
+
# Shortcut for creating a new box condition. It requires four arguments:
|
277
|
+
#
|
278
|
+
# * **argument**: `CAS::Op` function for condition
|
279
|
+
# * **argument**: `CAS::Constant` lower limit
|
280
|
+
# * **argument**: `CAs::Constant` upper limit
|
281
|
+
# * **argument**: `Symbol` of condition type it can be:
|
282
|
+
# - `:closed` for `CAs::BoxConditionClosed`
|
283
|
+
# - `:open` for `CAs::BoxConditionOpen`
|
284
|
+
# - `:upper_closed` for `CAs::BoxConditionUpperClosed`
|
285
|
+
# - `:lower_closed` for `CAs::BoxConditionLowerClosed`
|
286
|
+
# * **returns**: `CAS::BoxCondition` new instance
|
287
|
+
def box(x, a, b, type=:closed)
|
288
|
+
case type
|
289
|
+
when :closed
|
290
|
+
return CAS::BoxConditionClosed.new(x, a, b)
|
291
|
+
when :open
|
292
|
+
return CAS::BoxConditionOpen.new(x, a, b)
|
293
|
+
when :upper_closed
|
294
|
+
return CAS::BoxConditionUpperClosed.new(x, a, b)
|
295
|
+
when :lower_closed
|
296
|
+
return CAS::BoxConditionLowerClosed.new(x, a, b)
|
297
|
+
else
|
298
|
+
raise CAS::CASError, "Unknown box condition type"
|
299
|
+
end
|
300
|
+
end
|
301
|
+
alias :in :box
|
302
|
+
end
|
303
|
+
|
304
|
+
class Op
|
305
|
+
# Shortcut for creating a new box condition. It requires limits and type:
|
306
|
+
#
|
307
|
+
# * **argument**: `CAS::Constant` lower limit
|
308
|
+
# * **argument**: `CAs::Constant` upper limit
|
309
|
+
# * **argument**: `Symbol` of condition type it can be:
|
310
|
+
# - `:closed` for `CAs::BoxConditionClosed`
|
311
|
+
# - `:open` for `CAs::BoxConditionOpen`
|
312
|
+
# - `:upper_closed` for `CAs::BoxConditionUpperClosed`
|
313
|
+
# - `:lower_closed` for `CAs::BoxConditionLowerClosed`
|
314
|
+
# * **returns**: `CAS::BoxCondition` new instance
|
315
|
+
def limit(a, b, type=:closed)
|
316
|
+
return CAS::box(self, a, b, type)
|
317
|
+
end
|
318
|
+
end # Op
|
319
|
+
end
|
@@ -0,0 +1,365 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module CAS
|
4
|
+
# ___ _ _ _ _
|
5
|
+
# / __|___ _ _ __| (_) |_(_)___ _ _
|
6
|
+
# | (__/ _ \ ' \/ _` | | _| / _ \ ' \
|
7
|
+
# \___\___/_||_\__,_|_|\__|_\___/_||_|
|
8
|
+
|
9
|
+
##
|
10
|
+
# Condition class is a pseudo-class for all the other kind of conditions:
|
11
|
+
#
|
12
|
+
# * Equal
|
13
|
+
# * Greater
|
14
|
+
# * GreaterEqual
|
15
|
+
# * Smaller
|
16
|
+
# * SmallerEqual
|
17
|
+
#
|
18
|
+
# When derivated, the two functions (that can be considered as the difference of two elements)
|
19
|
+
# are derived autonoumouosly. A condition is composed by:
|
20
|
+
#
|
21
|
+
# * left function (x)
|
22
|
+
# * right function (y)
|
23
|
+
# * type of condition
|
24
|
+
class Condition
|
25
|
+
# Left hand side
|
26
|
+
attr_reader :x
|
27
|
+
# Right hand side
|
28
|
+
attr_reader :y
|
29
|
+
|
30
|
+
# Initializer for a new condition. The condition is implicit in the class, thus a
|
31
|
+
# pure `CAS::Condition` cannot be used.
|
32
|
+
#
|
33
|
+
# * **argument**: `CAS::Op` left argument
|
34
|
+
# * **argument**: `CAS::Op` right argument
|
35
|
+
# * **returns**: `CAS::Condition` new instance
|
36
|
+
def initialize(x, y)
|
37
|
+
@x = x
|
38
|
+
@y = y
|
39
|
+
self.representative
|
40
|
+
end
|
41
|
+
|
42
|
+
# Saves some required elements
|
43
|
+
def representative
|
44
|
+
@cond_type = "??"
|
45
|
+
@cond_repr = "??"
|
46
|
+
self
|
47
|
+
end
|
48
|
+
|
49
|
+
# Function call will evaluate left and right functions to solve the
|
50
|
+
# relation
|
51
|
+
#
|
52
|
+
# * **argument**: `Hash` with feed dictionary
|
53
|
+
# * **returns**: `Trueclass` or `Falseclass`
|
54
|
+
def call(_fd)
|
55
|
+
raise CAS::CASError, "This is a virtual method"
|
56
|
+
end
|
57
|
+
|
58
|
+
# Inspector for the class. It is class specific
|
59
|
+
#
|
60
|
+
# * **returns**: `String`
|
61
|
+
def inspect
|
62
|
+
"#{self.class}(#{@x.inspect}, #{@y.inspect})"
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns a string that represents the object to be printed
|
66
|
+
#
|
67
|
+
# `String`
|
68
|
+
def to_s
|
69
|
+
"(#{@x} #{@cond_repr} #{@y})"
|
70
|
+
end
|
71
|
+
|
72
|
+
# Return the code that performs a condition evaluation
|
73
|
+
#
|
74
|
+
# * **returns**: `String`
|
75
|
+
def to_code
|
76
|
+
"(#{@x} #{@cond_type} #{@y})"
|
77
|
+
end
|
78
|
+
|
79
|
+
# Returns an array of variables of the two functions in the condition
|
80
|
+
#
|
81
|
+
# * **returns**: `Array` of `CAS::Variable`
|
82
|
+
def args
|
83
|
+
(@x.args + @y.args).uniq
|
84
|
+
end
|
85
|
+
|
86
|
+
# Performs the derivative of the two elements:
|
87
|
+
#
|
88
|
+
# ```
|
89
|
+
# d
|
90
|
+
# -- [f(x) > g(y)] = f'(x) > g'(x)
|
91
|
+
# dx
|
92
|
+
# ```
|
93
|
+
#
|
94
|
+
# since between the two there is a difference relation.
|
95
|
+
#
|
96
|
+
# * **argument**: `CAS::Op` to perform the derivative
|
97
|
+
def diff(v)
|
98
|
+
CAS::Help.assert v, CAS::Op
|
99
|
+
|
100
|
+
@x.diff(v)
|
101
|
+
@y.diff(v)
|
102
|
+
self.simplify
|
103
|
+
end
|
104
|
+
|
105
|
+
# Returns true if one of the two functions depends upon the expression included
|
106
|
+
#
|
107
|
+
# * **argument**: `CAS::Op` operator to check against for dependencies
|
108
|
+
# * **returns**: `TrueClass` or `FalseClass`
|
109
|
+
def depend?(v)
|
110
|
+
CAS::Help.assert v, CAS::Op
|
111
|
+
|
112
|
+
@x.depend?(v) or @y.depend?(v)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Return true if two functions are equal, false if different
|
116
|
+
#
|
117
|
+
# * **argument**: `CAS::Op` operator to check against for equality
|
118
|
+
# * **returns**: `TrueClass` or `FalseClass`
|
119
|
+
def ==(op)
|
120
|
+
CAS::Help.assert(op, CAS::Op)
|
121
|
+
|
122
|
+
# condB = (@x == op.y) and (@y == op.x)
|
123
|
+
return ((@x == op.x) and (@y == op.y) and (self.class == op.class))
|
124
|
+
end
|
125
|
+
|
126
|
+
# Simplify left and right term of the operator
|
127
|
+
#
|
128
|
+
# * **returns**: `CAS::Condition`
|
129
|
+
def simplify
|
130
|
+
@x.simplify
|
131
|
+
@y.simplify
|
132
|
+
return self
|
133
|
+
end
|
134
|
+
|
135
|
+
# Substitute in the two elements using a dictionary
|
136
|
+
#
|
137
|
+
# * **returns**: `Hash` of substitutions
|
138
|
+
def subs(fd)
|
139
|
+
CAS::Help.assert(fd, Hash)
|
140
|
+
@x.subs(fd)
|
141
|
+
@y.subs(fd)
|
142
|
+
return self
|
143
|
+
end
|
144
|
+
|
145
|
+
# Returns the dot graphviz representation of the code
|
146
|
+
#
|
147
|
+
# * **returns**: `String`
|
148
|
+
def dot_graph(node)
|
149
|
+
cls = "#{self.class.to_s.gsub("CAS::", "")}_#{self.object_id}"
|
150
|
+
"#{cls} -> #{@x.dot_graph node}\n #{cls} -> #{@y.dot_graph node}"
|
151
|
+
end
|
152
|
+
end # Condition
|
153
|
+
|
154
|
+
# ___ _
|
155
|
+
# | __|__ _ _ _ __ _| |
|
156
|
+
# | _|/ _` | || / _` | |
|
157
|
+
# |___\__, |\_,_\__,_|_|
|
158
|
+
# |_|
|
159
|
+
|
160
|
+
##
|
161
|
+
# This class is a Condition for two equal function
|
162
|
+
class Equal < CAS::Condition
|
163
|
+
# Saves some required elements
|
164
|
+
def representative
|
165
|
+
@cond_type, @cond_repr = "==", "≡"
|
166
|
+
self
|
167
|
+
end
|
168
|
+
|
169
|
+
# Function call will evaluate left and right functions to solve the
|
170
|
+
# relation
|
171
|
+
#
|
172
|
+
# * **argument**: `Hash` with feed dictionary
|
173
|
+
# * **returns**: `Trueclass` or `Falseclass`
|
174
|
+
def call(fd)
|
175
|
+
CAS::Help.assert fd, Hash
|
176
|
+
|
177
|
+
return (@x.call(fd) == @y.call(fd))
|
178
|
+
end
|
179
|
+
|
180
|
+
# Return true if two functions are equal, false if different
|
181
|
+
#
|
182
|
+
# * **argument**: `CAS::Op` operator to check against for equality
|
183
|
+
# * **returns**: `TrueClass` or `FalseClass`
|
184
|
+
def ==(op)
|
185
|
+
CAS::Help.assert(op, CAS::Op)
|
186
|
+
cond_f = ((@x == op.x) and (@y == op.y)) or ((@x == op.y) and (@y == op.x))
|
187
|
+
return (cond_f and (self.class == op.class))
|
188
|
+
end
|
189
|
+
end # Equal
|
190
|
+
|
191
|
+
# ___ _ _
|
192
|
+
# / __|_ __ __ _| | |___ _ _
|
193
|
+
# \__ \ ' \/ _` | | / -_) '_|
|
194
|
+
# |___/_|_|_\__,_|_|_\___|_|
|
195
|
+
|
196
|
+
##
|
197
|
+
# This class is a Condition for left smaller function
|
198
|
+
class Smaller < CAS::Condition
|
199
|
+
# Saves some required elements
|
200
|
+
def representative
|
201
|
+
@cond_type = @cond_repr = "<"
|
202
|
+
self
|
203
|
+
end
|
204
|
+
|
205
|
+
# Function call will evaluate left and right functions to solve the
|
206
|
+
# relation
|
207
|
+
#
|
208
|
+
# * **argument**: `Hash` with feed dictionary
|
209
|
+
# * **returns**: `Trueclass` or `Falseclass`
|
210
|
+
def call(fd)
|
211
|
+
CAS::Help.assert fd, Hash
|
212
|
+
|
213
|
+
return (@x.call(fd) < @y.call(fd))
|
214
|
+
end
|
215
|
+
end # Smaller
|
216
|
+
|
217
|
+
# ___ _
|
218
|
+
# / __|_ _ ___ __ _| |_ ___ _ _
|
219
|
+
# | (_ | '_/ -_) _` | _/ -_) '_|
|
220
|
+
# \___|_| \___\__,_|\__\___|_|
|
221
|
+
|
222
|
+
##
|
223
|
+
# This class is a Condition for right smaller function
|
224
|
+
class Greater < CAS::Condition
|
225
|
+
# Saves some required elements
|
226
|
+
def representative
|
227
|
+
@cond_type = @cond_repr = ">"
|
228
|
+
self
|
229
|
+
end
|
230
|
+
|
231
|
+
# Function call will evaluate left and right functions to solve the
|
232
|
+
# relation
|
233
|
+
#
|
234
|
+
# * **argument**: `Hash` with feed dictionary
|
235
|
+
# * **returns**: `Trueclass` or `Falseclass`
|
236
|
+
def call(fd)
|
237
|
+
CAS::Help.assert fd, Hash
|
238
|
+
|
239
|
+
return (@x.call(fd) > @y.call(fd))
|
240
|
+
end
|
241
|
+
end # Greater
|
242
|
+
|
243
|
+
# ___ _ _ ___ _
|
244
|
+
# / __|_ __ __ _| | |___ _ _| __|__ _ _ _ __ _| |
|
245
|
+
# \__ \ ' \/ _` | | / -_) '_| _|/ _` | || / _` | |
|
246
|
+
# |___/_|_|_\__,_|_|_\___|_| |___\__, |\_,_\__,_|_|
|
247
|
+
# |_|
|
248
|
+
|
249
|
+
##
|
250
|
+
# This class is a Condition for left smaller or equal function
|
251
|
+
class SmallerEqual < CAS::Condition
|
252
|
+
# Saves some required elements
|
253
|
+
def representative
|
254
|
+
@cond_type = "<="
|
255
|
+
@cond_repr = "≤"
|
256
|
+
self
|
257
|
+
end
|
258
|
+
|
259
|
+
# Function call will evaluate left and right functions to solve the
|
260
|
+
# relation
|
261
|
+
#
|
262
|
+
# * **argument**: `Hash` with feed dictionary
|
263
|
+
# * **returns**: `Trueclass` or `Falseclass`
|
264
|
+
def call(fd)
|
265
|
+
CAS::Help.assert fd, Hash
|
266
|
+
|
267
|
+
return (@x.call(fd) <= @y.call(fd))
|
268
|
+
end
|
269
|
+
end # SmallerEqual
|
270
|
+
|
271
|
+
# ___ _ ___ _
|
272
|
+
# / __|_ _ ___ __ _| |_ ___ _ _| __|__ _ _ _ __ _| |
|
273
|
+
# | (_ | '_/ -_) _` | _/ -_) '_| _|/ _` | || / _` | |
|
274
|
+
# \___|_| \___\__,_|\__\___|_| |___\__, |\_,_\__,_|_|
|
275
|
+
# |_|
|
276
|
+
|
277
|
+
##
|
278
|
+
# This class is a condition for right smaller or equal function
|
279
|
+
class GreaterEqual < CAS::Condition
|
280
|
+
# Saves some required elements
|
281
|
+
def representative
|
282
|
+
@cond_type = ">="
|
283
|
+
@cond_repr = "≥"
|
284
|
+
self
|
285
|
+
end
|
286
|
+
|
287
|
+
# Function call will evaluate left and right functions to solve the
|
288
|
+
# relation
|
289
|
+
#
|
290
|
+
# * **argument**: `Hash` with feed dictionary
|
291
|
+
# * **returns**: `Trueclass` or `Falseclass`
|
292
|
+
def call(fd)
|
293
|
+
CAS::Help.assert fd, Hash
|
294
|
+
|
295
|
+
return (@x.call(fd) >= @y.call(fd))
|
296
|
+
end
|
297
|
+
end # SmallerEqual
|
298
|
+
|
299
|
+
# Shortcut creates a `CAS::Equal` object
|
300
|
+
def self.equal(x, y)
|
301
|
+
CAS::Equal.new(x, y)
|
302
|
+
end
|
303
|
+
|
304
|
+
# Shortcut creates a `CAS::Greater` object
|
305
|
+
def self.greater(x, y)
|
306
|
+
CAS::Greater.new(x, y)
|
307
|
+
end
|
308
|
+
|
309
|
+
# Shortcut creates a `CAS::GreaterEqual` object
|
310
|
+
def self.greater_equal(x, y)
|
311
|
+
CAS::GreaterEqual.new(x, y)
|
312
|
+
end
|
313
|
+
|
314
|
+
# Shortcut creates `CAS::Smaller` object
|
315
|
+
def self.smaller(x, y)
|
316
|
+
CAS::Smaller.new(x, y)
|
317
|
+
end
|
318
|
+
|
319
|
+
# Shortcut creates a `CAs::SmallerEqual` object
|
320
|
+
def self.smaller_equal(x, y)
|
321
|
+
CAS::SmallerEqual.new(x, y)
|
322
|
+
end
|
323
|
+
|
324
|
+
class Op
|
325
|
+
# Shortcut for creating equality condition.
|
326
|
+
#
|
327
|
+
# * **argument**: `CAS::Op` ther element of the condition
|
328
|
+
# * **returns**: `CAS::Equal` new instance
|
329
|
+
def equal(v)
|
330
|
+
CAS.equal(self, v)
|
331
|
+
end
|
332
|
+
|
333
|
+
# Shortcut for creating greater kind condition.
|
334
|
+
#
|
335
|
+
# * **argument**: `CAS::Op` ther element of the condition
|
336
|
+
# * **returns**: `CAS::Greater` new instance
|
337
|
+
def greater(v)
|
338
|
+
CAS.greater(self, v)
|
339
|
+
end
|
340
|
+
|
341
|
+
# Shortcut for creating a smaller kind condition.
|
342
|
+
#
|
343
|
+
# * **argument**: `CAS::Op` ther element of the condition
|
344
|
+
# * **returns**: `CAS::Smaller` new instance
|
345
|
+
def smaller(v)
|
346
|
+
CAS.smaller(self, v)
|
347
|
+
end
|
348
|
+
|
349
|
+
# Shortcut for creating a greater equal kind condition.
|
350
|
+
#
|
351
|
+
# * **argument**: `CAS::Op` ther element of the condition
|
352
|
+
# * **returns**: `CAS::GreaterEqual` new instance
|
353
|
+
def greater_equal(v)
|
354
|
+
CAS.greater_equal(self, v)
|
355
|
+
end
|
356
|
+
|
357
|
+
# Shortcut for creating a smaller equal kind condition.
|
358
|
+
#
|
359
|
+
# * **argument**: `CAS::Op` ther element of the condition
|
360
|
+
# * **returns**: `CAS::SmallerEqual` new instance
|
361
|
+
def smaller_equal(v)
|
362
|
+
CAS.smaller_equal(self, v)
|
363
|
+
end
|
364
|
+
end # Op
|
365
|
+
end
|