Functions | |
| void | CrossProduct (const double A[3], const double B[3], double C[3]) |
| double | DotProduct (const double A[3], const double B[3]) |
| void | eigenValsAndVecsOf3by3SymMatrix (double m11, double m12, double m13, double m22, double m23, double m33, double &l1, double &l2, double &l3, double v1[3], double v2[3], double v3[3]) |
| void | eigenValsAndVecsOf3by3SymMatrixUsingQRFactor (double m11, double m12, double m13, double m22, double m23, double m33, double &l1, double &l2, double &l3, double v1[3], double v2[3], double v3[3]) |
| double | eigenValsOf3by3SymMatrix (double m11, double m12, double m13, double m22, double m23, double m33, double &lamda1, double &lamda2, double &lamda3) |
| double | eigenValsOf3by3SymMatrixSmith1961 (double m11, double m12, double m13, double m22, double m23, double m33, double &lamda1, double &lamda2, double &lamda3) |
| void | FindAnEigenVector (double &m11, double &m12, double &m13, double &m22, double &m23, double &m33, double l1, double v1[3]) |
| void | FindOrthogonalVectors (const double iA[3], double oB[3], double oC[3]) |
| double | RootFindingByNewtonRaphsonMethod (void(*funcd)(double x, double *fx, double *dfx), double x1, double x2, double xacc) |
| double | rootOfCubicPolynomial (double a, double b, double c, double d, int rootNo) |
| double | rootsOfCubicPolynomial (double a, double b, double c, double d, double &r1, double &r2, double &r3) |
| double | rootsOfCubicPolynomial (double a, double b, double c, double d, std::complex< double > &r1, std::complex< double > &r2, std::complex< double > &r3) |
| void | rootsOfCubicPolynomialCodeGeneratedByMaple (double a, double b, double c, double d, std::complex< double > &r1, std::complex< double > &r2, std::complex< double > &r3) |
Variables | |
| const double | PI = 3.141592654 |
| void SP_Maths::CrossProduct | ( | const double | A[3], | |
| const double | B[3], | |||
| double | C[3] | |||
| ) |
Definition at line 21 of file sp_mathematics.cpp.
00022 { 00023 C[0] = A[1]*B[2] - A[2]*B[1]; 00024 C[1] = A[2]*B[0] - A[0]*B[2]; 00025 C[2] = A[0]*B[1] - A[1]*B[0]; 00026 } // END FN: CrossProduct()
| double SP_Maths::DotProduct | ( | const double | A[3], | |
| const double | B[3] | |||
| ) |
| void SP_Maths::eigenValsAndVecsOf3by3SymMatrix | ( | double | m11, | |
| double | m12, | |||
| double | m13, | |||
| double | m22, | |||
| double | m23, | |||
| double | m33, | |||
| double & | l1, | |||
| double & | l2, | |||
| double & | l3, | |||
| double | v1[3], | |||
| double | v2[3], | |||
| double | v3[3] | |||
| ) |
Definition at line 526 of file sp_mathematics.cpp.
00531 { 00532 double errThreshold = 1E-05; // error tolerant value 00533 00534 double discriminant = eigenValsOf3by3SymMatrix( m11, m12, m13, m22, m23, m33, l1, l2, l3 ); 00535 00536 // Smith's Method (1961) 00537 //double discriminant = eigenValsOf3by3SymMatrixSmith1961( m11, m12, m13, m22, m23, m33, ll1, ll2, ll3 ); 00538 00539 //cout << "discriminant = " << discriminant << endl; 00540 //cout << "l1: " << l1 << " l2: " << l2 << " l3: " << l3 << endl; 00541 00542 // ******************************************************************** 00543 // ASSUME all eigen values are real! 00544 00545 // If discriminant > 0, then one root is real and two complex conjugate. 00546 /* 00547 if ( discriminant > errThreshold ) { 00548 cerr << "ERR: Discriminant > 0, i.e. one eigen value is real and two complex conjugate!" << "\n"; 00549 cerr << "CONT: The function is not intended for this kind of matrix!" << endl; 00550 return; 00551 } 00552 */ 00553 00554 00555 00556 // If all eigen values are equal, then eigen vectors can be 00557 // any vectors that are orthogonal to one another. 00558 // Also in this case, discriminant == 0. 00559 //if ( fabs(m12) < errThreshold && fabs(m13) < errThreshold && fabs(m23) < errThreshold ) { 00560 const double ratio = 100000.0; 00561 if ( fabs(l1 - l2) < fabs(l1/ratio) ) { 00562 if ( fabs(l1 - l3) < fabs(l1/ratio) ) { // CASE: l1 == l2 == l3 00563 v1[0] = 1; v1[1] = 0; v1[2] = 0; 00564 v2[0] = 0; v2[1] = 1; v2[2] = 0; 00565 v3[0] = 0; v3[1] = 0; v3[2] = 1; 00566 cout << "CASE: l1 == l2 == l3\n"; 00567 } 00568 else { // CASE: l1 == l2 != l3 00569 FindAnEigenVector( m11, m12, m13, m22, m23, m33, l3, v3 ); 00570 FindOrthogonalVectors( v3, v1, v2 ); 00571 cout << "CASE: l1 == l2 != l3\n"; 00572 } 00573 } 00574 else if ( fabs(l2 - l3) < fabs(l2/ratio) ) { // CASE: l1 != l2 == l3 00575 FindAnEigenVector( m11, m12, m13, m22, m23, m33, l1, v1 ); 00576 FindOrthogonalVectors( v1, v2, v3 ); 00577 cout << "CASE: l1 != l2 == l3\n"; 00578 } 00579 else if ( fabs(l1 - l3) < fabs(l1/ratio) ) { // CASE: l1 == l3 != l2 00580 FindAnEigenVector( m11, m12, m13, m22, m23, m33, l2, v2 ); 00581 FindOrthogonalVectors( v2, v1, v3 ); 00582 cout << "CASE: l1 == l3 != l2\n"; 00583 } 00584 else { // CASE: l1 != l2 != l3 00585 //if ( fabs(l1) > fabs(l2) && fabs(l1) > fabs(l3) ) {} 00586 FindAnEigenVector( m11, m12, m13, m22, m23, m33, l1, v1 ); 00587 //FindOrthogonalVectors( v1, v2, v3 ); 00588 FindAnEigenVector( m11, m12, m13, m22, m23, m33, l2, v2 ); 00589 FindAnEigenVector( m11, m12, m13, m22, m23, m33, l3, v3 ); 00590 cout << "CASE: l1 != l2 != l3\n"; 00591 } 00592 00593 cout << "v1*v2 = " << DotProduct(v1,v2) << "\n"; 00594 cout << "v2*v3 = " << DotProduct(v2,v3) << "\n"; 00595 cout << "v1*v3 = " << DotProduct(v1,v3) << "\n"; 00596 } // END FN: eigenValsAndVecsOf3by3SymMatrix()
| void SP_Maths::eigenValsAndVecsOf3by3SymMatrixUsingQRFactor | ( | double | m11, | |
| double | m12, | |||
| double | m13, | |||
| double | m22, | |||
| double | m23, | |||
| double | m33, | |||
| double & | l1, | |||
| double & | l2, | |||
| double & | l3, | |||
| double | v1[3], | |||
| double | v2[3], | |||
| double | v3[3] | |||
| ) |
Definition at line 603 of file sp_mathematics.cpp.
00608 { 00609 //double errThreshold = 5E-3; // error tolerant value 00610 static const int TIMES_LIMIT = 256; 00611 int iterationTimes = 1; 00612 00613 SPtMatrix< double > IT( 3, 3 ); 00614 SPtMatrix< double > EG( 3, 3 ); 00615 IT.Set( 0, 0, m11 ); IT.Set( 0, 1, m12 ); IT.Set( 0, 2, m13 ); 00616 IT.Set( 1, 0, m12 ); IT.Set( 1, 1, m22 ); IT.Set( 1, 2, m23 ); 00617 IT.Set( 2, 0, m13 ); IT.Set( 2, 1, m23 ); IT.Set( 2, 2, m33 ); 00618 00619 //cout << "IT is \n"; 00620 //IT.DisplayElements(); 00621 do { 00622 iterationTimes *= 2; 00623 00624 MatrixOperations::EigenValsByQRFactorization( IT, iterationTimes, &EG ); 00625 00626 cout << "QR Factorization iterates " << iterationTimes << " times.\n"; 00627 00628 //cout << "IT is \n"; 00629 //IT.DisplayElements(); 00630 //cout << "EG is \n"; 00631 //EG.DisplayElements(); 00632 00633 l1 = EG.Get( 0, 0 ); 00634 l2 = EG.Get( 1, 1 ); 00635 l3 = EG.Get( 2, 2 ); 00636 00637 // If all eigen values are equal, then eigen vectors can be 00638 // any vectors that are orthogonal to one another. 00639 // Also in this case, discriminant == 0. 00640 //if ( fabs(m12) < errThreshold && fabs(m13) < errThreshold && fabs(m23) < errThreshold ) { 00641 const double ratio = 10000.0; 00642 if ( fabs(l1 - l2) < fabs(l1/ratio) ) { 00643 if ( fabs(l1 - l3) < fabs(l1/ratio) ) { // CASE: l1 == l2 == l3 00644 v1[0] = 1; v1[1] = 0; v1[2] = 0; 00645 v2[0] = 0; v2[1] = 1; v2[2] = 0; 00646 v3[0] = 0; v3[1] = 0; v3[2] = 1; 00647 cout << "CASE: l1 == l2 == l3\n"; 00648 } 00649 else { // CASE: l1 == l2 != l3 00650 FindAnEigenVector( m11, m12, m13, m22, m23, m33, l3, v3 ); 00651 FindOrthogonalVectors( v3, v1, v2 ); 00652 cout << "CASE: l1 == l2 != l3\n"; 00653 } 00654 } 00655 else if ( fabs(l2 - l3) < fabs(l2/ratio) ) { // CASE: l1 != l2 == l3 00656 FindAnEigenVector( m11, m12, m13, m22, m23, m33, l1, v1 ); 00657 FindOrthogonalVectors( v1, v2, v3 ); 00658 cout << "CASE: l1 != l2 == l3\n"; 00659 } 00660 else if ( fabs(l1 - l3) < fabs(l1/ratio) ) { // CASE: l1 == l3 != l2 00661 FindAnEigenVector( m11, m12, m13, m22, m23, m33, l2, v2 ); 00662 FindOrthogonalVectors( v2, v1, v3 ); 00663 cout << "CASE: l1 == l3 != l2\n"; 00664 } 00665 else { // CASE: l1 != l2 != l3 00666 //if ( fabs(l1) > fabs(l2) && fabs(l1) > fabs(l3) ) {} 00667 FindAnEigenVector( m11, m12, m13, m22, m23, m33, l1, v1 ); 00668 //FindOrthogonalVectors( v1, v2, v3 ); 00669 FindAnEigenVector( m11, m12, m13, m22, m23, m33, l2, v2 ); 00670 FindAnEigenVector( m11, m12, m13, m22, m23, m33, l3, v3 ); 00671 cout << "CASE: l1 != l2 != l3\n"; 00672 } 00673 00674 cout << "v1*v2 = " << DotProduct(v1,v2) << "\n"; 00675 cout << "v2*v3 = " << DotProduct(v2,v3) << "\n"; 00676 cout << "v1*v3 = " << DotProduct(v1,v3) << "\n"; 00677 } while ( fabs(DotProduct(v1,v2) + DotProduct(v2,v3) + DotProduct(v1,v3)) > 1E-06 && iterationTimes <= TIMES_LIMIT ); 00678 } // END FN: eigenValsAndVecsOf3by3SymMatrixUsingQRFactor()
| double SP_Maths::eigenValsOf3by3SymMatrix | ( | double | m11, | |
| double | m12, | |||
| double | m13, | |||
| double | m22, | |||
| double | m23, | |||
| double | m33, | |||
| double & | lamda1, | |||
| double & | lamda2, | |||
| double & | lamda3 | |||
| ) |
Definition at line 397 of file sp_mathematics.cpp.
00401 { 00402 double errThreshold = 1E-6; // error tolerant value 00403 double b, c, d = 0; 00404 double f[5]; 00405 00406 // coefficients of the characteristic polynomial of the 3x3 symmetric matrix 00407 b = - m11 - m22 - m33; 00408 c = (m11*m22 + m22*m33 + m33*m11) - (m12*m12 + m23*m23 + m13*m13); 00409 //d = m11*m23*m23 + m22*m13*m13 + m33*m12*m12 - m11*m22*m33 - 2*m12*m23*m13; 00410 00411 f[0] = m11*m23*m23; 00412 f[1] = m22*m13*m13; 00413 f[2] = m33*m12*m12; 00414 f[3] = -m11*m22*m33; 00415 f[4] = -2*m12*m23*m13; 00416 double dNeg = 0; 00417 for ( int i = 0; i < 5; i++ ) { 00418 if ( f[i] >= 0 ) d += f[i]; 00419 else dNeg += f[i]; 00420 } 00421 d += dNeg; 00422 00423 // the roots of the polynomial function are the eigen values of the matrix 00424 if ( fabs(m12) < errThreshold && fabs(m13) < errThreshold && fabs(m23) < errThreshold ) { 00425 double difThreshold = fabs( m11 * 1E-06 ); 00426 if ( fabs(m11-m22) < difThreshold && fabs(m11-m33) < difThreshold ) { // all roots are real and at least two are equal if discriminant = 0. 00427 lamda1 = lamda2 = lamda3 = ( m11 + m22 + m33 ) / 3.0; 00428 return 0; // return zero discriminant value 00429 } 00430 else { // all roots are real and unequal if discriminant < 0. 00431 lamda1 = m11; 00432 lamda2 = m22; 00433 lamda3 = m33; 00434 return -1; // return negative discriminant value 00435 } 00436 } 00437 00438 // Find roots using formulas from "Handbook of Mathematic" 00439 double discriminant = rootsOfCubicPolynomial( 1, b, c, d, lamda1, lamda2, lamda3 ); 00440 00441 return static_cast<double>(discriminant); 00442 } // END FN: eigenValsOf3by3SymMatrix()
| double SP_Maths::eigenValsOf3by3SymMatrixSmith1961 | ( | double | m11, | |
| double | m12, | |||
| double | m13, | |||
| double | m22, | |||
| double | m23, | |||
| double | m33, | |||
| double & | lamda1, | |||
| double & | lamda2, | |||
| double & | lamda3 | |||
| ) |
Definition at line 449 of file sp_mathematics.cpp.
00453 { 00454 00455 double errThreshold = 1E-10; 00456 00457 // 3m = trace(A) 00458 // 2q = det(A - mI) 00459 // 6p = the sum of squares of elements of (A - mI) 00460 // discriminant = p^3 - q^2 00461 // phi = 1/3*arctan( sqrt(discriminant)/q ) 00462 // root1 = m + 2*sqrt(p)*cos(phi) 00463 // root2 = m - sqrt(p)*(cos(phi) + sqrt(3)*sin(phi)) 00464 // root3 = m - sqrt(p)*(cos(phi) - sqrt(3)*sin(phi)) 00465 double m, p, q, phi, discriminant; 00466 00467 00468 SPtMatrix3x3< double > IT( m11, m12, m13, 00469 m12, m22, m23, 00470 m13, m23, m33 ); 00471 SPtMatrix3x3< double > I( 1,0,0, 0,1,0, 0,0,1 ); 00472 00473 00474 m = ( m11 + m22 + m33 ) / 3.0; 00475 00476 SPtMatrix3x3< double > B = IT - m*I; 00477 00478 q = ( B.Get(0,0) * ( B.Get(1,1)*B.Get(2,2) - B.Get(2,1)*B.Get(1,2) ) 00479 - B.Get(1,0) * ( B.Get(0,1)*B.Get(2,2) - B.Get(2,1)*B.Get(0,2) ) 00480 + B.Get(2,0) * ( B.Get(0,1)*B.Get(1,2) - B.Get(1,1)*B.Get(0,2) ) 00481 ) / 2.0; 00482 00483 p = 0; 00484 for ( int r = 0; r < 3; r++ ) { 00485 for ( int c = 0; c < 3; c++ ) { 00486 p += B.Get(r,c)*B.Get(r,c); 00487 } 00488 } 00489 p /= 6.0; 00490 00491 discriminant = p*p*p - q*q; 00492 if ( discriminant >= 0 ) { 00493 phi = atan( sqrt(discriminant)/q ) / 3.0; 00494 00495 lamda1 = m + 2*sqrt(p)*cos(phi); 00496 lamda2 = m - sqrt((double)p)*(cos(phi) + sqrt((double)3)*sin(phi)); 00497 lamda3 = m - sqrt((double)p)*(cos(phi) - sqrt((double)3)*sin(phi)); 00498 } 00499 else { 00500 cout << "Discriminant (Smith's Method (1961) < 0: discriminant = " << discriminant << "\n"; 00501 } 00502 00503 // the roots of the polynomial function are the eigen values of the matrix 00504 if ( fabs(m12) < errThreshold && fabs(m13) < errThreshold && fabs(m23) < errThreshold ) { 00505 double difThreshold = fabs( m11 * 1E-06 ); 00506 if ( fabs(m11-m22) < difThreshold && fabs(m11-m33) < difThreshold ) { // all roots are real and at least two are equal if discriminant = 0. 00507 lamda1 = lamda2 = lamda3 = ( m11 + m22 + m33 ) / 3.0; 00508 return 0; // return zero discriminant value 00509 } 00510 else { // all roots are real and unequal if discriminant < 0. 00511 lamda1 = m11; 00512 lamda2 = m22; 00513 lamda3 = m33; 00514 return -1; // return negative discriminant value 00515 } 00516 } 00517 00518 return static_cast<double>(discriminant); 00519 } // END FN: eigenValsOf3by3SymMatrixSmith1961()
| void SP_Maths::FindAnEigenVector | ( | double & | m11, | |
| double & | m12, | |||
| double & | m13, | |||
| double & | m22, | |||
| double & | m23, | |||
| double & | m33, | |||
| double | l1, | |||
| double | v1[3] | |||
| ) |
Definition at line 39 of file sp_mathematics.cpp.
00041 : 3x3 Symmetric Matrix 00042 double l1, // O/P: eigen value 00043 double v1[3] // O/P: eigen vector 00044 ) 00045 { 00046 double a1, b1 = m12, c1 = m13; 00047 double a2 = m12, b2, c2 = m23; 00048 double a3 = m13, b3 = m23, c3; 00049 00050 a1 = m11 - l1; 00051 b2 = m22 - l1; 00052 c3 = m33 - l1; 00053 double divider = b2*a1 - b1*a2 - b3*a1 + b1*a3; 00054 //if ( divider != 0 ) { 00055 if ( fabs(divider) > 1E-40 ) { 00056 v1[0] = (-b2*c1 + b1*c2 + b3*c1 - b1*c3) / divider; 00057 v1[1] = (a2*c1 - a1*c2 - a3*c1 + a1*c3) /divider; 00058 v1[2] = 1; 00059 00060 // make the vector a unit vector 00061 double vecLen = sqrt( v1[0]*v1[0] + v1[1]*v1[1] + v1[2]*v1[2] ); 00062 v1[0] /= vecLen; 00063 v1[1] /= vecLen; 00064 v1[2] /= vecLen; 00065 } 00066 else { 00067 v1[0] = 0; 00068 v1[1] = 0; 00069 v1[2] = 0; 00070 } 00071 } // END FN: FindAnEigenVector()
| void SP_Maths::FindOrthogonalVectors | ( | const double | iA[3], | |
| double | oB[3], | |||
| double | oC[3] | |||
| ) |
Definition at line 76 of file sp_mathematics.cpp.
00077 { 00078 SPtMatrix< double > A( 3, 1 ), B( 3, 1 ), C( 3, 1 ); 00079 for ( int i = 0; i < 3; i++ ) { 00080 A.Set( i, 0, iA[i] ); 00081 } 00082 00083 // alpha for x, beta for y, and zeta for z 00084 00085 double angleZeta; 00086 if ( iA[0] != 0 ) angleZeta = atan( iA[1] / iA[0] ); 00087 else angleZeta = ( iA[1] > 0 ? 1.0 : -1.0 ) * PI / 2.0; 00088 double angleBeta = asin( iA[2] / sqrt( iA[0]*iA[0] + iA[1]*iA[1] + iA[2]*iA[2] ) ); 00089 //double angleAlpha = 90.0/180.0*PI; 00090 SPtMatrix< double > Rz( 3, 3 ); 00091 Rz.Set( 0, 0, cos( angleZeta ) ); Rz.Set( 0, 1, sin( angleZeta ) ); 00092 Rz.Set( 1, 0, -sin( angleZeta ) ); Rz.Set( 1, 1, cos( angleZeta ) ); 00093 Rz.Set( 2, 2, 1 ); 00094 SPtMatrix< double > Ry( 3, 3 ); 00095 Ry.Set( 0, 0, cos( angleBeta ) ); Ry.Set( 0, 2, -sin( angleBeta ) ); 00096 Ry.Set( 1, 1, 1 ); 00097 Ry.Set( 2, 0, sin( angleBeta ) ); Ry.Set( 2, 2, cos( angleBeta ) ); 00098 00099 SPtMatrix< double > Ryy( 3, 3 ); 00100 Ryy.Set( 0, 0, cos( PI/2.0 ) ); Ryy.Set( 0, 2, -sin( PI/2.0 ) ); 00101 Ryy.Set( 1, 1, 1 ); 00102 Ryy.Set( 2, 0, sin( PI/2.0 ) ); Ryy.Set( 2, 2, cos( PI/2.0 ) ); 00103 00104 /* 00105 SPtMatrix< double > Rx( 3, 3 ); 00106 Rx.Set( 0, 0, 1 ); 00107 Rx.Set( 1, 1, cos( angleAlpha ) ); Rx.Set( 1, 2, sin( angleAlpha ) ); 00108 Rx.Set( 2, 1, -sin( angleAlpha ) ); Rx.Set( 2, 2, cos( angleAlpha ) ); 00109 */ 00110 00111 SPtMatrix< double > Rym( 3, 3 ); 00112 Rym.Set( 0, 0, cos( -angleBeta ) ); Rym.Set( 0, 2, -sin( -angleBeta ) ); 00113 Rym.Set( 1, 1, 1 ); 00114 Rym.Set( 2, 0, sin( -angleBeta ) ); Rym.Set( 2, 2, cos( -angleBeta ) ); 00115 SPtMatrix< double > Rzm( 3, 3 ); 00116 Rzm.Set( 0, 0, cos( -angleZeta ) ); Rzm.Set( 0, 1, sin( -angleZeta ) ); 00117 Rzm.Set( 1, 0, -sin( -angleZeta ) ); Rzm.Set( 1, 1, cos( -angleZeta ) ); 00118 Rzm.Set( 2, 2, 1 ); 00119 00120 //B = Rz * Ry * Ryy * Rym * Rzm * A; 00121 B = Rzm * Rym * Ryy * Ry * Rz * A; 00122 00123 //B.DisplayElements(); 00124 //(A.GetTranspose()*B).DisplayElements(); 00125 00126 oB[0] = B.Get( 0, 0 ); 00127 oB[1] = B.Get( 1, 0 ); 00128 oB[2] = B.Get( 2, 0 ); 00129 00130 cout << "\niA*oB = " << ( iA[0]*oB[0] + iA[1]*oB[1] + iA[2]*oB[2] ) << "\n"; 00131 CrossProduct( iA, oB, oC ); 00132 } // END FN: FindOrthogonalVectors()
| double SP_Maths::RootFindingByNewtonRaphsonMethod | ( | void(*)(double x, double *fx, double *dfx) | funcd, | |
| double | x1, | |||
| double | x2, | |||
| double | xacc | |||
| ) |
Definition at line 688 of file sp_mathematics.cpp.
00692 { 00693 const int ITERATION_LIMIT = 200; 00694 double x, fx, dx = 0, dfx; 00695 00696 x = 0.5 * (x1 + x2); // initial guess is the middle of the interval (x1,x2) 00697 for ( int i = 1; i < ITERATION_LIMIT; i++ ) { 00698 (*funcd)( x, &fx, &dfx ); 00699 if ( fx != 0 && dfx != 0) { 00700 dx = fx/dfx; 00701 x -= dx; 00702 } 00703 if ( (x1-x)*(x-x2) < 0.0 ) { 00704 cerr << "From RootFindingByNewtonRaphsonMethod():\n" 00705 << " The root lies outside the provided interval (x1,x2)!" << endl; 00706 return -777; 00707 } 00708 if ( fabs(dx) < xacc ) return x; // the convergence value is the root 00709 } 00710 00711 cerr << "From RootFindingByNewtonRaphsonMethod():\n" 00712 << " Maximum number of iterations exceeded!" << endl; 00713 return -777; 00714 } // END FN: RootFindingByNewtonRaphsonMethod()
| double SP_Maths::rootOfCubicPolynomial | ( | double | a, | |
| double | b, | |||
| double | c, | |||
| double | d, | |||
| int | rootNo | |||
| ) |
Definition at line 306 of file sp_mathematics.cpp.
00307 { 00308 double a1, a2, a3; 00309 double Q, R, D; 00310 double S, T; // FIX IT HERE! 00311 double zeta; 00312 double rootValue; 00313 00314 a1 = b/a; 00315 a2 = c/a; 00316 a3 = d/a; 00317 Q = (3.0*a2 - a1*a1) / 9.0; 00318 R = (9.0*a1*a2 - 27.0*a3 - 2.0*a1*a1*a1) / 54.0; 00319 D = Q*Q*Q + R*R; 00320 00321 // If a1, a2, a3 are real and if D = Q^3 + R^2 is the discriminant, then 00322 // (i) one root is real and two complex conjugate if D > 0 00323 // (ii) all roots are real and at least two are equal if D = 0 00324 // (iii) all roots are real and unequal if D < 0. 00325 00326 if ( D >= 0 ) { 00327 double Dh = sqrt(D); 00328 S = pow(R + Dh, 1.0/3.0); // FIX IT HERE! 00329 T = R - Dh; 00330 if ( T >= 0 ) T = pow( T, 1.0/3.0 ); 00331 else T = -pow( -T, 1.0/3.0 ); 00332 00333 switch ( rootNo ) { 00334 // first root 00335 case 1: 00336 rootValue = S + T - a1/3.0; 00337 return rootValue; 00338 break; 00339 00340 // second root 00341 case 2: 00342 rootValue = -(S + T)/2.0 - a1/3.0; // + i*sqrt(3.0)*(S - T)/2.0; 00343 return rootValue; 00344 break; 00345 00346 // third root 00347 case 3: 00348 rootValue = -(S + T)/2.0 - a1/3.0; // - i*sqrt(3.0)*(S - T)/2.0; 00349 return rootValue; 00350 break; 00351 00352 // default 00353 default: 00354 cerr << "ERROR: Incorrect Root# Option!" << endl; 00355 return -777; 00356 break; 00357 } 00358 } 00359 00360 // All roots are real and unequal if D < 0. 00361 //if ( D < 0 ) { 00362 else { 00363 zeta = acos( R / sqrt(-(Q*Q*Q)) ); 00364 switch ( rootNo ) { 00365 // first root 00366 case 1: 00367 rootValue = 2 * sqrt(-Q) * cos(zeta/3.0) - a1/3.0; 00368 return rootValue; 00369 break; 00370 00371 // second root 00372 case 2: 00373 rootValue = 2 * sqrt(-Q) * cos(zeta/3.0 + 2.0/3.0*PI) - a1/3.0; 00374 return rootValue; 00375 break; 00376 00377 // third root 00378 case 3: 00379 rootValue = 2 * sqrt(-Q) * cos(zeta/3.0 + 4.0/3.0*PI) - a1/3.0; 00380 return rootValue; 00381 break; 00382 00383 // default 00384 default: 00385 cerr << "ERROR: Incorrect Root# Option!" << endl; 00386 return -777; 00387 break; 00388 } 00389 } 00390 } // END FN: rootOfCubicPolynomial()
| double SP_Maths::rootsOfCubicPolynomial | ( | double | a, | |
| double | b, | |||
| double | c, | |||
| double | d, | |||
| double & | r1, | |||
| double & | r2, | |||
| double & | r3 | |||
| ) |
Definition at line 284 of file sp_mathematics.cpp.
00286 { 00287 std::complex< double > cr1, cr2, cr3; 00288 double discriminant = rootsOfCubicPolynomial( a, b, c, d, cr1, cr2, cr3 ); 00289 r1 = cr1.real(); 00290 r2 = cr2.real(); 00291 r3 = cr3.real(); 00292 00293 return discriminant; 00294 }
| double SP_Maths::rootsOfCubicPolynomial | ( | double | a, | |
| double | b, | |||
| double | c, | |||
| double | d, | |||
| std::complex< double > & | r1, | |||
| std::complex< double > & | r2, | |||
| std::complex< double > & | r3 | |||
| ) |
Definition at line 194 of file sp_mathematics.cpp.
00198 { 00199 double a1, a2, a3; 00200 double Q, R, D; 00201 std::complex<double> S, T; 00202 double zeta; 00203 00204 a1 = b/a; 00205 a2 = c/a; 00206 a3 = d/a; 00207 00208 //Q = (3.0*a2 - a1*a1) / 9.0; 00209 //R = (9.0*a1*a2 - 27.0*a3 - 2.0*a1*a1*a1) / 54.0; 00210 // Q^3 + R^2 can factor 9*9*9 (or 27*27) out 00211 // So Q = 3*a2 - a1^2 00212 // and R = (f1 + f2 + f3) / 2 00213 00214 Q = 3.0*a2 - a1*a1; 00215 double Rpos = 0, Rneg = 0; 00216 double f[3]; 00217 f[0] = 9.0*a1*a2; 00218 f[1] = -27.0*a3; 00219 f[2] = -2.0*a1*a1*a1; 00220 for ( int i = 0; i < 3; i++ ) { 00221 ( f[i] >= 0 ) ? ( Rpos += f[i] ) : ( Rneg += f[i] ); 00222 //if ( f[i] >= 0 ) Rpos += f[i]; 00223 //else Rneg += f[i]; 00224 } 00225 R = (Rpos + Rneg) / 2.0; 00226 00227 00228 00229 D = ( Q*Q*Q + R*R ) / 729.0; 00230 Q /= 9.0; 00231 R /= 27.0; 00232 00233 // If a1, a2, a3 are real and if D = Q^3 + R^2 is the discriminant, then 00234 // (i) one root is real and two complex conjugate if D > 0 00235 // (ii) all roots are real and at least two are equal if D = 0 00236 // (iii) all roots are real and unequal if D < 0. 00237 00238 if ( D >= 0 ) { 00239 std::complex<double> Dh = sqrt(D); 00240 00241 S = pow(R + Dh, 1.0/3.0); 00242 T = pow(R - Dh, 1.0/3.0); 00243 00244 r1 = S + T - a1/3.0; 00245 std::complex<double> pureComplex( 0, sqrt(3.0) ); 00246 //r2 = -(S + T)/2.0 - a1/3.0 + i*sqrt(3.0)*(S - T)/2.0; 00247 //r3 = -(S + T)/2.0 - a1/3.0 - i*sqrt(3.0)*(S - T)/2.0; 00248 r2 = - (S + T)/2.0 - a1/3.0 + pureComplex*(S - T)/2.0; 00249 r3 = - (S + T)/2.0 - a1/3.0 - pureComplex*(S - T)/2.0; 00250 } 00251 00252 // All roots are real and unequal if D < 0. 00253 //if ( D < 0 ) { 00254 else { 00255 //cout << "D < 0" << endl; 00256 zeta = acos( R / sqrt(-(Q*Q*Q)) ); 00257 r1 = 2 * sqrt(-Q) * cos(zeta/3.0) - a1/3.0; 00258 r2 = 2 * sqrt(-Q) * cos(zeta/3.0 + 2.0/3.0*PI) - a1/3.0; 00259 r3 = 2 * sqrt(-Q) * cos(zeta/3.0 + 4.0/3.0*PI) - a1/3.0; 00260 } 00261 00262 // DEBUG: 00263 cout.precision( 10 ); 00264 cout << "*x^3" << (a1>0 ? " + " : " - ") << fabs(a1) << "*x^2"<< (a1>0 ? " + " : " - ") 00265 << fabs(a2) << "*x" << (a1>0 ? " + " : " - ") << fabs(a3) << "\n"; 00266 cout << "Q = " << Q << "\n"; 00267 cout << "R = " << R << "\n"; 00268 cout << "Q^3 = " << Q*Q*Q << "\n"; 00269 cout << "R^2 = " << R*R << "\n"; 00270 cout << "D = " << D << "\n"; 00271 cout << "Root#1: " << r1 << " Root#2: " << r2 << " Root#3: " << r3 << "\n"; 00272 cout.precision( 6 ); 00273 00274 00275 std::complex<double> cr1, cr2, cr3; 00276 rootsOfCubicPolynomialCodeGeneratedByMaple( a, b, c, d, cr1, cr2, cr3 ); 00277 00278 00279 return D; // return discriminant 00280 } // END FN: rootsOfCubicPolynomial()
| void SP_Maths::rootsOfCubicPolynomialCodeGeneratedByMaple | ( | double | a, | |
| double | b, | |||
| double | c, | |||
| double | d, | |||
| std::complex< double > & | r1, | |||
| std::complex< double > & | r2, | |||
| std::complex< double > & | r3 | |||
| ) |
Definition at line 135 of file sp_mathematics.cpp.
00138 { 00139 std::complex<double> a1; 00140 std::complex<double> a2; 00141 std::complex<double> a3; 00142 00143 a1 = b/a; 00144 a2 = c/a; 00145 a3 = d/a; 00146 00147 std::complex<double> div = 1.0/3.0; 00148 00149 // common part for all roots 00150 std::complex<double> t1 = a2*a1; 00151 std::complex<double> t4 = a1*a1; 00152 std::complex<double> t5 = t4*a1; 00153 std::complex<double> t7 = a2*a2; 00154 std::complex<double> t14 = a3*a3; 00155 std::complex<double> t19 = sqrt(12.0*t7*a2-3.0*t7*t4-54.0*t1*a3+81.0*t14+12.0*a3*t5); 00156 std::complex<double> t22 = pow(36.0*t1-108.0*a3-8.0*t5+12.0*t19,div); 00157 00158 // Root# 1 00159 r1 = t22/6.0-6.0*(a2/3.0-t4/9.0)/t22-a1/3.0; 00160 00161 // common part for root# 2 and 3 00162 std::complex<double> t28 = (a2/3.0-t4/9.0)/t22; 00163 std::complex<double> t31 = sqrt(3.0); 00164 00165 // Root# 2 00166 //r2 = -t22/12.0+3.0*t28-a1/3.0+(1.0/2.0*sqrt(-1.0))*t31*(t22/6.0+6.0*t28); 00167 std::complex<double> st1 = t31*(t22/6.0+6.0*t28); 00168 std::complex<double> st2 = (sqrt(-1.0)); 00169 cout << st1 << ", " << st2 << endl; 00170 r2 = -t22/12.0+3.0*t28-a1/3.0+(1.0/2.0*sqrt(-1.0))*t31*(t22/6.0+6.0*t28); 00171 00172 // Root# 3 00173 //r3 = -t22/12.0+3.0*t28-a1/3.0+(-1.0/2.0*sqrt(-1.0))*t31*(t22/6.0+6.0*t28); 00174 r2 = -t22/12.0+3.0*t28-a1/3.0+(1.0/2.0*sqrt(-1.0))*t31*(t22/6.0+6.0*t28); 00175 00176 00177 // DEBUG: 00178 cout.precision( 10 ); 00179 // cout << "*x^3" << (a1>0 ? " + " : " - ") << fabs(a1) << "*x^2"<< (a1>0 ? " + " : " - ") 00180 // << fabs(a2) << "*x" << (a1>0 ? " + " : " - ") << fabs(a3) << "\n"; 00181 cout << "Root#1: " << r1 << " Root#2: " << r2 << " Root#3: " << r3 << "\n"; 00182 cout.precision( 6 ); 00183 00184 } // END FN: rootsOfCubicPolynomial()
| const double SP_Maths::PI = 3.141592654 |
Definition at line 27 of file sp_mathematics.h.
1.5.6