Thanks for the suggestions!<div><br></div><div>I don't think UFCS would help us. Our problem is that we can't do this:<div>triangular.d:</div><div>  struct TriangularMatrix {</div><div><br></div><div>  }</div><div>

<br></div><div>  void sum( T )( T x ) if( is( T : TriangularMatrix ) ) {</div><div><br></div><div>  }</div><div><br></div><div>diagonal.d:</div><div>  struct DiagonalMatrix {</div><div><br></div><div>  }</div><div><br></div>

<div>  void sum( T )( T x ) if( is( T : DiagonalMatrix ) ) {</div><div>      </div><div>  }</div><div><br></div><div>main.d:</div><div>import diagonal;</div><div>import triangular;</div><div><br></div><div>void bar() {</div>

<div>   TriangularMatrix a;</div><div>   Diagonal b;</div><div>   sum( a );  // this does not compile because sum() is ambiguous</div><div>   sum( b );  // nor does this</div><div>}</div><div><br></div><div>This, AFAIK, is deliberate to avoid name hijacking - ADL in C++ had its share of criticism. I doubt we will ever get this behaviour in D and that is perhaps a good thing. I may have misunderstood UFCS though - or what you meant by making non-member function calls look nicer - please correct me if that's the case. <br>

<div><br></div><div>Don't worry about long names, t() is already the way transposition is defined SciD. Moreover, it's a property so you can actually do "a.t * a" - convenience galore. I'm also considering of creating a submodule like std.linalg.short which defines aliases with short names for types and free functions - this will allow particularly numerics-heavy functions to be written more compactly. I'm not entirely sure it would be a good idea though as it may sacrifice readability where it's most needed.<br clear="all">

<div><br></div><div>---</div>Cristi Cobzarenco<div>BSc in Artificial Intelligence and Computer Science</div><div>University of Edinburgh<br>Profile: <a href="http://www.google.com/profiles/cristi.cobzarenco" target="_blank">http://www.google.com/profiles/cristi.cobzarenco</a></div>

<br>
<br><br><div class="gmail_quote">On 10 April 2012 01:36, Michael Chen <span dir="ltr"><<a href="mailto:sth4nth@gmail.com">sth4nth@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

Hi, Cristi,<br>
>From change log of D 2.059. I saw that uniform function call syntax<br>
was implemented. I hope you can leverage this feature to make non<br>
member function calls look nicer. Another suggestion, please use<br>
shorter function name for example M.t() instead of M.transpose() so<br>
that long expression is easy to read.<br>
<br>
Best,<br>
Mo<br>
<br>
On Mon, Apr 9, 2012 at 6:52 AM, Cristi Cobzarenco<br>
<div class="HOEnZb"><div class="h5"><<a href="mailto:cristi.cobzarenco@gmail.com">cristi.cobzarenco@gmail.com</a>> wrote:<br>
> On 8 April 2012 18:59, Caligo <<a href="mailto:iteronvexor@gmail.com">iteronvexor@gmail.com</a>> wrote:<br>
>><br>
>> On Tue, Apr 3, 2012 at 6:20 AM, Cristi Cobzarenco<br>
>> <<a href="mailto:cristi.cobzarenco@gmail.com">cristi.cobzarenco@gmail.com</a>> wrote:<br>
>> ><br>
>> > The point of these is to have light-weight element wise operation<br>
>> > support.<br>
>> > It's true that in theory the built-in arrays do this. However, this<br>
>> > library<br>
>> > is built on top BLAS/LAPACK, which means operations on large matrices<br>
>> > will<br>
>> > be faster than on D arrays.<br>
>> ><br>
>><br>
>> I can't agree with building it on top of LAPACK or any other BLAS<br>
>> implementation, but perhaps I shouldn't complain because I'm not the<br>
>> one who's going to be implementing it.  I like the approach Eigen has<br>
>> taken where it offers its own BLAS implementation and, iirc, other<br>
>> BLAS libraries can be used as optional back-ends.<br>
><br>
><br>
> Yes, I agree with you. I already built naive implementations for BLAS &<br>
> LAPACK functions as part of my last year project, using external libraries<br>
> is optional (building with version=nodeps ensures absolutely no dependencies<br>
> are needed). The argument still stands, though. If you _do_ use external<br>
> BLAS libraries then using value arrays will _still_ be faster.<br>
><br>
>><br>
>><br>
>> > Also, as far as I know, D doesn't support<br>
>> > allocating dynamic 2-D arrays (as in not arrays of arrays), not to<br>
>> > mention<br>
>> > 2-D slicing (keeping track of leading dimension).<br>
>> ><br>
>><br>
>> I fail to see why there is any need for 2D arrays.  We need to make<br>
>> sure multidimensional arrays (matrices) have data in very good<br>
>> arrangements.  This is called tiling and it requires 1D arrays:  2D<br>
>> arrays are stored as 1D arrays together with an indexing mechanism.<br>
><br>
><br>
> That is precisely what I meant. We need wrappers around D arrays, because<br>
> they, by themselves, do not support 2-D indexing. By providing a wrapper we<br>
> allow the nice syntax of matrix[ a, b ]. This kind of wrapping is already in<br>
> SciD by CowMatrix. I meant we shouldn't use D built-in arrays directly, not<br>
> not at all. Also, as mentioned before, we can't use new for allocation,<br>
> because we want the library to be GC-independent.<br>
>><br>
>><br>
>> > Also I'm not sure how a case like this will be compiled, it may or may<br>
>> > not<br>
>> > allocate a temporary:<br>
>> ><br>
>> > a[] = b[] * c[] + d[] * 2.0;<br>
>> ><br>
>> > The expression templates in SciD mean there will be no temporary<br>
>> > allocation<br>
>> > in this call.<br>
>> ><br>
>><br>
>> Why are expression templates used?<br>
><br>
><br>
> As H. S. Teoh rightfully pointed out, it is important not to allocate<br>
> temporaries in matrix operations. You want to evaluate A = B * 3.0 + D * 2.0<br>
> (where .* is element-wise multiplication) as (in BLAS terms):<br>
>   copy( B, A );<br>
>   scal( 3.0, A );<br>
>   axpy( D, 2.0, A );<br>
><br>
> Or with naive expression template evaluation:<br>
>   for( i = 0 ; i < n ; ++ i ) {<br>
>      A[ i ] = B[ i ] * 3.0 + D * 2.0;<br>
>   }<br>
><br>
> The D compiler would instead evaluate this as:<br>
>   // allocate temporaries<br>
>   allocate( tmp1, A.length );<br>
>   allocate( tmp2, A.length );<br>
>   allocate( tmp3, A.length );<br>
><br>
>   // compute tmp1 = B * 3.0<br>
>   copy( B, tmp1 );<br>
>   scal( 3.0, tmp1 );<br>
><br>
>   // compute tmp2 = D * 2.0;<br>
>   copy( D, tmp2 );<br>
>   scal( 2.0, tmp2 );<br>
><br>
>   // compute tmp3 = tmp1 + tmp2;<br>
>   copy( tmp1, tmp3 );<br>
>   axpy( tmp2, 1.0, tmp1 );<br>
><br>
>   // copy tmp3 into A<br>
>   copy( tmp3, A );<br>
><br>
> Plenty of useless computation. Note this is not a fault of the compiler, it<br>
> has no way of knowing which temporaries can be optimised away for user types<br>
> (i.e. our matrices).<br>
><br>
>> Are you pretty much rewriting Eigen in D?<br>
><br>
> No. It is just the interface - and even that only to a certain extent - that<br>
> will mimic Eigen. The core the library would be very similar to what I<br>
> implemented for SciD last year, which, you will find, is very D-like and not<br>
> at all like Eigen.<br>
><br>
><br>
</div></div></blockquote></div><br></div></div></div>