laguerre.cpp
上传用户:jtjnyq9001
上传日期:2014-11-21
资源大小:3974k
文件大小:2k
源码类别:

3G开发

开发平台:

Visual C++

  1. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. //
  3. //  File = laguerre.cpp
  4. //
  5. //  Laguerre method for finding polynomial roots
  6. //
  7. #include <math.h>
  8. #include <stdlib.h>
  9. #include <iostream>
  10. #include "laguerre.h"
  11. using namespace std;
  12. #ifdef _DEBUG
  13.   extern ofstream *DebugFile;
  14. #endif
  15. int LaguerreMethod( CmplxPolynomial *poly,
  16.                     std::complex<double> *root_ptr,
  17.                     double epsilon,
  18.                     double epsilon2,
  19.                     int max_iter)
  20. {
  21. int iter, j, order;
  22. complex<double> p_eval, p_p, p_p_p;
  23. complex<double> root, f, f_sq, g, rad;
  24. complex<double> f_p_r, f_m_r, delta_root;
  25. double old_delta_mag, root_mag, error;
  26. complex<double> *coeff;
  27. order = poly->GetDegree();
  28. coeff = new complex<double>[order+1];
  29. poly->CopyCoeffs(coeff);
  30. root = *root_ptr;
  31. old_delta_mag = 1000.0;
  32. for(iter=1; iter<=max_iter; iter++)
  33.   {
  34.   p_p_p = complex<double>(0.0,0.0);
  35.   p_p = complex<double>(0.0,0.0);
  36.   p_eval = coeff[order];
  37.   error = std::abs<double>(p_eval);
  38.   root_mag = std::abs<double>(root);
  39.   for( j=order-1; j>=0; j--)
  40.     {
  41.     p_p_p = p_p + root * p_p_p;
  42.     p_p = p_eval + root * p_p;
  43.     p_eval = coeff[j] + root * p_eval;
  44.     error = std::abs<double>(p_eval) + root_mag * error;
  45.     }
  46.   error = epsilon2 * error;
  47.   p_p_p = 2.0 * p_p_p;
  48.   if(std::abs<double>(p_eval) < error)
  49.     {
  50.     cout << "mag(p_eval) = " << std::abs<double>(p_eval) << "  error = "
  51.          << error << endl;
  52.     *root_ptr = root;
  53.     delete [] coeff;
  54.     return(1);
  55.     }
  56.   f = p_p/p_eval;
  57.   f_sq = f * f;
  58.   g = f_sq - p_p_p/p_eval;
  59.   rad = double(order-1)*(double(order) * g - f_sq);
  60.   rad = std::sqrt<double>(rad);
  61.   f_p_r = f + rad;
  62.   f_m_r = f - rad;
  63.   if( std::abs<double>(f_p_r) > std::abs<double>(f_m_r) )
  64.     {
  65.     delta_root = std::complex<double>(double(order), 0.0) / f_p_r;
  66.     }
  67.   else
  68.     {
  69.     delta_root = std::complex<double>(double(order), 0.0) / f_m_r;
  70.     }
  71.   root = root - delta_root;
  72.   if( (iter > 6) && (std::abs<double>(delta_root) > old_delta_mag) )
  73.     {
  74.     *root_ptr = root;
  75.     delete [] coeff;
  76.     return(2);
  77.     }
  78.   if( std::abs<double>(delta_root) < (epsilon * std::abs<double>(root)))
  79.     {
  80.     *root_ptr = root;
  81.     delete [] coeff;
  82.     return(3);
  83.     }
  84.   old_delta_mag = std::abs<double>(delta_root);
  85.   }
  86. #ifdef _DEBUG
  87.   *DebugFile << "Laguerre method failed to converge" << endl;
  88. #endif
  89. delete [] coeff;
  90. return(-1);
  91. }