gps_pvt 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/CHANGELOG.md +5 -0
  4. data/CODE_OF_CONDUCT.md +84 -0
  5. data/Gemfile +10 -0
  6. data/README.md +86 -0
  7. data/Rakefile +86 -0
  8. data/bin/console +15 -0
  9. data/bin/setup +8 -0
  10. data/ext/gps_pvt/Coordinate/Coordinate_wrap.cxx +6613 -0
  11. data/ext/gps_pvt/GPS/GPS_wrap.cxx +16019 -0
  12. data/ext/gps_pvt/SylphideMath/SylphideMath_wrap.cxx +21050 -0
  13. data/ext/gps_pvt/extconf.rb +70 -0
  14. data/ext/ninja-scan-light/tool/navigation/EGM.h +2971 -0
  15. data/ext/ninja-scan-light/tool/navigation/GPS.h +2432 -0
  16. data/ext/ninja-scan-light/tool/navigation/GPS_Solver.h +479 -0
  17. data/ext/ninja-scan-light/tool/navigation/GPS_Solver_Base.h +1081 -0
  18. data/ext/ninja-scan-light/tool/navigation/GPS_Solver_MultiFrequency.h +199 -0
  19. data/ext/ninja-scan-light/tool/navigation/GPS_Solver_RAIM.h +210 -0
  20. data/ext/ninja-scan-light/tool/navigation/MagneticField.h +928 -0
  21. data/ext/ninja-scan-light/tool/navigation/NTCM.h +211 -0
  22. data/ext/ninja-scan-light/tool/navigation/RINEX.h +1781 -0
  23. data/ext/ninja-scan-light/tool/navigation/WGS84.h +186 -0
  24. data/ext/ninja-scan-light/tool/navigation/coordinate.h +406 -0
  25. data/ext/ninja-scan-light/tool/param/bit_array.h +145 -0
  26. data/ext/ninja-scan-light/tool/param/complex.h +558 -0
  27. data/ext/ninja-scan-light/tool/param/matrix.h +4049 -0
  28. data/ext/ninja-scan-light/tool/param/matrix_fixed.h +665 -0
  29. data/ext/ninja-scan-light/tool/param/matrix_special.h +562 -0
  30. data/ext/ninja-scan-light/tool/param/quaternion.h +765 -0
  31. data/ext/ninja-scan-light/tool/param/vector3.h +651 -0
  32. data/ext/ninja-scan-light/tool/swig/Coordinate.i +177 -0
  33. data/ext/ninja-scan-light/tool/swig/GPS.i +1102 -0
  34. data/ext/ninja-scan-light/tool/swig/SylphideMath.i +1234 -0
  35. data/ext/ninja-scan-light/tool/swig/extconf.rb +5 -0
  36. data/ext/ninja-scan-light/tool/swig/makefile +53 -0
  37. data/ext/ninja-scan-light/tool/swig/spec/GPS_spec.rb +417 -0
  38. data/ext/ninja-scan-light/tool/swig/spec/SylphideMath_spec.rb +489 -0
  39. data/gps_pvt.gemspec +57 -0
  40. data/lib/gps_pvt/receiver.rb +375 -0
  41. data/lib/gps_pvt/ubx.rb +148 -0
  42. data/lib/gps_pvt/version.rb +5 -0
  43. data/lib/gps_pvt.rb +9 -0
  44. data/sig/gps_pvt.rbs +4 -0
  45. metadata +117 -0
@@ -0,0 +1,489 @@
1
+ require 'rspec'
2
+
3
+ $: << File::join(File::dirname(__FILE__), '..', 'build_SWIG')
4
+ require 'SylphideMath.so'
5
+
6
+ require 'matrix'
7
+
8
+ shared_examples 'Matrix' do
9
+ let(:params){{
10
+ :rc => [8, 8],
11
+ :acceptable_delta => 1E-10,
12
+ }}
13
+ describe "initializer" do
14
+ let(:compare_with){
15
+ params[:rc][0].times.map{params[:rc][1].times.map{gen_elm.call}}
16
+ }
17
+ it 'accepts (i,j)' do
18
+ expect{ mat_type::new(*params[:rc]) }.not_to raise_error
19
+ expect( mat_type::new(*params[:rc]).rows ).to equal(params[:rc][0])
20
+ expect( mat_type::new(*params[:rc]).columns ).to equal(params[:rc][1])
21
+ end
22
+ it 'accepts ([[]])' do
23
+ expect{ mat_type::new(compare_with) }.not_to raise_error
24
+ expect( mat_type::new(compare_with).rows ).to equal(params[:rc][0])
25
+ expect( mat_type::new(compare_with).columns ).to equal(params[:rc][1])
26
+ end
27
+ it 'accepts (Matrix)' do
28
+ expect{ mat_type::new(Matrix::build(*params[:rc]){0}) }.not_to raise_error
29
+ expect( mat_type::new(Matrix::build(*params[:rc]){0}).rows ).to equal(params[:rc][0])
30
+ expect( mat_type::new(Matrix::build(*params[:rc]){0}).columns ).to equal(params[:rc][1])
31
+ end
32
+ it 'accepts (custom class)' do
33
+ r, c = params[:rc]
34
+ a_gen = proc{Class.new{
35
+ define_method(:row_size){r}
36
+ define_method(:column_size){c}
37
+ define_method(:[]){|i, j| i + j}
38
+ }::new}
39
+ a = a_gen.call
40
+ expect{ mat_type::new(a) }.not_to raise_error
41
+ expect( mat_type::new(a).rows ).to equal(params[:rc][0])
42
+ expect( mat_type::new(a).columns ).to equal(params[:rc][1])
43
+
44
+ a.define_singleton_method(:[]){|i, j| raise(IndexError) if i != j; 0}
45
+ expect{ mat_type::new(a) }.to raise_error(IndexError)
46
+
47
+ a = a_gen.call
48
+ a.define_singleton_method(:row_size){-1}
49
+ expect{ mat_type::new(a) }.to raise_error(RuntimeError)
50
+ end
51
+ it 'is invoked with I, identity, unit' do
52
+ [:I, :identity, :unit].each{|f|
53
+ expect{ mat_type::send(f, params[:rc][0]) }.not_to raise_error
54
+ expect( mat_type::send(f, params[:rc][0]).rows ).to equal(params[:rc][0])
55
+ expect( mat_type::send(f, params[:rc][0]).columns ).to equal(params[:rc][1])
56
+ }
57
+ end
58
+ it 'is invoked with scalar' do
59
+ expect{ mat_type::scalar(params[:rc][0], 1) }.not_to raise_error
60
+ expect( mat_type::scalar(params[:rc][0], 1).rows ).to equal(params[:rc][0])
61
+ expect( mat_type::scalar(params[:rc][0], 1).columns ).to equal(params[:rc][1])
62
+ end
63
+ it 'sets its elements with [], [[]], Matrix' do
64
+ expect( mat_type::new(params[:rc][0], params[:rc][1], compare_with.flatten).to_a ).to eq(compare_with)
65
+ expect{ mat_type::new(params[:rc][0], params[:rc][1], compare_with.flatten[0..-2]) }.to raise_error(RuntimeError)
66
+ expect( mat_type::new(params[:rc][0], params[:rc][1], compare_with.flatten + [gen_elm.call]).to_a ).to eq(compare_with)
67
+ expect{ mat_type::new(params[:rc][0], params[:rc][1], compare_with.flatten[0..-2] + [nil]) }.to raise_error(RuntimeError)
68
+
69
+ expect( mat_type::new(params[:rc][0], params[:rc][1], compare_with).to_a ).to eq(compare_with)
70
+ expect{ mat_type::new(params[:rc][0], params[:rc][1], compare_with[0..-2]) }.to raise_error(RuntimeError)
71
+ expect( mat_type::new(params[:rc][0], params[:rc][1], compare_with + [params[:rc][1].times.map{gen_elm.call}]).to_a ).to eq(compare_with)
72
+ expect( mat_type::new(compare_with).to_a ).to eq(compare_with)
73
+
74
+ expect( mat_type::new(Matrix[*compare_with]).to_a ).to eq(compare_with)
75
+ end
76
+ it 'sets its elements with {}' do
77
+ expect( mat_type::new(*params[:rc]){|i, j| compare_with[i][j]}.to_a ).to eq(compare_with)
78
+ expect{ mat_type::new(*params[:rc]){nil}.to_a }.to raise_error(RuntimeError)
79
+ expect{ mat_type::new(compare_with){|i, j| compare_with[i][j]} }.to raise_error(ArgumentError)
80
+ expect{ mat_type::new(Matrix[*compare_with]){|i, j| compare_with[i][j]} }.to raise_error(ArgumentError)
81
+
82
+ expect{ mat_type::new(*params[:rc]){raise(IndexError) } }.to raise_error(IndexError)
83
+ end
84
+ end
85
+
86
+ describe 'property' do
87
+ let(:mat){{
88
+ :square => proc{
89
+ k = 0
90
+ mat_type::new(params[:rc][0], params[:rc][0]){|i, j| k += 1}
91
+ }.call,
92
+ :not_square => proc{
93
+ k = 0
94
+ mat_type::new(params[:rc][0], params[:rc][0] * 2){|i, j| k += 1}
95
+ }.call,
96
+ :diagonal => mat_type::new(params[:rc][0], params[:rc][0]){|i, j| i == j ? 1 : 0},
97
+ :symmetric => mat_type::new(params[:rc][0], params[:rc][0]){|i, j| i + j},
98
+ }}
99
+ describe 'is checked with' do
100
+ it 'square?' do
101
+ expect(mat[:square].square?) .to eq(true)
102
+ expect(mat[:not_square].square?).to eq(false)
103
+ expect(mat[:diagonal].square?) .to eq(true)
104
+ expect(mat[:symmetric].square?) .to eq(true)
105
+ end
106
+ it 'diagonal?' do
107
+ expect(mat[:square].diagonal?) .to eq(false)
108
+ expect(mat[:not_square].diagonal?) .to eq(false)
109
+ expect(mat[:diagonal].diagonal?) .to eq(true)
110
+ expect(mat[:symmetric].diagonal?) .to eq(false)
111
+ end
112
+ it 'symmetric?' do
113
+ expect(mat[:square].symmetric?) .to eq(false)
114
+ expect(mat[:not_square].symmetric?) .to eq(false)
115
+ expect(mat[:diagonal].symmetric?) .to eq(true)
116
+ expect(mat[:symmetric].symmetric?) .to eq(true)
117
+ end
118
+ it 'different_size?' do
119
+ mat.keys.combination(2).each{|mat1, mat2|
120
+ expect(mat[mat1].different_size?(mat[mat2])).to eq([mat1, mat2].include?(:not_square))
121
+ }
122
+ end
123
+ end
124
+ describe 'is calculated with' do
125
+ it 'trace, tr' do
126
+ [:trace, :tr].each{|f|
127
+ expect(mat[:square].send(f)).to eq(Matrix[*mat[:square].to_a].trace)
128
+ expect{mat[:not_square].send(f)}.to raise_error(RuntimeError)
129
+ }
130
+ end
131
+ it 'sum' do
132
+ expect(mat[:square].sum).to eq(Matrix[*mat[:square].to_a].sum)
133
+ expect(mat[:not_square].sum).to eq(Matrix[*mat[:not_square].to_a].sum)
134
+ end
135
+ it 'determinat, det' do
136
+ [:determinant, :det].each{|f|
137
+ #expect(mat[:square].send(f)).to eq(Matrix[*mat[:square].to_a].det)
138
+ expect{mat[:not_square].send(f)}.to raise_error(RuntimeError)
139
+ }
140
+ end
141
+ end
142
+ end
143
+
144
+ describe 'element' do
145
+ let(:compare_with){
146
+ 2.times.collect{params[:rc][0].times.map{params[:rc][1].times.map{gen_elm.call}}}
147
+ }
148
+ let(:mat){
149
+ compare_with.collect{|item| mat_type::new(item)}
150
+ }
151
+ it 'is accessible with []' do
152
+ params[:rc][0].times{|i|
153
+ params[:rc][1].times{|j|
154
+ expect(mat[0][i, j]).to eq(compare_with[0][i][j])
155
+ }
156
+ }
157
+ end
158
+ it 'is changeable with []=' do
159
+ params[:rc][0].times{|i|
160
+ params[:rc][1].times{|j|
161
+ mat[0][i, j] = compare_with[1][i][j]
162
+ expect(mat[0][i, j]).to eq(compare_with[1][i][j])
163
+ }
164
+ }
165
+ end
166
+ end
167
+
168
+ describe 'elements' do
169
+ let(:compare_with){
170
+ 2.times.collect{params[:rc][0].times.map{params[:rc][1].times.map{gen_elm.call}}}
171
+ }
172
+ let(:mat){
173
+ compare_with.collect{|item| mat_type::new(item)}
174
+ }
175
+ it 'is cloneable with copy' do
176
+ mat_orig, mat_clone = [mat[0], mat[0].copy]
177
+ expect(mat_clone).not_to equal(mat_orig)
178
+ expect(mat_clone.to_a).to eq(mat_orig.to_a)
179
+ mat_clone[0, 0] *= 2
180
+ expect(mat_clone.to_a).not_to eq(mat_orig.to_a)
181
+ end
182
+ it 'is replaceable by using replace! with [], [[]], Matrix or {}' do
183
+ [
184
+ compare_with[1].flatten, # []
185
+ compare_with[1], # [[]]
186
+ mat[1], # Matrix
187
+ Matrix[*compare_with[1]], # Matrix(builtin)
188
+ proc{|i, j| mat[1][i, j]}, # {}
189
+ ].each{|arg|
190
+ mat_orig = mat[0].copy
191
+ mat_replaced = arg.kind_of?(Proc) ? mat_orig.send(:replace!, &arg) : mat_orig.send(:replace!, arg)
192
+ expect(mat_replaced).to equal(mat_orig)
193
+ expect(mat_replaced).not_to equal(mat[1])
194
+ expect(mat_replaced.to_a).to eq(mat[1].to_a)
195
+ }
196
+ end
197
+ it 'is swappable with swap_rows! or swap_cloumns!' do
198
+ mat_builtin = Matrix[*compare_with[0]]
199
+ [:swap_rows!, :swap_columns!].each.with_index{|func, i|
200
+ params[:rc][i].times.to_a.combination(2).to_a{|a, b|
201
+ mat[0].send(func, a, b)
202
+ mat_builtin.send(func, a, b)
203
+ expect(mat[0].to_a).to eq(mat_builtin.to_a)
204
+ }
205
+ }
206
+ end
207
+ it 'is checked in their equality by using ==' do
208
+ expect(mat[0] == mat[0]).to be(true)
209
+ expect(mat[0] == mat[0].copy).to be(true)
210
+ expect(mat[0].to_a == compare_with[0]).to be(true)
211
+ expect{mat[0] == compare_with[0]}.to raise_error(ArgumentError)
212
+ expect(mat[0].to_a == Matrix[*compare_with[0]].to_a).to be(true)
213
+ expect{mat[0] == Matrix[*compare_with[0]]}.to raise_error(ArgumentError)
214
+ end
215
+ end
216
+
217
+ describe 'view' do
218
+ let(:compare_with){params[:rc][0].times.map{params[:rc][1].times.map{gen_elm.call}}}
219
+ let(:mat){mat_type::new(compare_with)}
220
+ it 'supports transposed with transpose, t' do
221
+ expect(mat.transpose.to_a).to eq(Matrix[*compare_with].transpose.to_a)
222
+ expect(mat.t.to_a).to eq(Matrix[*compare_with].t.to_a)
223
+ end
224
+ it 'supports conjugated with conjugate' do
225
+ expect(mat.conjugate.to_a).to eq(Matrix[*compare_with].conjugate.to_a) if mat.respond_to?(:conjugate)
226
+ expect(mat.conjugate.to_a).to eq(Matrix[*compare_with].conj.to_a)
227
+ end
228
+ it 'supports adjointed with adjoint' do
229
+ expect(mat.adjoint.to_a).to eq(Matrix[*compare_with].conjugate.transpose.to_a) if mat.respond_to?(:adjoint)
230
+ expect(mat.adjoint.to_a).to eq(Matrix[*compare_with].conj.t.to_a)
231
+ end
232
+ it 'supports submatrix with partial' do
233
+ expect(mat.partial(params[:rc][0] - 1, params[:rc][1] - 1, 1, 1).to_a) \
234
+ .to eq(Matrix[*compare_with[1..-1].collect{|values| values[1..-1]}].to_a)
235
+ end
236
+ it 'supports row_vector with row_vector' do
237
+ params[:rc][0].times{|i|
238
+ expect(mat.row_vector(i).to_a[0]) \
239
+ .to eq(Matrix[*compare_with].row_vectors[i].to_a)
240
+ }
241
+ end
242
+ it 'supports column_vector with column_vector' do
243
+ params[:rc][1].times{|j|
244
+ expect(mat.column_vector(j).to_a.flatten) \
245
+ .to eq(Matrix[*compare_with].column_vectors[j].to_a)
246
+ }
247
+ end
248
+ it 'generates circular matrix with circular' do
249
+ params[:rc][0].times{|i|
250
+ params[:rc][1].times{|j|
251
+ expect(mat.circular(*([i, j] + params[:rc])).to_a) \
252
+ .to eq(Matrix[*compare_with.collect{|v| v.rotate(j)}.rotate(i)].to_a)
253
+ }
254
+ }
255
+ end
256
+ end
257
+
258
+ describe 'iterator' do
259
+ let(:compare_with){params[:rc][0].times.map{params[:rc][1].times.map{gen_elm.call}}}
260
+ let(:mat){mat_type::new(compare_with)}
261
+ let(:opt){{
262
+ nil => params[:rc][0].times.to_a.product(params[:rc][1].times.to_a),
263
+ :all => params[:rc][0].times.to_a.product(params[:rc][1].times.to_a),
264
+ :diagonal => params[:rc].min.times.collect{|i| [i, i]},
265
+ :off_diagonal => params[:rc][0].times.to_a.product(params[:rc][1].times.to_a).reject{|i, j| i == j},
266
+ :lower => params[:rc][0].times.to_a.product(params[:rc][1].times.to_a).select{|i, j| i >= j},
267
+ :upper => params[:rc][0].times.to_a.product(params[:rc][1].times.to_a).select{|i, j| i <= j},
268
+ :strict_lower => params[:rc][0].times.to_a.product(params[:rc][1].times.to_a).select{|i, j| i > j},
269
+ :strict_upper => params[:rc][0].times.to_a.product(params[:rc][1].times.to_a).select{|i, j| i < j},
270
+ }}
271
+ it 'supports each, each_with_index' do
272
+ [:each, :each_with_index].each{|func|
273
+ opt.each{|k, indices|
274
+ candidates = (func.to_s =~ /with_index$/) \
275
+ ? indices.collect{|i, j| [compare_with[i][j], i, j]} \
276
+ : indices.collect{|i, j| [compare_with[i][j]]}
277
+ mat.send(*[func, k].compact){|*v|
278
+ i = candidates.find_index(v)
279
+ expect(i).not_to be(nil)
280
+ candidates.delete_at(i)
281
+ }
282
+ expect(candidates.empty?).to be(true)
283
+ }
284
+ }
285
+ end
286
+ it 'supports map, collect, map_with_index, collect_with_index' do
287
+ [:map, :collect, :map_with_index, :collect_with_index].each{|func|
288
+ opt.each{|k, indices|
289
+ candidates = (func.to_s =~ /with_index$/) \
290
+ ? indices.collect{|i, j| [compare_with[i][j], i, j]} \
291
+ : indices.collect{|i, j| [compare_with[i][j]]}
292
+ mat2 = mat.send(*[func, k].compact){|*v|
293
+ i = candidates.find_index(v)
294
+ expect(i).not_to be(nil)
295
+ candidates.delete_at(i)
296
+ v[0] * 2
297
+ }
298
+ expect(candidates.empty?).to be(true)
299
+ expect(mat.to_a).to eq(compare_with)
300
+ expect(mat2.to_a).to eq(compare_with.collect.with_index{|values, i|
301
+ values.collect.with_index{|v, j|
302
+ indices.include?([i, j]) ? (v * 2) : v
303
+ }
304
+ })
305
+ }
306
+ }
307
+ end
308
+ it 'supports map!, collect!, map_with_index!, collect_with_index!' do
309
+ [:map!, :collect!].each{|func|
310
+ opt.each{|k, indices|
311
+ candidates = (func.to_s =~ /with_index$/) \
312
+ ? indices.collect{|i, j| [compare_with[i][j], i, j]} \
313
+ : indices.collect{|i, j| [compare_with[i][j]]}
314
+ mat = mat_type::new(compare_with)
315
+ mat2 = mat.send(*[func, k].compact){|*v|
316
+ i = candidates.find_index(v)
317
+ expect(i).not_to be(nil)
318
+ candidates.delete_at(i)
319
+ v[0] * 2
320
+ }
321
+ expect(candidates.empty?).to be(true)
322
+ expect(mat2.to_a).to eq(mat.to_a)
323
+ expect(mat2.to_a).to eq(compare_with.collect.with_index{|values, i|
324
+ values.collect.with_index{|v, j|
325
+ indices.include?([i, j]) ? (v * 2) : v
326
+ }
327
+ })
328
+ }
329
+ }
330
+ end
331
+ end
332
+
333
+ describe 'operators' do
334
+ let(:compare_with){ # [N*N, N*N, N*(N+1), N*(N+1)]
335
+ 2.times.collect{params[:rc][0].times.map{params[:rc][0].times.map{gen_elm.call}}} \
336
+ + 2.times.collect{params[:rc][0].times.map{(params[:rc][0] + 1).times.map{gen_elm.call}}}
337
+ }
338
+ let(:mat){
339
+ compare_with.collect{|item| mat_type::new(item)}
340
+ }
341
+ it 'have unary -' do
342
+ [0, 2].each{|i|
343
+ expect((-mat[i]).to_a).to eq((Matrix[*compare_with[i]] * -1).to_a)
344
+ }
345
+ end
346
+ it 'have +(scalar)' do
347
+ expect((mat[0] + 1).to_a).to eq((Matrix[*compare_with[0]] + Matrix::unit(params[:rc][0])).to_a)
348
+ expect{mat[2] + 1}.to raise_error(RuntimeError)
349
+ end
350
+ it 'have +(mat)' do
351
+ [[0, 1], [2, 3]].each{|i, j|
352
+ expect((mat[i] + mat[j]).to_a).to eq((Matrix[*compare_with[i]] + Matrix[*compare_with[j]]).to_a)
353
+ }
354
+ end
355
+ it 'have -(scalar)' do
356
+ expect((mat[0] - 1).to_a).to eq((Matrix[*compare_with[0]] - Matrix::unit(params[:rc][0])).to_a)
357
+ expect{mat[2] - 1}.to raise_error(RuntimeError)
358
+ end
359
+ it 'have -(mat)' do
360
+ [[0, 1], [2, 3]].each{|i, j|
361
+ expect((mat[i] - mat[j]).to_a).to eq((Matrix[*compare_with[i]] - Matrix[*compare_with[j]]).to_a)
362
+ }
363
+ end
364
+ it 'have *(scalar)' do
365
+ [0, 2].each{|i|
366
+ expect((mat[i] * 2).to_a).to eq((Matrix[*compare_with[i]] * 2).to_a)
367
+ }
368
+ end
369
+ it 'have *(mat)' do
370
+ expect((mat[0] * mat[1]).to_a).to eq((Matrix[*compare_with[0]] * Matrix[*compare_with[1]]).to_a)
371
+ expect{mat[2] * mat[3]}.to raise_error(RuntimeError)
372
+ expect((mat[2] * mat[3].t).to_a).to eq((Matrix[*compare_with[2]] * Matrix[*compare_with[3]].t).to_a)
373
+ end
374
+ it 'have /(scalar)' do
375
+ expect((mat[0] / 2).to_a).to eq((Matrix[*compare_with[0]] / 2).to_a)
376
+ expect((mat[2] / 2).to_a).to eq((Matrix[*compare_with[2]] / 2).to_a)
377
+ end
378
+ let(:inversible){
379
+ # L * U
380
+ mat_type::new(compare_with[0]).map_with_index!{|v, i, j| (i >= j) ? (i == j ? 1 : v) : 0} \
381
+ * mat_type::new(compare_with[1]).map_with_index!{|v, i, j| (i <= j) ? (i == j ? 1 : v) : 0}
382
+ }
383
+ it 'have inverse, inv' do
384
+ [:inverse, :inv].each{|func|
385
+ (Matrix[*(inversible.send(func).to_a)] - Matrix[*(inversible.to_a)].send(func)).each{|v|
386
+ expect(v.abs).to be < params[:acceptable_delta]
387
+ }
388
+ expect{mat[2].send(func)}.to raise_error(RuntimeError)
389
+ }
390
+ end
391
+ it 'have /(mat)' do
392
+ (Matrix[*((mat[0] / mat[1]).to_a)] - (Matrix[*compare_with[0]] / Matrix[*compare_with[1]])).each{|v|
393
+ expect(v.abs).to be < params[:acceptable_delta]
394
+ }
395
+ expect{mat[2] / mat[3]}.to raise_error(RuntimeError)
396
+ end
397
+ end
398
+
399
+ describe 'decomposition' do
400
+ let(:compare_with){ params[:rc][0].times.map{params[:rc][0].times.map{gen_elm.call} } }
401
+ let(:mat){{
402
+ :L => mat_type::new(compare_with).map_with_index!{|v, i, j| (i >= j) ? (i == j ? 1 : v) : 0},
403
+ :U => mat_type::new(compare_with).map_with_index!{|v, i, j| (i <= j) ? (i == j ? 1 : v) : 0},
404
+ :D => mat_type::new(compare_with).map_with_index!{|v, i, j| (i == j) ? v : 0},
405
+ :Q => mat_type::new(params[:rc][0].times.map{(params[:rc][0] * 2).times.map{gen_elm.call}}).qr[0],
406
+ }}
407
+ it 'supports LU' do
408
+ src = mat_type::new(Matrix[*mat[:L].to_a] * Matrix[*mat[:U].to_a])
409
+ [:lup, :lup_decomposition].each{|func|
410
+ mat_l, mat_u, mat_p = src.send(func).collect{|item| Matrix[*item.to_a]}
411
+ expect(mat_l.lower_triangular?).to be(true)
412
+ expect(mat_u.upper_triangular?).to be(true)
413
+ ((mat_l * mat_u * mat_p) - Matrix[*src.to_a]).each{|v|
414
+ expect(v.abs).to be < params[:acceptable_delta]
415
+ }
416
+ }
417
+ end
418
+ it 'supports QR' do
419
+ src = mat_type::new(Matrix[*mat[:L].to_a] * Matrix[*mat[:U].to_a])
420
+ [:qr, :qr_decomposition].each{|func|
421
+ [[0, 0], [2, 0], [0, 2]].each{|i, j|
422
+ src2 = src.partial(src.rows - i, src.columns - j, i, j)
423
+ mat_q, mat_r = src2.send(func).collect{|item| Matrix[*item.to_a]}
424
+ expect(mat_r.upper_triangular?).to be(true)
425
+ expect((mat_q.det - 1).abs).to be < params[:acceptable_delta]
426
+ ((mat_q * mat_r) - Matrix[*src2.to_a]).each{|v|
427
+ expect(v.abs).to be < params[:acceptable_delta]
428
+ }
429
+ ((mat_q * mat_q.t.conj) - Matrix::unit(mat_q.row_size)).each{|v|
430
+ expect(v.abs).to be < params[:acceptable_delta]
431
+ }
432
+ }
433
+ }
434
+ end
435
+ it 'supports eigenvalue' do
436
+ mat_q, mat_u = [:Q, :U].collect{|k| Matrix[*mat[k].map{|v| v}.to_a]}
437
+ expect((mat_q.det - 1).abs).to be < params[:acceptable_delta]
438
+ expect(mat_u.det).to eq(1)
439
+ src = mat_q * mat_u * Matrix[*mat[:D].to_a]
440
+ mat_v, mat_d = mat_type::new(src.to_a).eigen.collect{|item| Matrix[*item.to_a]}
441
+ expect(mat_d.diagonal?).to be(true)
442
+ mat_d.row_size.times{|i|
443
+ (src * mat_v.column_vectors[0] - mat_v.column_vectors[0] * mat_d[0, 0]).each{|v|
444
+ expect(v.abs).to be < params[:acceptable_delta]
445
+ }
446
+ }
447
+ end
448
+ end
449
+ end
450
+
451
+ =begin
452
+ TODO
453
+ :debug
454
+ :to_s
455
+ :to_a
456
+ =end
457
+
458
+ describe SylphideMath::MatrixD do
459
+ let(:mat_type){SylphideMath::MatrixD}
460
+ let(:gen_elm){proc{rand}}
461
+ include_examples 'Matrix'
462
+
463
+ describe 'decomposition' do
464
+ let(:compare_with){ params[:rc][0].times.map{params[:rc][0].times.map{gen_elm.call} } }
465
+ let(:mat){{
466
+ :U => mat_type::new(compare_with).map_with_index!{|v, i, j| (i <= j) ? (i == j ? 1 : v) : 0},
467
+ :D => mat_type::new(compare_with).map_with_index!{|v, i, j| (i == j) ? v : 0},
468
+ }}
469
+ it 'supports UD' do
470
+ src = mat_type::new((Matrix[*mat[:U].to_a] * Matrix[*mat[:D].to_a] * Matrix[*mat[:U].t.to_a]).to_a)
471
+ src.map_with_index!(:strict_upper){|v, i, j| src[j, i]}
472
+ expect(Matrix[*src.to_a].symmetric?).to be(true)
473
+ [:ud, :ud_decomposition].each{|func|
474
+ mat_u, mat_d = src.send(func).collect{|item| Matrix[*item.to_a]}
475
+ expect(mat_u.upper_triangular?).to be(true)
476
+ expect(mat_d.diagonal?).to be(true)
477
+ ((mat_u * mat_d * mat_u.t) - Matrix[*src.to_a]).each{|v|
478
+ expect(v.abs).to be < params[:acceptable_delta]
479
+ }
480
+ }
481
+ end
482
+ end
483
+ end
484
+
485
+ describe SylphideMath::MatrixComplexD do
486
+ let(:mat_type){SylphideMath::MatrixComplexD}
487
+ let(:gen_elm){proc{Complex(rand, rand)}}
488
+ include_examples 'Matrix'
489
+ end
data/gps_pvt.gemspec ADDED
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/gps_pvt/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "gps_pvt"
7
+ spec.version = GPS_PVT::VERSION
8
+ spec.authors = ["fenrir(M.Naruoka)"]
9
+ spec.email = ["fenrir.naru@gmail.com"]
10
+
11
+ spec.summary = "GPS position, velocity, and time (PVT) solver"
12
+ spec.description = "This module calculate PVT by using raw observation obtained from a GPS receiver"
13
+ spec.homepage = "https://github.com/fenrir-naru/gps_pvt"
14
+ spec.required_ruby_version = ">= 2.6.0"
15
+
16
+ #spec.metadata["allowed_push_host"] = "TODO: Set to your gem server 'https://example.com'"
17
+
18
+ spec.metadata["homepage_uri"] = spec.homepage
19
+ spec.metadata["source_code_uri"] = spec.homepage
20
+ #spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
21
+
22
+ spec.extensions = ["ext/gps_pvt/extconf.rb"]
23
+
24
+ # Specify which files should be added to the gem when it is released.
25
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
26
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
27
+ `git ls-files -z`.split("\x0").reject do |f|
28
+ (f == __FILE__) || f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
29
+ end
30
+ end
31
+ spec.bindir = "exe"
32
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
33
+ spec.require_paths = ["lib"]
34
+
35
+ spec.files += proc{
36
+ base_dir = File::absolute_path(File.dirname(__FILE__))
37
+ require 'pathname'
38
+ # get an array of submodule dirs by executing 'pwd' inside each submodule
39
+ `git submodule --quiet foreach pwd`.split($/).collect{|dir|
40
+ # issue git ls-files in submodule's directory
41
+ `git -C #{dir} ls-files -v`.split($/).collect{|f|
42
+ next nil unless f =~ /^H */ # consider git sparse checkout
43
+ # get relative path
44
+ f = Pathname::new(File::join(dir, $'))
45
+ (f.relative? ? f : f.relative_path_from(base_dir)).to_s
46
+ }.compact
47
+ }.flatten
48
+ }.call
49
+
50
+ # Uncomment to register a new dependency of your gem
51
+ # spec.add_dependency "example-gem", "~> 1.0"
52
+ spec.add_development_dependency "rake"
53
+ spec.add_development_dependency "rake-compiler"
54
+
55
+ # For more information and examples about making a new gem, checkout our
56
+ # guide at: https://bundler.io/guides/creating_gem.html
57
+ end