home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_11_09 / cordic.cpp < prev    next >
C/C++ Source or Header  |  1993-02-28  |  5KB  |  191 lines

  1. //CORDIC.CPP  the implementation of methods prototyped in CORDIC.H
  2.  
  3. #include "CORDIC.HPP"
  4.  
  5. #define TEST
  6.  
  7.  
  8.                 //define static members declared in the class declaration
  9. int cordic::ArcTan[NBits];  //array of integer arcTan's
  10. int cordic::xInit = 0;          //length of initial vector
  11. int cordic::instance = 0;             //previous instance of CORDIC?
  12. long cordic::CordicBase = 0;
  13. long cordic::HalfBase = 0;
  14. long cordic::Quad2Boundary = 0;
  15. long cordic::Quad3Boundary = 0;
  16.  
  17.                 //define a handy constant
  18. const long sixtyfourK = 0x10000;
  19.  
  20.  
  21. void cordic::cordic(void) //constructor:  initializes statics for use later
  22. {
  23.     if(!instance)          //only one instance
  24.     {
  25.         int i;                //index arcTan[]
  26.         double f;             //calc initial x projection
  27.         long powr;        //calc powers of 2 up to 2^(2*(NBits-1))
  28.  
  29.         CordicBase = 1 << NBits;      //(* 2^NBits)
  30.         HalfBase = CordicBase >> 1;   //(/2)
  31.         Quad2Boundary = CordicBase << 1;
  32.         Quad3Boundary = CordicBase + Quad2Boundary;
  33.  
  34.         //a diminishing series of ArcTan's
  35.         powr = 1;
  36.         for(i = 0; i < NBits; i ++)
  37.         {
  38.             ArcTan[i] = int(atan(1.0/powr)/(M_PI/2)*CordicBase + 0.5);
  39.             powr <<= 1;
  40.         }
  41.  
  42.         //figure the starting x by compensating for elongation during the
  43.         //expansion of the series.
  44.         f = 1.0;
  45.         powr = 1;
  46.         for (i = 0;i < NBits;i++)
  47.         {
  48.             f = (f * (powr + 1)) / powr;
  49.             powr <<= 2;                     //even powers of 2
  50.         }
  51.         f = 1.0/sqrt(f);
  52.         xInit = int(CordicBase * f + 0.5);
  53.     }// if(!instance)
  54.     instance ++;
  55. }//cordic::cordic()
  56.  
  57. cordic::~cordic()  //destructor--does nothing in this implementation
  58. {
  59.     if(!--instance){}
  60. }
  61.  
  62. long cordic::cordicbase(void) { return CordicBase;}
  63.  
  64. //the following routine takes input only in positive cordic angle units
  65. //within the first 64K(once around the circle)
  66. void cordic::sinCos(unsigned long theta, int &sin, int &cos)    // input in cordic Units
  67. {
  68.     int quadrant;     //quadrant of input theta
  69.     int z;            //theta in the first quadrant
  70.     int i;            //index vector rotations
  71.     int x, y, x1, y1; //projections before and after rotation
  72.  
  73.     //determine quadrant of input angle theta, translate to 1st quadrant,
  74.     //recording original quadrant for adjusting sign at end of computation
  75.     if(theta < CordicBase)
  76.     {
  77.         quadrant = Quad1;
  78.         z = int(theta);
  79.     }
  80.     else if(theta < Quad2Boundary)
  81.     {
  82.         quadrant = Quad2;
  83.         z = int(Quad2Boundary - theta);
  84.     }
  85.     else if(theta < Quad3Boundary)
  86.     {
  87.         quadrant = Quad3;
  88.         z = int(theta - Quad2Boundary);
  89.     }
  90.     else
  91.     {
  92.         quadrant = Quad4;
  93.         z = - int(theta);
  94.     }
  95.  
  96.     //initialize the projections on the x and y axes
  97.     x = xInit;
  98.     y = 0;
  99.  
  100.     //negate z so target angle will be 0 while vector rotates in 1st quad.
  101.     z = -z;
  102.  
  103.     //rotate nBits times.
  104.     for(i = 0;i < NBits; i++)
  105.     {
  106.         if(z < 0)
  107.         {
  108.             //Counterclockwise rotation
  109.             z += ArcTan[i];
  110.             y1 = y + (x >> i);
  111.             x1 = x - (y >> i);
  112.         }
  113.         else
  114.         {
  115.             //Clockwise rotation
  116.             z -= ArcTan[i];
  117.             y1 = y - (x >> i);
  118.             x1 = x + (y >> i);
  119.         }
  120.  
  121.         //put new projections into old for next iter.
  122.         x = x1;
  123.         y = y1;
  124.     }// for i = 0 .. nBits
  125.  
  126.     //determine sign based on quadrant
  127.     cos = (quadrant == Quad1 || quadrant == Quad4) ? x : -x;
  128.     sin = (quadrant == Quad1 || quadrant == Quad2) ? y : -y;
  129. }//cordic::sinCos(long, int, int)
  130.  
  131.  
  132. //this function takes inputs in cordic angle units greater than 64K, and
  133. //less than 0, up to the size of long
  134. void cordic::sinCos(long theta, int &sin, int &cos) //input of any long
  135. {
  136.     theta %= sixtyfourK;
  137.     if(theta < 0)
  138.         theta += sixtyfourK;
  139.     sinCos((unsigned long)theta, sin, cos); //1st ver. of sinCos does the work
  140. }
  141. //takes input in positive or negative radians
  142. void cordic::sinCos(float theta, int &sin, int &cos)   // input in Radians
  143. {
  144.     long CordicTheta;
  145.     CordicTheta = long((theta / (2 * M_PI)) * sixtyfourK);
  146.     sinCos(CordicTheta, sin, cos);  //second version of sinCos does the work
  147. }
  148.  
  149. //define predefined instance
  150. cordic cord;
  151.  
  152.  
  153. #ifdef TEST
  154. #include <iostream.h>
  155. int main()
  156. {
  157.     unsigned long thetau;
  158.     long theta;
  159.     float thetaf;
  160.     int sine, cosine;
  161.     cout << endl << "The unsigned long version: " << endl;
  162.     for(thetau = 0;thetau <= sixtyfourK; thetau += 300)
  163.     {
  164.         cord.sinCos(thetau, sine, cosine);
  165.         cout << thetau << "  "
  166.                 << sine << "  "
  167.                 << cosine << endl;
  168.     }//for(thetau...)
  169.     cout << endl << "The long version: " << endl;
  170.     for(theta = - sixtyfourK / 2;theta <= sixtyfourK * 2 ; theta += 800)
  171.     {
  172.         cord.sinCos(theta, sine, cosine);
  173.         cout << theta << "  "
  174.                 << sine << "  "
  175.                 << cosine << endl;
  176.     }//for(theta...)
  177.     cout << endl << "The float version: " << endl;
  178.     thetaf = 0;
  179.     for(theta = 0;theta <= 360 ; theta++)
  180.     {
  181.         cord.sinCos(thetaf, sine, cosine);
  182.         cout << (thetaf * 180 / M_PI) << "  "
  183.                 << sine << "  "
  184.                 << cosine << endl;
  185.         thetaf += (2 * M_PI)/360;
  186.     }//for(theta...)  thetaf
  187.     return 0;
  188. }
  189.  
  190.  
  191. #endif //TEST