EVOLUTION-MANAGER
Edit File: complex.h
// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 8 -*- // // complex.h: Rcpp R/C++ interface class library -- complex // // Copyright (C) 2010 - 2018 Dirk Eddelbuettel and Romain Francois // // This file is part of Rcpp. // // Rcpp is free software: you can redistribute it and/or modify it // under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 2 of the License, or // (at your option) any later version. // // Rcpp is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with Rcpp. If not, see <http://www.gnu.org/licenses/>. #ifndef Rcpp__sugar__complex_h #define Rcpp__sugar__complex_h namespace Rcpp{ namespace sugar{ template <bool NA, typename RESULT_TYPE, typename T, typename FunPtr> class SugarComplex : public Rcpp::VectorBase< Rcpp::traits::r_sexptype_traits<RESULT_TYPE>::rtype , NA, SugarComplex<NA,RESULT_TYPE,T,FunPtr> > { public: typedef Rcpp::VectorBase<CPLXSXP,NA,T> VEC_TYPE ; SugarComplex( FunPtr ptr_, const VEC_TYPE & vec_) : ptr(ptr_), vec(vec_){} inline RESULT_TYPE operator[]( R_xlen_t i) const { Rcomplex x = vec[i] ; if( Rcpp::traits::is_na<CPLXSXP>( x ) ) return Rcpp::traits::get_na< Rcpp::traits::r_sexptype_traits<RESULT_TYPE>::rtype >() ; return ptr( x ); } inline R_xlen_t size() const { return vec.size() ; } private: FunPtr ptr ; const VEC_TYPE& vec ; }; } // sugar namespace internal{ inline double complex__Re( Rcomplex x){ return x.r ; } inline double complex__Im( Rcomplex x){ return x.i ; } inline double complex__Mod( Rcomplex x){ return ::sqrt( x.i * x.i + x.r * x.r) ; } inline Rcomplex complex__Conj( Rcomplex x){ Rcomplex y ; y.r = x.r; y.i = -x.i ; return y ; } inline double complex__Arg( Rcomplex x ){ return ::atan2(x.i, x.r); } // TODO: this does not use HAVE_C99_COMPLEX as in R, perhaps it should inline Rcomplex complex__exp( Rcomplex x){ Rcomplex y ; double expx = ::exp(x.r); y.r = expx * ::cos(x.i); y.i = expx * ::sin(x.i); return y ; } inline Rcomplex complex__log( Rcomplex x){ Rcomplex y ; y.i = ::atan2(x.i, x.r); y.r = ::log(::hypot(x.r, x.i)); return y ; } inline Rcomplex complex__sqrt(Rcomplex z){ Rcomplex r ; double mag; if( (mag = ::hypot(z.r, z.i)) == 0.0) r.r = r.i = 0.0; else if(z.r > 0) { r.r = ::sqrt(0.5 * (mag + z.r) ); r.i = z.i / r.r / 2; } else { r.i = ::sqrt(0.5 * (mag - z.r) ); if(z.i < 0) r.i = - r.i; r.r = z.i / r.i / 2; } return r ; } inline Rcomplex complex__cos(Rcomplex z){ Rcomplex r ; r.r = ::cos(z.r) * ::cosh(z.i); r.i = - ::sin(z.r) * ::sinh(z.i); return r ; } inline Rcomplex complex__cosh(Rcomplex z){ Rcomplex r; r.r = ::cos(-z.i) * ::cosh( z.r); r.i = - ::sin(-z.i) * ::sinh(z.r); return r ; } inline Rcomplex complex__sin(Rcomplex z){ Rcomplex r ; r.r = ::sin(z.r) * ::cosh(z.i); r.i = ::cos(z.r) * ::sinh(z.i); return r; } inline Rcomplex complex__tan(Rcomplex z){ Rcomplex r ; double x2, y2, den; x2 = 2.0 * z.r; y2 = 2.0 * z.i; den = ::cos(x2) + ::cosh(y2); r.r = ::sin(x2)/den; /* any threshold between -log(DBL_EPSILON) and log(DBL_XMAX) will do*/ if (ISNAN(y2) || ::fabs(y2) < 50.0) r.i = ::sinh(y2)/den; else r.i = (y2 <0 ? -1.0 : 1.0); return r ; } inline Rcomplex complex__asin(Rcomplex z) { Rcomplex r ; double alpha, bet, t1, t2, x, y; x = z.r; y = z.i; t1 = 0.5 * ::hypot(x + 1, y); t2 = 0.5 * ::hypot(x - 1, y); alpha = t1 + t2; bet = t1 - t2; r.r = ::asin(bet); r.i = ::log(alpha + ::sqrt(alpha*alpha - 1)); if(y < 0 || (y == 0 && x > 1)) r.i *= -1; return r ; } inline Rcomplex complex__acos(Rcomplex z) { Rcomplex r, Asin = complex__asin(z); r.r = M_PI_2 - Asin.r; r.i = - Asin.i; return r ; } /* Complex Arctangent Function */ /* Equation (4.4.39) Abramowitz and Stegun */ /* with additional terms to force the branch cuts */ /* to agree with figure 4.4, p79. Continuity */ /* on the branch cuts (pure imaginary axis; x==0, |y|>1) */ /* is standard: z_asin() is continuous from the right */ /* if y >= 1, and continuous from the left if y <= -1. */ inline Rcomplex complex__atan(Rcomplex z) { Rcomplex r; double x, y; x = z.r; y = z.i; r.r = 0.5 * ::atan(2 * x / ( 1 - x * x - y * y)); r.i = 0.25 * ::log((x * x + (y + 1) * (y + 1)) / (x * x + (y - 1) * (y - 1))); if(x*x + y*y > 1) { r.r += M_PI_2; if(x < 0 || (x == 0 && y < 0)) r.r -= M_PI; } return r ; } inline Rcomplex complex__acosh(Rcomplex z){ Rcomplex r, a = complex__acos(z); r.r = -a.i; r.i = a.r; return r ; } inline Rcomplex complex__asinh(Rcomplex z){ Rcomplex r, b; b.r = -z.i; b.i = z.r; Rcomplex a = complex__asin(b); r.r = a.i; r.i = -a.r; return r ; } inline Rcomplex complex__atanh(Rcomplex z){ Rcomplex r, b; b.r = -z.i; b.i = z.r; Rcomplex a = complex__atan(b); r.r = a.i; r.i = -a.r; return r ; } inline Rcomplex complex__sinh(Rcomplex z) { Rcomplex r, b; b.r = -z.i; b.i = z.r; Rcomplex a = complex__sin(b); r.r = a.i; r.i = -a.r; return r ; } inline Rcomplex complex__tanh(Rcomplex z) { Rcomplex r, b; b.r = -z.i; b.i = z.r; Rcomplex a = complex__tan(b); r.r = a.i; r.i = -a.r; return r ; } } // internal #define RCPP_SUGAR_COMPLEX(__NAME__,__OUT__) \ template <bool NA, typename T> \ inline sugar::SugarComplex<NA,__OUT__,T, __OUT__ (*)(Rcomplex) > \ __NAME__(const VectorBase<CPLXSXP,NA,T>& t) { \ return sugar::SugarComplex<NA,__OUT__,T, __OUT__ (*)(Rcomplex) >( \ internal::complex__##__NAME__, t); \ } RCPP_SUGAR_COMPLEX( Re, double ) RCPP_SUGAR_COMPLEX( Im, double ) RCPP_SUGAR_COMPLEX( Mod, double ) RCPP_SUGAR_COMPLEX( Arg, double ) RCPP_SUGAR_COMPLEX( Conj, Rcomplex ) RCPP_SUGAR_COMPLEX( exp, Rcomplex ) RCPP_SUGAR_COMPLEX( log, Rcomplex ) RCPP_SUGAR_COMPLEX( sqrt, Rcomplex ) RCPP_SUGAR_COMPLEX( cos, Rcomplex ) RCPP_SUGAR_COMPLEX( sin, Rcomplex ) RCPP_SUGAR_COMPLEX( tan, Rcomplex ) RCPP_SUGAR_COMPLEX( acos, Rcomplex ) RCPP_SUGAR_COMPLEX( asin, Rcomplex ) RCPP_SUGAR_COMPLEX( atan, Rcomplex ) RCPP_SUGAR_COMPLEX( acosh, Rcomplex ) RCPP_SUGAR_COMPLEX( asinh, Rcomplex ) RCPP_SUGAR_COMPLEX( atanh, Rcomplex ) RCPP_SUGAR_COMPLEX( cosh, Rcomplex ) RCPP_SUGAR_COMPLEX( sinh, Rcomplex ) RCPP_SUGAR_COMPLEX( tanh, Rcomplex ) #undef RCPP_SUGAR_COMPLEX } // Rcpp #endif