libflame
12600
|
Functions | |
FLA_Error | FLA_Wilkshift_tridiag (FLA_Obj delta1, FLA_Obj epsilon, FLA_Obj delta2, FLA_Obj kappa) |
FLA_Error | FLA_Wilkshift_tridiag_ops (float delta1, float epsilon, float delta2, float *kappa) |
double | fla_dlapy2 (double x, double y) |
FLA_Error | FLA_Wilkshift_tridiag_opd (double delta1, double epsilon, double delta2, double *kappa) |
double fla_dlapy2 | ( | double | x, |
double | y | ||
) |
References FLA_Check_error_level(), FLA_Obj_datatype(), FLA_Wilkshift_tridiag_check(), FLA_Wilkshift_tridiag_opd(), and FLA_Wilkshift_tridiag_ops().
{ FLA_Datatype datatype; datatype = FLA_Obj_datatype( delta1 ); if ( FLA_Check_error_level() >= FLA_MIN_ERROR_CHECKING ) FLA_Wilkshift_tridiag_check( delta1, epsilon, delta2, kappa ); switch ( datatype ) { case FLA_FLOAT: { float* delta1_p = ( float* ) FLA_FLOAT_PTR( delta1 ); float* epsilon_p = ( float* ) FLA_FLOAT_PTR( epsilon ); float* delta2_p = ( float* ) FLA_FLOAT_PTR( delta2 ); float* kappa_p = ( float* ) FLA_FLOAT_PTR( kappa ); FLA_Wilkshift_tridiag_ops( *delta1_p, *epsilon_p, *delta2_p, kappa_p ); break; } case FLA_DOUBLE: { double* delta1_p = ( double* ) FLA_DOUBLE_PTR( delta1 ); double* epsilon_p = ( double* ) FLA_DOUBLE_PTR( epsilon ); double* delta2_p = ( double* ) FLA_DOUBLE_PTR( delta2 ); double* kappa_p = ( double* ) FLA_DOUBLE_PTR( kappa ); FLA_Wilkshift_tridiag_opd( *delta1_p, *epsilon_p, *delta2_p, kappa_p ); break; } } return FLA_SUCCESS; }
FLA_Error FLA_Wilkshift_tridiag_opd | ( | double | delta1, |
double | epsilon, | ||
double | delta2, | ||
double * | kappa | ||
) |
Referenced by FLA_Tevd_eigval_n_opd_var1(), FLA_Tevd_eigval_v_opd_var1(), FLA_Tevd_eigval_v_opd_var3(), FLA_Tevd_find_perfshift_opd(), and FLA_Wilkshift_tridiag().
{ double a = delta1; double c = epsilon; double d = delta2; double p, q, r, s, k; // Begin with kappa equal to d. k = d; // Compute a scaling factor to promote numerical stability. s = fabs( a ) + 2.0 * fabs( c ) + fabs( d ); if ( s == 0.0 ) return FLA_SUCCESS; // Compute q with scaling applied. q = ( c / s ) * ( c / s ); if ( q != 0.0 ) { // Compute p = 0.5*( a - d ) with scaling applied. p = 0.5 * ( ( a / s ) - ( d / s ) ); // Compute r = sqrt( p*p - q ). r = sqrt( p * p + q ); // If p*r is negative, then we need to negate r to ensure we use the // larger of the two eigenvalues. if ( p * r < 0.0 ) r = -r; // Compute the Wilkinson shift with scaling removed: // k = lambda_min + d // = d + lambda_min // = d + (-q / lambda_max) // = d - q / lambda_max // = d - q / (p + r) k = k - s * ( q / ( p + r ) ); /* // LAPACK method: p = 0.5 * ( ( a ) - ( d ) ) / c ; //r = sqrt( p * p + 1.0 ); r = fla_dlapy2( p, 1.0 ); if ( p < 0.0 ) r = -r; k = k - ( c / ( p + r ) ); */ } // Save the result. *kappa = k; return FLA_SUCCESS; }
FLA_Error FLA_Wilkshift_tridiag_ops | ( | float | delta1, |
float | epsilon, | ||
float | delta2, | ||
float * | kappa | ||
) |
Referenced by FLA_Wilkshift_tridiag().
{ float a = delta1; float c = epsilon; float d = delta2; float p, q, r, s, k; // Begin with kappa equal to d. k = d; // Compute a scaling factor to promote numerical stability. s = fabs( a ) + 2.0F * fabs( c ) + fabs( d ); if ( s == 0.0F ) return FLA_SUCCESS; // Compute q with scaling applied. q = ( c / s ) * ( c / s ); if ( q != 0.0F ) { // Compute p = 0.5*( a - d ) with scaling applied. p = 0.5F * ( ( a / s ) - ( d / s ) ); // Compute r = sqrt( p*p - q ). r = sqrt( p * p + q ); // If p*r is negative, then we need to negate r to ensure we use the // larger of the two eigenvalues. if ( p * r < 0.0F ) r = -r; // Compute the Wilkinson shift with scaling removed: // k = lambda_min + d // = d + lambda_min // = d + (-q / lambda_max) // = d - q / lambda_max // = d - q / (p + r) k = k - s * ( q / ( p + r ) ); } // Save the result. *kappa = k; return FLA_SUCCESS; }