title: Eigen: Efficient implementation of matrix from C++ array
body: <p>Would it be possible to implement a class that receives a C-style pointer as a template argument and somehow resolves into a <em>static</em> Eigen matrix but using the memory provided?
  Say a declaration would look something like:</p>
  
  <pre><code>EIGEN_ALIGN16 double array[9];
  CMatrix&lt;double,3,3,array&gt; :: m;
  </code></pre>
  
  <p>I do know about maps, but the example code I provide below has proven them to be slower by 20% when compared to static Eigen matrices.</p>
  
  <p>These would be the premises:</p>
  
  <ul>
  <li><strong>I need to provide my own C pointer</strong>. This way I can efficiently reuse C code without incurring copies.</li>
  <li><strong>The resulting matrix should look static to Eigen</strong> so that Eigen can optimize as it would with a static array at compile time. Look at my example above where at compile time I would provide both matrix size (static) and the C pointer.</li>
  <li>CMatrix <strong>should fall back to</strong> Eigen::Matrix. When the additional template parameter for the C array is not provided I would get the normal Eigen matrix.</li>
  <li><strong>I do not intend to make a full Eigen extension</strong>. With that I mean is I do not care about all kind of checks to provide a neat extension for other users. I just want the most efficient solution for this problem</li>
  </ul>
  
  <p>Would it be possible to implement a solution by adding a new constructor? Say something like:</p>
  
  <pre><code>EIGEN_ALIGN16 double data[9];
  Eigen::Matrix&lt;double,3,3&gt; m(data); //where data is NOT copied but used to replace the static allocation used by default.
  </code></pre>
  
  <p>Find below my code for benchmarking Map vs. Matrix efficiency. It is self contained and you can compile with:</p>
  
  <pre><code>g++ -Ofast -DNDEBUG -DEIGEN_NO_MALLOC -I/path_to_my_Eigen benchmark1.cpp -o benchmark1 -lrt
  </code></pre>
  
  <p>Here is the code:</p>
  
  <pre><code>#include &lt;Eigen/Eigen&gt;
  #include &lt;bench/BenchTimer.h&gt;
  
  #include &lt;iostream&gt;
  
  using namespace Eigen;
  using namespace std;
  
  //#define CLASSIC_METHOD
  #define USE_MAPS
  
  EIGEN_DONT_INLINE void classic(double VO[4], double AT[4][4], double VI[4])
  {
    for (int ii=0; ii&lt;4; ii++)
      {
        VO[ii] = AT[ii][0] * VI[0] +
                 AT[ii][1] * VI[1] +
                 AT[ii][2] * VI[2] +
                 AT[ii][3] * VI[3];
      }
  };
  
  template &lt;typename OutputType, typename MatrixType, typename VectorType&gt;
  EIGEN_DONT_INLINE void modern(MatrixBase&lt;OutputType&gt;&amp; VOE, const MatrixBase&lt;MatrixType&gt;&amp; A44, const MatrixBase&lt;VectorType&gt;&amp; VIE)
  {
    VOE.noalias() = A44.transpose()*VIE;
  };
  
  int main()
  {
    EIGEN_ALIGN16 double AT[4][4] = {0.1, 0.2, 0.3, 2.0, 0.2, 0.3, 0.4, 3.0, 0.3, 0.4, 0.5, 4.0, 0.0, 0.0, 0.0, 1.0};
    EIGEN_ALIGN16 double VI[4] = {1, 2, 3, 4};
    EIGEN_ALIGN16 double VO[4];
  
  //Eigen matrices
  
  #ifndef USE_MAPS
    Matrix4d A44 = Matrix4d::MapAligned(AT[0]);
        Vector4d VIE = Vector4d::MapAligned(VI);
    Vector4d VOE(0,0,0,0);
  #else
    Map&lt;Matrix4d,Aligned&gt; A44(AT[0]);
    Map&lt;Vector4d,Aligned&gt; VIE(VI);
    Map&lt;Vector4d,Aligned&gt; VOE(VO);
  
    // Map&lt;Matrix4d&gt; A44(AT[0]);                                                                                                                                                                                                                                      
    // Map&lt;Vector4d&gt; VIE(VI);                                                                                                                                                                                                                                           
    // Map&lt;Vector4d&gt; VOE(VO);
  
  #endif
  
  #ifdef EIGEN_VECTORIZE
    cout &lt;&lt; "EIGEN_VECTORIZE defined" &lt;&lt; endl;
  #else
      cout &lt;&lt; "EIGEN_VECTORIZE NOT defined" &lt;&lt; endl;
  #endif
  
    cout &lt;&lt; "VIE:" &lt;&lt; endl;
    cout &lt;&lt; VIE &lt;&lt; endl;
  
    VI[0] = 3.14;
    cout &lt;&lt; "VIE:" &lt;&lt; endl;
    cout &lt;&lt; VIE &lt;&lt; endl;
  
    BenchTimer timer;
  
    const int num_tries = 5;
    const int num_repetitions = 200000000;
  
  #ifdef CLASSIC_METHOD
    BENCH(timer, num_tries, num_repetitions, classic(VO, AT, VI));
    std::cout &lt;&lt; Vector4d::MapAligned(VO) &lt;&lt; std::endl;
  #else
    BENCH(timer, num_tries, num_repetitions, modern(VOE, A44, VIE));
    std::cout &lt;&lt; VOE &lt;&lt; std::endl;
  #endif
  
    double elapsed = timer.best();
    std::cout &lt;&lt; "elapsed time: " &lt;&lt; elapsed*1000.0 &lt;&lt; " ms" &lt;&lt; std::endl;
  
    return 0;
  }
  </code></pre>