SheafSystem  0.0.0.0
symmetric_matrix_3x3.impl.h
1 
2 //
3 // Copyright (c) 2014 Limit Point Systems, Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 
18 // Implementation for symmetric_matrix_3x3.
19 
20 
21 #ifndef SYMMETRIC_MATRIX_3X3_IMPL_H
22 #define SYMMETRIC_MATRIX_3X3_IMPL_H
23 
24 #ifndef SHEAF_DLL_SPEC_H
25 #include "SheafSystem/sheaf_dll_spec.h"
26 #endif
27 
28 #ifndef ASSERT_CONTRACT_H
29 #include "SheafSystem/assert_contract.h"
30 #endif
31 
32 #ifndef ERROR_MESSAGE_H
33 #include "SheafSystem/error_message.h"
34 #endif
35 
36 #ifndef GENERAL_MATRIX_1x3_H
37 #include "SheafSystem/general_matrix_1x3.h"
38 #endif
39 
40 #ifndef GENERAL_MATRIX_3X1_H
41 #include "SheafSystem/general_matrix_3x1.h"
42 #endif
43 
44 #ifndef GENERAL_MATRIX_3X2_H
45 #include "SheafSystem/general_matrix_3x2.h"
46 #endif
47 
48 #ifndef GENERAL_MATRIX_3X3_H
49 #include "SheafSystem/general_matrix_3x3.h"
50 #endif
51 
52 #ifndef SYMMETRIC_MATRIX_3X3_H
53 #include "SheafSystem/symmetric_matrix_3x3.h"
54 #endif
55 
56 #ifndef STD_SSTREAM_H
57 #include "SheafSystem/std_sstream.h"
58 #endif
59 
60 #ifndef STD_CMATH_H
61 #include "SheafSystem/std_cmath.h"
62 #endif
63 
64 #ifndef STD_ALGORITHM_H
65 #include "SheafSystem/std_algorithm.h"
66 #endif
67 
68 
69 namespace fiber_bundle
70 {
71 
72 using namespace sheaf;
73 
74 //==============================================================================
75 // MEMBER FUNCTIONS
76 //==============================================================================
77 
79 template <typename T>
80 symmetric_matrix_3x3<T>::
81 operator met_e3_row_dofs_type<T>& () const
82 {
83  // Preconditions:
84 
85  // Body:
86 
87  T* lcomps = const_cast<T*>(components);
88 
89  met_e3_row_dofs_type<T>& result =
90  reinterpret_cast<met_e3_row_dofs_type<T>&>(*lcomps);
91 
92 
93  return result;
94 }
95 
96 
98 template <typename T>
100 operator st2_e3_row_dofs_type<T>& () const
101 {
102  // Preconditions:
103 
104  // Body:
105 
106  T* lcomps = const_cast<T*>(components);
107 
108  st2_e3_row_dofs_type<T>& result =
109  reinterpret_cast<st2_e3_row_dofs_type<T>&>(*lcomps);
110 
111 
112  return result;
113 }
114 
116 template <typename T>
117 int
120 {
121  // Preconditions:
122 
123  // Body:
124 
125  // Postconditions:
126 
127  // Exit:
128 
129  return 3;
130 }
131 
133 template <typename T>
134 int
137 {
138  // Preconditions:
139 
140  // Body:
141 
142  // Postconditions:
143 
144  // Exit:
145 
146  return 3;
147 }
148 
150 template <typename T>
151 int
153 d()
154 {
155  // Preconditions:
156 
157  // Body:
158 
159  // Postconditions:
160 
161  // Exit:
162 
163  return 6;
164 }
165 
167 template <typename T>
168 T*
170 operator[](int nrow)
171 {
172  // Preconditions:
173 
174  require(nrow >= 0 && nrow < number_of_rows());
175 
176  // Body:
177 
178  T* result = &components[row_index(nrow)];
179 
180  // Postconditions:
181 
182  ensure(result != 0);
183 
184  // Exit:
185 
186  return result;
187 }
188 
189 template <typename T>
190 const T*
192 operator[](int nrow) const
193 {
194  // Preconditions:
195 
196  require(nrow >= 0 && nrow < number_of_rows());
197 
198  // Body:
199 
200  const T* result = &components[row_index(nrow)];
201 
202  // Postconditions:
203 
204  ensure(result != 0);
205 
206  // Exit:
207 
208  return result;
209 }
210 
212 template <typename T>
214 operator T* ()
215 {
216  // Preconditions:
217 
218  // Body:
219 
220  //cout << "symmetric_matrix_3x3<T>::operator T* () " << std::endl;
221 
222  T* result = components;
223 
224  // Postconditions:
225 
226  ensure(result != 0);
227 
228  // Exit:
229 
230  return result;
231 }
232 
234 template <typename T>
236 operator const T* () const
237 {
238  // Preconditions:
239 
240  // Body:
241 
242  //cout << "symmetric_matrix_3x3<T>::operator const T* () const " << std::endl;
243 
244  const T* result = components;
245 
246  // Postconditions:
247 
248  ensure(result != 0);
249 
250  // Exit:
251 
252  return result;
253 }
254 
256 template <typename T>
257 int
259 row_index(int xrow) const
260 {
261 
262  // Preconditions:
263 
264  require(xrow >= 0 && xrow < number_of_rows());
265 
266  // Body:
267 
268  int nrows = number_of_rows();
269  int result = (xrow*(2*nrows-1-xrow))/2;
270 
271  //int result = (xrow*(5-xrow))/2;
272 
273  // Postconditions:
274 
275  ensure(result == (xrow*(2*number_of_rows()-1-xrow))/2);
276 
277  // Exit:
278 
279  return result;
280 }
281 
283 template <typename T>
285 operator general_matrix_3x3<T> () const
286 {
287  // Preconditions:
288 
289  // Body:
290 
291  general_matrix_3x3<T> result;
292 
293  const symmetric_matrix_3x3<T>& lm = *this;
294 
295  result[0][0] = lm[0][0];
296  result[0][1] = lm[0][1];
297  result[0][2] = lm[0][2];
298 
299  result[1][0] = lm[0][1];
300  result[1][1] = lm[1][1];
301  result[1][2] = lm[1][2];
302 
303  result[2][0] = lm[0][2];
304  result[2][1] = lm[1][2];
305  result[2][2] = lm[2][2];
306 
307  // Postconditions:
308 
309  ensure(unexecutable("result == *this"));
310 
311  // Exit:
312 
313  return result;
314 }
315 
317 template <typename T>
320 row(int xrow) const
321 {
322  // Preconditions:
323 
324  require(xrow >= 0 && xrow < number_of_rows());
325 
326  // Body:
327 
328  general_matrix_1x3<T> result;
329 
330  // Just brute force it for the 3x3 case.
331 
332  if(xrow == 0)
333  {
334  result.components[0] = components[0]; // lm[0][0];
335  result.components[1] = components[1]; // lm[0][1];
336  result.components[2] = components[2]; // lm[0][2];
337  }
338  else if(xrow == 1)
339  {
340  result.components[0] = components[1]; // lm[0][1];
341  result.components[1] = components[3]; // lm[1][1];
342  result.components[2] = components[4]; // lm[1][2];
343  }
344  else // xrow == 2
345  {
346  result.components[0] = components[2]; // lm[0][2];
347  result.components[1] = components[4]; // lm[1][2];
348  result.components[2] = components[5]; // lm[2][2];
349  }
350 
351  // Postconditions:
352 
353  // Exit:
354 
355  return result;
356 
357 }
358 
360 template <typename T>
363 column(int xcolumn) const
364 {
365  // Preconditions:
366 
367  require(xcolumn >= 0 && xcolumn < number_of_columns());
368 
369  // Body:
370 
371  general_matrix_3x1<T> result;
372 
373  // Just brute force it for the 3x3 case.
374 
375  if(xcolumn == 0)
376  {
377  result.components[0] = components[0]; // lm[0][0];
378  result.components[1] = components[1]; // lm[1][0];
379  result.components[2] = components[2]; // lm[2][0];
380  }
381  else if(xcolumn == 1)
382  {
383  result.components[0] = components[1]; // lm[0][1];
384  result.components[1] = components[3]; // lm[1][1];
385  result.components[2] = components[4]; // lm[2][1];
386  }
387  else // xcolumn == 2
388  {
389  result.components[0] = components[2]; // lm[0][2];
390  result.components[1] = components[4]; // lm[1][2];
391  result.components[2] = components[5]; // lm[2][2];
392  }
393 
394  // Postconditions:
395 
396  // Exit:
397 
398  return result;
399 }
400 
402 template <typename T>
403 void
406 {
407  // Preconditions:
408 
409  // Body:
410 
411  // Get the cofactors.
412 
413  const symmetric_matrix_3x3<T>& lm = *this;
414 
415  T a00 = lm[0][0];
416  T a01 = lm[0][1];
417  T a02 = lm[0][2];
418  T a10 = a01;
419  T a11 = lm[1][1];
420  T a12 = lm[1][2];
421  T a20 = a02;
422  T a21 = a12;
423  T a22 = lm[2][2];
424 
425  T c00 = a11*a22 - a12*a21;
426  //T c01 = a12*a20 - a10*a22;
427  //T c02 = a10*a21 - a11*a20;
428 
429  T c10 = a02*a21 - a01*a22;
430  T c11 = a00*a22 - a02*a20;
431  //T c12 = a01*a20 - a00*a21;
432 
433  T c20 = a01*a12 - a02*a11;
434  T c21 = a02*a10 - a00*a12;
435  T c22 = a00*a11 - a01*a10;
436 
437  // The adjoint matrix is the transpose of the cofactor matrix.
438 
439  xresult[0][0] = c00;
440  xresult[0][1] = c10;
441  xresult[0][2] = c20;
442 
443  //xresult[1][0] = c01;
444  xresult[1][1] = c11;
445  xresult[1][2] = c21;
446 
447  //xresult[2][0] = c02;
448  //xresult[2][1] = c12;
449  xresult[2][2] = c22;
450 
451 
452  // Postconditions:
453 
454  // Exit:
455 }
456 
458 template <typename T>
461 adjoint() const
462 {
463  // Preconditions:
464 
465  // Body:
466 
468  adjoint(result);
469 
470  // Postconditions:
471 
472  // Exit:
473 
474  return result;
475 }
476 
478 template <typename T>
479 void
481 assign(const T& xvalue)
482 {
483  // Preconditions:
484 
485  // Body:
486 
487  for(int i=0; i<d(); ++i)
488  {
489  components[i] = xvalue;
490  }
491 
492  // Postconditions:
493 
494  ensure_for_all(i, 0, d(), components[i] == xvalue);
495 
496  // Exit:
497 
498 }
499 
501 template <typename T>
502 void
504 determinant(T& xresult) const
505 {
506  // Preconditions:
507 
508  // Body:
509 
510  const symmetric_matrix_3x3<T>& lm = *this;
511 
512  T a00 = lm[0][0];
513  T a01 = lm[0][1];
514  T a02 = lm[0][2];
515  T a10 = a01;
516  T a11 = lm[1][1];
517  T a12 = lm[1][2];
518  T a20 = a02;
519  T a21 = a12;
520  T a22 = lm[2][2];
521 
522  T c00 = a11*a22 - a12*a21;
523  T c01 = a12*a20 - a10*a22;
524  T c02 = a10*a21 - a11*a20;
525 
526  xresult = a00*c00 + a01*c01 + a02*c02;
527 
528  // Postconditions:
529 
530  // Exit:
531 
532 }
533 
535 template <typename T>
536 T
538 determinant() const
539 {
540  // Preconditions:
541 
542  // Body:
543 
544  T result;
545 
546  determinant(result);
547 
548  // Postconditions:
549 
550  // Exit:
551 
552  return result;
553 }
554 
556 template <typename T>
557 void
560 {
561  // Preconditions:
562 
563  // Body:
564 
565  // Calculate the eigenvalues of the matrix.
566 
567  // For 3x3 matrices the eigenvalues can be determined
568  // by solving a cubic equation, ie;
569  // a*x*x*x = b*x*x +c*x +d = 0.
570 
571  //@todo $$TODO: We need a templated cubic equation solver function.
572  // For example:
573  // template <typename T> cubic_solver(T a, T b, T c, T d,
574  // T result[3]);
575 
576  T lambda_0;
577  T lambda_1;
578  T lambda_2;
579 
580  const T zero = T(0);
581 
582  const symmetric_matrix_3x3<T>& lm = *this;
583 
584  T a00 = lm[0][0];
585  T a01 = lm[0][1];
586  T a02 = lm[0][2];
587  T a10 = a01;
588  T a11 = lm[1][1];
589  T a12 = lm[1][2];
590  T a20 = a02;
591  T a21 = a12;
592  T a22 = lm[2][2];
593 
594  T d = -determinant();
595  T c = a00*(a11 + a22) + a11*a22 - a01*a10 - a02*a20 - a12*a21;
596  T b = -(a00 + a11 + a22);
597  T a = 1.0;
598 
599  // If the determanant (-d) == 0.0, one eigenvalue is 0 and we can factor
600  // to get a quadratic to solve (a*x*x = b*x +c = 0).
601 
602  if(d == 0)
603  {
604  T discriminant = b*b - 4.0*c;
605 
606  if(discriminant < 0.0)
607  {
608  post_fatal_error_message("Matrix has 2 complex roots.");
609  }
610 
611  T sqrt_discriminant = sqrt(discriminant);
612 
613  lambda_0 = zero;
614  lambda_1 = 0.5*(-b+sqrt_discriminant);;
615  lambda_2 = 0.5*(-b-sqrt_discriminant);
616  }
617  else
618  {
619  T q = (3.0*c - b*b)/9.0;
620  T r = (b*(9.0*c - 2.0*b*b) - 27.0*d) / 54.0;
621 
622  T discriminant = q*q*q + r*r;
623  T b3 = b/3.0;
624 
625  if(discriminant > 0.0)
626  {
627  // There is one real root and 2 complex conjugate roots.
628 
629  post_fatal_error_message("Matrix has 2 complex roots.");
630  }
631  else if(discriminant == 0.0)
632  {
633  // There are 3 real roots and 2 are equal.
634 
635  T powr = (r < 0) ? -pow(-r, 1.0/3.0) : pow(r, 1.0/3.0);
636  lambda_0 = (2.0*powr) - b3;
637  lambda_1 = (-powr) - b3;
638  lambda_2 = lambda_1;
639  }
640  else // discriminant < 0.0
641  {
642  // There are 3 real unequal roots.
643 
644  // Need pi but M_PI is not part of the standard; so compute it.
645 
646  static const T L_PI = acos(T(-1.0));
647  q = -q;
648  T t1 = acos(r/sqrt(q*q*q));
649  T t2 = 2.0*sqrt(q);
650 
651  lambda_0 = t2*cos(t1/3.0) - b3;
652  lambda_1 = t2*cos((t1 + 2.0*L_PI)/3.0) - b3;
653  lambda_2 = t2*cos((t1 + 4.0*L_PI)/3.0) - b3;
654  }
655 
656  // Assign the diagonals of the result matrix to the
657  // eigenvalues and zero to the rest of the elements.
658 
659  xresult.assign(zero);
660 
661  // Sort into accending order.
662 
663  T tmp[3] = {lambda_0, lambda_1, lambda_2};
664 
665  std::sort(&tmp[0], &tmp[3]);
666 
667  xresult[0][0] = tmp[0];
668  xresult[1][1] = tmp[1];
669  xresult[2][2] = tmp[2];
670  }
671 
672  // Postconditions:
673 
674  ensure(xresult.is_diagonal());
675  ensure(unexecutable("for_all i, 0, 2, xresult[i][i] == real number"));
676 
677  // Exit:
678 
679 }
680 
682 template <typename T>
686 {
687  // Preconditions:
688 
689  // Body:
690 
692  diagonalization(result);
693 
694  // Postconditions:
695 
696  ensure(result.is_diagonal());
697  ensure(unexecutable("for_all i, 0, 2, result[i][i] == real number"));
698 
699  // Exit:
700 
701  return result;
702 }
703 
705 template <typename T>
706 void
709 {
710  // Preconditions:
711 
712  // Body:
713 
714  const T one = T(1);
715  const T zero = T(0);
716 
717  xresult.assign(zero);
718 
719  xresult[0][0] = one;
720  xresult[1][1] = one;
721  xresult[2][2] = one;
722 
723  // Postconditions:
724 
725  ensure(xresult.is_identity());
726 
727  // Exit:
728 }
729 
731 template <typename T>
734 identity() const
735 {
736  // Preconditions:
737 
738  // Body:
739 
741  identity(result);
742 
743  // Postconditions:
744 
745  ensure(result.is_identity());
746 
747  // Exit:
748 
749  return result;
750 }
751 
752 
754 template <typename T>
755 void
758 {
759  // Preconditions:
760 
761  // Body:
762 
763  const symmetric_matrix_3x3<T>& lm = *this;
764 
765  T a00 = lm[0][0];
766  T a01 = lm[0][1];
767  T a02 = lm[0][2];
768  T a10 = a01;
769  T a11 = lm[1][1];
770  T a12 = lm[1][2];
771  T a20 = a02;
772  T a21 = a12;
773  T a22 = lm[2][2];
774 
775  // Cofactors:
776 
777  T c00 = a11*a22 - a12*a21;
778  T c01 = a12*a20 - a10*a22;
779  T c02 = a10*a21 - a11*a20;
780 
781  T determinant = a00*c00 + a01*c01 + a02*c02;
782 
783  if(determinant == 0.0)
784  {
785  post_fatal_error_message("No inverse; determinant is zero.");
786  }
787 
788  T c10 = a02*a21 - a01*a22;
789  T c11 = a00*a22 - a02*a20;
790  //T c12 = a01*a20 - a00*a21;
791 
792  T c20 = a01*a12 - a02*a11;
793  T c21 = a02*a10 - a00*a12;
794  T c22 = a00*a11 - a01*a10;
795 
796  xresult[0][0] = c00/determinant;
797  xresult[0][1] = c10/determinant;
798  xresult[0][2] = c20/determinant;
799 
800  //xresult[1][0] = c01/determinant;
801  xresult[1][1] = c11/determinant;
802  xresult[1][2] = c21/determinant;
803 
804  //xresult[2][0] = c02/determinant;
805  //xresult[2][1] = c12/determinant;
806  xresult[2][2] = c22/determinant;
807 
808  // Postconditions:
809 
810  // Exit:
811 }
812 
814 template <typename T>
817 inverse() const
818 {
819  // Preconditions:
820 
821  // Body:
822 
824  inverse(result);
825 
826  // Postconditions:
827 
828  // Exit:
829 
830  return result;
831 }
832 
834 template <typename T>
835 bool
837 is_diagonal() const
838 {
839  // Preconditions:
840 
841  // Body:
842 
843  const symmetric_matrix_3x3<T>& lm = *this;
844 
845  bool result = (lm[0][1]==0.0) && (lm[0][2]==0.0) && (lm[1][2]==0.0);
846 
847  // Postconditions:
848 
849  // Exit:
850 
851  return result;
852 
853 }
854 
856 template <typename T>
857 bool
859 is_identity() const
860 {
861  // Preconditions:
862 
863  // Body:
864 
865  const symmetric_matrix_3x3<T>& lm = *this;
866 
867  bool result = is_diagonal() &&
868  (lm[0][0]==1.0) && (lm[1][1]==1.0) && (lm[2][2]==1.0);
869 
870  // Postconditions:
871 
872  // Exit:
873 
874  return result;
875 
876 }
877 
879 template <typename T>
880 bool
883 {
884  // Preconditions:
885 
886  // Body:
887 
891 
892  // Since the eigenvalues must all be positive.
893  // So, create the diagonalization and compare all of
894  // to eigenvalues (diagonals) to zero.
895 
896  symmetric_matrix_3x3<T> ldiag = diagonalization();
897 
898  bool result = true;
899  for(int i=0; i<number_of_rows(); ++i)
900  {
901  if(ldiag[i][i] <= 0)
902  {
903  result = false;
904  break;
905  }
906  }
907 
908  // Postconditions:
909 
910  // Exit:
911 
912  return result;
913 }
914 
916 template <typename T>
917 void
919 multiply(const T& xscalar, symmetric_matrix_3x3<T>& xresult) const
920 {
921  // Preconditions:
922 
923  // Body:
924 
925  for(int i=0; i<d(); ++i)
926  {
927  xresult.components[i] = xscalar*components[i];
928  }
929 
930  // Postconditions:
931 
932  //@issue $$ISSUE: We can't make the following comparison because of
933  // floating point roundoff.
934  //ensure_for_all(i, 0, d(), xresult.components[i] == xscalar*components[i]);
935 
936  // Exit:
937 
938 }
939 
941 template <typename T>
944 multiply(const T& xscalar) const
945 {
946  // Preconditions:
947 
948  // Body:
949 
951  multiply(xscalar, result);
952 
953  // Postconditions:
954 
955  // Exit:
956 
957  return result;
958 }
959 
961 template <typename T>
962 void
965  general_matrix_3x1<T>& xresult) const
966 {
967  // Preconditions:
968 
969  // Body:
970 
971  // Multiply [A][B] where [A] = *this & [B] = xother.
972 
973  const symmetric_matrix_3x3<T>& lm = *this;
974 
975  T a00 = lm[0][0];
976  T a01 = lm[0][1];
977  T a02 = lm[0][2];
978  T a10 = a01;
979  T a11 = lm[1][1];
980  T a12 = lm[1][2];
981  T a20 = a02;
982  T a21 = a12;
983  T a22 = lm[2][2];
984 
985  T b00 = xother[0][0];
986  T b10 = xother[1][0];
987  T b20 = xother[2][0];
988 
989  xresult[0][0] = a00*b00 + a01*b10 + a02*b20;
990  xresult[1][0] = a10*b00 + a11*b10 + a12*b20;
991  xresult[2][0] = a20*b00 + a21*b10 + a22*b20;
992 
993  // Postconditions:
994 
995  // Exit:
996 
997 }
998 
1000 template <typename T>
1003 multiply(const general_matrix_3x1<T>& xother) const
1004 {
1005  // Preconditions:
1006 
1007  // Body:
1008 
1009  general_matrix_3x1<T> result;
1010  multiply(xother, result);
1011 
1012  // Postconditions:
1013 
1014  // Exit:
1015 
1016  return result;
1017 }
1018 
1020 template <typename T>
1021 void
1024  general_matrix_3x2<T>& xresult) const
1025 {
1026  // Preconditions:
1027 
1028  // Body:
1029 
1030  // Multiply [A][B] where [A] = *this & [B] = xother.
1031 
1032  const symmetric_matrix_3x3<T>& lm = *this;
1033 
1034  T a00 = lm[0][0];
1035  T a01 = lm[0][1];
1036  T a02 = lm[0][2];
1037  T a10 = a01;
1038  T a11 = lm[1][1];
1039  T a12 = lm[1][2];
1040  T a20 = a02;
1041  T a21 = a12;
1042  T a22 = lm[2][2];
1043 
1044  T b00 = xother[0][0];
1045  T b01 = xother[0][1];
1046 
1047  T b10 = xother[1][0];
1048  T b11 = xother[1][1];
1049 
1050  T b20 = xother[2][0];
1051  T b21 = xother[1][1];
1052 
1053  xresult[0][0] = a00*b00 + a01*b10 + a02*b20;
1054  xresult[0][1] = a00*b01 + a01*b11 + a02*b21;
1055 
1056  xresult[1][0] = a10*b00 + a11*b10 + a12*b20;
1057  xresult[1][1] = a10*b01 + a11*b11 + a12*b21;
1058 
1059  xresult[2][0] = a20*b00 + a21*b10 + a22*b20;
1060  xresult[2][1] = a20*b01 + a21*b11 + a22*b21;
1061 
1062  // Postconditions:
1063 
1064  // Exit:
1065 
1066 }
1067 
1069 template <typename T>
1072 multiply(const general_matrix_3x2<T>& xother) const
1073 {
1074  // Preconditions:
1075 
1076  // Body:
1077 
1078  general_matrix_3x2<T> result;
1079  multiply(xother, result);
1080 
1081  // Postconditions:
1082 
1083  // Exit:
1084 
1085  return result;
1086 }
1087 
1089 template <typename T>
1090 void
1093  general_matrix_3x3<T>& xresult) const
1094 {
1095  // Preconditions:
1096 
1097  // Body:
1098 
1099  // Multiply [A][B] where [A] = *this & [B] = xother.
1100 
1101  const symmetric_matrix_3x3<T>& lm = *this;
1102 
1103  T a00 = lm[0][0];
1104  T a01 = lm[0][1];
1105  T a02 = lm[0][2];
1106  T a10 = a01;
1107  T a11 = lm[1][1];
1108  T a12 = lm[1][2];
1109  T a20 = a02;
1110  T a21 = a12;
1111  T a22 = lm[2][2];
1112 
1113  T b00 = xother[0][0];
1114  T b01 = xother[0][1];
1115  T b02 = xother[0][2];
1116 
1117  T b10 = xother[1][0];
1118  T b11 = xother[1][1];
1119  T b12 = xother[1][2];
1120 
1121  T b20 = xother[2][0];
1122  T b21 = xother[2][1];
1123  T b22 = xother[2][2];
1124 
1125  xresult[0][0] = a00*b00 + a01*b10 + a02*b20;
1126  xresult[0][1] = a00*b01 + a01*b11 + a02*b21;
1127  xresult[0][2] = a00*b02 + a01*b12 + a02*b22;
1128 
1129  xresult[1][0] = a10*b00 + a11*b10 + a12*b20;
1130  xresult[1][1] = a10*b01 + a11*b11 + a12*b21;
1131  xresult[1][2] = a10*b02 + a11*b12 + a12*b22;
1132 
1133  xresult[2][0] = a20*b00 + a21*b10 + a22*b20;
1134  xresult[2][1] = a20*b01 + a21*b11 + a22*b21;
1135  xresult[2][2] = a20*b02 + a21*b12 + a22*b22;
1136 
1137  // Postconditions:
1138 
1139  // Exit:
1140 
1141 }
1142 
1144 template <typename T>
1147 multiply(const general_matrix_3x3<T>& xother) const
1148 {
1149  // Preconditions:
1150 
1151  // Body:
1152 
1153  general_matrix_3x3<T> result;
1154  multiply(xother, result);
1155 
1156  // Postconditions:
1157 
1158  // Exit:
1159 
1160  return result;
1161 }
1162 
1164 template <typename T>
1165 void
1168  general_matrix_3x3<T>& xresult) const
1169 {
1170  // Preconditions:
1171 
1172  // Body:
1173 
1174  // Multiply [A][B] where [A] = *this & [B] = xother.
1175 
1176  const symmetric_matrix_3x3<T>& lm = *this;
1177 
1178  T a00 = lm[0][0];
1179  T a01 = lm[0][1];
1180  T a02 = lm[0][2];
1181  T a10 = a01;
1182  T a11 = lm[1][1];
1183  T a12 = lm[1][2];
1184  T a20 = a02;
1185  T a21 = a12;
1186  T a22 = lm[2][2];
1187 
1188  T b00 = xother[0][0];
1189  T b01 = xother[0][1];
1190  T b02 = xother[0][2];
1191  T b10 = b01;
1192  T b11 = xother[1][1];
1193  T b12 = xother[1][2];
1194  T b20 = b02;
1195  T b21 = b12;
1196  T b22 = xother[2][2];
1197 
1198  xresult[0][0] = a00*b00 + a01*b10 + a02*b20;
1199  xresult[0][1] = a00*b01 + a01*b11 + a02*b21;
1200  xresult[0][2] = a00*b02 + a01*b12 + a02*b22;
1201 
1202  xresult[1][0] = a10*b00 + a11*b10 + a12*b20;
1203  xresult[1][1] = a10*b01 + a11*b11 + a12*b21;
1204  xresult[1][2] = a10*b02 + a11*b12 + a12*b22;
1205 
1206  xresult[2][0] = a20*b00 + a21*b10 + a22*b20;
1207  xresult[2][1] = a20*b01 + a21*b11 + a22*b21;
1208  xresult[2][2] = a20*b02 + a21*b12 + a22*b22;
1209 
1210  // Postconditions:
1211 
1212  // Exit:
1213 
1214 }
1215 
1217 template <typename T>
1220 multiply(const symmetric_matrix_3x3<T>& xother) const
1221 {
1222  // Preconditions:
1223 
1224  // Body:
1225 
1226  general_matrix_3x3<T> result;
1227  multiply(xother, result);
1228 
1229  // Postconditions:
1230 
1231  // Exit:
1232 
1233  return result;
1234 }
1235 
1237 template <typename T>
1238 void
1240 trace(T& xresult) const
1241 {
1242  // Preconditions:
1243 
1244  // Body:
1245 
1246  const symmetric_matrix_3x3<T>& lm = *this;
1247 
1248  // Unroll the loop for efficiency.
1249 
1250  xresult = lm[0][0] + lm[1][1] + lm[2][2];
1251 
1252  // Postconditions:
1253 
1254  // Exit:
1255 }
1256 
1258 template <typename T>
1259 T
1261 trace() const
1262 {
1263  // Preconditions:
1264 
1265  // Body:
1266 
1267  T result;
1268 
1269  trace(result);
1270 
1271  // Postconditions:
1272 
1273  // Exit:
1274 
1275  return result;
1276 }
1277 
1279 template <typename T>
1280 void
1283 {
1284  // Preconditions:
1285 
1286  // Body:
1287 
1288  // The transpose of a symmetric matrix is the same as the
1289  // original matrix. But, we'll return it if you really want
1290  // it.
1291 
1292  int ld = d();
1293 
1294  for(int i=0; i<ld; ++i)
1295  {
1296  xresult.components[i] = components[i];
1297  }
1298 
1299  // Postconditions:
1300 
1301  // Exit:
1302 
1303 }
1304 
1306 template <typename T>
1309 transpose() const
1310 {
1311  // Preconditions:
1312 
1313  // Body:
1314 
1315  symmetric_matrix_3x3<T> result;
1316  transpose(result);
1317 
1318  // Postconditions:
1319 
1320  // Exit:
1321 
1322  return result;
1323 }
1324 
1325 // =============================================================================
1326 // NON-MEMBER FUNCTIONS
1327 // =============================================================================
1328 
1329 #ifndef DOXYGEN_SKIP_IMPLEMENTATIONS
1330 
1332 template <typename T>
1333 std::ostream& operator<<(std::ostream& xos, const symmetric_matrix_3x3<T>& xm)
1334 {
1335  // Preconditions:
1336 
1337  // Body:
1338 
1339  // Here we will actually print the below the diagonal
1340  // even though we don't store them.
1341 
1342  int nrows = xm.number_of_rows();
1343  int ncols = xm.number_of_columns();
1344 
1345  for(int i=0; i<nrows; ++i)
1346  {
1347  for(int j=0; j<ncols; ++j)
1348  {
1349  double v;
1350  if(i <= j)
1351  v = xm[i][j];
1352  else
1353  v = xm[j][i];
1354 
1355  xos << " " << v;
1356  }
1357  xos << std::endl;
1358  }
1359 
1360  // Postconditions:
1361 
1362  // Exit:
1363 
1364  return xos;
1365 }
1366 
1367 #endif // ifndef DOXYGEN_SKIP_IMPLEMENTATIONS
1368 
1370 template <typename T>
1371 void
1373  general_matrix_3x3<T>& xeigenvectors,
1374  symmetric_matrix_3x3<T>& xdiagonal)
1375 {
1376  //$$TODO: Provide a better explanation.
1377 
1378  // Determine the eigenvalues and eigenvectors of a real 3x3 symmetric matrix.
1379  // Uses the cyclic Jacobi method.
1380 
1381  // Preconditions:
1382 
1383  // Body:
1384 
1385  T eigenvalues[3];
1386  jacobi_transformation(xm, xeigenvectors, eigenvalues);
1387 
1388  for(int i=0; i<3; ++i)
1389  {
1390  xdiagonal[i][i] = eigenvalues[i];
1391  }
1392 
1393  // Postconditions:
1394 
1395  // Body:
1396 
1397 }
1398 
1400 template <typename T>
1401 void
1403  general_matrix_3x3<T>& xeigenvectors,
1404  T xeigenvalues[3])
1405 {
1406  //$$TODO: Provide a better explanation.
1407 
1408  // Determine the eigenvalues and eigenvectors of a real 3x3 symmetric matrix.
1409  // Uses the cyclic Jacobi method. This code is basically a templatized version
1410  // of the code in "Numerical Recipes, 11.1".
1411 
1412  // Preconditions:
1413 
1414  // Body:
1415 
1416  static const int n = 3;
1417 
1418  static const int max_iterations = 50;
1419  static const T zero = 0.0;
1420 
1421  // Copy the original symmetric matrix into a second matrix
1422  // to be used for working storage.
1423 
1424  symmetric_matrix_3x3<T> lm = xm;
1425 
1426  //cout << "lm:" << std::endl << lm << std::endl;
1427 
1428  //int number_of_rotations = 0;
1429 
1430  // Initialize xeigenvectors to the identity matrix.
1431 
1432  xeigenvectors = xeigenvectors.identity();
1433 
1434  //cout << "xeigenvectors:" << std::endl << xeigenvectors << std::endl;
1435 
1436  // Initialize b and xeigenvalues to the diagonal of lm;
1437 
1438  T b[3];
1439  T z[3];
1440  for(int i=0; i<n; ++i)
1441  {
1442  T lmii = lm[i][i];
1443  xeigenvalues[i] = lmii;
1444  b[i] = lmii;
1445  z[i] = 0.0;
1446  }
1447 
1448  int i;
1449  for(i=0; i<max_iterations; ++i)
1450  {
1451  // Sum the off diagonals.
1452 
1453  T sum = fabs(lm[0][1]) + fabs(lm[0][2]) + fabs(lm[1][2]);
1454 
1455  //cout << "number_of_rotations = " << number_of_rotations;
1456  //cout << " sum = " << sum << std::endl;
1457 
1458  // Test for convergence.
1459 
1460  if(sum == zero)
1461  {
1462  // The iteration has converged; so break out of the loop;
1463 
1464  break;
1465  }
1466 
1467  T tresh = (i>=3) ? 0.0 : (0.2*sum/(n*n));
1468 
1469  for(int ip=0; ip<n-1; ++ip)
1470  {
1471  for(int iq=ip+1; iq<n; ++iq)
1472  {
1473  T g = 100.0*fabs(lm[ip][iq]);
1474 
1475  // After 4 sweeps, skip the rotation if the off-diagonal element is small.
1476 
1477  if(i > 3
1478  && (fabs(xeigenvalues[ip])+g) == fabs(xeigenvalues[ip])
1479  && (fabs(xeigenvalues[iq])+g) == fabs(xeigenvalues[iq]))
1480  {
1481  lm[ip][iq] = 0.0;
1482  }
1483  else if(fabs(lm[ip][iq]) > tresh)
1484  {
1485  T t;
1486  T h = xeigenvalues[iq] - xeigenvalues[ip];
1487  if((fabs(h)+g) == fabs(h))
1488  {
1489  t = lm[ip][iq]/h;
1490  }
1491  else
1492  {
1493  T theta = 0.5*h/(lm[ip][iq]);
1494  t = 1.0/(fabs(theta) + sqrt(1.0+theta*theta));
1495  if(theta < 0.0) t = -t;
1496  }
1497 
1498  T cos = 1.0/sqrt(1.0 + t*t);
1499  T sin = t*cos;
1500  T tau = sin/(1.0 + cos);
1501  h = t*lm[ip][iq];
1502 
1503  z[ip] -= h;
1504  z[iq] += h;
1505  xeigenvalues[ip] -= h;
1506  xeigenvalues[iq] += h;
1507 
1508  lm[ip][iq] = 0.0;
1509 
1510  for(int j=0; j<ip; ++j)
1511  {
1512  g = lm[j][ip];
1513  h = lm[j][iq];
1514  lm[j][ip] = g - (sin * (h + (g * tau)));
1515  lm[j][iq] = h + (sin * (g - (h * tau)));
1516  }
1517 
1518  for(int j=ip+1; j<iq; ++j)
1519  {
1520  g = lm[ip][j];
1521  h = lm[j][iq];
1522  lm[ip][j] = g - (sin * (h + (g * tau)));
1523  lm[j][iq] = h + (sin * (g - (h * tau)));
1524  }
1525 
1526  for(int j=iq+1; j<n; ++j)
1527  {
1528  g = lm[ip][j];
1529  h = lm[iq][j];
1530  lm[ip][j] = g - (sin * (h + (g * tau)));
1531  lm[iq][j] = h + (sin * (g - (h * tau)));
1532  }
1533 
1534  for(int j=0; j<n; ++j)
1535  {
1536  g = xeigenvectors[j][ip];
1537  h = xeigenvectors[j][iq];
1538  xeigenvectors[j][ip] = g - (sin * (h + (g * tau)));
1539  xeigenvectors[j][iq] = h + (sin * (g - (h * tau)));
1540  }
1541 
1542  //++number_of_rotations;
1543  }
1544  }
1545  }
1546 
1547  // Update the eigenvalues and reinitialize z.
1548 
1549  for(int ip=0; ip<3; ++ip)
1550  {
1551  b[ip] += z[ip];
1552  xeigenvalues[ip] = b[ip];
1553  z[ip] = 0.0;
1554  }
1555 
1556  }
1557 
1558  if(i >= max_iterations)
1559  {
1560  post_fatal_error_message("Too many Jacobi iterations");
1561  }
1562 
1563  // Sort in ascending value of eigenvalues.
1564 
1565  sort_eigenvalues(xeigenvectors, xeigenvalues);
1566 
1567  //$$TODO: Transpose so eigenvectors are the rows?.
1568 
1569  // Postconditions:
1570 
1571  // Exit:
1572 
1573 
1574 
1575 }
1576 
1578 template <typename T>
1579 void
1581  T xeigenvalues[3])
1582 {
1583  // Sort the eigenvalues and eigenvectors into ascending order.
1584  // At this point the eigenvectors are stored by columns.
1585 
1586  // Preconditions:
1587 
1588  // Body;
1589 
1590  static const int n = 3;
1591 
1592  for(int i=0; i<n; ++i)
1593  {
1594  T ev_min = xeigenvalues[i];
1595  int k = i;
1596 
1597  int j;
1598  for(j=i+1; j<n; ++j)
1599  {
1600  if(ev_min > xeigenvalues[j])
1601  {
1602  ev_min = xeigenvalues[j];
1603  k = j;
1604  }
1605  }
1606 
1607  if(k != j)
1608  {
1609  // Swap the eigenvalues.
1610 
1611  xeigenvalues[k] = xeigenvalues[i];
1612  xeigenvalues[i] = ev_min;
1613 
1614  // Swap the eigenvectors.
1615 
1616  for(int j=0; j<n; ++j)
1617  {
1618  T temp = xeigenvectors[j][i];
1619  xeigenvectors[j][i] = xeigenvectors[j][k];
1620  xeigenvectors[j][k] = temp;
1621  }
1622  }
1623  }
1624 
1625  // Postconditions:
1626 
1627  // Exit:
1628 
1629 }
1630 
1631 //==============================================================================
1632 //==============================================================================
1633 
1634 } // namespace fiber_bundle
1635 
1636 #endif // SYMMETRIC_MATRIX_3X3_IMPL_H
1637 
SHEAF_DLL_SPEC void sqrt(const sec_at0 &x0, sec_at0 &xresult, bool xauto_access)
Compute sqrt of x0 (sqrt(x0)) (pre-allocated version).
Definition: sec_at0.cc:1556
void jacobi_transformation(const symmetric_matrix_3x3< T > &xm, general_matrix_3x3< T > &xeigenvectors, T xeigenvalues[3])
Determine the eigenvectors and eigenvalues of a real symmetric matrix xm.
bool is_identity() const
True if this is an identity matrix.
Row dofs type for class st2_e3.
Definition: st2_e3.h:53
T trace() const
The trace of the matrix (auto-allocated).
static int d()
Dimension of the underlying elements.
General matrix with 3 rows and 2 columns.
static int number_of_rows()
The number of rows.
void sort_eigenvalues(general_matrix_3x3< T > &xeigenvectors, T xeigenvalues[3])
Utility function to sort the eigenvalues into ascending order. Called from jacobi_transformation.
void assign(const T &xscalar)
Assign all elements of this matrix to the value xvalue.
int row_index(int xrow) const
Index for row xrow in the linear storage array.
T * operator[](int xrow)
Pointer to the first element in row xrow of this matrix. Facilitates accessing elements via matrix[i]...
void trace(const S0 &x0, SR &xresult, bool xauto_access)
Definition: sec_st2.impl.h:99
general_matrix_3x1< T > column(int xcolumn) const
A 3x1 matrix containing the elements or column xcolumn.
symmetric_matrix_3x3< T > identity() const
The identity matrix (auto-allocated).
General matrix with 3 rows and 1 column.
Row dofs type for class met_e3.
Definition: met_e3.h:51
T components[6]
Linear storage array.
bool is_positive_definite() const
True if this matrix is positive definite.
SHEAF_DLL_SPEC void fabs(const sec_at0 &x0, sec_at0 &xresult, bool xauto_access)
Compute fabs of x0 (fabs(x0)) (pre-allocated version).
Definition: sec_at0.cc:1331
symmetric_matrix_3x3< T > inverse() const
The inverse of the matrix (auto-allocated).
T components[3]
Linear storage array.
symmetric_matrix_3x3< T > adjoint() const
The adjoint of the matrix (auto-allocated).
void identity(general_matrix_3x3< T > &xresult) const
The identity matrix (pre-allocated).
SHEAF_DLL_SPEC void cos(const sec_at0 &x0, sec_at0 &xresult, bool xauto_access)
Compute cos of x0 (cos(x0)) (pre-allocated version).
Definition: sec_at0.cc:1270
void determinant(const S0 &x0, SR &xresult, bool xauto_access)
Definition: sec_st2.impl.h:131
symmetric_matrix_3x3< T > transpose() const
The transpose of the matrix (auto-allocated).
bool is_diagonal() const
True if this matrix is diagonal.
SHEAF_DLL_SPEC void acos(const sec_at0 &x0, sec_at0 &xresult, bool xauto_access)
Compute acos of x0 (acos(x0)) (pre-allocated version).
Definition: sec_at0.cc:1154
static int number_of_columns()
The number of columns.
General matrix with 3 rows and 3 columns.
General matrix with 1 row and 3 columns.
Namespace for the sheaves component of the sheaf system.
general_matrix_1x3< T > row(int xrow) const
A 1x3 matrix containing the elements or row xrow.
void multiply(const T &xscalar, symmetric_matrix_3x3< T > &xresult) const
This matrix multiplied by a scalar (pre-allocated).
T determinant() const
The determinant of the matrix (auto-allocated).
T components[3]
Linear storage array.
SHEAF_DLL_SPEC void multiply(const vd &x0, const vd_value_type &x1, vd &xresult, bool xauto_access)
Vector x0 multiplied by scalar x1 (pre-allocated version for persistent types).
Definition: vd.cc:1924
Namespace for the fiber_bundles component of the sheaf system.
SHEAF_DLL_SPEC void pow(const sec_at0 &x0, const vd_value_type &xexponent, sec_at0 &xresult, bool xauto_access)
Compute x0 to power xexponent (pow(x0, xexponent)) (pre-allocated version).
Definition: sec_at0.cc:1495
SHEAF_DLL_SPEC void inverse(const gl2_lite &xlite, gl2_lite &xresult)
Inverse (pre-allocated version for volatile type).
Definition: gl2.cc:1484
SHEAF_DLL_SPEC void sin(const sec_at0 &x0, sec_at0 &xresult, bool xauto_access)
Compute sin of x0 (sin(x0)) (pre-allocated version).
Definition: sec_at0.cc:1516
symmetric_matrix_3x3< T > diagonalization() const
The diagonalization of the matrix (auto-allocated).
A tensor of degree 2 over an abstract vector space (persistent version).
Definition: t2.h:226
Symmetric matrix with 3 rows and 3 columns.