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.
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