re PR libstdc++/48760 (std::complex constructor buggy in the face of NaN's)
[gcc.git] / libstdc++-v3 / include / std / complex
index 6f0fe44eefcf3add319f5c8edbe91ee5a555ee22..0ce7e55343f93b6274d1612aaa41a47e8936a6b5 100644 (file)
@@ -1,7 +1,7 @@
 // The template and inlines for the -*- C++ -*- complex number classes.
 
 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-// 2006, 2007, 2008, 2009, 2010
+// 2006, 2007, 2008, 2009, 2010, 2011
 // Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
@@ -46,7 +46,9 @@
 #include <cmath>
 #include <sstream>
 
-_GLIBCXX_BEGIN_NAMESPACE(std)
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   /**
    * @defgroup complex_numbers Complex Numbers
@@ -447,17 +449,17 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
   //@{
   ///  Return true if @a x is equal to @a y.
   template<typename _Tp>
-    inline bool
+    inline _GLIBCXX_CONSTEXPR bool
     operator==(const complex<_Tp>& __x, const complex<_Tp>& __y)
     { return __x.real() == __y.real() && __x.imag() == __y.imag(); }
 
   template<typename _Tp>
-    inline bool
+    inline _GLIBCXX_CONSTEXPR bool
     operator==(const complex<_Tp>& __x, const _Tp& __y)
     { return __x.real() == __y && __x.imag() == _Tp(); }
 
   template<typename _Tp>
-    inline bool
+    inline _GLIBCXX_CONSTEXPR bool
     operator==(const _Tp& __x, const complex<_Tp>& __y)
     { return __x == __y.real() && _Tp() == __y.imag(); }
   //@}
@@ -465,17 +467,17 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
   //@{
   ///  Return false if @a x is equal to @a y.
   template<typename _Tp>
-    inline bool
+    inline _GLIBCXX_CONSTEXPR bool
     operator!=(const complex<_Tp>& __x, const complex<_Tp>& __y)
     { return __x.real() != __y.real() || __x.imag() != __y.imag(); }
 
   template<typename _Tp>
-    inline bool
+    inline _GLIBCXX_CONSTEXPR bool
     operator!=(const complex<_Tp>& __x, const _Tp& __y)
     { return __x.real() != __y || __x.imag() != _Tp(); }
 
   template<typename _Tp>
-    inline bool
+    inline _GLIBCXX_CONSTEXPR bool
     operator!=(const _Tp& __x, const complex<_Tp>& __y)
     { return __x != __y.real() || _Tp() != __y.imag(); }
   //@}
@@ -529,12 +531,12 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
   // Values
 #ifdef __GXX_EXPERIMENTAL_CXX0X__
   template<typename _Tp>
-    inline _Tp
+    inline constexpr _Tp
     real(const complex<_Tp>& __z)
     { return __z.real(); }
     
   template<typename _Tp>
-    inline _Tp
+    inline constexpr _Tp
     imag(const complex<_Tp>& __z)
     { return __z.imag(); }
 #else
@@ -1044,7 +1046,14 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
       _GLIBCXX_CONSTEXPR complex(_ComplexT __z) : _M_value(__z) { }
 
       _GLIBCXX_CONSTEXPR complex(float __r = 0.0f, float __i = 0.0f)
-      : _M_value(__r + __i * 1.0fi) { }
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      : _M_value{ __r, __i } { }
+#else
+      {
+       __real__ _M_value = __r;
+       __imag__ _M_value = __i;
+      }
+#endif
 
       explicit _GLIBCXX_CONSTEXPR complex(const complex<double>&);
       explicit _GLIBCXX_CONSTEXPR complex(const complex<long double>&);        
@@ -1184,7 +1193,14 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
       _GLIBCXX_CONSTEXPR complex(_ComplexT __z) : _M_value(__z) { }
 
       _GLIBCXX_CONSTEXPR complex(double __r = 0.0, double __i = 0.0)
-      : _M_value(__r + __i * 1.0i) { }
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      : _M_value{ __r, __i } { }
+#else
+      {
+       __real__ _M_value = __r;
+       __imag__ _M_value = __i;
+      }
+#endif
 
       _GLIBCXX_CONSTEXPR complex(const complex<float>& __z)
       : _M_value(__z.__rep()) { }
@@ -1326,7 +1342,14 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
 
       _GLIBCXX_CONSTEXPR complex(long double __r = 0.0L, 
                                 long double __i = 0.0L)
-      : _M_value(__r + __i * 1.0Li) { }
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+      : _M_value{ __r, __i } { }
+#else
+      {
+       __real__ _M_value = __r;
+       __imag__ _M_value = __i;
+      }
+#endif
 
       _GLIBCXX_CONSTEXPR complex(const complex<float>& __z)
       : _M_value(__z.__rep()) { }
@@ -1494,9 +1517,12 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
 
   // @} group complex_numbers
 
-_GLIBCXX_END_NAMESPACE
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
 
-_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
+namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   // See ext/type_traits.h for the primary template.
   template<typename _Tp, typename _Up>
@@ -1520,27 +1546,328 @@ _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
       typedef std::complex<typename __promote_2<_Tp, _Up>::__type> __type;
     };
 
-_GLIBCXX_END_NAMESPACE
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
 
 #ifdef __GXX_EXPERIMENTAL_CXX0X__
-#  if defined(_GLIBCXX_INCLUDE_AS_TR1)
-#    error C++0x header cannot be included from TR1 header
-#  endif
-#  if defined(_GLIBCXX_INCLUDE_AS_CXX0X)
-#    include <tr1_impl/complex>
-#  else
-#    define _GLIBCXX_INCLUDE_AS_CXX0X
-#    define _GLIBCXX_BEGIN_NAMESPACE_TR1
-#    define _GLIBCXX_END_NAMESPACE_TR1
-#    define _GLIBCXX_TR1
-#    include <tr1_impl/complex>
-#    undef _GLIBCXX_TR1
-#    undef _GLIBCXX_END_NAMESPACE_TR1
-#    undef _GLIBCXX_BEGIN_NAMESPACE_TR1
-#    undef _GLIBCXX_INCLUDE_AS_CXX0X
-#  endif
-
-_GLIBCXX_BEGIN_NAMESPACE(std)
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  // Forward declarations.
+  template<typename _Tp> std::complex<_Tp> acos(const std::complex<_Tp>&);
+  template<typename _Tp> std::complex<_Tp> asin(const std::complex<_Tp>&);
+  template<typename _Tp> std::complex<_Tp> atan(const std::complex<_Tp>&);
+
+  template<typename _Tp> std::complex<_Tp> acosh(const std::complex<_Tp>&);
+  template<typename _Tp> std::complex<_Tp> asinh(const std::complex<_Tp>&);
+  template<typename _Tp> std::complex<_Tp> atanh(const std::complex<_Tp>&);
+  // DR 595.
+  template<typename _Tp> _Tp               fabs(const std::complex<_Tp>&);
+
+  template<typename _Tp>
+    inline std::complex<_Tp>
+    __complex_acos(const std::complex<_Tp>& __z)
+    {
+      const std::complex<_Tp> __t = std::asin(__z);
+      const _Tp __pi_2 = 1.5707963267948966192313216916397514L;
+      return std::complex<_Tp>(__pi_2 - __t.real(), -__t.imag());
+    }
+
+#if _GLIBCXX_USE_C99_COMPLEX_TR1
+  inline __complex__ float
+  __complex_acos(__complex__ float __z)
+  { return __builtin_cacosf(__z); }
+
+  inline __complex__ double
+  __complex_acos(__complex__ double __z)
+  { return __builtin_cacos(__z); }
+
+  inline __complex__ long double
+  __complex_acos(const __complex__ long double& __z)
+  { return __builtin_cacosl(__z); }
+
+  template<typename _Tp>
+    inline std::complex<_Tp>
+    acos(const std::complex<_Tp>& __z)
+    { return __complex_acos(__z.__rep()); }
+#else
+  /// acos(__z) [8.1.2].
+  //  Effects:  Behaves the same as C99 function cacos, defined
+  //            in subclause 7.3.5.1.
+  template<typename _Tp>
+    inline std::complex<_Tp>
+    acos(const std::complex<_Tp>& __z)
+    { return __complex_acos(__z); }
+#endif
+
+  template<typename _Tp>
+    inline std::complex<_Tp>
+    __complex_asin(const std::complex<_Tp>& __z)
+    {
+      std::complex<_Tp> __t(-__z.imag(), __z.real());
+      __t = std::asinh(__t);
+      return std::complex<_Tp>(__t.imag(), -__t.real());
+    }
+
+#if _GLIBCXX_USE_C99_COMPLEX_TR1
+  inline __complex__ float
+  __complex_asin(__complex__ float __z)
+  { return __builtin_casinf(__z); }
+
+  inline __complex__ double
+  __complex_asin(__complex__ double __z)
+  { return __builtin_casin(__z); }
+
+  inline __complex__ long double
+  __complex_asin(const __complex__ long double& __z)
+  { return __builtin_casinl(__z); }
+
+  template<typename _Tp>
+    inline std::complex<_Tp>
+    asin(const std::complex<_Tp>& __z)
+    { return __complex_asin(__z.__rep()); }
+#else
+  /// asin(__z) [8.1.3].
+  //  Effects:  Behaves the same as C99 function casin, defined
+  //            in subclause 7.3.5.2.
+  template<typename _Tp>
+    inline std::complex<_Tp>
+    asin(const std::complex<_Tp>& __z)
+    { return __complex_asin(__z); }
+#endif
+  
+  template<typename _Tp>
+    std::complex<_Tp>
+    __complex_atan(const std::complex<_Tp>& __z)
+    {
+      const _Tp __r2 = __z.real() * __z.real();
+      const _Tp __x = _Tp(1.0) - __r2 - __z.imag() * __z.imag();
+
+      _Tp __num = __z.imag() + _Tp(1.0);
+      _Tp __den = __z.imag() - _Tp(1.0);
+
+      __num = __r2 + __num * __num;
+      __den = __r2 + __den * __den;
+
+      return std::complex<_Tp>(_Tp(0.5) * atan2(_Tp(2.0) * __z.real(), __x),
+                              _Tp(0.25) * log(__num / __den));
+    }
+
+#if _GLIBCXX_USE_C99_COMPLEX_TR1
+  inline __complex__ float
+  __complex_atan(__complex__ float __z)
+  { return __builtin_catanf(__z); }
+
+  inline __complex__ double
+  __complex_atan(__complex__ double __z)
+  { return __builtin_catan(__z); }
+
+  inline __complex__ long double
+  __complex_atan(const __complex__ long double& __z)
+  { return __builtin_catanl(__z); }
+
+  template<typename _Tp>
+    inline std::complex<_Tp>
+    atan(const std::complex<_Tp>& __z)
+    { return __complex_atan(__z.__rep()); }
+#else
+  /// atan(__z) [8.1.4].
+  //  Effects:  Behaves the same as C99 function catan, defined
+  //            in subclause 7.3.5.3.
+  template<typename _Tp>
+    inline std::complex<_Tp>
+    atan(const std::complex<_Tp>& __z)
+    { return __complex_atan(__z); }
+#endif
+
+  template<typename _Tp>
+    std::complex<_Tp>
+    __complex_acosh(const std::complex<_Tp>& __z)
+    {
+      std::complex<_Tp> __t((__z.real() - __z.imag())
+                           * (__z.real() + __z.imag()) - _Tp(1.0),
+                           _Tp(2.0) * __z.real() * __z.imag());
+      __t = std::sqrt(__t);
+
+      return std::log(__t + __z);
+    }
+
+#if _GLIBCXX_USE_C99_COMPLEX_TR1
+  inline __complex__ float
+  __complex_acosh(__complex__ float __z)
+  { return __builtin_cacoshf(__z); }
+
+  inline __complex__ double
+  __complex_acosh(__complex__ double __z)
+  { return __builtin_cacosh(__z); }
+
+  inline __complex__ long double
+  __complex_acosh(const __complex__ long double& __z)
+  { return __builtin_cacoshl(__z); }
+
+  template<typename _Tp>
+    inline std::complex<_Tp>
+    acosh(const std::complex<_Tp>& __z)
+    { return __complex_acosh(__z.__rep()); }
+#else
+  /// acosh(__z) [8.1.5].
+  //  Effects:  Behaves the same as C99 function cacosh, defined
+  //            in subclause 7.3.6.1.
+  template<typename _Tp>
+    inline std::complex<_Tp>
+    acosh(const std::complex<_Tp>& __z)
+    { return __complex_acosh(__z); }
+#endif
+
+  template<typename _Tp>
+    std::complex<_Tp>
+    __complex_asinh(const std::complex<_Tp>& __z)
+    {
+      std::complex<_Tp> __t((__z.real() - __z.imag())
+                           * (__z.real() + __z.imag()) + _Tp(1.0),
+                           _Tp(2.0) * __z.real() * __z.imag());
+      __t = std::sqrt(__t);
+
+      return std::log(__t + __z);
+    }
+
+#if _GLIBCXX_USE_C99_COMPLEX_TR1
+  inline __complex__ float
+  __complex_asinh(__complex__ float __z)
+  { return __builtin_casinhf(__z); }
+
+  inline __complex__ double
+  __complex_asinh(__complex__ double __z)
+  { return __builtin_casinh(__z); }
+
+  inline __complex__ long double
+  __complex_asinh(const __complex__ long double& __z)
+  { return __builtin_casinhl(__z); }
+
+  template<typename _Tp>
+    inline std::complex<_Tp>
+    asinh(const std::complex<_Tp>& __z)
+    { return __complex_asinh(__z.__rep()); }
+#else
+  /// asinh(__z) [8.1.6].
+  //  Effects:  Behaves the same as C99 function casin, defined
+  //            in subclause 7.3.6.2.
+  template<typename _Tp>
+    inline std::complex<_Tp>
+    asinh(const std::complex<_Tp>& __z)
+    { return __complex_asinh(__z); }
+#endif
+
+  template<typename _Tp>
+    std::complex<_Tp>
+    __complex_atanh(const std::complex<_Tp>& __z)
+    {
+      const _Tp __i2 = __z.imag() * __z.imag();
+      const _Tp __x = _Tp(1.0) - __i2 - __z.real() * __z.real();
+
+      _Tp __num = _Tp(1.0) + __z.real();
+      _Tp __den = _Tp(1.0) - __z.real();
+
+      __num = __i2 + __num * __num;
+      __den = __i2 + __den * __den;
+
+      return std::complex<_Tp>(_Tp(0.25) * (log(__num) - log(__den)),
+                              _Tp(0.5) * atan2(_Tp(2.0) * __z.imag(), __x));
+    }
+
+#if _GLIBCXX_USE_C99_COMPLEX_TR1
+  inline __complex__ float
+  __complex_atanh(__complex__ float __z)
+  { return __builtin_catanhf(__z); }
+
+  inline __complex__ double
+  __complex_atanh(__complex__ double __z)
+  { return __builtin_catanh(__z); }
+
+  inline __complex__ long double
+  __complex_atanh(const __complex__ long double& __z)
+  { return __builtin_catanhl(__z); }
+
+  template<typename _Tp>
+    inline std::complex<_Tp>
+    atanh(const std::complex<_Tp>& __z)
+    { return __complex_atanh(__z.__rep()); }
+#else
+  /// atanh(__z) [8.1.7].
+  //  Effects:  Behaves the same as C99 function catanh, defined
+  //            in subclause 7.3.6.3.
+  template<typename _Tp>
+    inline std::complex<_Tp>
+    atanh(const std::complex<_Tp>& __z)
+    { return __complex_atanh(__z); }
+#endif
+
+  template<typename _Tp>
+    inline _Tp
+    /// fabs(__z) [8.1.8].
+    //  Effects:  Behaves the same as C99 function cabs, defined
+    //            in subclause 7.3.8.1.
+    fabs(const std::complex<_Tp>& __z)
+    { return std::abs(__z); }
+
+  /// Additional overloads [8.1.9].
+  template<typename _Tp>
+    inline typename __gnu_cxx::__promote<_Tp>::__type
+    arg(_Tp __x)
+    {
+      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
+#if (_GLIBCXX_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC)
+      return std::signbit(__x) ? __type(3.1415926535897932384626433832795029L)
+                              : __type();
+#else
+      return std::arg(std::complex<__type>(__x));
+#endif
+    }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__promote<_Tp>::__type
+    imag(_Tp)
+    { return _Tp(); }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__promote<_Tp>::__type
+    norm(_Tp __x)
+    {
+      typedef typename __gnu_cxx::__promote<_Tp>::__type __type;
+      return __type(__x) * __type(__x);
+    }
+
+  template<typename _Tp>
+    inline typename __gnu_cxx::__promote<_Tp>::__type
+    real(_Tp __x)
+    { return __x; }
+
+  template<typename _Tp, typename _Up>
+    inline std::complex<typename __gnu_cxx::__promote_2<_Tp, _Up>::__type>
+    pow(const std::complex<_Tp>& __x, const _Up& __y)
+    {
+      typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+      return std::pow(std::complex<__type>(__x), __type(__y));
+    }
+
+  template<typename _Tp, typename _Up>
+    inline std::complex<typename __gnu_cxx::__promote_2<_Tp, _Up>::__type>
+    pow(const _Tp& __x, const std::complex<_Up>& __y)
+    {
+      typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+      return std::pow(__type(__x), std::complex<__type>(__y));
+    }
+
+  template<typename _Tp, typename _Up>
+    inline std::complex<typename __gnu_cxx::__promote_2<_Tp, _Up>::__type>
+    pow(const std::complex<_Tp>& __x, const std::complex<_Up>& __y)
+    {
+      typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+      return std::pow(std::complex<__type>(__x),
+                     std::complex<__type>(__y));
+    }
 
   // Forward declarations.
   // DR 781.
@@ -1592,8 +1919,9 @@ _GLIBCXX_BEGIN_NAMESPACE(std)
     conj(_Tp __x)
     { return __x; }
 
-_GLIBCXX_END_NAMESPACE
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
 
-#endif
+#endif  // __GXX_EXPERIMENTAL_CXX0X__
 
-#endif /* _GLIBCXX_COMPLEX */
+#endif  /* _GLIBCXX_COMPLEX */