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

3G开发

开发平台:

Visual C++

  1. //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2. //
  3. //  File = cmpxpoly.cpp
  4. //
  5. //
  6. #include <math.h>
  7. #include "cmpxpoly.h"
  8. #include "laguerre.h"
  9. #include "pause.h"
  10. #include "stdlib.h"
  11. #include "psstream.h"
  12. #include <iostream>
  13. using std::complex;
  14. extern PracSimStream ErrorStream;
  15. extern PracSimStream DetailedResults;
  16. //======================================================
  17. //  default constructor
  18. CmplxPolynomial::CmplxPolynomial( )
  19. {
  20.    Poly_Degree = 0;
  21.    Poly_Coeff = new complex<double>[1];
  22.    Poly_Coeff[0] = complex<double>( 0.0, 0.0);
  23.    RemCoeff = NULL;
  24.    Root = NULL;
  25.    return;
  26. };
  27. //======================================================
  28. //  copy constructor
  29. CmplxPolynomial::CmplxPolynomial( 
  30.                      const CmplxPolynomial& original )
  31. {
  32.    int i;
  33.    Poly_Degree = original.Poly_Degree;
  34.    Poly_Coeff = new complex<double>[Poly_Degree+1];
  35.    for( i=0; i<=Poly_Degree; i++)
  36.       Poly_Coeff[i] = original.Poly_Coeff[i];
  37.    if(original.Root != NULL){
  38.       Root = new complex<double>[Poly_Degree];
  39.       for( i=0; i<Poly_Degree; i++)
  40.          Root[i] = original.Root[i];
  41.    }
  42.    return;
  43. };
  44. //======================================================
  45. //  constructor for initializing a binomial
  46. CmplxPolynomial
  47.          ::CmplxPolynomial( const complex<double> coeff_1,
  48.                             const complex<double> coeff_0 )
  49. {
  50.    Poly_Degree = 1;
  51.    Poly_Coeff = new complex<double>[2];
  52.    RemCoeff = NULL;
  53.    Root = NULL;
  54.    Poly_Coeff[0] = coeff_0;
  55.    Poly_Coeff[1] = coeff_1;
  56.    return;
  57. }
  58. //======================================================
  59. //   initializing constructor - complex coeff
  60. CmplxPolynomial
  61.             ::CmplxPolynomial( const int degree,
  62.                                const complex<double> *coeff)
  63. {
  64.    Poly_Degree = degree;
  65.    Poly_Coeff = new complex<double>[degree+1];
  66.    RemCoeff = NULL;
  67.    Root = NULL;
  68.    for(int i=0; i<=degree; i++) Poly_Coeff[i] = coeff[i]; 
  69.    return;
  70. }
  71. //======================================================
  72. //   initializing constructor - real coeff
  73. CmplxPolynomial
  74.             ::CmplxPolynomial( const double *coeff,
  75.                                const int degree )
  76. {
  77.    Poly_Degree = degree;
  78.    Poly_Coeff = new complex<double>[degree+1];
  79.    RemCoeff = NULL;
  80.    Root = NULL;
  81.    for(int i=0; i<=degree; i++) 
  82.             Poly_Coeff[i] = complex<double>(coeff[i],0.0);
  83.    return;
  84. };
  85. //======================================================
  86. //  assignment operator
  87. CmplxPolynomial& CmplxPolynomial
  88.             ::operator= (const CmplxPolynomial& right)
  89. {
  90.    if (Poly_Coeff != right.Poly_Coeff){
  91.       //------------------------------------------------
  92.       // Get rid of old coefficient array to make way 
  93.       // for a new one of the correct length for the 
  94.       // new polynomial being assigned 
  95.       delete [] Poly_Coeff;
  96.       delete [] Root;
  97.       Poly_Degree = right.Poly_Degree;
  98.       Poly_Coeff = new complex<double>[Poly_Degree+1];
  99.       for( int i=0; i<=Poly_Degree; i++)
  100.                         Poly_Coeff[i] = right.Poly_Coeff[i];
  101.    }
  102.    if(right.Root != NULL){
  103.       Root = new complex<double>[Poly_Degree];
  104.       int i;
  105.       for( i=0; i<Poly_Degree; i++)
  106.                         Root[i] = right.Root[i];
  107.    }
  108.    return *this;
  109. }
  110. //======================================================
  111. // multiply assign operator        
  112. CmplxPolynomial& CmplxPolynomial
  113.          ::operator*= (const CmplxPolynomial &right)
  114. {
  115.    //---------------------------------------------------
  116.    // save pointer to original coefficient array so that
  117.    // this array can be deleted once no longer needed
  118.    complex<double> *orig_coeff = Poly_Coeff;
  119.    int orig_degree = Poly_Degree;
  120.    //---------------------------------------------------
  121.    // create new longer array to hold the new coeff 
  122.    Poly_Degree += right.Poly_Degree;
  123.    Poly_Coeff = new complex<double>[Poly_Degree+1];
  124.    for( int i=0; i<=Poly_Degree; i++)
  125.                   Poly_Coeff[i] = complex<double>(0.0, 0.0);
  126.    //---------------------------------
  127.    //  perform multiplication
  128.    for(  int rgt_indx=0; 
  129.             rgt_indx<= right.Poly_Degree; rgt_indx++){
  130.       for( int orig_indx=0; 
  131.                orig_indx <= orig_degree; orig_indx++){
  132.          Poly_Coeff[orig_indx+rgt_indx] +=
  133.             (orig_coeff[orig_indx] * 
  134.             right.Poly_Coeff[rgt_indx]);
  135.       }
  136.    }
  137.    return *this;
  138. }    
  139. //======================================================
  140. // divide assign operator        
  141. CmplxPolynomial& CmplxPolynomial
  142.          ::operator/= (const CmplxPolynomial &divisor)
  143. {
  144.  //----------------------------------------------------
  145.  //  In general, polynomial division will produce a
  146.  //  quotient and a remainder.  This routine returns
  147.  //  the quotient as its result.  The remainder will be
  148.  //  stored in a member variable so that it can be
  149.  //  checked or retrived by subsequent calls to the
  150.  //  appropriate member functions.
  151.  //-----------------------------------------------------
  152.  // save pointer to original coefficient array so that 
  153.  // this array can be deleted once no longer needed
  154.  
  155.  int dvdnd_deg, dvsr_deg, j, k;
  156.  
  157.  //-----------------------------------------------------
  158.  //  create new array to hold the new coefficients 
  159.  
  160.  if(RemCoeff == NULL) RemCoeff = 
  161.                         new std::complex<double>[Poly_Degree+1];
  162.  dvdnd_deg = Poly_Degree;
  163.  dvsr_deg = divisor.Poly_Degree;
  164.  Poly_Degree -= dvsr_deg;
  165.    
  166.  //---------------------------------
  167.  //  perform division
  168.  
  169.   for(j=0; j<=dvdnd_deg; j++){
  170.     RemCoeff[j] = Poly_Coeff[j];
  171.     Poly_Coeff[j] = complex<double>(0.0,0.0);
  172.     }
  173.   for( k=dvdnd_deg-dvsr_deg; k>=0; k--){
  174.     Poly_Coeff[k] = RemCoeff[dvsr_deg+k]/
  175.                      divisor.Poly_Coeff[dvsr_deg];
  176.     for(j=dvsr_deg+k-1; j>=k; j--)
  177.       RemCoeff[j] -= Poly_Coeff[k]*divisor.Poly_Coeff[j-k];
  178.     }
  179.  for(j=dvsr_deg; j<=dvdnd_deg; j++)
  180.                 RemCoeff[j] = complex<double>(0.0,0.0);
  181.  return *this;
  182. //======================================================
  183. //  Find roots of polynomial
  184. void CmplxPolynomial::FindRoots( void )
  185. {
  186.    complex<double>* root;
  187.    int status, i;
  188.    CmplxPolynomial root_factor;
  189.    root = new complex<double>[Poly_Degree];
  190.    CmplxPolynomial work_poly;
  191.    double epsilon=0.0000001;
  192.    double epsilon2=1.0e-10;
  193.    int max_iter=12;
  194.    if(Root == NULL) Root = new complex<double>[Poly_Degree];
  195.    //------------------------------------------------
  196.    // find coarse locations for roots
  197.    work_poly = CmplxPolynomial(Poly_Degree, Poly_Coeff);
  198.    for(i=0; i<Poly_Degree-1; i++){
  199.       Root[i] = complex<double>(0.0,0.0);
  200.       status = LaguerreMethod( &work_poly, &(Root[i]),
  201.                      epsilon, epsilon2, max_iter);
  202.       if(status <0) {
  203.          ErrorStream 
  204.             << "Laguerre method did not converge"
  205.             << endl;
  206.          exit(75);
  207.       }
  208.       root_factor = 
  209.          CmplxPolynomial( complex<double>(1.0,0.0),-Root[i]);
  210.       work_poly /= root_factor;
  211.       work_poly.DumpToStream(&cout);
  212.       pause();
  213.    }
  214.    Root[Poly_Degree-1] = -(work_poly.GetCoeff(0));
  215.    //------------------------------------------------
  216.    //  polish the roots
  217.    work_poly = CmplxPolynomial(Poly_Degree, Poly_Coeff);
  218.    for(i=0; i<Poly_Degree; i++){
  219.       status = LaguerreMethod( &work_poly, &(Root[i]), 
  220.          epsilon, epsilon2, max_iter);
  221.       if(status <0) {
  222.          ErrorStream 
  223.             << "Laguerre method did not converge" 
  224.             << endl;
  225.          exit(76);
  226.       }
  227.       DetailedResults << "Polished Root[" << i 
  228.          << "] = (" 
  229.          << Root[i].real() << ", " 
  230.          << Root[i].imag() << ") " 
  231.          << " (" << status << ")" << endl;
  232.       pause();
  233.    }
  234.    return;
  235. }
  236. //======================================================
  237. //  Get array of polynomial root values
  238. complex<double> *CmplxPolynomial::GetRoots( void )
  239. {
  240.    complex<double>* root;
  241.    int i;
  242.    root = new complex<double>[Poly_Degree];
  243.    if(Root == NULL) this->FindRoots();
  244.    for(i=0; i<Poly_Degree; i++) root[i] = Root[i];
  245.    return(root);
  246. }
  247. //======================================================
  248. //  reflect root across the unit circle
  249. void CmplxPolynomial::ReflectRoot( int root_idx )
  250. {
  251.    FindRoots();
  252.    Root[root_idx] = complex<double>(1.0,0.0)/Root[root_idx];
  253.    //BuildFromRoots();
  254. }
  255. //======================================================
  256. //
  257. int CmplxPolynomial::GetDegree(void)
  258. {
  259.    return(Poly_Degree);
  260. }
  261. //======================================================
  262. //
  263. complex<double> CmplxPolynomial::GetCoeff(int k)
  264. {
  265.    return Poly_Coeff[k];
  266. }
  267. //======================================================
  268. //
  269. void CmplxPolynomial::CopyCoeffs(complex<double> *coeff)
  270. {
  271.    for(int i=0; i<=Poly_Degree; i++) coeff[i] = Poly_Coeff[i];
  272.    return;
  273. }
  274. //======================================================
  275. //  dump polynomial to an output stream
  276. void CmplxPolynomial::DumpToStream( ostream* output_stream)
  277. {
  278.  (*output_stream) << "Poly_Degree = " << Poly_Degree << endl;
  279.  
  280.  for(int i=Poly_Degree; i>=0; i--)
  281.    {
  282.     (*output_stream) << "Poly_Coeff[" << i << "] = " 
  283.                      << Poly_Coeff[i].real() << ", "
  284.                      << Poly_Coeff[i].imag() << endl;
  285.    }
  286.  return;
  287. }  
  288. //---------------------------------
  289. //  force desired instantiations