NFFT Logo 3.1.0 API Reference

wigner.c

00001 /*
00002  * Copyright (c) 2002, 2009 Jens Keiner, Stefan Kunis, Daniel Potts
00003  *
00004  * This program is free software; you can redistribute it and/or modify it under
00005  * the terms of the GNU General Public License as published by the Free Software
00006  * Foundation; either version 2 of the License, or (at your option) any later
00007  * version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but WITHOUT
00010  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00012  * details.
00013  *
00014  * You should have received a copy of the GNU General Public License along with
00015  * this program; if not, write to the Free Software Foundation, Inc., 51
00016  * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 /* $Id: wigner.c 3114 2009-03-15 15:23:32Z vollrath $ */
00020 
00021 #include <math.h>
00022 #include <stdio.h>
00023 #include "infft.h"
00024 #include "wigner.h"
00025 
00026 double SO3_gamma(int m1, int m2, int j)
00027 {
00028   double dj, dm1, dm2, M, mini;
00029   static int i;
00030   static double result;
00031 
00032   dj = (double) j;
00033   dm1 = (double) m1;
00034   dm2 = (double) m2;
00035   M = (double) (ABS(m1) > ABS(m2) ? ABS(m1) : ABS(m2));
00036   mini = (double) (ABS(m1) < ABS(m2) ? ABS(m1) : ABS(m2));
00037 
00038   if (j == -1)
00039   {
00040     /* Constant is ((2n)!)^(1/2) / (2^n n!). */
00041     result = 1.0;
00042     for (i = 1; i <= M - mini; i++)
00043     {
00044 
00045       result *= (M + mini + i) / (4.0 * i);
00046     }
00047 
00048     if (m1 < m2 && (ABS(m1) + ABS(m2)) % 2 == 1)
00049       result = -(1 / POW(2, mini) * SQRT(result));
00050     else
00051       result = (1 / POW(2, mini) * SQRT(result));
00052 
00053     return result;
00054 
00055   }
00056   else if (j <= M)
00057   {
00058     return (0.0);
00059   }
00060   else
00061   {
00062     return (
00063     //SQRT( (2.*dj + 3.)/(2.*dj - 1.) ) *
00064     -(dj + 1.) / SQRT(((dj + 1.) * (dj + 1.) - dm1 * dm1) * ((dj + 1.) * (dj
00065         + 1.) - dm2 * dm2)) * SQRT((dj * dj - dm1 * dm1)
00066         * (dj * dj - dm2 * dm2)) / dj);
00067   }
00068 }
00069 
00070 inline double SO3_alpha(int m1, int m2, int j)
00071 {
00072   double dj, dm1, dm2, M, mini, neg;
00073   dj = (double) j;
00074   dm1 = (double) m1;
00075   dm2 = (double) m2;
00076   M = (double) (ABS(m1) > ABS(m2) ? ABS(m1) : ABS(m2));
00077   mini = (double) (ABS(m1) < ABS(m2) ? ABS(m1) : ABS(m2));
00078 
00081   if ((dm1 < 0 && dm2 >= 0) || (dm2 < 0 && dm1 >= 0))
00082   {
00083     neg = -1.0;
00084   }
00085   else
00086   {
00087     neg = 1.0;
00088   }
00089 
00090   if (j == -1)
00091   {
00092     return (0.0);
00093   }
00094   else if (j == 0)
00095   {
00096     if (dm1 == dm2)
00097     {
00098       return 1.0;
00099     }
00100     else
00101     {
00102       return (int) (dm1 + dm2) % 2 == 0 ? -1.0 : 0.0;
00103     }
00104   }
00105   else if (j < M - mini)
00106   {
00107     return j % 2 == 0 ? -1.0 : 1.0;
00108   }
00109   else if (j < M)
00110   {
00111     return 1.0 * neg;
00112   }
00113   else
00114   {
00115     return (
00116 
00117     //SQRT( (2.*dj + 3.)/(2.*dj + 1.) ) *
00118     (dj + 1.) * (2. * dj + 1.) / SQRT(((dj + 1.) * (dj + 1.) - dm1 * dm1)
00119         * ((dj + 1.) * (dj + 1.) - dm2 * dm2)));
00120   }
00121 }
00122 
00123 double SO3_beta(int m1, int m2, int j)
00124 {
00125   double dj, dm1, dm2, M, mini;
00126 
00127   dj = (double) j;
00128   dm1 = (double) m1;
00129   dm2 = (double) m2;
00130   M = (double) (ABS(m1) > ABS(m2) ? ABS(m1) : ABS(m2));
00131   mini = (double) (ABS(m1) < ABS(m2) ? ABS(m1) : ABS(m2));
00132 
00133   if (0 <= j && j < M)
00134   {
00135     return (1.0);
00136 
00137   }
00138   else
00139   {
00140     if (dm1 == 0. || dm2 == 0.)
00141       return (0.0);
00142     else
00143       return ((-dm1 * dm2 * (2. * dj + 1.) / dj) / SQRT(((dj + 1.) * (dj + 1.)
00144           - dm1 * dm1) * ((dj + 1.) * (dj + 1.) - dm2 * dm2)));
00145   }
00146 
00147 }
00148 
00149 /*compute the coefficients for all degrees*/
00150 
00151 inline void SO3_alpha_row(double *alpha, int N, int k, int m)
00152 {
00153   int j;
00154   double *alpha_act = alpha;
00155   for (j = -1; j <= N; j++)
00156   {
00157     *alpha_act = SO3_alpha(k, m, j);
00158     alpha_act++;
00159   }
00160 }
00161 
00162 inline void SO3_beta_row(double *beta, int N, int k, int m)
00163 {
00164   int j;
00165   double *beta_act = beta;
00166   for (j = -1; j <= N; j++)
00167   {
00168     *beta_act = SO3_beta(k, m, j);
00169     beta_act++;
00170   }
00171 }
00172 
00173 inline void SO3_gamma_row(double *gamma, int N, int k, int m)
00174 {
00175   int j;
00176   double *gamma_act = gamma;
00177   for (j = -1; j <= N; j++)
00178   {
00179     *gamma_act = SO3_gamma(k, m, j);
00180     gamma_act++;
00181   }
00182 }
00183 
00184 /*compute for all degrees l and orders k*/
00185 
00186 inline void SO3_alpha_matrix(double *alpha, int N, int m)
00187 {
00188   int i, j;
00189   double *alpha_act = alpha;
00190   for (i = -N; i <= N; i++)
00191   {
00192     for (j = -1; j <= N; j++)
00193     {
00194       *alpha_act = SO3_alpha(i, m, j);
00195       alpha_act++;
00196     }
00197   }
00198 }
00199 
00200 inline void SO3_beta_matrix(double *alpha, int N, int m)
00201 {
00202   int i, j;
00203   double *alpha_act = alpha;
00204   for (i = -N; i <= N; i++)
00205   {
00206     for (j = -1; j <= N; j++)
00207     {
00208       *alpha_act = SO3_beta(i, m, j);
00209       alpha_act++;
00210     }
00211   }
00212 }
00213 
00214 inline void SO3_gamma_matrix(double *alpha, int N, int m)
00215 {
00216   int i, j;
00217   double *alpha_act = alpha;
00218   for (i = -N; i <= N; i++)
00219   {
00220     for (j = -1; j <= N; j++)
00221     {
00222       *alpha_act = SO3_gamma(i, m, j);
00223       alpha_act++;
00224     }
00225   }
00226 }
00227 
00228 /*compute all 3termrecurrence coeffs*/
00229 
00230 inline void SO3_alpha_all(double *alpha, int N)
00231 {
00232   int q;
00233   int i, j, m;
00234   double *alpha_act = alpha;
00235   q = 0;
00236   for (m = -N; m <= N; m++)
00237   {
00238     for (i = -N; i <= N; i++)
00239     {
00240       for (j = -1; j <= N; j++)
00241       {
00242         *alpha_act = SO3_alpha(i, m, j);
00243         fprintf(stdout, "alpha_all_%d^[%d,%d]=%f\n", j, i, m,
00244             SO3_alpha(i, m, j));
00245         alpha_act++;
00246         q = q + 1;
00247 
00248       }
00249     }
00250   }
00251 }
00252 
00253 inline void SO3_beta_all(double *alpha, int N)
00254 {
00255   int i, j, m;
00256   double *alpha_act = alpha;
00257   for (m = -N; m <= N; m++)
00258   {
00259     for (i = -N; i <= N; i++)
00260     {
00261       for (j = -1; j <= N; j++)
00262       {
00263         *alpha_act = SO3_beta(i, m, j);
00264         alpha_act++;
00265       }
00266     }
00267   }
00268 }
00269 
00270 inline void SO3_gamma_all(double *alpha, int N)
00271 {
00272   int i, j, m;
00273   double *alpha_act = alpha;
00274   for (m = -N; m <= N; m++)
00275   {
00276     for (i = -N; i <= N; i++)
00277     {
00278       for (j = -1; j <= N; j++)
00279       {
00280         *alpha_act = SO3_gamma(i, m, j);
00281         alpha_act++;
00282       }
00283     }
00284   }
00285 }
00286 
00287 inline void eval_wigner(double *x, double *y, int size, int k, double *alpha,
00288     double *beta, double *gamma)
00289 {
00290   /* Evaluate the wigner function d_{k,nleg} (l,x) for the vector
00291    * of knots  x[0], ..., x[size-1] by the Clenshaw algorithm
00292    */
00293   int i, j;
00294   double a, b, x_val_act, a_old;
00295   double *x_act, *y_act;
00296   double *alpha_act, *beta_act, *gamma_act;
00297 
00298   /* Traverse all nodes. */
00299   x_act = x;
00300   y_act = y;
00301   for (i = 0; i < size; i++)
00302   {
00303     a = 1.0;
00304     b = 0.0;
00305     x_val_act = *x_act;
00306 
00307     if (k == 0)
00308     {
00309       *y_act = 1.0;
00310     }
00311     else
00312     {
00313       alpha_act = &(alpha[k]);
00314       beta_act = &(beta[k]);
00315       gamma_act = &(gamma[k]);
00316       for (j = k; j > 1; j--)
00317       {
00318         a_old = a;
00319         a = b + a_old * ((*alpha_act) * x_val_act + (*beta_act));
00320         b = a_old * (*gamma_act);
00321         alpha_act--;
00322         beta_act--;
00323         gamma_act--;
00324       }
00325       *y_act = (a * ((*alpha_act) * x_val_act + (*beta_act)) + b);
00326     }
00327     x_act++;
00328     y_act++;
00329   }
00330 }
00331 
00332 inline int eval_wigner_thresh(double *x, double *y, int size, int k,
00333     double *alpha, double *beta, double *gamma, double threshold)
00334 {
00335 
00336   int i, j;
00337   double a, b, x_val_act, a_old;
00338   double *x_act, *y_act;
00339   double *alpha_act, *beta_act, *gamma_act;
00340 
00341   /* Traverse all nodes. */
00342   x_act = x;
00343   y_act = y;
00344   for (i = 0; i < size; i++)
00345   {
00346     a = 1.0;
00347     b = 0.0;
00348     x_val_act = *x_act;
00349 
00350     if (k == 0)
00351     {
00352       *y_act = 1.0;
00353     }
00354     else
00355     {
00356       alpha_act = &(alpha[k]);
00357       beta_act = &(beta[k]);
00358       gamma_act = &(gamma[k]);
00359       for (j = k; j > 1; j--)
00360       {
00361         a_old = a;
00362         a = b + a_old * ((*alpha_act) * x_val_act + (*beta_act));
00363         b = a_old * (*gamma_act);
00364         alpha_act--;
00365         beta_act--;
00366         gamma_act--;
00367       }
00368       *y_act = (a * ((*alpha_act) * x_val_act + (*beta_act)) + b);
00369       if (fabs(*y_act) > threshold)
00370       {
00371         return 1;
00372       }
00373     }
00374     x_act++;
00375     y_act++;
00376   }
00377   return 0;
00378 }
00379 
00380 /************************************************************************/
00381 /* L2 normed wigner little d, WHERE THE DEGREE OF THE FUNCTION IS EQUAL
00382  TO ONE OF ITS ORDERS. This is the function to use when starting the
00383  three-term recurrence at orders (m1,m2)
00384 
00385  Note that, by definition, since I am starting the recurrence with this
00386  function, that the degree j of the function is equal to max(abs(m1), abs(m2) ).
00387  */
00388 
00389 double wigner_start(int m1, int m2, double theta)
00390 {
00391 
00392   int i, l, delta;
00393   int cosPower, sinPower;
00394   int absM1, absM2;
00395   double dl, dm1, dm2, normFactor, sinSign;
00396   double dCP, dSP;
00397   double max;
00398   double min;
00399 
00400   max = (double) (ABS(m1) > ABS(m2) ? ABS(m1) : ABS(m2));
00401   min = (double) (ABS(m1) < ABS(m2) ? ABS(m1) : ABS(m2));
00402 
00403   l = max;
00404   delta = l - min;
00405 
00406   absM1 = ABS(m1);
00407   absM2 = ABS(m2);
00408   dl = (double) l;
00409   dm1 = (double) m1;
00410   dm2 = (double) m2;
00411   sinSign = 1.;
00412   normFactor = 1.;
00413 
00414   for (i = 0; i < delta; i++)
00415     normFactor *= SQRT((2. * dl - ((double) i)) / (((double) i) + 1.));
00416 
00417   /* need to adjust to make the L2-norm equal to 1 */
00418 
00419   normFactor *= SQRT((2. * dl + 1.) / 2.);
00420 
00421   if (l == absM1)
00422     if (m1 >= 0)
00423     {
00424       cosPower = l + m2;
00425       sinPower = l - m2;
00426       if ((l - m2) % 2)
00427         sinSign = -1.;
00428     }
00429     else
00430     {
00431       cosPower = l - m2;
00432       sinPower = l + m2;
00433     }
00434   else if (m2 >= 0)
00435   {
00436     cosPower = l + m1;
00437     sinPower = l - m1;
00438   }
00439   else
00440   {
00441     cosPower = l - m1;
00442     sinPower = l + m1;
00443     if ((l + m1) % 2)
00444       sinSign = -1.;
00445   }
00446 
00447   dCP = (double) cosPower;
00448   dSP = (double) sinPower;
00449 
00450   return normFactor * sinSign * POW(sin(theta / 2), dSP) * POW(cos(theta / 2),
00451       dCP);
00452 }

Generated on 19 Mar 2009 by Doxygen 1.5.3