January 23, 2014 symmetric signed types | ||||
---|---|---|---|---|
| ||||
There is one mistake in C that D proliverates: The T.min value of signed types. e.g. byte a = -128; auto b = -a; What type should b get? (of course "byte" but the value doesn't fit!) Also getting the absolute value of some signed variable need to return a different type or doesn't work correct for all input. E.g. "ubyte abs(byte)" - this functions which can't even use a template, or has anybody a good idea ho to express "unsigned T abs(T)(T x)"? So I thought I could design a new type "sbyte" with symmetric range (-127..127) and an additional value NaN (yes, the old 0x80). (and of course larger, similar types - by the way: why wasn't "short" instead called "word"? Then my new type would be "sword" :-) It worked all well until I found that the new operators !<> !<= etc can't be overloaded (they are only available for floating types)! Why is this so? D made all the floatingpoint stuff so much better than C, but the integral types still suffer the same old flaws. |
January 23, 2014 Re: symmetric signed types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dominikus Dittes Scherkl | Dominikus Dittes Scherkl: > E.g. "ubyte abs(byte)" - this functions which can't even use a template, or has anybody a good idea ho to express > "unsigned T abs(T)(T x)"? I think this is not hard to do in D. > by the way: why wasn't "short" instead called "word"? On most modern CPUs a word is longer than a short. > It worked all well until I found that the new operators !<> !<= etc can't be overloaded (they are only available for floating types)! Why is this so? > D made all the floating point stuff so much better than C, but the integral types still suffer the same old flaws. Those FP operators are about to be deprecated. Apparently they add too much complexity for what they offer. using std.math.isNan should suffice. Bye, bearophile |
January 23, 2014 Re: symmetric signed types | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On Thursday, 23 January 2014 at 14:40:58 UTC, bearophile wrote: > Dominikus Dittes Scherkl: > >> E.g. "ubyte abs(byte)" - this functions which can't even use a template, or has anybody a good idea ho to express >> "unsigned T abs(T)(T x)"? > > I think this is not hard to do in D. Not hard. But very ugly. How would you express "the corresponding type of same size but unsigned?" But anyway, this is not what I wanted to do. >> by the way: why wasn't "short" instead called "word"? > > On most modern CPUs a word is longer than a short. I know. In C "int" was meant to be the machine word. But as 32bit machines became common everybody assumes int to be 32bit (which made lots of code defective) and still used "word" to refer to 16bit types. Its only I'd love to have a "sword" type in D :-D > >> It worked all well until I found that the new operators !<> !<= etc can't be overloaded (they are only available for floating types)! Why is this so? >> D made all the floating point stuff so much better than C, but the integral types still suffer the same old flaws. > > Those FP operators are about to be deprecated. Apparently they add too much complexity for what they offer. using std.math.isNan should suffice. Ok. Good to know. "isNan" is easy to implement for my new type. But for FP - aren't there more values which the special operators take care of? Infinity, negative zero, values near zero etc? Hmm - ok, std.math contains them all. But apperently the abs() function implemented there makes exactly the above mentioned error: abs(-128) = -128 because it returns the same type as the input has. I hate standard functions that produce bogous results. This is why I think we would be better off with symmetric signed types. Would also provide a perfect init value just like FP: NaN. Ok, it costs some performance, but for that I would always prefer unsigned types where you can do all the bit-fiddling shift and overflow-with-carry-bit (oh, wait: this is also not available in D. Why?!? Pretty much every processor has it and its available in about every assembler I've ever seen. Why not in D?) From signed types I expect reasonable performance but save operations (e.g. everything that produces over or underflow should deliver NaN and not arbitrary garbage) |
January 23, 2014 Re: symmetric signed types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dominikus Dittes Scherkl | On Thursday, 23 January 2014 at 12:09:24 UTC, Dominikus Dittes Scherkl wrote:
> Also getting the absolute value of some signed variable
> need to return a different type or doesn't work correct for all input.
> E.g. "ubyte abs(byte)" - this functions which can't even use a template,
> or has anybody a good idea ho to express "unsigned T abs(T)(T x)"?
import std.traits : Unsigned;
Unsigned!T abs(T)(T x) { /+ magic... +/ }
|
January 23, 2014 Re: symmetric signed types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stanislav Blinov | On Thursday, 23 January 2014 at 16:52:14 UTC, Stanislav Blinov wrote:
> On Thursday, 23 January 2014 at 12:09:24 UTC, Dominikus Dittes Scherkl wrote:
>
>> Also getting the absolute value of some signed variable
>> need to return a different type or doesn't work correct for all input.
>> E.g. "ubyte abs(byte)" - this functions which can't even use a template,
>> or has anybody a good idea ho to express "unsigned T abs(T)(T x)"?
>
> import std.traits : Unsigned;
>
> Unsigned!T abs(T)(T x) { /+ magic... +/ }
Cool. So why it that not used in std.math.abs?
|
January 23, 2014 Re: symmetric signed types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dominikus Dittes Scherkl | On Thursday, 23 January 2014 at 16:54:29 UTC, Dominikus Dittes Scherkl wrote: > Cool. So why it that not used in std.math.abs? http://d.puremagic.com/issues/show_bug.cgi?id=8666 Andrei's comment sums it up pretty much. AFAIK there may also be some portability considertaions when performing casts. |
January 23, 2014 Re: symmetric signed types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dominikus Dittes Scherkl | On 1/23/14 4:09 AM, Dominikus Dittes Scherkl wrote: > There is one mistake in C that D proliverates: > > The T.min value of signed types. > > e.g. > > byte a = -128; > auto b = -a; > > What type should b get? (of course "byte" but the value doesn't fit!) The type will be int. > Also getting the absolute value of some signed variable > need to return a different type or doesn't work correct for all input. > E.g. "ubyte abs(byte)" - this functions which can't even use a template, > or has anybody a good idea ho to express "unsigned T abs(T)(T x)"? http://dlang.org/phobos/std_conv.html#.unsigned > So I thought I could design a new type "sbyte" with symmetric range > (-127..127) and an additional value NaN (yes, the old 0x80). > (and of course larger, similar types - by the way: why wasn't "short" > instead called "word"? Then my new type would be "sword" :-) > > It worked all well until I found that the new operators !<> !<= etc > can't be overloaded (they are only available for floating types)! > Why is this so? We're deprecating the new operators :o). > D made all the floatingpoint stuff so much better than C, but the > integral types still suffer the same old flaws. There are quite a few improvements for integrals, too, most importantly of the kind that don't exact a speed penalty. Andrei |
January 23, 2014 Re: symmetric signed types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrei Alexandrescu | On 1/23/2014 12:35 PM, Andrei Alexandrescu wrote:
> On 1/23/14 4:09 AM, Dominikus Dittes Scherkl wrote:
>> What type should b get? (of course "byte" but the value doesn't fit!)
>
> The type will be int.
As an aside, the C integral arithmetic rules are often criticized. However, nobody has found another set of rules that didn't come with (sometimes severe) shortcomings of their own.
The huge advantage of the C rules is they are very widely known, used, and understood.
|
January 24, 2014 Re: symmetric signed types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | Walter Bright:
> The huge advantage of the C rules is they are very widely known, used, and understood.
And following them allows me to translate intricate C code to D with less headaches.
Still, Go has adopted a different strategy...
Bye,
bearophile
|
January 24, 2014 Re: symmetric signed types | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 1/23/2014 4:50 PM, bearophile wrote: > Walter Bright: > >> The huge advantage of the C rules is they are very widely known, used, and >> understood. > > And following them allows me to translate intricate C code to D with less > headaches. > > Still, Go has adopted a different strategy... I know. 1. Go determines the type of (e1 op e2) as the type of the first operand. http://golang.org/ref/spec#Arithmetic_operators I consider this not only surprising (as we expect + to be commutative) but can lead to unexpected truncation, as in (byte = byte + int32). It'll also lead to unexpected signed/unsigned bugs when converting C code. 2. Go also requires casts in order to assign one integral type to another: http://golang.org/ref/spec#Assignability I suspect that leads to a lot of casts, and such makes for hard-to-find bugs when code is refactored. If Go ever gets generics, this effect will get worse. The Go rules are definitely simpler than the C rules, but I don't see otherwise an improvement in reducing unintended behavior. D, on the other hand, uses C rules with implicit casting as long as value range propagation says truncation will not result. The rules are more complex, but work out surprisingly naturally and I believe are a real advance in reducing unintended behavior. Note that even Dominikus' "mistake" is not one that resulted in unexpected truncation. |
Copyright © 1999-2021 by the D Language Foundation