symcalc 0.5 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/symcalc.rb +381 -343
- metadata +17 -12
- data/lib/LICENSE.txt +0 -95
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e57698a5da7f300ef21e41ecc27fe2e0be86186213daa9b3736c8603b005b9fa
|
4
|
+
data.tar.gz: b108fddfb4a9ad62327f2b1161e2557b9c4c0fc132403e5bea08658470bc903c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d811d18c96abea729176dd8b918c9c75de4e183706c7b7912d049efd2cfd028321d923cda9149ba443772ef21073aba693476a824b777c758b65f89c9128adf5
|
7
|
+
data.tar.gz: d56da69a5f839a0dd2c7efba40f85f4ca78980219109fad8228182b3cab2db48f7515a1be49910c19d9c4785ab187ad95618c1aaa15e8fa64560dade60b234a3
|
data/lib/symcalc.rb
CHANGED
@@ -1,12 +1,25 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
# Copyright (c) 2023 Kyryl Shyshko
|
1
|
+
# Copyright (c) 2024 Kyryl Shyshko
|
4
2
|
#
|
5
|
-
#
|
6
|
-
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
7
6
|
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
8
|
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
|
16
|
+
# SymCalc auto simplify option
|
17
|
+
if !$SYMCALC_AUTO_SIMPLIFY
|
18
|
+
$SYMCALC_AUTO_SIMPLIFY = true
|
19
|
+
end
|
9
20
|
|
21
|
+
# The SymCalc module
|
22
|
+
module SymCalc
|
10
23
|
|
11
24
|
class Equation
|
12
25
|
|
@@ -14,8 +27,12 @@ class Equation
|
|
14
27
|
self.display()
|
15
28
|
end
|
16
29
|
|
17
|
-
def inspect
|
18
|
-
|
30
|
+
# def inspect
|
31
|
+
# self.display()
|
32
|
+
# end
|
33
|
+
|
34
|
+
def display
|
35
|
+
""
|
19
36
|
end
|
20
37
|
|
21
38
|
def coerce(other)
|
@@ -23,23 +40,43 @@ class Equation
|
|
23
40
|
end
|
24
41
|
|
25
42
|
def *(eq)
|
26
|
-
|
43
|
+
eq = Multiplication.new([self, to_equation(eq)])
|
44
|
+
eq = eq.simplify if $SYMCALC_AUTO_SIMPLIFY
|
45
|
+
eq
|
27
46
|
end
|
28
47
|
|
29
48
|
def /(eq)
|
30
|
-
|
49
|
+
eq = Division.new(self, to_equation(eq))
|
50
|
+
eq = eq.simplify if $SYMCALC_AUTO_SIMPLIFY
|
51
|
+
eq
|
31
52
|
end
|
32
53
|
|
33
54
|
def +(eq)
|
34
|
-
|
55
|
+
eq = Sum.new([self, to_equation(eq)])
|
56
|
+
eq = eq.simplify if $SYMCALC_AUTO_SIMPLIFY
|
57
|
+
eq
|
58
|
+
end
|
59
|
+
|
60
|
+
def -@()
|
61
|
+
eq = Negate.new(self)
|
62
|
+
eq = eq.simplify if $SYMCALC_AUTO_SIMPLIFY
|
63
|
+
eq
|
35
64
|
end
|
36
65
|
|
37
66
|
def -(eq)
|
38
|
-
|
67
|
+
eq = Sum.new([self, Negate.new(to_equation(eq))])
|
68
|
+
eq = eq.simplify if $SYMCALC_AUTO_SIMPLIFY
|
69
|
+
eq
|
39
70
|
end
|
40
71
|
|
41
72
|
def **(eq)
|
42
|
-
|
73
|
+
eq = Power.new(self, to_equation(eq))
|
74
|
+
eq = eq.simplify if $SYMCALC_AUTO_SIMPLIFY
|
75
|
+
eq
|
76
|
+
end
|
77
|
+
|
78
|
+
def __derivative__(variable: nil)
|
79
|
+
raise "No derivative function implemented for this object"
|
43
80
|
end
|
44
81
|
|
45
82
|
# Calculate the derivative of the given function
|
@@ -57,17 +94,19 @@ class Equation
|
|
57
94
|
#
|
58
95
|
def derivative(order: 1, variable: nil)
|
59
96
|
if variable == nil && self.all_variables.size < 2
|
60
|
-
fx = self
|
97
|
+
fx = self.simplify
|
61
98
|
order.times do
|
62
|
-
fx = fx.
|
99
|
+
fx = fx.__derivative__
|
100
|
+
fx = fx.simplify if $SYMCALC_AUTO_SIMPLIFY
|
63
101
|
end
|
64
102
|
return fx
|
65
103
|
elsif variable == nil && self.all_variables.size > 1
|
66
104
|
raise "Expected a variable as input for a #{self.all_variables.size}-dimensional function"
|
67
105
|
else
|
68
|
-
fx = self
|
106
|
+
fx = self.simplify
|
69
107
|
order.times do
|
70
|
-
fx = fx.
|
108
|
+
fx = fx.__derivative__(variable: variable)
|
109
|
+
fx = fx.simplify if $SYMCALC_AUTO_SIMPLIFY
|
71
110
|
end
|
72
111
|
return fx
|
73
112
|
end
|
@@ -81,100 +120,12 @@ class Equation
|
|
81
120
|
# Accepts no arguments
|
82
121
|
#
|
83
122
|
def simplify
|
84
|
-
|
85
|
-
simplified = self.__simplify__
|
86
|
-
|
87
|
-
if [Multiplication, Division].include? simplified.class
|
88
|
-
m_els = simplified.__get_m_elements__(Hash.new)
|
89
|
-
|
90
|
-
if m_els.keys.size == 0
|
91
|
-
return EquationValue.new(0)
|
92
|
-
elsif m_els.keys.size == 1
|
93
|
-
part = m_els.keys[0]
|
94
|
-
power = to_equation(m_els.values[0])
|
95
|
-
if part == "exp"
|
96
|
-
part = (power == to_equation(1)) ? BasicVars::E : Exp.new(power)
|
97
|
-
else
|
98
|
-
part = part ** power if power != to_equation(1)
|
99
|
-
end
|
100
|
-
return part
|
101
|
-
else
|
102
|
-
els_index = 0
|
103
|
-
eq = nil
|
104
|
-
|
105
|
-
coeff = to_equation(1)
|
106
|
-
|
107
|
-
m_els.size.times do |els_index|
|
108
|
-
base = m_els.keys[els_index]
|
109
|
-
power = m_els[base]
|
110
|
-
|
111
|
-
base = base.simplify if base.is_a? Equation
|
112
|
-
power = power.simplify if power.is_a? Equation
|
113
|
-
|
114
|
-
base = to_equation base if base != "exp"
|
115
|
-
power = to_equation power
|
116
|
-
|
117
|
-
if power == to_equation(0)
|
118
|
-
next
|
119
|
-
end
|
120
|
-
|
121
|
-
if base.is_a?(EquationValue) && power.is_a?(EquationValue)
|
122
|
-
case power
|
123
|
-
when EquationValue.new(1)
|
124
|
-
coeff *= base
|
125
|
-
else
|
126
|
-
coeff *= base ** power
|
127
|
-
end
|
128
|
-
next
|
129
|
-
end
|
130
|
-
|
131
|
-
if base == "exp"
|
132
|
-
case power
|
133
|
-
when to_equation(1)
|
134
|
-
part = BasicVars::E
|
135
|
-
else
|
136
|
-
part = Exp.new(power)
|
137
|
-
end
|
138
|
-
else
|
139
|
-
case power
|
140
|
-
when to_equation(1)
|
141
|
-
part = base
|
142
|
-
else
|
143
|
-
part = base ** power
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
if eq == nil
|
148
|
-
eq = part
|
149
|
-
else
|
150
|
-
eq *= part
|
151
|
-
end
|
152
|
-
|
153
|
-
end
|
154
|
-
|
155
|
-
# coeff = to_equation(coeff.eval({}))
|
156
|
-
coeff = coeff.__simplify__
|
157
|
-
|
158
|
-
|
159
|
-
if coeff == to_equation(1)
|
160
|
-
eq = eq
|
161
|
-
elsif coeff == to_equation(0)
|
162
|
-
eq = to_equation(0)
|
163
|
-
elsif eq == nil
|
164
|
-
eq = coeff
|
165
|
-
else
|
166
|
-
eq = coeff * eq
|
167
|
-
end
|
168
|
-
|
169
|
-
return eq
|
170
|
-
end
|
171
|
-
|
172
|
-
else
|
173
|
-
return simplified
|
174
|
-
end
|
175
|
-
|
123
|
+
self.__simplify__
|
176
124
|
end
|
177
125
|
|
126
|
+
def __eval__(var_hash)
|
127
|
+
raise "__eval__ method not implemented for this class"
|
128
|
+
end
|
178
129
|
|
179
130
|
# Evaluates the function at given variable values
|
180
131
|
# Accepts the hash of variables and their values to evalualte the function
|
@@ -184,28 +135,42 @@ class Equation
|
|
184
135
|
# fx = x ** 2
|
185
136
|
# puts fx.eval(x: 3)
|
186
137
|
#
|
187
|
-
def eval(var_hash)
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
end
|
199
|
-
return computed
|
138
|
+
def eval(var_hash = nil)
|
139
|
+
var_hash = Hash.new if !var_hash
|
140
|
+
if var_hash.values.size == 0
|
141
|
+
result = self.__eval__(var_hash)
|
142
|
+
elsif !var_hash.values[0].is_a?(Array)
|
143
|
+
result = self.__eval__ var_hash
|
144
|
+
elsif var_hash.values[0].is_a? Array
|
145
|
+
result = []
|
146
|
+
var_hash.values[0].size.times do |i|
|
147
|
+
hash = var_hash.map {|k, v| [k, v[i]]}.to_h
|
148
|
+
result << self.__eval__(hash)
|
200
149
|
end
|
201
|
-
|
202
|
-
|
203
|
-
# return nil
|
204
|
-
# end
|
150
|
+
end
|
151
|
+
result
|
205
152
|
end
|
206
153
|
|
207
154
|
|
208
155
|
|
156
|
+
def __sub__ original, replacement
|
157
|
+
return to_equation(replacement) if self == to_equation(original)
|
158
|
+
return self
|
159
|
+
end
|
160
|
+
|
161
|
+
# Returns an equation with an expression substituted for the replacement
|
162
|
+
#
|
163
|
+
# Example:
|
164
|
+
# a = SymCalc.var("a")
|
165
|
+
# f = a ** 2
|
166
|
+
# x = SymCalc.var("x")
|
167
|
+
# puts f.sub(a, 3 * x) # => (3 * x) ** 2
|
168
|
+
#
|
169
|
+
def sub original, replacement
|
170
|
+
eq = self.__sub__(original, replacement)
|
171
|
+
eq = eq.simplify if $SYMCALC_AUTO_SIMPLIFY
|
172
|
+
eq
|
173
|
+
end
|
209
174
|
|
210
175
|
end
|
211
176
|
|
@@ -232,7 +197,11 @@ class EquationValue < Equation
|
|
232
197
|
end
|
233
198
|
|
234
199
|
def __eval__ var_hash
|
235
|
-
|
200
|
+
if @value.is_a? Integer
|
201
|
+
return @value.to_f
|
202
|
+
else
|
203
|
+
return @value
|
204
|
+
end
|
236
205
|
end
|
237
206
|
|
238
207
|
def __derivative__ variable: nil
|
@@ -240,38 +209,52 @@ class EquationValue < Equation
|
|
240
209
|
end
|
241
210
|
|
242
211
|
def ==(value)
|
243
|
-
|
244
|
-
return @value == value.value
|
245
|
-
else
|
246
|
-
return false
|
247
|
-
end
|
212
|
+
@value == value
|
248
213
|
end
|
249
214
|
|
250
|
-
def
|
251
|
-
|
215
|
+
def all_variables
|
216
|
+
[]
|
252
217
|
end
|
253
218
|
|
254
|
-
|
255
|
-
|
256
|
-
|
219
|
+
end
|
220
|
+
|
221
|
+
# Implements the Constant class. Behaves like EquationValue when evaluating and like Variable when printing
|
222
|
+
class Constant < Equation
|
223
|
+
|
224
|
+
attr_accessor :value, :name
|
225
|
+
|
226
|
+
def initialize(name, value)
|
227
|
+
@value = value
|
228
|
+
@name = name
|
229
|
+
end
|
230
|
+
|
231
|
+
def display
|
232
|
+
return @name
|
257
233
|
end
|
258
234
|
|
259
|
-
def
|
260
|
-
if
|
261
|
-
|
235
|
+
def __eval__ var_hash
|
236
|
+
if @value.is_a? Integer
|
237
|
+
return @value.to_f
|
262
238
|
else
|
263
|
-
|
239
|
+
return @value
|
264
240
|
end
|
265
|
-
return var_hash
|
266
241
|
end
|
267
242
|
|
243
|
+
def __derivative__ variable: nil
|
244
|
+
return EquationValue.new 0
|
245
|
+
end
|
246
|
+
|
247
|
+
def ==(value)
|
248
|
+
@value == value
|
249
|
+
end
|
268
250
|
|
269
251
|
def all_variables
|
270
252
|
[]
|
271
253
|
end
|
272
|
-
|
254
|
+
|
273
255
|
end
|
274
256
|
|
257
|
+
|
275
258
|
# Implements the Variable class
|
276
259
|
class Variable < Equation
|
277
260
|
|
@@ -284,20 +267,16 @@ class Variable < Equation
|
|
284
267
|
# fx = x ** 2
|
285
268
|
# fx.eval # => 25
|
286
269
|
#
|
287
|
-
def initialize name
|
270
|
+
def initialize name
|
288
271
|
@name = name
|
289
|
-
@fixed_value = fixed_value
|
290
272
|
end
|
291
273
|
|
292
274
|
def display
|
293
275
|
return @name
|
294
276
|
end
|
295
277
|
|
296
|
-
|
297
278
|
def __eval__ var_hash
|
298
|
-
if @
|
299
|
-
return @fixed_value
|
300
|
-
elsif var_hash.keys.include?(@name.to_sym) or var_hash.keys.include?(@name.to_s)
|
279
|
+
if var_hash.keys.include?(@name.to_sym) or var_hash.keys.include?(@name.to_s)
|
301
280
|
return (var_hash[@name.to_sym] or var_hash[@name.to_s])
|
302
281
|
else
|
303
282
|
raise "No value provided for #{@name.to_s} in eval"
|
@@ -313,13 +292,8 @@ class Variable < Equation
|
|
313
292
|
end
|
314
293
|
end
|
315
294
|
|
316
|
-
def
|
317
|
-
|
318
|
-
var_hash[self] += 1
|
319
|
-
else
|
320
|
-
var_hash[self] = 1
|
321
|
-
end
|
322
|
-
return var_hash
|
295
|
+
def __simplify__
|
296
|
+
self
|
323
297
|
end
|
324
298
|
|
325
299
|
def all_variables
|
@@ -327,160 +301,183 @@ class Variable < Equation
|
|
327
301
|
end
|
328
302
|
end
|
329
303
|
|
330
|
-
# Basic variables that are already implemented in SymCalc and have fixed values
|
331
|
-
module BasicVars
|
332
|
-
|
333
|
-
E = Variable.new "e", Math::E
|
334
|
-
|
335
|
-
end
|
336
304
|
|
337
305
|
# Implements sum operations in SymCalc
|
338
306
|
class Sum < Equation
|
339
|
-
def initialize
|
340
|
-
@
|
341
|
-
|
307
|
+
def initialize elements
|
308
|
+
@elements = []
|
309
|
+
elements.each do |eq|
|
310
|
+
if eq.is_a? Sum
|
311
|
+
@elements += eq.instance_variable_get(:@elements)
|
312
|
+
else
|
313
|
+
@elements << eq
|
314
|
+
end
|
315
|
+
end
|
342
316
|
end
|
343
317
|
|
344
318
|
def display
|
345
|
-
return "(#{
|
319
|
+
return @elements.map{|eq| "(#{eq.display})"}.join(" + ")
|
346
320
|
end
|
347
321
|
|
348
322
|
def __eval__ var_hash
|
349
|
-
return @
|
323
|
+
return @elements.map{|eq| eq.eval(var_hash)}.sum
|
350
324
|
end
|
351
325
|
|
352
326
|
def __derivative__ variable: nil
|
353
|
-
return
|
327
|
+
return Sum.new(@elements.map{|eq| eq.__derivative__(variable: variable)})
|
354
328
|
end
|
355
329
|
|
356
330
|
def __simplify__
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
return @lside
|
365
|
-
else
|
366
|
-
return self
|
331
|
+
simplified = @elements.map{|eq| eq.__simplify__}
|
332
|
+
|
333
|
+
simplified.filter! do |el|
|
334
|
+
if el.is_a? EquationValue
|
335
|
+
next if el.value == 0
|
336
|
+
end
|
337
|
+
true
|
367
338
|
end
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
if el_hash.keys.include? self
|
372
|
-
el_hash[self] += 1
|
373
|
-
else
|
374
|
-
el_hash[self] = 1
|
339
|
+
|
340
|
+
if simplified.size == 1
|
341
|
+
return simplified[0]
|
375
342
|
end
|
376
|
-
|
343
|
+
|
344
|
+
return Sum.new(simplified)
|
377
345
|
end
|
378
346
|
|
379
347
|
def all_variables
|
380
|
-
return
|
348
|
+
return @elements.map{|eq| eq.all_variables }.flatten.uniq
|
381
349
|
end
|
382
350
|
|
351
|
+
def __sub__ original, replacement
|
352
|
+
return to_equation(replacement) if self == to_equation(original)
|
353
|
+
|
354
|
+
return Sum.new(@elements.map{|eq| eq.__sub__(original, replacement)})
|
355
|
+
end
|
383
356
|
end
|
384
357
|
|
385
358
|
# Implements the subtraction operation in SymCalc
|
386
|
-
class
|
387
|
-
def initialize
|
388
|
-
@
|
389
|
-
@rside = rside
|
359
|
+
class Negate < Equation
|
360
|
+
def initialize eq
|
361
|
+
@eq = eq
|
390
362
|
end
|
391
363
|
|
392
364
|
def display
|
393
|
-
return "
|
365
|
+
return "-(#{@eq.display})"
|
394
366
|
end
|
395
367
|
|
396
368
|
def __eval__ var_hash
|
397
|
-
return
|
369
|
+
return -@eq.eval(var_hash)
|
398
370
|
end
|
399
371
|
|
400
372
|
def __derivative__ variable: nil
|
401
|
-
return
|
402
|
-
end
|
403
|
-
|
404
|
-
def __get_m_elements__ el_hash
|
405
|
-
if el_hash.keys.include? self
|
406
|
-
el_hash[self] += 1
|
407
|
-
else
|
408
|
-
el_hash[self] = 1
|
409
|
-
end
|
410
|
-
return el_hash
|
373
|
+
return -@eq.__derivative__(variable: variable)
|
411
374
|
end
|
412
375
|
|
413
376
|
def __simplify__
|
414
|
-
|
415
|
-
@rside = @rside.__simplify__
|
416
|
-
|
417
|
-
if (@lside.is_a? EquationValue) && (@rside.is_a? EquationValue)
|
418
|
-
return EquationValue.new((@lside - @rside).eval(Hash.new))
|
419
|
-
elsif @rside == EquationValue.new(0)
|
420
|
-
return @lside
|
421
|
-
elsif @lside == EquationValue.new(0)
|
422
|
-
return -1 * @rside
|
423
|
-
elsif @lside == @rside
|
424
|
-
return EquationValue.new(0)
|
425
|
-
else
|
426
|
-
return self
|
427
|
-
end
|
377
|
+
return Negate.new(@eq.__simplify__)
|
428
378
|
end
|
429
379
|
|
430
380
|
def all_variables
|
431
|
-
return
|
381
|
+
return @eq.all_variables
|
382
|
+
end
|
383
|
+
|
384
|
+
def __sub__ original, replacement
|
385
|
+
return to_equation(replacement) if self == to_equation(original)
|
386
|
+
return Negate.new(@eq.__sub__(original, replacement))
|
432
387
|
end
|
433
388
|
end
|
434
389
|
|
435
390
|
# Implements the multiplication operation in SymCalc
|
436
391
|
class Multiplication < Equation
|
437
|
-
def initialize
|
438
|
-
@
|
439
|
-
|
392
|
+
def initialize elements
|
393
|
+
@elements = []
|
394
|
+
elements.each do |el|
|
395
|
+
if el.is_a? Multiplication
|
396
|
+
@elements += el.instance_variable_get(:@elements)
|
397
|
+
else
|
398
|
+
@elements << el
|
399
|
+
end
|
400
|
+
end
|
440
401
|
end
|
441
402
|
|
442
403
|
def display
|
443
|
-
return "(#{
|
404
|
+
return @elements.map{|el| "(#{el.display})"}.join(" * ")
|
444
405
|
end
|
445
406
|
|
446
407
|
def __eval__ var_hash
|
447
|
-
|
408
|
+
result = 1
|
409
|
+
@elements.each do |el|
|
410
|
+
result *= el.__eval__(var_hash)
|
411
|
+
end
|
412
|
+
result
|
448
413
|
end
|
449
414
|
|
450
415
|
def __derivative__ variable: nil
|
451
|
-
|
416
|
+
|
417
|
+
sum_of_mults_arr = []
|
418
|
+
|
419
|
+
@elements.size.times do |element_index|
|
420
|
+
mult_arr = []
|
421
|
+
|
422
|
+
|
423
|
+
mult_arr << @elements[element_index].__derivative__(variable: variable)
|
424
|
+
|
425
|
+
@elements.size.times do |mult_el_index|
|
426
|
+
if element_index == mult_el_index
|
427
|
+
next
|
428
|
+
end
|
429
|
+
mult_arr << @elements[mult_el_index]
|
430
|
+
end
|
431
|
+
|
432
|
+
sum_of_mults_arr << Multiplication.new(mult_arr)
|
433
|
+
end
|
434
|
+
|
435
|
+
return Sum.new(sum_of_mults_arr)
|
452
436
|
end
|
453
437
|
|
454
438
|
def __simplify__
|
455
|
-
@lside = @lside.__simplify__
|
456
|
-
@rside = @rside.__simplify__
|
457
439
|
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
440
|
+
numbers = []
|
441
|
+
simplified = []
|
442
|
+
|
443
|
+
@elements.each do |eq|
|
444
|
+
s_eq = eq.__simplify__()
|
445
|
+
|
446
|
+
if s_eq.is_a? EquationValue
|
447
|
+
if s_eq.value == 0
|
448
|
+
return EquationValue.new(0)
|
449
|
+
elsif s_eq.value == 1
|
450
|
+
next
|
451
|
+
else
|
452
|
+
numbers << s_eq.value
|
453
|
+
end
|
468
454
|
else
|
469
|
-
|
470
|
-
end
|
471
|
-
|
472
|
-
|
455
|
+
simplified << s_eq
|
456
|
+
end
|
457
|
+
end
|
458
|
+
|
459
|
+
|
460
|
+
coeff = 1
|
461
|
+
numbers.each {|n| coeff *= n}
|
462
|
+
|
463
|
+
if coeff != 1
|
464
|
+
simplified.insert 0, EquationValue.new(coeff)
|
465
|
+
end
|
466
|
+
|
467
|
+
if simplified.size == 1
|
468
|
+
return simplified[0]
|
473
469
|
end
|
470
|
+
|
471
|
+
return Multiplication.new(simplified)
|
474
472
|
end
|
475
473
|
|
476
|
-
def
|
477
|
-
|
478
|
-
el_hash = @rside.__get_m_elements__(el_hash)
|
479
|
-
return el_hash
|
474
|
+
def all_variables
|
475
|
+
return @elements.map{|el| el.all_variables}.flatten.uniq
|
480
476
|
end
|
481
477
|
|
482
|
-
def
|
483
|
-
return (
|
478
|
+
def __sub__ original, replacement
|
479
|
+
return to_equation(replacement) if self == to_equation(original)
|
480
|
+
return Multiplication.new(@elements.map{|el| el.__sub__(original, replacement)})
|
484
481
|
end
|
485
482
|
end
|
486
483
|
|
@@ -503,8 +500,8 @@ class Division < Equation
|
|
503
500
|
end
|
504
501
|
|
505
502
|
def __derivative__ variable: nil
|
506
|
-
return (@lside * @rside ** (-1)).derivative(variable: variable)
|
507
|
-
|
503
|
+
# return (@lside * @rside ** (-1)).derivative(variable: variable)
|
504
|
+
return (@lside.derivative * @rside - @lside * @rside.derivative) / (@rside ** 2)
|
508
505
|
end
|
509
506
|
|
510
507
|
def __simplify__
|
@@ -525,23 +522,15 @@ class Division < Equation
|
|
525
522
|
end
|
526
523
|
end
|
527
524
|
|
528
|
-
def __get_m_elements__ el_hash
|
529
|
-
mult = @lside.__get_m_elements__(el_hash)
|
530
|
-
div = @rside.__get_m_elements__({})
|
531
|
-
div.each do |k, v|
|
532
|
-
if mult.keys.include? k
|
533
|
-
mult[k] -= v
|
534
|
-
else
|
535
|
-
mult[k] = -v
|
536
|
-
end
|
537
|
-
end
|
538
|
-
return mult
|
539
|
-
end
|
540
|
-
|
541
525
|
|
542
526
|
def all_variables
|
543
527
|
return (@lside.all_variables + @rside.all_variables).uniq
|
544
528
|
end
|
529
|
+
|
530
|
+
def __sub__ original, replacement
|
531
|
+
return to_equation(replacement) if self == to_equation(original)
|
532
|
+
return @lside.__sub__(original, replacement) / @rside.__sub__(original, replacement)
|
533
|
+
end
|
545
534
|
end
|
546
535
|
|
547
536
|
|
@@ -584,18 +573,14 @@ class Exp < Equation
|
|
584
573
|
end
|
585
574
|
end
|
586
575
|
|
587
|
-
def __get_m_elements__ var_hash
|
588
|
-
if var_hash.keys.include? "exp"
|
589
|
-
var_hash["exp"] += @power
|
590
|
-
else
|
591
|
-
var_hash["exp"] = @power
|
592
|
-
end
|
593
|
-
return var_hash
|
594
|
-
end
|
595
|
-
|
596
576
|
def all_variables
|
597
577
|
return @power.all_variables
|
598
578
|
end
|
579
|
+
|
580
|
+
def __sub__ original, replacement
|
581
|
+
return to_equation(replacement) if self == to_equation(original)
|
582
|
+
return Exp.new(@power.__sub__(original, replacement))
|
583
|
+
end
|
599
584
|
end
|
600
585
|
|
601
586
|
|
@@ -631,37 +616,29 @@ class Power < Equation
|
|
631
616
|
return false
|
632
617
|
end
|
633
618
|
end
|
634
|
-
|
635
|
-
def __get_m_elements__ var_hash
|
636
|
-
elms = @base.__get_m_elements__({})
|
637
|
-
elms.each do |k, v|
|
638
|
-
if var_hash.keys.include? k
|
639
|
-
var_hash[k] += v * @power
|
640
|
-
else
|
641
|
-
var_hash[k] = @power
|
642
|
-
end
|
643
|
-
end
|
644
|
-
return var_hash
|
645
|
-
end
|
646
|
-
|
619
|
+
|
647
620
|
def __simplify__
|
648
621
|
|
649
|
-
|
650
|
-
|
622
|
+
s_base = @base.__simplify__
|
623
|
+
s_power = @power.__simplify__
|
651
624
|
|
652
|
-
if
|
625
|
+
if s_power == EquationValue.new(0)
|
653
626
|
return EquationValue.new(1)
|
654
|
-
elsif
|
655
|
-
return
|
656
|
-
elsif
|
657
|
-
computed =
|
627
|
+
elsif s_power == EquationValue.new(1)
|
628
|
+
return s_base
|
629
|
+
elsif s_base.is_a?(EquationValue) && s_power.is_a?(EquationValue)
|
630
|
+
computed = s_base.value ** s_power.value
|
658
631
|
if computed.to_s.size <= 6
|
659
632
|
return to_equation(computed)
|
660
633
|
else
|
661
|
-
return
|
634
|
+
return s_base ** power
|
662
635
|
end
|
636
|
+
elsif s_base.is_a?(Power)
|
637
|
+
new_base = s_base.base
|
638
|
+
new_power = s_base.power * s_power
|
639
|
+
return (new_base ** new_power).__simplify__
|
663
640
|
else
|
664
|
-
return
|
641
|
+
return Power.new(s_base, s_power)
|
665
642
|
end
|
666
643
|
|
667
644
|
end
|
@@ -669,6 +646,11 @@ class Power < Equation
|
|
669
646
|
def all_variables
|
670
647
|
return (@base.all_variables + @power.all_variables).uniq
|
671
648
|
end
|
649
|
+
|
650
|
+
def __sub__ original, replacement
|
651
|
+
return to_equation(replacement) if self == to_equation(original)
|
652
|
+
return @base.__sub__(original, replacement) ** @power.__sub__(original, replacement)
|
653
|
+
end
|
672
654
|
end
|
673
655
|
|
674
656
|
# Implements the sin operation in SymCalc
|
@@ -689,18 +671,18 @@ class Sin < Equation
|
|
689
671
|
return Cos.new(@eq) * @eq.derivative(variable: variable)
|
690
672
|
end
|
691
673
|
|
692
|
-
def
|
693
|
-
|
694
|
-
var_hash[self] += 1
|
695
|
-
else
|
696
|
-
var_hash[self] = 1
|
697
|
-
end
|
698
|
-
return var_hash
|
674
|
+
def __simplify__
|
675
|
+
return Sin.new(@eq.__simplify__)
|
699
676
|
end
|
700
677
|
|
701
678
|
def all_variables
|
702
679
|
return @eq.all_variables
|
703
680
|
end
|
681
|
+
|
682
|
+
def __sub__ original, replacement
|
683
|
+
return to_equation(replacement) if self == to_equation(original)
|
684
|
+
return Sin.new(@eq.__sub__(original, replacement))
|
685
|
+
end
|
704
686
|
end
|
705
687
|
|
706
688
|
# Implements the cos operation in SymCalc
|
@@ -721,18 +703,18 @@ class Cos < Equation
|
|
721
703
|
return -1 * Sin.new(@eq) * @eq.derivative(variable: variable)
|
722
704
|
end
|
723
705
|
|
724
|
-
def
|
725
|
-
|
726
|
-
var_hash[self] += 1
|
727
|
-
else
|
728
|
-
var_hash[self] = 1
|
729
|
-
end
|
730
|
-
return var_hash
|
706
|
+
def __simplify__
|
707
|
+
return Cos.new(@eq.__simplify__)
|
731
708
|
end
|
732
709
|
|
733
710
|
def all_variables
|
734
711
|
return @eq.all_variables
|
735
712
|
end
|
713
|
+
|
714
|
+
def __sub__ original, replacement
|
715
|
+
return to_equation(replacement) if self == to_equation(original)
|
716
|
+
return Cos.new(@eq.__sub__(original, replacement))
|
717
|
+
end
|
736
718
|
end
|
737
719
|
|
738
720
|
|
@@ -757,18 +739,18 @@ class Ln < Equation
|
|
757
739
|
return 1 / @eq * @eq.derivative(variable: variable)
|
758
740
|
end
|
759
741
|
|
760
|
-
def
|
761
|
-
|
762
|
-
var_hash[self] += 1
|
763
|
-
else
|
764
|
-
var_hash[self] = 1
|
765
|
-
end
|
766
|
-
return var_hash
|
742
|
+
def __simplify__
|
743
|
+
return Ln.new(@eq.__simplify__)
|
767
744
|
end
|
768
|
-
|
745
|
+
|
769
746
|
def all_variables
|
770
747
|
return @eq.all_variables
|
771
748
|
end
|
749
|
+
|
750
|
+
def __sub__ original, replacement
|
751
|
+
return to_equation(replacement) if self == to_equation(original)
|
752
|
+
return Ln.new(@eq.__sub__(original, replacement))
|
753
|
+
end
|
772
754
|
end
|
773
755
|
|
774
756
|
# Implements the logarithm operation in SymCalc
|
@@ -776,7 +758,7 @@ class Log < Equation
|
|
776
758
|
|
777
759
|
attr_accessor :eq, :base
|
778
760
|
|
779
|
-
# Implements the
|
761
|
+
# Implements the logarithm operation in SymCalc
|
780
762
|
# Accepts the base and equation arguments
|
781
763
|
#
|
782
764
|
# Example:
|
@@ -801,53 +783,109 @@ class Log < Equation
|
|
801
783
|
return 1 / (Ln.new(@base) * @eq) * @eq.derivative(variable: variable)
|
802
784
|
end
|
803
785
|
|
804
|
-
def
|
805
|
-
|
806
|
-
var_hash[self] += 1
|
807
|
-
else
|
808
|
-
var_hash[self] = 1
|
809
|
-
end
|
810
|
-
return var_hash
|
786
|
+
def __simplify__
|
787
|
+
return Log.new(@base.__simplify__, @eq.__simplify__)
|
811
788
|
end
|
812
789
|
|
813
790
|
def all_variables
|
814
791
|
return (@base.all_variables + @eq.all_variables).uniq
|
815
792
|
end
|
793
|
+
|
794
|
+
def __sub__ original, replacement
|
795
|
+
return to_equation(replacement) if self == to_equation(original)
|
796
|
+
return Log.new(@base.__sub__(original, replacement), @eq.__sub__(original, replacement))
|
797
|
+
end
|
816
798
|
end
|
817
799
|
|
818
|
-
#
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
823
|
-
|
800
|
+
# Implements the absolute value operation in SymCalc
|
801
|
+
class Abs < Equation
|
802
|
+
|
803
|
+
attr_accessor :eq
|
804
|
+
|
805
|
+
def initialize eq
|
806
|
+
@eq = to_equation(eq)
|
824
807
|
end
|
825
808
|
|
826
|
-
|
827
|
-
|
828
|
-
return Cos.new(to_equation(eq))
|
809
|
+
def display
|
810
|
+
return "|#{@eq.display}|"
|
829
811
|
end
|
830
812
|
|
831
|
-
|
832
|
-
|
833
|
-
|
813
|
+
def __eval__ var_hash
|
814
|
+
return @eq.eval(var_hash).abs
|
815
|
+
end
|
816
|
+
|
817
|
+
def __derivative__ variable: nil
|
818
|
+
return @eq / Abs.new(@eq) * @eq.derivative(variable: variable)
|
834
819
|
end
|
835
820
|
|
836
|
-
|
837
|
-
|
838
|
-
|
821
|
+
def __simplify__
|
822
|
+
if @eq.is_a?(Power) && @eq.power.is_a?(EquationValue) && @eq.power.value.is_a?(Numeric) && (@eq.power.value % 2 == 0)
|
823
|
+
return @eq
|
824
|
+
end
|
825
|
+
self
|
839
826
|
end
|
840
827
|
|
841
|
-
|
842
|
-
|
843
|
-
return Exp.new(to_equation(power))
|
828
|
+
def all_variables
|
829
|
+
return @eq.all_variables
|
844
830
|
end
|
845
831
|
|
846
|
-
|
847
|
-
|
848
|
-
|
832
|
+
def __sub__ original, replacement
|
833
|
+
return to_equation(replacement) if self == to_equation(original)
|
834
|
+
return Abs.new(@eq.__sub__(original, replacement))
|
849
835
|
end
|
836
|
+
end
|
837
|
+
|
838
|
+
|
839
|
+
# Basic variables that are already implemented in SymCalc and have fixed values
|
840
|
+
module Constants
|
850
841
|
|
851
|
-
|
842
|
+
Pi = Constant.new "pi", Math::PI
|
843
|
+
E = Constant.new "e", Math::E
|
844
|
+
|
845
|
+
end
|
846
|
+
|
847
|
+
|
848
|
+
|
849
|
+
|
850
|
+
# sin(equation) is the same as Sin.new(equation), just shorter
|
851
|
+
def sin(eq)
|
852
|
+
return Sin.new(to_equation(eq))
|
853
|
+
end
|
854
|
+
|
855
|
+
# cos(equation) is the same as Cos.new(equation), just shorter
|
856
|
+
def cos(eq)
|
857
|
+
return Cos.new(to_equation(eq))
|
858
|
+
end
|
859
|
+
|
860
|
+
# ln(equation) is the same as Ln.new(equation), just shorter
|
861
|
+
def ln(eq)
|
862
|
+
return Ln.new(to_equation(eq))
|
863
|
+
end
|
864
|
+
|
865
|
+
# log(base, equation) is the same as Log.new(base, equation), just shorter
|
866
|
+
def log(base, eq)
|
867
|
+
return Log.new(to_equation(base), to_equation(eq))
|
868
|
+
end
|
869
|
+
|
870
|
+
# exp(equation) is the same as Exp.new(equation), just shorter
|
871
|
+
def exp(power)
|
872
|
+
return Exp.new(to_equation(power))
|
873
|
+
end
|
874
|
+
|
875
|
+
# var(name) is the same as Variable.new(name), just shorter
|
876
|
+
def var(name)
|
877
|
+
Variable.new name
|
878
|
+
end
|
879
|
+
|
880
|
+
def const(name, value)
|
881
|
+
Constant.new name, value
|
882
|
+
end
|
883
|
+
|
884
|
+
# abs(equation) is the same as Abs.new(equation), just shorter
|
885
|
+
def abs eq
|
886
|
+
return Abs.new(to_equation(eq))
|
887
|
+
end
|
888
|
+
|
889
|
+
module_function :sin, :cos, :ln, :log, :exp, :var, :abs, :const
|
852
890
|
|
853
891
|
end
|
metadata
CHANGED
@@ -1,28 +1,34 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: symcalc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kyryl Shyshko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-07-29 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description: SymCalc
|
14
|
-
|
13
|
+
description: 'SymCalc adds symbolic mathematics and calculus to your code. Create,
|
14
|
+
evaluate and differentiate mathematical functions with a single method call.
|
15
|
+
|
16
|
+
'
|
15
17
|
email: kyryloshy@gmail.com
|
16
18
|
executables: []
|
17
19
|
extensions: []
|
18
20
|
extra_rdoc_files: []
|
19
21
|
files:
|
20
|
-
- lib/LICENSE.txt
|
21
22
|
- lib/symcalc.rb
|
22
|
-
homepage: https://
|
23
|
+
homepage: https://symcalc.site/ruby
|
23
24
|
licenses:
|
24
|
-
-
|
25
|
-
metadata:
|
25
|
+
- Apache-2.0
|
26
|
+
metadata:
|
27
|
+
changelog_uri: https://symcalc.site/ruby/changelog
|
28
|
+
documentation_uri: https://symcalc.site/ruby/docs
|
29
|
+
homepage_uri: https://symcalc.site/ruby
|
30
|
+
source_code_uri: https://github.com/symcalc/symcalc-ruby
|
31
|
+
bug_tracker_uri: https://github.com/symcalc/symcalc-ruby/issues
|
26
32
|
post_install_message:
|
27
33
|
rdoc_options: []
|
28
34
|
require_paths:
|
@@ -31,16 +37,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
31
37
|
requirements:
|
32
38
|
- - ">="
|
33
39
|
- !ruby/object:Gem::Version
|
34
|
-
version:
|
40
|
+
version: 3.0.0
|
35
41
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
36
42
|
requirements:
|
37
43
|
- - ">="
|
38
44
|
- !ruby/object:Gem::Version
|
39
45
|
version: '0'
|
40
46
|
requirements: []
|
41
|
-
rubygems_version: 3.
|
47
|
+
rubygems_version: 3.5.10
|
42
48
|
signing_key:
|
43
49
|
specification_version: 4
|
44
|
-
summary:
|
45
|
-
in code.
|
50
|
+
summary: Symbolic mathematics and calculus in Ruby
|
46
51
|
test_files: []
|
data/lib/LICENSE.txt
DELETED
@@ -1,95 +0,0 @@
|
|
1
|
-
Attribution-ShareAlike 4.0 International
|
2
|
-
|
3
|
-
By exercising the Licensed Rights (defined below), You accept and agree to be bound by the terms and conditions of this Creative Commons Attribution-ShareAlike 4.0 International Public License ("Public License"). To the extent this Public License may be interpreted as a contract, You are granted the Licensed Rights in consideration of Your acceptance of these terms and conditions, and the Licensor grants You such rights in consideration of benefits the Licensor receives from making the Licensed Material available under these terms and conditions.
|
4
|
-
|
5
|
-
Section 1 – Definitions.
|
6
|
-
|
7
|
-
Adapted Material means material subject to Copyright and Similar Rights that is derived from or based upon the Licensed Material and in which the Licensed Material is translated, altered, arranged, transformed, or otherwise modified in a manner requiring permission under the Copyright and Similar Rights held by the Licensor. For purposes of this Public License, where the Licensed Material is a musical work, performance, or sound recording, Adapted Material is always produced where the Licensed Material is synched in timed relation with a moving image.
|
8
|
-
Adapter's License means the license You apply to Your Copyright and Similar Rights in Your contributions to Adapted Material in accordance with the terms and conditions of this Public License.
|
9
|
-
BY-SA Compatible License means a license listed at creativecommons.org/compatiblelicenses , approved by Creative Commons as essentially the equivalent of this Public License.
|
10
|
-
Copyright and Similar Rights means copyright and/or similar rights closely related to copyright including, without limitation, performance, broadcast, sound recording, and Sui Generis Database Rights, without regard to how the rights are labeled or categorized. For purposes of this Public License, the rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights.
|
11
|
-
Effective Technological Measures means those measures that, in the absence of proper authority, may not be circumvented under laws fulfilling obligations under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, and/or similar international agreements.
|
12
|
-
Exceptions and Limitations means fair use, fair dealing, and/or any other exception or limitation to Copyright and Similar Rights that applies to Your use of the Licensed Material.
|
13
|
-
License Elements means the license attributes listed in the name of a Creative Commons Public License. The License Elements of this Public License are Attribution and ShareAlike.
|
14
|
-
Licensed Material means the artistic or literary work, database, or other material to which the Licensor applied this Public License.
|
15
|
-
Licensed Rights means the rights granted to You subject to the terms and conditions of this Public License, which are limited to all Copyright and Similar Rights that apply to Your use of the Licensed Material and that the Licensor has authority to license.
|
16
|
-
Licensor means the individual(s) or entity(ies) granting rights under this Public License.
|
17
|
-
Share means to provide material to the public by any means or process that requires permission under the Licensed Rights, such as reproduction, public display, public performance, distribution, dissemination, communication, or importation, and to make material available to the public including in ways that members of the public may access the material from a place and at a time individually chosen by them.
|
18
|
-
Sui Generis Database Rights means rights other than copyright resulting from Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, as amended and/or succeeded, as well as other essentially equivalent rights anywhere in the world.
|
19
|
-
You means the individual or entity exercising the Licensed Rights under this Public License. Your has a corresponding meaning.
|
20
|
-
Section 2 – Scope.
|
21
|
-
|
22
|
-
License grant .
|
23
|
-
Subject to the terms and conditions of this Public License, the Licensor hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, irrevocable license to exercise the Licensed Rights in the Licensed Material to:
|
24
|
-
reproduce and Share the Licensed Material, in whole or in part; and
|
25
|
-
produce, reproduce, and Share Adapted Material.
|
26
|
-
Exceptions and Limitations . For the avoidance of doubt, where Exceptions and Limitations apply to Your use, this Public License does not apply, and You do not need to comply with its terms and conditions.
|
27
|
-
Term . The term of this Public License is specified in Section 6(a) .
|
28
|
-
Media and formats; technical modifications allowed . The Licensor authorizes You to exercise the Licensed Rights in all media and formats whether now known or hereafter created, and to make technical modifications necessary to do so. The Licensor waives and/or agrees not to assert any right or authority to forbid You from making technical modifications necessary to exercise the Licensed Rights, including technical modifications necessary to circumvent Effective Technological Measures. For purposes of this Public License, simply making modifications authorized by this Section 2(a)(4) never produces Adapted Material.
|
29
|
-
Downstream recipients .
|
30
|
-
Offer from the Licensor – Licensed Material . Every recipient of the Licensed Material automatically receives an offer from the Licensor to exercise the Licensed Rights under the terms and conditions of this Public License.
|
31
|
-
Additional offer from the Licensor – Adapted Material . Every recipient of Adapted Material from You automatically receives an offer from the Licensor to exercise the Licensed Rights in the Adapted Material under the conditions of the Adapter’s License You apply.
|
32
|
-
No downstream restrictions . You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, the Licensed Material if doing so restricts exercise of the Licensed Rights by any recipient of the Licensed Material.
|
33
|
-
No endorsement . Nothing in this Public License constitutes or may be construed as permission to assert or imply that You are, or that Your use of the Licensed Material is, connected with, or sponsored, endorsed, or granted official status by, the Licensor or others designated to receive attribution as provided in Section 3(a)(1)(A)(i) .
|
34
|
-
Other rights .
|
35
|
-
Moral rights, such as the right of integrity, are not licensed under this Public License, nor are publicity, privacy, and/or other similar personality rights; however, to the extent possible, the Licensor waives and/or agrees not to assert any such rights held by the Licensor to the limited extent necessary to allow You to exercise the Licensed Rights, but not otherwise.
|
36
|
-
Patent and trademark rights are not licensed under this Public License.
|
37
|
-
To the extent possible, the Licensor waives any right to collect royalties from You for the exercise of the Licensed Rights, whether directly or through a collecting society under any voluntary or waivable statutory or compulsory licensing scheme. In all other cases the Licensor expressly reserves any right to collect such royalties.
|
38
|
-
Section 3 – License Conditions.
|
39
|
-
|
40
|
-
Your exercise of the Licensed Rights is expressly made subject to the following conditions.
|
41
|
-
|
42
|
-
Attribution .
|
43
|
-
If You Share the Licensed Material (including in modified form), You must:
|
44
|
-
|
45
|
-
retain the following if it is supplied by the Licensor with the Licensed Material:
|
46
|
-
identification of the creator(s) of the Licensed Material and any others designated to receive attribution, in any reasonable manner requested by the Licensor (including by pseudonym if designated);
|
47
|
-
a copyright notice;
|
48
|
-
a notice that refers to this Public License;
|
49
|
-
a notice that refers to the disclaimer of warranties;
|
50
|
-
a URI or hyperlink to the Licensed Material to the extent reasonably practicable;
|
51
|
-
indicate if You modified the Licensed Material and retain an indication of any previous modifications; and
|
52
|
-
indicate the Licensed Material is licensed under this Public License, and include the text of, or the URI or hyperlink to, this Public License.
|
53
|
-
You may satisfy the conditions in Section 3(a)(1) in any reasonable manner based on the medium, means, and context in which You Share the Licensed Material. For example, it may be reasonable to satisfy the conditions by providing a URI or hyperlink to a resource that includes the required information.
|
54
|
-
If requested by the Licensor, You must remove any of the information required by Section 3(a)(1)(A) to the extent reasonably practicable.
|
55
|
-
ShareAlike .
|
56
|
-
In addition to the conditions in Section 3(a) , if You Share Adapted Material You produce, the following conditions also apply.
|
57
|
-
|
58
|
-
The Adapter’s License You apply must be a Creative Commons license with the same License Elements, this version or later, or a BY-SA Compatible License.
|
59
|
-
You must include the text of, or the URI or hyperlink to, the Adapter's License You apply. You may satisfy this condition in any reasonable manner based on the medium, means, and context in which You Share Adapted Material.
|
60
|
-
You may not offer or impose any additional or different terms or conditions on, or apply any Effective Technological Measures to, Adapted Material that restrict exercise of the rights granted under the Adapter's License You apply.
|
61
|
-
Section 4 – Sui Generis Database Rights.
|
62
|
-
|
63
|
-
Where the Licensed Rights include Sui Generis Database Rights that apply to Your use of the Licensed Material:
|
64
|
-
|
65
|
-
for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, reuse, reproduce, and Share all or a substantial portion of the contents of the database;
|
66
|
-
if You include all or a substantial portion of the database contents in a database in which You have Sui Generis Database Rights, then the database in which You have Sui Generis Database Rights (but not its individual contents) is Adapted Material, including for purposes of Section 3(b) ; and
|
67
|
-
You must comply with the conditions in Section 3(a) if You Share all or a substantial portion of the contents of the database.
|
68
|
-
For the avoidance of doubt, this Section 4 supplements and does not replace Your obligations under this Public License where the Licensed Rights include other Copyright and Similar Rights.
|
69
|
-
|
70
|
-
Section 5 – Disclaimer of Warranties and Limitation of Liability.
|
71
|
-
|
72
|
-
Unless otherwise separately undertaken by the Licensor, to the extent possible, the Licensor offers the Licensed Material as-is and as-available, and makes no representations or warranties of any kind concerning the Licensed Material, whether express, implied, statutory, or other. This includes, without limitation, warranties of title, merchantability, fitness for a particular purpose, non-infringement, absence of latent or other defects, accuracy, or the presence or absence of errors, whether or not known or discoverable. Where disclaimers of warranties are not allowed in full or in part, this disclaimer may not apply to You.
|
73
|
-
To the extent possible, in no event will the Licensor be liable to You on any legal theory (including, without limitation, negligence) or otherwise for any direct, special, indirect, incidental, consequential, punitive, exemplary, or other losses, costs, expenses, or damages arising out of this Public License or use of the Licensed Material, even if the Licensor has been advised of the possibility of such losses, costs, expenses, or damages. Where a limitation of liability is not allowed in full or in part, this limitation may not apply to You.
|
74
|
-
The disclaimer of warranties and limitation of liability provided above shall be interpreted in a manner that, to the extent possible, most closely approximates an absolute disclaimer and waiver of all liability.
|
75
|
-
Section 6 – Term and Termination.
|
76
|
-
|
77
|
-
This Public License applies for the term of the Copyright and Similar Rights licensed here. However, if You fail to comply with this Public License, then Your rights under this Public License terminate automatically.
|
78
|
-
Where Your right to use the Licensed Material has terminated under Section 6(a), it reinstates:
|
79
|
-
|
80
|
-
automatically as of the date the violation is cured, provided it is cured within 30 days of Your discovery of the violation; or
|
81
|
-
upon express reinstatement by the Licensor.
|
82
|
-
For the avoidance of doubt, this Section 6(b) does not affect any right the Licensor may have to seek remedies for Your violations of this Public License.
|
83
|
-
|
84
|
-
For the avoidance of doubt, the Licensor may also offer the Licensed Material under separate terms or conditions or stop distributing the Licensed Material at any time; however, doing so will not terminate this Public License.
|
85
|
-
Sections 1 , 5 , 6 , 7 , and 8 survive termination of this Public License.
|
86
|
-
Section 7 – Other Terms and Conditions.
|
87
|
-
|
88
|
-
The Licensor shall not be bound by any additional or different terms or conditions communicated by You unless expressly agreed.
|
89
|
-
Any arrangements, understandings, or agreements regarding the Licensed Material not stated herein are separate from and independent of the terms and conditions of this Public License.
|
90
|
-
Section 8 – Interpretation.
|
91
|
-
|
92
|
-
For the avoidance of doubt, this Public License does not, and shall not be interpreted to, reduce, limit, restrict, or impose conditions on any use of the Licensed Material that could lawfully be made without permission under this Public License.
|
93
|
-
To the extent possible, if any provision of this Public License is deemed unenforceable, it shall be automatically reformed to the minimum extent necessary to make it enforceable. If the provision cannot be reformed, it shall be severed from this Public License without affecting the enforceability of the remaining terms and conditions.
|
94
|
-
No term or condition of this Public License will be waived and no failure to comply consented to unless expressly agreed to by the Licensor.
|
95
|
-
Nothing in this Public License constitutes or may be interpreted as a limitation upon, or waiver of, any privileges and immunities that apply to the Licensor or You, including from the legal processes of any jurisdiction or authority.
|