kxi 1.0.1 → 1.0.2
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
- data/lib/kxi.rb +44 -39
- data/lib/kxi/application/config.rb +177 -177
- data/lib/kxi/application/config_reader.rb +16 -16
- data/lib/kxi/application/event.rb +35 -35
- data/lib/kxi/application/logger.rb +155 -155
- data/lib/kxi/application/version.rb +106 -74
- data/lib/kxi/application/version_expression.rb +94 -69
- data/lib/kxi/application/workspace.rb +105 -0
- data/lib/kxi/cli/anonymous_argument.rb +50 -50
- data/lib/kxi/cli/argument.rb +56 -56
- data/lib/kxi/cli/argument_values.rb +83 -83
- data/lib/kxi/cli/explicit_argument.rb +38 -38
- data/lib/kxi/cli/flag_argument.rb +15 -15
- data/lib/kxi/cli/named_argument.rb +59 -59
- data/lib/kxi/cli/property_list.rb +57 -48
- data/lib/kxi/cli/table.rb +82 -62
- data/lib/kxi/cli/verb.rb +282 -280
- data/lib/kxi/collections/array_collection.rb +106 -106
- data/lib/kxi/collections/enumerable.rb +527 -527
- data/lib/kxi/collections/enumerator.rb +31 -31
- data/lib/kxi/collections/hash_collection.rb +100 -100
- data/lib/kxi/collections/protected_collection.rb +20 -19
- data/lib/kxi/exceptions/abstract_exception.rb +34 -34
- data/lib/kxi/exceptions/argument_exception.rb +21 -21
- data/lib/kxi/exceptions/collection_exception.rb +13 -13
- data/lib/kxi/exceptions/configuration_exception.rb +36 -25
- data/lib/kxi/exceptions/dimension_mismatch_exception.rb +29 -0
- data/lib/kxi/exceptions/invalid_type_exception.rb +32 -32
- data/lib/kxi/exceptions/no_argument_exception.rb +20 -20
- data/lib/kxi/exceptions/not_implemented_exception.rb +12 -12
- data/lib/kxi/exceptions/out_of_range_exception.rb +43 -43
- data/lib/kxi/exceptions/parse_exception.rb +28 -20
- data/lib/kxi/exceptions/verb_expected_exception.rb +20 -20
- data/lib/kxi/exceptions/workspace_collision_exception.rb +21 -0
- data/lib/kxi/math/math.rb +45 -0
- data/lib/kxi/math/matrix.rb +303 -0
- data/lib/kxi/math/polynomial.rb +141 -101
- data/lib/kxi/math/vector.rb +181 -0
- data/lib/kxi/platform.rb +103 -57
- data/lib/kxi/reflection/stack_frame.rb +80 -80
- data/lib/kxi/version.rb +4 -4
- metadata +8 -3
- data/lib/kxi/exceptions/invalid_operation_exception.rb +0 -11
@@ -0,0 +1,303 @@
|
|
1
|
+
# Created by Matyáš Pokorný on 2018-04-12.
|
2
|
+
|
3
|
+
module KXI
|
4
|
+
module Math
|
5
|
+
# Represents a matrix
|
6
|
+
class Matrix
|
7
|
+
# Returns a square identity matrix
|
8
|
+
# @param [Integer] n Dimension of matrix
|
9
|
+
# @return [KXI::Math::Matrix] Square identity matrix of given dimension
|
10
|
+
def self.identity(n)
|
11
|
+
return KXI::Math::Matrix.new(n, n) { |c, r| c == r ? 1 : 0 }
|
12
|
+
end
|
13
|
+
|
14
|
+
# Returns the number of rows
|
15
|
+
# @return [Integer] Number of rows
|
16
|
+
def rows
|
17
|
+
@rows
|
18
|
+
end
|
19
|
+
|
20
|
+
# Returns the number of columns
|
21
|
+
# @return [Integer] Number of columns
|
22
|
+
def columns
|
23
|
+
@cols
|
24
|
+
end
|
25
|
+
|
26
|
+
# Instantiates the {KXI::Math::Matrix} class
|
27
|
+
# @overload initialize(cols)
|
28
|
+
# Creates a square matrix
|
29
|
+
# @param [Integer] cols Dimension of matrix
|
30
|
+
# @overload initialize(cols, rows)
|
31
|
+
# Creates a matrix
|
32
|
+
# @param [Integer] cols Number of columns in the matrix
|
33
|
+
# @param [Integer] rows Number of rows in the matrix
|
34
|
+
def initialize(cols, rows = nil)
|
35
|
+
rows = cols if rows == nil
|
36
|
+
@data = []
|
37
|
+
cols.times do |i|
|
38
|
+
if block_given?
|
39
|
+
@data[i] = []
|
40
|
+
rows.times do |j|
|
41
|
+
v = yield(i, j)
|
42
|
+
raise(KXI::Exceptions::InvalidTypeException.new(v.type, Numeric)) unless v.is_a?(Numeric)
|
43
|
+
@data[i].push(v)
|
44
|
+
end
|
45
|
+
else
|
46
|
+
@data[i] = [0.0] * rows
|
47
|
+
end
|
48
|
+
end
|
49
|
+
@cols = cols
|
50
|
+
@rows = rows
|
51
|
+
end
|
52
|
+
|
53
|
+
# Swaps two rows of the matrix
|
54
|
+
# @param [Integer] a First row to swap
|
55
|
+
# @param [Integer] b Second row to swap with
|
56
|
+
# @raise [KXI::Exceptions::OutOfRangeException] When one of arguments is out of range
|
57
|
+
# @return [KXI::Math::Matrix] New matrix with swapped rows
|
58
|
+
def row_swap(a, b)
|
59
|
+
raise(KXI::Exceptions::OutOfRangeException.new(a, 0, @rows - 1)) if a < 0 or a >= @rows
|
60
|
+
raise(KXI::Exceptions::OutOfRangeException.new(b, 0, @rows - 1)) if b < 0 or b >= @rows
|
61
|
+
return KXI::Math::Matrix.new(@cols, @rows) do |c, r|
|
62
|
+
next get(c, b) if r == a
|
63
|
+
next get(c, a) if r == b
|
64
|
+
get(c, r)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# Multiplies a row of matrix with specific coefficient
|
69
|
+
# @overload row_mult(src, cof)
|
70
|
+
# Multiplies a row by coefficient into that row
|
71
|
+
# @param [Integer] src Row to multiply
|
72
|
+
# @param [Numeric] cof Coefficient to multiply with
|
73
|
+
# @raise [KXI::Exceptions::OutOfRangeException] When one of arguments is out of range
|
74
|
+
# @return [Matrix] New matrix with multiplied row
|
75
|
+
# @overload row_mult(src, cof, dst)
|
76
|
+
# Multiplies a row by coefficient into other row
|
77
|
+
# @param [Integer] src Row to multiply
|
78
|
+
# @param [Numeric] cof Coefficient to multiply with
|
79
|
+
# @param [Numeric] dst Row to write the results of multiplication
|
80
|
+
# @raise [KXI::Exceptions::OutOfRangeException] When one of arguments is out of range
|
81
|
+
# @return [Matrix] New matrix with multiplied row
|
82
|
+
def row_mult!(src, cof, dst = nil)
|
83
|
+
dst = src if dst == nil
|
84
|
+
raise(KXI::Exceptions::OutOfRangeException.new(src, 0, @rows - 1)) if src < 0 or src >= @rows
|
85
|
+
raise(KXI::Exceptions::OutOfRangeException.new(dst, 0, @rows - 1)) if dst < 0 or dst >= @rows
|
86
|
+
return KXI::Math::Matrix.new(@cols, @rows) do |c, r|
|
87
|
+
next cof * get(c, src) if r == dst
|
88
|
+
get(c, r)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# Multiplies a row of matrix with specific coefficient
|
93
|
+
# @overload row_mult(src, cof)
|
94
|
+
# Multiplies a row by coefficient and adds that to the row
|
95
|
+
# @param [Integer] src Row to multiply
|
96
|
+
# @param [Numeric] cof Coefficient to multiply with
|
97
|
+
# @raise [KXI::Exceptions::OutOfRangeException] When one of arguments is out of range
|
98
|
+
# @return [Matrix] New matrix with multiplied row
|
99
|
+
# @overload row_mult(src, cof, dst)
|
100
|
+
# Multiplies a row by coefficient and adds that to other row
|
101
|
+
# @param [Integer] src Row to multiply
|
102
|
+
# @param [Numeric] cof Coefficient to multiply with
|
103
|
+
# @param [Numeric] dst Row to write the results of multiplication
|
104
|
+
# @raise [KXI::Exceptions::OutOfRangeException] When one of arguments is out of range
|
105
|
+
# @return [Matrix] New matrix with multiplied row
|
106
|
+
def row_mult(src, cof, dst = nil)
|
107
|
+
dst = src if dst == nil
|
108
|
+
return KXI::Math::Matrix.new(@cols, @rows) do |c, r|
|
109
|
+
next get(c, r) + cof * get(c, src) if r == dst
|
110
|
+
get(c, r)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def sign(col, row)
|
115
|
+
return ((col % 2 == 0) == (row % 2 == 0)) ? 1 : -1
|
116
|
+
end
|
117
|
+
|
118
|
+
# Computes the determinant of matrix
|
119
|
+
# @return [Numeric] Determinant of matrix
|
120
|
+
def determinant
|
121
|
+
return get(0, 0) * get(1, 1) - get(1, 0) * get(0, 1) if @cols == 2
|
122
|
+
ci = 0
|
123
|
+
cz = 0
|
124
|
+
@cols.times do |col|
|
125
|
+
zeros = 0
|
126
|
+
@rows.times { |row| zeros += 1 if get(col, row) == 0 }
|
127
|
+
if zeros > cz
|
128
|
+
ci = col
|
129
|
+
cz = zeros
|
130
|
+
end
|
131
|
+
end
|
132
|
+
ret = 0
|
133
|
+
@rows.times do |row|
|
134
|
+
if get(ci, row) != 0
|
135
|
+
ret += sign(ci, row) * get(ci, row) * sub(ci, row).determinant
|
136
|
+
end
|
137
|
+
end
|
138
|
+
return ret
|
139
|
+
end
|
140
|
+
|
141
|
+
# Computes the inverse of matrix
|
142
|
+
# @return [KXI::Math::Matrix] Inverse matrix
|
143
|
+
def inverse
|
144
|
+
return (KXI::Math::Matrix.new(@cols, @rows) { |c, r| sign(c, r) * sub(c, r).determinant }).transpose * (1 / determinant)
|
145
|
+
end
|
146
|
+
|
147
|
+
def sub(col, row)
|
148
|
+
return KXI::Math::Matrix.new(@cols - 1, @rows - 1) do |c, r|
|
149
|
+
c = c + 1 if c >= col
|
150
|
+
r = r + 1 if r >= row
|
151
|
+
next get(c, r)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Gets the value of matrix at given column and row
|
156
|
+
# @param [Integer] col Column to get
|
157
|
+
# @param [Integer] row Row to get
|
158
|
+
# @raise [KXI::Exceptions::OutOfRangeException] When one of arguments is out of range
|
159
|
+
# @return [Numeric] Value of matrix at given column and row
|
160
|
+
def get(col, row)
|
161
|
+
raise(KXI::Exceptions::OutOfRangeException.new(col, 0, @cols - 1)) if col < 0 or col >= @cols
|
162
|
+
raise(KXI::Exceptions::OutOfRangeException.new(row, 0, @rows - 1)) if row < 0 or row >= @rows
|
163
|
+
return @data[col][row]
|
164
|
+
end
|
165
|
+
|
166
|
+
# Sets the value of vector at specific dimension
|
167
|
+
# @overload set(col, row, val)
|
168
|
+
# Sets the value of vector at specific dimension
|
169
|
+
# @param [Integer] col Column to set
|
170
|
+
# @param [Integer] row Row to set
|
171
|
+
# @param [Integer] val Value to set the matrix to
|
172
|
+
# @raise [KXI::Exceptions::OutOfRangeException] When one of arguments is out of range
|
173
|
+
# @raise [KXI::Exceptions::InvalidTypeException] When value has invalid type
|
174
|
+
# @return [Numeric] Value passed to function
|
175
|
+
# @overload set(col, row, val)
|
176
|
+
# Sets the values of vector to range of values starting from specific dimension
|
177
|
+
# @param [Integer] col Column to set
|
178
|
+
# @param [Integer] row Row to set
|
179
|
+
# @param [Array] val Values to set the matrix to
|
180
|
+
# @raise [KXI::Exceptions::OutOfRangeException] When one of arguments is out of range
|
181
|
+
# @raise [KXI::Exceptions::InvalidTypeException] When value has invalid type
|
182
|
+
# @return [Numeric] Value passed to function
|
183
|
+
def set(col, row, value)
|
184
|
+
raise(KXI::Exceptions::OutOfRangeException.new(col, 0, @cols - 1)) if col < 0 or col >= @cols
|
185
|
+
raise(KXI::Exceptions::OutOfRangeException.new(row, 0, @rows - 1)) if row < 0 or row >= @rows
|
186
|
+
if value.is_a?(Array)
|
187
|
+
i = 0
|
188
|
+
while i + col < @cols and i < value.length
|
189
|
+
j = 0
|
190
|
+
while j + row < @rows and j < value[i].length
|
191
|
+
@data[col + i][row + j] = value[i][j].to_f
|
192
|
+
j += 1
|
193
|
+
end
|
194
|
+
i += 1
|
195
|
+
end
|
196
|
+
elsif value.is_a?(Numeric)
|
197
|
+
@data[col][row] = value.to_f
|
198
|
+
else
|
199
|
+
raise(KXI::Exceptions::InvalidTypeException.new(value.type, Numeric, Array))
|
200
|
+
end
|
201
|
+
return value
|
202
|
+
end
|
203
|
+
|
204
|
+
# Iterates over each element of matrix
|
205
|
+
# @yield [col, row, val] Iterator function
|
206
|
+
# @yieldparam [Integer] col Column passed to iterator
|
207
|
+
# @yieldparam [Integer] row Row passed to iterator
|
208
|
+
# @yieldparam [Numeric] val Value of matrix at given column and row
|
209
|
+
def each
|
210
|
+
@cols.times do |col|
|
211
|
+
@rows.times do |row|
|
212
|
+
yield(col, row, @data[col][row])
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
# Returns the transpose of matrix
|
218
|
+
# @return [KXI::Math::Matrix] Transposed matrix
|
219
|
+
def transpose
|
220
|
+
ret = KXI::Math::Matrix.new(@rows, @cols)
|
221
|
+
each do |col, row, value|
|
222
|
+
ret.set(row, col, value)
|
223
|
+
end
|
224
|
+
return ret
|
225
|
+
end
|
226
|
+
|
227
|
+
# Multiplies matrix
|
228
|
+
# @overload *(other)
|
229
|
+
# Scales matrix
|
230
|
+
# @param [Numeric] other Scalar to multiply with
|
231
|
+
# @raise [KXI::Exceptions::InvalidTypeException] When value is of invalid type
|
232
|
+
# @return [KXI::Math::Matrix] Scaled matrix
|
233
|
+
# @overload *(other)
|
234
|
+
# Multiplies matrix by another matrix
|
235
|
+
# @param [KXI::Math::Matrix] other Right-side matrix to multiply with
|
236
|
+
# @raise [KXI::Exceptions::InvalidTypeException] When value is of invalid type
|
237
|
+
# @return [KXI::Math::Matrix] Multiplied matrix
|
238
|
+
# @overload *(other)
|
239
|
+
# Multiplies matrix by vector
|
240
|
+
# @param [KXI::Math::Vector] other Vector to multiply with
|
241
|
+
# @raise [KXI::Exceptions::InvalidTypeException] When value is of invalid type
|
242
|
+
# @return [KXI::Math::Vector] Result of multiplication
|
243
|
+
def *(other)
|
244
|
+
if other.is_a?(Numeric)
|
245
|
+
return KXI::Math::Matrix.new(@cols, @rows) { |c, r| other * get(c, r) }
|
246
|
+
elsif other.is_a?(KXI::Math::Matrix)
|
247
|
+
return KXI::Math::Matrix.new(other.columns, @rows) do |c, r|
|
248
|
+
sum = 0
|
249
|
+
@cols.times { |i| sum += get(i, r) * other.get(c, i) }
|
250
|
+
next sum
|
251
|
+
end
|
252
|
+
elsif other.is_a?(KXI::Math::Vector)
|
253
|
+
return KXI::Math::Vector.new(@rows) do |d|
|
254
|
+
sum = 0
|
255
|
+
@cols.times { |c| sum += get(c, d) * other[c] }
|
256
|
+
next sum
|
257
|
+
end
|
258
|
+
else
|
259
|
+
raise(KXI::Exceptions::InvalidTypeException.new(other.class, Numeric, KXI::Math::Matrix, KXI::Math::Vector))
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
# Compares matrix
|
264
|
+
# @param [void] other Value to compare to
|
265
|
+
# @return [Boolean] True if matrix is equivalent to given value; false otherwise
|
266
|
+
def ==(other)
|
267
|
+
return false unless other.is_a?(KXI::Math::Matrix)
|
268
|
+
return false if @cols != other.columns or @row != other.rows
|
269
|
+
@cols.times do |col|
|
270
|
+
@rows.times do |row|
|
271
|
+
return false if get(col, row) != other.get(col, row)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
def str(num)
|
277
|
+
return (num == num.to_i ? num.to_i : num).to_s
|
278
|
+
end
|
279
|
+
|
280
|
+
# Converts matrix to string
|
281
|
+
# @param [Boolean] d Determines whether string should be decorated
|
282
|
+
# @return [String] String representation of matrix
|
283
|
+
def to_s(d = true)
|
284
|
+
ret = ''
|
285
|
+
just = [0] * @cols
|
286
|
+
each { |c, r, v| d = str(v).length; just[c] = d if d > just[c] }
|
287
|
+
@rows.times do |row|
|
288
|
+
ret += $/ unless row == 0
|
289
|
+
ret += '|' if d
|
290
|
+
@cols.times do |col|
|
291
|
+
ret += ' ' unless col == 0
|
292
|
+
ret += str(get(col, row)).rjust(just[col], ' ')
|
293
|
+
end
|
294
|
+
ret += '|' if d
|
295
|
+
end
|
296
|
+
|
297
|
+
return ret
|
298
|
+
end
|
299
|
+
|
300
|
+
private :sign, :sub, :str
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
data/lib/kxi/math/polynomial.rb
CHANGED
@@ -1,102 +1,142 @@
|
|
1
|
-
# Created by Matyáš Pokorný on 2018-01-26.
|
2
|
-
|
3
|
-
module KXI
|
4
|
-
module Math
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
@cfs
|
17
|
-
end
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
1
|
+
# Created by Matyáš Pokorný on 2018-01-26.
|
2
|
+
|
3
|
+
module KXI
|
4
|
+
module Math
|
5
|
+
# Represents a polynomial
|
6
|
+
class Polynomial
|
7
|
+
# Returns the degree of polynomial
|
8
|
+
# @return [Integer] Degree of polynomial
|
9
|
+
def degree
|
10
|
+
@cfs.length - 1
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns the coefficients of polynomial
|
14
|
+
# @return [Array<Numeric>] Coefficients of polynomial
|
15
|
+
def coefficients
|
16
|
+
@cfs
|
17
|
+
end
|
18
|
+
|
19
|
+
# Instantiates the {KXI::Math::Polynomial} class
|
20
|
+
# @param [Numeric] cfs Coefficients of polynomial
|
21
|
+
def initialize(*cfs)
|
22
|
+
cfs.shift while cfs.length > 1 and cfs[0] == 0
|
23
|
+
@cfs = cfs.collect do |i|
|
24
|
+
raise(KXI::Exceptions::InvalidTypeException.new(i.class, Numeric)) unless i.is_a?(Numeric)
|
25
|
+
i.to_f
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Converts polynomial to string
|
30
|
+
# @return [String] String equivalent to polynomial
|
31
|
+
def to_s
|
32
|
+
return (@cfs[0] == @cfs[0].to_i ? @cfs[0].to_i : @cfs[0]) if degree == 0
|
33
|
+
ret = nil
|
34
|
+
foreach do |k, d|
|
35
|
+
if k != 0
|
36
|
+
k = k.to_i if k.to_i == k
|
37
|
+
if d > 0
|
38
|
+
if ret == nil
|
39
|
+
ret = k >= 0 ? '' : '-'
|
40
|
+
else
|
41
|
+
ret += k >= 0 ? ' + ' : ' - '
|
42
|
+
end
|
43
|
+
ret += (k >= 0 ? k : -k).to_s if k != 1 and k != -1
|
44
|
+
ret += "x#{d > 1 ? "^#{d.to_s}" : ''}"
|
45
|
+
else
|
46
|
+
if ret == nil
|
47
|
+
ret = k >= 0 ? '' : '-'
|
48
|
+
else
|
49
|
+
ret += k >= 0 ? ' + ' : ' - '
|
50
|
+
end
|
51
|
+
ret += (k >= 0 ? k : -k).to_s
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
return ret
|
56
|
+
end
|
57
|
+
|
58
|
+
# Takes the derivative of polynomial
|
59
|
+
# @param [Integer] n Order of derivation
|
60
|
+
# @return [KXI::Math::Polynomial] Polynomial that represents the n-th derivative
|
61
|
+
def derivative(n = 1)
|
62
|
+
return Polynomial.new(0) if degree <= n
|
63
|
+
cfs = []
|
64
|
+
foreach do |k, d|
|
65
|
+
if d >= n
|
66
|
+
cfs.push(k * KXI::Math.pfact(d, d - n))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
return Polynomial.new(*cfs)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Takes the integral of polynomial
|
73
|
+
# @return [KXI::Math::Polynomial] Polynomial that represents the integral
|
74
|
+
def integral
|
75
|
+
cfs = []
|
76
|
+
foreach do |k, d|
|
77
|
+
cfs.push(k / (d + 1))
|
78
|
+
end
|
79
|
+
cfs.push(0)
|
80
|
+
return Polynomial.new(*cfs)
|
81
|
+
end
|
82
|
+
|
83
|
+
# Integrates the polynomial
|
84
|
+
# @param [Numeric] x1 First bound of integration
|
85
|
+
# @param [Numeric] x2 Second bound of integration
|
86
|
+
# @return [Numeric] Result of integration
|
87
|
+
def integrate(x1, x2)
|
88
|
+
min = x1 > x2 ? x2 : x1
|
89
|
+
max = x1 > x2 ? x1 : x2
|
90
|
+
i = integral
|
91
|
+
return i.at(max) - i.at(min)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Returns the value of polynomial
|
95
|
+
# @param [Numeric] x Value of x
|
96
|
+
# @return [Numeric] Value of polynomial at x
|
97
|
+
def at(x)
|
98
|
+
sum = 0
|
99
|
+
foreach do |k, d|
|
100
|
+
sum += k * (x ** d)
|
101
|
+
end
|
102
|
+
return sum
|
103
|
+
end
|
104
|
+
|
105
|
+
# Iterates over every coefficient of polynomial (from higher powers to lower powers)
|
106
|
+
# @yield [k] Iterator
|
107
|
+
# @yieldparam [Numeric] k Coefficient of polynomial
|
108
|
+
def foreach
|
109
|
+
d = degree
|
110
|
+
@cfs.each do |k|
|
111
|
+
yield(k, d)
|
112
|
+
d -= 1
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Multiplies polynomial
|
117
|
+
# @overload *(other)
|
118
|
+
# Multiplies polynomial with coefficient
|
119
|
+
# @param [Numeric] other Coefficient to multiply with
|
120
|
+
# @return [KXI::Math::Polynomial] Result of multiplication
|
121
|
+
# @overload *(other)
|
122
|
+
# Multiplies polynomial with other polynomial
|
123
|
+
# @param [KXI::Math::Polynomial] other Polynomial to multiply with
|
124
|
+
# @return [KXI::Math::Polynomial] Result of multiplication
|
125
|
+
def *(other)
|
126
|
+
if other.is_a?(Polynomial)
|
127
|
+
cfs = [0] * (degree + other.degree + 1)
|
128
|
+
foreach do |k1, d1|
|
129
|
+
other.foreach do |k2, d2|
|
130
|
+
cfs[d1 + d2] += k1 * k2
|
131
|
+
end
|
132
|
+
end
|
133
|
+
return Polynomial.new(*cfs)
|
134
|
+
elsif other.is_a?(Numeric)
|
135
|
+
return @cfs.collect { |k| k * other }
|
136
|
+
else
|
137
|
+
raise(KXI::Exceptions::InvalidTypeException.new(other.class, Numeric, KXI::Math::Polynomial))
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
102
142
|
end
|