namespace Eigen {

/** \eigenManualPage TopicStructHavingEigenMembers Structures Having Eigen Members

\eigenAutoToc

\section StructHavingEigenMembers_summary Executive Summary


If you define a structure having members of \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen types", you must ensure that calling operator new on it allocates properly aligned buffers.
If you're compiling in \cpp17 mode only with a sufficiently recent compiler (e.g., GCC>=7, clang>=5, MSVC>=19.12), then everything is taken care by the compiler and you can stop reading.

Otherwise, you have to overload its `operator new` so that it generates properly aligned pointers (e.g., 32-bytes-aligned for Vector4d and AVX).
Fortunately, %Eigen provides you with a macro `EIGEN_MAKE_ALIGNED_OPERATOR_NEW` that does that for you.

\section StructHavingEigenMembers_what What kind of code needs to be changed?

The kind of code that needs to be changed is this:

\code
class Foo
{
  ...
  Eigen::Vector2d v;
  ...
};

...

Foo *foo = new Foo;
\endcode

In other words: you have a class that has as a member a \ref TopicFixedSizeVectorizable "fixed-size vectorizable Eigen object", and then you dynamically create an object of that class.

\section StructHavingEigenMembers_how How should such code be modified?

Very easy, you just need to put a `EIGEN_MAKE_ALIGNED_OPERATOR_NEW` macro in a public part of your class, like this:

\code
class Foo
{
  ...
  Eigen::Vector4d v;
  ...
public:
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};

...

Foo *foo = new Foo;
\endcode

This macro makes `new Foo` always return an aligned pointer.

In \cpp17, this macro is empty.

If this approach is too intrusive, see also the \ref StructHavingEigenMembers_othersolutions "other solutions".

\section StructHavingEigenMembers_why Why is this needed?

OK let's say that your code looks like this:

\code
class Foo
{
  ...
  Eigen::Vector4d v;
  ...
};

...

Foo *foo = new Foo;
\endcode

A Eigen::Vector4d consists of 4 doubles, which is 256 bits.
This is exactly the size of an AVX register, which makes it possible to use AVX for all sorts of operations on this vector.
But AVX instructions (at least the ones that %Eigen uses, which are the fast ones) require 256-bit alignment.
Otherwise you get a segmentation fault.

For this reason, %Eigen takes care by itself to require 256-bit alignment for Eigen::Vector4d, by doing two things:
\li %Eigen requires 256-bit alignment for the Eigen::Vector4d's array (of 4 doubles). This is done with the <a href="https://en.cppreference.com/w/cpp/keyword/alignas">alignas</a> keyword.
\li %Eigen overloads the `operator new` of Eigen::Vector4d so it will always return 256-bit aligned pointers. (removed in \cpp17)

Thus, normally, you don't have to worry about anything, %Eigen handles alignment of operator new for you...

... except in one case. When you have a `class Foo` like above, and you dynamically allocate a new `Foo` as above, then, since `Foo` doesn't have aligned `operator new`, the returned pointer foo is not necessarily 256-bit aligned.

The alignment attribute of the member `v` is then relative to the start of the class `Foo`. If the `foo` pointer wasn't aligned, then `foo->v` won't be aligned either!

The solution is to let `class Foo` have an aligned `operator new`, as we showed in the previous section.

This explanation also holds for SSE/NEON/MSA/Altivec/VSX targets, which require 16-bytes alignment, and AVX512 which requires 64-bytes alignment for fixed-size objects multiple of 64 bytes (e.g., Eigen::Matrix4d).

\section StructHavingEigenMembers_movetotop Should I then put all the members of Eigen types at the beginning of my class?

That's not required. Since %Eigen takes care of declaring adequate alignment, all members that need it are automatically aligned relatively to the class. So code like this works fine:

\code
class Foo
{
  double x;
  Eigen::Vector4d v;
public:
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};
\endcode

That said, as usual, it is recommended to sort the members so that alignment does not waste memory.
In the above example, with AVX, the compiler will have to reserve 24 empty bytes between `x` and `v`.


\section StructHavingEigenMembers_dynamicsize What about dynamic-size matrices and vectors?

Dynamic-size matrices and vectors, such as Eigen::VectorXd, allocate dynamically their own array of coefficients, so they take care of requiring absolute alignment automatically. So they don't cause this issue. The issue discussed here is only with \ref TopicFixedSizeVectorizable  "fixed-size vectorizable matrices and vectors".


\section StructHavingEigenMembers_bugineigen So is this a bug in Eigen?

No, it's not our bug. It's more like an inherent problem of the c++ language specification that has been solved in c++17 through the feature known as <a href="http://wg21.link/p0035r4">dynamic memory allocation for over-aligned data</a>.


\section StructHavingEigenMembers_conditional What if I want to do this conditionally (depending on template parameters) ?

For this situation, we offer the macro `EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)`.
It will generate aligned operators like `EIGEN_MAKE_ALIGNED_OPERATOR_NEW` if `NeedsToAlign` is true.
It will generate operators with the default alignment if `NeedsToAlign` is false.
In \cpp17, this macro is empty.

Example:

\code
template<int n> class Foo
{
  typedef Eigen::Matrix<float,n,1> Vector;
  enum { NeedsToAlign = (sizeof(Vector)%16)==0 };
  ...
  Vector v;
  ...
public:
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW_IF(NeedsToAlign)
};

...

Foo<4> *foo4 = new Foo<4>; // foo4 is guaranteed to be 128bit-aligned
Foo<3> *foo3 = new Foo<3>; // foo3 has only the system default alignment guarantee
\endcode


\section StructHavingEigenMembers_othersolutions Other solutions

In case putting the `EIGEN_MAKE_ALIGNED_OPERATOR_NEW` macro everywhere is too intrusive, there are other solutions.

\subsection othersolutions1 Disabling alignment

The first is to disable alignment requirement for the fixed size members:
\code
class Foo
{
  ...
  Eigen::Matrix<double,4,1,Eigen::DontAlign> v;
  ...
};
\endcode
This `v` is fully compatible with aligned Eigen::Vector4d.
This has only for effect to make load/stores to `v` more expensive (usually slightly, but that's hardware dependent).


\subsection othersolutions2 Owning Eigen objects through smart pointers

If only one or two fixed-size vectorizable Eigen objects are involved, the containing class can store them through
owning smart pointers instead of storing them directly. Then each Eigen object is dynamically allocated on its own and
uses Eigen's aligned allocation, while the containing object no longer has an over-aligned Eigen member:

\code
class Foo
{
  ...
  std::unique_ptr<Eigen::Vector4d> v;
  ...
public:
  Foo() : v(new Eigen::Vector4d) {}
  void bar()
  {
    // use *v instead of v
    ...
  }
};
\endcode

Do not use a naked owning pointer for this unless you also define the destructor and copy/move operations correctly.
A `std::unique_ptr` member also makes `Foo` non-copyable unless you define copy operations with the desired ownership
semantics.
For several Eigen members, grouping them into a helper structure as shown below is usually clearer and requires only
one additional allocation.

\subsection othersolutions3 Private structure

Another solution consists in storing the fixed-size objects into a private struct which will be dynamically allocated
at the construction time of the main object:

\code
struct Foo_d
{
  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
  Vector4d v;
  ...
};


struct Foo {
  Foo() { init_d(); }
  ~Foo() { delete d; }
  void bar()
  {
    // use d->v instead of v
    ...
  }
private:
  void init_d() { d = new Foo_d; }
  Foo_d* d;
};
\endcode

The clear advantage here is that the class `Foo` remains unchanged regarding alignment issues.
The drawback is that an additional heap allocation will be required whatsoever.

*/

}
