This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of CD1 status.
Section: 28.4.7 [complex.value.ops] Status: CD1 Submitter: Stefan Große Pawig Opened: 2006-09-24 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [complex.value.ops].
View all issues with CD1 status.
Discussion:
TR1 introduced, in the C compatibility chapter, the function fabs(complex<T>):
----- SNIP ----- 8.1.1 Synopsis [tr.c99.cmplx.syn] namespace std { namespace tr1 { [...] template<class T> complex<T> fabs(const complex<T>& x); } // namespace tr1 } // namespace std [...] 8.1.8 Function fabs [tr.c99.cmplx.fabs] 1 Effects: Behaves the same as C99 function cabs, defined in subclause 7.3.8.1. ----- SNIP -----
The current C++0X draft document (n2009.pdf) adopted this definition in chapter 26.3.1 (under the comment // 26.3.7 values) and 26.3.7/7.
But in C99 (ISO/IEC 9899:1999 as well as the 9899:TC2 draft document n1124), the referenced subclause reads
----- SNIP ----- 7.3.8.1 The cabs functions Synopsis 1 #include <complex.h> double cabs(double complex z); float cabsf(float complex z); long double cabsl(long double z); Description 2 The cabs functions compute the complex absolute value (also called norm, modulus, or magnitude) of z. Returns 3 The cabs functions return the complex absolute value. ----- SNIP -----
Note that the return type of the cabs*() functions is not a complex type. Thus, they are equivalent to the already well established template<class T> T abs(const complex<T>& x); (26.2.7/2 in ISO/IEC 14882:1998, 26.3.7/2 in the current draft document n2009.pdf).
So either the return value of fabs() is specified wrongly, or fabs() does not behave the same as C99's cabs*().
Possible Resolutions
This depends on the intention behind the introduction of fabs().
If the intention was to provide a /complex/ valued function that calculates the magnitude of its argument, this should be explicitly specified. In TR1, the categorization under "C compatibility" is definitely wrong, since C99 does not provide such a complex valued function.
Also, it remains questionable if such a complex valued function is really needed, since complex<T> supports construction and assignment from real valued arguments. There is no difference in observable behaviour between
complex<double> x, y; y = fabs(x); complex<double> z(fabs(x));
and
complex<double> x, y; y = abs(x); complex<double> z(abs(x));
If on the other hand the intention was to provide the intended functionality of C99, fabs() should be either declared deprecated or (for C++0X) removed from the standard, since the functionality is already provided by the corresponding overloads of abs().
[ Bellevue: ]
Bill believes that abs() is a suitable overload. We should remove fabs().
Proposed resolution:
Change the synopsis in 28.4.2 [complex.syn]:
template<class T> complex<T> fabs(const complex<T>&);
Remove 28.4.7 [complex.value.ops], p7:
template<class T> complex<T> fabs(const complex<T>& x);
-7- Effects: Behaves the same as C99 function cabs, defined in subclause 7.3.8.1.
[ Kona (2007): Change the return type of fabs(complex) to T. Proposed Disposition: Ready ]