float CT stringification
bearophile
bearophileHUGS at lycos.com
Thu Jun 5 03:31:45 PDT 2008
Metaprogramming in D is a really slow thing, there must be faster & simpler ways.
(I think there are simpler ways, using a scripting language to create D code before the compilation. I have created a Python templating system that seem to work well enough for C++).
I have written the following code to test compile time optimization regarding a small kernel convolution, the metaGenerated() is as fast as the hand written version. I show it here because it may be interesting to someone.
But currently the metaGenerated() doesn't work if the kernel2 contains floating point values. I think this problem can be solved with a compile time function/template like ToString that works on floating point values too, do you have it?
Bye,
bearophile
import std.stdio: put = writef, putr = writefln;
import std.metastrings: Format, ToString;
static import std.c.time;
double clock() {
auto t = std.c.time.clock();
if (t == -1)
return 0.0;
else
return t/cast(double)std.c.time.CLOCKS_PER_SEC;
}
template Tuple(T...) {
alias T Tuple;
}
template GenTerm(string m, string x, string y, int nr, int nc, int posx, int posy, ker...) {
static if (ker[nc * posy + posx] == 0)
const string GenTerm = "";
else static if (ker[nc * posy + posx] == 1)
const string GenTerm = Format!("%s[%s+%s][%s+%s] + ",
m,
x,
ToString!(posx - (nc / 2)),
y,
ToString!(posy - (nr / 2)));
else
const string GenTerm = Format!("%s * %s[%s+%s][%s+%s] + ",
ToString!(ker[nc * posy + posx]), //error if ker[] isn't integral
m,
x,
ToString!(posx - (nc / 2)),
y,
ToString!(posy - (nr / 2)));
}
template GenConvolutionLine(string m, string x, string y, int nr, int nc, int posx, int posy, ker...) {
static if (posx < nc)
const string GenConvolutionLine = GenTerm!(m, x, y, nr, nc, posx, posy, ker) ~
GenConvolutionLine!(m, x, y, nr, nc, posx+1, posy, ker);
else
const string GenConvolutionLine = "";
}
template GenConvolution(string m, string x, string y, int nr, int nc, int posy, ker...) {
static if (posy < nr)
const string GenConvolution = GenConvolutionLine!(m, x, y, nr, nc, 0, posy, ker) ~
GenConvolution!(m, x, y, nr, nc, posy+1, ker);
else
const string GenConvolution = "0";
}
template Convolution(string m, string x, string y, int nc, ker...) {
const string Convolution = GenConvolution!(m, x, y, ker.length / nc, nc, 0, ker);
}
// ------------------------------------------------------
void dynamic(float[][] inm, float[][] outm, float[] kern, int w, int h) {
int height = inm.length;
int width = inm[0].length;
for (int x = 1; x < width - 1; ++x)
for (int y = 1; y < height - 1; ++y) {
float sum = 0.0;
for (int i = 0; i < w; ++i)
for (int j = 0; j < h; ++j)
sum += kern[j * w + i] * inm[x + i - w / 2][y + j - h / 2];
outm[x - 1][y - 1] = sum;
}
}
void handWritten(float[][] inm, float[][] outm) {
int height = inm.length;
int width = inm[0].length;
for (int x = 1; x < width - 1; ++x)
for (int y = 1; y < height - 1; ++y)
outm[x - 1][y - 1] = inm[x+1][y] + inm[x-1][y] + inm[x][y-1] + inm[x][y+1] - 4 * inm[x][y];
}
void metaGenerated(kernel...)(float[][] inm, float[][] outm) {
int height = inm.length;
int width = inm[0].length;
//pragma(msg, Convolution!("inm", "x", "y", 3, kernel)); // to see it
for (int x = 1; x < width - 1; ++x)
for (int y = 1; y < height - 1; ++y)
mixin("outm[x - 1][y - 1] = " ~ Convolution!("inm", "x", "y", 3, kernel) ~ ";");
}
void main() {
const int WIDTH = 200;
const int HEIGHT = WIDTH;
const int NLOOP = 500;
auto data = new float[][](WIDTH, HEIGHT);
auto output = new float[][](WIDTH-2, HEIGHT-2);
for (int j; j < WIDTH; ++j)
data[j][] = 1.5;
auto t0 = clock();
float[] kernel1 = [0, 1, 0, 1, -4, 1, 0, 1, 0];
for (int i; i < NLOOP; ++i)
dynamic(data, output, kernel1, 3, 3);
auto t1 = clock();
for (int i; i < NLOOP; ++i)
handWritten(data, output);
auto t2 = clock();
alias Tuple!(0, 1, 0, 1, -4, 1, 0, 1, 0) kernel2;
for (int i; i < NLOOP; ++i)
metaGenerated!(kernel2)(data, output);
auto t3 = clock();
putr("Dynamic : ", t1 - t0);
putr("Hand written : ", t2 - t1);
putr("Meta-generated: ", t3 - t2);
}
More information about the Digitalmars-d-learn
mailing list