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