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