January 06, 2007
I've been experimenting with D's template capabilities to speed up some number crunching codes.
In that process I adapted the evaluation of the dot product of two arrays, originally in C++ and found at: http://osl.iu.edu/~tveldhui/papers/techniques/.

I think the D version is very concise and simple to understand, so it could be added to the examples given in the templates documentation. On the other hand, this kind of examples could motivate people working on numerical codes to try D.

--------------------------------------------
/// Rational:
///  Using a loop to compute the dot product of two small/medium size float arrays, e.g.
///
///     float s = 0.0;
///     for (int i=0, i < size, ++i)
///           s += a[i]*b[i];
///     return s;
///
///  can be very inefficient when compared to the hand written expression
///
///     return a[O]*b[0] + a[1]*b[1] + .....;
///
///  Using template metaprogramming we can get the same effect without explicitly writing
///  code for different array size and type.

struct dot_product(T, int N) {
    static T opCall (T[N] a, T[N] b) {
        return meta_dot!(N-1, N, T)(a,b); // expands to: a[0]*b[0] + a[1]*b[1] + .... at compilation time
    }
}

struct meta_dot(int I, int N, T) {
    static T opCall(T[N] a, T[N] b) {
        static if (I == 0)
   	    return a[0]*b[0];
        else
   	    return a[I]*b[I] + meta_dot!(I-1, N, T)(a,b);
     }
}

// -------
// Usage:
// -------
float[3] a;
float[3] b;
a[] = 0.5;
b[] = 0.5;
float dot = dot_product!(float, 3)(a, b);
writefln("dot: %f", dot); // = 0.750000
---------------------------------------------

Paulo
January 06, 2007
Paulo Herrera wrote:
> I've been experimenting with D's template capabilities to speed up some
> number crunching codes.
> In that process I adapted the evaluation of the dot product of two
> arrays, originally in C++ and found at:
> http://osl.iu.edu/~tveldhui/papers/techniques/.
> 
> I think the D version is very concise and simple to understand, so it could be added to the examples given in the templates documentation. On the other hand, this kind of examples could motivate people working on numerical codes to try D.
> 

Nice. Function templates make the code even nicer-looking, IMHO:

import std.stdio;

T dot_product(T, size_t N)(T[N] a, T[N] b) {
	return meta_dot!(N-1, N, T)(a,b);
}

T meta_dot(size_t I, size_t N, T)(T[N] a, T[N] b) {
	static if (I == 0)
		return a[0]*b[0];
	else
		return a[I]*b[I] + meta_dot!(I-1, N, T)(a,b);
}

void main() {
	float[3] a;
	float[3] b;
	a[] = 0.5;
	b[] = 0.5;
	float dot = dot_product(a, b); // note how implicit function template
instantiation means we don't need to specify float and 3
	writefln("dot: %f", dot);
}


-- 
Remove ".doesnotlike.spam" from the mail address.