How to automatically generate function overloads
3 days ago
Blatnik
3 days ago
Blatnik
3 days ago
Zone
3 days ago
Blatnik

I'm porting over my linear algebra library from C++, and I have a bunch of functions that work on both scalars and vectors. The vector versions just apply the scalar function to every element of the vector, for example:

``````float clamp01(float x) { return x < 0 ? 0 : (x > 1 ? 1 : x); }

float[N] clamp01(size_t N)(float[N] vec)
{
float[N] result;
static foreach (i; 0 .. N)
result[i] = clamp01(vec[i]);

return result;
}
``````

And this is great, I don't have to write the same function for different array lengths.

But I still have like 30-ish of these functions and I would like to generate the array overload automatically from the scalar overload.

So I would like something like a mixin, that I can use like this:

``````mixin Vectorize_Unary_Function!clamp01; // Generates the code above.
mixin Vectorize_Unary_Function!floor;
mixin Vectorize_Unary_Function!ceil;
...
``````

It doesn't have to be a mixin like this. I don't really care what it is as long as it works :)

How could I do this?

On Tuesday, 4 May 2021 at 11:00:42 UTC, Blatnik wrote:

>

How could I do this?

``````mixin template Vectorize_Unary_Function(alias Function)
{
float[N] Function(size_t N)(float[N] vec)
{
float[N] result;
static foreach (i; 0 .. N)
result[i] = Function(vec[i]);
return result;
}
}
``````

But it didn't work.

``````mixin Vectorize_Unary_Function!clamp01;

float vec = [1, 2];
float clamped = clamp01(vec); // Error
``````

I think it actually declared a function called "Function" instead of calling it "clamp01" like the alias I passed in.

On Tuesday, 4 May 2021 at 11:00:42 UTC, Blatnik wrote:

>

I'm porting over my linear algebra library from C++, and I have a bunch of functions that work on both scalars and vectors. The vector versions just apply the scalar function to every element of the vector, for example:

``````float clamp01(float x) { return x < 0 ? 0 : (x > 1 ? 1 : x); }

float[N] clamp01(size_t N)(float[N] vec)
{
float[N] result;
static foreach (i; 0 .. N)
result[i] = clamp01(vec[i]);

return result;
}
``````

And this is great, I don't have to write the same function for different array lengths.

But I still have like 30-ish of these functions and I would like to generate the array overload automatically from the scalar overload.

So I would like something like a mixin, that I can use like this:

``````mixin Vectorize_Unary_Function!clamp01; // Generates the code above.
mixin Vectorize_Unary_Function!floor;
mixin Vectorize_Unary_Function!ceil;
...
``````

It doesn't have to be a mixin like this. I don't really care what it is as long as it works :)

How could I do this?

``````float clamp01(float x) { return x < 0 ? 0 : (x > 1 ? 1 : x); }

template Vectorize_Unary_Function(alias fun) {
float[N] Vectorize_Unary_Function(size_t N)(float[N] vec)
{
float[N] result;
static foreach (i; 0 .. N)
result[i] = fun(vec[i]);
return result;
}
}

alias clamp01 = Vectorize_Unary_Function!clamp01;

void main() {
float vec = [1,2,3,4,5];
float other = clamp01(vec);
writeln(vec);
writeln(other);
}
``````

Not exactly what you were asking for but I hope it works, tricky part is I'm not sure how to generate the function name without string mixins so that's why I used alias instead.

On Tuesday, 4 May 2021 at 11:21:20 UTC, Zone wrote:

>
``````template Vectorize_Unary_Function(alias fun) {
float[N] Vectorize_Unary_Function(size_t N)(float[N] vec)
{
float[N] result;
static foreach (i; 0 .. N)
result[i] = fun(vec[i]);
return result;
}
}

alias clamp01 = Vectorize_Unary_Function!clamp01;
``````

Not exactly what you were asking for but I hope it works, tricky part is I'm not sure how to generate the function name without string mixins so that's why I used alias instead.

Awesome, this does exactly what I wanted. Thanks for the help! :)