conj
and proj
Section: 29.4.10 [cmplx.over] Status: C++11 Submitter: Marc Steinbach Opened: 2009-06-11 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [cmplx.over].
View all issues with C++11 status.
Discussion:
In clause 1, the Working Draft (N2857) specifies overloads of the functions
arg, conj, imag, norm, proj, real
for non-complex arithmetic types (float
, double
,
long double
, and integers).
The only requirement (clause 2) specifies effective type promotion of arguments.
I strongly suggest to add the following requirement on the return types:
All the specified overloads must return real (i.e., non-complex) values, specifically, the nested
value_type
of effectively promoted arguments.
(This has no effect on arg
, imag
, norm
, real
:
they are real-valued anyway.)
Rationale:
Mathematically, conj()
and proj()
, like the transcendental functions, are
complex-valued in general but map the (extended) real line to itself.
In fact, both functions act as identity on the reals.
A typical user will expect conj()
and proj()
to preserve this essential
mathematical property in the same way as exp()
, sin()
, etc.
A typical use of conj()
, e.g., is the generic scalar product of n-vectors:
template<typename T> inline T scalar_product(size_t n, T const* x, T const* y) { T result = 0; for (size_t i = 0; i < n; ++i) result += x[i] * std::conj(y[i]); return result; }
This will work equally well for real and complex floating-point types T
if
conj()
returns T
. It will not work with real types if conj()
returns complex values.
Instead, the implementation of scalar_product
becomes either less efficient
and less useful (if a complex result is always returned), or unnecessarily
complicated (if overloaded versions with proper return types are defined).
In the second case, the real-argument overload of conj()
cannot be used.
In fact, it must be avoided.
Overloaded conj()
and proj()
are principally needed in generic programming.
All such use cases will benefit from the proposed return type requirement,
in a similar way as the scalar_product
example.
The requirement will not harm use cases where a complex return value
is expected, because of implicit conversion to complex.
Without the proposed return type guarantee, I find overloaded versions
of conj()
and proj()
not only useless but actually troublesome.
[ 2009-11-11 Moved to Tentatively Ready after 5 positive votes on c++std-lib. ]
Proposed resolution:
Insert a new paragraph after 29.4.10 [cmplx.over]/2:
All of the specified overloads shall have a return type which is the nested
value_type
of the effectively cast arguments.