On Saturday, 29 January 2022 at 01:06:45 UTC, Siarhei Siamashka wrote:
>Modern programing languages tend to have separate operators or intrinsincs for wrapped and non-wrapped (trap on overflow) arithmetic operations.
Well, in C++ "unsigned int" is defined to have modular arithmetics. The problem in C++ isn't that it is modular, but that people use "unsigned int" as a value range type, rather than when they want modular arithmetics. This is just a design influenced by classic machine language instructions rather than principled thoughts about math. This problem would probably have been much less if the type had been named "modular int" and not "unsigned int"! Syntax matters. :-D
In Ada I believe this is done explicitly, which clearly is much better.
As for practical problems: In C++ you can still enable signed overflow checks. In D you cannot even do that, because in D all integer operations are defined to be modular.
Interestingly, the main complaint about modular arithmetics in C++ is not about correctness however, but about poor optimizations. As a result, thoughtfully designed C++ libraries avoid using unsigned integers in interfaces.
Why are modular arithmetics performing worse than regular arithmetics? It is often much more difficult (in some cases impossible) to optimize computations that are mapped onto a circle than computations that are mapped onto a straight line!
This is something that D should fix!!
>I think that it's only a matter of time until processors start adding the missing instructions to make this fast.
No. It isn't crazy slow because of the check. It is crazy slow because it prevents optimizations in complex expressions.
In theory you could compute the overflow as a separate expression and do speculative computations, then switch to a slow path on overflow, but that would be more of a high level approach than a system level approach. In low level programming the programmer wants the code to map to machine language instructions without blowing up the code size in ways that are hard to predict. You want some transparency in how the code you write maps to the hardware instructions.
To make overflow checks really cast you need a much more advanced type system with constraints, so that the compiler can know what values an integer picked up from the heap can have.