gps_pvt 0.9.3 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -380,6 +380,32 @@ struct MatrixBuilder_Dependency<
380
380
  (MatrixViewProperty<ViewType_R>::transposed ? nR_R : nC_R)>,
381
381
  ViewType> > {};
382
382
 
383
+ template <
384
+ class T, class T_op,
385
+ class T2, class T3, class T4, class T5,
386
+ class ViewType,
387
+ int nR_L, int nC_L, class ViewType_L,
388
+ int nR_R, int nC_R, class ViewType_R,
389
+ bool horizontal_R>
390
+ struct MatrixBuilder_Dependency<
391
+ Matrix_Frozen<
392
+ T,
393
+ Array2D_Operator<T_op, Array2D_Operator_Stack<
394
+ Matrix_Frozen<T2, Array2D_Fixed<T3, nR_L, nC_L>, ViewType_L>,
395
+ Matrix_Frozen<T4, Array2D_Fixed<T5, nR_R, nC_R>, ViewType_R>,
396
+ horizontal_R> >,
397
+ ViewType> >
398
+ : public MatrixBuilder_Dependency<
399
+ Matrix_Frozen<
400
+ T,
401
+ Array2D_Fixed<
402
+ T,
403
+ (MatrixViewProperty<ViewType_L>::transposed ? nC_L : nR_L)
404
+ + (horizontal_R ? 0 : (MatrixViewProperty<ViewType_R>::transposed ? nC_R : nR_R)),
405
+ (MatrixViewProperty<ViewType_L>::transposed ? nR_L : nC_L)
406
+ + (horizontal_R ? (MatrixViewProperty<ViewType_R>::transposed ? nR_R : nC_R) : 0)>,
407
+ ViewType> > {};
408
+
383
409
  // For optimization of local temporary matrix
384
410
  template <
385
411
  template <class, class, class> class MatrixT,
@@ -1094,18 +1094,18 @@ struct GPS_User_PVT
1094
1094
  .append(inspect_str(v_key_value)).append("}").c_str());
1095
1095
  }
1096
1096
  rb_hash_foreach(v_key_value,
1097
- #if RUBY_API_VERSION < 20700
1097
+ %#if RUBY_API_VERSION_CODE < 20700
1098
1098
  // @see https://docs.ruby-lang.org/ja/latest/doc/news=2f2_7_0.html
1099
1099
  (int (*)(ANYARGS))
1100
- #endif
1100
+ %#endif
1101
1101
  arg_t::iter2, v_arg);
1102
1102
  return ST_CONTINUE;
1103
1103
  }
1104
1104
  } arg = {val};
1105
1105
  rb_hash_foreach(obj,
1106
- #if RUBY_API_VERSION < 20700
1106
+ %#if RUBY_API_VERSION_CODE < 20700
1107
1107
  (int (*)(ANYARGS))
1108
- #endif
1108
+ %#endif
1109
1109
  arg_t::iter1, reinterpret_cast<VALUE>(&arg));
1110
1110
  return SWIG_OK;
1111
1111
  }
@@ -1169,6 +1169,7 @@ struct GPS_Measurement {
1169
1169
  L1_RANGE_RATE_SIGMA,
1170
1170
  L1_SIGNAL_STRENGTH_dBHz,
1171
1171
  L1_LOCK_SEC,
1172
+ L1_CARRIER_PHASE_AMBIGUITY_SCALE,
1172
1173
  L1_FREQUENCY,
1173
1174
  #define make_entry(key) L2CM_ ## key, L2CL_ ## key
1174
1175
  #define make_entry2(key) make_entry(key), make_entry(key ## _SIGMA)
@@ -1178,6 +1179,7 @@ struct GPS_Measurement {
1178
1179
  make_entry2(RANGE_RATE),
1179
1180
  make_entry(SIGNAL_STRENGTH_dBHz),
1180
1181
  make_entry(LOCK_SEC),
1182
+ make_entry(CARRIER_PHASE_AMBIGUITY_SCALE),
1181
1183
  #undef make_entry2
1182
1184
  #undef make_entry
1183
1185
  ITEMS_PREDEFINED,
@@ -123,16 +123,16 @@ class Complex;
123
123
  typedef Complex<T> value_type;
124
124
  static int asval(VALUE obj, value_type *v) {
125
125
  if(RB_TYPE_P(obj, T_COMPLEX)){
126
- #if RUBY_API_VERSION_CODE < 20600
126
+ %#if RUBY_API_VERSION_CODE < 20600
127
127
  static const ID id_r(rb_intern("real")), id_i(rb_intern("imag"));
128
128
  int res = swig::asval(rb_funcall(obj, id_r, 0), &(v->real()));
129
129
  if(!SWIG_IsOK(res)){return res;}
130
130
  return swig::asval(rb_funcall(obj, id_i, 0), &(v->imaginary()));
131
- #else
131
+ %#else
132
132
  int res = swig::asval(rb_complex_real(obj), &(v->real()));
133
133
  if(!SWIG_IsOK(res)){return res;}
134
134
  return swig::asval(rb_complex_imag(obj), &(v->imaginary()));
135
- #endif
135
+ %#endif
136
136
  }else{
137
137
  v->imaginary() = T(0);
138
138
  return swig::asval(obj, &(v->real()));
@@ -148,14 +148,14 @@ class Complex;
148
148
  template <class T> struct traits_check< Complex<T>, value_category> {
149
149
  static bool check(VALUE obj) {
150
150
  if(RB_TYPE_P(obj, T_COMPLEX)){
151
- #if RUBY_API_VERSION_CODE < 20600
151
+ %#if RUBY_API_VERSION_CODE < 20600
152
152
  static const ID id_r(rb_intern("real")), id_i(rb_intern("imag"));
153
153
  return swig::check<T>(rb_funcall(obj, id_r, 0))
154
154
  && swig::check<T>(rb_funcall(obj, id_i, 0));
155
- #else
155
+ %#else
156
156
  return swig::check<T>(rb_complex_real(obj))
157
157
  && swig::check<T>(rb_complex_imag(obj));
158
- #endif
158
+ %#endif
159
159
  }else{
160
160
  return swig::check<T>(obj);
161
161
  }
@@ -345,12 +345,6 @@ struct MatrixViewFilter : public BaseView {
345
345
  res.view().partial(new_rows, new_columns, row_offset, column_offset);
346
346
  return res;
347
347
  }
348
- template <class T, class Array2D_Type, class ViewType>
349
- static Matrix_Frozen<T, Array2D_Type, self_t> partial(
350
- const Matrix_Frozen<T, Array2D_Type, ViewType> &orig,
351
- const unsigned int &new_rows, const unsigned int &new_columns) {
352
- return partial(orig, new_rows, new_columns, 0, 0);
353
- }
354
348
 
355
349
  template<class CharT, class Traits>
356
350
  friend std::basic_ostream<CharT, Traits> &operator<<(
@@ -412,17 +406,27 @@ class Matrix_Frozen {
412
406
  template <class T2, class Array2D_Type2, class ViewType2>
413
407
  bool operator==(const Matrix_Frozen<T2, Array2D_Type2, ViewType2> &matrix) const noexcept;
414
408
  // bool operator!= // automatically defined
415
-
409
+
416
410
  bool isSquare() const noexcept;
417
411
  bool isDiagonal() const noexcept;
412
+ bool isLowerTriangular() const noexcept;
413
+ bool isUpperTriangular() const noexcept;
418
414
  bool isSymmetric() const noexcept;
415
+ bool isHermitian() const noexcept;
416
+ bool isSkewSymmetric() const noexcept;
417
+ bool isNormal() const noexcept;
418
+ bool isOrthogonal() const noexcept;
419
+ bool isUnitary() const noexcept;
419
420
 
420
- T trace(const bool &do_check = true) const;
421
+ T trace() const;
421
422
  T sum() const noexcept;
422
423
 
423
424
  // bool isLU() const noexcept
424
425
 
425
- T determinant(const bool &do_check = true) const;
426
+ T determinant() const;
427
+ unsigned int rank() const;
428
+ T cofactor(
429
+ const unsigned int &row, const unsigned int &column) const;
426
430
  };
427
431
 
428
432
  template <class T, class Array2D_Type, class ViewType = MatrixViewBase<> >
@@ -470,6 +474,11 @@ typedef MatrixViewTranspose<MatrixViewSizeVariable<MatrixViewOffset<MatrixViewBa
470
474
 
471
475
  %{
472
476
  struct MatrixUtil {
477
+ struct each_break_t {
478
+ unsigned int r, c;
479
+ each_break_t(const unsigned int &row, const unsigned int &column)
480
+ : r(row), c(column) {}
481
+ };
473
482
  enum each_which_t {
474
483
  EACH_ALL,
475
484
  EACH_DIAGONAL,
@@ -478,6 +487,7 @@ struct MatrixUtil {
478
487
  EACH_UPPER,
479
488
  EACH_STRICT_LOWER,
480
489
  EACH_STRICT_UPPER,
490
+ EACH_UNKNOWN,
481
491
  };
482
492
  template <class T,
483
493
  class Array2D_Type, class ViewType,
@@ -488,7 +498,7 @@ struct MatrixUtil {
488
498
  const T &src_elm, T *dst_elm,
489
499
  const unsigned int &i, const unsigned int &j),
490
500
  const each_which_t &each_which = EACH_ALL,
491
- Matrix<T, Array2D_Type2, ViewType2> *dst = NULL){
501
+ Matrix<T, Array2D_Type2, ViewType2> *dst = NULL) {
492
502
  unsigned int i_max(src.rows()), j_max(src.columns());
493
503
  switch(each_which){
494
504
  case EACH_DIAGONAL:
@@ -544,10 +554,8 @@ struct MatrixUtil {
544
554
  }
545
555
  }
546
556
  #if defined(SWIGRUBY)
547
- static const each_which_t &sym2each_which(const VALUE &value){
548
- if(!RB_TYPE_P(value, T_SYMBOL)){
549
- std::invalid_argument("Symbol is required");
550
- }
557
+ static each_which_t sym2each_which(const VALUE &value){
558
+ if(!RB_TYPE_P(value, T_SYMBOL)){return EACH_UNKNOWN;}
551
559
  static const struct {
552
560
  VALUE sym;
553
561
  each_which_t which;
@@ -564,9 +572,7 @@ struct MatrixUtil {
564
572
  while(value != cmp[i].sym){
565
573
  if(++i >= (sizeof(cmp) / sizeof(cmp[0]))){break;}
566
574
  }
567
- if(i >= (sizeof(cmp) / sizeof(cmp[0]))){
568
- std::invalid_argument("Unknown enumerate direction");
569
- }
575
+ if(i >= (sizeof(cmp) / sizeof(cmp[0]))){return EACH_UNKNOWN;}
570
576
  return cmp[i].which;
571
577
  }
572
578
  #endif
@@ -671,6 +677,8 @@ struct MatrixUtil {
671
677
  %catches(std::out_of_range) rowVector;
672
678
  %catches(std::out_of_range) columnVector;
673
679
  %catches(std::logic_error, std::runtime_error) determinant;
680
+ %catches(std::logic_error) rank;
681
+ %catches(std::logic_error, std::runtime_error) cofactor;
674
682
 
675
683
  T __getitem__(const unsigned int &row, const unsigned int &column) const {
676
684
  return ($self)->operator()(row, column);
@@ -731,6 +739,17 @@ struct MatrixUtil {
731
739
  return (Matrix<T, Array2D_Dense<T> >)(($self)->operator-(scalar));
732
740
  }
733
741
 
742
+ #ifdef SWIGRUBY
743
+ %alias entrywise_product "hadamard_product";
744
+ #endif
745
+ %catches(std::invalid_argument) entrywise_product;
746
+ template <class T2, class Array2D_Type2, class ViewType2>
747
+ Matrix<T, Array2D_Dense<T> > entrywise_product(
748
+ const Matrix_Frozen<T2, Array2D_Type2, ViewType2> &matrix) const {
749
+ return (Matrix<T, Array2D_Dense<T> >)(($self)->entrywise_product(matrix));
750
+ }
751
+ INSTANTIATE_MATRIX_FUNC(entrywise_product, entrywise_product);
752
+
734
753
  template <class T2, class Array2D_Type2, class ViewType2>
735
754
  Matrix<T, Array2D_Dense<T> > operator*(
736
755
  const Matrix_Frozen<T2, Array2D_Type2, ViewType2> &matrix)
@@ -738,6 +757,18 @@ struct MatrixUtil {
738
757
  return (Matrix<T, Array2D_Dense<T> >)(($self)->operator*(matrix));
739
758
  }
740
759
  INSTANTIATE_MATRIX_FUNC(operator*, __mul__);
760
+
761
+ // TODO __pow__ for **
762
+ // TODO __pos__ for +@
763
+
764
+ Matrix<T, Array2D_Dense<T> > first_minor(
765
+ const unsigned int &row,
766
+ const unsigned int &column) const noexcept {
767
+ return (Matrix<T, Array2D_Dense<T> >)(($self)->matrix_for_minor(row, column));
768
+ }
769
+ Matrix<T, Array2D_Dense<T> > adjugate() const {
770
+ return (Matrix<T, Array2D_Dense<T> >)(($self)->adjugate());
771
+ }
741
772
 
742
773
  %typemap(in,numinputs=0)
743
774
  Matrix<T, Array2D_Dense<T> > &output_L (Matrix<T, Array2D_Dense<T> > temp),
@@ -816,16 +847,33 @@ struct MatrixUtil {
816
847
  s << $self->inspect();
817
848
  return s.str();
818
849
  }
850
+
851
+ /* The followings are better to be implemented in Ruby
852
+ * combine, hstack, vstack (due to their arguments are variable)
853
+ */
819
854
 
820
855
  #ifdef SWIGRUBY
821
856
  %rename("square?") isSquare;
822
857
  %rename("diagonal?") isDiagonal;
858
+ %rename("lower_triangular?") isLowerTriangular;
859
+ %rename("upper_triangular?") isUpperTriangular;
823
860
  %rename("symmetric?") isSymmetric;
861
+ %rename("hermitian?") isHermitian;
862
+ %rename("skew_symmetric?") isSkewSymmetric;
863
+ %alias isSkewSymmetric "antisymmetric?"
864
+ %rename("normal?") isNormal;
865
+ %rename("orthogonal?") isOrthogonal;
866
+ %rename("unitary?") isUnitary;
824
867
  %rename("different_size?") isDifferentSize;
868
+ %alias __getitem__ "element,component";
869
+ // %alias __eq__ "eql?"; // Intentionally commented out because eql? is more strict than ==
870
+ %alias rows "row_size,row_count";
871
+ %alias columns "column_size,column_count";
825
872
  %alias trace "tr";
826
873
  %alias determinant "det";
827
874
  %alias inverse "inv";
828
875
  %alias transpose "t";
876
+ %alias conjugate "conj";
829
877
  %alias lup "lup_decomposition";
830
878
  %alias ud "ud_decomposition";
831
879
  %alias qr "qr_decomposition";
@@ -833,7 +881,7 @@ struct MatrixUtil {
833
881
  %fragment(SWIG_From_frag(Matrix_Frozen_Helper<T>), "header",
834
882
  fragment=SWIG_Traits_frag(T)){
835
883
  template <bool with_index = false, bool assign = false>
836
- static inline void matrix_yield_internal(
884
+ static inline VALUE matrix_yield_internal(
837
885
  const T &src, T *dst, const unsigned int &i, const unsigned int &j){
838
886
  SWIG_Object v;
839
887
  if(with_index){
@@ -848,6 +896,7 @@ struct MatrixUtil {
848
896
  s << "Unknown input (T expected) [" << i << "," << j << "]: ";
849
897
  throw std::invalid_argument(s.str().append(inspect_str(v)));
850
898
  }
899
+ return v;
851
900
  }
852
901
  static void matrix_yield(
853
902
  const T &src, T *dst, const unsigned int &i, const unsigned int &j){
@@ -865,11 +914,17 @@ struct MatrixUtil {
865
914
  const T &src, T *dst, const unsigned int &i, const unsigned int &j){
866
915
  matrix_yield_internal<true, true>(src, dst, i, j);
867
916
  }
917
+
918
+ static void matrix_yield_check(
919
+ const T &src, T *dst, const unsigned int &i, const unsigned int &j){
920
+ VALUE res(matrix_yield_internal<false, false>(src, dst, i, j));
921
+ if(RTEST(res)){throw typename MatrixUtil::each_break_t(i, j);}
922
+ }
868
923
  static void (*matrix_each(const T *))
869
924
  (const T &, T *, const unsigned int &, const unsigned int &) {
870
925
  ID id_thisf(rb_frame_this_func()), id_callee(rb_frame_callee());
871
926
  static const ID
872
- id_map(rb_intern("map")), id_mapb(rb_intern("map!")),
927
+ id_map(rb_intern("map")), id_mapb(rb_intern("map!")),
873
928
  id_eachwi(rb_intern("each_with_index"));
874
929
  if((id_thisf == id_map) || (id_thisf == id_mapb)){
875
930
  static const ID with_index[] = {
@@ -895,14 +950,14 @@ struct MatrixUtil {
895
950
  }
896
951
  $1 = matrix_each((const T *)0);
897
952
  }
898
- %typemap(typecheck) const typename MatrixUtil::each_which_t &each_which {
899
- $1 = RB_TYPE_P($input, T_SYMBOL);
953
+ %typemap(typecheck,precedence=SWIG_TYPECHECK_POINTER) const typename MatrixUtil::each_which_t each_which {
954
+ $1 = (MatrixUtil::sym2each_which($input) != MatrixUtil::EACH_UNKNOWN);
900
955
  }
901
- %typemap(in) const typename MatrixUtil::each_which_t &each_which {
902
- try{
903
- $1 = &const_cast<typename MatrixUtil::each_which_t &>(MatrixUtil::sym2each_which($input));
904
- }catch(std::invalid_argument &e){
905
- SWIG_exception(SWIG_ValueError, e.what());
956
+ %typemap(in) const typename MatrixUtil::each_which_t each_which {
957
+ $1 = MatrixUtil::sym2each_which($input);
958
+ if($1 == MatrixUtil::EACH_UNKNOWN){
959
+ SWIG_exception(SWIG_ValueError,
960
+ std::string("Unknown enumerate direction: ").append(inspect_str($1)).c_str());
906
961
  }
907
962
  }
908
963
  %catches(native_exception) each;
@@ -910,7 +965,7 @@ struct MatrixUtil {
910
965
  void (*each_func)(
911
966
  const T &src, T *dst,
912
967
  const unsigned int &i, const unsigned int &j),
913
- const typename MatrixUtil::each_which_t &each_which = MatrixUtil::EACH_ALL) const {
968
+ const typename MatrixUtil::each_which_t each_which = MatrixUtil::EACH_ALL) const {
914
969
  MatrixUtil::each(*$self, each_func, each_which);
915
970
  return *$self;
916
971
  }
@@ -921,13 +976,37 @@ struct MatrixUtil {
921
976
  void (*each_func)(
922
977
  const T &src, T *dst,
923
978
  const unsigned int &i, const unsigned int &j),
924
- const typename MatrixUtil::each_which_t &each_which = MatrixUtil::EACH_ALL) const {
979
+ const typename MatrixUtil::each_which_t each_which = MatrixUtil::EACH_ALL) const {
925
980
  Matrix<T, Array2D_Dense<T> > res($self->operator Matrix<T, Array2D_Dense<T> >());
926
981
  MatrixUtil::each(*$self, each_func, each_which, &res);
927
982
  return res;
928
983
  }
929
984
  %alias map "collect,map_with_index,collect_with_index";
930
985
 
986
+ %catches(native_exception) index;
987
+ VALUE index(
988
+ const typename MatrixUtil::each_which_t each_which = MatrixUtil::EACH_ALL) const {
989
+ try{
990
+ MatrixUtil::each(*$self, matrix_yield_check, each_which);
991
+ return Qnil;
992
+ }catch(const typename MatrixUtil::each_break_t &each_break){
993
+ return rb_ary_new_from_args(2, UINT2NUM(each_break.r), UINT2NUM(each_break.c));
994
+ }
995
+ }
996
+ %typemap(check,noblock=1) VALUE idx_selector {
997
+ if(MatrixUtil::sym2each_which($1) == MatrixUtil::EACH_UNKNOWN){
998
+ SWIG_exception(SWIG_ValueError,
999
+ std::string("Unknown enumerate direction: ").append(inspect_str($1)).c_str());
1000
+ }
1001
+ }
1002
+ VALUE index(VALUE value, VALUE idx_selector = Qnil) const {
1003
+ return rb_block_call(
1004
+ rb_current_receiver(), rb_frame_callee(),
1005
+ (RTEST(idx_selector) ? 1 : 0), &idx_selector,
1006
+ (rb_block_call_func_t)rb_equal, value);
1007
+ }
1008
+ %alias index "find_index";
1009
+
931
1010
  SWIG_Object to_a() const {
932
1011
  unsigned int i_max($self->rows()), j_max($self->columns());
933
1012
  SWIG_Object res = rb_ary_new2(i_max);
@@ -1086,7 +1165,7 @@ MAKE_TO_S(Matrix_Frozen)
1086
1165
  void (*each_func)(
1087
1166
  const T &src, T *dst,
1088
1167
  const unsigned int &i, const unsigned int &j),
1089
- const typename MatrixUtil::each_which_t &each_which = MatrixUtil::EACH_ALL){
1168
+ const typename MatrixUtil::each_which_t each_which = MatrixUtil::EACH_ALL){
1090
1169
  MatrixUtil::each(*$self, each_func, each_which, $self);
1091
1170
  }
1092
1171
  %rename("map!") map_bang;
@@ -1115,6 +1194,14 @@ MAKE_TO_S(Matrix_Frozen)
1115
1194
  return MatView_f::partial(*$self, new_rows, new_columns, row_offset, column_offset);
1116
1195
  #else
1117
1196
  return $self->partial(new_rows, new_columns, row_offset, column_offset);
1197
+ #endif
1198
+ }
1199
+ Matrix_Frozen<type, storage, view_to> partial(
1200
+ const unsigned int &new_rows, const unsigned int &new_columns) const {
1201
+ #if defined(USE_MATRIX_VIEW_FILTER)
1202
+ return MatView_f::partial(*$self, new_rows, new_columns, 0, 0);
1203
+ #else
1204
+ return $self->partial(new_rows, new_columns, 0, 0);
1118
1205
  #endif
1119
1206
  }
1120
1207
  Matrix_Frozen<type, storage, view_to> row_vector(const unsigned int &row) const {
@@ -1132,6 +1219,9 @@ MAKE_TO_S(Matrix_Frozen)
1132
1219
  #endif
1133
1220
  }
1134
1221
  };
1222
+ /* Ruby #row, #column, #row_vectors, #column_vectors are not intentionally implemented
1223
+ * because a vector is treated as a (1*n) or (n*1) matrix in C++.
1224
+ */
1135
1225
  %enddef
1136
1226
 
1137
1227
  %define INSTANTIATE_MATRIX_EIGEN2(type, ctype, storage, view)
@@ -1152,7 +1242,7 @@ MAKE_TO_S(Matrix_Frozen)
1152
1242
  void eigen(
1153
1243
  Matrix<ctype, Array2D_Dense<ctype > > &output_V,
1154
1244
  Matrix<ctype, Array2D_Dense<ctype > > &output_D) const {
1155
- typedef typename Matrix_Frozen<type, storage, view >::complex_t::m_t cmat_t;
1245
+ typedef Matrix<ctype, Array2D_Dense<ctype > > cmat_t;
1156
1246
  cmat_t VD($self->eigen());
1157
1247
  output_V = VD.partial($self->rows(), $self->rows()).copy();
1158
1248
  cmat_t D($self->rows(), $self->rows());
@@ -1308,6 +1398,19 @@ INSTANTIATE_MATRIX_EIGEN(double, Complex<double>);
1308
1398
  INSTANTIATE_MATRIX(Complex<double>, ComplexD);
1309
1399
  INSTANTIATE_MATRIX_EIGEN(Complex<double>, Complex<double>);
1310
1400
 
1401
+ %rename("tolerance=") set_tolerance;
1402
+ %rename("tolerance") get_tolerance;
1403
+ %inline %{
1404
+ double set_tolerance(const double &width){
1405
+ MatrixValue<double>::zero = width;
1406
+ MatrixValue<Complex<double> >::zero = width;
1407
+ return width;
1408
+ }
1409
+ double get_tolerance(){
1410
+ return set_tolerance(MatrixValue<double>::zero.width);
1411
+ }
1412
+ %}
1413
+
1311
1414
  #undef INSTANTIATE_MATRIX_FUNC
1312
1415
  #undef INSTANTIATE_MATRIX_TRANSPOSE
1313
1416
  #undef INSTANTIATE_MATRIX_PARTIAL
@@ -6,6 +6,8 @@ require 'SylphideMath.so'
6
6
  require 'matrix'
7
7
 
8
8
  shared_examples 'Matrix' do
9
+ let!(:tolerance){SylphideMath::tolerance}
10
+ after{SylphideMath::tolerance = tolerance}
9
11
  let(:params){{
10
12
  :rc => [8, 8],
11
13
  :acceptable_delta => 1E-10,
@@ -92,17 +94,25 @@ shared_examples 'Matrix' do
92
94
  end
93
95
 
94
96
  describe 'property' do
95
- let(:mat){{
96
- :square => proc{
97
+ let(:mat_gen){{
98
+ :square => proc{|r| # example: [[1, 3, 6], [2, 5, 8], [4, 7, 9]]
97
99
  k = 0
98
- mat_type::new(params[:rc][0], params[:rc][0]){|i, j| k += 1}
99
- }.call,
100
+ res = mat_type::new(r, r)
101
+ (r * 2 - 1).times{|ij|
102
+ (([ij - r + 1, 0].max)..([ij, r - 1].min)).each{|i| res[ij - i, i] = (k += 1)}
103
+ }
104
+ res
105
+ }
106
+ }}
107
+ let(:mat){{
108
+ :square => mat_gen[:square].call(params[:rc][0]),
100
109
  :not_square => proc{
101
110
  k = 0
102
111
  mat_type::new(params[:rc][0], params[:rc][0] * 2){|i, j| k += 1}
103
112
  }.call,
104
113
  :diagonal => mat_type::new(params[:rc][0], params[:rc][0]){|i, j| i == j ? 1 : 0},
105
114
  :symmetric => mat_type::new(params[:rc][0], params[:rc][0]){|i, j| i + j},
115
+ :unit => mat_type::I(params[:rc][0]),
106
116
  }}
107
117
  describe 'is checked with' do
108
118
  it 'square?' do
@@ -117,12 +127,52 @@ shared_examples 'Matrix' do
117
127
  expect(mat[:diagonal].diagonal?) .to eq(true)
118
128
  expect(mat[:symmetric].diagonal?) .to eq(false)
119
129
  end
130
+ it 'lower_triangular?' do
131
+ expect(mat[:square].lower_triangular?) .to eq(false)
132
+ expect(mat[:not_square].lower_triangular?) .to eq(false)
133
+ expect(mat[:diagonal].lower_triangular?) .to eq(true)
134
+ expect(mat[:symmetric].lower_triangular?) .to eq(false)
135
+ end
136
+ it 'upper_triangular?' do
137
+ expect(mat[:square].upper_triangular?) .to eq(false)
138
+ expect(mat[:not_square].upper_triangular?) .to eq(false)
139
+ expect(mat[:diagonal].upper_triangular?) .to eq(true)
140
+ expect(mat[:symmetric].upper_triangular?) .to eq(false)
141
+ end
120
142
  it 'symmetric?' do
121
143
  expect(mat[:square].symmetric?) .to eq(false)
122
144
  expect(mat[:not_square].symmetric?) .to eq(false)
123
145
  expect(mat[:diagonal].symmetric?) .to eq(true)
124
146
  expect(mat[:symmetric].symmetric?) .to eq(true)
125
147
  end
148
+ it 'hermitian?' do
149
+ expect(mat[:square].hermitian?) .to eq(false)
150
+ expect(mat[:not_square].hermitian?) .to eq(false)
151
+ expect(mat[:diagonal].hermitian?) .to eq(true)
152
+ expect(mat[:symmetric].hermitian?) .to eq(true)
153
+ end
154
+ it 'skew_symmetric?' do
155
+ expect(mat[:square].skew_symmetric?) .to eq(false)
156
+ expect(mat[:not_square].skew_symmetric?) .to eq(false)
157
+ expect(mat[:diagonal].skew_symmetric?) .to eq(true)
158
+ expect(mat[:symmetric].skew_symmetric?) .to eq(false)
159
+ end
160
+ it 'normal?' do
161
+ expect(mat[:square].normal?) .to eq(false)
162
+ expect(mat[:not_square].normal?) .to eq(false)
163
+ expect(mat[:diagonal].normal?) .to eq(true)
164
+ expect(mat[:symmetric].normal?) .to eq(true)
165
+ end
166
+ it 'orthogonal?' do
167
+ expect(mat[:square].orthogonal?) .to eq(false)
168
+ expect(mat[:not_square].orthogonal?).to eq(false)
169
+ expect(mat[:unit].orthogonal?) .to eq(true)
170
+ end
171
+ it 'unitary?' do
172
+ expect(mat[:square].unitary?) .to eq(false)
173
+ expect(mat[:not_square].unitary?) .to eq(false)
174
+ expect(mat[:unit].unitary?) .to eq(true)
175
+ end
126
176
  it 'different_size?' do
127
177
  mat.keys.combination(2).each{|mat1, mat2|
128
178
  expect(mat[mat1].different_size?(mat[mat2])).to eq([mat1, mat2].include?(:not_square))
@@ -142,10 +192,40 @@ shared_examples 'Matrix' do
142
192
  end
143
193
  it 'determinant, det' do
144
194
  [:determinant, :det].each{|f|
145
- #expect(mat[:square].send(f)).to eq(Matrix[*mat[:square].to_a].det)
195
+ expect(mat[:square].send(f)).to eq(Matrix[*mat[:square].to_a].det)
146
196
  expect{mat[:not_square].send(f)}.to raise_error(RuntimeError)
147
197
  }
148
198
  end
199
+ it 'rank' do
200
+ (5..8).each{|n|
201
+ orig = mat_gen[:square].call(n)
202
+ expect(orig.rank).to eq(Matrix[*orig.to_a].rank)
203
+ }
204
+ expect(mat[:symmetric].rank).to eq(Matrix[*mat[:symmetric].to_a].rank)
205
+ expect{mat[:not_square].rank}.to raise_error(RuntimeError)
206
+ end
207
+ it 'cofactor' do
208
+ SylphideMath::tolerance = 1E-10
209
+ (5..8).each{|n|
210
+ orig = mat_gen[:square].call(n)
211
+ cmp = Matrix[*orig.to_a]
212
+ orig.rows.times{|i|
213
+ orig.columns.times{|j|
214
+ a, b = [orig, cmp].collect{|item| item.cofactor(i, j)} #rescue next
215
+ expect((a - b).abs).to be < params[:acceptable_delta]
216
+ }
217
+ }
218
+ }
219
+ end
220
+ it 'adjugate' do
221
+ SylphideMath::tolerance = 1E-10
222
+ (5..8).each{|n|
223
+ orig = mat_gen[:square].call(n)
224
+ (Matrix[*orig.adjugate.to_a] - Matrix[*orig.to_a].adjugate).each{|v|
225
+ expect(v.abs).to be < params[:acceptable_delta]
226
+ }
227
+ }
228
+ end
149
229
  end
150
230
  end
151
231
 
@@ -257,6 +337,8 @@ shared_examples 'Matrix' do
257
337
  expect(mat.adjoint.to_a).to eq(Matrix[*compare_with].conj.t.to_a)
258
338
  end
259
339
  it 'supports submatrix with partial' do
340
+ expect(mat.partial(params[:rc][0] - 1, params[:rc][1] - 1).to_a) \
341
+ .to eq(Matrix[*compare_with[0..-2].collect{|values| values[0..-2]}].to_a)
260
342
  expect(mat.partial(params[:rc][0] - 1, params[:rc][1] - 1, 1, 1).to_a) \
261
343
  .to eq(Matrix[*compare_with[1..-1].collect{|values| values[1..-1]}].to_a)
262
344
  end
@@ -280,6 +362,14 @@ shared_examples 'Matrix' do
280
362
  }
281
363
  }
282
364
  end
365
+ it 'generates minor matrix with first_minor' do
366
+ params[:rc][0].times{|i|
367
+ params[:rc][1].times{|j|
368
+ expect(mat.first_minor(i, j).to_a) \
369
+ .to eq(Matrix[*compare_with].first_minor(i, j).to_a)
370
+ }
371
+ }
372
+ end
283
373
  end
284
374
 
285
375
  describe 'iterator' do
@@ -310,6 +400,19 @@ shared_examples 'Matrix' do
310
400
  }
311
401
  }
312
402
  end
403
+ it 'supports index, find_index' do
404
+ cnd = proc{|v| v.abs >= 0.5}
405
+ [:index, :find_index].each{|func|
406
+ opt.each{|k, indices|
407
+ expect(mat.send(*[func, k].compact, &cnd)).to eq(
408
+ indices.select{|i, j| cnd.call(compare_with[i][j])}.first)
409
+ indices.each{|i, j|
410
+ expect(mat.send(*[func, compare_with[i][j], k].compact)).to eq([i, j])
411
+ }
412
+ expect(mat.send(*[func, 1, k].compact)).to be(nil)
413
+ }
414
+ }
415
+ end
313
416
  it 'supports map, collect, map_with_index, collect_with_index' do
314
417
  [:map, :collect, :map_with_index, :collect_with_index].each{|func|
315
418
  opt.each{|k, indices|
@@ -398,6 +501,13 @@ shared_examples 'Matrix' do
398
501
  expect{mat[2] * mat[3]}.to raise_error(ArgumentError)
399
502
  expect((mat[2] * mat[3].t).to_a).to eq((Matrix[*compare_with[2]] * Matrix[*compare_with[3]].t).to_a)
400
503
  end
504
+ it 'have entrywise_product(mat), a.k.a. .*(mat)' do
505
+ [:entrywise_product, :hadamard_product].each{|func|
506
+ [[0, 1], [2, 3]].each{|i, j|
507
+ expect((mat[i].send(func, mat[j])).to_a).to eq((Matrix[*compare_with[i]].send(func, Matrix[*compare_with[j]])).to_a)
508
+ }
509
+ } if Gem::Version::create(RUBY_VERSION) >= Gem::Version::create("2.5.0")
510
+ end
401
511
  it 'have /(scalar)' do
402
512
  expect((mat[0] / 2).to_a).to eq((Matrix[*compare_with[0]] / 2).to_a)
403
513
  expect((mat[2] / 2).to_a).to eq((Matrix[*compare_with[2]] / 2).to_a)
data/gps_pvt.gemspec CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
17
17
 
18
18
  spec.metadata["homepage_uri"] = spec.homepage
19
19
  spec.metadata["source_code_uri"] = spec.homepage
20
- #spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
20
+ #spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
21
21
 
22
22
  spec.extensions = ["ext/gps_pvt/extconf.rb"]
23
23
 
@@ -63,6 +63,7 @@ Gem::Specification.new do |spec|
63
63
  spec.add_development_dependency "rake-compiler"
64
64
  spec.add_development_dependency "rspec", "~> 3.0"
65
65
  spec.add_development_dependency "matrix" if GPS_PVT::version_compare(RUBY_VERSION, "3.1") >= 0
66
+ spec.add_development_dependency "github_changelog_generator"
66
67
 
67
68
  # For more information and examples about making a new gem, checkout our
68
69
  # guide at: https://bundler.io/guides/creating_gem.html
data/lib/gps_pvt/ntrip.rb CHANGED
@@ -54,7 +54,7 @@ class Ntrip < Net::HTTP
54
54
  llh0 = Coordinate::LLH::new(D2R * lat_deg, D2R * lng_deg, 0)
55
55
  collect{|pt, prop|
56
56
  llh = Coordinate::LLH::new(*([:latitude, :longitude].collect{|k| D2R * prop[k].to_f} + [0]))
57
- [llh0.xyz.dist(llh.xyz), prop]
57
+ [llh0.xyz.distance(llh.xyz), prop]
58
58
  }.sort{|a, b| a[0] <=> b[0]} # return [distance, property]
59
59
  end
60
60
  end