symath 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +7 -0
  5. data/CODE_OF_CONDUCT.md +74 -0
  6. data/Gemfile +8 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +616 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/setup +8 -0
  12. data/lib/symath/definition/abs.rb +48 -0
  13. data/lib/symath/definition/arccos.rb +25 -0
  14. data/lib/symath/definition/arccot.rb +23 -0
  15. data/lib/symath/definition/arccsc.rb +24 -0
  16. data/lib/symath/definition/arcsec.rb +24 -0
  17. data/lib/symath/definition/arcsin.rb +25 -0
  18. data/lib/symath/definition/arctan.rb +23 -0
  19. data/lib/symath/definition/bounds.rb +39 -0
  20. data/lib/symath/definition/codiff.rb +31 -0
  21. data/lib/symath/definition/constant.rb +111 -0
  22. data/lib/symath/definition/cos.rb +17 -0
  23. data/lib/symath/definition/cot.rb +17 -0
  24. data/lib/symath/definition/csc.rb +17 -0
  25. data/lib/symath/definition/curl.rb +27 -0
  26. data/lib/symath/definition/d.rb +62 -0
  27. data/lib/symath/definition/div.rb +27 -0
  28. data/lib/symath/definition/exp.rb +112 -0
  29. data/lib/symath/definition/fact.rb +55 -0
  30. data/lib/symath/definition/flat.rb +31 -0
  31. data/lib/symath/definition/function.rb +197 -0
  32. data/lib/symath/definition/grad.rb +23 -0
  33. data/lib/symath/definition/hodge.rb +23 -0
  34. data/lib/symath/definition/int.rb +75 -0
  35. data/lib/symath/definition/laplacian.rb +23 -0
  36. data/lib/symath/definition/lmd.rb +97 -0
  37. data/lib/symath/definition/ln.rb +45 -0
  38. data/lib/symath/definition/number.rb +51 -0
  39. data/lib/symath/definition/operator.rb +228 -0
  40. data/lib/symath/definition/sec.rb +17 -0
  41. data/lib/symath/definition/sharp.rb +31 -0
  42. data/lib/symath/definition/sin.rb +17 -0
  43. data/lib/symath/definition/sqrt.rb +62 -0
  44. data/lib/symath/definition/tan.rb +17 -0
  45. data/lib/symath/definition/trig.rb +95 -0
  46. data/lib/symath/definition/variable.rb +284 -0
  47. data/lib/symath/definition/xd.rb +28 -0
  48. data/lib/symath/definition.rb +205 -0
  49. data/lib/symath/equation.rb +67 -0
  50. data/lib/symath/fraction.rb +177 -0
  51. data/lib/symath/matrix.rb +252 -0
  52. data/lib/symath/minus.rb +125 -0
  53. data/lib/symath/operation/differential.rb +167 -0
  54. data/lib/symath/operation/distributivelaw.rb +367 -0
  55. data/lib/symath/operation/exterior.rb +64 -0
  56. data/lib/symath/operation/integration.rb +329 -0
  57. data/lib/symath/operation/match.rb +166 -0
  58. data/lib/symath/operation/normalization.rb +458 -0
  59. data/lib/symath/operation.rb +36 -0
  60. data/lib/symath/operator.rb +163 -0
  61. data/lib/symath/parser.rb +473 -0
  62. data/lib/symath/parser.y +129 -0
  63. data/lib/symath/poly/dup.rb +835 -0
  64. data/lib/symath/poly/galois.rb +621 -0
  65. data/lib/symath/poly.rb +142 -0
  66. data/lib/symath/power.rb +224 -0
  67. data/lib/symath/product.rb +183 -0
  68. data/lib/symath/sum.rb +174 -0
  69. data/lib/symath/type.rb +282 -0
  70. data/lib/symath/value.rb +372 -0
  71. data/lib/symath/version.rb +3 -0
  72. data/lib/symath/wedge.rb +48 -0
  73. data/lib/symath.rb +157 -0
  74. data/symath.gemspec +39 -0
  75. 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