[OT] The Usual Arithmetic Confusions
Siarhei Siamashka
siarhei.siamashka at gmail.com
Fri Feb 4 04:32:23 UTC 2022
On Thursday, 3 February 2022 at 05:50:24 UTC, Walter Bright wrote:
> On 2/2/2022 6:25 PM, Siarhei Siamashka wrote:
>> On Thursday, 3 February 2022 at 01:05:15 UTC, Walter Bright
>> wrote:
>>> I find it works well. For example,
>>>
>>> int i;
>>> byte b = i & 0xFF;
>>>
>>> passes without complaint with VRP.
>>
>> No, it's doesn't pass: `Error: cannot implicitly convert
>> expression i & 255 of type int to byte`.
>
> My mistake. b should have been declared as ubyte.
Regarding your original example with the `byte` type. Maybe the
use of the following code can be encouraged as a good idiomatic
overflow-safe way to do it in D language?
int i;
byte b = i.to!byte;
i = -129;
b = i.to!byte; // std.conv.ConvOverflowException
This is 2 characters shorter and IMHO nicer looking than `byte b
= cast(byte)i;`. An overflow check is done at runtime to catch
bugs, but good optimizing compilers are actually smart enough to
eliminate it when the range of possible values of `i` is known at
compile time. For example:
void foobar(byte[] a)
{
foreach (i ; 0 .. a.length)
a[i] = (i % 37).to!byte;
}
Gets compiled into:
$ gdc-12.0.1 -O3 -fno-weak-templates -c test.d && objdump -d
test.o
0000000000000000 <_D4test6foobarFAgZv>:
0: 48 85 ff test %rdi,%rdi
3: 74 37 je 3c
<_D4test6foobarFAgZv+0x3c>
5: 49 b8 8b 7c d6 0d a6 movabs $0xdd67c8a60dd67c8b,%r8
c: c8 67 dd
f: 31 c9 xor %ecx,%ecx
11: 0f 1f 80 00 00 00 00 nopl 0x0(%rax)
18: 48 89 c8 mov %rcx,%rax
1b: 49 f7 e0 mul %r8
1e: 48 c1 ea 05 shr $0x5,%rdx
22: 48 8d 04 d2 lea (%rdx,%rdx,8),%rax
26: 48 8d 14 82 lea (%rdx,%rax,4),%rdx
2a: 48 89 c8 mov %rcx,%rax
2d: 48 29 d0 sub %rdx,%rax
30: 88 04 0e mov %al,(%rsi,%rcx,1)
33: 48 83 c1 01 add $0x1,%rcx
37: 48 39 cf cmp %rcx,%rdi
3a: 75 dc jne 18
<_D4test6foobarFAgZv+0x18>
3c: c3 retq
Slow division is replaced by multiplication and shifts,
conditional branches are only done to compare `i` with the array
length. The `.to!byte` part doesn't have any overhead at all and
bytes are just directly written to the destination array via `mov
%al,(%rsi,%rcx,1)` instruction.
More information about the Digitalmars-d
mailing list