sl@0: /*
sl@0:  * © Portions copyright (c) 2006-2007 Nokia Corporation.  All rights reserved.
sl@0:  *
sl@0:  * Copyright (c) 1999
sl@0:  * Silicon Graphics Computer Systems, Inc.
sl@0:  *
sl@0:  * Copyright (c) 1999 
sl@0:  * Boris Fomitchev
sl@0:  *
sl@0:  * This material is provided "as is", with absolutely no warranty expressed
sl@0:  * or implied. Any use is at your own risk.
sl@0:  *
sl@0:  * Permission to use or copy this software for any purpose is hereby granted 
sl@0:  * without fee, provided the above notices are retained on all copies.
sl@0:  * Permission to modify the code and to distribute modified code is granted,
sl@0:  * provided the above notices are retained, and a notice that the code was
sl@0:  * modified is included with the above copyright notice.
sl@0:  *
sl@0:  */ 
sl@0: # include "stlport_prefix.h"
sl@0: // Complex division and square roots.
sl@0: 
sl@0: #include "complex_impl.h"
sl@0: #ifdef __ARMCC__
sl@0: #undef _STLP_TEMPLATE_NULL
sl@0: #define _STLP_TEMPLATE_NULL 
sl@0: #endif
sl@0: _STLP_BEGIN_NAMESPACE
sl@0: 
sl@0: // Absolute value
sl@0: #ifdef __SYMBIAN32__
sl@0: 
sl@0: float abs_l(const complex<float>& __z)
sl@0: {
sl@0:   return _STLP_HYPOTF(__z._M_re, __z._M_im);
sl@0: }
sl@0: 
sl@0: double _STLP_CALL abs_l(const complex<double>& __z)
sl@0: {
sl@0:   return _STLP_HYPOT(__z._M_re, __z._M_im);
sl@0: }
sl@0: 
sl@0: #ifndef _STLP_NO_LONG_DOUBLE
sl@0: long double _STLP_CALL abs_l(const complex<long double>& __z)
sl@0: {
sl@0:   return _STLP_HYPOTL(__z._M_re, __z._M_im);
sl@0: }
sl@0: #endif
sl@0: #else
sl@0: _STLP_TEMPLATE_NULL
sl@0: _STLP_EXP_DECLSPEC float _STLP_CALL abs(const complex<float>& __z)
sl@0: {
sl@0:   return _STLP_HYPOTF(__z._M_re, __z._M_im);
sl@0: }
sl@0: _STLP_TEMPLATE_NULL
sl@0: _STLP_EXP_DECLSPEC double _STLP_CALL abs(const complex<double>& __z)
sl@0: {
sl@0:   return _STLP_HYPOT(__z._M_re, __z._M_im);
sl@0: }
sl@0: 
sl@0: #ifndef _STLP_NO_LONG_DOUBLE
sl@0: _STLP_TEMPLATE_NULL
sl@0: _STLP_EXP_DECLSPEC long double _STLP_CALL abs(const complex<long double>& __z)
sl@0: {
sl@0:   return _STLP_HYPOTL(__z._M_re, __z._M_im);
sl@0: }
sl@0: #endif
sl@0: #endif
sl@0: 
sl@0: // Phase
sl@0: #ifdef __SYMBIAN32__
sl@0: 
sl@0: float _STLP_CALL arg_l(const complex<float>& __z) 
sl@0: {
sl@0:   return _STLP_ATAN2F(__z._M_im, __z._M_re);
sl@0: }
sl@0: 
sl@0: 
sl@0: double _STLP_CALL arg_l(const complex<double>& __z) 
sl@0: {
sl@0:   return _STLP_ATAN2(__z._M_im, __z._M_re);
sl@0: }
sl@0: 
sl@0: #ifndef _STLP_NO_LONG_DOUBLE
sl@0: long double _STLP_CALL arg_l(const complex<long double>& __z) 
sl@0: {
sl@0:   return _STLP_ATAN2L(__z._M_im, __z._M_re);
sl@0: }
sl@0: #endif
sl@0: #else
sl@0: 
sl@0: _STLP_TEMPLATE_NULL 
sl@0: _STLP_EXP_DECLSPEC float _STLP_CALL arg(const complex<float>& __z) 
sl@0: {
sl@0:   return _STLP_ATAN2F(__z._M_im, __z._M_re);
sl@0: }
sl@0: 
sl@0: _STLP_TEMPLATE_NULL 
sl@0: _STLP_EXP_DECLSPEC double _STLP_CALL arg(const complex<double>& __z) 
sl@0: {
sl@0:   return _STLP_ATAN2(__z._M_im, __z._M_re);
sl@0: }
sl@0: 
sl@0: #ifndef _STLP_NO_LONG_DOUBLE
sl@0: _STLP_TEMPLATE_NULL
sl@0: _STLP_EXP_DECLSPEC long double _STLP_CALL arg(const complex<long double>& __z) 
sl@0: {
sl@0:   return _STLP_ATAN2L(__z._M_im, __z._M_re);
sl@0: }
sl@0: #endif
sl@0: #endif
sl@0: 
sl@0: // Construct a complex number from polar representation
sl@0: #ifdef __SYMBIAN32__
sl@0: complex<float> _STLP_CALL polar_l(const float& __rho, const float& __phi) 
sl@0: {
sl@0:   return complex<float>(__rho * _STLP_COSF(__phi), __rho * _STLP_SINF(__phi));
sl@0: }
sl@0: 
sl@0: complex<double> _STLP_CALL polar_l(const double& __rho, const double& __phi) 
sl@0: {
sl@0:   return complex<double>(__rho * _STLP_COS(__phi), __rho * _STLP_SIN(__phi));
sl@0: }
sl@0: 
sl@0: #ifndef _STLP_NO_LONG_DOUBLE
sl@0: complex<long double> _STLP_CALL polar_l(const long double& __rho, const long double& __phi)
sl@0: {
sl@0:   return complex<long double>(__rho * _STLP_COSL(__phi), __rho * _STLP_SINL(__phi));
sl@0: }
sl@0: #endif
sl@0: 
sl@0: #else
sl@0: _STLP_TEMPLATE_NULL
sl@0: _STLP_EXP_DECLSPEC complex<float> _STLP_CALL polar(const float& __rho, const float& __phi) 
sl@0: {
sl@0:   return complex<float>(__rho * _STLP_COSF(__phi), __rho * _STLP_SINF(__phi));
sl@0: }
sl@0: _STLP_TEMPLATE_NULL
sl@0: _STLP_EXP_DECLSPEC complex<double> _STLP_CALL polar(const double& __rho, const double& __phi) 
sl@0: {
sl@0:   return complex<double>(__rho * _STLP_COS(__phi), __rho * _STLP_SIN(__phi));
sl@0: }
sl@0: 
sl@0: #ifndef _STLP_NO_LONG_DOUBLE
sl@0: _STLP_TEMPLATE_NULL 
sl@0: _STLP_EXP_DECLSPEC complex<long double> _STLP_CALL polar(const long double& __rho, const long double& __phi)
sl@0: {
sl@0:   return complex<long double>(__rho * _STLP_COSL(__phi), __rho * _STLP_SINL(__phi));
sl@0: }
sl@0: #endif
sl@0: 
sl@0: #endif
sl@0: // Division
sl@0: 
sl@0: void  _STLP_EXP_DECLSPEC
sl@0: complex<float>::_div(const float& __z1_r, const float& __z1_i,
sl@0: 		     const float& __z2_r, const float& __z2_i,
sl@0: 		     float& __res_r, float& __res_i) {
sl@0:   float __ar = __z2_r >= 0 ? __z2_r : -__z2_r;
sl@0:   float __ai = __z2_i >= 0 ? __z2_i : -__z2_i;
sl@0: 
sl@0:   if (__ar <= __ai) {
sl@0:     float __ratio = __z2_r / __z2_i;
sl@0:     float __denom = __z2_i * (1 + __ratio * __ratio);
sl@0:     __res_r = (__z1_r * __ratio + __z1_i) / __denom;
sl@0:     __res_i = (__z1_i * __ratio - __z1_r) / __denom;
sl@0:   }
sl@0:   else {
sl@0:     float __ratio = __z2_i / __z2_r;
sl@0:     float __denom = __z2_r * (1 + __ratio * __ratio);
sl@0:     __res_r = (__z1_r + __z1_i * __ratio) / __denom;
sl@0:     __res_i = (__z1_i - __z1_r * __ratio) / __denom;
sl@0:   }
sl@0: }
sl@0: 
sl@0: void  _STLP_EXP_DECLSPEC
sl@0: complex<float>::_div(const float& __z1_r,
sl@0:                      const float& __z2_r, const float& __z2_i,
sl@0:                      float& __res_r, float& __res_i) {
sl@0:   float __ar = __z2_r >= 0 ? __z2_r : -__z2_r;
sl@0:   float __ai = __z2_i >= 0 ? __z2_i : -__z2_i;
sl@0: 
sl@0:   if (__ar <= __ai) {
sl@0:     float __ratio = __z2_r / __z2_i;
sl@0:     float __denom = __z2_i * (1 + __ratio * __ratio);
sl@0:     __res_r = (__z1_r * __ratio) / __denom;
sl@0:     __res_i = - __z1_r / __denom;
sl@0:   }
sl@0:   else {
sl@0:     float __ratio = __z2_i / __z2_r;
sl@0:     float __denom = __z2_r * (1 + __ratio * __ratio);
sl@0:     __res_r = __z1_r / __denom;
sl@0:     __res_i = - (__z1_r * __ratio) / __denom;
sl@0:   }
sl@0: }
sl@0: 
sl@0: 
sl@0: void  _STLP_EXP_DECLSPEC
sl@0: complex<double>::_div(const double& __z1_r, const double& __z1_i,
sl@0:                       const double& __z2_r, const double& __z2_i,
sl@0:                       double& __res_r, double& __res_i) {
sl@0:   double __ar = __z2_r >= 0 ? __z2_r : -__z2_r;
sl@0:   double __ai = __z2_i >= 0 ? __z2_i : -__z2_i;
sl@0: 
sl@0:   if (__ar <= __ai) {
sl@0:     double __ratio = __z2_r / __z2_i;
sl@0:     double __denom = __z2_i * (1 + __ratio * __ratio);
sl@0:     __res_r = (__z1_r * __ratio + __z1_i) / __denom;
sl@0:     __res_i = (__z1_i * __ratio - __z1_r) / __denom;
sl@0:   }
sl@0:   else {
sl@0:     double __ratio = __z2_i / __z2_r;
sl@0:     double __denom = __z2_r * (1 + __ratio * __ratio);
sl@0:     __res_r = (__z1_r + __z1_i * __ratio) / __denom;
sl@0:     __res_i = (__z1_i - __z1_r * __ratio) / __denom;
sl@0:   }
sl@0: }
sl@0: 
sl@0: void _STLP_EXP_DECLSPEC
sl@0: complex<double>::_div(const double& __z1_r,
sl@0:                       const double& __z2_r, const double& __z2_i,
sl@0:                       double& __res_r, double& __res_i) {
sl@0:   double __ar = __z2_r >= 0 ? __z2_r : -__z2_r;
sl@0:   double __ai = __z2_i >= 0 ? __z2_i : -__z2_i;
sl@0: 
sl@0:   if (__ar <= __ai) {
sl@0:     double __ratio = __z2_r / __z2_i;
sl@0:     double __denom = __z2_i * (1 + __ratio * __ratio);
sl@0:     __res_r = (__z1_r * __ratio) / __denom;
sl@0:     __res_i = - __z1_r / __denom;
sl@0:   }
sl@0:   else {
sl@0:     double __ratio = __z2_i / __z2_r;
sl@0:     double __denom = __z2_r * (1 + __ratio * __ratio);
sl@0:     __res_r = __z1_r / __denom;
sl@0:     __res_i = - (__z1_r * __ratio) / __denom;
sl@0:   }
sl@0: }
sl@0: 
sl@0: #ifndef _STLP_NO_LONG_DOUBLE
sl@0: void  _STLP_CALL
sl@0: complex<long double>::_div(const long double& __z1_r, const long double& __z1_i,
sl@0:                            const long double& __z2_r, const long double& __z2_i,
sl@0:                            long double& __res_r, long double& __res_i) {
sl@0:   long double __ar = __z2_r >= 0 ? __z2_r : -__z2_r;
sl@0:   long double __ai = __z2_i >= 0 ? __z2_i : -__z2_i;
sl@0: 
sl@0:   if (__ar <= __ai) {
sl@0:     long double __ratio = __z2_r / __z2_i;
sl@0:     long double __denom = __z2_i * (1 + __ratio * __ratio);
sl@0:     __res_r = (__z1_r * __ratio + __z1_i) / __denom;
sl@0:     __res_i = (__z1_i * __ratio - __z1_r) / __denom;
sl@0:   }
sl@0:   else {
sl@0:     long double __ratio = __z2_i / __z2_r;
sl@0:     long double __denom = __z2_r * (1 + __ratio * __ratio);
sl@0:     __res_r = (__z1_r + __z1_i * __ratio) / __denom;
sl@0:     __res_i = (__z1_i - __z1_r * __ratio) / __denom;
sl@0:   }
sl@0: }
sl@0: 
sl@0: 
sl@0: void _STLP_CALL
sl@0: complex<long double>::_div(const long double& __z1_r,
sl@0:                            const long double& __z2_r, const long double& __z2_i,
sl@0:                            long double& __res_r, long double& __res_i) {
sl@0:   long double __ar = __z2_r >= 0 ? __z2_r : -__z2_r;
sl@0:   long double __ai = __z2_i >= 0 ? __z2_i : -__z2_i;
sl@0: 
sl@0:   if (__ar <= __ai) {
sl@0:     long double __ratio = __z2_r / __z2_i;
sl@0:     long double __denom = __z2_i * (1 + __ratio * __ratio);
sl@0:     __res_r = (__z1_r * __ratio) / __denom;
sl@0:     __res_i = - __z1_r / __denom;
sl@0:   }
sl@0:   else {
sl@0:     long double __ratio = __z2_i / __z2_r;
sl@0:     long double __denom = __z2_r * (1 + __ratio * __ratio);
sl@0:     __res_r = __z1_r / __denom;
sl@0:     __res_i = - (__z1_r * __ratio) / __denom;
sl@0:   }
sl@0: }
sl@0: #endif
sl@0: 
sl@0: //----------------------------------------------------------------------
sl@0: // Square root
sl@0: 
sl@0: 
sl@0: _STLP_EXP_DECLSPEC complex<float> _STLP_CALL
sl@0: sqrt(const complex<float>& z) {
sl@0:   float re = z._M_re;
sl@0:   float im = z._M_im;
sl@0:   float mag = _STLP_HYPOTF(re, im);
sl@0:   complex<float> result;
sl@0: 
sl@0:   if (mag == 0.) {
sl@0:     result._M_re = result._M_im = 0.f;
sl@0:   } else if (re > 0.f) {
sl@0:     result._M_re = _STLP_SQRTF(0.5f * (mag + re));
sl@0:     result._M_im = im/result._M_re/2.f;
sl@0:   } else {
sl@0:     result._M_im = _STLP_SQRTF(0.5f * (mag - re));
sl@0:     if (im < 0.f)
sl@0:       result._M_im = - result._M_im;
sl@0:     result._M_re = im/result._M_im/2.f;
sl@0:   }
sl@0:   return result;
sl@0: }
sl@0: 
sl@0: 
sl@0: _STLP_EXP_DECLSPEC complex<double>  _STLP_CALL
sl@0: sqrt(const complex<double>& z) {
sl@0:   double re = z._M_re;
sl@0:   double im = z._M_im;
sl@0:   double mag = _STLP_HYPOT(re, im);
sl@0:   complex<double> result;
sl@0: 
sl@0:   if (mag == 0.) {
sl@0:     result._M_re = result._M_im = 0.;
sl@0:   } else if (re > 0.) {
sl@0:     result._M_re = _STLP_SQRT(0.5 * (mag + re));
sl@0:     result._M_im = im/result._M_re/2;
sl@0:   } else {
sl@0:     result._M_im = _STLP_SQRT(0.5 * (mag - re));
sl@0:     if (im < 0.)
sl@0:       result._M_im = - result._M_im;
sl@0:     result._M_re = im/result._M_im/2;
sl@0:   }
sl@0:   return result;
sl@0: }
sl@0: 
sl@0: #ifndef _STLP_NO_LONG_DOUBLE
sl@0: _STLP_EXP_DECLSPEC complex<long double> _STLP_CALL
sl@0: sqrt(const complex<long double>& z) {
sl@0:   long double re = z._M_re;
sl@0:   long double im = z._M_im;
sl@0:   long double mag = _STLP_HYPOTL(re, im);
sl@0:   complex<long double> result;
sl@0: 
sl@0:   if (mag == 0.L) {
sl@0:     result._M_re = result._M_im = 0.L;
sl@0:   } else if (re > 0.L) {
sl@0:     result._M_re = _STLP_SQRTL(0.5L * (mag + re));
sl@0:     result._M_im = (im/result._M_re) * .5L;
sl@0:   } else {
sl@0:     result._M_im = _STLP_SQRTL(0.5L * (mag - re));
sl@0:     if (im < 0.L)
sl@0:       result._M_im = - result._M_im;
sl@0:     result._M_re = (im/result._M_im) * .5L;
sl@0:   }
sl@0:   return result;
sl@0: }
sl@0: #endif
sl@0: 
sl@0: #ifdef __SYMBIAN32__
sl@0: template <class _Tp>
sl@0: _STLP_EXP_DECLSPEC _Tp  _STLP_CALL abs_tp(const complex<_Tp>& val)
sl@0:     {
sl@0:     return abs_l(val);
sl@0:     }
sl@0: 
sl@0: template <class _Tp>
sl@0: _STLP_EXP_DECLSPEC _Tp  _STLP_CALL arg_tp(const complex<_Tp>& val)
sl@0:     {
sl@0:     return arg_l(val);
sl@0:     }
sl@0:     
sl@0: template <class _Tp>
sl@0: _STLP_EXP_DECLSPEC complex<_Tp> _STLP_CALL polar_tp(const _Tp& __rho, const _Tp& __phi)
sl@0:     {
sl@0:     return polar_l(__rho, __phi);
sl@0:     }
sl@0: 
sl@0:  
sl@0: void dummy_instantiate_func()
sl@0: {
sl@0:     const complex<float> val;
sl@0:     float fval;
sl@0:     abs_tp(val);
sl@0:     arg_tp(val);
sl@0:     polar_tp(fval, fval);
sl@0:     const complex<double> dval;
sl@0:     double dv;
sl@0:     abs_tp(dval);
sl@0:     arg_tp(dval);
sl@0:     polar_tp(dv, dv);
sl@0: 
sl@0: #ifndef _STLP_NO_LONG_DOUBLE
sl@0:     const complex<long double> lval;
sl@0:     long double lv;
sl@0:     abs_tp(lval);
sl@0:     arg_tp(lval);
sl@0:     polar_tp(lv, lv);
sl@0: #endif
sl@0: }
sl@0: 
sl@0: 
sl@0: #endif
sl@0: //template <>
sl@0: //_STLP_EXP_DECLSPEC float  _STLP_CALL abs_tp(const complex<float>& val);
sl@0: 
sl@0: _STLP_END_NAMESPACE
sl@0: 
sl@0: #ifdef __ARMCC__
sl@0: #undef _STLP_TEMPLATE_NULL
sl@0: #endif