Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
April 08, 2017 Convert this C macro kroundup32 to D mixin? | ||||
---|---|---|---|---|
| ||||
What is the D mixin version equivalent to this macro: #define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) The macro looks cryptic. What the macro does has been explained here: http://stackoverflow.com/questions/3384852/could-someone-help-explain-what-this-c-one-liner-does But I still don't know how to convert that to D mixin. I would like 'mixin' instead of a function is to avoid function call overhead. Also because it is short, so I think a mixin is enough, not a 'template mixin'. |
April 08, 2017 Re: Convert this C macro kroundup32 to D mixin? | ||||
---|---|---|---|---|
| ||||
Posted in reply to biocyberman | On Saturday, 8 April 2017 at 09:53:47 UTC, biocyberman wrote: > > What is the D mixin version equivalent to this macro: > > #define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) > > The macro looks cryptic. What the macro does has been explained here: http://stackoverflow.com/questions/3384852/could-someone-help-explain-what-this-c-one-liner-does > > But I still don't know how to convert that to D mixin. I would like 'mixin' instead of a function is to avoid function call overhead. Also because it is short, so I think a mixin is enough, not a 'template mixin'. I would expect if you implement it as a function the compiler will inline it. You can always use the pragma(inline, true) [1] with -inline to verify. [1] https://dlang.org/spec/pragma.html#inline |
April 08, 2017 Re: Convert this C macro kroundup32 to D mixin? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | On Saturday, 8 April 2017 at 10:02:01 UTC, Mike Parker wrote:
>
> I would expect if you implement it as a function the compiler will inline it. You can always use the pragma(inline, true) [1] with -inline to verify.
>
> [1] https://dlang.org/spec/pragma.html#inline
This gives me no error, so it does inline it.
T kroundup32(T)(T x) {
pragma(inline, true);
--(x);
(x)|=(x)>>1;
(x)|=(x)>>2;
(x)|=(x)>>4;
(x)|=(x)>>8;
(x)|=(x)>>16;
return ++(x);
}
|
April 08, 2017 Re: Convert this C macro kroundup32 to D mixin? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | On Saturday, 8 April 2017 at 10:02:01 UTC, Mike Parker wrote:
>
> I would expect if you implement it as a function the compiler will inline it. You can always use the pragma(inline, true) [1] with -inline to verify.
>
> [1] https://dlang.org/spec/pragma.html#inline
Thanks for mentioning pragma. However, anyway to do it with mixin? It's so cool so I want to do more stuffs with it :)
|
April 08, 2017 Re: Convert this C macro kroundup32 to D mixin? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Mike Parker | On Saturday, 8 April 2017 at 10:09:47 UTC, Mike Parker wrote:
> T kroundup32(T)(T x) {
> pragma(inline, true);
> --(x);
> (x)|=(x)>>1;
> (x)|=(x)>>2;
> (x)|=(x)>>4;
> (x)|=(x)>>8;
> (x)|=(x)>>16;
> return ++(x);
> }
I also came up with this:
import std.stdio;
pragma( inline, true ):
static int kroundup32( int x){
--(x);
writeln("X: ",x);
(x)|=(x)>>1;
writeln("X: ",x);
(x)|=(x)>>2;
writeln("X: ",x);
(x)|=(x)>>4;
writeln("X: ",x);
(x)|=(x)>>8;
writeln("X: ",x);
(x)|=(x)>>16;
writeln("X: ",x);
++(x);
writeln("X: ",x);
return x;
}
int main(){
int num = 31;
num = kroundup32(num);
writeln("Num:", num);
return 0;
}
Is this way of using pragma the same as your way? I am still new to this so I want to understand more.
And is it a good idea to do manipulate 'num' directly so I can omit 'return' and avoid re-assigning statement? That's what C version does.
|
April 08, 2017 Re: Convert this C macro kroundup32 to D mixin? | ||||
---|---|---|---|---|
| ||||
Posted in reply to biocyberman | On Saturday, 8 April 2017 at 11:01:34 UTC, biocyberman wrote: > On Saturday, 8 April 2017 at 10:09:47 UTC, Mike Parker wrote: >> T kroundup32(T)(T x) { >> pragma(inline, true); >> --(x); >> (x)|=(x)>>1; >> (x)|=(x)>>2; >> (x)|=(x)>>4; >> (x)|=(x)>>8; >> (x)|=(x)>>16; >> return ++(x); >> } > > > I also came up with this: > > import std.stdio; > pragma( inline, true ): > static int kroundup32( int x){ > --(x); > writeln("X: ",x); > (x)|=(x)>>1; > writeln("X: ",x); > (x)|=(x)>>2; > writeln("X: ",x); > (x)|=(x)>>4; > writeln("X: ",x); > (x)|=(x)>>8; > writeln("X: ",x); > (x)|=(x)>>16; > writeln("X: ",x); > ++(x); > writeln("X: ",x); > > return x; > } > > int main(){ > int num = 31; > num = kroundup32(num); > writeln("Num:", num); > return 0; > } > > Is this way of using pragma the same as your way? I am still new to this so I want to understand more. The ':' means that it applies to everything that follows it, so while it doesn't matters in this example if you had pragma( inline, true ): int kroundup32( int x) { ... } auto someVeryLargeFunction( Args args) { // ... } and then you used someVeryLargeFunction in a bunch of places then that would cause a lot of binary bloat. > > And is it a good idea to do manipulate 'num' directly so I can omit 'return' and avoid re-assigning statement? That's what C version does. if you want the the function to affect the variable use a 'ref' as in void kroundup32(T)(ref T x) { pragma(inline, true); --(x); (x)|=(x)>>1; (x)|=(x)>>2; (x)|=(x)>>4; (x)|=(x)>>8; (x)|=(x)>>16; return ++(x); } int main(){ int num = 31; writeln("Before: ",num); // 31 kroundup32(num); writeln("After: ", num); //32 return 0; } is it a good idea? I would not think it is necessary. As an aside the C version has parentheses around the "x" because it is a macro and it is substituted as text not symbolically, they are not needed in D. |
April 08, 2017 Re: Convert this C macro kroundup32 to D mixin? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicholas Wilson | On Saturday, 8 April 2017 at 11:24:02 UTC, Nicholas Wilson wrote: > The ':' means that it applies to everything that follows it, so while it doesn't matters in this example if you had > pragma( inline, true ): > int kroundup32( int x) { ... } > > auto someVeryLargeFunction( Args args) > { > // ... > } > > and then you used someVeryLargeFunction in a bunch of places then that would cause a lot of binary bloat. That's big difference! Thank you for pointing this out for me. > if you want the the function to affect the variable use a 'ref' as in > > void kroundup32(T)(ref T x) { > pragma(inline, true); > --(x); > (x)|=(x)>>1; > (x)|=(x)>>2; > (x)|=(x)>>4; > (x)|=(x)>>8; > (x)|=(x)>>16; > return ++(x); > } > > int main(){ > int num = 31; > writeln("Before: ",num); // 31 > kroundup32(num); > writeln("After: ", num); //32 > return 0; > } > > is it a good idea? I would not think it is necessary. > > As an aside the C version has parentheses around the "x" because it is a macro and it is substituted as text not symbolically, they are not needed in D. This thing now is clear and settled while I try to navigate my mind around many new things. Really appreciate your help, Nicolas. |
April 08, 2017 Re: Convert this C macro kroundup32 to D mixin? | ||||
---|---|---|---|---|
| ||||
Posted in reply to biocyberman | On 04/08/2017 03:11 AM, biocyberman wrote: > On Saturday, 8 April 2017 at 10:02:01 UTC, Mike Parker wrote: >> >> I would expect if you implement it as a function the compiler will >> inline it. You can always use the pragma(inline, true) [1] with >> -inline to verify. >> >> [1] https://dlang.org/spec/pragma.html#inline > > Thanks for mentioning pragma. However, anyway to do it with mixin? It's > so cool so I want to do more stuffs with it :) You can mixin declarations with a template but I don't see how it can help here. A string mixin would work but it's really ugly at the use site: string roundUp(alias x)() if (is (typeof(x) == uint)) { import std.string : format; return format(q{ --%1$s; %1$s |= %1$s >> 1; %1$s |= %1$s >> 2; %1$s |= %1$s >> 4; %1$s |= %1$s >> 8; %1$s |= %1$s >> 16; ++%1$s; }, x.stringof); } void main() { uint i = 42; mixin (roundUp!i); // <-- Ugly assert(i == 64); } Compare that to the following natural syntax that a function provides: void roundUp(ref uint x) { // ... } void main() { uint i = 42; i.roundUp(); // <-- Natural } Ali |
April 09, 2017 Re: Convert this C macro kroundup32 to D mixin? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Saturday, 8 April 2017 at 21:34:30 UTC, Ali Çehreli wrote: > You can mixin declarations with a template but I don't see how it can help here. A string mixin would work but it's really ugly at the use site: > > string roundUp(alias x)() > if (is (typeof(x) == uint)) { > > import std.string : format; > return format(q{ > --%1$s; > %1$s |= %1$s >> 1; > %1$s |= %1$s >> 2; > %1$s |= %1$s >> 4; > %1$s |= %1$s >> 8; > %1$s |= %1$s >> 16; > ++%1$s; > }, x.stringof); > } > > void main() { > uint i = 42; > mixin (roundUp!i); // <-- Ugly > > assert(i == 64); > } > > Compare that to the following natural syntax that a function provides: > > void roundUp(ref uint x) { > // ... > } > > void main() { > uint i = 42; > i.roundUp(); // <-- Natural > } > > Ali You made the point, it looks really ugly :). However, sometimes if this ugliness offer better performance, I would - in a desperate mood - use it. That's only 'if'. I put two other variant to a test, and this ugly version does worst as well. You can check out here: https://gist.github.com/biocyberman/0ad27721780e66546cbb6a39c0770d99 Maybe it is because string formating cost. Moving the import statement out of the function does not speed things up. |
Copyright © 1999-2021 by the D Language Foundation