TypeFunction example: ImplictConvTargets

Stefan Koch uplink.coder at googlemail.com
Tue Oct 6 11:14:05 UTC 2020


On Monday, 5 October 2020 at 11:44:34 UTC, Stefan Koch wrote:
> Hi,
>
> I've posted an incomplete version of a semantic translation of 
> ImplictConvTargets from a template into a type function.
>
> After a few rather trivial fixes let me show you what the code 
> looks like now.
>
> ---
> alias type = alias;
>
> // needed to avoid deeper changes ... in the future it may be 
> unnecessary.
> auto makeAliasArray(type[] types ...)
> {
>     return types;
> }
>
> enum basic_types = makeAliasArray(bool, ubyte, char, byte, 
> ushort, wchar, short, uint, dchar, int, ulong, long);
>
> type[] convTargets(type T)
> {
>     if (isBasicType(T))
>         return basicTypeConvTargets(T);
>     return null;
> }
>
> bool isBasicType(type T)
> {
>     foreach(t;basic_types)
>     {
>         if (is(T == t))
>             return true;
>     }
>     return false;
> }
>
> type[] basicTypeConvTargets(type T)
> {
>     type[] targets;
>     targets.length = basic_types.length;
>     assert(isBasicType(T), "You may not call this function when 
> you don't have a basic type ... (given: " ~ T.stringof ~ ")");
>     size_t n = 0;
>     foreach(t;basic_types)
>     {
>         if (is(T : t))
>         {
>             targets[n++] = t;
>         }
>     }
>     return targets[0 .. n];
> }
> // 42 lines including whitespace and comments
>
> pragma(msg, convTargets(long)); // outputs [(ulong), (long)]
> ---
>
> And again here is the part of the template that we just 
> re-implemented:
> ---
>     static if (is(T == bool))
>         alias ImplicitConversionTargets =
>             AliasSeq!(byte, ubyte, short, ushort, int, uint, 
> long, ulong, CentTypeList,
>                        float, double, real, char, wchar, dchar);
>     else static if (is(T == byte))
>         alias ImplicitConversionTargets =
>             AliasSeq!(short, ushort, int, uint, long, ulong, 
> CentTypeList,
>                        float, double, real, char, wchar, dchar);
>     else static if (is(T == ubyte))
>         alias ImplicitConversionTargets =
>             AliasSeq!(short, ushort, int, uint, long, ulong, 
> CentTypeList,
>                        float, double, real, char, wchar, dchar);
>     else static if (is(T == short))
>         alias ImplicitConversionTargets =
>             AliasSeq!(int, uint, long, ulong, CentTypeList, 
> float, double, real);
>     else static if (is(T == ushort))
>         alias ImplicitConversionTargets =
>             AliasSeq!(int, uint, long, ulong, CentTypeList, 
> float, double, real);
>     else static if (is(T == int))
>         alias ImplicitConversionTargets =
>             AliasSeq!(long, ulong, CentTypeList, float, double, 
> real);
>     else static if (is(T == uint))
>         alias ImplicitConversionTargets =
>             AliasSeq!(long, ulong, CentTypeList, float, double, 
> real);
>     else static if (is(T == long))
>         alias ImplicitConversionTargets = AliasSeq!(float, 
> double, real);
>     else static if (is(T == ulong))
>         alias ImplicitConversionTargets = AliasSeq!(float, 
> double, real);
>     // part omitted because we don't have ucent and cent in our 
> list
>     else static if (is(T == char))
>         alias ImplicitConversionTargets =
>             AliasSeq!(wchar, dchar, byte, ubyte, short, ushort,
>                        int, uint, long, ulong, CentTypeList, 
> float, double, real);
>     else static if (is(T == wchar))
>         alias ImplicitConversionTargets =
>             AliasSeq!(dchar, short, ushort, int, uint, long, 
> ulong, CentTypeList,
>                        float, double, real);
>     else static if (is(T == dchar))
>         alias ImplicitConversionTargets =
>             AliasSeq!(int, uint, long, ulong, CentTypeList, 
> float, double, real);
>     // 41 lines including white-space and comments (only that 
> there is no white-space or comments)
> ---
>
> I leave it up to you to decide which version is more 
> understandable and extendable (should we ever get another basic 
> type :))
>
> As noted previously please do discuss!
> Maybe you like the template version more?
> Let me know.

And here is the performance comparison:

uplimk at uplimk-virtual-machine:~/d/dmd$ hyperfine -w 10 
"generated/linux/release/64/dmd xx_tf.d -sktf -c" 
"generated/linux/release/64/dmd xx.d -c " 
"generated/linux/release/64/dmd xx_adam.d -c"
Benchmark #1: generated/linux/release/64/dmd xx_tf.d -sktf -c
   Time (mean ± σ):       9.1 ms ±   0.4 ms    [User: 5.8 ms, 
System: 3.2 ms]
   Range (min … max):     8.5 ms …  10.7 ms    288 runs

Benchmark #2: generated/linux/release/64/dmd xx.d -c
   Time (mean ± σ):      17.3 ms ±   0.6 ms    [User: 11.3 ms, 
System: 5.9 ms]
   Range (min … max):    16.5 ms …  19.5 ms    166 runs

Benchmark #3: generated/linux/release/64/dmd xx_adam.d -c
   Time (mean ± σ):      20.4 ms ±   0.7 ms    [User: 15.2 ms, 
System: 5.0 ms]
   Range (min … max):    19.5 ms …  22.7 ms    144 runs

Summary
   'generated/linux/release/64/dmd xx_tf.d -sktf -c' ran
     1.91 ± 0.11 times faster than 'generated/linux/release/64/dmd 
xx.d -c '
     2.24 ± 0.13 times faster than 'generated/linux/release/64/dmd 
xx_adam.d -c'


The source code can be found here:

https://gist.github.com/UplinkCoder/d29dd143b352d28390426a3ffedf9521

So can the benchmark results.
Note: not importing std.meta gives the template version (xx.d) a 
speed boost of 3 milliseconds.


More information about the Digitalmars-d mailing list