1// -*-c++-*-
2/*****************************************************************
3 * file lacomplex Locally modified copy of stdc++'s file complex
4 *  -------------------
5 * begin                : 2004-01-14
6 * copyright            : (C) 2004 by Christian Stimming
7 * email                : stimming@tuhh.de
8 *
9 * (Almost) All changes by Christian are marked with "CS:".
10***************************************************************************/
11
12// The template and inlines for the -*- C++ -*- complex number classes.
13
14// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
15// Free Software Foundation, Inc.
16//
17// This file is part of the GNU ISO C++ Library.  This library is free
18// software; you can redistribute it and/or modify it under the
19// terms of the GNU General Public License as published by the
20// Free Software Foundation; either version 2, or (at your option)
21// any later version.
22
23// This library is distributed in the hope that it will be useful,
24// but WITHOUT ANY WARRANTY; without even the implied warranty of
25// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26// GNU General Public License for more details.
27
28// You should have received a copy of the GNU General Public License along
29// with this library; see the file COPYING.  If not, write to the Free
30// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
31// USA.
32
33// As a special exception, you may use this file as part of a free software
34// library without restriction.  Specifically, if other files instantiate
35// templates or use macros or inline functions from this file, or you compile
36// this file and link it with other files to produce an executable, this
37// file does not by itself cause the resulting executable to be covered by
38// the GNU General Public License.  This exception does not however
39// invalidate any other reasons why the executable file might be covered by
40// the GNU General Public License.
41
42//
43// ISO C++ 14882: 26.2  Complex Numbers
44// Note: this is not a conforming implementation.
45// Initially implemented by Ulrich Drepper <drepper@cygnus.com>
46// Improved by Gabriel Dos Reis <dosreis@cmla.ens-cachan.fr>
47//
48
49/** \file lacomplex
50 * \brief Complex data type that can be used from the application.
51 *
52 * This file has been heavily copied from the Standard
53 *  C++ Library header <\c complex >. See the explanations at la::complex
54 *  for the reasons.
55 */
56
57#ifndef LACOMPLEX_CPPHEADER
58#define LACOMPLEX_CPPHEADER
59
60//#pragma GCC system_header
61
62#if LAPACKPP_HAVE_BITS_CPP_TYPE_TRAITS_H
63// This is for gcc >= 3.0.0
64#  include <bits/c++config.h>
65#  include <bits/cpp_type_traits.h>
66#endif // LAPACKPP_HAVE_BITS_CPP_TYPE_TRAITS_H
67
68#include <cmath>
69#include <iosfwd>
70#include <sstream>
71#include <complex>
72
73#if defined __GNUC__ && (__GNUC__ < 3)
74// This is for gcc2.95
75#  include <iostream>
76#endif
77
78
79/** \brief Namespace of Lapack++.
80 *
81 * This namespace defines the complex data type that can be used
82 * from the application, and also various matrix template
83 * functions.
84 *
85 * This namespace defines the complex data type that is used for
86 * passing scalars in and out of LAPACK++. It is a copy of the \c
87 * std::complex<double> and it includes automatic conversion from and
88 * to \c std::complex<double>. Additionally it includes automatic
89 * conversion from and to the internal FORTRAN type \ref COMPLEX,
90 * which is why this class is needed to pass complex values into
91 * Lapack++.
92 *
93 * This file has been heavily copied from the Standard C++ Library
94 * header <\c complex >. See the explanations at la::complex for the
95 * reasons.
96 */
97namespace la
98{
99  /** \name Functions for Lapack++ complex number type */
100  //@{
101#if LAPACKPP_HAVE_BITS_CPP_TYPE_TRAITS_H
102  using std::ios_base;
103#else
104  typedef std::ios ios_base;
105#endif
106
107  // Forward declarations
108  template<typename _Tp> class complex;
109  //template<> class complex<float>;
110#if defined __GNUC__ && (__GNUC__ > 2)
111  template<> class complex<double>;
112#endif
113  //template<> class complex<long double>;
114
115  template<typename _Tp> _Tp abs(const complex<_Tp>&);
116  template<typename _Tp> _Tp arg(const complex<_Tp>&);
117  template<typename _Tp> _Tp norm(const complex<_Tp>&);
118
119
120  // Transcendentals:
121
122
123/** @brief Complex data type that can be used from the application.
124 *
125 * This type is used for passing scalars in and out of LAPACK++. It is
126 * a copy of the \c std::complex<double> and it includes automatic
127 * conversion from and to \c std::complex<double>. Additionally it
128 * includes automatic conversion from and to the internal FORTRAN type
129 * \ref COMPLEX, which is why this class is needed to pass complex
130 * values into Lapack++.
131 *
132 * Again: If you get errors when passing a \c std::complex<double>
133 * into Lapack++, then you first need to convert your \c
134 * std::complex<double> into this \c LaComplex value.
135 */
136  // 26.2.2  Primary template class complex
137  template<typename _Tp>
138    class complex
139    {
140    public:
141      typedef _Tp value_type;
142
143      complex(const _Tp& = _Tp(), const _Tp & = _Tp());
144
145      // Let's the compiler synthetize the copy constructor
146      // complex (const complex<_Tp>&);
147      template<typename _Up>
148        complex(const complex<_Up>&);
149      // CS: Additionally add conversion *from* stdc++ type.
150      complex(const std::complex<_Tp>&);
151      // CS: end
152
153      _Tp real() const;
154      _Tp imag() const;
155
156      complex<_Tp>& operator=(const _Tp&);
157      complex<_Tp>& operator+=(const _Tp&);
158      complex<_Tp>& operator-=(const _Tp&);
159      complex<_Tp>& operator*=(const _Tp&);
160      complex<_Tp>& operator/=(const _Tp&);
161
162      // Let's the compiler synthetize the
163      // copy and assignment operator
164      // complex<_Tp>& operator= (const complex<_Tp>&);
165      template<typename _Up>
166        complex<_Tp>& operator=(const complex<_Up>&);
167      template<typename _Up>
168        complex<_Tp>& operator+=(const complex<_Up>&);
169      template<typename _Up>
170        complex<_Tp>& operator-=(const complex<_Up>&);
171      template<typename _Up>
172        complex<_Tp>& operator*=(const complex<_Up>&);
173      template<typename _Up>
174        complex<_Tp>& operator/=(const complex<_Up>&);
175
176      // CS: Additionally add converstions to old C-style complex type
177      complex(COMPLEX);
178      operator COMPLEX() const;
179      COMPLEX toCOMPLEX() const;
180      operator std::complex<_Tp>() const;
181      // CS: end additions
182
183    private:
184      _Tp _M_real, _M_imag;
185    };
186
187  template<typename _Tp>
188    inline _Tp
189    complex<_Tp>::real() const { return _M_real; }
190
191  template<typename _Tp>
192    inline _Tp
193    complex<_Tp>::imag() const { return _M_imag; }
194
195  template<typename _Tp>
196    inline
197    complex<_Tp>::complex(const _Tp& __r, const _Tp& __i)
198    : _M_real(__r), _M_imag(__i) { }
199
200  template<typename _Tp>
201    template<typename _Up>
202    inline
203    complex<_Tp>::complex(const complex<_Up>& __z)
204    : _M_real(__z.real()), _M_imag(__z.imag()) { }
205
206  // CS: addition
207  template<typename _Tp>
208    inline
209    complex<_Tp>::complex(const std::complex<_Tp>& __z)
210    : _M_real(__z.real()), _M_imag(__z.imag()) { }
211  // CS: end addition
212
213  template<typename _Tp>
214    complex<_Tp>&
215    complex<_Tp>::operator=(const _Tp& __t)
216    {
217     _M_real = __t;
218     _M_imag = _Tp();
219     return *this;
220    }
221
222  // 26.2.5/1
223  template<typename _Tp>
224    inline complex<_Tp>&
225    complex<_Tp>::operator+=(const _Tp& __t)
226    {
227      _M_real += __t;
228      return *this;
229    }
230
231  // 26.2.5/3
232  template<typename _Tp>
233    inline complex<_Tp>&
234    complex<_Tp>::operator-=(const _Tp& __t)
235    {
236      _M_real -= __t;
237      return *this;
238    }
239
240  // 26.2.5/5
241  template<typename _Tp>
242    complex<_Tp>&
243    complex<_Tp>::operator*=(const _Tp& __t)
244    {
245      _M_real *= __t;
246      _M_imag *= __t;
247      return *this;
248    }
249
250  // 26.2.5/7
251  template<typename _Tp>
252    complex<_Tp>&
253    complex<_Tp>::operator/=(const _Tp& __t)
254    {
255      _M_real /= __t;
256      _M_imag /= __t;
257      return *this;
258    }
259
260  template<typename _Tp>
261    template<typename _Up>
262    complex<_Tp>&
263    complex<_Tp>::operator=(const complex<_Up>& __z)
264    {
265      _M_real = __z.real();
266      _M_imag = __z.imag();
267      return *this;
268    }
269
270  // 26.2.5/9
271  template<typename _Tp>
272    template<typename _Up>
273    complex<_Tp>&
274    complex<_Tp>::operator+=(const complex<_Up>& __z)
275    {
276      _M_real += __z.real();
277      _M_imag += __z.imag();
278      return *this;
279    }
280
281  // 26.2.5/11
282  template<typename _Tp>
283    template<typename _Up>
284    complex<_Tp>&
285    complex<_Tp>::operator-=(const complex<_Up>& __z)
286    {
287      _M_real -= __z.real();
288      _M_imag -= __z.imag();
289      return *this;
290    }
291
292  // 26.2.5/13
293  // XXX: This is a grammar school implementation.
294  template<typename _Tp>
295    template<typename _Up>
296    complex<_Tp>&
297    complex<_Tp>::operator*=(const complex<_Up>& __z)
298    {
299      const _Tp __r = _M_real * __z.real() - _M_imag * __z.imag();
300      _M_imag = _M_real * __z.imag() + _M_imag * __z.real();
301      _M_real = __r;
302      return *this;
303    }
304
305  // 26.2.5/15
306  // XXX: This is a grammar school implementation.
307  template<typename _Tp>
308    template<typename _Up>
309    complex<_Tp>&
310    complex<_Tp>::operator/=(const complex<_Up>& __z)
311    {
312      const _Tp __r =  _M_real * __z.real() + _M_imag * __z.imag();
313      const _Tp __n = norm(__z);
314      _M_imag = (_M_imag * __z.real() - _M_real * __z.imag()) / __n;
315      _M_real = __r / __n;
316      return *this;
317    }
318
319  // CS: Additionally add converstions to old C-style complex type
320  template<typename _Tp>
321  inline
322  complex<_Tp>::complex(COMPLEX c)
323    : _M_real(c.r), _M_imag(c.i) { }
324
325  template<typename _Tp>
326  inline
327  complex<_Tp>::operator COMPLEX() const
328  {
329    return toCOMPLEX();
330  }
331
332  template<typename _Tp>
333  inline COMPLEX
334  complex<_Tp>::toCOMPLEX() const
335  {
336    COMPLEX r;
337    r.r = _M_real;
338    r.i = _M_imag;
339    return r;
340  }
341
342  template<typename _Tp>
343  inline
344  complex<_Tp>::operator std::complex<_Tp>() const
345  {
346    return std::complex<_Tp>(real(), imag());
347  }
348  // CS: end
349
350  // Operators:
351  template<typename _Tp>
352    inline complex<_Tp>
353    operator+(const complex<_Tp>& __x, const complex<_Tp>& __y)
354    { return complex<_Tp> (__x) += __y; }
355
356  template<typename _Tp>
357    inline complex<_Tp>
358    operator+(const complex<_Tp>& __x, const _Tp& __y)
359    { return complex<_Tp> (__x) += __y; }
360
361  template<typename _Tp>
362    inline complex<_Tp>
363    operator+(const _Tp& __x, const complex<_Tp>& __y)
364    { return complex<_Tp> (__y) += __x; }
365
366  template<typename _Tp>
367    inline complex<_Tp>
368    operator-(const complex<_Tp>& __x, const complex<_Tp>& __y)
369    { return complex<_Tp> (__x) -= __y; }
370
371  template<typename _Tp>
372    inline complex<_Tp>
373    operator-(const complex<_Tp>& __x, const _Tp& __y)
374    { return complex<_Tp> (__x) -= __y; }
375
376  template<typename _Tp>
377    inline complex<_Tp>
378    operator-(const _Tp& __x, const complex<_Tp>& __y)
379    { return complex<_Tp> (__x) -= __y; }
380
381  template<typename _Tp>
382    inline complex<_Tp>
383    operator*(const complex<_Tp>& __x, const complex<_Tp>& __y)
384    { return complex<_Tp> (__x) *= __y; }
385
386  template<typename _Tp>
387    inline complex<_Tp>
388    operator*(const complex<_Tp>& __x, const _Tp& __y)
389    { return complex<_Tp> (__x) *= __y; }
390
391  template<typename _Tp>
392    inline complex<_Tp>
393    operator*(const _Tp& __x, const complex<_Tp>& __y)
394    { return complex<_Tp> (__y) *= __x; }
395
396  template<typename _Tp>
397    inline complex<_Tp>
398    operator/(const complex<_Tp>& __x, const complex<_Tp>& __y)
399    { return complex<_Tp> (__x) /= __y; }
400
401  template<typename _Tp>
402    inline complex<_Tp>
403    operator/(const complex<_Tp>& __x, const _Tp& __y)
404    { return complex<_Tp> (__x) /= __y; }
405
406  template<typename _Tp>
407    inline complex<_Tp>
408    operator/(const _Tp& __x, const complex<_Tp>& __y)
409    { return complex<_Tp> (__x) /= __y; }
410
411  template<typename _Tp>
412    inline complex<_Tp>
413    operator+(const complex<_Tp>& __x)
414    { return __x; }
415
416  template<typename _Tp>
417    inline complex<_Tp>
418    operator-(const complex<_Tp>& __x)
419    {  return complex<_Tp>(-__x.real(), -__x.imag()); }
420
421  template<typename _Tp>
422    inline bool
423    operator==(const complex<_Tp>& __x, const complex<_Tp>& __y)
424    { return __x.real() == __y.real() && __x.imag() == __y.imag(); }
425
426  template<typename _Tp>
427    inline bool
428    operator==(const complex<_Tp>& __x, const _Tp& __y)
429    { return __x.real() == __y && __x.imag() == _Tp(); }
430
431  template<typename _Tp>
432    inline bool
433    operator==(const _Tp& __x, const complex<_Tp>& __y)
434    { return __x == __y.real() && _Tp() == __y.imag(); }
435
436  template<typename _Tp>
437    inline bool
438    operator!=(const complex<_Tp>& __x, const complex<_Tp>& __y)
439    { return __x.real() != __y.real() || __x.imag() != __y.imag(); }
440
441  template<typename _Tp>
442    inline bool
443    operator!=(const complex<_Tp>& __x, const _Tp& __y)
444    { return __x.real() != __y || __x.imag() != _Tp(); }
445
446  template<typename _Tp>
447    inline bool
448    operator!=(const _Tp& __x, const complex<_Tp>& __y)
449    { return __x != __y.real() || _Tp() != __y.imag(); }
450
451  template<typename _Tp>
452    std::istream&
453    operator>>(std::istream& __is, complex<_Tp>& __x)
454    {
455      _Tp __re_x, __im_x;
456      char __ch;
457      __is >> __ch;
458      if (__ch == '(')
459	{
460	  __is >> __re_x >> __ch;
461	  if (__ch == ',')
462	    {
463	      __is >> __im_x >> __ch;
464	      if (__ch == ')')
465		__x = complex<_Tp>(__re_x, __im_x);
466	      else
467		__is.setstate(ios_base::failbit);
468	    }
469	  else if (__ch == ')')
470	    __x = complex<_Tp>(__re_x, _Tp(0));
471	  else
472	    __is.setstate(ios_base::failbit);
473	}
474      else
475	{
476	  __is.putback(__ch);
477	  __is >> __re_x;
478	  __x = complex<_Tp>(__re_x, _Tp(0));
479	}
480      return __is;
481    }
482
483  template<typename _Tp>
484    std::ostream&
485    operator<<(std::ostream& __os, const complex<_Tp>& __x)
486    {
487      std::ostringstream __s;
488      __s.flags(__os.flags());
489#if defined __GNUC__ && (__GNUC__ > 2)
490      __s.imbue(__os.getloc());
491#endif
492      __s.precision(__os.precision());
493      __s << '(' << __x.real() << ',' << __x.imag() << ')';
494      return __os << __s.str();
495    }
496
497  // Values
498  template<typename _Tp>
499    inline _Tp
500    real(const complex<_Tp>& __z)
501    { return __z.real(); }
502
503  template<typename _Tp>
504    inline _Tp
505    imag(const complex<_Tp>& __z)
506    { return __z.imag(); }
507
508#ifndef DOXYGEN_IGNORE
509  template<typename _Tp>
510    inline _Tp
511    abs(const complex<_Tp>& __z)
512    {
513      _Tp __x = __z.real();
514      _Tp __y = __z.imag();
515      const _Tp __s = std::max(std::abs(__x), std::abs(__y));
516      if (__s == _Tp())  // well ...
517        return __s;
518      __x /= __s;
519      __y /= __s;
520      return __s * sqrt(__x * __x + __y * __y);
521    }
522
523  template<typename _Tp>
524    inline _Tp
525    arg(const complex<_Tp>& __z)
526    { return atan2(__z.imag(), __z.real()); }
527
528  // 26.2.7/5: norm(__z) returns the squared magintude of __z.
529  //     As defined, norm() is -not- a norm is the common mathematical
530  //     sens used in numerics.  The helper class _Norm_helper<> tries to
531  //     distinguish between builtin floating point and the rest, so as
532  //     to deliver an answer as close as possible to the real value.
533  template<bool>
534    struct _Norm_helper
535    {
536      template<typename _Tp>
537        static inline _Tp _S_do_it(const complex<_Tp>& __z)
538        {
539          const _Tp __x = __z.real();
540          const _Tp __y = __z.imag();
541          return __x * __x + __y * __y;
542        }
543    };
544
545  template<>
546    struct _Norm_helper<true>
547    {
548      template<typename _Tp>
549        static inline _Tp _S_do_it(const complex<_Tp>& __z)
550        {
551          _Tp __res = abs(__z);
552          return __res * __res;
553        }
554    };
555
556  template<typename _Tp>
557    inline _Tp
558    norm(const complex<_Tp>& __z)
559    {
560	return _Norm_helper<
561#if LAPACKPP_HAVE_BITS_CPP_TYPE_TRAITS_H
562	    std::__is_floating<_Tp>::
563#  if defined __GNUC__ && (__GNUC__ > 3)
564	    // This member name is for gcc>=4.0.0
565	    __value
566#  else
567	    // This member name is for gcc 3.x.x
568	    _M_type
569#  endif // __GNUC__ > 3
570	    && !
571#  ifdef _GLIBCXX_FAST_MATH
572	    // This macro name is new in gcc3.4
573	    _GLIBCXX_FAST_MATH
574#  else
575	    // This macro name is for gcc3.3
576	    _GLIBCPP_FAST_MATH
577#  endif // _GLIBCXX_FAST_MATH
578#else // LAPACKPP_HAVE_BITS_CPP_TYPE_TRAITS_H
579	    false
580#endif // LAPACKPP_HAVE_BITS_CPP_TYPE_TRAITS_H
581	    >::_S_do_it(__z);
582    }
583
584#endif // DOXYGEN_IGNORE
585  // much deleted...
586
587#if defined __GNUC__ && (__GNUC__ > 2)
588  // 26.2.3  complex specializations
589  // complex<double> specialization
590  template<> class complex<double>
591  {
592  public:
593    typedef double value_type;
594
595    complex(double  =0.0, double =0.0);
596#ifdef _GLIBCPP_BUGGY_COMPLEX
597    complex(const complex& __z) : _M_value(__z._M_value) { }
598#endif // _GLIBCPP_BUGGY_COMPLEX
599    complex(const complex<float>&);
600    explicit complex(const complex<long double>&);
601    // CS: Additionally add conversion *from* stdc++ type.
602    complex(const std::complex<double>&);
603    // CS: end
604
605    double real() const;
606    double imag() const;
607
608    complex<double>& operator=(double);
609    complex<double>& operator+=(double);
610    complex<double>& operator-=(double);
611    complex<double>& operator*=(double);
612    complex<double>& operator/=(double);
613
614    // The compiler will synthetize this, efficiently.
615    // complex& operator= (const complex&);
616    template<typename _Tp>
617      complex<double>& operator=(const complex<_Tp>&);
618    template<typename _Tp>
619      complex<double>& operator+=(const complex<_Tp>&);
620    template<typename _Tp>
621      complex<double>& operator-=(const complex<_Tp>&);
622    template<typename _Tp>
623      complex<double>& operator*=(const complex<_Tp>&);
624    template<typename _Tp>
625      complex<double>& operator/=(const complex<_Tp>&);
626
627    // CS: Additionally add converstions to old C-style complex type
628    complex(COMPLEX);
629    operator COMPLEX() const;
630    COMPLEX toCOMPLEX() const;
631    operator std::complex<double>() const;
632    // CS: end additions
633
634  private:
635    typedef __complex__ double _ComplexT;
636    _ComplexT _M_value;
637
638    complex(_ComplexT __z) : _M_value(__z) { }
639
640    friend class complex<float>;
641    friend class complex<long double>;
642  };
643
644  inline double
645  complex<double>::real() const
646  { return __real__ _M_value; }
647
648  inline double
649  complex<double>::imag() const
650  { return __imag__ _M_value; }
651
652  inline
653  complex<double>::complex(double __r, double __i)
654  {
655    __real__ _M_value = __r;
656    __imag__ _M_value = __i;
657  }
658
659  // CS: addition
660  inline
661  complex<double>::complex(const std::complex<double>&__s)
662  {
663    __real__ _M_value = __s.real();
664    __imag__ _M_value = __s.imag();
665  }
666  // CS: end addition
667
668  inline complex<double>&
669  complex<double>::operator=(double __d)
670  {
671    __real__ _M_value = __d;
672    __imag__ _M_value = 0.0;
673    return *this;
674  }
675
676  inline complex<double>&
677  complex<double>::operator+=(double __d)
678  {
679    __real__ _M_value += __d;
680    return *this;
681  }
682
683  inline complex<double>&
684  complex<double>::operator-=(double __d)
685  {
686    __real__ _M_value -= __d;
687    return *this;
688  }
689
690  inline complex<double>&
691  complex<double>::operator*=(double __d)
692  {
693    _M_value *= __d;
694    return *this;
695  }
696
697  inline complex<double>&
698  complex<double>::operator/=(double __d)
699  {
700    _M_value /= __d;
701    return *this;
702  }
703
704  template<typename _Tp>
705    inline complex<double>&
706    complex<double>::operator=(const complex<_Tp>& __z)
707    {
708      __real__ _M_value = __z.real();
709      __imag__ _M_value = __z.imag();
710      return *this;
711    }
712
713  template<typename _Tp>
714    inline complex<double>&
715    complex<double>::operator+=(const complex<_Tp>& __z)
716    {
717      __real__ _M_value += __z.real();
718      __imag__ _M_value += __z.imag();
719      return *this;
720    }
721
722  template<typename _Tp>
723    inline complex<double>&
724    complex<double>::operator-=(const complex<_Tp>& __z)
725    {
726      __real__ _M_value -= __z.real();
727      __imag__ _M_value -= __z.imag();
728      return *this;
729    }
730
731  template<typename _Tp>
732    inline complex<double>&
733    complex<double>::operator*=(const complex<_Tp>& __z)
734    {
735      _ComplexT __t;
736      __real__ __t = __z.real();
737      __imag__ __t = __z.imag();
738      _M_value *= __t;
739      return *this;
740    }
741
742  template<typename _Tp>
743    inline complex<double>&
744    complex<double>::operator/=(const complex<_Tp>& __z)
745    {
746      _ComplexT __t;
747      __real__ __t = __z.real();
748      __imag__ __t = __z.imag();
749      _M_value /= __t;
750      return *this;
751    }
752
753  // CS: Additionally add converstions to old C-style complex type
754  inline
755  complex<double>::complex(COMPLEX __c)
756  {
757    __real__ _M_value = __c.r;
758    __imag__ _M_value = __c.i;
759  }
760
761  inline
762  complex<double>::operator COMPLEX() const
763  {
764    return toCOMPLEX();
765  }
766
767  inline COMPLEX
768  complex<double>::toCOMPLEX() const
769  {
770    COMPLEX r;
771    r.r = real();
772    r.i = imag();
773    return r;
774  }
775
776  inline
777  complex<double>::operator std::complex<double>() const
778  {
779    return std::complex<double>(real(), imag());
780  }
781  // CS: end
782#endif // (__GNUC__ > 2)
783
784  // much deleted...
785
786  //@}
787} // namespace std
788
789#endif	/* _CPP_COMPLEX */
790