gps_pvt 0.1.1

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