symath 0.1.0
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 +7 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +21 -0
- data/README.md +616 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/symath/definition/abs.rb +48 -0
- data/lib/symath/definition/arccos.rb +25 -0
- data/lib/symath/definition/arccot.rb +23 -0
- data/lib/symath/definition/arccsc.rb +24 -0
- data/lib/symath/definition/arcsec.rb +24 -0
- data/lib/symath/definition/arcsin.rb +25 -0
- data/lib/symath/definition/arctan.rb +23 -0
- data/lib/symath/definition/bounds.rb +39 -0
- data/lib/symath/definition/codiff.rb +31 -0
- data/lib/symath/definition/constant.rb +111 -0
- data/lib/symath/definition/cos.rb +17 -0
- data/lib/symath/definition/cot.rb +17 -0
- data/lib/symath/definition/csc.rb +17 -0
- data/lib/symath/definition/curl.rb +27 -0
- data/lib/symath/definition/d.rb +62 -0
- data/lib/symath/definition/div.rb +27 -0
- data/lib/symath/definition/exp.rb +112 -0
- data/lib/symath/definition/fact.rb +55 -0
- data/lib/symath/definition/flat.rb +31 -0
- data/lib/symath/definition/function.rb +197 -0
- data/lib/symath/definition/grad.rb +23 -0
- data/lib/symath/definition/hodge.rb +23 -0
- data/lib/symath/definition/int.rb +75 -0
- data/lib/symath/definition/laplacian.rb +23 -0
- data/lib/symath/definition/lmd.rb +97 -0
- data/lib/symath/definition/ln.rb +45 -0
- data/lib/symath/definition/number.rb +51 -0
- data/lib/symath/definition/operator.rb +228 -0
- data/lib/symath/definition/sec.rb +17 -0
- data/lib/symath/definition/sharp.rb +31 -0
- data/lib/symath/definition/sin.rb +17 -0
- data/lib/symath/definition/sqrt.rb +62 -0
- data/lib/symath/definition/tan.rb +17 -0
- data/lib/symath/definition/trig.rb +95 -0
- data/lib/symath/definition/variable.rb +284 -0
- data/lib/symath/definition/xd.rb +28 -0
- data/lib/symath/definition.rb +205 -0
- data/lib/symath/equation.rb +67 -0
- data/lib/symath/fraction.rb +177 -0
- data/lib/symath/matrix.rb +252 -0
- data/lib/symath/minus.rb +125 -0
- data/lib/symath/operation/differential.rb +167 -0
- data/lib/symath/operation/distributivelaw.rb +367 -0
- data/lib/symath/operation/exterior.rb +64 -0
- data/lib/symath/operation/integration.rb +329 -0
- data/lib/symath/operation/match.rb +166 -0
- data/lib/symath/operation/normalization.rb +458 -0
- data/lib/symath/operation.rb +36 -0
- data/lib/symath/operator.rb +163 -0
- data/lib/symath/parser.rb +473 -0
- data/lib/symath/parser.y +129 -0
- data/lib/symath/poly/dup.rb +835 -0
- data/lib/symath/poly/galois.rb +621 -0
- data/lib/symath/poly.rb +142 -0
- data/lib/symath/power.rb +224 -0
- data/lib/symath/product.rb +183 -0
- data/lib/symath/sum.rb +174 -0
- data/lib/symath/type.rb +282 -0
- data/lib/symath/value.rb +372 -0
- data/lib/symath/version.rb +3 -0
- data/lib/symath/wedge.rb +48 -0
- data/lib/symath.rb +157 -0
- data/symath.gemspec +39 -0
- metadata +160 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'symath/definition/function'
|
2
|
+
|
3
|
+
module SyMath
|
4
|
+
class Definition::Arccos < Definition::Function
|
5
|
+
def initialize()
|
6
|
+
super(:arccos)
|
7
|
+
|
8
|
+
@reductions = {
|
9
|
+
-1.to_m => :pi,
|
10
|
+
-fn(:sqrt, 3)/2 => 5*:pi/6,
|
11
|
+
-fn(:sqrt, 2)/2 => 3*:pi/4,
|
12
|
+
-1.to_m/2 => 2*:pi/3,
|
13
|
+
0.to_m => :pi/2,
|
14
|
+
1.to_m/2 => :pi/3,
|
15
|
+
fn(:sqrt, 2)/2 => :pi/4,
|
16
|
+
fn(:sqrt, 3)/2 => :pi/6,
|
17
|
+
1.to_m => 0.to_m,
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def description()
|
22
|
+
return 'arccos(x) - inverse trigonometric cosine'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'symath/definition/function'
|
2
|
+
|
3
|
+
module SyMath
|
4
|
+
class Definition::Arccot < Definition::Function
|
5
|
+
def initialize()
|
6
|
+
super(:arccot)
|
7
|
+
|
8
|
+
@reductions = {
|
9
|
+
-fn(:sqrt, 3) => 5*:pi/6,
|
10
|
+
-1.to_m => 3*:pi/4,
|
11
|
+
-fn(:sqrt, 3)/3 => 2*:pi/3,
|
12
|
+
0.to_m => :pi/2,
|
13
|
+
fn(:sqrt, 3)/3 => :pi/3,
|
14
|
+
1.to_m => :pi/4,
|
15
|
+
fn(:sqrt, 3) => :pi/6,
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def description()
|
20
|
+
return 'arccot(x) - inverse trigonometric cotangent'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'symath/definition/function'
|
2
|
+
|
3
|
+
module SyMath
|
4
|
+
class Definition::Arccsc < Definition::Function
|
5
|
+
def initialize()
|
6
|
+
super(:arccsc)
|
7
|
+
|
8
|
+
@reductions = {
|
9
|
+
-2.to_m => -:pi/6,
|
10
|
+
-fn(:sqrt, 2) => -:pi/4,
|
11
|
+
-2*fn(:sqrt, 3)/3 => -:pi/3,
|
12
|
+
-1.to_m => -:pi/2,
|
13
|
+
1.to_m => :pi/2,
|
14
|
+
2*fn(:sqrt, 3)/3 => :pi/3,
|
15
|
+
fn(:sqrt, 2) => :pi/4,
|
16
|
+
2.to_m => :pi/6,
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def description()
|
21
|
+
return 'arccsc(x) - inverse trigonometric cosecant'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'symath/definition/function'
|
2
|
+
|
3
|
+
module SyMath
|
4
|
+
class Definition::Arcsec < Definition::Function
|
5
|
+
def initialize()
|
6
|
+
super(:arcsec)
|
7
|
+
|
8
|
+
@reductions = {
|
9
|
+
-2.to_m => 2*:pi/3,
|
10
|
+
-fn(:sqrt, 2) => 3*:pi/4,
|
11
|
+
-2*fn(:sqrt, 3)/3 => 5*:pi/6,
|
12
|
+
-1.to_m => :pi,
|
13
|
+
1.to_m => 0.to_m,
|
14
|
+
2*fn(:sqrt, 3)/3 => :pi/6,
|
15
|
+
fn(:sqrt, 2) => :pi/4,
|
16
|
+
2.to_m => :pi/3
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def description()
|
21
|
+
return 'arcsec(x) - inverse trigonometric secant'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'symath/definition/function'
|
2
|
+
|
3
|
+
module SyMath
|
4
|
+
class Definition::Arcsin < Definition::Function
|
5
|
+
def initialize()
|
6
|
+
super(:arcsin)
|
7
|
+
|
8
|
+
@reductions = {
|
9
|
+
-1.to_m => -:pi/2,
|
10
|
+
-fn(:sqrt, 3)/2 => -:pi/3,
|
11
|
+
-fn(:sqrt, 2)/2 => -:pi/4,
|
12
|
+
-1.to_m/2 => -:pi/6,
|
13
|
+
0.to_m => 0.to_m,
|
14
|
+
1.to_m/2 => :pi/6,
|
15
|
+
fn(:sqrt, 2)/2 => :pi/4,
|
16
|
+
fn(:sqrt, 3)/2 => :pi/3,
|
17
|
+
1.to_m => :pi/2,
|
18
|
+
}
|
19
|
+
end
|
20
|
+
|
21
|
+
def description()
|
22
|
+
return 'arcsin(x) - inverse trigonometric sine'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'symath/definition/function'
|
2
|
+
|
3
|
+
module SyMath
|
4
|
+
class Definition::Arctan < Definition::Function
|
5
|
+
def initialize()
|
6
|
+
super(:arctan)
|
7
|
+
|
8
|
+
@reductions = {
|
9
|
+
-fn(:sqrt, 3) => -:pi/3,
|
10
|
+
-1.to_m => -:pi/4,
|
11
|
+
-fn(:sqrt, 3)/3 => -:pi/6,
|
12
|
+
0.to_m => 0.to_m,
|
13
|
+
fn(:sqrt, 3)/3 => :pi/6,
|
14
|
+
1.to_m => :pi/4,
|
15
|
+
fn(:sqrt, 3) => :pi/3,
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
def description()
|
20
|
+
return 'arctan(x) - inverse trigonometric tangent'
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'symath/value'
|
2
|
+
require 'symath/definition/operator'
|
3
|
+
|
4
|
+
module SyMath
|
5
|
+
class Definition::Bounds < Definition::Operator
|
6
|
+
def initialize()
|
7
|
+
super(:bounds, args: [:f, :a, :b],
|
8
|
+
exp: :f.to_m.(:b) - :f.to_m.(:a))
|
9
|
+
end
|
10
|
+
|
11
|
+
def description()
|
12
|
+
return 'bounds(ex, x, a, b) - bounds operator, (ex)[x=b] - (ex)[x=a]'
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_s(args = nil)
|
16
|
+
if !args
|
17
|
+
args = @args
|
18
|
+
end
|
19
|
+
|
20
|
+
exp = args[0]
|
21
|
+
a = args[2]
|
22
|
+
b = args[3]
|
23
|
+
|
24
|
+
return "[#{exp}](#{a},#{b})"
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_latex(args = nil)
|
28
|
+
if !args
|
29
|
+
args = @args
|
30
|
+
end
|
31
|
+
|
32
|
+
exp = args[0].to_latex
|
33
|
+
a = args[2].to_latex
|
34
|
+
b = args[3].to_latex
|
35
|
+
|
36
|
+
return "\\left[#{exp}\\right]^{#{b}}_{#{a}}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'symath/value'
|
2
|
+
require 'symath/definition/operator'
|
3
|
+
|
4
|
+
module SyMath
|
5
|
+
class Definition::CoDiff < Definition::Operator
|
6
|
+
def initialize()
|
7
|
+
# The co-differential is defined as: (-1)**(n*k+ 1)*d*(F).
|
8
|
+
# n : Dimension of the basis vector space
|
9
|
+
# k : Grade of input function F
|
10
|
+
# (the sign is calculated by the overridden evaluate method)
|
11
|
+
super(:codiff, args: [:f], exp: 'hodge(xd(hodge(f)))')
|
12
|
+
end
|
13
|
+
|
14
|
+
def description()
|
15
|
+
return 'codiff(f) - codifferential of function f'
|
16
|
+
end
|
17
|
+
|
18
|
+
def evaluate_call(c)
|
19
|
+
vars = SyMath.get_variable(:basis.to_m).row(0)
|
20
|
+
n = vars.length
|
21
|
+
k = c.args[0].type.degree
|
22
|
+
sign = ((-1)**(n*k + 1)).to_m
|
23
|
+
|
24
|
+
return sign*super(c)
|
25
|
+
end
|
26
|
+
|
27
|
+
def latex_format()
|
28
|
+
return '\delta %s'
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'symath/definition'
|
2
|
+
require 'set'
|
3
|
+
|
4
|
+
module SyMath
|
5
|
+
class Definition::Constant < Definition
|
6
|
+
@@ltx_symbol = {
|
7
|
+
:pi => '\pi',
|
8
|
+
:e => '\mathrm{e}',
|
9
|
+
:phi => '\varphi',
|
10
|
+
:nan => '\mathrm{NaN}',
|
11
|
+
:oo => '\infty',
|
12
|
+
};
|
13
|
+
|
14
|
+
@@descriptions = {
|
15
|
+
:pi => 'ratio of cirle cirumference/diameter (3.14159265...)',
|
16
|
+
:e => 'eulers number (2.71828182...)',
|
17
|
+
:phi => 'golden ratio (1.61803398...)',
|
18
|
+
:nan => "'not a number', i.e. an invalid value",
|
19
|
+
:oo => 'positive infinity',
|
20
|
+
:i => 'imaginary unit, first basic quaternion',
|
21
|
+
:j => 'second basic quaternion',
|
22
|
+
:k => 'third basic quaternion',
|
23
|
+
}
|
24
|
+
|
25
|
+
@@unit_quaternions = [:i, :j, :k].to_set
|
26
|
+
|
27
|
+
def self.init_builtin()
|
28
|
+
# Define the builtin constants
|
29
|
+
self.new(:pi)
|
30
|
+
self.new(:e)
|
31
|
+
self.new(:phi)
|
32
|
+
self.new(:nan)
|
33
|
+
self.new(:oo)
|
34
|
+
self.new(:i)
|
35
|
+
self.new(:j)
|
36
|
+
self.new(:k)
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.constants()
|
40
|
+
return self.definitions.grep(SyMath::Definition::Constant)
|
41
|
+
end
|
42
|
+
|
43
|
+
def description()
|
44
|
+
return "#{@name} - #{@@descriptions[@name]}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def is_nan?()
|
48
|
+
return @name == :nan
|
49
|
+
end
|
50
|
+
|
51
|
+
def is_finite?()
|
52
|
+
return (@name != :oo and @name != :nan)
|
53
|
+
end
|
54
|
+
|
55
|
+
def is_positive?()
|
56
|
+
return (!is_zero? and !is_nan?)
|
57
|
+
end
|
58
|
+
|
59
|
+
def is_zero?()
|
60
|
+
return false
|
61
|
+
end
|
62
|
+
|
63
|
+
def is_unit_quaternion?()
|
64
|
+
return @@unit_quaternions.member?(@name)
|
65
|
+
end
|
66
|
+
|
67
|
+
def calc_unit_quaternions(q)
|
68
|
+
# Calculation map for unit quaternions
|
69
|
+
qmap = {
|
70
|
+
:i => {
|
71
|
+
:i => -1.to_m,
|
72
|
+
:j => :k.to_m,
|
73
|
+
:k => -:j.to_m,
|
74
|
+
},
|
75
|
+
:j => {
|
76
|
+
:i => -:k.to_m,
|
77
|
+
:j => -1.to_m,
|
78
|
+
:k => :i.to_m,
|
79
|
+
},
|
80
|
+
:k => {
|
81
|
+
:i => :j.to_m,
|
82
|
+
:j => -:i.to_m,
|
83
|
+
:k => -1.to_m,
|
84
|
+
},
|
85
|
+
}
|
86
|
+
|
87
|
+
return qmap[@name][q.name]
|
88
|
+
end
|
89
|
+
|
90
|
+
def type()
|
91
|
+
n = @name
|
92
|
+
if n == :e or n == :pi or n == :phi
|
93
|
+
return 'real'.to_t
|
94
|
+
elsif n == :i
|
95
|
+
return 'imaginary'.to_t
|
96
|
+
elsif is_unit_quaternion?
|
97
|
+
return 'quaternion'.to_t
|
98
|
+
else
|
99
|
+
return 'nonfinite'.to_t
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def to_latex()
|
104
|
+
if @@ltx_symbol.key?(@name)
|
105
|
+
return @@ltx_symbol[@name]
|
106
|
+
else
|
107
|
+
return @name.to_s
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'symath/definition/trig'
|
2
|
+
|
3
|
+
module SyMath
|
4
|
+
class Definition::Cos < Definition::Trig
|
5
|
+
def initialize()
|
6
|
+
super(:cos)
|
7
|
+
end
|
8
|
+
|
9
|
+
def description()
|
10
|
+
return "cos(x) - trigonometric cosine"
|
11
|
+
end
|
12
|
+
|
13
|
+
def reduce_call(c)
|
14
|
+
return reduce_sin_and_cos(c, 1)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'symath/definition/trig'
|
2
|
+
|
3
|
+
module SyMath
|
4
|
+
class Definition::Cot < Definition::Trig
|
5
|
+
def initialize()
|
6
|
+
super(:cot)
|
7
|
+
end
|
8
|
+
|
9
|
+
def description()
|
10
|
+
return 'cot(x) - trigonometric cotangent'
|
11
|
+
end
|
12
|
+
|
13
|
+
def reduce_call(c)
|
14
|
+
return reduce_tan_and_cot(c, 1, -1)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'symath/definition/trig'
|
2
|
+
|
3
|
+
module SyMath
|
4
|
+
class Definition::Csc < Definition::Trig
|
5
|
+
def initialize()
|
6
|
+
super(:csc)
|
7
|
+
end
|
8
|
+
|
9
|
+
def description()
|
10
|
+
return 'csc(x) - trigonometric cosecant'
|
11
|
+
end
|
12
|
+
|
13
|
+
def reduce_call(c)
|
14
|
+
return reduce_sec_and_csc(c, 0)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'symath/value'
|
2
|
+
require 'symath/definition/operator'
|
3
|
+
|
4
|
+
module SyMath
|
5
|
+
class Definition::Curl < Definition::Operator
|
6
|
+
def initialize()
|
7
|
+
# Curl is defined as (*(d(Fb)))#
|
8
|
+
super(:curl, args: [:f], exp: '#(hodge(xd(b(f))))')
|
9
|
+
end
|
10
|
+
|
11
|
+
def description()
|
12
|
+
return 'curl(f) - curl of vector field f'
|
13
|
+
end
|
14
|
+
|
15
|
+
def evaluate_call(c)
|
16
|
+
if SyMath.get_variable(:basis.to_m).row(0).length != 3
|
17
|
+
raise 'Curl is only defined for 3 dimensions'
|
18
|
+
end
|
19
|
+
|
20
|
+
return super(c)
|
21
|
+
end
|
22
|
+
|
23
|
+
def latex_format()
|
24
|
+
return '\nabla\times %s'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'symath/value'
|
2
|
+
require 'symath/definition/operator'
|
3
|
+
require 'symath/definition/function'
|
4
|
+
|
5
|
+
module SyMath
|
6
|
+
class Definition::D < Definition::Operator
|
7
|
+
def initialize()
|
8
|
+
super(:d)
|
9
|
+
end
|
10
|
+
|
11
|
+
def description()
|
12
|
+
return 'd(f) - differential of f with respect to its input variables'
|
13
|
+
end
|
14
|
+
|
15
|
+
def validate_args(e)
|
16
|
+
# Arguments 1, 2, ... are supposed to be variables to differentiate
|
17
|
+
# over.
|
18
|
+
e.args[1..-1].each do |v|
|
19
|
+
if !v.is_a?(SyMath::Definition::Variable)
|
20
|
+
raise "Expected variable, got #{v.class.name}"
|
21
|
+
end
|
22
|
+
|
23
|
+
if v.is_d?
|
24
|
+
raise "Var is not allowed to be differential, got #{v}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def compose_with_simplify(name, args)
|
30
|
+
exp = args[0]
|
31
|
+
vars = args[1..-1]
|
32
|
+
|
33
|
+
if exp.is_a?(SyMath::Definition::Variable) and
|
34
|
+
exp.type.is_scalar? and
|
35
|
+
vars.length == 0
|
36
|
+
return exp.to_d
|
37
|
+
end
|
38
|
+
|
39
|
+
return
|
40
|
+
end
|
41
|
+
|
42
|
+
def evaluate_call(c)
|
43
|
+
e = c.args[0]
|
44
|
+
|
45
|
+
# If argument is a function, differentiate on all function
|
46
|
+
# arguments.
|
47
|
+
if e.is_a?(SyMath::Definition::Function)
|
48
|
+
vars = e.args
|
49
|
+
else
|
50
|
+
# Find first free variable in expression.
|
51
|
+
vars = [(e.variables)[0].to_m]
|
52
|
+
e = lmd(e, *vars)
|
53
|
+
end
|
54
|
+
|
55
|
+
return lmd(e.d(vars), *vars)
|
56
|
+
end
|
57
|
+
|
58
|
+
def latex_format()
|
59
|
+
return '\mathrm{d}(%s)'
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'symath/value'
|
2
|
+
require 'symath/definition/operator'
|
3
|
+
|
4
|
+
module SyMath
|
5
|
+
class Definition::Div < Definition::Operator
|
6
|
+
def initialize()
|
7
|
+
# Div is defined as *d*(Fb)
|
8
|
+
super(:div, args: [:f], exp: 'hodge(xd(hodge(b(f))))')
|
9
|
+
end
|
10
|
+
|
11
|
+
def description()
|
12
|
+
return 'div(f) - divergence of vector field f'
|
13
|
+
end
|
14
|
+
|
15
|
+
def evaluate_call(c)
|
16
|
+
if SyMath.get_variable(:basis.to_m).row(0).length != 3
|
17
|
+
raise 'Div is only defined for 3 dimensions'
|
18
|
+
end
|
19
|
+
|
20
|
+
super(c)
|
21
|
+
end
|
22
|
+
|
23
|
+
def latex_format()
|
24
|
+
return '\nabla\cdot %s'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'symath/definition/function'
|
2
|
+
|
3
|
+
module SyMath
|
4
|
+
class Definition::Exp < Definition::Function
|
5
|
+
def initialize()
|
6
|
+
super(:exp)
|
7
|
+
end
|
8
|
+
|
9
|
+
def description()
|
10
|
+
return 'exp(x) - exponential function (e**x)'
|
11
|
+
end
|
12
|
+
|
13
|
+
def reduce_call(call)
|
14
|
+
arg = call.args[0]
|
15
|
+
|
16
|
+
if arg.is_nan?
|
17
|
+
return :nan.to_m
|
18
|
+
end
|
19
|
+
|
20
|
+
if arg == 0
|
21
|
+
return 1.to_m
|
22
|
+
elsif arg == 1
|
23
|
+
return :e.to_m
|
24
|
+
end
|
25
|
+
|
26
|
+
if arg.is_finite? == false
|
27
|
+
if SyMath.setting(:complex_arithmetic)
|
28
|
+
return :nan.to_m
|
29
|
+
else
|
30
|
+
if arg.is_positive? == true
|
31
|
+
return :oo.to_m
|
32
|
+
else
|
33
|
+
return 0.to_m
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
if SyMath.setting(:complex_arithmetic)
|
39
|
+
ret = 1.to_m
|
40
|
+
|
41
|
+
arg.terms.each do |t|
|
42
|
+
if t.is_a?(SyMath::Minus)
|
43
|
+
t = t.args[0]
|
44
|
+
minus = true
|
45
|
+
else
|
46
|
+
minus = false
|
47
|
+
end
|
48
|
+
|
49
|
+
if t.class.method_defined?('definition') and
|
50
|
+
t.definition.is_a?(SyMath::Definition::Ln)
|
51
|
+
# exp(ln(c)) = c
|
52
|
+
t2 = t.args[0]
|
53
|
+
else
|
54
|
+
# Euler's formula
|
55
|
+
c, dc = check_pi_fraction(t, true)
|
56
|
+
if !c.nil?
|
57
|
+
if dc == 1
|
58
|
+
c *= 2
|
59
|
+
elsif dc != 2
|
60
|
+
# Not reducible
|
61
|
+
return call
|
62
|
+
end
|
63
|
+
|
64
|
+
case c % 4
|
65
|
+
when 0
|
66
|
+
t2 = 1
|
67
|
+
when 1
|
68
|
+
t2 = :i
|
69
|
+
when 2
|
70
|
+
t2 = -1
|
71
|
+
when 3
|
72
|
+
t2 = -:i
|
73
|
+
end
|
74
|
+
else
|
75
|
+
# Cannot reduce
|
76
|
+
return call
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
ret = minus ? ret/t2 : ret*t2
|
81
|
+
end
|
82
|
+
|
83
|
+
return ret
|
84
|
+
else
|
85
|
+
ret = 1.to_m
|
86
|
+
|
87
|
+
call.args[0].terms.each do |t|
|
88
|
+
if t.is_a?(SyMath::Minus)
|
89
|
+
t = t.args[0]
|
90
|
+
minus = true
|
91
|
+
else
|
92
|
+
minus = false
|
93
|
+
end
|
94
|
+
|
95
|
+
# exp(ln(c)) = c for positive c
|
96
|
+
if t.class.method_defined?('definition') and
|
97
|
+
t.definition.is_a?(SyMath::Definition::Ln)
|
98
|
+
if t.args[0].is_number?
|
99
|
+
ret = minus ? ret/t.args[0] : ret*t.args[0]
|
100
|
+
next
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Cannot reduce
|
105
|
+
return call
|
106
|
+
end
|
107
|
+
|
108
|
+
return ret
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'symath/definition/function'
|
2
|
+
|
3
|
+
module SyMath
|
4
|
+
class Definition::Fact < Definition::Function
|
5
|
+
def initialize()
|
6
|
+
super(:fact)
|
7
|
+
end
|
8
|
+
|
9
|
+
def description()
|
10
|
+
return 'fact(x) - factorial'
|
11
|
+
end
|
12
|
+
|
13
|
+
def reduce_call(c)
|
14
|
+
arg = c.args[0]
|
15
|
+
|
16
|
+
if arg.is_number?
|
17
|
+
if arg.value <= SyMath.setting(:max_calculated_factorial)
|
18
|
+
return (2..arg.value).reduce(1, :*).to_m
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
return c
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s(args = nil)
|
26
|
+
if args
|
27
|
+
if args[0].is_a?(SyMath::Definition::Variable) or
|
28
|
+
args[0].is_a?(SyMath::Definition::Constant)
|
29
|
+
arg = args[0].to_s
|
30
|
+
else
|
31
|
+
arg = "(#{args[0].to_s})"
|
32
|
+
end
|
33
|
+
else
|
34
|
+
arg = '(...)'
|
35
|
+
end
|
36
|
+
|
37
|
+
return "#{arg}!"
|
38
|
+
end
|
39
|
+
|
40
|
+
def to_latex(args = nil)
|
41
|
+
if args
|
42
|
+
if args[0].is_a?(SyMath::Definition::Variable) or
|
43
|
+
args[0].is_a?(SyMath::Definition::Constant)
|
44
|
+
arg = args[0].to_latex
|
45
|
+
else
|
46
|
+
arg = "(#{args[0].to_latex})"
|
47
|
+
end
|
48
|
+
else
|
49
|
+
arg = '(...)'
|
50
|
+
end
|
51
|
+
|
52
|
+
return "#{arg}!"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|