symath 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|