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

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?

3 days ago

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

>

How could I do this?

I've already tried 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[2] vec = [1, 2];
float[2] clamped = clamp01(vec); // Error

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

3 days ago

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[5] vec = [1,2,3,4,5];
    float[5] 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.

3 days ago

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! :)