Main Page   Namespace List   Compound List   File List   Compound Members   File Members  

copy-ocsTools.cc

Go to the documentation of this file.
00001 // $Id: ocsTools.cc,v 1.35 2002/06/21 00:52:26 lima Exp $
00002 // #####################################################################
00003 //
00004 //    ocsTools.cc
00005 //
00006 //    Functions from several authors and external libraries. 
00007 //
00008 //    Copyright:
00009 //       Optical Fiber Communications Laboratory (OFCL)
00010 //       Computer Science & Electrical Engineering Department (CSEE)
00011 //       University of Maryland Baltimore County (UMBC)
00012 //
00013 //    The copyright applies to functions written in the OFCL members
00014 // #####################################################################
00015 
00016 #include "ocsTools.hh"
00017 #include "ocsConst.hh"
00018 
00019 extern ofstream LogFile;
00020 
00021 
00022 // #################################################################
00023 // #################################################################
00024 
00025 // Functions written by Ivan Lima Jr.
00026 
00027 
00028 //########################################################
00029 //## Get the radius of a circle that contains three points
00030 //#  in the 3-dimensional space (x,y,z), returns the 
00031 //#  central point and, more importantly, returns the 
00032 //#  vector that is normal to the circle whose length
00033 //#  is equal to the total arc length.
00034 //#  It will be used as a penalty extraction to feedback
00035 //#  the PMD compensator.
00036 //## By: Ivan Lima
00037 double GetRadiusCircle(double *PointA, double *PointB, double *PointC)
00038 {
00039    double vectorAB[4];
00040    double vectorBC[4];
00041    double vectorABxBC[4];
00042    double **matrixA = dmatrix(1,3,1,3);
00043    double **matrixB = dmatrix(1,3,1,1);   
00044 
00045    for (int ii = 1; ii < 4; ii++) {   
00046       vectorAB[ii] = PointB[ii] - PointA[ii];
00047       vectorBC[ii] = PointC[ii] - PointB[ii];      
00048       vectorABxBC[ii] = vectorBC[ii];
00049    }   
00050 
00051    CrossProduct(vectorAB, vectorABxBC, 1);
00052 
00053  
00054    for (int ii = 1; ii < 4; ii++) {
00055       matrixA[1][ii] = vectorAB[ii];
00056       matrixA[2][ii] = vectorBC[ii];      
00057       matrixA[3][ii] = vectorABxBC[ii];   
00058       matrixB[ii][1] = 0;            
00059    }   
00060    
00061    for (int ii = 1; ii < 4; ii++) {
00062       matrixB[1][1] += vectorAB[ii]*(PointA[ii]+PointB[ii])/2.;   
00063       matrixB[2][1] += vectorBC[ii]*(PointB[ii]+PointC[ii])/2.;
00064       matrixB[3][1] += vectorABxBC[ii]*PointB[ii]; 
00065    }  
00066       
00067    //## Now solve X from A*X = B
00068    //#  where X is a vector at the center of the circle
00069    gaussj(matrixA,3,matrixB,1);
00070 
00071    double PointCenter[4];
00072    for (int ii = 1; ii < 4; ii++) {  
00073       PointCenter[ii] = matrixB[ii][1];
00074    }
00075    
00076    //## Lines for debugging purpose  
00077    cout << "DistA_Center "
00078         << GetDistance2Points(PointA,PointCenter,1) << endl;
00079    cout << "DistB_Center "
00080         << GetDistance2Points(PointB,PointCenter,1) << endl;
00081    cout << "DistC_Center "
00082         << GetDistance2Points(PointC,PointCenter,1) << endl;        
00083    //## End of line for debugging purposes
00084    
00085    //## The central point will return in PointC
00086    //## The vector that is normal to the circle 
00087    //#  is returned in PointA. In order to 
00088    //#  obtain the polarization dispersion vector 
00089    //#  from it one needs to divide it by the 
00090    //#  frequency difference (in Hz) between the original
00091    //#  PointA and PointC.
00092    //## The Polarization dispersion vector will 
00093    //#  return in PointA, but it has to be 
00094    //#  divided by the frequency difference between
00095    //#  PointA and PointC. It must be done by the user.
00096    
00097    double vectorCenterA[4];
00098    double vectorCenterB[4];   
00099    double vectorCenterC[4];   
00100    for (int ii = 1; ii < 4; ii++) {   
00101       vectorCenterA[ii] = PointA[ii] - PointCenter[ii];
00102       vectorCenterB[ii] = PointB[ii] - PointCenter[ii];
00103       vectorCenterC[ii] = PointC[ii] - PointCenter[ii];            
00104    }      
00105    double Radius = GetDistance2Points(PointB,PointCenter,1); 
00106    double ArcLength;
00107    ArcLength = Radius*( 
00108                acos( vectorCenterA[1]*vectorCenterB[1]
00109                     +vectorCenterA[2]*vectorCenterB[2]
00110                     +vectorCenterA[3]*vectorCenterB[3] )
00111               +acos( vectorCenterB[1]*vectorCenterC[1]
00112                     +vectorCenterB[2]*vectorCenterC[2]
00113                     +vectorCenterB[3]*vectorCenterC[3] ) );    
00114    
00115 
00116    //## Set the values to be returned   
00117    for (int ii = 1; ii < 4; ii++) {  
00118       PointC[ii] = PointCenter[ii];
00119       if ( sq(vectorABxBC[1])
00120           +sq(vectorABxBC[2])
00121           +sq(vectorABxBC[3]) != 0 ) { 
00122          PointA[ii] = vectorABxBC[ii]
00123                      /sqrt( sq(vectorABxBC[1])
00124                            +sq(vectorABxBC[2])
00125                            +sq(vectorABxBC[3]) )
00126                      *ArcLength/(2*pi);      
00127       }               
00128       else {
00129         PointA[ii] = 0;
00130       }          
00131    }      
00132    
00133 
00134         
00135    return Radius;     
00136 }
00137 
00138 //####  Returns the distance between 2 points in 3 dimensions
00139 //## By: Ivan Lima
00140 double GetDistance2Points(double *PointA, double *PointB, int FirstCoord)
00141 {
00142    double Distance = 0;
00143    for (int ii = 0; ii < 3; ii++) {     
00144       Distance += sq(PointA[ii+FirstCoord] - PointB[ii+FirstCoord]);
00145    }
00146    return sqrt(Distance);   
00147 }
00148 
00149 
00150 //#### This function takes care of the periodicity of the value ii
00151 //##   The value of ii must be between (-Periodicity) and (2*Periodicity-1)
00152 //##   The result is a value between 0 and (Periodicity-1)
00153 //## By: Aurenice Lima
00154 int Periodicity(int ii, int Periodicity)
00155 {
00156    int nn;
00157    if (ii < 0)
00158       nn = Periodicity + ii;
00159    else if (ii >= Periodicity)
00160       nn = ii - Periodicity;   
00161    else
00162       nn = ii;         
00163    return nn;  
00164 }
00165 
00166 
00167 //## It produces the angles and the matrices that rotates the 
00168 //#  vector to (-1,0,0)
00169 //## By: Ivan Lima
00170 void TransRzRyV3to_Xhat( double *Vector, double *thetaZthetaY)
00171 //                        ,double Rotation[][3])
00172 {
00173    double delta,gamma;                              
00174    //double Ry[3][3], Rz[3][3];
00175 
00176    //cout<<"Trans "<<Vector[0]<<" "<<Vector[1]<<" "<<Vector[2]<<endl;      
00177    
00178    if (Vector[0] != 0)  
00179       delta = atan(Vector[2]/Vector[0]); 
00180    else 
00181       delta = pi/2.; 
00182    RotatesAboutY(delta,Vector); //,Ry); //## 01/11/27
00183    if (Vector[0] < 0)  
00184       gamma = 1/2.*atan(Vector[1]/Vector[0]);  
00185    else if (Vector[0] > 0)   {      
00186       if (atan(Vector[1]/Vector[0]) < 0) 
00187          gamma = 1/2.*(atan(Vector[1]/Vector[0]) + pi );
00188       else
00189          gamma = 1/2.*(atan(Vector[1]/Vector[0]) - pi );               
00190    }      
00191    else {
00192       if (Vector[1] > 0) 
00193          gamma = -pi/4;
00194       else
00195          gamma =  pi/4;       
00196    }      
00197    RotatesAboutZ(2*gamma,Vector); //,Rz); 
00198 
00199    thetaZthetaY[0] = 2*gamma; // ## Rz       
00200    thetaZthetaY[1] = delta;   // ## Ry   
00201         
00202    //cout<<"Trans "<<Vector[0]<<" "<<Vector[1]<<" "<<Vector[2]<<endl;       
00203    //Multiply(Rotation,Rz,Ry);     
00204 }
00205 
00206 
00207 //## It produces the angles and the matrices that rotates the 
00208 //#  vector to (0, y, z > 0)
00209 //## By: Ivan Lima
00210 void TransRyV3to_YZ( double *Vector, double *thetaY)
00211 {
00212    double delta;                              
00213 
00214    //cout<<"Trans "<<Vector[0]<<" "<<Vector[1]<<" "<<Vector[2]<<endl;      
00215    if (Vector[2] != 0)  {
00216       delta = -atan(Vector[0]/Vector[2]); 
00217    }   
00218    else {
00219       delta = -sgn(Vector[0])*pi/2.; 
00220    }   
00221    if (Vector[2] < 0 ) {
00222       delta += -pi;
00223     }  
00224       
00225    RotatesAboutY(delta,Vector); //,Ry);
00226 
00227    *thetaY = delta;   // ## Ry   
00228    //cout<<"Trans "<<Vector[0]<<" "<<Vector[1]<<" "<<Vector[2]<<endl;       
00229    //Multiply(Rotation,Rz,Ry);     
00230 }
00231 
00232 
00233 //## Transforms from (vx,vy,vz) to (-1,0,0) 
00234 //## Returning the angles and the Trans. Matrix RzRx
00235 //## This method should be replaced by the one where the
00236 //## two angles are separate scalar quantities (not a vector)
00237 //## By: Ivan Lima
00238 void TransRzRxV3to_Xhat( double *Vector, double *thetaZthetaX)
00239 //                    ,double Rotation[][3])
00240 {
00241 
00242    double thetaZ;
00243    double thetaX;
00244    TransRzRxV3to_Xhat( Vector, &thetaZ, &thetaX);
00245    thetaZthetaX[0] = thetaZ; // ## Rz angle       
00246    thetaZthetaX[1] = thetaX;   // ## Rx angle    
00247 /*
00248    double delta,gamma;                                 
00249    
00250    //double Rx[3][3], Rz[3][3];
00251 
00252    //cout<<"Trans "<<Vector[0]<<" "<<Vector[1]<<" "<<Vector[2]<<endl;      
00253    if (Vector[1] != 0)  
00254       delta = atan(Vector[2]/Vector[1]); 
00255    else 
00256       delta = pi/2.; 
00257    RotatesAboutX(delta,Vector); //,Rx);
00258    if (Vector[0] < 0)  
00259       gamma = 1/2.*atan(Vector[1]/Vector[0]);  
00260    else if (Vector[0] > 0)   {      
00261       if (atan(Vector[1]/Vector[0]) < 0) 
00262          gamma = 1/2.*(atan(Vector[1]/Vector[0]) + pi );
00263       else
00264          gamma = 1/2.*(atan(Vector[1]/Vector[0]) - pi );               
00265    }      
00266    else {
00267       if (Vector[1] > 0) 
00268          gamma = -pi/4;
00269       else
00270          gamma =  pi/4;       
00271    }      
00272    RotatesAboutZ(2*gamma,Vector); //,Rz); 
00273 
00274    thetaZthetaX[0] = 2*gamma; // ## Rz angle       
00275    thetaZthetaX[1] = delta;   // ## Rx angle    
00276    //cout<<"Trans "<<Vector[0]<<" "<<Vector[1]<<" "<<Vector[2]<<endl;       
00277    //Multiply(Rotation,Rz,Rx);     
00278 */   
00279 }   
00280 
00281 
00282 
00283 
00284 
00285 //## Transforms from (vx,vy,vz) to (-1,0,0) 
00286 //## Returning the angles and the Trans. Matrix RzRx
00287 //## By: Ivan Lima
00288 void TransRzRxV3to_Xhat( double *Vector, double *thetaZ, double *thetaX)
00289 //                    ,double Rotation[][3])
00290 {
00291    double delta,gamma;                              
00292 
00293    //cout<<"Trans "<<Vector[0]<<" "<<Vector[1]<<" "<<Vector[2]<<endl;      
00294    if (Vector[1] != 0)  
00295       delta = atan(Vector[2]/Vector[1]); 
00296    else 
00297       delta = pi/2.; 
00298    RotatesAboutX(delta,Vector); //,Rx);
00299    if (Vector[0] < 0)  
00300       gamma = 1/2.*atan(Vector[1]/Vector[0]);  
00301    else if (Vector[0] > 0)   {      
00302       if (atan(Vector[1]/Vector[0]) < 0) 
00303          gamma = 1/2.*(atan(Vector[1]/Vector[0]) + pi );
00304       else
00305          gamma = 1/2.*(atan(Vector[1]/Vector[0]) - pi );               
00306    }      
00307    else {
00308       if (Vector[1] > 0) 
00309          gamma = -pi/4;
00310       else
00311          gamma =  pi/4;       
00312    }      
00313    RotatesAboutZ(2*gamma,Vector); //,Rz); 
00314 
00315    *thetaZ = 2*gamma; // ## Rz angle       
00316    *thetaX = delta;   // ## Rx angle    
00317    //cout<<"Trans "<<Vector[0]<<" "<<Vector[1]<<" "<<Vector[2]<<endl;       
00318    //Multiply(Rotation,Rz,Rx);     
00319 }   
00320 
00321 
00322 
00323 
00324 
00325 
00326 
00327 
00328 
00329 //## Solve the 3x3 multiplication: Right3x3 = Left3x3*Right3x3
00330 //## By: Ivan Lima
00331 void Multiply( double Left[][3], double Right[][3])
00332 {
00333    double RightTmp[3][3];
00334    for (int ii = 0; ii < 3; ii++) {
00335       for (int jj = 0; jj < 3; jj++) {
00336          RightTmp[ii][jj] = Right[ii][jj];             
00337       }   
00338    }   
00339    for (int ii = 0; ii < 3; ii++) {
00340       for (int jj = 0; jj < 3; jj++) {
00341          for (int kk = 0; kk < 3; kk++) {
00342             Right[ii][jj] += Left[ii][kk]*RightTmp[kk][jj];             
00343          }   
00344          //cout << "  "<<  ii << " " << jj << "  " << Left[ii][jj] << endl;          
00345          //cout << "  "<<  ii << " " << jj << "  " << Right[ii][jj] << endl;          
00346          //cout << ii << " " << jj << "  " << Result[ii][jj] << endl;          
00347       }   
00348    }   
00349 }
00350 
00351 
00352 //## Solve the matrix3x3 vector multipl.: Right3 = Left3x3*Right3
00353 //## By: Ivan Lima
00354 void Multiply(double Left[][3],double Right[3])
00355 {
00356    double RightTmp[3];
00357    for (int ii = 0; ii < 3; ii++)
00358       RightTmp[ii] = Right[ii];
00359    for (int ii = 0; ii < 3; ii++) {   
00360       Right[ii] = 0;
00361       for (int jj = 0; jj < 3; jj++) {
00362          Right[ii] += Left[ii][jj]*RightTmp[jj];             
00363       }   
00364   }       
00365 }
00366 
00367 //## Make the CrossProduct
00368 
00369 //## The result will be returned in Right
00370 //## By: Ivan Lima
00371 void CrossProduct(double *Left, double *Right, int FirstCoord)
00372 {
00373    //## FirstCoord determines where the vector starts
00374    //#  0 -> 0,1,2
00375    //#  1 -> 1,2,3
00376    double RightTmp[4];
00377    for (int ii = 0; ii < 3; ii++) {
00378       RightTmp[ii+FirstCoord] = Right[ii+FirstCoord];
00379    }
00380    Right[0+FirstCoord] = Left[1+FirstCoord]*RightTmp[2+FirstCoord] 
00381                       -Left[2+FirstCoord]*RightTmp[1+FirstCoord];
00382    Right[1+FirstCoord] = Left[2+FirstCoord]*RightTmp[0+FirstCoord] 
00383                       -Left[0+FirstCoord]*RightTmp[2+FirstCoord];
00384    Right[2+FirstCoord] = Left[0+FirstCoord]*RightTmp[1+FirstCoord] 
00385                       -Left[1+FirstCoord]*RightTmp[0+FirstCoord];   
00386 }
00387 
00388 
00389 //## Rotates about Z
00390 //## By: Ivan Lima
00391 void RotatesAboutZ(double angle, double *Vector) //, double Rz[][3])
00392 {
00393 
00394    double Rz[3][3];
00395    //for (int ii=0; ii < 3; ii++)
00396    //   for (int jj = 0; jj < 3; jj++)
00397    //      Rz[ii][jj] = 0;    
00398    Rz[0][0] =  cos(angle);   Rz[0][1] =  sin(angle);
00399    Rz[1][0] = -sin(angle);   Rz[1][1] =  cos(angle);
00400    //Rz[2][2] = 1.;
00401    
00402    double tmpVector[3];
00403    tmpVector[0] = Vector[0];
00404    tmpVector[1] = Vector[1];    
00405    Vector[0] = Rz[0][0]*tmpVector[0] + Rz[0][1]*tmpVector[1];
00406    Vector[1] = Rz[1][0]*tmpVector[0] + Rz[1][1]*tmpVector[1];      
00407 }
00408 
00409 
00410 //## Rotates about X
00411 //## By: Ivan Lima
00412 void RotatesAboutX(double angle, double *Vector) //, double Rx[][3])
00413 {    
00414    double Rx[3][3];
00415    //for (int ii = 0; ii < 3; ii++)
00416    //   for (int jj=0; jj < 3; jj++)
00417    //      Rx[ii][jj] = 0;    
00418    //Rx[0][0] = 1.;         
00419    Rx[1][1] =  cos(angle);    Rx[1][2] =  sin(angle);
00420    Rx[2][1] = -sin(angle);    Rx[2][2] =  cos(angle);
00421    
00422    double tmpVector[3];
00423    tmpVector[1] = Vector[1];   
00424    tmpVector[2] = Vector[2];   
00425    Vector[1] = Rx[1][1]*tmpVector[1] + Rx[1][2]*tmpVector[2];
00426    Vector[2] = Rx[2][1]*tmpVector[1] + Rx[2][2]*tmpVector[2];   
00427 }
00428 
00429 
00430 // ## Rotates about Y
00431 //##  By: Ivan Lima
00432 void RotatesAboutY(double angle, double *Vector) //, double Ry[][3])
00433 {
00434    double Ry[3][3];
00435    //for (int ii = 0; ii < 3; ii++)
00436    //   for (int jj=0; jj < 3; jj++)
00437    //      Ry[ii][jj] = 0;  
00438    Ry[0][0] =  cos(angle);              Ry[0][2] =  sin(angle);           
00439    //                        Ry[1][1] = 1.;         
00440    Ry[2][0] = -sin(angle);               Ry[2][2] =  cos(angle);
00441    
00442    double tmpVector[3];
00443    tmpVector[0] = Vector[0];   
00444    tmpVector[2] = Vector[2];   
00445    Vector[0] = Ry[0][0]*tmpVector[0] + Ry[0][2]*tmpVector[2];
00446    Vector[2] = Ry[2][0]*tmpVector[0] + Ry[2][2]*tmpVector[2];   
00447 }
00448 
00449 
00450 // ## Scalar product
00451 //## The coordinates are from 0 to 2
00452 //## By: Ivan Lima
00453 double ScalarProduct(double *VectorA, double *VectorB) // from 0 to 2
00454 {
00455    return( VectorA[0]*VectorB[0]
00456           +VectorA[1]*VectorB[1]
00457           +VectorA[2]*VectorB[2]);
00458 } 
00459 
00460 //## Gets the length of a vector
00461 //## By: Ivan Lima
00462 double GetVectorLength(double *Vector, int Dimension) // from 0 to dimension-1
00463 {
00464    double VectorLength = 0;
00465    for (int ii = 0; ii < Dimension; ii++) {
00466       VectorLength += sq(Vector[ii]);
00467    }   
00468    return sqrt(VectorLength);   
00469 } 
00470 
00471 
00472 
00473 //## Rotates a Jones vector about X
00474 //## By: Ivan Lima
00475 void RotatesAboutX(double angle, cplx *JonesVector) 
00476 {    
00477    cplx TransM[2][2];     
00478    TransM[0][0] =  exp(-jc*angle/2.);  TransM[0][1] =  0;
00479    TransM[1][0] = 0;                  TransM[1][1] =  exp(jc*angle/2.);
00480    
00481    cplx tmpJonesVector[2];
00482    tmpJonesVector[0] = JonesVector[0];   
00483    tmpJonesVector[1] = JonesVector[1];   
00484    JonesVector[0] =  TransM[0][0]*tmpJonesVector[0] 
00485                    + TransM[0][1]*tmpJonesVector[1];
00486    JonesVector[1] =  TransM[1][0]*tmpJonesVector[0] 
00487                    + TransM[1][1]*tmpJonesVector[1];   
00488 }
00489 
00490 
00491 //## Rotates a Jones vector about Y
00492 //## By: Ivan Lima
00493 void RotatesAboutY(double angle, cplx *JonesVector) 
00494 {    
00495    cplx TransM[2][2];     
00496    TransM[0][0] =  cos(angle/2.);    TransM[0][1] =  jc*sin(angle/2.);
00497    TransM[1][0] = jc*sin(angle/2.); TransM[1][1] =  cos(angle/2.);
00498    
00499    cplx tmpJonesVector[2];
00500    tmpJonesVector[0] = JonesVector[0];   
00501    tmpJonesVector[1] = JonesVector[1];   
00502    JonesVector[0] =  TransM[0][0]*tmpJonesVector[0] 
00503                    + TransM[0][1]*tmpJonesVector[1];
00504    JonesVector[1] =  TransM[1][0]*tmpJonesVector[0] 
00505                    + TransM[1][1]*tmpJonesVector[1];   
00506 }
00507 
00508 
00509 
00510 
00511 //## Rotates a Jones vector about Z
00512 //## By: Ivan Lima
00513 void RotatesAboutZ(double angle, cplx *JonesVector) 
00514 {    
00515    cplx TransM[2][2];     
00516    TransM[0][0] =  cos(angle/2.);    TransM[0][1] =  sin(angle/2.);
00517    TransM[1][0] = -sin(angle/2.);    TransM[1][1] =  cos(angle/2.);
00518    
00519    cplx tmpJonesVector[2];
00520    tmpJonesVector[0] = JonesVector[0];   
00521    tmpJonesVector[1] = JonesVector[1];   
00522    JonesVector[0] =  TransM[0][0]*tmpJonesVector[0] 
00523                    + TransM[0][1]*tmpJonesVector[1];
00524    JonesVector[1] =  TransM[1][0]*tmpJonesVector[0] 
00525                    + TransM[1][1]*tmpJonesVector[1];   
00526 }
00527 
00528 
00529 
00530 
00531 // ############################################
00532  
00533 //## Converts from dB to the linear scale
00534 //## By: Ivan Lima
00535 double dB2Linear(double dBvalue)
00536 {
00537    return(pow(10.,dBvalue/10.) ); 
00538 }
00539 
00540 
00541 // ########################################
00542 
00543 double dBm2Linear(double dBmPower)
00544 {
00545 
00546   // Written by John Zweck, Dec 15th 2000
00547 
00548   // Returns power is in Watts, W
00549 
00550   return(pow(10.0,dBmPower/10.0 - 3.0) );
00551 
00552 
00553 }
00554 
00555 // ####################################
00556 
00557 double Linear2dB(double LinearValue)
00558 {
00559  // Written by John Zweck, Dec 15th 2000
00560 
00561   return 10.0*log10(LinearValue);  
00562 
00563 
00564 }
00565 
00566 // #####################################
00567 
00568 double Linear2dBm(double LinearPower)
00569 {
00570  // Written by John Zweck, Dec 15th 2000
00571 
00572   // The input power LinearValue must be power in Watts, W.
00573 
00574    return 10.0*log10(LinearPower*1000.0);  
00575 
00576 }
00577 
00578 
00579 //####################################
00580 //## This function is adequate to limit
00581 //#  the maximum amount of power penalty
00582 //#  that a system can suffer
00583 //## By: Ivan Lima (5/10/02)
00584 double Linear2dB_Limited(double LinearValue, double MaxValue_dB)
00585 {
00586   //if (LinearValue <= 0) {
00587   if ( LinearValue >= dB2Linear(MaxValue_dB) ) {
00588      //## Maximum value set to 20 dB
00589      LinearValue = dB2Linear(MaxValue_dB);
00590   }   
00591   return Linear2dB(LinearValue);   
00592 }
00593 
00594 
00595 //#####################################
00596 //## By: Ivan Lima
00597 double GetDegreeOfPolarization(double *StokesVector)
00598 {
00599    if ( StokesVector[0]*(1 + 2*NEAR_ZERO) < 
00600          sqrt(sq(StokesVector[1]) + sq(StokesVector[2])
00601         +sq(StokesVector[3])) ) {
00602       cout << "From: DegreeOfPolarization()" << endl 
00603            << "Error: The  Stokes  Vector has DOP > 1." 
00604            << endl
00605            << "Please, check simulation algorithm" 
00606            << endl;
00607       for (int ii = 0; ii < 4; ii++)
00608          cout << "StokesVector[" << ii << "] = " 
00609               << StokesVector[ii] << endl;     
00610       exit(1);
00611    }   
00612    return(sqrt( sq(StokesVector[1]) + sq(StokesVector[2])
00613                +sq(StokesVector[3]) )/StokesVector[0] );
00614 }      
00615      
00616 //######################################################     
00617 //## By: Ivan Lima
00618 double GetPhase(const cplx Phasor) 
00619 //## Garanteed from -pi to pi
00620 {
00621    if (abs(Phasor) == 0) 
00622       return(0.);
00623    else   // phase = sgn( Aim ) * acos( Are/Ao)
00624       return( sgn(real(-jc*Phasor))*acos(real(Phasor)/abs(Phasor)) );      
00625 }
00626 
00627 
00628 //##################################################
00629 //## By: Ivan Lima
00630 void Stokes2Jones(const double *Stokes, cplx *Jones)
00631 //## The Stokes vector should have dimension 4: from 1 to 3   
00632 //## The Jones  vector should have dimension 2: from 0 to 1  
00633 //## The Jones  vector is returned normalized
00634 {   
00635    //## Ths step provides robustness agains lack of normalization
00636    //#  Obviously, it assumes that the Stokes parameters
00637    //#  are totaly polarized.
00638    double Stokes0 = sqrt(sq(Stokes[1])+sq(Stokes[2])+sq(Stokes[3]) );
00639    //if (Stokes0 < NEAR_ZERO) {
00640    //   cout << "Error: the Stokes parameters cannot be zero." << endl;
00641    //   cout << "Exiting from Stokes2Jones()" << endl;
00642    //   exit(1);
00643    //}             
00644    if (Stokes0 == 0) {
00645       Jones[0] = Jones[1] = 0;
00646    }
00647    else {
00648       double StokesNorm[4];   
00649       StokesNorm[1] = Stokes[1]/Stokes0;
00650       StokesNorm[2] = Stokes[2]/Stokes0;
00651       StokesNorm[3] = Stokes[3]/Stokes0;   
00652       double PhaseXY; 
00653       //if (sq(StokesNorm[1]) >= 1 - NEAR_ZERO) {
00654       if (sq(StokesNorm[1]) == 1) {      
00655             PhaseXY = 0;
00656       }      
00657       else {
00658          PhaseXY = acos( StokesNorm[2]/sqrt(1-sq(StokesNorm[1]) ) );
00659       }   
00660       Jones[0] = sqrt((1. + StokesNorm[1])/2.);
00661       Jones[1] = sqrt((1. - StokesNorm[1])/2.)
00662                 *exp(-jc*sgn(StokesNorm[3])*PhaseXY);         
00663    }          
00664 }
00665 
00666 //#####################################################
00667 //## By: Ivan Lima
00668 void Stokes2JonesKeepPower(const double *Stokes, cplx *Jones)
00669 {
00670    Stokes2Jones(Stokes,Jones);
00671    double TotPower = sqrt(sqrt( sq(Stokes[1])
00672                           +sq(Stokes[2])+sq(Stokes[3])) );
00673    Jones[0] *= TotPower; 
00674    Jones[1] *= TotPower;                      
00675 }
00676 
00677 
00678 //##################################################
00679 //## By: Ivan Lima
00680 void Jones2Stokes(const cplx *Jones, double *Stokes)
00681 //## The Jones  vector should have dimension 2: from 0 to 1  
00682 //## The Stokes vector should have dimension 4: from 0 to 3 
00683 //## The Stokes vector is returned normalized
00684 {   
00685    Stokes[0]   = sq(abs(Jones[0])) + sq(abs(Jones[1]));
00686    if (Stokes[0] != 0) {
00687       Stokes[1] = (sq(abs(Jones[0]))-sq(abs(Jones[1])) )
00688                   /Stokes[0];                           //##  |uc|^2-|vc|^2
00689       Stokes[2] = 2*real(Jones[0]*conj(Jones[1]))
00690                   /Stokes[0];                           //##  2 Re{uc . vc*}
00691       Stokes[3] = 2*real(-jc*Jones[0]*conj(Jones[1]))  
00692                   /Stokes[0];                           //## 2 Im{uc . vc*}         
00693       Stokes[0] = 1;             
00694    }
00695    else  {
00696       Stokes[1] = Stokes[2] = Stokes[3] = 0;
00697    }                     
00698 }
00699 
00700 
00701 //##################################################
00702 //## By: Ivan Lima
00703 void Jones2StokesKeepPower(const cplx *Jones, double *Stokes)
00704 {
00705    Jones2Stokes(Jones,Stokes);
00706    double TotPower = sq(abs(Jones[0])) + sq(abs(Jones[1]));
00707    for (int ii = 0; ii < 4; ii++) {
00708       Stokes[ii] *= TotPower;
00709    }
00710 }
00711 
00712 
00713 
00714 // ##### End of functions written by Ivan T. Lima Jr.
00715 
00716 
00717 // #################################################################
00718 // #################################################################
00719 
00720 // Functions written by John Zweck
00721 
00722 double Frequency2Wavelength(double Frequency)
00723 {
00724   // Frequency is in Hz
00725 
00726   return LightSpeed/Frequency;  
00727 }
00728 
00729 // ############################################################
00730 
00731 double Wavelength2Frequency(double Wavelength)
00732 {
00733   return LightSpeed/Wavelength; // returns Frequency  in Hz
00734 }
00735 
00736 
00737 // ##############################################################
00738 // ##############################################################
00739 
00740 // ##### The functions below were written by Ronald Holzloehner
00741 
00742 //--------------------------------------------
00743 // Box-Mueller random number generator
00744 // see D. Knuth: "The Art of Computer Programming", 3rd ed, vol 2, p.122
00745 
00746 void gaussian_pdf(int N, double stan_dev, double *vec)
00747 {
00748   double *p_vec = &(vec[0]);
00749   double *const p_vec_end = &(vec[N]);
00750   double v1, v2, SSs;
00751 
00752   for( ;p_vec < p_vec_end; )
00753   {
00754     do{ 
00755         v1 = 2.0*drand48() - 1.0;
00756         v2 = 2.0*drand48() - 1.0;
00757         SSs = sq(v1) + sq(v2);
00758       }while(SSs > 1.0);
00759 
00760     double a = stan_dev * sqrt(-2.0 * log(SSs)/SSs);
00761     *p_vec = a * v1;
00762     p_vec++;
00763     *p_vec = a * v2;
00764     p_vec++;
00765   }
00766 }
00767 
00768 
00769 //--------------------------------------------------------------------
00770 // 5th order normalized Bessel function, see bessel5.m
00771 
00772 cplx bessel5(double omega, double omega_0, double FWHM)
00773 {
00774   // 5th order
00775   const double mult = 4.8548214044214655;
00776 
00777   const cplx s = cplx( 0.0, (omega-omega_0)/FWHM * mult );
00778 
00779   // 5th order normalized polynomial
00780   return 945.0  /  (945.0 + s * (945.0 + s * (420.0+s * (105.0+s * (15.0+s)  ))));
00781 }
00782 
00783 
00784 //----------------------------------------------------------------------
00785 // electrical filter, 5th-order Bessel
00786 // Input: my_power_time[]
00787 // Output: my_power_time[]
00788 // global side effects: none
00789 
00790 void electrical_filter(cplx *my_power_time, cfftw *fft, double fwhm_norm)
00791 {
00792   fft->FFT(my_power_time, 0);
00793   cplx *power_f_p = fft->work;
00794   const int N = fft->give_N();
00795   double phase0125 = arg(bessel5(fwhm_norm/8.0, 0.0, fwhm_norm)); // go almost 0.5*fwhm
00796   for(int i=0; i < N; i++, power_f_p++)
00797   {
00798     // delta_f is the same for the splitstep data vector (length N_SS)
00799     // and for downsampled values b[] since delta_f = 1/T_total
00800     // CAUTION: delta_f is independent of step number, delta_t not!!
00801     double freq = fft->freq(i);
00802     double phase = -freq/(fwhm_norm/8.0) * phase0125; // minus to compensate
00803     *power_f_p *= cplx(cos(phase), sin(phase))
00804       * bessel5(freq, 0.0, fwhm_norm);
00805   }
00806   // transform back to time domain
00807   fft->IFFT(0, my_power_time);
00808   
00809 //    cout << "\n  Values at cutoff (should be 1/sqrt(2)): " << 
00810 //    abs(bessel5(bessel_FWHM/2, 0, bessel_FWHM)) << "\t" <<
00811 //    abs(bessel5(-bessel_FWHM/2, 0, bessel_FWHM)) << endl;
00812 } // electrical_filter()
00813 
00814 
00815 //----------------------------------------------------------------------
00816 // implements optical Gaussian filter
00817 // multiplies optical field (not intensity!) in frequency domain
00818 // Input: my_field_freq[]
00819 // Output: both  my_field_time[], my_field_freq[]
00820 // CAUTION: gives FWHM in intensity, not field !! (checked 21 Jan 00)
00821 
00822 void optical_filter(cplx *my_field_time, cplx *my_field_freq, 
00823    cfftw *fft, double fwhm_norm)
00824 {
00825   cplx *field_f = my_field_freq;
00826   int i;
00827   double sigma = fwhm_norm / 2.35482 * M_SQRT2;
00828   const int N = fft->give_N();
00829   for(i=0; i < N; i++, field_f++)
00830   {
00831     // CAUTION: delta_f is independent of step number, delta_t not!!
00832     *field_f *= exp(-0.5*sq(fft->freq(i)/sigma));
00833   }
00834   fft->IFFT(my_field_freq, my_field_time);
00835 
00836 } // optical_filter()
00837 
00838 //-----------------------------------------------------------------------
00839 // enable program to be migrated by MOSIX
00840 // Options: MOSIX_UNLOCK or MOSIX_LOCK
00841 int lock_or_unlock_mosix(int what)
00842 {
00843   ofstream *lock_file;
00844 
00845   char lock_name[50];
00846   sprintf(lock_name, "/proc/%d/lock", getpid());
00847   lock_file = new ofstream( lock_name, ios::out );
00848   if(lock_file->bad())
00849     return 1;
00850   *lock_file << ((what==MOSIX_LOCK)?"1":"0") << endl;
00851   lock_file->close();
00852   return 0;
00853 }
00854 
00855 
00856 //-----------------------------------------------------------------------
00857 // tell MOSIX this is a pure CPU job (as opposed to one with lots of I/O)
00858 
00859 int cpujob_mosix(void)
00860 {
00861   ofstream *cpu_file;
00862 
00863   cpu_file = new ofstream( "/proc/mosix/decay/cpujob", ios::out );
00864   if(cpu_file->bad())
00865     return 1;
00866   *cpu_file << 1 << endl;
00867   cpu_file->close();
00868   return 0;
00869 }
00870 
00871 
00872 //-----------------------------------------------------------------------
00873 // tell MOSIX that slow statistical decay applies to this program
00874 int slow_mosix(void)
00875 {
00876   ofstream *slow_file;
00877 
00878   slow_file = new ofstream( "/proc/mosix/decay/slow", ios::out );
00879   if(slow_file->bad())
00880     return 1;
00881   *slow_file << 1 << endl;
00882   slow_file->close();
00883   return 0;
00884 }
00885 
00886 
00887 //-----------------------------------------------------------------------
00888 double peak_power(cplx *in, int N)
00889 {
00890   cplx *p = in;
00891   cplx *const p_end = in+N;
00892   double max_power = norm(*p);
00893 
00894   for(p++; p < p_end; p++)
00895   {
00896     double tmp = norm(*p);
00897     if(tmp > max_power)
00898       max_power = tmp;
00899   }
00900   return max_power;
00901 }
00902 
00903 
00904 //-----------------------------------------------------------------------
00905 // Simpson's rule with a little trick -- it is assumed that
00906 // the signal is periodic and in[0] == in[N]
00907 // See Springer's Mathe, p. 377
00908 //
00909 // *in: input array
00910 // N:   length of array
00911 // width: 'time window', real step width times N
00912 
00913 double pulse_energy(cplx *in, int N, double width)
00914 {
00915   if(N%2)
00916   {
00917     cout << "\a\npulse_energy(): N must be even! Returning NAN..." << endl;
00918     cout << "Error in pulse_energy()." << endl;
00919     exit(1);
00920     //return NAN;
00921   }
00922 
00923   double sum1 = 0.0;
00924   cplx *p = in+1;
00925   cplx *const p_end = in+N;
00926   for(; p < p_end; p+=2)
00927     sum1 += norm(*p);
00928 
00929   double sum2 = 0.0;
00930   p = in; // yes, we start from index 0 here -- this inludes in[0]
00931   for(; p < p_end; p+=2)
00932     sum2 += norm(*p);
00933 
00934   // values in[0] and in[N] = in[0] are included in sum2
00935   return  width/double(N)/3.0 * ( 4.0*sum1 + 2.0*sum2 );
00936 }
00937 // ##### End functions written by Ronald Holzloehner
00938 
00939 
00940 // ##### Functions from Numerical Recipes
00941 
00942 // ## Attention: all the random numbers inside the program are 
00943 // obtained calling ranG(...). ranG(...) is defined here as
00944 // ran2(..), from Numerical Recipes, by default. 
00945 // But it can be changed to any other function alike.
00946 
00947 #define IM1 2147483563
00948 #define IM2 2147483399
00949 #define AM (1.0/IM1)
00950 #define IMM1 (IM1-1)
00951 #define IA1 40014
00952 #define IA2 40692
00953 #define IQ1 53668
00954 #define IQ2 52774
00955 #define IR1 12211
00956 #define IR2 3791
00957 #define NTAB 32
00958 #define NDIV (1+IMM1/NTAB)
00959 #define EPS 1.2e-7
00960 #define RNMX (1.0-EPS)
00961 
00962 //float ran2(long *idum)  //##### Original name from Numerical Recipes
00963 float ranG(long *idum)
00964 {
00965         int j;
00966         long k;
00967         static long idum2=123456789;
00968         static long iy=0;
00969         static long iv[NTAB];
00970         float temp;
00971 
00972         if (*idum <= 0) {
00973                 if (-(*idum) < 1) *idum=1;
00974                 else *idum = -(*idum);
00975                 idum2=(*idum);
00976                 for (j=NTAB+7;j>=0;j--) {
00977                         k=(*idum)/IQ1;
00978                         *idum=IA1*(*idum-k*IQ1)-k*IR1;
00979                         if (*idum < 0) *idum += IM1;
00980                         if (j < NTAB) iv[j] = *idum;
00981                 }
00982                 iy=iv[0];
00983         }
00984         k=(*idum)/IQ1;
00985         *idum=IA1*(*idum-k*IQ1)-k*IR1;
00986         if (*idum < 0) *idum += IM1;
00987         k=idum2/IQ2;
00988         idum2=IA2*(idum2-k*IQ2)-k*IR2;
00989         if (idum2 < 0) idum2 += IM2;
00990         j=iy/NDIV;
00991         iy=iv[j]-idum2;
00992         iv[j] = *idum;
00993         if (iy < 1) iy += IMM1;        
00994         if ((temp=AM*iy) > RNMX) return RNMX;
00995         else return temp;
00996 }
00997 #undef IM1
00998 #undef IM2
00999 #undef AM
01000 #undef IMM1
01001 #undef IA1
01002 #undef IA2
01003 #undef IQ1
01004 #undef IQ2
01005 #undef IR1
01006 #undef IR2
01007 #undef NTAB
01008 #undef NDIV
01009 #undef EPS
01010 #undef RNMX
01011 // (C) Copr. 1986-92 Numerical Recipes Software *1%:?!#:V3+). 
01012 
01013 
01014 #define IA 16807
01015 #define IM 2147483647
01016 #define AM (1.0/IM)
01017 #define IQ 127773
01018 #define IR 2836
01019 #define NTAB 32
01020 #define NDIV (1+(IM-1)/NTAB)
01021 #define EPS 1.2e-7
01022 #define RNMX (1.0-EPS)
01023 
01024 float ran1(long *idum)  //##### Original name from Numerical Recipes
01025 //float ranG(long *idum)
01026 {
01027         int j;
01028         long k;
01029         static long iy=0;
01030         static long iv[NTAB];
01031         float temp;
01032 
01033         if (*idum <= 0 || !iy) {
01034                 if (-(*idum) < 1) *idum=1;
01035                 else *idum = -(*idum);
01036                 for (j=NTAB+7;j>=0;j--) {
01037                         k=(*idum)/IQ;
01038                         *idum=IA*(*idum-k*IQ)-IR*k;
01039                         if (*idum < 0) *idum += IM;
01040                         if (j < NTAB) iv[j] = *idum;
01041                 }
01042                 iy=iv[0];
01043         }
01044         k=(*idum)/IQ;
01045         *idum=IA*(*idum-k*IQ)-IR*k;
01046         if (*idum < 0) *idum += IM;
01047         j=iy/NDIV;
01048         iy=iv[j];
01049         iv[j] = *idum;
01050         if ((temp=AM*iy) > RNMX) return RNMX;
01051         else return temp;
01052 }
01053 #undef IA
01054 #undef IM
01055 #undef AM
01056 #undef IQ
01057 #undef IR
01058 #undef NTAB
01059 #undef NDIV
01060 #undef EPS
01061 #undef RNMX
01062 // (C) Copr. 1986-92 Numerical Recipes Software *1%:?!#:V3+). 
01063 
01064 
01065 // ## Changed by Ivan in 8/25/2000 respect to the random generator
01066 // #  For arbitrary mean and standart deviation use it like:
01067 // #  myRandNumber = myMean + myStdDev*Gaussian_pdf(mySeedPointer);
01068 #include <math.h>
01069 
01070 float Gaussian_pdf(long *idum)
01071 //float gasdev(long *idum)
01072 {
01073         //float ran1(long *idum);
01074         float ranG(long *idum);
01075         static int iset=0;
01076         static float gset;
01077         float fac,rsq,v1,v2;
01078 
01079         if  (iset == 0) {
01080                 do {
01081                         v1=2.0*ranG(idum)-1.0;
01082                         v2=2.0*ranG(idum)-1.0;
01083                         //v1=2.0*ran1(idum)-1.0;
01084                         //v2=2.0*ran1(idum)-1.0;                        
01085                         rsq=v1*v1+v2*v2;
01086                 } while (rsq >= 1.0 || rsq == 0.0);
01087                 fac=sqrt(-2.0*log(rsq)/rsq);
01088                 gset=v1*fac;
01089                 iset=1;
01090                 return v2*fac;
01091         } else {
01092                 iset=0;
01093                 return gset;
01094         }
01095 }
01096 // (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+).
01097 
01098 
01099 // ## Optimization functions from Numerical Recipes
01100 #include <math.h>
01101 #define NRANSI
01102 #include "nrutil.h"
01103 #define ITMAX 200
01104 
01105 void powell(float p[], float xi[][4], int n, float ftol, int *iter, float *fret,
01106         float (*func)(float []))
01107 //void powell(float p[], float **xi, int n, float ftol, int *iter, float *fret,
01108 //      float (*func)(float []))        
01109 {
01110         void linmin(float p[], float xi[], int n, float *fret,
01111                 float (*func)(float []));
01112         int i,ibig,j;
01113         float del,fp,fptt,t,*pt,*ptt,*xit;
01114 
01115         pt=nrvector(1,n);
01116         ptt=nrvector(1,n);
01117         xit=nrvector(1,n);
01118         *fret=(*func)(p);
01119         for (j=1;j<=n;j++) pt[j]=p[j];
01120         for (*iter=1;;++(*iter)) {
01121                 fp=(*fret);
01122                 ibig=0;
01123                 del=0.0;
01124                 for (i=1;i<=n;i++) {
01125                         for (j=1;j<=n;j++) xit[j]=xi[j][i];
01126                         fptt=(*fret);
01127                         linmin(p,xit,n,fret,func);
01128                         if (fabs(fptt-(*fret)) > del) {
01129                                 del=fabs(fptt-(*fret));
01130                                 ibig=i;
01131                         }
01132                 }
01133                 if (2.0*fabs(fp-(*fret)) <= ftol*(fabs(fp)+fabs(*fret))) {
01134                         free_nrvector(xit,1,n);
01135                         free_nrvector(ptt,1,n);
01136                         free_nrvector(pt,1,n);
01137                         return;
01138                 }
01139                 if (*iter == ITMAX) nrerror("powell exceeding maximum iterations.");
01140                 for (j=1;j<=n;j++) {
01141                         ptt[j]=2.0*p[j]-pt[j];
01142                         xit[j]=p[j]-pt[j];
01143                         pt[j]=p[j];
01144                 }
01145                 fptt=(*func)(ptt);
01146                 if (fptt < fp) {
01147                         t=2.0*(fp-2.0*(*fret)+fptt)*SQR(fp-(*fret)-del)-del*SQR(fp-fptt);
01148                         if (t < 0.0) {
01149                                 linmin(p,xit,n,fret,func);
01150                                 for (j=1;j<=n;j++) {
01151                                         xi[j][ibig]=xi[j][n];
01152                                         xi[j][n]=xit[j];
01153                                 }
01154                         }
01155                 }
01156         }
01157 }
01158 #undef ITMAX
01159 #undef NRANSI
01160 // (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+). 
01161 
01162 
01163 #define NRANSI
01164 #include "nrutil.h"
01165 #define TOL 2.0e-4
01166 
01167 int ncom;
01168 float *pcom,*xicom,(*nrfunc)(float []);
01169 
01170 void linmin(float p[], float xi[], int n, float *fret, float (*func)(float []))
01171 {
01172         float brent(float ax, float bx, float cx,
01173                 float (*f)(float), float tol, float *xmin);
01174         float f1dim(float x);
01175         void mnbrak(float *ax, float *bx, float *cx, float *fa, float *fb,
01176                 float *fc, float (*func)(float));
01177         int j;
01178         float xx,xmin,fx,fb,fa,bx,ax;
01179 
01180         ncom=n;
01181         pcom=nrvector(1,n);
01182         xicom=nrvector(1,n);
01183         nrfunc=func;
01184         for (j=1;j<=n;j++) {
01185                 pcom[j]=p[j];
01186                 xicom[j]=xi[j];
01187         }
01188         ax=0.0;
01189         xx=1.0;
01190         mnbrak(&ax,&xx,&bx,&fa,&fx,&fb,f1dim);
01191         *fret=brent(ax,xx,bx,f1dim,TOL,&xmin);        
01192         for (j=1;j<=n;j++) {
01193                 xi[j] *= xmin;
01194                 p[j] += xi[j];
01195         }
01196         free_nrvector(xicom,1,n);
01197         free_nrvector(pcom,1,n);
01198 }
01199 #undef TOL
01200 #undef NRANSI
01201 // (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+). 
01202 
01203 #define NRANSI
01204 #include "nrutil.h"
01205 
01206 extern int ncom;
01207 extern float *pcom,*xicom,(*nrfunc)(float []);
01208 
01209 float f1dim(float x)
01210 {
01211         int j;
01212         float f,*xt;
01213 
01214         xt=nrvector(1,ncom);
01215         for (j=1;j<=ncom;j++) xt[j]=pcom[j]+x*xicom[j];
01216         f=(*nrfunc)(xt);
01217         free_nrvector(xt,1,ncom);
01218         return f;
01219 }
01220 #undef NRANSI
01221 // (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+). 
01222 
01223 #include <math.h>
01224 #define NRANSI
01225 #include "nrutil.h"
01226 #define GOLD 1.618034
01227 #define GLIMIT 100.0
01228 #define TINY 1.0e-20
01229 #define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
01230 
01231 void mnbrak(float *ax, float *bx, float *cx, float *fa, float *fb, float *fc,
01232         float (*func)(float))
01233 {
01234         float ulim,u,r,q,fu,dum;
01235 
01236         *fa=(*func)(*ax);
01237         *fb=(*func)(*bx);
01238         if (*fb > *fa) {
01239                 SHFT(dum,*ax,*bx,dum)
01240                 SHFT(dum,*fb,*fa,dum)
01241         }
01242         *cx=(*bx)+GOLD*(*bx-*ax);
01243         *fc=(*func)(*cx);
01244         while (*fb > *fc) {
01245                 r=(*bx-*ax)*(*fb-*fc);
01246                 q=(*bx-*cx)*(*fb-*fa);
01247                 u=(*bx)-((*bx-*cx)*q-(*bx-*ax)*r)/
01248                         (2.0*SIGN(FMAX(fabs(q-r),TINY),q-r));
01249                 ulim=(*bx)+GLIMIT*(*cx-*bx);
01250                 if ((*bx-u)*(u-*cx) > 0.0) {
01251                         fu=(*func)(u);
01252                         if (fu < *fc) {
01253                                 *ax=(*bx);
01254                                 *bx=u;
01255                                 *fa=(*fb);
01256                                 *fb=fu;
01257                                 return;
01258                         } else if (fu > *fb) {
01259                                 *cx=u;
01260                                 *fc=fu;
01261                                 return;
01262                         }
01263                         u=(*cx)+GOLD*(*cx-*bx);
01264                         fu=(*func)(u);
01265                 } else if ((*cx-u)*(u-ulim) > 0.0) {
01266                         fu=(*func)(u);
01267                         if (fu < *fc) {
01268                                 SHFT(*bx,*cx,u,*cx+GOLD*(*cx-*bx))
01269                                 SHFT(*fb,*fc,fu,(*func)(u))
01270                         }
01271                 } else if ((u-ulim)*(ulim-*cx) >= 0.0) {
01272                         u=ulim;
01273                         fu=(*func)(u);
01274                 } else {
01275                         u=(*cx)+GOLD*(*cx-*bx);
01276                         fu=(*func)(u);
01277                 }
01278                 SHFT(*ax,*bx,*cx,u)
01279                 SHFT(*fa,*fb,*fc,fu)
01280         }
01281 }
01282 #undef GOLD
01283 #undef GLIMIT
01284 #undef TINY
01285 #undef SHFT
01286 #undef NRANSI
01287 // (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+). 
01288 
01289 #include <math.h>
01290 #define NRANSI
01291 #include "nrutil.h"
01292 #define ITMAX 100
01293 #define CGOLD 0.3819660
01294 #define ZEPS 1.0e-10
01295 #define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
01296 
01297 float brent(float ax, float bx, float cx, float (*f)(float), float tol,
01298         float *xmin)
01299 {
01300         int iter;
01301         float a,b,d,etemp,fu,fv,fw,fx,p,q,r,tol1,tol2,u,v,w,x,xm;
01302         float e=0.0;
01303 
01304         a=(ax < cx ? ax : cx);
01305         b=(ax > cx ? ax : cx);
01306         x=w=v=bx;
01307         fw=fv=fx=(*f)(x);
01308         for (iter=1;iter<=ITMAX;iter++) {
01309                 xm=0.5*(a+b);
01310                 tol2=2.0*(tol1=tol*fabs(x)+ZEPS);
01311                 if (fabs(x-xm) <= (tol2-0.5*(b-a))) {
01312                         *xmin=x;
01313                         return fx;
01314                 }
01315                 if (fabs(e) > tol1) {
01316                         r=(x-w)*(fx-fv);
01317                         q=(x-v)*(fx-fw);
01318                         p=(x-v)*q-(x-w)*r;
01319                         q=2.0*(q-r);
01320                         if (q > 0.0) p = -p;
01321                         q=fabs(q);
01322                         etemp=e;
01323                         e=d;
01324                         if (fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-x))
01325                                 d=CGOLD*(e=(x >= xm ? a-x : b-x));
01326                         else {
01327                                 d=p/q;
01328                                 u=x+d;
01329                                 if (u-a < tol2 || b-u < tol2)
01330                                         d=SIGN(tol1,xm-x);
01331                         }
01332                 } else {
01333                         d=CGOLD*(e=(x >= xm ? a-x : b-x));
01334                 }
01335                 u=(fabs(d) >= tol1 ? x+d : x+SIGN(tol1,d));
01336                 fu=(*f)(u);
01337                 if (fu <= fx) {
01338                         if (u >= x) a=x; else b=x;
01339                         SHFT(v,w,x,u)
01340                         SHFT(fv,fw,fx,fu)
01341                 } else {
01342                         if (u < x) a=u; else b=u;
01343                         if (fu <= fw || w == x) {
01344                                 v=w;
01345                                 w=u;
01346                                 fv=fw;
01347                                 fw=fu;
01348                         } else if (fu <= fv || v == x || v == w) {
01349                                 v=u;
01350                                 fv=fu;
01351                         }
01352                 }
01353         }
01354         nrerror("Too many iterations in brent");
01355         *xmin=x;
01356         return fx;
01357 }
01358 #undef ITMAX
01359 #undef CGOLD
01360 #undef ZEPS
01361 #undef SHFT
01362 #undef NRANSI
01363 // (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+). 
01364 
01365 
01366 
01367 
01368 // ## Conjugate Gradient Method in double precision
01369 #include <math.h>
01370 #define NRANSI
01371 #include "nrutil.h"
01372 #define ITMAX 200
01373 #define EPS 1.0e-10
01374 #define FREEALLD free_dvector(xi,1,n);free_dvector(h,1,n);free_dvector(g,1,n);
01375 
01376 void frprmnd(double p[], int n, double ftol, int *iter, double *fret,
01377         double (*func)(double []), void (*dfunc)(double [], double []))
01378 {
01379         void linmind(double p[], double xi[], int n, double *fret,
01380                 double (*func)(double []));
01381         int j,its;
01382         double gg,gam,fp,dgg;
01383         double *g,*h,*xi;
01384 
01385         g=dvector(1,n);
01386         h=dvector(1,n);
01387         xi=dvector(1,n);
01388         fp=(*func)(p);
01389         (*dfunc)(p,xi);
01390         for (j=1;j<=n;j++) {
01391                 g[j] = -xi[j];
01392                 xi[j]=h[j]=g[j];
01393         }
01394         for (its=1;its<=ITMAX;its++) {
01395                 *iter=its;
01396                 linmind(p,xi,n,fret,func);
01397                 if (2.0*fabs(*fret-fp) <= ftol*(fabs(*fret)+fabs(fp)+EPS)) {
01398                         FREEALLD
01399                         return;
01400                 }
01401                 fp=(*func)(p);
01402                 (*dfunc)(p,xi);
01403                 dgg=gg=0.0;
01404                 for (j=1;j<=n;j++) {
01405                         gg += g[j]*g[j];
01406                         dgg += (xi[j]+g[j])*xi[j];
01407                 }
01408                 if (gg == 0.0) {
01409                         FREEALLD
01410                         return;
01411                 }
01412                 gam=dgg/gg;
01413                 for (j=1;j<=n;j++) {
01414                         g[j] = -xi[j];
01415                         xi[j]=h[j]=g[j]+gam*h[j];
01416                 }
01417         }
01418         nrerror("Too many iterations in frprmn");
01419 }
01420 #undef ITMAX
01421 #undef EPS
01422 #undef FREEALLD
01423 #undef NRANSI
01424 // (C) Copr. 19 
01425 
01426 
01427 #define NRANSI
01428 #include "nrutil.h"
01429 #define TOL 2.0e-4
01430 
01431 //int ncom;
01432 double *pcomd,*xicomd,(*nrfuncd)(double []);
01433 
01434 void linmind(double p[], double xi[], int n, double *fret, double (*func)(double []))
01435 {
01436         double brentd(double ax, double bx, double cx,
01437                 double (*f)(double), double tol, double *xmin);
01438         double f1dim(double x);
01439         void mnbrakd(double *ax, double *bx, double *cx, double *fa, double *fb,
01440                 double *fc, double (*func)(double));
01441         int j;
01442         double xx,xmin,fx,fb,fa,bx,ax;
01443 
01444         ncom=n;
01445         pcomd=dvector(1,n);
01446         xicomd=dvector(1,n);
01447         nrfuncd=func;
01448         for (j=1;j<=n;j++) {
01449                 pcomd[j]=p[j];
01450                 xicomd[j]=xi[j];
01451         }
01452         ax=0.0;
01453         xx=1.0;
01454         mnbrakd(&ax,&xx,&bx,&fa,&fx,&fb,f1dim);
01455         *fret=brentd(ax,xx,bx,f1dim,TOL,&xmin);        
01456         for (j=1;j<=n;j++) {
01457                 xi[j] *= xmin;
01458                 p[j] += xi[j];
01459         }
01460         free_dvector(xicomd,1,n);
01461         free_dvector(pcomd,1,n);
01462 }
01463 #undef TOL
01464 #undef NRANSI
01465 // (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+). 
01466 
01467 #define NRANSI
01468 #include "nrutil.h"
01469 
01470 extern int ncom;
01471 extern double *pcomd,*xicomd,(*nrfuncd)(double []);
01472 
01473 double f1dim(double x)
01474 {
01475         int j;
01476         double f,*xt;
01477 
01478         xt=dvector(1,ncom);
01479         for (j=1;j<=ncom;j++) xt[j]=pcomd[j]+x*xicomd[j];
01480         f=(*nrfuncd)(xt);
01481         free_dvector(xt,1,ncom);
01482         return f;
01483 }
01484 #undef NRANSI
01485 // (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+). 
01486 
01487 #include <math.h>
01488 #define NRANSI
01489 #include "nrutil.h"
01490 #define GOLD 1.618034
01491 #define GLIMIT 100.0
01492 #define TINY 1.0e-20
01493 #define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
01494 
01495 void mnbrakd(double *ax, double *bx, double *cx, double *fa, double *fb, double *fc,
01496         double (*func)(double))
01497 {
01498         double ulim,u,r,q,fu,dum;
01499 
01500         *fa=(*func)(*ax);
01501         *fb=(*func)(*bx);
01502         if (*fb > *fa) {
01503                 SHFT(dum,*ax,*bx,dum)
01504                 SHFT(dum,*fb,*fa,dum)
01505         }
01506         *cx=(*bx)+GOLD*(*bx-*ax);
01507         *fc=(*func)(*cx);
01508         while (*fb > *fc) {
01509                 r=(*bx-*ax)*(*fb-*fc);
01510                 q=(*bx-*cx)*(*fb-*fa);
01511                 u=(*bx)-((*bx-*cx)*q-(*bx-*ax)*r)/
01512                         (2.0*SIGN(FMAX(fabs(q-r),TINY),q-r));
01513                 ulim=(*bx)+GLIMIT*(*cx-*bx);
01514                 if ((*bx-u)*(u-*cx) > 0.0) {
01515                         fu=(*func)(u);
01516                         if (fu < *fc) {
01517                                 *ax=(*bx);
01518                                 *bx=u;
01519                                 *fa=(*fb);
01520                                 *fb=fu;
01521                                 return;
01522                         } else if (fu > *fb) {
01523                                 *cx=u;
01524                                 *fc=fu;
01525                                 return;
01526                         }
01527                         u=(*cx)+GOLD*(*cx-*bx);
01528                         fu=(*func)(u);
01529                 } else if ((*cx-u)*(u-ulim) > 0.0) {
01530                         fu=(*func)(u);
01531                         if (fu < *fc) {
01532                                 SHFT(*bx,*cx,u,*cx+GOLD*(*cx-*bx))
01533                                 SHFT(*fb,*fc,fu,(*func)(u))
01534                         }
01535                 } else if ((u-ulim)*(ulim-*cx) >= 0.0) {
01536                         u=ulim;
01537                         fu=(*func)(u);
01538                 } else {
01539                         u=(*cx)+GOLD*(*cx-*bx);
01540                         fu=(*func)(u);
01541                 }
01542                 SHFT(*ax,*bx,*cx,u)
01543                 SHFT(*fa,*fb,*fc,fu)
01544         }
01545 }
01546 #undef GOLD
01547 #undef GLIMIT
01548 #undef TINY
01549 #undef SHFT
01550 #undef NRANSI
01551 // (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+). 
01552 
01553 #include <math.h>
01554 #define NRANSI
01555 #include "nrutil.h"
01556 #define ITMAX 100
01557 #define CGOLD 0.3819660
01558 #define ZEPS 1.0e-10
01559 #define SHFT(a,b,c,d) (a)=(b);(b)=(c);(c)=(d);
01560 
01561 double brentd(double ax, double bx, double cx, double (*f)(double), double tol,
01562         double *xmin)
01563 {
01564         int iter;
01565         double a,b,d,etemp,fu,fv,fw,fx,p,q,r,tol1,tol2,u,v,w,x,xm;
01566         double e=0.0;
01567 
01568         a=(ax < cx ? ax : cx);
01569         b=(ax > cx ? ax : cx);
01570         x=w=v=bx;
01571         fw=fv=fx=(*f)(x);
01572         for (iter=1;iter<=ITMAX;iter++) {
01573                 xm=0.5*(a+b);
01574                 tol2=2.0*(tol1=tol*fabs(x)+ZEPS);
01575                 if (fabs(x-xm) <= (tol2-0.5*(b-a))) {
01576                         *xmin=x;
01577                         return fx;
01578                 }
01579                 if (fabs(e) > tol1) {
01580                         r=(x-w)*(fx-fv);
01581                         q=(x-v)*(fx-fw);
01582                         p=(x-v)*q-(x-w)*r;
01583                         q=2.0*(q-r);
01584                         if (q > 0.0) p = -p;
01585                         q=fabs(q);
01586                         etemp=e;
01587                         e=d;
01588                         if (fabs(p) >= fabs(0.5*q*etemp) || p <= q*(a-x) || p >= q*(b-x))
01589                                 d=CGOLD*(e=(x >= xm ? a-x : b-x));
01590                         else {
01591                                 d=p/q;
01592                                 u=x+d;
01593                                 if (u-a < tol2 || b-u < tol2)
01594                                         d=SIGN(tol1,xm-x);
01595                         }
01596                 } else {
01597                         d=CGOLD*(e=(x >= xm ? a-x : b-x));
01598                 }
01599                 u=(fabs(d) >= tol1 ? x+d : x+SIGN(tol1,d));
01600                 fu=(*f)(u);
01601                 if (fu <= fx) {
01602                         if (u >= x) a=x; else b=x;
01603                         SHFT(v,w,x,u)
01604                         SHFT(fv,fw,fx,fu)
01605                 } else {
01606                         if (u < x) a=u; else b=u;
01607                         if (fu <= fw || w == x) {
01608                                 v=w;
01609                                 w=u;
01610                                 fv=fw;
01611                                 fw=fu;
01612                         } else if (fu <= fv || v == x || v == w) {
01613                                 v=u;
01614                                 fv=fu;
01615                         }
01616                 }
01617         }
01618         nrerror("Too many iterations in brentd");
01619         *xmin=x;
01620         return fx;
01621 }
01622 #undef ITMAX
01623 #undef CGOLD
01624 #undef ZEPS
01625 #undef SHFT
01626 #undef NRANSI
01627 // (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+). 
01628 
01629 
01630 // ## End of functions for the optimization in double precision
01631 
01632 
01633 
01634 
01635 // ## Conjugate Gradient Method
01636 #include <math.h>
01637 #define NRANSI
01638 #include "nrutil.h"
01639 #define ITMAX 200
01640 #define EPS 1.0e-10
01641 #define FREEALL free_nrvector(xi,1,n);free_nrvector(h,1,n);free_nrvector(g,1,n);
01642 
01643 void frprmn(float p[], int n, float ftol, int *iter, float *fret,
01644         float (*func)(float []), void (*dfunc)(float [], float []))
01645 {
01646         void linmin(float p[], float xi[], int n, float *fret,
01647                 float (*func)(float []));
01648         int j,its;
01649         float gg,gam,fp,dgg;
01650         float *g,*h,*xi;
01651 
01652         g=nrvector(1,n);
01653         h=nrvector(1,n);
01654         xi=nrvector(1,n);
01655         fp=(*func)(p);
01656         (*dfunc)(p,xi);
01657         for (j=1;j<=n;j++) {
01658                 g[j] = -xi[j];
01659                 xi[j]=h[j]=g[j];
01660         }
01661         for (its=1;its<=ITMAX;its++) {
01662                 *iter=its;
01663                 linmin(p,xi,n,fret,func);
01664                 if (2.0*fabs(*fret-fp) <= ftol*(fabs(*fret)+fabs(fp)+EPS)) {
01665                         FREEALL
01666                         return;
01667                 }
01668                 fp=(*func)(p);
01669                 (*dfunc)(p,xi);
01670                 dgg=gg=0.0;
01671                 for (j=1;j<=n;j++) {
01672                         gg += g[j]*g[j];
01673                         dgg += (xi[j]+g[j])*xi[j];
01674                 }
01675                 if (gg == 0.0) {
01676                         FREEALL
01677                         return;
01678                 }
01679                 gam=dgg/gg;
01680                 for (j=1;j<=n;j++) {
01681                         g[j] = -xi[j];
01682                         xi[j]=h[j]=g[j]+gam*h[j];
01683                 }
01684         }
01685         nrerror("Too many iterations in frprmn");
01686 }
01687 #undef ITMAX
01688 #undef EPS
01689 #undef FREEALL
01690 #undef NRANSI
01691 // (C) Copr. 19 
01692 
01693 // ## End of functions for the optimization
01694 
01695 
01696 // ## Functions from nrutil.c
01697 
01698 #include <stdio.h>
01699 #include <stddef.h>
01700 #include <stdlib.h>
01701 
01702 #define NR_END 1
01703 #define FREE_ARG char*
01704 
01705 void nrerror(char error_text[])
01706 /* Numerical Recipes standard error handler */
01707 {
01708         fprintf(stderr,"Numerical Recipes run-time error...\n");
01709         fprintf(stderr,"%s\n",error_text);
01710         fprintf(stderr,"...now exiting to system...\n");
01711         exit(1);
01712 }
01713 
01714 
01715 
01716 float *nrvector(long nl, long nh)
01717 /* allocate a float vector with subscript range v[nl..nh] */
01718 {
01719         float *v;
01720 
01721         v=(float *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(float)));
01722         if (!v) nrerror("allocation failure in nrvector()");
01723         return v-nl+NR_END;
01724 }
01725 
01726 int *ivector(long nl, long nh)
01727 /* allocate an int vector with subscript range v[nl..nh] */
01728 {
01729         int *v;
01730 
01731         v=(int *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(int)));
01732         if (!v) nrerror("allocation failure in ivector()");
01733         return v-nl+NR_END;
01734 }
01735 
01736 unsigned char *cvector(long nl, long nh)
01737 /* allocate an unsigned char vector with subscript range v[nl..nh] */
01738 {
01739         unsigned char *v;
01740 
01741         v=(unsigned char *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(unsigned char)));
01742         if (!v) nrerror("allocation failure in cvector()");
01743         return v-nl+NR_END;
01744 }
01745 
01746 unsigned long *lvector(long nl, long nh)
01747 /* allocate an unsigned long vector with subscript range v[nl..nh] */
01748 {
01749         unsigned long *v;
01750 
01751         v=(unsigned long *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(long)));
01752         if (!v) nrerror("allocation failure in lvector()");
01753         return v-nl+NR_END;
01754 }
01755 
01756 double *dvector(long nl, long nh)
01757 /* allocate a double vector with subscript range v[nl..nh] */
01758 {
01759         double *v;
01760 
01761         v=(double *)malloc((size_t) ((nh-nl+1+NR_END)*sizeof(double)));
01762         if (!v) nrerror("allocation failure in dvector()");
01763         return v-nl+NR_END;
01764 }
01765 
01766 float **matrix(long nrl, long nrh, long ncl, long nch)
01767 /* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch] */
01768 {
01769         long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
01770         float **m;
01771 
01772         /* allocate pointers to rows */
01773         m=(float **) malloc((size_t)((nrow+NR_END)*sizeof(float*)));
01774         if (!m) nrerror("allocation failure 1 in matrix()");
01775         m += NR_END;
01776         m -= nrl;
01777 
01778         /* allocate rows and set pointers to them */
01779         m[nrl]=(float *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(float)));
01780         if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
01781         m[nrl] += NR_END;
01782         m[nrl] -= ncl;
01783 
01784         for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;
01785 
01786         /* return pointer to array of pointers to rows */
01787         return m;
01788 }
01789 
01790 double **dmatrix(long nrl, long nrh, long ncl, long nch)
01791 /* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch] */
01792 {
01793         long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
01794         double **m;
01795 
01796         /* allocate pointers to rows */
01797         m=(double **) malloc((size_t)((nrow+NR_END)*sizeof(double*)));
01798         if (!m) nrerror("allocation failure 1 in matrix()");
01799         m += NR_END;
01800         m -= nrl;
01801 
01802         /* allocate rows and set pointers to them */
01803         m[nrl]=(double *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(double)));
01804         if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
01805         m[nrl] += NR_END;
01806         m[nrl] -= ncl;
01807 
01808         for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;
01809 
01810         /* return pointer to array of pointers to rows */
01811         return m;
01812 }
01813 
01814 
01815 cplx **cmatrix(long nrl, long nrh, long ncl, long nch)
01816 /* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch] */
01817 {
01818         long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
01819         cplx **m;
01820 
01821         /* allocate pointers to rows */
01822         m=(cplx **) malloc((size_t)((nrow+NR_END)*sizeof(cplx*)));
01823         if (!m) nrerror("allocation failure 1 in matrix()");
01824         m += NR_END;
01825         m -= nrl;
01826 
01827         /* allocate rows and set pointers to them */
01828         m[nrl]=(cplx *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(cplx)));
01829         if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
01830         m[nrl] += NR_END;
01831         m[nrl] -= ncl;
01832 
01833         for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;
01834 
01835         /* return pointer to array of pointers to rows */
01836         return m;
01837 }
01838 
01839 int **imatrix(long nrl, long nrh, long ncl, long nch)
01840 /* allocate a int matrix with subscript range m[nrl..nrh][ncl..nch] */
01841 {
01842         long i, nrow=nrh-nrl+1,ncol=nch-ncl+1;
01843         int **m;
01844 
01845         /* allocate pointers to rows */
01846         m=(int **) malloc((size_t)((nrow+NR_END)*sizeof(int*)));
01847         if (!m) nrerror("allocation failure 1 in matrix()");
01848         m += NR_END;
01849         m -= nrl;
01850 
01851 
01852         /* allocate rows and set pointers to them */
01853         m[nrl]=(int *) malloc((size_t)((nrow*ncol+NR_END)*sizeof(int)));
01854         if (!m[nrl]) nrerror("allocation failure 2 in matrix()");
01855         m[nrl] += NR_END;
01856         m[nrl] -= ncl;
01857 
01858         for(i=nrl+1;i<=nrh;i++) m[i]=m[i-1]+ncol;
01859 
01860         /* return pointer to array of pointers to rows */
01861         return m;
01862 }
01863 
01864 float **submatrix(float **a, long oldrl, long oldrh, long oldcl, long oldch,
01865         long newrl, long newcl)
01866 /* point a submatrix [newrl..][newcl..] to a[oldrl..oldrh][oldcl..oldch] */
01867 {
01868         long i,j,nrow=oldrh-oldrl+1,ncol=oldcl-newcl;
01869         float **m;
01870 
01871         /* allocate array of pointers to rows */
01872         m=(float **) malloc((size_t) ((nrow+NR_END)*sizeof(float*)));
01873         if (!m) nrerror("allocation failure in submatrix()");
01874         m += NR_END;
01875         m -= newrl;
01876 
01877         /* set pointers to rows */
01878         for(i=oldrl,j=newrl;i<=oldrh;i++,j++) m[j]=a[i]+ncol;
01879 
01880         /* return pointer to array of pointers to rows */
01881         return m;
01882 }
01883 
01884 float **convert_matrix(float *a, long nrl, long nrh, long ncl, long nch)
01885 /* allocate a float matrix m[nrl..nrh][ncl..nch] that points to the matrix
01886 declared in the standard C manner as a[nrow][ncol], where nrow=nrh-nrl+1
01887 and ncol=nch-ncl+1. The routine should be called with the address
01888 &a[0][0] as the first argument. */
01889 {
01890         long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1;
01891         float **m;
01892 
01893         /* allocate pointers to rows */
01894         m=(float **) malloc((size_t) ((nrow+NR_END)*sizeof(float*)));
01895         if (!m) nrerror("allocation failure in convert_matrix()");
01896         m += NR_END;
01897         m -= nrl;
01898 
01899         /* set pointers to rows */
01900         m[nrl]=a-ncl;
01901         for(i=1,j=nrl+1;i<nrow;i++,j++) m[j]=m[j-1]+ncol;
01902         /* return pointer to array of pointers to rows */
01903         return m;
01904 }
01905 
01906 float ***f3tensor(long nrl, long nrh, long ncl, long nch, long ndl, long ndh)
01907 /* allocate a float 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */
01908 {
01909         long i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;
01910         float ***t;
01911 
01912         /* allocate pointers to pointers to rows */
01913         t=(float ***) malloc((size_t)((nrow+NR_END)*sizeof(float**)));
01914         if (!t) nrerror("allocation failure 1 in f3tensor()");
01915         t += NR_END;
01916         t -= nrl;
01917 
01918         /* allocate pointers to rows and set pointers to them */
01919         t[nrl]=(float **) malloc((size_t)((nrow*ncol+NR_END)*sizeof(float*)));
01920         if (!t[nrl]) nrerror("allocation failure 2 in f3tensor()");
01921         t[nrl] += NR_END;
01922         t[nrl] -= ncl;
01923 
01924         /* allocate rows and set pointers to them */
01925         t[nrl][ncl]=(float *) malloc((size_t)((nrow*ncol*ndep+NR_END)*sizeof(float)));
01926         if (!t[nrl][ncl]) nrerror("allocation failure 3 in f3tensor()");
01927         t[nrl][ncl] += NR_END;
01928         t[nrl][ncl] -= ndl;
01929 
01930         for(j=ncl+1;j<=nch;j++) t[nrl][j]=t[nrl][j-1]+ndep;
01931         for(i=nrl+1;i<=nrh;i++) {
01932                 t[i]=t[i-1]+ncol;
01933                 t[i][ncl]=t[i-1][ncl]+ncol*ndep;
01934                 for(j=ncl+1;j<=nch;j++) t[i][j]=t[i][j-1]+ndep;
01935         }
01936 
01937         /* return pointer to array of pointers to rows */
01938         return t;
01939 }
01940 
01941 
01942 void free_dvector(double *v, long nl, long nh)
01943 /* free a double vector allocated with vector() */
01944 {
01945         free((FREE_ARG) (v+nl-NR_END));
01946 }
01947 
01948 void free_nrvector(float *v, long nl, long nh)
01949 /* free a float nrvector allocated with nrvector() */
01950 {
01951         free((FREE_ARG) (v+nl-NR_END));
01952 }
01953 
01954 void free_ivector(int *v, long nl, long nh)
01955 /* free an int vector allocated with ivector() */
01956 {
01957         free((FREE_ARG) (v+nl-NR_END));
01958 }
01959 
01960 void free_cvector(unsigned char *v, long nl, long nh)
01961 /* free an unsigned char vector allocated with cvector() */
01962 {
01963         free((FREE_ARG) (v+nl-NR_END));
01964 }
01965 
01966 void free_lvector(unsigned long *v, long nl, long nh)
01967 /* free an unsigned long vector allocated with lvector() */
01968 {
01969         free((FREE_ARG) (v+nl-NR_END));
01970 }
01971 
01972 
01973 void free_matrix(float **m, long nrl, long nrh, long ncl, long nch)
01974 /* free a float matrix allocated by matrix() */
01975 {
01976         free((FREE_ARG) (m[nrl]+ncl-NR_END));
01977         free((FREE_ARG) (m+nrl-NR_END));
01978 }
01979 
01980 void free_dmatrix(double **m, long nrl, long nrh, long ncl, long nch)
01981 /* free a double matrix allocated by dmatrix() */
01982 {
01983         free((FREE_ARG) (m[nrl]+ncl-NR_END));
01984         free((FREE_ARG) (m+nrl-NR_END));
01985 }
01986 
01987 
01988 void free_cmatrix(cplx **m, long nrl, long nrh, long ncl, long nch)
01989 /* free a double matrix allocated by dmatrix() */
01990 {
01991         free((FREE_ARG) (m[nrl]+ncl-NR_END));
01992         free((FREE_ARG) (m+nrl-NR_END));
01993 }
01994 
01995 void free_imatrix(int **m, long nrl, long nrh, long ncl, long nch)
01996 /* free an int matrix allocated by imatrix() */
01997 {
01998         free((FREE_ARG) (m[nrl]+ncl-NR_END));
01999         free((FREE_ARG) (m+nrl-NR_END));
02000 }
02001 
02002 void free_submatrix(float **b, long nrl, long nrh, long ncl, long nch)
02003 /* free a submatrix allocated by submatrix() */
02004 {
02005         free((FREE_ARG) (b+nrl-NR_END));
02006 }
02007 
02008 void free_convert_matrix(float **b, long nrl, long nrh, long ncl, long nch)
02009 /* free a matrix allocated by convert_matrix() */
02010 {
02011         free((FREE_ARG) (b+nrl-NR_END));
02012 }
02013 
02014 void free_f3tensor(float ***t, long nrl, long nrh, long ncl, long nch,
02015         long ndl, long ndh)
02016 /* free a float f3tensor allocated by f3tensor() */
02017 {
02018         free((FREE_ARG) (t[nrl][ncl]+ndl-NR_END));
02019         free((FREE_ARG) (t[nrl]+ncl-NR_END));
02020         free((FREE_ARG) (t+nrl-NR_END));
02021 }
02022 
02023 
02024 
02025 
02026 
02027 
02028 #include <math.h>
02029 #define NRANSI
02030 #include "nrutil.h"
02031 #define SWAP(a,b) {temp=(a);(a)=(b);(b)=temp;}
02032 
02033 // ## Changed by Ivan in 01/2001 from float to double
02034 
02035 void gaussj(double **a, int n, double **b, int m) //
02036 {
02037         int *indxc,*indxr,*ipiv;
02038         int i,icol,irow,j,k,l,ll;
02039         double big,dum,pivinv,temp;  //
02040 
02041         indxc=ivector(1,n);
02042         indxr=ivector(1,n);
02043         ipiv=ivector(1,n);
02044         for (j=1;j<=n;j++) ipiv[j]=0;
02045         for (i=1;i<=n;i++) {
02046                 big=0.0;
02047                 for (j=1;j<=n;j++)
02048                         if (ipiv[j] != 1)
02049                                 for (k=1;k<=n;k++) {
02050                                         if (ipiv[k] == 0) {
02051                                                 if (abs(a[j][k]) >= big) {
02052                                                         big=abs(a[j][k]);
02053                                                         irow=j;
02054                                                         icol=k;
02055                                                 }
02056                                         } else if (ipiv[k] > 1) nrerror("gaussj: Singular Matrix-1");
02057                                 }
02058                 ++(ipiv[icol]);
02059                 if (irow != icol) {
02060                         for (l=1;l<=n;l++) SWAP(a[irow][l],a[icol][l])
02061                         for (l=1;l<=m;l++) SWAP(b[irow][l],b[icol][l])
02062                 }
02063                 indxr[i]=irow;
02064                 indxc[i]=icol;
02065                 if (a[icol][icol] == 0.0) nrerror("gaussj: Singular Matrix-2");
02066                 pivinv=1.0/a[icol][icol];
02067                 a[icol][icol]=1.0;
02068                 for (l=1;l<=n;l++) a[icol][l] *= pivinv;
02069                 for (l=1;l<=m;l++) b[icol][l] *= pivinv;
02070                 for (ll=1;ll<=n;ll++)
02071                         if (ll != icol) {
02072                                 dum=a[ll][icol];
02073                                 a[ll][icol]=0.0;
02074                                 for (l=1;l<=n;l++) a[ll][l] -= a[icol][l]*dum;
02075                                 for (l=1;l<=m;l++) b[ll][l] -= b[icol][l]*dum;
02076                         }
02077         }
02078         for (l=n;l>=1;l--) {
02079                 if (indxr[l] != indxc[l])
02080                         for (k=1;k<=n;k++)
02081                                 SWAP(a[k][indxr[l]],a[k][indxc[l]]);
02082         }
02083         free_ivector(ipiv,1,n);
02084         free_ivector(indxr,1,n);
02085         free_ivector(indxc,1,n);
02086 }
02087 #undef SWAP
02088 #undef NRANSI
02089 /* (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+). */
02090 
02091 
02092 
02093 
02094 
02095 
02096 #include <math.h>
02097 #define NRANSI
02098 #include "nrutil.h"
02099 #define SWAP(a,b) {temp=(a);(a)=(b);(b)=temp;}
02100 
02101 // ## Changed by Ivan in 04/2001 from double to cplx
02102 void gaussj_complex(cplx **a, int n, cplx **b, int m) //
02103 {
02104         int *indxc,*indxr,*ipiv;
02105         int i,icol,irow,j,k,l,ll;
02106         cplx dum,pivinv,temp;  //
02107         double big;
02108         indxc=ivector(1,n);
02109         indxr=ivector(1,n);
02110         ipiv=ivector(1,n);
02111         for (j=1;j<=n;j++) ipiv[j]=0;
02112         for (i=1;i<=n;i++) {
02113                 big=0.0;
02114                 for (j=1;j<=n;j++)
02115                         if (ipiv[j] != 1)
02116                                 for (k=1;k<=n;k++) {
02117                                         if (ipiv[k] == 0) {
02118                                                 if (abs(a[j][k]) >= big) {
02119                                                         big=abs(a[j][k]);
02120                                                         irow=j;
02121                                                         icol=k;
02122                                                 }
02123                                         } else if (ipiv[k] > 1) nrerror("gaussj: Singular Matrix-1");
02124                                 }
02125                 ++(ipiv[icol]);
02126                 if (irow != icol) {
02127                         for (l=1;l<=n;l++) SWAP(a[irow][l],a[icol][l])
02128                         for (l=1;l<=m;l++) SWAP(b[irow][l],b[icol][l])
02129                 }
02130                 indxr[i]=irow;
02131                 indxc[i]=icol;
02132                 if (a[icol][icol] == 0.0) nrerror("gaussj: Singular Matrix-2");
02133                 pivinv=1.0/a[icol][icol];
02134                 a[icol][icol]=1.0;
02135                 for (l=1;l<=n;l++) a[icol][l] *= pivinv;
02136                 for (l=1;l<=m;l++) b[icol][l] *= pivinv;
02137                 for (ll=1;ll<=n;ll++)
02138                         if (ll != icol) {
02139                                 dum=a[ll][icol];
02140                                 a[ll][icol]=0.0;
02141                                 for (l=1;l<=n;l++) a[ll][l] -= a[icol][l]*dum;
02142                                 for (l=1;l<=m;l++) b[ll][l] -= b[icol][l]*dum;
02143                         }
02144         }
02145         for (l=n;l>=1;l--) {
02146                 if (indxr[l] != indxc[l])
02147                         for (k=1;k<=n;k++)
02148                                 SWAP(a[k][indxr[l]],a[k][indxc[l]]);
02149         }
02150         free_ivector(ipiv,1,n);
02151         free_ivector(indxr,1,n);
02152         free_ivector(indxc,1,n);
02153 }
02154 #undef SWAP
02155 #undef NRANSI
02156 /* (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+). */
02157 
02158 
02159 float erffc(float x)
02160 {
02161         float gammp(float a, float x);
02162         float gammq(float a, float x);
02163 
02164         return x < 0.0 ? 1.0+gammp(0.5,x*x) : gammq(0.5,x*x);
02165 }
02166 /* (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+). */
02167 
02168 float gammp(float a, float x)
02169 {
02170         void gcf(float *gammcf, float a, float x, float *gln);
02171         void gser(float *gamser, float a, float x, float *gln);
02172         void nrerror(char error_text[]);
02173         float gamser,gammcf,gln;
02174 
02175         if (x < 0.0 || a <= 0.0) nrerror("Invalid arguments in routine gammp");
02176         if (x < (a+1.0)) {
02177                 gser(&gamser,a,x,&gln);
02178                 return gamser;
02179         } else {
02180                 gcf(&gammcf,a,x,&gln);
02181                 return 1.0-gammcf;
02182         }
02183 }
02184 /* (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+). */
02185 
02186 #include <math.h>
02187 #define ITMAX 100
02188 #define EPS 3.0e-7
02189 #define FPMIN 1.0e-30
02190 
02191 void gcf(float *gammcf, float a, float x, float *gln)
02192 {
02193         float gammln(float xx);
02194         void nrerror(char error_text[]);
02195         int i;
02196         float an,b,c,d,del,h;
02197 
02198         *gln=gammln(a);
02199         b=x+1.0-a;
02200         c=1.0/FPMIN;
02201         d=1.0/b;
02202         h=d;
02203         for (i=1;i<=ITMAX;i++) {
02204                 an = -i*(i-a);
02205                 b += 2.0;
02206                 d=an*d+b;
02207                 if (fabs(d) < FPMIN) d=FPMIN;
02208                 c=b+an/c;
02209                 if (fabs(c) < FPMIN) c=FPMIN;
02210                 d=1.0/d;
02211                 del=d*c;
02212                 h *= del;
02213                 if (fabs(del-1.0) < EPS) break;
02214         }
02215         if (i > ITMAX) nrerror("a too large, ITMAX too small in gcf");
02216         *gammcf=exp(-x+a*log(x)-(*gln))*h;
02217 }
02218 #undef ITMAX
02219 #undef EPS
02220 #undef FPMIN
02221 /* (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+). */
02222 
02223 #include <math.h>
02224 #define ITMAX 100
02225 #define EPS 3.0e-7
02226 
02227 void gser(float *gamser, float a, float x, float *gln)
02228 {
02229         float gammln(float xx);
02230         void nrerror(char error_text[]);
02231         int n;
02232         float sum,del,ap;
02233 
02234         *gln=gammln(a);
02235         if (x <= 0.0) {
02236                 if (x < 0.0) nrerror("x less than 0 in routine gser");
02237                 *gamser=0.0;
02238                 return;
02239         } else {
02240                 ap=a;
02241                 del=sum=1.0/a;
02242                 for (n=1;n<=ITMAX;n++) {
02243                         ++ap;
02244                         del *= x/ap;
02245                         sum += del;
02246                         if (fabs(del) < fabs(sum)*EPS) {
02247                                 *gamser=sum*exp(-x+a*log(x)-(*gln));
02248                                 return;
02249                         }
02250                 }
02251                 nrerror("a too large, ITMAX too small in routine gser");
02252                 return;
02253         }
02254 }
02255 #undef ITMAX
02256 #undef EPS
02257 /* (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+). */
02258 
02259 
02260 #include <math.h>
02261 
02262 float gammln(float xx)
02263 {
02264         double x,y,tmp,ser;
02265         static double cof[6]={76.18009172947146,-86.50532032941677,
02266                 24.01409824083091,-1.231739572450155,
02267                 0.1208650973866179e-2,-0.5395239384953e-5};
02268         int j;
02269 
02270         y=x=xx;
02271         tmp=x+5.5;
02272         tmp -= (x+0.5)*log(tmp);
02273         ser=1.000000000190015;
02274         for (j=0;j<=5;j++) ser += cof[j]/++y;
02275         return -tmp+log(2.5066282746310005*ser/x);
02276 }
02277 /* (C) Copr. 1986-92 Numeric*/
02278 
02279 
02280 float gammq(float a, float x)
02281 {
02282         void gcf(float *gammcf, float a, float x, float *gln);
02283         void gser(float *gamser, float a, float x, float *gln);
02284         void nrerror(char error_text[]);
02285         float gamser,gammcf,gln;
02286 
02287         if (x < 0.0 || a <= 0.0) nrerror("Invalid arguments in routine gammq");
02288         if (x < (a+1.0)) {
02289                 gser(&gamser,a,x,&gln);
02290                 return 1.0-gamser;
02291         } else {
02292                 gcf(&gammcf,a,x,&gln);
02293                 return gammcf;
02294         }
02295 }
02296 /* (C) Copr. 1986-92 Numerical Recipes Software *1%:?!$:V3+). */
02297 
02298 
02299 
02300 // ##### End of functions obtained from Numerical Recipes
02301 
02302 
02303 

Generated at Mon Jun 9 20:08:10 2003 for OCS by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000