Boost C++ Libraries: Ticket #4034: better vector/matrix assignment (or initialization) https://svn.boost.org/trac10/ticket/4034 <p> proposal from Nasos Iliopoulos: </p> <p> I suppose many of you miss the functionality of creating certain matrices or vectors as in plain c: </p> <p> double vec[] = {0.1, 2.0, 5.0. 0.3} </p> <p> With the proposed classes (in the attached file) it is possible to fill vectors and matrices like that: </p> <pre class="wiki">vector&lt;double&gt; vec(3); vec &lt;&lt; 1.0, 2.0, 3.0; </pre><pre class="wiki">vector_range&lt;vector&lt;double&gt; &gt; vr (a, range (1, 3)); vr &lt;&lt; 11.0, 12.0; </pre><pre class="wiki">matrix&lt;double&gt; mat(3,3); mat &lt;&lt; 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0; </pre><p> or even: </p> <pre class="wiki">mat &lt;&lt; 1.0, 2.0, 3.0, vec, 7.0, 8.0, 9.0; </pre><p> you can also use this form: </p> <pre class="wiki">vector&lt;double&gt; vec(10); vec &lt;&lt; 1.0 , project(a, range(0,2)), 10.0, 11.0, a, 15.0, 16.0; </pre><p> Another nice trick that is especially useful for sparse matrices and vectors is: </p> <pre class="wiki">compressed_matrix&lt;double&gt; cm(3,4, 3*4); cm &lt;&lt; non_vector(4), 1.0, 2.0, project(a,range(0,2)), non_vector(3),2; </pre><p> where the non_vector free functions returns a "non vector" object that is used to traverse the expression without modifying it. </p> <p> I would appreciate your general feedback, thoughts, critisism as well as your opinion in the following issues: </p> <ul><li>Are there any features beside those presented above and in the attached example that you probably would like to see? </li></ul><p> <br /> </p> <ul><li>Where do you think this should be added? As a separate header file, or included in vector_ and matrix_ expression headers? </li></ul><p> <br /> </p> <ul><li>I found it incovenient to implement this functionallity using iterators (especially when the functions work on sparse types). Does anybody think there are considerable gains if attempting that? </li></ul><p> <br /> </p> <ul><li>I also consider implementing functionality so that project(a, range(..)) &lt;&lt; ...; is possible, but I initially faced some problems. I think that _range and _slice classes need to include an operator&lt;&lt; in order for this to work. If somebody wants to work on that it would be great. </li></ul><p> <br /> I will write the unit tests if the maintainers consider the proposed code for addition into uBlas. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/4034 Trac 1.4.3 Gunter Mon, 22 Mar 2010 21:58:25 GMT attachment set https://svn.boost.org/trac10/ticket/4034 https://svn.boost.org/trac10/ticket/4034 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">assigner.zip</span> </li> </ul> <p> proposed header file and example </p> Ticket nasos_i@… Sun, 28 Mar 2010 20:33:17 GMT attachment set https://svn.boost.org/trac10/ticket/4034 https://svn.boost.org/trac10/ticket/4034 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">assignment.patch.tar.gz</span> </li> </ul> <p> universal assignment operator&lt;&lt; for vector and matrix expressions </p> Ticket nasos_i@… Sun, 28 Mar 2010 20:39:41 GMT <link>https://svn.boost.org/trac10/ticket/4034#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4034#comment:1</guid> <description> <p> I attach a whole new version of the assignment operator (assignment.patch.tar.gz). The patch contains a header assignment.hpp and unit tests (test_assignment.cpp). I think some sophisticated assignment tricks can be used with those operators (still finding news ways they can be used). This version is a complete rewrite, but in terms of interface the differences are the following: </p> <ol start="0"><li>Name was changed to assignment after Boost.Assignment. </li></ol><ol><li>non_vector(T i) was removed and was replaced by move(T i) </li></ol><ol start="2"><li>move(T i, T j) was added for matrix expression traversing </li></ol><ol start="3"><li>Absolute traverser was added so that move_to(T i) and move_to(T i, T j) can be used on vector and matrix containers respectively. </li></ol><ol start="4"><li>mat1 &lt;&lt; mat2, ... support was added </li></ol><ol start="5"><li>A simple traits mechanism so that fill policy can be chosen was implemented. This allows for: </li></ol><pre class="wiki">compressed_matrix&lt;double&gt; cm; cm &lt;&lt; fill_policy::sparse_push_back(), 1, 2, mat, vec, vec_expres, ...; </pre><ol start="6"><li>A number of test cases were added in the spirit of <a class="ext-link" href="http://svn.boost.org/svn/boost/trunk/libs/numeric/ublas/test/test_coordinate_matrix_sort.cpp"><span class="icon">​</span>http://svn.boost.org/svn/boost/trunk/libs/numeric/ublas/test/test_coordinate_matrix_sort.cpp</a>. </li></ol><p> They patch looks ready for merging to ublas, but of course this is only under my eyes. Comments, suggestions are HIGHLY desired. </p> <p> Beside the sparse_push_back policy, performance was not considered but with the fill_policy tag it looks that we can implement more sophisticated assignments now. I can write a small tutorial or guide, but I would like to now the format I should provide it in. </p> <p> Best Nasos </p> </description> <category>Ticket</category> </item> <item> <author>cassioliandre@…</author> <pubDate>Sat, 10 Apr 2010 10:41:44 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4034#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4034#comment:2</guid> <description> <p> Hi guys, I found the overall discussion very stimulating. </p> <p> Using uBlas can be quite annoying for the lack of such assignement operators that in my experience (i'm working on the optimization and fem simulation field). </p> <p> I was wondering if it not might be the case to take a look to the Boost::Assign library and see if it can be extended and adapted to work with uBlas. For naive assignament it already provides operator+= and similar that could be useful to simply fill vectors. For a matrix, a machinery similar to the one in place for map could be used. </p> <p> In this way uBlas could be used more freely besides for instance a std::vector, for which Boost::Assign already works. </p> <p> For what concern how to rule the access if by rows or columns, I suggest to possibilities: </p> <ul><li>do not allow free access but force user to specify the column or row access explicitly, as for instance as <div class="wiki-code"><div class="code"><pre> <span class="n">boost</span><span class="o">::</span><span class="n">numeric</span><span class="o">::</span><span class="n">ublas</span><span class="o">::</span><span class="n">matrix</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;</span> <span class="n">m</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span><span class="mi">10</span><span class="p">);</span> <span class="n">m</span> <span class="o">+=</span> <span class="n">row</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">a_vector_of_values</span> <span class="p">),</span> <span class="n">row</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">another_list_of_values</span><span class="p">);</span> </pre></div></div></li></ul><p> </p> <ul><li>an std::stream modificator like syntax might be used: <div class="wiki-code"><div class="code"><pre> <span class="n">boost</span><span class="o">::</span><span class="n">numeric</span><span class="o">::</span><span class="n">ublas</span><span class="o">::</span><span class="n">matrix</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;</span> <span class="n">m</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span><span class="mi">10</span><span class="p">);</span> <span class="n">m</span> <span class="o">&lt;&lt;</span> <span class="n">row</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">&lt;&lt;</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="o">&lt;&lt;</span> <span class="n">row</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">&lt;&lt;</span> <span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">7</span><span class="p">;</span> </pre></div></div></li></ul><p> Best Regards, Andrea </p> </description> <category>Ticket</category> </item> <item> <author>nasos_i@…</author> <pubDate>Sat, 10 Apr 2010 23:10:42 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4034#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4034#comment:3</guid> <description> <p> Hi Andrea, I just saw your post as I am getting ready to upload the new version of assignment operator. Anyway, you have some nice comments and as having worked on the subject I would like to add my experience: </p> <ol><li>My first choice was to take a look at Boost::Assign. The basics of the ublas assignment code are inspired from Boost::Assign, but because of the relatively small (just 50 or 60) lines of code that were needed from Boost Assign, the rest should be considerably different (because of matrices and especially sparse containers). </li></ol><ol start="2"><li>I am not sure whether it must be restricted to just rows (or columns). Anyway the code following allows for that behaviour if such verbosity is desired, based on Gunter's comments in the mailing list. </li></ol><p> Best Nasos </p> </description> <category>Ticket</category> </item> <item> <author>nasos_i@…</author> <pubDate>Sat, 10 Apr 2010 23:26:57 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/4034 https://svn.boost.org/trac10/ticket/4034 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">assignment2.zip</span> </li> </ul> <p> Assignment operator&lt;&lt;= </p> Ticket nasos_i@… Sat, 10 Apr 2010 23:28:33 GMT <link>https://svn.boost.org/trac10/ticket/4034#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4034#comment:4</guid> <description> <p> Based on the comments by Gunter (<a class="ext-link" href="http://lists.boost.org/MailArchives/ublas/2010/03/4121.php"><span class="icon">​</span>http://lists.boost.org/MailArchives/ublas/2010/03/4121.php</a>) and David (<a class="ext-link" href="http://lists.boost.org/MailArchives/ublas/2010/03/4123.php"><span class="icon">​</span>http://lists.boost.org/MailArchives/ublas/2010/03/4123.php</a>), I attach the new version of the assignment operator (assignment2.zip). The main differences with the previous are the following: </p> <ol><li>Added a number of manipulators based on standard library concepts (like std::setprecision). Those allow for functionality like moving to the next row or column, moving to the begining of a row, etc. </li></ol><ol start="2"><li>Changed the assigner overall design from tag dispatch based to policy based. I figured out that this allows for better extensibility. </li></ol><ol start="3"><li>Added a fairly extensive number of unit tests (this takes some time to compile) </li></ol><ol start="4"><li>Added benchmarks that show that the performance is equivalent to classical assignment even for small containers. </li></ol><ol start="5"><li>Added a number of examples of how the assignment may be used in a variety of situations. </li></ol><ol start="6"><li>Commented most of the code. </li></ol><ol start="7"><li>Changed the operator from &lt;&lt; to &lt;&lt;=, as I feel it is more representative of the work done by the assignment. </li></ol><p> Best regards </p> <p> Nasos </p> </description> <category>Ticket</category> </item> <item> <author>cassioliandre@…</author> <pubDate>Sun, 11 Apr 2010 14:41:03 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4034#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4034#comment:5</guid> <description> <p> Nice job! I want to make few comments I hope that will be useful: </p> <ul><li>I found sometimes misleading the plain sintax: <div class="wiki-code"><div class="code"><pre><span class="n">matrix</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;</span> <span class="n">A</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">);</span> <span class="n">A</span> <span class="o">&lt;&lt;=</span> <span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">7</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">9</span><span class="p">;</span> </pre></div></div></li></ul><p> and in any case too many modificators may give rise to confusion and code mess. Why do not use the column_adaptor and row adaptor to explicitly insert cols and rows? </p> <div class="wiki-code"><div class="code"><pre><span class="n">matrix</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;</span> <span class="n">A</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">);</span> <span class="c1">//sorry for the non-standard syntax....</span> <span class="n">row_adaptor</span><span class="p">(</span><span class="n">A</span><span class="p">,</span><span class="mi">0</span><span class="p">)</span> <span class="o">&lt;&lt;=</span> <span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">;</span> <span class="n">row_adaptor</span><span class="p">(</span><span class="n">A</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span> <span class="o">&lt;&lt;=</span> <span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">;</span> <span class="n">row_adaptor</span><span class="p">(</span><span class="n">A</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span> <span class="o">&lt;&lt;=</span> <span class="mi">7</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">9</span><span class="p">;</span> </pre></div></div><p> the use of new_col and next_row is nice, and I might say in my opinion the plain traversing should be avoided, at least if no performance issues arise. The use of BOOST_UBLAS_DEFAULT_ASSIGN_BY_COLUMN define is not as clear as a many people might think. Instead, if traversing is needed, an explicit manipulator can do the trick. </p> <p> I do not think that assuming row_traversing by default is a clean and safe policy. I 'd rather imagine no default policy and explicit control by the user. The same applies to the wrapping. </p> <p> Another suggestion might be the inserte based syntax proposed for the MTL4: </p> <div class="wiki-code"><div class="code"><pre><span class="n">matrix</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;</span> <span class="n">A</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="mi">3</span><span class="p">);</span> <span class="n">row_inserter</span> <span class="nf">row_ins</span><span class="p">(</span><span class="n">A</span><span class="p">);</span> <span class="c1">//sorry for the non-standard syntax....</span> <span class="n">row_ins</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="o">&lt;&lt;=</span> <span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">;</span> <span class="n">row_ins</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="o">&lt;&lt;=</span> <span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">;</span> <span class="n">row_ins</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">&lt;&lt;=</span> <span class="mi">7</span><span class="p">,</span><span class="mi">8</span><span class="p">,</span><span class="mi">9</span><span class="p">;</span> </pre></div></div><ul><li>performances are not equivalent to the standard assignement as claimed. I've played a little bit with the g++ compiler (version 4.4.3 with boost 1.42) with my old intel centrino laptop and the results show a loss of performance between 13% to 1566.67%, depending on the test and the optimization options (from -DNDEBUG only to -DNDEBUG -O3 -ftree-vectorize -funroll-all-loops). </li></ul><p> From my point of view, it sounds strange that performances could decay in such way, for the containers are created of the right size and no resizing take place (as for push_back operations). I can't see at the moment what might cause such overhead, but a code profiling might help. Forcing a more aggressive compilation helps, but I deep understand might be a good starting point to work out some hidden problems. </p> <p> By the way, it looks very promising! And indeed I do appreciate the idea of a set of static manipulators , possibly faster than the normal ones. </p> </description> <category>Ticket</category> </item> <item> <author>nasos_i@…</author> <pubDate>Mon, 12 Apr 2010 00:49:50 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/4034#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/4034#comment:6</guid> <description> <p> Andrea, </p> <p> I suppose this debate will go on for a while, as I feel that people are divided in the explicit or implicit traversing options :). Anyway both can be implemented so I suppose it is a matter of choice from Gunter and David, or from the overall popularity in the mailing list or here. </p> <blockquote class="citation"> <p> Why do not use the column_adaptor and row adaptor to explicitly insert cols and rows? </p> </blockquote> <p> This can be achieved in a way as for example: </p> <pre class="wiki"> matrix&lt;double&gt; m; matrix_row&lt;matrix&lt;double&gt; &gt; mr (m, 0); mr &lt;&lt;= 1,2,3; std::cout &lt;&lt; m &lt;&lt; std::endl; </pre><p> I think there may be the need for a few more overloads to achieve what you propose in general. What do you think of just using the matrix proxies? What do others think? </p> <blockquote class="citation"> <p> in my opinion the plain traversing should be avoided, at least if no performance issues arise .... I do not think that assuming row_traversing by default is a clean and safe policy. I 'd rather imagine no default policy and explicit control by the user. The same applies to the wrapping </p> </blockquote> <p> It indeed may be safer and I think no performance issues arise from that. I am not personally convinced though that the safety penalty in stake is that big to drop such convenience. Another consideration for uBlas also is the way people look into it for the first time, I believe an interface that makes sense for the first time user, with certain customisation options for the most advance would turn to be beneficial. </p> <p> Anyway a simple redirection will disable the assignment without an explicit definition of the traverse and wrap policies. </p> <blockquote class="citation"> <p> performances are not equivalent to the standard assignement as claimed </p> </blockquote> <p> Unfortunately on my intel core 2 duo laptop (like 2 years old) I see no statistically significant difference in performance. Other times the classical assignment is faster and other times the assigner assignment is faster (this difference ranges from 0 to 10% both ways). I will look in the assembly code and maybe try to compile on other machines too. </p> <p> My understanding though is that for very small containers, and for certain compilers or architectures, there maybe the need of creating empty objects (like the ones used for certain manipulators), that may still require an 1-byte constructor to be invoked. If you see such a difference maybe something like that is happening with the specific setup. I tried to avoid such a problem by using function based manipulators (like std::endl), but because of the generally more complicated nature of the assigner objects relative to streams, a good design could not be achieved. After all my benchmarks did not signify that this was necessary. Will look more into that and if somebody has something to input (like architectures or compilers that this is the case) I will really like to look into it. </p> <p> Also what is the performance penalty (negative or positive, the last test in the benchmarks gives you for full optimization? This is supposed to be very light weight). </p> <p> Thanx for the very constructive input! </p> <p> </p> </description> <category>Ticket</category> </item> <item> <dc:creator>David Bellot</dc:creator> <pubDate>Mon, 05 Jul 2010 08:33:35 GMT</pubDate> <title>status, milestone changed; cc, resolution set https://svn.boost.org/trac10/ticket/4034#comment:7 https://svn.boost.org/trac10/ticket/4034#comment:7 <ul> <li><strong>cc</strong> <span class="trac-author">David Bellot</span> added </li> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> <li><strong>milestone</strong> <span class="trac-field-old">To Be Determined</span> → <span class="trac-field-new">Boost 1.44.0</span> </li> </ul> Ticket