Expression template

Etranger via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat Jul 23 04:05:57 PDT 2016


Hello all,

I will greatly appreciate if you could help me with my first step 
in the D land.

*YOU CAN SKIP DIRECTLY TO THE QUESTION BELLOW*:

Please allow me to introduce myself and give you my feelings 
about the D language then I'll ask my question. I'm a 
mathematician that works mainly on computer vision and machine 
learning for a research institute. All my CV code is written in 
C++ (runs on android and iOs) and no need to say that I'm 
desperately looking to replace it by a more modern language. My 
main complains about C++ are safety, implicit conversion between 
numeric types, tooling (no unified package manager, benchmarking 
or testing framework), verbose generics, poor standard library 
(although boost is great, but then compile time goes crazy), not 
so great at writing "high level" code when needed ... it just old.

I looked into some contenders: D, ocaml, Go, rust, even Haskell! 
GC languages are definitely not an option for computer vision and 
low level machine learning (writing ML libs), so GO, ocaml and 
haskell are out. (Although I use Go for production when I have to 
deal with concurrency and networks (getting energy data from 
sensors or web crawlers). The language is meh but the finishing 
(tooling, stability, documentation and libraries) is great).

So the only left possible alternatives are D and rust. I looked 
into D few years later but didn't look far as it was advertised 
as a GC language and the community (and support) seemed too 
small, and the tooling/libs not so great. I spent allot of time 
following rust and learning it, and put allot of hope in it. 
However, today rust seems to have 3 main deal breaking weaknesses 
for my particular use :

1-Bad C++ interop, and no plans to make it better. For me as for 
many developers in my field, I cannot work without my tools (like 
openCV, Eigen, Armadillo ...). No matter how good the language 
is, if it does not allow me to use well known and tested 
libraries that I need in my day job (or offers equivalent quality 
libs), I just cannot use it, its impossible.

2- Limited support for generics and little interest at enhancing 
them. Generic programming is essential to build highly efficient 
numeric libraries, like Eigen and Armadillo that relays heavily 
on expression templates to avoid temporaries. Rust still does not 
support integer template parameters and its trait based generics 
may be more secure but are very hard to use and impractical for 
non trivial generic code.

3- Memory management. The borrow checker is a real advantage when 
there is a need for highly efficient code. But for the less 
demanding applications in term of efficiency, it is a burden and 
I think a GC is more adapted for such applications.

Although rust is a wonderful language with a great community, The 
points 1 and 2 are deal breaking for me, and are what made me 
return to D and have a better look (expect allot of peoples like 
me I think when the hype start to diminish around rust and people 
that have tasted a modern programming language find them self 
unable to return to C++ but too limited by rust constraints).

By contrast, the 3 main weaknesses of rust (for me) are what 
attract me to the D language:

1- Good foundations for a full C++ interopt. Although we still 
cannot use C++ libs without any bindings like in objective-C. The 
work made so far on the D compiler + Calypso ( 
https://github.com/Syniurge/Calypso ) give me hope that one day, 
I'll just be able to put and "import opencv2.core;" into my code 
and use D in my work. By the way, make Calypso an official 
project to allow full interop with C++, stabilize one compiler on 
all major platforms and I'll throw C++ from the window and never 
look back.

2- Great at generics (hello Andrei !)

3- Optional Gc with I hope full support for non-GC memory 
management soon.

In brief, D is great, if you give it full c++ interop and 
stabilize the compiler(s) and the tooling, get backed by some big 
name in the industry, I think it is condemned to succeed.

****THE QUESTION****

Expression templates are heavily used in C++ to build highly 
efficient linear algebra libraries with lazy evaluation. I order 
to learn D, I'm trying to implement such system in D, so I can 
maybe interface it with ndslices and translate a linear algebra 
lib like Eigen in D.

For a first step, I tried to translate the example given here 
https://en.wikipedia.org/wiki/Expression_templates , and here is 
my attempt:

***************** start of code ******************
import std.stdio;
import std.traits;
import std.conv;

struct VecExpression(alias mixins) {
   mixin (mixins);
   VecSum!(typeof(this), VecExpression!(RHS)) opBinary(string op, 
alias RHS)(ref VecExpression!(RHS) rhs)
{
   static if (op == "+") return VecSum!(typeof(this), 
VecExpression!(RHS))(&this, &rhs);
}
}


mixin template Vec_impl(int n) {
   double[n] elems;

   @disable this();

   this(double[n] e){
     elems=e;
   }

   double opIndex(int i) {
     return elems[i];
   }
}

alias Vec(alias n) = VecExpression!("mixin 
Vec_impl!("~to!string(n)~");"); //Vec(int n) does not work

mixin template VecSum_impl(E1, E2) {
   E1 * e1;
   E2 * e2;

   @disable this();

   this(E1 * ee1, E2 * ee2){
     e1=ee1;
     e2=ee2;
   }

   double opIndex(int i) {
     return (*e1)[i]+(*e2)[i];
   }
}

alias VecSum(E1, E2) = VecExpression!("mixin 
VecSum_impl!("~fullyQualifiedName!E1~","~fullyQualifiedName!E2~");");

void main()
{
   Vec!(3) v1 = Vec!(3)([5., 2., 3.]), v2 = Vec!(3)([1., 4., 3.]), 
v3 = Vec!(3)([3., 2., 1.]);
   auto res = v1+v2;
   for(int i=0; i < 3; ++i){
     writefln("%f + %f = %f", v1[i], v2[i],  res[i]);
   }
   auto res2 = res+v3;
   for(int i=0; i < 3; ++i){
     writefln("%f + %f = %f", res[i], v3[i],  res2[i]);
   }
   writeln(res);
   writeln(res2);

   // VecExpression!(Vec_impl!(3)) ve; // Error: template instance 
Vec_impl!3 mixin templates are not regular templates
}

***************** end of code ******************

My questions:

1- Is there a cleaner way to do it ? I had to use struct because 
I want every thing to happen at compile time and on the stack 
(without gc). And I had to use string mixins because template 
mixin does not work the way I tried to use it ( see the error 
last line).

2- Is there a safer way to do it (without using pointers) ?

3- Do you think I'll hit a wall with this approach ?

4- Do you known any D libs that uses expression template for 
linear algebra ?

I thank you in advance for your help and wish you a nice weekend 
(and apologize for my bad english) :)




More information about the Digitalmars-d-learn mailing list