www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to automatically generate function overloads

reply Blatnik <blatblatnik gmail.com> writes:
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:

```D
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:

```D
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?
May 04
next sibling parent Blatnik <blatblatnik gmail.com> writes:
On Tuesday, 4 May 2021 at 11:00:42 UTC, Blatnik wrote:
 How could I do this?
I've already tried this: ```D 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. ```D 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.
May 04
prev sibling parent reply Zone <none 0.0.0.0> writes:
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:

 ```D
 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:

 ```D
 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?
```D 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.
May 04
parent Blatnik <blatblatnik gmail.com> writes:
On Tuesday, 4 May 2021 at 11:21:20 UTC, Zone wrote:
 ```D
 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! :)
May 04