NFFT Logo 3.1.0 API Reference

legendre.c

00001 /*
00002  * Copyright (c) 2002, 2009 Jens Keiner, Daniel Potts, Stefan Kunis
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: legendre.c 3113 2009-03-13 19:51:55Z keiner $ */
00020 
00021 #include <math.h>
00022 #include <stdio.h>
00023 #include "infft.h"
00024 #include "util.h"
00025 #include "legendre.h"
00026 
00027 /* One over sqrt(pi) */
00028 DK(KSQRTPII,0.56418958354775628694807945156077258584405062932900);
00029 
00030 static inline R alpha_al(const int k, const int n)
00031 {
00032   if (k > 0)
00033   {
00034     if (k < n)
00035       return IF(k%2,K(1.0),K(-1.0));
00036     else
00037       return SQRT(((R)(2*k+1))/((R)(k-n+1))*((R)(2*k+1))/((R)(k+n+1)));
00038   }
00039   else if (k == 0)
00040   {
00041     if (n == 0)
00042       return K(1.0);
00043     else
00044       return IF(n%2,K(0.0),K(-1.0));
00045   }
00046   return K(0.0);
00047 }
00048 
00049 static inline R beta_al(const int k, const int n)
00050 {
00051   if (0 <= k && k < n)
00052     return K(1.0);
00053   else
00054     return K(0.0);
00055 }
00056 
00057 static inline R gamma_al(const int k, const int n)
00058 {
00059   if (k == -1)
00060   {
00061     /* The constant is
00062      *     ((2n)!)^(1/2) / (2^n n!)
00063      *   = sqrt((gamma(n+1/2))/(sqrt(pi)*gamma(n+1))).
00064      */
00065     return SQRT(KSQRTPII*nfft_lambda((R)(n),K(0.5)));
00066   }
00067   else if (k <= n)
00068     return K(0.0);
00069   else
00070     return -SQRT(((R)(k-n))/((R)(k-n+1))*((R)(k+n))/((R)(k+n+1)));
00071 }
00072 
00073 void alpha_al_row(R *alpha, const int N, const int n)
00074 {
00075   int j;
00076   R *p = alpha;
00077   for (j = -1; j <= N; j++)
00078     *p++ = alpha_al(j,n);
00079 }
00080 
00081 void beta_al_row(R *beta, const int N, const int n)
00082 {
00083   int j;
00084   R *p = beta;
00085   for (j = -1; j <= N; j++)
00086     *p++ = beta_al(j,n);
00087 }
00088 
00089 void gamma_al_row(R *gamma, const int N, const int n)
00090 {
00091   int j;
00092   R *p = gamma;
00093   for (j = -1; j <= N; j++)
00094     *p++ = gamma_al(j,n);
00095 }
00096 
00097 inline void alpha_al_all(R *alpha, const int N)
00098 {
00099   int i,j;
00100   R *p = alpha;
00101   for (i = 0; i <= N; i++)
00102     for (j = -1; j <= N; j++)
00103       *p++ = alpha_al(j,i);
00104 }
00105 
00106 inline void beta_al_all(R *alpha, const int N)
00107 {
00108   int i,j;
00109   R *p = alpha;
00110   for (i = 0; i <= N; i++)
00111     for (j = -1; j <= N; j++)
00112       *p++ = beta_al(j,i);
00113 }
00114 
00115 inline void gamma_al_all(R *alpha, const int N)
00116 {
00117   int i,j;
00118   R *p = alpha;
00119   for (i = 0; i <= N; i++)
00120     for (j = -1; j <= N; j++)
00121       *p++ = gamma_al(j,i);
00122 }
00123 
00124 void eval_al(R *x, R *y, const int size, const int k, R *alpha,
00125   R *beta, R *gamma)
00126 {
00127   /* Evaluate the associated Legendre polynomial P_{k,nleg} (l,x) for the vector
00128    * of knots  x[0], ..., x[size-1] by the Clenshaw algorithm
00129    */
00130   int i,j;
00131   R a,b,x_val_act,a_old;
00132   R *x_act, *y_act;
00133   R *alpha_act, *beta_act, *gamma_act;
00134 
00135   /* Traverse all nodes. */
00136   x_act = x;
00137   y_act = y;
00138   for (i = 0; i < size; i++)
00139   {
00140     a = 1.0;
00141     b = 0.0;
00142     x_val_act = *x_act;
00143 
00144     if (k == 0)
00145     {
00146       *y_act = 1.0;
00147     }
00148     else
00149     {
00150       alpha_act = &(alpha[k]);
00151       beta_act = &(beta[k]);
00152       gamma_act = &(gamma[k]);
00153       for (j = k; j > 1; j--)
00154       {
00155         a_old = a;
00156         a = b + a_old*((*alpha_act)*x_val_act+(*beta_act));
00157          b = a_old*(*gamma_act);
00158         alpha_act--;
00159         beta_act--;
00160         gamma_act--;
00161       }
00162       *y_act = (a*((*alpha_act)*x_val_act+(*beta_act))+b);
00163     }
00164     x_act++;
00165     y_act++;
00166   }
00167 }
00168 
00169 int eval_al_thresh(R *x, R *y, const int size, const int k, R *alpha,
00170   R *beta, R *gamma, R threshold)
00171 {
00172   /* Evaluate the associated Legendre polynomial P_{k,nleg} (l,x) for the vector
00173    * of knots  x[0], ..., x[size-1] by the Clenshaw algorithm
00174    */
00175   int i,j;
00176   R a,b,x_val_act,a_old;
00177   R *x_act, *y_act;
00178   R *alpha_act, *beta_act, *gamma_act;
00179 
00180   /* Traverse all nodes. */
00181   x_act = x;
00182   y_act = y;
00183   for (i = 0; i < size; i++)
00184   {
00185     a = 1.0;
00186     b = 0.0;
00187     x_val_act = *x_act;
00188 
00189     if (k == 0)
00190     {
00191      *y_act = 1.0;
00192     }
00193     else
00194     {
00195       alpha_act = &(alpha[k]);
00196       beta_act = &(beta[k]);
00197       gamma_act = &(gamma[k]);
00198       for (j = k; j > 1; j--)
00199       {
00200         a_old = a;
00201         a = b + a_old*((*alpha_act)*x_val_act+(*beta_act));
00202          b = a_old*(*gamma_act);
00203         alpha_act--;
00204         beta_act--;
00205         gamma_act--;
00206       }
00207       *y_act = (a*((*alpha_act)*x_val_act+(*beta_act))+b);
00208       if (fabs(*y_act) > threshold)
00209       {
00210         return 1;
00211       }
00212     }
00213     x_act++;
00214     y_act++;
00215   }
00216   return 0;
00217 }

Generated on 19 Mar 2009 by Doxygen 1.5.3