valib
Vortex Analysis LIBrary
Loading...
Searching...
No Matches
linalg3.h
Go to the documentation of this file.
1
4
5#ifndef VA_LINALG3_H
6#define VA_LINALG3_H
7
8#include "common_defs.h"
9
10/***************************************************************************/
14
15/***************************************************************************/
20VA_DEVICE_FUN VA_REAL valib_sign(VA_REAL a, VA_REAL b)
21{
22 return (b < (VA_REAL) 0.) ? -fabs(a) : fabs(a);
23}
24
25/***************************************************************************/
29VA_DEVICE_FUN VA_COMPLEX valib_makec(VA_REAL a, VA_REAL b)
30{
31#if defined(VA_CUDA)
32 #if defined(VA_USE_DOUBLE_PRECISION)
33 return make_cuDoubleComplex(a, b);
34 #else
35 return make_cuFloatComplex(a, b);
36 #endif
37#elif defined(VA_HIP)
38 #if defined(VA_USE_DOUBLE_PRECISION)
39 return make_hipDoubleComplex(a, b);
40 #else
41 return make_hipFloatComplex(a, b);
42 #endif
43#else
44 return a + I*b;
45#endif
46}
47
48/***************************************************************************/
52VA_DEVICE_FUN VA_REAL valib_creal(VA_COMPLEX a)
53{
54#if defined(VA_CUDA)
55 #if defined(VA_USE_DOUBLE_PRECISION)
56 return cuCreal(a);
57 #else
58 return cuCrealf(a);
59 #endif
60#elif defined(VA_HIP)
61 #if defined(VA_USE_DOUBLE_PRECISION)
62 return hipCreal(a);
63 #else
64 return hipCrealf(a);
65 #endif
66#else
67 return creal(a);
68#endif
69}
70
71/***************************************************************************/
75VA_DEVICE_FUN VA_REAL valib_cimag(VA_COMPLEX a)
76{
77#if defined(VA_CUDA)
78 #if defined(VA_USE_DOUBLE_PRECISION)
79 return cuCimag(a);
80 #else
81 return cuCimagf(a);
82 #endif
83#elif defined(VA_HIP)
84 #if defined(VA_USE_DOUBLE_PRECISION)
85 return hipCimag(a);
86 #else
87 return hipCimagf(a);
88 #endif
89#else
90 return cimag(a);
91#endif
92}
93
94/***************************************************************************/
98VA_DEVICE_FUN VA_REAL valib_cabs(VA_COMPLEX a)
99{
100 VA_REAL ar = valib_creal(a);
101 VA_REAL ai = valib_cimag(a);
102 return sqrt(ar*ar + ai*ai);
103}
104
105/***************************************************************************/
109VA_DEVICE_FUN VA_COMPLEX valib_cadd(VA_COMPLEX a, VA_COMPLEX b)
110{
111 return valib_makec(valib_creal(a) + valib_creal(b),
112 valib_cimag(a) + valib_cimag(b));
113}
114/***************************************************************************/
118VA_DEVICE_FUN VA_COMPLEX valib_cmultiply(VA_COMPLEX a, VA_COMPLEX b)
119{
120 VA_REAL ar = valib_creal(a);
121 VA_REAL ai = valib_cimag(a);
122 VA_REAL br = valib_creal(b);
123 VA_REAL bi = valib_cimag(b);
124
125 VA_REAL cr = ar*br - ai*bi;
126 VA_REAL ci = ar*bi + ai*br;
127 return valib_makec(cr, ci);
128}
129
130/***************************************************************************/
134VA_DEVICE_FUN VA_REAL valib_cubic_root(VA_REAL x)
135{
136 return valib_sign(pow(fabs(x), (VA_REAL) 1.0/3.0), x);
137}
138
139/***************************************************************************/
144VA_DEVICE_FUN VA_REAL valib_max(VA_REAL a, VA_REAL b)
145{
146 return (a > b) ? a : b;
147}
148
149/***************************************************************************/
154VA_DEVICE_FUN VA_REAL valib_min(VA_REAL a, VA_REAL b)
155{
156 return (a < b) ? a : b;
157}
158
159/***************************************************************************/
163VA_DEVICE_FUN VA_REAL valib_square(VA_REAL a)
164{
165 return (a * a);
166}
167
168/***************************************************************************/
172VA_DEVICE_FUN void valib_swap_values(VA_REAL *a, VA_REAL *b)
173{
174 VA_REAL buf;
175 buf = *a;
176 *a = *b;
177 *b = buf;
178}
179
180/***************************************************************************/
188VA_DEVICE_FUN void valib_solve_cubic_equation(VA_REAL a, VA_REAL b,
189 VA_REAL c, VA_REAL d,
190 VA_REAL *x1,
191 VA_COMPLEX *x2,
192 VA_COMPLEX *x3,
193 int *info)
194{
195 int debug = 0;
196
197 VA_REAL q = pow(b/(3.*a), (VA_REAL) 3.) - (b*c)/(6.*a*a) + d/(2.*a);
198 VA_REAL p = (3*a*c - b*b) / (9*a*a);
199
200 VA_REAL delta = p*p*p + q*q;
201
202 if (debug) {
203 printf("q: %lf \n", q);
204 printf("p: %lf \n", p);
205 printf("delta: %lf \n", delta);
206 }
207
208 if (delta >= 0.) {
209 if (debug) {
210 printf("This is a good case with two complex roots.\n");
211 }
212 }
213 else {
214 if (debug) {
215 printf("Discriminant is negative, this is not a good way to get roots.\n");
216 }
217 *info = -1;
218 return;
219 }
220
221 VA_REAL sr = sqrt(delta);
222
223 if (debug) {
224 printf("sr: %lf \n", sr);
225 }
226
227 VA_REAL mqpsr = -q + sr;
228 VA_REAL mqmsr = -q - sr;
229
230 if (debug) {
231 printf("mqpsr: %lf \n", mqpsr);
232 printf("mqmsr: %lf \n", mqmsr);
233 }
234
235 VA_REAL u = valib_cubic_root(mqpsr);
236 VA_REAL v = valib_cubic_root(mqmsr);
237
238 // Remove this check as it makes the functions fail even for some cases
239 // where the results are OK.
240 //if (fabs(u*v + p) > 1.e-3) {
241 // if (debug) {
242 // printf("Check of uv = -p failed, check = %lf.", fabs(u*v + p));
243 // }
244 // *info = -2;
245 // return;
246 //}
247
248 VA_COMPLEX e1 = valib_makec(-0.5, sqrt(3.)/2.);
249 VA_COMPLEX e2 = valib_makec(-0.5, -sqrt(3.)/2.);
250
251 VA_COMPLEX uc = valib_makec(u, 0);
252 VA_COMPLEX vc = valib_makec(v, 0);
253
254 VA_COMPLEX y2 = valib_cadd(valib_cmultiply(e1,uc), valib_cmultiply(e2,vc));
255 VA_COMPLEX y3 = valib_cadd(valib_cmultiply(e2,uc), valib_cmultiply(e1,vc));
256
257 VA_REAL shift = -b/(3.*a);
258 VA_COMPLEX shiftc = valib_makec(shift, 0);
259
260 *x1 = u + v + shift; // the real root
261 *x2 = valib_cadd(y2, shiftc); // the complex roots
262 *x3 = valib_cadd(y3, shiftc);
263
264 if (debug) {
265 VA_COMPLEX ac = valib_makec(a, 0.);
266 VA_COMPLEX bc = valib_makec(b, 0.);
267 VA_COMPLEX cc = valib_makec(c, 0.);
268 VA_COMPLEX dc = valib_makec(d, 0.);
269
270 // check that ax^3 + bx^2 + cx + d is close to zero for all the roots
271 VA_REAL check1 = a*(*x1)*(*x1)*(*x1) + b*(*x1)*(*x1) + c*(*x1) + d;
272 VA_COMPLEX check2 = valib_cadd(valib_cmultiply(ac,valib_cmultiply(valib_cmultiply((*x2),(*x2)),(*x2))), valib_cadd(valib_cmultiply(bc,valib_cmultiply((*x2),(*x2))), valib_cadd(valib_cmultiply(cc,(*x2)), dc)));
273 VA_COMPLEX check3 = valib_cadd(valib_cmultiply(ac,valib_cmultiply(valib_cmultiply((*x3),(*x3)),(*x3))), valib_cadd(valib_cmultiply(bc,valib_cmultiply((*x3),(*x3))), valib_cadd(valib_cmultiply(cc,(*x3)), dc)));
274
275 if (fabs(check1) > 1.e-5) {
276 printf("Check of x1 failed.");
277 }
278 if (valib_cabs(check2) > 1.e-5) {
279 printf("Check of x2 failed.");
280 }
281 if (valib_cabs(check3) > 1.e-5) {
282 printf("Check of x3 failed.");
283 }
284 }
285
286 // finished correctly
287 *info = 0;
288}
289
290/***************************************************************************/
296
297/***************************************************************************/
301VA_DEVICE_FUN void valib_vec_zero3(VA_REAL *v)
302{
303 int i;
304 for (i = 0; i < 3; i++) {
305 v[i] = 0.;
306 }
307}
308
309/***************************************************************************/
313VA_DEVICE_FUN VA_REAL valib_scalar_prod3(VA_REAL *v1, VA_REAL *v2)
314{
315 VA_REAL result = (VA_REAL) 0.;
316 int i;
317 for (i = 0; i < 3; i++)
318 {
319 result = result + v1[i]*v2[i];
320 }
321 return result;
322}
323
324/***************************************************************************/
328VA_DEVICE_FUN void valib_cross_prod3(VA_REAL *v1, VA_REAL *v2, VA_REAL *v3)
329{
330 v3[0] = v1[1] * v2[2] - v1[2] * v2[1];
331 v3[1] = v1[2] * v2[0] - v1[0] * v2[2];
332 v3[2] = v1[0] * v2[1] - v1[1] * v2[0];
333}
334
335/***************************************************************************/
341
342/***************************************************************************/
346VA_DEVICE_FUN void valib_mat_zero3(VA_REAL *A)
347{
348 int i, j;
349 for (j = 0; j < 3; j++) {
350 for (i = 0; i < 3; i++) {
351 A[j*3+i] = 0.;
352 }
353 }
354}
355
356/***************************************************************************/
360VA_DEVICE_FUN void valib_mat_copy3(VA_REAL *A, VA_REAL *B)
361{
362 int i, j;
363 for (j = 0; j < 3; j++) {
364 for (i = 0; i < 3; i++) {
365 B[j*3+i] = A[j*3+i];
366 }
367 }
368}
369
370/***************************************************************************/
374VA_DEVICE_FUN void valib_norm_frobenius3(VA_REAL *A, VA_REAL *norm)
375{
376 *norm = 0.0;
377 int i, j;
378 for (j = 0; j < 3; j++) {
379 for (i = 0; i < 3; i++) {
380 *norm = *norm + A[j*3+i]*A[j*3+i];
381 }
382 }
383 *norm = sqrt(*norm);
384}
385
386/***************************************************************************/
390VA_DEVICE_FUN void valib_trace3(VA_REAL *A, VA_REAL *tr3)
391{
392 *tr3 = A[0] + A[4] + A[8];
393}
394
395/***************************************************************************/
399VA_DEVICE_FUN void valib_second_invariant3(VA_REAL *A,
400 VA_REAL *second_invariant)
401{
402 *second_invariant = ( A[0]*A[4] + A[4]*A[8] + A[0]*A[8] )
403 - ( A[1]*A[3] + A[2]*A[6] + A[5]*A[7] );
404}
405
406/***************************************************************************/
410VA_DEVICE_FUN void valib_determinant3(VA_REAL *A, VA_REAL *det)
411{
412 *det = A[0] * A[4] * A[8]
413 + A[3] * A[7] * A[2]
414 + A[6] * A[1] * A[5]
415 - A[0] * A[7] * A[5]
416 - A[3] * A[1] * A[8]
417 - A[6] * A[4] * A[2];
418}
419
420/***************************************************************************/
424VA_DEVICE_FUN void valib_transpose3(VA_REAL *A)
425{
426 valib_swap_values(&A[1], &A[3]);
427 valib_swap_values(&A[2], &A[6]);
428 valib_swap_values(&A[5], &A[7]);
429}
430
431/***************************************************************************/
437VA_DEVICE_FUN void valib_sym_antisym3(VA_REAL *A)
438{
439 VA_REAL ud, ld;
440
441 int i, j;
442 for (i = 0; i < 3; i++) {
443 for (j = i+1; j < 3; j++) {
444 ud = A[i + j*3];
445 ld = A[j + i*3];
446
447 A[i + j*3] = (VA_REAL) 0.5 * (ud + ld);
448 A[j + i*3] = (VA_REAL) 0.5 * (ld - ud);
449 }
450 }
451}
452
453/***************************************************************************/
461VA_DEVICE_FUN void valib_deviatorise3(VA_REAL *A)
462{
463 // get trace(A)
464 VA_REAL trace;
465 valib_trace3(A, &trace);
466
467 // subtract a multiple of the third of the trace from the diagonal
468 A[0] = A[0] - (VA_REAL) (1./3.) * trace;
469 A[4] = A[4] - (VA_REAL) (1./3.) * trace;
470 A[8] = A[8] - (VA_REAL) (1./3.) * trace;
471}
472
473/***************************************************************************/
478VA_DEVICE_FUN void valib_matvec3_prod(int trans_a, VA_REAL *A,
479 VA_REAL *x, VA_REAL *y)
480{
481 int i, j;
482 for (i = 0; i < 3; i++) {
483 y[i] = 0.0;
484 for (j = 0; j < 3; j++) {
485 if (trans_a == 0) {
486 y[i] = y[i] + A[j*3+i]*x[j];
487 }
488 else {
489 y[i] = y[i] + A[i*3+j]*x[j];
490 }
491 }
492 }
493}
494
495/***************************************************************************/
500VA_DEVICE_FUN void valib_rank1_update3(VA_REAL alpha,
501 VA_REAL *x, VA_REAL *y,
502 VA_REAL *A)
503{
504 int ind;
505 VA_REAL tmp;
506
507 ind = 0;
508 int i, j;
509 for (j = 0; j < 3; j++) {
510 tmp = alpha * y[j];
511 for (i = 0; i < 3; i++) {
512 A[ind] = A[ind] + x[i]*tmp;
513 ind = ind + 1;
514 }
515 }
516}
517
518/***************************************************************************/
523VA_DEVICE_FUN void valib_tatt3(VA_REAL *A, VA_REAL *T, VA_REAL *TATT)
524{
525 unsigned i, j, ind;
526
527 // zero TATT
528 valib_mat_zero3(TATT);
529
530 // perform series of rank one updates
531 ind = 0;
532 for (i = 0; i < 3; i++) {
533 for (j = 0; j < 3; j++) {
534 // call rank one update on each element of A
535 valib_rank1_update3(A[ind], &T[j*3], &T[i*3], TATT);
536 ind = ind + 1;
537 }
538 }
539}
540
541/***************************************************************************/
546VA_DEVICE_FUN void valib_matmat3_prod(int trans_a, int trans_b,
547 VA_REAL *A, VA_REAL *B, VA_REAL *C)
548{
549 int i, j, k;
550 for (i = 0; i < 3; i++) {
551 for (j = 0; j < 3; j++) {
552 for (k = 0; k < 3; k++) {
553 if (trans_a == 0 && trans_b == 0) {
554 C[j*3+i] = C[j*3+i] + A[k*3+i] * B[j*3+k];
555 }
556 else if (trans_a != 0 && trans_b == 0) {
557 C[j*3+i] = C[j*3+i] + A[i*3+k] * B[j*3+k];
558 }
559 else if (trans_a == 0 && trans_b != 0) {
560 C[j*3+i] = C[j*3+i] + A[k*3+i] * B[k*3+j];
561 }
562 else {//(trans_a != 0 && trans_b != 0)
563 C[j*3+i] = C[j*3+i] + A[i*3+k] * B[k*3+j];
564 }
565 }
566 }
567 }
568}
569
570/***************************************************************************/
575VA_DEVICE_FUN void valib_ttat3(VA_REAL *A, VA_REAL *T, VA_REAL *TTAT)
576{
577 // zero TATT
578 valib_mat_zero3(TTAT);
579
580 // first multiply A*T
581 VA_REAL AT[3*3];
582 valib_mat_zero3(AT);
583 valib_matmat3_prod(0, 0, A, T, AT);
584
585 // now premultiply T^T * (A*T)
586 valib_matmat3_prod(1, 0, T, AT, TTAT);
587}
588
589/***************************************************************************/
593VA_DEVICE_FUN void valib_gram_schmidt3(VA_REAL *Q)
594{
595 VA_REAL factor;
596
597 // column-wise process
598 int i, j, k;
599 for (j = 0; j < 3; j++) {
600 for (i = 0; i < j; i++) {
601 // compute the scalar product with previous columns
602 factor = valib_scalar_prod3(&Q[j*3], &Q[i*3]);
603
604 // subtract the projected vector
605 for (k = 0; k < 3; k++) {
606 Q[j*3+k] = Q[j*3+k] - factor * Q[i*3+k];
607 }
608 }
609
610 // normalize the column
611 factor = valib_scalar_prod3(&Q[j*3], &Q[j*3]);
612 VA_REAL numerical_zero = 1.e-7;
613 if (factor > numerical_zero) {
614 // normalize
615 for (k = 0; k < 3; k++) {
616 Q[j*3+k] = Q[j*3+k] / sqrt(factor);
617 }
618 }
619 }
620}
621
622/***************************************************************************/
626VA_DEVICE_FUN void valib_eigenvalues_sym3(VA_REAL *A, VA_REAL *eigval)
627{
628 // compute first invariant
629 VA_REAL Idev;
630 valib_trace3(A, &Idev);
631 VA_REAL IdevMod = Idev / 3.;
632
633 // compute deviator
634 VA_REAL dev[9];
635 valib_mat_copy3(A, dev);
636 dev[0] = dev[0] - IdevMod;
637 dev[4] = dev[4] - IdevMod;
638 dev[8] = dev[8] - IdevMod;
639
640 // compute second invariant of deviator
641 VA_REAL IIdev;
642 valib_second_invariant3(dev, &IIdev);
643 VA_REAL IIdevMod = -IIdev / 3.;
644
645 // compute half the determinant (third invariant) of deviator
646 VA_REAL IIIdev;
647 valib_determinant3(dev, &IIIdev);
648 VA_REAL IIIdevMod = 0.5 * IIIdev;
649
650 // Compute the phi angle, use increased precision to avoid overflow.
651 double dIIdevMod = IIdevMod;
652 double dIIIdevMod = IIIdevMod;
653 double daux = pow(dIIdevMod,3) - pow(dIIIdevMod,2);
654 // assure nonnegativity
655 if (daux < 0.) {
656 daux = 0.;
657 }
658 VA_REAL phi;
659 phi = atan2( sqrt(daux), dIIIdevMod ) / 3.;
660 // readjust to the right quadrant
661 if (phi < 0.) phi += VA_PI / 3.;
662
663 // eigenvalues
664 eigval[0] = IdevMod + 2.*sqrt(IIdevMod) * cos(phi);
665 eigval[1] = IdevMod - sqrt(IIdevMod) * (cos(phi) + sqrt(3.) * sin(phi));
666 eigval[2] = IdevMod - sqrt(IIdevMod) * (cos(phi) - sqrt(3.) * sin(phi));
667
668 // sort eigenvalues
669 if (eigval[0] > eigval[1] ) valib_swap_values( &eigval[0], &eigval[1] );
670 if (eigval[1] > eigval[2] ) valib_swap_values( &eigval[1], &eigval[2] );
671 if (eigval[0] > eigval[1] ) valib_swap_values( &eigval[0], &eigval[1] );
672
673 return;
674}
675
676/***************************************************************************/
682VA_DEVICE_FUN int valib_find_pivot3(VA_REAL *A, int jcol, int start)
683{
684 int debug = 0;
685 int ipiv = start;
686 for (int i = start+1; i<3; i++) {
687 if (fabs(A[i+jcol*3]) > fabs(A[ipiv+jcol*3]))
688 ipiv = i;
689 }
690
691 VA_REAL numerical_zero = 1.e-5;
692 if (fabs(A[ipiv+jcol*3]) < numerical_zero) {
693 if (debug)
694 printf("Warning: no nonzero pivot in column %d.\n", jcol);
695
696 ipiv = -1;
697 }
698
699 return ipiv;
700}
701
702/***************************************************************************/
709VA_DEVICE_FUN void valib_find_nullspace3(VA_REAL *A, VA_REAL *x, int *info)
710{
711 int debug = 0;
712
713 // zero the vector
714 x[0] = 0.; x[1] = 0.; x[2] = 0.;
715
716 // handle special cases with zero column
717 int num_zero_cols = 0;
718 int i_zero_col = -1;
719 int ip;
720 for (int ji = 0; ji < 3; ji++) {
721 int j = 2-ji;
722 ip = valib_find_pivot3(A,j,0);
723 if (ip == -1) {
724 if (debug) {
725 printf("There is no meaningful pivot in the %d-th column.\n",j);
726 }
727 num_zero_cols++;
728 i_zero_col = j;
729 }
730 }
731
732 if (num_zero_cols > 0) {
733 if (num_zero_cols > 1) {
734 if (debug) {
735 printf("Oops! The matrix has more than one zero columns. I search only for 1-dimensional nullspace.\n");
736 }
737 *info = -1;
738 return;
739 }
740 else {
741 x[i_zero_col] = 1.;
742 *info = 0;
743 return;
744 }
745 }
746
747 // in the usual case, permute the rows and eliminate first column
748 if (ip != 0) {
749 for (int j = 0; j < 3; j++) {
750 valib_swap_values(&A[j*3], &A[ip+j*3]);
751 }
752 }
753
754 if (debug) {
755 printf("Matrix in GEM after 1st swap: \n");
756 for (int i = 0; i < 3; i++) {
757 for (int j = 0; j < 3; j++) {
758 printf(" %lf ", A[i+j*3]);
759 }
760 printf("\n");
761 }
762 }
763
764 VA_REAL coef;
765
766 // eliminate the first column using the pivot
767 for (int i = 1; i < 3; i++) {
768 coef = A[i] / A[0];
769 for (int j = 0; j < 3; j++) {
770 A[i+j*3] -= coef*A[j*3];
771 }
772 }
773
774 if (debug) {
775 printf("Matrix in GEM without 1st col: \n");
776 for (int i = 0; i < 3; i++) {
777 for (int j = 0; j < 3; j++) {
778 printf(" %lf ", A[i+j*3]);
779 }
780 printf("\n");
781 }
782 }
783
784 // now work on the second column
785 int jpiv, jfree;
786 ip = valib_find_pivot3(A,1,1);
787 if (ip == -1) {
788 // the second column is not a pivot one, we can search for the nullspace
789 jpiv = 2;
790 jfree = 1;
791 }
792 else {
793 jpiv = 1;
794 jfree = 2;
795 }
796
797 ip = valib_find_pivot3(A,jpiv,1);
798 if (ip == -1) {
799 if (debug) {
800 printf("Matrix in GEM when it should not find another pivot: \n");
801 for (int i = 0; i < 3; i++) {
802 for (int j = 0; j < 3; j++) {
803 printf(" %lf ", A[i+j*3]);
804 }
805 printf("\n");
806 }
807 printf("Something is wrong with the matrix, the defect seems larger than one.");
808 }
809 *info = -2;
810 return;
811 }
812 if (ip == 2) {
813 // swap the rows
814 for (int j = 0; j < 3; j++) {
815 valib_swap_values(&A[1+j*3], &A[2+j*3]);
816 }
817 }
818
819 // eliminate the last row
820 coef = A[2+jpiv*3] / A[1+jpiv*3];
821 for (int j = 0; j < 3; j++) {
822 A[2+j*3] -= coef*A[1+j*3];
823 }
824 // eliminate the first row
825 coef = A[0+jpiv*3] / A[1+jpiv*3];
826 for (int j = 0; j < 3; j++) {
827 A[j*3] -= coef*A[1+j*3];
828 }
829
830 // check that the last row, in particular the last entry, is zero
831 //if (valib_find_pivot3(A,2,2) != -1) {
832 if (A[8] > 1.e-4) {
833 if (debug) {
834 printf("Matrix in GEM when it should not find last pivot: \n");
835 for (int i = 0; i < 3; i++) {
836 for (int j = 0; j < 3; j++) {
837 printf(" %lf ", A[i+j*3]);
838 }
839 printf("\n");
840 }
841 }
842 printf("Warning: The matrix for finding eigenvectors seems to be full rank.\n");
843 //*info = -2;
844 //return;
845 }
846
847 if (debug) {
848 printf("Matrix in GEM before dividing by diagonal: \n");
849 for (int i = 0; i < 3; i++) {
850 for (int j = 0; j < 3; j++) {
851 printf(" %lf ", A[i+j*3]);
852 }
853 printf("\n");
854 }
855 }
856
857 // finalize the Gauss-Jordan elimination by dividing with the diagonal values
858 coef = A[0];
859 for (int j = 0; j < 3; j++) {
860 A[j*3] /= coef;
861 }
862 coef = A[1+jpiv*3];
863 for (int j = 0; j < 3; j++) {
864 A[1+j*3] /= coef;
865 }
866
867 if (debug) {
868 printf("Matrix in GEM in the upper right echelon form:\n");
869 for (int i = 0; i < 3; i++) {
870 for (int j = 0; j < 3; j++) {
871 printf(" %d %lf ", i+j*3, A[i+j*3]);
872 }
873 printf("\n");
874 }
875 }
876
877 // fill the nullspace basis vector
878 x[jfree] = 1.;
879 x[jpiv] = -A[jpiv+jfree*3];
880 x[0] = -A[jfree*3];
881
882 // normalize the basis vector
883 VA_REAL norm = sqrt(valib_scalar_prod3(&x[0], &x[0]));
884 for (int i = 0; i < 3; i++) {
885 x[i] /= norm;
886 }
887
888 *info = 0;
889}
890
891
892/***************************************************************************/
898VA_DEVICE_FUN void valib_constructQ3(VA_REAL sina, VA_REAL cosa,
899 VA_REAL sinb, VA_REAL cosb,
900 VA_REAL sing, VA_REAL cosg,
901 VA_REAL *Q )
902{
903 Q[0] = cosa*cosb*cosg - sina*sing;
904 Q[1] = -cosa*cosb*sing - sina*cosg;
905 Q[2] = cosa*sinb;
906 Q[3] = sina*cosb*cosg + cosa*sing;
907 Q[4] = -sina*cosb*sing + cosa*cosg;
908 Q[5] = sina*sinb;
909 Q[6] = -sinb*cosg;
910 Q[7] = sinb*sing;
911 Q[8] = cosb;
912}
913
914/***************************************************************************/
920VA_DEVICE_FUN void valib_constructQfromN3(VA_REAL *n, VA_REAL *Q)
921{
922 VA_REAL vec[3];
923 VA_REAL factor;
924
925 // initialize the first row of Q with n
926 Q[0] = n[0]; Q[1] = n[1]; Q[2] = n[2];
927
928 // fill some entries to initialize the other entries in matrix Q
929 Q[3] = n[1]; Q[4] = n[2]; Q[5] = n[0];
930 Q[6] = n[2]; Q[7] = n[0]; Q[8] = n[1];
931
932 // perform Gram-Schmidt orthogonalization
934
935 // swap the first and the third column - at the moment, the matrix contains
936 // | z y x |
937 int i;
938 for (i = 0; i < 3; i++) {
939 valib_swap_values(&Q[i], &Q[6+i]);
940 }
941
942 // verify that the matrix has a right-hand oriented coordinate system,
943 // Q_1 x Q_2 = Q_3
944 valib_cross_prod3(&Q[0], &Q[3], vec);
945
946 // revert sign of the new x-axis to keep right-hand oriented coordinate
947 // system
948 factor = valib_scalar_prod3(vec, &Q[6]);
949 if (factor < 0.) {
950 for (i = 0; i < 3; i++) {
951 Q[i] = -Q[i];
952 }
953 }
954
955 // transpose the matrix
957}
958
959/***************************************************************************/
962
963#endif // VA_LINALG3_H
VA_DEVICE_FUN VA_REAL valib_cubic_root(VA_REAL x)
Definition linalg3.h:134
VA_DEVICE_FUN VA_REAL valib_cimag(VA_COMPLEX a)
Definition linalg3.h:75
VA_DEVICE_FUN VA_COMPLEX valib_cmultiply(VA_COMPLEX a, VA_COMPLEX b)
Definition linalg3.h:118
VA_DEVICE_FUN void valib_cross_prod3(VA_REAL *v1, VA_REAL *v2, VA_REAL *v3)
Definition linalg3.h:328
VA_DEVICE_FUN void valib_tatt3(VA_REAL *A, VA_REAL *T, VA_REAL *TATT)
Definition linalg3.h:523
VA_DEVICE_FUN VA_COMPLEX valib_cadd(VA_COMPLEX a, VA_COMPLEX b)
Definition linalg3.h:109
VA_DEVICE_FUN void valib_rank1_update3(VA_REAL alpha, VA_REAL *x, VA_REAL *y, VA_REAL *A)
Definition linalg3.h:500
VA_DEVICE_FUN void valib_ttat3(VA_REAL *A, VA_REAL *T, VA_REAL *TTAT)
Definition linalg3.h:575
VA_DEVICE_FUN void valib_deviatorise3(VA_REAL *A)
Definition linalg3.h:461
VA_DEVICE_FUN VA_REAL valib_scalar_prod3(VA_REAL *v1, VA_REAL *v2)
Definition linalg3.h:313
VA_DEVICE_FUN void valib_vec_zero3(VA_REAL *v)
Definition linalg3.h:301
VA_DEVICE_FUN void valib_matvec3_prod(int trans_a, VA_REAL *A, VA_REAL *x, VA_REAL *y)
Definition linalg3.h:478
VA_DEVICE_FUN VA_REAL valib_min(VA_REAL a, VA_REAL b)
Definition linalg3.h:154
VA_DEVICE_FUN void valib_sym_antisym3(VA_REAL *A)
Definition linalg3.h:437
VA_DEVICE_FUN VA_COMPLEX valib_makec(VA_REAL a, VA_REAL b)
Definition linalg3.h:29
VA_DEVICE_FUN void valib_transpose3(VA_REAL *A)
Definition linalg3.h:424
VA_DEVICE_FUN void valib_mat_copy3(VA_REAL *A, VA_REAL *B)
Definition linalg3.h:360
VA_DEVICE_FUN VA_REAL valib_cabs(VA_COMPLEX a)
Definition linalg3.h:98
VA_DEVICE_FUN void valib_swap_values(VA_REAL *a, VA_REAL *b)
Definition linalg3.h:172
VA_DEVICE_FUN VA_REAL valib_square(VA_REAL a)
Definition linalg3.h:163
VA_DEVICE_FUN void valib_second_invariant3(VA_REAL *A, VA_REAL *second_invariant)
Definition linalg3.h:399
VA_DEVICE_FUN void valib_find_nullspace3(VA_REAL *A, VA_REAL *x, int *info)
Definition linalg3.h:709
VA_DEVICE_FUN void valib_gram_schmidt3(VA_REAL *Q)
Definition linalg3.h:593
VA_DEVICE_FUN void valib_constructQfromN3(VA_REAL *n, VA_REAL *Q)
Definition linalg3.h:920
VA_DEVICE_FUN int valib_find_pivot3(VA_REAL *A, int jcol, int start)
Definition linalg3.h:682
VA_DEVICE_FUN void valib_mat_zero3(VA_REAL *A)
Definition linalg3.h:346
VA_DEVICE_FUN VA_REAL valib_creal(VA_COMPLEX a)
Definition linalg3.h:52
VA_DEVICE_FUN void valib_solve_cubic_equation(VA_REAL a, VA_REAL b, VA_REAL c, VA_REAL d, VA_REAL *x1, VA_COMPLEX *x2, VA_COMPLEX *x3, int *info)
Definition linalg3.h:188
VA_DEVICE_FUN VA_REAL valib_sign(VA_REAL a, VA_REAL b)
Definition linalg3.h:20
VA_DEVICE_FUN void valib_eigenvalues_sym3(VA_REAL *A, VA_REAL *eigval)
Definition linalg3.h:626
VA_DEVICE_FUN void valib_constructQ3(VA_REAL sina, VA_REAL cosa, VA_REAL sinb, VA_REAL cosb, VA_REAL sing, VA_REAL cosg, VA_REAL *Q)
Definition linalg3.h:898
VA_DEVICE_FUN void valib_matmat3_prod(int trans_a, int trans_b, VA_REAL *A, VA_REAL *B, VA_REAL *C)
Definition linalg3.h:546
VA_DEVICE_FUN void valib_trace3(VA_REAL *A, VA_REAL *tr3)
Definition linalg3.h:390
VA_DEVICE_FUN void valib_norm_frobenius3(VA_REAL *A, VA_REAL *norm)
Definition linalg3.h:374
VA_DEVICE_FUN void valib_determinant3(VA_REAL *A, VA_REAL *det)
Definition linalg3.h:410
VA_DEVICE_FUN VA_REAL valib_max(VA_REAL a, VA_REAL b)
Definition linalg3.h:144