Boost logo

Boost :

From: David Abrahams (david.abrahams_at_[hidden])
Date: 2002-01-10 18:00:24


----- Original Message -----
From: "Ralf W. Grosse-Kunstleve" <rwgk_at_[hidden]>

> - The real world problem is indeed compatibility with
> existing C or FORTRAN code.
>
> - For in-place FFT's it is only necessary to cast a pointer
> to the beginning of a vector (in the general sense) of
> std::complex to a pointer to the beginning of a
> vector of real numbers (e.g. float or double).
> I.e., essentially memory is reused for different types
> without actually caring about the conversions between
> the types. Using reinterpret_cast<> for this purpose
> seems perfectly OK.

Except that it's not portable. There's no guarantee that the compiler
doesn't insert padding in a complex. It doesn't even have to use the
cartesian representation internally, but that's fixable without a core
language change.

>
> Regarding compatibility with existing C code:
> C does not have a complex type.

C99 does, AFAIK.

> FFTW (e.g.) introduces
> its own type. I guess it is next to impossible to ensure
> portable conversions from std::complex to custom types
> like FFTW's.

As the language is currently defined, yes.

> Regarding compatibility with existing FORTRAN code:
> AFAIK FORTRAN COMPLEX are by definition stored as
> consecutive real values, real part first, imaginary
> part second. Here it would help if std::complex
> was derived from boost::array<T, 2>.

Doesn't FFTW use an equivalent representation?
struct { float re, im; }; is an example of one.

> My proposal was (message 22021 in this group):
>
> template <class T> class complex : public boost::array<T, 2> {
> //...
> };
>
> complex<double> c;
> double* a = c.elems;
>
> No cast required.
>
> Not even for reusing memory in an in-place FFT procedure.

Because complex has a base class, it is now a non-POD type.

  complex<double>* storage = new complex<double>[128];
  double* a = storage->elems;
  double crash = a[2]; // undefined behavior

The requirements for PODs, distilled from the standard, are:

A POD-struct is an aggregate class that has no non-static data members
of type pointer to member, non-POD-struct, non-POD-union (or array of
such types) or reference, and has no user-defined copy assign- ment
operator and no user-defined destructor. Similarly, a POD-union is an
aggregate union that has no non-static data members of type pointer to
member, non-POD-struct, non-POD-union (or array of such types) or
reference, and has no user-defined copy assignment operator and no
user-defined destructor. A POD class is a class that is either a
POD-struct or a POD-union.

An aggregate is an array or a class (clause 9) with no user-declared
constructors (12.1), no private or protected non-static data members
(clause 11), no base classes (clause 10), and no virtual functions
(10.3).

> This would work portably with FORTRAN code, and, more
> importantly, code that is ported from FORTRAN to C++ (such
> as my fftbx posted here earlier).

I'm afraid not :(

> My proposal is compatible with all existing implementations
> of std::complex that I know about, but formalizes
> assumptions that are commonly made in practice (this should
> include the assumption that the complex value is internally
> represented as a real and an imaginary part, as opposed to,
> e.g. an amplitude and an angle).

And a few others.

> It does not, however (as I realize now), improve
> portability when using C code such as FFTW from C++. (But
> then again, it would be easy to modify the C header file to
> derive the custom type from std::complex if compiled with
> C++).

Hmm. I'm not sure that's so easy. Besides, many people don't have access to
the source code of the libraries they use, or are unwilling to rebuild them.

-Dave


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk