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,228 @@
1
+ require 'symath/definition'
2
+
3
+ module SyMath
4
+ class Definition::Operator < Definition
5
+ attr_reader :args
6
+ attr_reader :exp
7
+
8
+ def self.init_builtin()
9
+ SyMath::Definition::D.new
10
+ SyMath::Definition::Xd.new
11
+ SyMath::Definition::Int.new
12
+ SyMath::Definition::Bounds.new
13
+ SyMath::Definition::Sharp.new
14
+ SyMath::Definition::Flat.new
15
+ SyMath::Definition::Hodge.new
16
+ SyMath::Definition::Grad.new
17
+ SyMath::Definition::Curl.new
18
+ SyMath::Definition::Div.new
19
+ SyMath::Definition::Laplacian.new
20
+ SyMath::Definition::CoDiff.new
21
+
22
+ expressions = [
23
+ { :name => 'laplace',
24
+ :exp => 'lmd(int(f.(t)*e**(-s*t),d(t),0,oo),s)',
25
+ :desc => 'laplace transform',
26
+ },
27
+ { :name => 'fourier',
28
+ :exp => 'lmd(int(f.(x)*e**(-2*pi*i*x*w),d(x),-oo,oo),w)',
29
+ :desc => 'fourier transform',
30
+ },
31
+ { :name => 'invfourier',
32
+ :exp => 'lmd(int(f.(w)*e**(2*pi*i*x*w),d(w),-oo,oo),x)',
33
+ :desc => 'inverse fourier transform',
34
+ },
35
+ ]
36
+
37
+ expressions.each do |e|
38
+ self.new(e[:name], args: [:f], exp: e[:exp],
39
+ description: "#{e[:name]}(f) - #{e[:desc]}")
40
+ end
41
+
42
+ e = op(:d, lmd(:f, :t))/op(:d, :t)
43
+ self.new('dpart', args: [:f, :t], exp: e,
44
+ description: 'dpart - partial derivative')
45
+ end
46
+
47
+ def self.operators()
48
+ return self.definitions.select do |d|
49
+ d.is_operator? and !d.is_function?
50
+ end
51
+ end
52
+
53
+ def initialize(name, args: [], exp: nil, define_symbol: true,
54
+ description: nil)
55
+ if exp and !exp.is_a?(SyMath::Value)
56
+ exp = exp.to_m
57
+ end
58
+
59
+ @args = args.map { |a| a.to_m }
60
+ @exp = exp
61
+
62
+ super(name, define_symbol: define_symbol, description: description)
63
+ end
64
+
65
+ def compose_with_simplify(*args)
66
+ return
67
+ end
68
+
69
+ def validate_args(e)
70
+ return
71
+ end
72
+
73
+ def arity()
74
+ return @args.length
75
+ end
76
+
77
+ def ==(other)
78
+ if !super(other)
79
+ return false
80
+ end
81
+
82
+ o = other.to_m
83
+ return false if self.args.length != o.args.length
84
+ return false if self.exp != o.exp
85
+ return false if self.args != o.args
86
+ return true
87
+ end
88
+
89
+ alias eql? ==
90
+
91
+ def <=>(other)
92
+ s = super(other)
93
+ return s if s != 0
94
+
95
+ if arity != other.arity
96
+ return arity <=> other.arity
97
+ end
98
+
99
+ (0...arity).to_a.each do |i|
100
+ diff = args[i] <=> other.args[i]
101
+ if diff != 0
102
+ return diff
103
+ end
104
+ end
105
+
106
+ return 0
107
+ end
108
+
109
+ # The call method, or the .() operator, returns an operator or function
110
+ # object representing the operator or function being applied to a list of
111
+ # arguments.
112
+ def call(*args)
113
+ return SyMath::Operator.create(name, args.map { |a| a.nil? ? a : a.to_m })
114
+ end
115
+
116
+ def is_operator?()
117
+ return true
118
+ end
119
+
120
+ # Evaluate the operator in use
121
+ def evaluate_call(c)
122
+ if !exp
123
+ # Operator has no expression, return it unchanged.
124
+ return c
125
+ end
126
+
127
+ # Operator has expression. Exand it.
128
+ res = exp.deep_clone
129
+ if arity != c.arity
130
+ raise "Cannot evaluate #{name} with #{c.arity} arguments. Expected #{arity}."
131
+ end
132
+
133
+ map = {}
134
+ args.each_with_index do |a, i|
135
+ map[a] = c.args[i]
136
+ end
137
+ res.replace(map)
138
+
139
+ # Recursively evaluate the expanded formula.
140
+ res = res.evaluate
141
+ return res
142
+ end
143
+
144
+ def replace(map)
145
+ # FIXME: We probably need to filter out the local variables before
146
+ # replacing
147
+ if !exp.nil?
148
+ @exp = exp.replace(map)
149
+ end
150
+
151
+ # Replace all arguments
152
+ @args = @args.map do |a|
153
+ a.replace(map)
154
+ end
155
+
156
+ return self
157
+ end
158
+
159
+ def to_s(args = nil)
160
+ if !args
161
+ args = @args
162
+ end
163
+
164
+ if args.length > 0
165
+ arglist = args.map { |a| a.to_s }.join(',')
166
+ else
167
+ arglist = "..."
168
+ end
169
+
170
+ return "#{@name}(#{arglist})"
171
+ end
172
+
173
+ def latex_format()
174
+ return "\\operatorname{#{name}}(%s)"
175
+ end
176
+
177
+ def to_latex(args = nil)
178
+ if !args
179
+ args = @args
180
+ end
181
+
182
+ if args.length > 0
183
+ arglist = args.map { |a| a.to_latex }.join(',')
184
+ else
185
+ arglist = "..."
186
+ end
187
+
188
+ return sprintf(latex_format, arglist)
189
+ end
190
+
191
+ def dump(indent = 0)
192
+ res = super(indent)
193
+ i = ' '*indent
194
+ if args
195
+ arglist = args.map { |a| a.to_s }.join(',')
196
+ res = "#{res}\n#{i} args: #{arglist}"
197
+ end
198
+ if exp
199
+ res = "#{res}\n#{i} exp: #{exp}"
200
+ end
201
+ end
202
+ end
203
+ end
204
+
205
+ def op(o, *args)
206
+ return SyMath::Operator.create(o, args.map { |a| a.nil? ? a : a.to_m })
207
+ end
208
+
209
+ def define_op(name, args, exp = nil)
210
+ if exp
211
+ return SyMath::Definition::Operator.new(name, args: args, exp: exp)
212
+ else
213
+ return SyMath::Definition::Operator.new(name, args: args)
214
+ end
215
+ end
216
+
217
+ require 'symath/definition/d'
218
+ require 'symath/definition/xd'
219
+ require 'symath/definition/int'
220
+ require 'symath/definition/bounds'
221
+ require 'symath/definition/sharp'
222
+ require 'symath/definition/flat'
223
+ require 'symath/definition/hodge'
224
+ require 'symath/definition/grad'
225
+ require 'symath/definition/curl'
226
+ require 'symath/definition/div'
227
+ require 'symath/definition/laplacian'
228
+ require 'symath/definition/codiff'
@@ -0,0 +1,17 @@
1
+ require 'symath/definition/trig'
2
+
3
+ module SyMath
4
+ class Definition::Sec < Definition::Trig
5
+ def initialize()
6
+ super(:sec)
7
+ end
8
+
9
+ def description()
10
+ return 'sec(x) - trigonometric secant'
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,31 @@
1
+ require 'symath/value'
2
+ require 'symath/definition/operator'
3
+
4
+ module SyMath
5
+ class Definition::Sharp < Definition::Operator
6
+ def initialize()
7
+ super(:sharp)
8
+ end
9
+
10
+ def description()
11
+ return 'sharp(f) - musical raise/sharp/# 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.sharp
17
+ end
18
+
19
+ def to_s(args = nil)
20
+ if !args
21
+ args = @args
22
+ end
23
+
24
+ return "\#(#{args[0]})"
25
+ end
26
+
27
+ def latex_format()
28
+ return '%s^\sharp'
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,17 @@
1
+ require 'symath/definition/trig'
2
+
3
+ module SyMath
4
+ class Definition::Sin < Definition::Trig
5
+ def initialize()
6
+ super(:sin)
7
+ end
8
+
9
+ def description()
10
+ return 'sin(x) - trigonometric sine'
11
+ end
12
+
13
+ def reduce_call(c)
14
+ return reduce_sin_and_cos(c, 0)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,62 @@
1
+ require 'symath/definition/function'
2
+
3
+ module SyMath
4
+ class Definition::Sqrt < Definition::Function
5
+ def initialize()
6
+ super(:sqrt)
7
+ end
8
+
9
+ def description()
10
+ return 'sqrt(x) - square root'
11
+ end
12
+
13
+ def reduce_call(call)
14
+ arg = call.args[0]
15
+ i = 1.to_m
16
+
17
+ # Real: sqrt(-n) = NaN
18
+ # Complex: sqrt(-n) = i*sqrt(n)
19
+ if arg.is_a?(SyMath::Minus)
20
+ if SyMath.setting(:complex_arithmetic)
21
+ i = :i.to_m
22
+ arg = -arg
23
+ else
24
+ return :nan.to_m
25
+ end
26
+ end
27
+
28
+ if arg.is_number?
29
+ # sqrt(n*n) = n
30
+ # sqrt(-n*n) = i*n
31
+ if (Math.sqrt(arg.value) % 1).zero?
32
+ return i*Math.sqrt(arg.value).to_i
33
+ end
34
+ elsif arg.is_a?(SyMath::Power)
35
+ # sqrt(n**(2*a)) = n^a
36
+ # sqrt(-n**(2*a)) = i*n**a
37
+
38
+ # Find coefficient of exponent
39
+ c = 1
40
+ arg.exponent.factors.each do |ef|
41
+ if ef.is_number?
42
+ c *= ef.value
43
+ end
44
+ end
45
+
46
+ if c.even?
47
+ return i*arg.base**(arg.exponent/2)
48
+ end
49
+ end
50
+
51
+ if i != 1
52
+ return i*fn(:sqrt, arg)
53
+ else
54
+ return call
55
+ end
56
+ end
57
+
58
+ def to_latex(args = nil)
59
+ return '\sqrt{'.to_s + args[0].to_latex + '}'.to_s
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,17 @@
1
+ require 'symath/definition/trig'
2
+
3
+ module SyMath
4
+ class Definition::Tan < Definition::Trig
5
+ def initialize()
6
+ super(:tan)
7
+ end
8
+
9
+ def description()
10
+ return 'tan(x) - trigonometric tangent'
11
+ end
12
+
13
+ def reduce_call(c)
14
+ return reduce_tan_and_cot(c, 0, 1)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,95 @@
1
+ require 'symath/definition/function'
2
+
3
+ module SyMath
4
+ class Definition::Trig < Definition::Function
5
+ @@trig_reductions = {}
6
+
7
+ def self.initialize()
8
+ sqrt3 = fn(:sqrt, 3)
9
+ sqrt2 = fn(:sqrt, 2)
10
+
11
+ @@trig_reductions = {
12
+ :sin_div6 => [ 0.to_m, 1.to_m/2, sqrt3/2,
13
+ 1.to_m, sqrt3/2, 1.to_m/2,
14
+ 0.to_m, -(1.to_m/2), -(sqrt3/2),
15
+ -1.to_m, -(sqrt3/2), -(1.to_m/2)],
16
+
17
+ :sin_div4 => [ 0.to_m, sqrt2/2,
18
+ 1.to_m, sqrt2/2,
19
+ 0.to_m, -(sqrt2/2),
20
+ -1.to_m, -(sqrt2/2)],
21
+
22
+ :sec_div6 => [ 1.to_m, 2.to_m*sqrt3/3, 2.to_m,
23
+ nil, -2.to_m, -(2.to_m*sqrt3/2),
24
+ -1.to_m, -(2.to_m*sqrt3/3), -2.to_m,
25
+ nil, 2.to_m, 2.to_m*sqrt3/3],
26
+
27
+ :sec_div4 => [ 1.to_m, sqrt2/2,
28
+ nil, -(sqrt2/2),
29
+ -1.to_m, -(sqrt2/2),
30
+ nil, sqrt2/2],
31
+
32
+ :tan_div6 => [0.to_m, sqrt3/3, sqrt3,
33
+ nil, -sqrt3, -(sqrt3/3)],
34
+
35
+ :tan_div4 => [0.to_m, 1.to_m,
36
+ nil, -1.to_m],
37
+ }
38
+ end
39
+
40
+ def reduce_sin_and_cos(f, off)
41
+ c, dc = check_pi_fraction(f.args[0], false)
42
+ return f if c.nil?
43
+
44
+ # Divisor is divisible by 6
45
+ if 6 % dc == 0
46
+ return @@trig_reductions[:sin_div6][(off*3 + c*6/dc) % 12]
47
+ end
48
+
49
+ # Divisor is divisible by 4
50
+ if 4 % dc == 0
51
+ return @@trig_reductions[:sin_div4][(off*2 + c*4/dc) % 8]
52
+ end
53
+
54
+ return f
55
+ end
56
+
57
+ def reduce_tan_and_cot(f, off, sign)
58
+ c, dc = check_pi_fraction(f.args[0], false)
59
+ return f if c.nil?
60
+
61
+ # Divisor is divisible by 6
62
+ if 6 % dc == 0
63
+ ret = @@trig_reductions[:tan_div6][(off*3 + sign*c*6/dc) % 6]
64
+ return ret.nil? ? f : ret
65
+ end
66
+
67
+ # Divisor is divisible by 4
68
+ if 4 % dc == 0
69
+ ret = @@trig_reductions[:tan_div4][(off*2 + sign*c*4/dc) % 4]
70
+ return ret.nil? ? f : ret
71
+ end
72
+
73
+ return f
74
+ end
75
+
76
+ def reduce_sec_and_csc(f, off)
77
+ c, dc = check_pi_fraction(f.args[0], false)
78
+ return f if c.nil?
79
+
80
+ # Divisor is divisible by 6
81
+ if 6 % dc == 0
82
+ ret = @@trig_reductions[:sec_div6][(off*3 + c*6/dc) % 12]
83
+ return ret.nil? ? f : ret
84
+ end
85
+
86
+ # Divisor is divisible by 4
87
+ if 4 % dc == 0
88
+ ret = @@trig_reductions[:sec_div4][(off*2 + c*4/dc) % 8]
89
+ return ret.nil? ? f : ret
90
+ end
91
+
92
+ return f
93
+ end
94
+ end
95
+ end