Rcpp Version 0.9.10
complex.h
Go to the documentation of this file.
00001 // -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*-
00002 //
00003 // complex.h: Rcpp R/C++ interface class library -- complex
00004 //
00005 // Copyright (C) 2010 - 2011 Dirk Eddelbuettel and Romain Francois
00006 //
00007 // This file is part of Rcpp.
00008 //
00009 // Rcpp is free software: you can redistribute it and/or modify it
00010 // under the terms of the GNU General Public License as published by
00011 // the Free Software Foundation, either version 2 of the License, or
00012 // (at your option) any later version.
00013 //
00014 // Rcpp is distributed in the hope that it will be useful, but
00015 // WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU General Public License
00020 // along with Rcpp.  If not, see <http://www.gnu.org/licenses/>.
00021 
00022 #ifndef Rcpp__sugar__complex_h
00023 #define Rcpp__sugar__complex_h
00024 
00025 #ifdef HAVE_HYPOT
00026 # define RCPP_HYPOT ::hypot
00027 #else
00028 # define RCPP_HYPOT ::Rf_pythag
00029 #endif
00030 
00031 namespace Rcpp{
00032 namespace sugar{
00033 
00034         
00035 template <bool NA, typename OUT, typename T, typename FunPtr>
00036 class SugarComplex : public Rcpp::VectorBase< 
00037         Rcpp::traits::r_sexptype_traits<OUT>::rtype , 
00038         NA, 
00039         SugarComplex<NA,OUT,T,FunPtr>
00040         > {
00041 public:
00042         
00043         typedef Rcpp::VectorBase<CPLXSXP,NA,T> VEC_TYPE ;
00044         
00045         SugarComplex( FunPtr ptr_, const VEC_TYPE & vec_) : ptr(ptr_), vec(vec_){}
00046         
00047         inline OUT operator[]( int i) const { 
00048                 Rcomplex x = vec[i] ;
00049                 if( Rcpp::traits::is_na<CPLXSXP>( x ) ) 
00050                         return Rcpp::traits::get_na< Rcpp::traits::r_sexptype_traits<OUT>::rtype >() ;
00051                 return ptr( x ); 
00052         }
00053         inline int size() const { return vec.size() ; }
00054         
00055 private:
00056         FunPtr ptr ;
00057         const VEC_TYPE& vec ;
00058 };
00059 } // sugar
00060 
00061 namespace internal{
00062 inline double complex__Re( Rcomplex x){ return x.r ; }
00063         inline double complex__Im( Rcomplex x){ return x.i ; }
00064         inline double complex__Mod( Rcomplex x){ return ::sqrt( x.i * x.i + x.r * x.r) ; }
00065         inline Rcomplex complex__Conj( Rcomplex x){
00066                 Rcomplex y ;
00067                 y.r = x.r; 
00068                 y.i = -x.i ;
00069                 return y ;
00070         }
00071         // TODO: this does not use HAVE_C99_COMPLEX as in R, perhaps it should
00072         inline Rcomplex complex__exp( Rcomplex x){
00073                 Rcomplex y ;
00074                 double expx = ::exp(x.r);
00075         y.r = expx * ::cos(x.i);
00076         y.i = expx * ::sin(x.i);
00077                 return y ;
00078         }
00079         inline Rcomplex complex__log( Rcomplex x){
00080                 Rcomplex y ;
00081                 y.i = ::atan2(x.i, x.r);
00082                 y.r = ::log( RCPP_HYPOT( x.r, x.i ) );
00083             return y ;
00084         }
00085         inline Rcomplex complex__sqrt(Rcomplex z){
00086             Rcomplex r ;
00087                 double mag;
00088         
00089             if( (mag = RCPP_HYPOT(z.r, z.i)) == 0.0)
00090                 r.r = r.i = 0.0;
00091             else if(z.r > 0) {
00092                 r.r = ::sqrt(0.5 * (mag + z.r) );
00093                 r.i = z.i / r.r / 2;
00094             }
00095             else {
00096                 r.i = ::sqrt(0.5 * (mag - z.r) );
00097                 if(z.i < 0)
00098                     r.i = - r.i;
00099                 r.r = z.i / r.i / 2;
00100             }
00101             return r ;
00102         }
00103         inline Rcomplex complex__cos(Rcomplex z){
00104             Rcomplex r ;
00105             r.r = ::cos(z.r) * ::cosh(z.i);
00106             r.i = - ::sin(z.r) * ::sinh(z.i);
00107             return r ; 
00108         }
00109         inline Rcomplex complex__cosh(Rcomplex z){
00110             Rcomplex r;
00111             r.r = ::cos(-z.i) * ::cosh( z.r);
00112             r.i = - ::sin(-z.i) * ::sinh(z.r);
00113             return r ;
00114         }
00115         inline Rcomplex complex__sin(Rcomplex z){
00116                 Rcomplex r ;
00117             r.r = ::sin(z.r) * ::cosh(z.i);
00118             r.i = ::cos(z.r) * ::sinh(z.i);
00119             return r; 
00120         }
00121         inline Rcomplex complex__tan(Rcomplex z){
00122             Rcomplex r ;
00123                 double x2, y2, den;
00124             x2 = 2.0 * z.r;
00125             y2 = 2.0 * z.i;
00126             den = ::cos(x2) + ::cosh(y2);
00127             r.r = ::sin(x2)/den;
00128             /* any threshold between -log(DBL_EPSILON)
00129                and log(DBL_XMAX) will do*/
00130                if (ISNAN(y2) || ::fabs(y2) < 50.0)
00131                    r.i = ::sinh(y2)/den;
00132                else
00133                    r.i = (y2 <0 ? -1.0 : 1.0);
00134            return r ;
00135         }
00136         
00137 inline Rcomplex complex__asin(Rcomplex z)
00138 {
00139         Rcomplex r ;
00140     double alpha, bet, t1, t2, x, y;
00141     x = z.r;
00142     y = z.i;
00143     t1 = 0.5 * RCPP_HYPOT(x + 1, y);
00144     t2 = 0.5 * RCPP_HYPOT(x - 1, y);
00145     alpha = t1 + t2;
00146     bet = t1 - t2;
00147     r.r = ::asin(bet);
00148     r.i = ::log(alpha + ::sqrt(alpha*alpha - 1));
00149     if(y < 0 || (y == 0 && x > 1)) r.i *= -1;
00150     return r ;
00151 }
00152 
00153 inline Rcomplex complex__acos(Rcomplex z)
00154 {
00155     Rcomplex r, Asin = complex__asin(z);
00156     r.r = M_PI_2 - Asin.r;
00157     r.i = - Asin.i;
00158     return r ;
00159 }
00160 
00161         /* Complex Arctangent Function */
00162         /* Equation (4.4.39) Abramowitz and Stegun */
00163         /* with additional terms to force the branch cuts */
00164         /* to agree with figure 4.4, p79.  Continuity */
00165         /* on the branch cuts (pure imaginary axis; x==0, |y|>1) */
00166         /* is standard: z_asin() is continuous from the right */
00167         /*  if y >= 1, and continuous from the left if y <= -1. */
00168 
00169 inline Rcomplex complex__atan(Rcomplex z)
00170 {
00171     Rcomplex r; 
00172     double x, y;
00173     x = z.r;
00174     y = z.i;
00175     r.r = 0.5 * ::atan(2 * x / ( 1 - x * x - y * y));
00176     r.i = 0.25 * ::log((x * x + (y + 1) * (y + 1)) /
00177                       (x * x + (y - 1) * (y - 1)));
00178     if(x*x + y*y > 1) {
00179         r.r += M_PI_2;
00180         if(x < 0 || (x == 0 && y < 0)) r.r -= M_PI;
00181     }
00182     return r ;
00183 }
00184         
00185         
00186         inline Rcomplex complex__acosh(Rcomplex z){
00187             Rcomplex r, a = complex__acos(z);
00188             r.r = -a.i;
00189             r.i = a.r;
00190             return r ;
00191         }
00192         
00193         inline Rcomplex complex__asinh(Rcomplex z){
00194             Rcomplex r, b;
00195             b.r = -z.i;
00196             b.i =  z.r;
00197             Rcomplex a = complex__asin(b);
00198             r.r =  a.i;
00199             r.i = -a.r;
00200             return r ;
00201         }
00202         
00203         inline Rcomplex complex__atanh(Rcomplex z){
00204             Rcomplex r, b;
00205             b.r = -z.i;
00206             b.i =  z.r;
00207             Rcomplex a = complex__atan(b);
00208             r.r =  a.i;
00209             r.i = -a.r;
00210             return r ;
00211         }
00212 inline Rcomplex complex__sinh(Rcomplex z)
00213 {
00214     Rcomplex r, b;
00215     b.r = -z.i;
00216     b.i =  z.r;
00217     Rcomplex a = complex__sin(b);
00218     r.r =  a.i;
00219     r.i = -a.r;
00220     return r ;
00221 }
00222 
00223 inline Rcomplex complex__tanh(Rcomplex z)
00224 {
00225     Rcomplex r, b;
00226     b.r = -z.i;
00227     b.i =  z.r;
00228     Rcomplex a = complex__tan(b);
00229     r.r =  a.i;
00230     r.i = -a.r;
00231     return r ;
00232 }
00233 
00234         
00235 
00236 } // internal
00237 
00238 #define RCPP_SUGAR_COMPLEX(__NAME__,__OUT__)                                \
00239         template <bool NA, typename T>                                          \
00240         inline sugar::SugarComplex<NA,__OUT__,T, __OUT__ (*)(Rcomplex) >        \
00241         __NAME__(                                                               \
00242                 const VectorBase<CPLXSXP,NA,T>& t                                   \
00243                 ){                                                                  \
00244                 return sugar::SugarComplex<NA,__OUT__,T, __OUT__ (*)(Rcomplex) >(   \
00245                         internal::complex__##__NAME__, t                                \
00246                 ) ;                                                                 \
00247         }
00248 
00249 RCPP_SUGAR_COMPLEX( Re, double )
00250 RCPP_SUGAR_COMPLEX( Im, double )
00251 RCPP_SUGAR_COMPLEX( Mod, double )
00252 RCPP_SUGAR_COMPLEX( Conj, Rcomplex )
00253 RCPP_SUGAR_COMPLEX( exp, Rcomplex )
00254 RCPP_SUGAR_COMPLEX( log, Rcomplex )
00255 RCPP_SUGAR_COMPLEX( sqrt, Rcomplex )
00256 RCPP_SUGAR_COMPLEX( cos, Rcomplex ) 
00257 RCPP_SUGAR_COMPLEX( sin, Rcomplex )
00258 RCPP_SUGAR_COMPLEX( tan, Rcomplex )
00259 RCPP_SUGAR_COMPLEX( acos, Rcomplex ) 
00260 RCPP_SUGAR_COMPLEX( asin, Rcomplex )
00261 RCPP_SUGAR_COMPLEX( atan, Rcomplex )
00262 RCPP_SUGAR_COMPLEX( acosh, Rcomplex ) 
00263 RCPP_SUGAR_COMPLEX( asinh, Rcomplex )
00264 RCPP_SUGAR_COMPLEX( atanh, Rcomplex )
00265 RCPP_SUGAR_COMPLEX( cosh, Rcomplex )
00266 RCPP_SUGAR_COMPLEX( sinh, Rcomplex )
00267 RCPP_SUGAR_COMPLEX( tanh, Rcomplex )
00268 
00269 #undef RCPP_SUGAR_COMPLEX        
00270         
00271 } // Rcpp
00272 #endif
00273 
 All Classes Namespaces Files Functions Variables Typedefs Enumerator Friends Defines