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,31 @@
1
+ require 'symath/value'
2
+ require 'symath/definition/operator'
3
+
4
+ module SyMath
5
+ class Definition::Flat < Definition::Operator
6
+ def initialize()
7
+ super(:flat)
8
+ end
9
+
10
+ def description()
11
+ return 'flat(f) - musical lower/flat/b isomorphic operator'
12
+ end
13
+
14
+ def evaluate_call(c)
15
+ # Must normalize input, operation depends on factorized vectors
16
+ return c.args[0].evaluate.normalize.flat
17
+ end
18
+
19
+ def to_s(args = nil)
20
+ if !args
21
+ args = @args
22
+ end
23
+
24
+ return "b(#{args[0]})"
25
+ end
26
+
27
+ def latex_format()
28
+ return '%s^\flat'
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,197 @@
1
+ require 'symath/definition'
2
+
3
+ module SyMath
4
+ class Definition::Function < Definition::Operator
5
+ def self.init_builtin()
6
+ # Define the builtin functions
7
+ SyMath::Definition::Sqrt.new
8
+ SyMath::Definition::Sin.new
9
+ SyMath::Definition::Cos.new
10
+ SyMath::Definition::Tan.new
11
+ SyMath::Definition::Sec.new
12
+ SyMath::Definition::Csc.new
13
+ SyMath::Definition::Cot.new
14
+ SyMath::Definition::Arcsin.new
15
+ SyMath::Definition::Arccos.new
16
+ SyMath::Definition::Arctan.new
17
+ SyMath::Definition::Arcsec.new
18
+ SyMath::Definition::Arccsc.new
19
+ SyMath::Definition::Arccot.new
20
+ SyMath::Definition::Ln.new
21
+ SyMath::Definition::Exp.new
22
+ SyMath::Definition::Abs.new
23
+ SyMath::Definition::Fact.new
24
+
25
+ # Functions defined by an expression
26
+ expressions = [
27
+ { :name => 'sinh',
28
+ :exp => '(e**x - e**-x)/2',
29
+ :desc => 'hyperbolic sine',
30
+ },
31
+ { :name => 'cosh',
32
+ :exp => '(e**x + e**-x)/2',
33
+ :desc => 'hyperbolic cosine',
34
+ },
35
+ { :name => 'tanh',
36
+ :exp => '(e**x - e**-x)/(e**x + e**-x)',
37
+ :desc => 'hyperbolic tangent',
38
+ },
39
+ { :name => 'coth',
40
+ :exp => '(e**x + e**-x)/(e**x - e**-x)',
41
+ :desc => 'hyperbolic cotangent',
42
+ },
43
+ { :name => 'sech',
44
+ :exp => '2/(e**x + e**-x)',
45
+ :desc => 'hyperbolic secant',
46
+ },
47
+ { :name => 'csch',
48
+ :exp => '2/(e**x - e**-x)',
49
+ :desc => 'hyperbolic cosecant',
50
+ },
51
+ { :name => 'arsinh',
52
+ :exp => 'ln(x + sqrt(x**2 + 1))',
53
+ :desc => 'inverse hyperbolic sine',
54
+ },
55
+ { :name => 'arcosh',
56
+ :exp => 'ln(x + sqrt(x**2 - 1))',
57
+ :desc => 'inverse hyperbolic cosine',
58
+ },
59
+ { :name => 'artanh',
60
+ :exp => 'ln((1 + x)/(1 - x))/2',
61
+ :desc => 'inverse hyperbolic tangent',
62
+ },
63
+ { :name => 'arcoth',
64
+ :exp => 'ln((x + 1)/(x - 1))/2',
65
+ :desc => 'inverse hyperbolic cotangent',
66
+ },
67
+ { :name => 'arsech',
68
+ :exp => 'ln((1/x + sqrt(x**-2 - 1)))',
69
+ :desc => 'inverse hyperbolic secant',
70
+ },
71
+ { :name => 'arcsch',
72
+ :exp => 'ln((1/x + sqrt(x**-2 + 1)))',
73
+ :desc => 'inverse hyperbolic cosecant',
74
+ },
75
+ ]
76
+
77
+ expressions.each do |e|
78
+ self.new(e[:name], args: [:x], exp: e[:exp],
79
+ description: "#{e[:name]}(x) - #{e[:desc]}")
80
+ end
81
+ end
82
+
83
+ @@not_mentioned_funcs = {
84
+ :+ => true,
85
+ :- => true,
86
+ :* => true,
87
+ :/ => true,
88
+ :** => true,
89
+ :'=' => true,
90
+ }
91
+
92
+ def self.functions()
93
+ return self.definitions.select { |f|
94
+ f.is_function? and !@@not_mentioned_funcs[f.name]
95
+ }
96
+ end
97
+
98
+ @reductions = {}
99
+
100
+ def reduce_call(c, reductions = nil)
101
+ if reductions.nil?
102
+ reductions = @reductions
103
+ end
104
+
105
+ if reductions.has_key?(c.args[0])
106
+ return reductions[c.args[0]]
107
+ end
108
+
109
+ return c
110
+ end
111
+
112
+ # Check if expression is a constant fraction of pi and optionally
113
+ # i (imaginary unit)
114
+ def check_pi_fraction(e, im)
115
+ gotpi = false
116
+ gotim = !im
117
+ c = 1
118
+ dc = 1
119
+
120
+ # Check that factors are only constant, divisor constant and pi.
121
+ # Note: This code is similar to 'reduce_constant_factors'. Refactor?
122
+ e.factors.each do |f|
123
+ if f.is_divisor_factor?
124
+ if f.base.is_number?
125
+ dc *= f.base.value**f.exponent.argument.value
126
+ next
127
+ end
128
+ end
129
+
130
+ if f.is_negative_number?
131
+ c *= - f.argument.value
132
+ next
133
+ end
134
+
135
+ if f.is_number?
136
+ c *= f.value
137
+ next
138
+ end
139
+
140
+ if !gotpi and f == :pi
141
+ gotpi = true
142
+ next
143
+ end
144
+
145
+ if !gotim and f == :i
146
+ gotim = true
147
+ next
148
+ end
149
+
150
+ return nil
151
+ end
152
+
153
+ return nil if !gotpi and !gotim and c != 0
154
+
155
+ return c, dc
156
+ end
157
+
158
+ def is_function?()
159
+ return true
160
+ end
161
+
162
+ def latex_format()
163
+ return "#{name}(%s)"
164
+ end
165
+ end
166
+ end
167
+
168
+ def fn(f, *args)
169
+ return SyMath::Operator.create(f, args.map { |a| a.nil? ? a : a.to_m })
170
+ end
171
+
172
+ def define_fn(name, args, exp = nil)
173
+ if exp
174
+ return SyMath::Definition::Function.new(name, args: args, exp: exp)
175
+ else
176
+ return SyMath::Definition::Function.new(name, args: args)
177
+ end
178
+ end
179
+
180
+ require 'symath/definition/sin'
181
+ require 'symath/definition/cos'
182
+ require 'symath/definition/tan'
183
+ require 'symath/definition/sec'
184
+ require 'symath/definition/csc'
185
+ require 'symath/definition/cot'
186
+ require 'symath/definition/arcsin'
187
+ require 'symath/definition/arccos'
188
+ require 'symath/definition/arctan'
189
+ require 'symath/definition/arcsec'
190
+ require 'symath/definition/arccsc'
191
+ require 'symath/definition/arccot'
192
+ require 'symath/definition/ln'
193
+ require 'symath/definition/exp'
194
+ require 'symath/definition/abs'
195
+ require 'symath/definition/sqrt'
196
+ require 'symath/definition/fact'
197
+ require 'symath/definition/lmd'
@@ -0,0 +1,23 @@
1
+ require 'symath/value'
2
+ require 'symath/definition/operator'
3
+
4
+ module SyMath
5
+ class Definition::Grad < Definition::Operator
6
+ def initialize()
7
+ # Grad is defined as (dF)#
8
+ super(:grad, args: [:f], exp: '#(xd(f))')
9
+ end
10
+
11
+ def description()
12
+ return 'grad(f) - gradient of scalar field f'
13
+ end
14
+
15
+ def to_latex(args)
16
+ if !args
17
+ args = @args
18
+ end
19
+
20
+ return "\\nabla #{args[0].to_latex}"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ require 'symath/value'
2
+ require 'symath/definition/operator'
3
+
4
+ module SyMath
5
+ class Definition::Hodge < Definition::Operator
6
+ def initialize()
7
+ super(:hodge)
8
+ end
9
+
10
+ def description()
11
+ return 'hodge(f) - hodge star operator'
12
+ end
13
+
14
+ def evaluate_call(c)
15
+ # Must normalize input, operation depends on factorized vectors
16
+ return c.args[0].evaluate.normalize.hodge
17
+ end
18
+
19
+ def latex_format()
20
+ return '\star %s'
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,75 @@
1
+ require 'symath/value'
2
+ require 'symath/definition/operator'
3
+
4
+ module SyMath
5
+ class Definition::Int < Definition::Operator
6
+ def initialize()
7
+ super(:int)
8
+ end
9
+
10
+ def description()
11
+ return 'int(f, a, b) - integral of f [from a to b]'
12
+ end
13
+
14
+ def validate_args(e)
15
+ a = e.args[1]
16
+ b = e.args[2]
17
+
18
+ if (!a.nil? and b.nil?) or (a.nil? and !b.nil?)
19
+ raise "A cannot be defined without b and vica versa."
20
+ end
21
+ end
22
+
23
+ def get_variable(exp)
24
+ if exp.is_a?(SyMath::Operator) and
25
+ exp.definition.is_function? and
26
+ exp.definition.args.length > 0
27
+ v = exp.definition.args[0]
28
+ else
29
+ v = (exp.variables)[0].to_m
30
+ end
31
+
32
+ return v.to_d
33
+ end
34
+
35
+ def evaluate_call(c)
36
+ exp = c.args[0]
37
+ var = get_variable(exp)
38
+ a = c.args[1]
39
+ b = c.args[2]
40
+
41
+ exp = exp.evaluate
42
+
43
+ if a.nil?
44
+ ret = exp.normalize.anti_derivative(var)
45
+ return ret.nil? ? nil : ret + :C.to_m
46
+ else
47
+ int = exp.normalize.anti_derivative(var)
48
+ # TODO: Setting for evaluating the bounds expression?
49
+ return op(:bounds, lmd(int, var.undiff), a, b).evaluate
50
+ end
51
+ end
52
+
53
+ def to_latex(args)
54
+ if !args
55
+ args = @args
56
+ end
57
+
58
+ if args[0].is_sum_exp?
59
+ exp = "\\left(#{args[0].to_latex}\\right)"
60
+ else
61
+ exp = args[0].to_latex
62
+ end
63
+
64
+ var = get_variable(args[0])
65
+ a = args[1]
66
+ b = args[2]
67
+
68
+ if a.nil?
69
+ return "\\int #{exp}\\,#{var.to_latex}"
70
+ else
71
+ return "\\int_{#{a.to_latex}}^{#{b.to_latex}} #{exp}\\,#{var.to_latex}"
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,23 @@
1
+ require 'symath/value'
2
+ require 'symath/definition/operator'
3
+
4
+ module SyMath
5
+ class Definition::Laplacian < Definition::Operator
6
+ def initialize()
7
+ # The laplacian is defined as *d*dF
8
+ super(:laplacian, args: [:f], exp: 'hodge(xd(hodge(xd(f))))')
9
+ end
10
+
11
+ def description()
12
+ return 'laplacian(f) - laplacian of function f'
13
+ end
14
+
15
+ def to_latex(args)
16
+ if !args
17
+ args = @args
18
+ end
19
+
20
+ return "\\nabla^2 #{args[0].to_latex}"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,97 @@
1
+ require 'symath/value'
2
+ require 'symath/definition/function'
3
+
4
+ module SyMath
5
+ class Definition::Lmd < Definition::Function
6
+ def initialize(exp, *vars)
7
+ super('', args: vars, exp: exp, define_symbol: false)
8
+ end
9
+
10
+ def description()
11
+ return "{self.to_s} - Lambda function of expression #{exp}"
12
+ end
13
+
14
+ def compose_with_simplify(exp, vars)
15
+ vars.each do |v|
16
+ if !v.is_a?(SyMath::Definition::Variable)
17
+ raise "Expected variable, got #{v.class.name}"
18
+ end
19
+
20
+ if v.is_d?
21
+ raise "Var is not allowed to br differential, got #{v}"
22
+ end
23
+ end
24
+
25
+ # Simplify lmd(f(*args), *args) to f(*args)
26
+ if !exp.is_a?(SyMath::Operator)
27
+ return
28
+ end
29
+
30
+ if !exp.definition.is_function?
31
+ return
32
+ end
33
+
34
+ if exp.arity != vars.length
35
+ return
36
+ end
37
+
38
+ exp.args.each do |a|
39
+ if !a.is_a?(SyMath::Definition::Variable)
40
+ return
41
+ end
42
+
43
+ if a.is_d?
44
+ return
45
+ end
46
+ end
47
+
48
+ return exp
49
+ end
50
+
51
+ # Evaluate the operator definition
52
+ # FIXME: Is it right to evaluate the definition exp?
53
+ def evaluate()
54
+ if name == '' and !exp.nil?
55
+ e = exp.evaluate
56
+ return lmd(e, self.args)
57
+ end
58
+
59
+ return self
60
+ end
61
+
62
+ # For a lambda function, the call returns a function with a reference
63
+ # to our own lambda function definition.
64
+ def call(*args)
65
+ args = args.map { |a| a.nil? ? a : a.to_m }
66
+ return SyMath::Operator.new(self, args)
67
+ end
68
+
69
+ def reduce()
70
+ # FIXME: Reduce if lmd is just a wrapper around a function.
71
+ return self
72
+ end
73
+
74
+ def to_s(args = nil)
75
+ if !args
76
+ args = @args
77
+ end
78
+
79
+ if args.length > 0
80
+ arglist = args.map { |a| a.to_s }.join(',')
81
+ else
82
+ arglist = "..."
83
+ end
84
+
85
+ return "(#{exp}).(#{arglist})"
86
+ end
87
+
88
+ def latex_format()
89
+ return "(#{exp}).(%s)"
90
+ end
91
+ end
92
+ end
93
+
94
+ def lmd(exp, *args)
95
+ # Create a lamda (nameless) function.
96
+ return SyMath::Definition::Lmd.new(exp, *args)
97
+ end
@@ -0,0 +1,45 @@
1
+ require 'symath/definition/function'
2
+
3
+ module SyMath
4
+ class Definition::Ln < Definition::Function
5
+ def initialize()
6
+ super(:ln)
7
+
8
+ @reductions_real = {
9
+ 1.to_m => 0.to_m,
10
+ :e.to_m => 1.to_m,
11
+ 0.to_m => -:oo.to_m,
12
+ :oo.to_m => :oo.to_m,
13
+ }
14
+
15
+ @reductions_complex = {
16
+ 1.to_m => 0.to_m,
17
+ :e.to_m => 1.to_m,
18
+ -1.to_m => :pi.to_m*:i,
19
+ -:e.to_m => 1.to_m + :pi.to_m*:i,
20
+ :i.to_m => :pi.to_m*:i/2,
21
+ :e.to_m*:i => 1.to_m + :pi.to_m*:i/2,
22
+ -:i.to_m => -:pi.to_m*:i/2,
23
+ -:e.to_m*:i => 1.to_m - :pi.to_m*:i/2,
24
+ }
25
+ end
26
+
27
+ def description()
28
+ return 'ln(x) - natural logarithm'
29
+ end
30
+
31
+ def reduce_call(c)
32
+ arg = c.args[0]
33
+
34
+ if SyMath.setting(:complex_arithmetic)
35
+ return super(c, @reductions_complex)
36
+ else
37
+ if arg.is_a?(SyMath::Minus)
38
+ return :nan.to_m
39
+ end
40
+
41
+ return super(c, @reductions_real)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,51 @@
1
+ require 'symath/definition'
2
+
3
+ module SyMath
4
+ class Definition::Number < Definition
5
+ def initialize(name)
6
+ super(name.to_s, define_symbol: false)
7
+ end
8
+
9
+ def description()
10
+ return "#{name} - natural number"
11
+ end
12
+
13
+ def value()
14
+ return self.name.to_s.to_i
15
+ end
16
+
17
+ def is_nan?()
18
+ return false
19
+ end
20
+
21
+ def is_finite?()
22
+ return true
23
+ end
24
+
25
+ def is_positive?()
26
+ return value() > 0
27
+ end
28
+
29
+ def is_number?()
30
+ return true
31
+ end
32
+
33
+ def is_zero?()
34
+ return value() == 0
35
+ end
36
+
37
+ def type()
38
+ return :natural.to_t
39
+ end
40
+ end
41
+ end
42
+
43
+ class Integer
44
+ def to_m()
45
+ if self < 0
46
+ return SyMath::Definition::Number.new(-self).neg
47
+ else
48
+ return SyMath::Definition::Number.new(self)
49
+ end
50
+ end
51
+ end