digitalmars.D.bugs - DMD 0.96: type not promoting..
- Regan Heath (63/63) Jul 26 2004 Hi,
- Regan Heath (31/92) Jul 26 2004 I just tried it D with int and short, eg.
- Cabal (6/13) Jul 26 2004 In these lines you are adding 1 to int.max in an integer context which t...
- Regan Heath (34/57) Jul 26 2004 I assumed that is what was happening. Changing this:
- Daniel Horn (10/42) Jul 26 2004 Python just changed their language to do automatic type promotion
- Regan Heath (10/53) Jul 26 2004 and you will do integer math with my suggestion as long as you assign th...
- Arcane Jill (27/41) Jul 27 2004 Are you sure about D's current behavior. The way I read it, it currently...
- Derek Parnell (68/119) Jul 27 2004 It is doing this, but this is not what is wanted by Regan. The expressio...
- Regan Heath (14/143) Jul 27 2004 Exactly! I didn't think I had to spell this out, obviously this
- Regan Heath (32/91) Jul 27 2004 I assumed it was the same as C/C++.
- Arcane Jill (12/15) Jul 26 2004 I suspect it's probably not a bug, but defined behaviour. From "Lexical"...
- Regan Heath (8/28) Jul 26 2004 I figured that might be the case. Thanks for the above, I didn't find it...
- Walter (4/4) Jul 27 2004 D cares along wholesale the C/C++ rules on integral promotions in arithm...
Hi, I just got bitten by a type promotion problem, I was wondering whether people here think this is a bug, or otherwise. import std.string; void output(long a) { printf("%.*s\n",toString(a)); } void main() { long a,b; //inline output(int.max+1); //using long a = int.max+1; output(a); //using constant value output(2147483647+1); //using long in 2 steps b = int.max; b += 1; output(b); } Ouput: -2147483648 -2147483648 -2147483648 2147483648 The last result was the desired result in my case. I believe all 4 tests should give that result. The C equivalent, using short as C does not have a long (that is bigger than an int) and assuming that the D property is an int itself, which it seems to be, would be: #include <limits.h> void foo(int a) { printf("%d\n",a); } void main() { short max = SHRT_MAX; int a,b; //inline output(max+1); //using int a = max+1; output(a); //using constant value output(32767+1); //using int in 2 steps b = max; b += 1; output(b); } Output: 32768 32768 32768 32768 So it appears C is promoting the short 'a' to an int then adding 1 to it _or_ perhaps this is all due to how int and short are physically represented? Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 26 2004
I just tried it D with int and short, eg. import std.string; void output(int a) { printf("%.*s\n",toString(a)); } void main() { int a,b; //inline output(short.max+1); //using var a = short.max+1; output(a); //using constant value output(32767+1); //2 steps b = short.max; b += 1; output(b); } Output: 32768 32768 32768 32768 So it appears the behaviour is different when using int/short to long/int. Regan On Mon, 26 Jul 2004 20:06:59 +1200, Regan Heath <regan netwin.co.nz> wrote:Hi, I just got bitten by a type promotion problem, I was wondering whether people here think this is a bug, or otherwise. import std.string; void output(long a) { printf("%.*s\n",toString(a)); } void main() { long a,b; //inline output(int.max+1); //using long a = int.max+1; output(a); //using constant value output(2147483647+1); //using long in 2 steps b = int.max; b += 1; output(b); } Ouput: -2147483648 -2147483648 -2147483648 2147483648 The last result was the desired result in my case. I believe all 4 tests should give that result. The C equivalent, using short as C does not have a long (that is bigger than an int) and assuming that the D property is an int itself, which it seems to be, would be: #include <limits.h> void foo(int a) { printf("%d\n",a); } void main() { short max = SHRT_MAX; int a,b; //inline output(max+1); //using int a = max+1; output(a); //using constant value output(32767+1); //using int in 2 steps b = max; b += 1; output(b); } Output: 32768 32768 32768 32768 So it appears C is promoting the short 'a' to an int then adding 1 to it _or_ perhaps this is all due to how int and short are physically represented? Regan-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 26 2004
I would regard your first example as correct and the second as a bug in D.//inline output(int.max+1); //using long a = int.max+1; output(a); //using constant value output(2147483647+1);In these lines you are adding 1 to int.max in an integer context which trips over into negative values. Only after this has happened is the int promoted to a long, and so the long contains a negative value too. Your second example looks like D is actually doing its short arithmetic with integer types. Which would be wrong imo.
Jul 26 2004
On Mon, 26 Jul 2004 09:56:15 +0100, Cabal <cabalN05P4M myrealbox.com> wrote:I would regard your first example as correct and the second as a bug in D.I assumed that is what was happening. Changing this://inline output(int.max+1); //using long a = int.max+1; output(a); //using constant value output(2147483647+1);In these lines you are adding 1 to int.max in an integer context which trips over into negative values. Only after this has happened is the int promoted to a long, and so the long contains a negative value too.to://using constant value output(2147483647+1);also gives me what I want "2147483648", instead of "-2147483648", I guess one has to remember that constants in D are integers, unless you state otherwise.//using constant value output(2147483647L+1);Your second example looks like D is actually doing its short arithmetic with integer types. Which would be wrong imo.This example behaves as C/C++ does. I assume because: - short.max is actually an 'int' not a 'short'. - the constant is assumed to be an int. If short.max was a 'short' then my first trials would have given negative values and the last 2 positive values. How bout this for a radical new idea, I realise it would cause behaviour changes from C to D for the same expression, why not promote all operands in an expression to the resulting type, forcing people to use a cast if they do not want that behaviour. It occurs to me that wanting this behaviour is more common than wanting the current behaviour. eg. float a; int b; a = b/100; if 'b' and '100' are promoted to float before the calculation you get a different answer, and it's the answer you actually wanted in most cases. Currently you have to write the above as: a = cast(float)b/cast(float)100; or perhaps a = cast(float)b/100.0; I would argue the more common intent should be the default behaviour. Can anyone think of a counter example that shows a commonly desired outcome that is the current default behaviour? How does Java handle this sort of thing? What about python or Ruby? Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 26 2004
Python just changed their language to do automatic type promotion I hate it! :-( if you divide 2 integers you wish to do integer math, not float math... (think arrays,random numbers, etc..) Also it's a lot slower to start using the greatest possible type your expression could produce. If you wish this behavior, write a class to do it (see: Arcane Jill's Big Integer) :-) or else just do math on longs, or reals all the time, rather than using smaller types initially.How bout this for a radical new idea, I realise it would cause behaviour changes from C to D for the same expression, why not promote all operands in an expression to the resulting type, forcing people to use a cast if they do not want that behaviour. It occurs to me that wanting this behaviour is more common than wanting the current behaviour. eg. float a; int b; a = b/100; if 'b' and '100' are promoted to float before the calculation you get a different answer, and it's the answer you actually wanted in most cases. Currently you have to write the above as: a = cast(float)b/cast(float)100; or perhaps a = cast(float)b/100.0; I would argue the more common intent should be the default behaviour. Can anyone think of a counter example that shows a commonly desired outcome that is the current default behaviour? How does Java handle this sort of thing? What about python or Ruby? Regan.
Jul 26 2004
On Mon, 26 Jul 2004 16:55:05 -0700, Daniel Horn <hellcatv hotmail.com> wrote:Python just changed their language to do automatic type promotion I hate it! :-( if you divide 2 integers you wish to do integer math, not float math... (think arrays,random numbers, etc..)and you will do integer math with my suggestion as long as you assign the result to an int and not a float... IIRC python does not have clearly defined types, so they cannot make this decision, yes?Also it's a lot slower to start using the greatest possible type your expression could produce.That is not the behaviour I want. What I want is the operands to be cast to the result type _before_ the expression is evaluated, rather than the current behaviour which is to cast the result after the expression.If you wish this behavior, write a class to do it (see: Arcane Jill's Big Integer) :-) or else just do math on longs, or reals all the time, rather than using smaller types initially.-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/How bout this for a radical new idea, I realise it would cause behaviour changes from C to D for the same expression, why not promote all operands in an expression to the resulting type, forcing people to use a cast if they do not want that behaviour. It occurs to me that wanting this behaviour is more common than wanting the current behaviour. eg. float a; int b; a = b/100; if 'b' and '100' are promoted to float before the calculation you get a different answer, and it's the answer you actually wanted in most cases. Currently you have to write the above as: a = cast(float)b/cast(float)100; or perhaps a = cast(float)b/100.0; I would argue the more common intent should be the default behaviour. Can anyone think of a counter example that shows a commonly desired outcome that is the current default behaviour? How does Java handle this sort of thing? What about python or Ruby? Regan.
Jul 26 2004
In article <opsbrqxd1l5a2sq9 digitalmars.com>, Regan Heath says...the current behaviour. eg. float a; int b; a = b/100; if 'b' and '100' are promoted to float before the calculation you get a different answer, and it's the answer you actually wanted in most cases. Currently you have to write the above as: a = cast(float)b/cast(float)100; or perhaps a = cast(float)b/100.0; I would argue the more common intent should be the default behaviour.Are you sure about D's current behavior. The way I read it, it currently does exactly what you want. From the manual: "The usual arithmetic conversions convert operands of binary operators to a common type. The operands must already be of arithmetic types. The following rules are applied in order: 1. Typedefs are converted to their underlying type. 2. If either operand is real, the other operand is converted to real. 3. Else if either operand is double, the other operand is converted to double. 4. Else if either operand is float, the other operand is converted to float. 5. Else the integer promotions are done on each operand, followed by: 1. If both are the same type, no more conversions are done. 2. If both are signed or both are unsigned, the smaller type is converted to the larger. 3. If the signed type is larger than the unsigned type, the unsigned type is converted to the signed type. 4. The signed type is converted to the unsigned type." Obviously, if it's not doing this, it's a bug, but it's always seemed to work for me.Can anyone think of a counter example that shows a commonly desired outcome that is the current default behaviour?I'm not convinced that /is/ the current default behavior. D works the same way as C and C++.How does Java handle this sort of thing? What about python or Ruby?I think Java /also/ works the same way as C, C++ and D (except that Java doesn't have unsigned types apart from char). Can't speak for those languages, but I can tell you that PHP is really weird. It expands numbers as required, like Python, and doesn't have unsigned types, so the constant 0xFFFFFFFF is a /double/. Actually I don't like this. Jill
Jul 27 2004
On Tue, 27 Jul 2004 07:46:07 +0000 (UTC), Arcane Jill wrote:In article <opsbrqxd1l5a2sq9 digitalmars.com>, Regan Heath says...It is doing this, but this is not what is wanted by Regan. The expression 'a = b/100' is probable assessed thus ... ** b is an int. 100 is an int. Rule 5 applies. They remain 'int' as they are the same size integer. Thus the result of the calculation is an int too. ** a is a float, result is an int. Rule 4 applies. The result is converted to a float. The answer (assignment) is a float. But, not the expected value. It gets truncated to an int prior to conversion to a float. Maybe a better way would be for the compiler to recognize that the coder is asking for an assignment to a float, so all left-hand expressions need to be at least a float, but possibly promoted to real during calculation then truncated to float on assignment. If the coder wishes to cause the resulting left hand expression to be truncated to an integer, she could use an explicit cast. float a; int b; a = cast(int)(b/100);the current behaviour. eg. float a; int b; a = b/100; if 'b' and '100' are promoted to float before the calculation you get a different answer, and it's the answer you actually wanted in most cases. Currently you have to write the above as: a = cast(float)b/cast(float)100; or perhaps a = cast(float)b/100.0; I would argue the more common intent should be the default behaviour.Are you sure about D's current behavior. The way I read it, it currently does exactly what you want. From the manual: "The usual arithmetic conversions convert operands of binary operators to a common type. The operands must already be of arithmetic types. The following rules are applied in order: 1. Typedefs are converted to their underlying type. 2. If either operand is real, the other operand is converted to real. 3. Else if either operand is double, the other operand is converted to double. 4. Else if either operand is float, the other operand is converted to float. 5. Else the integer promotions are done on each operand, followed by: 1. If both are the same type, no more conversions are done. 2. If both are signed or both are unsigned, the smaller type is converted to the larger. 3. If the signed type is larger than the unsigned type, the unsigned type is converted to the signed type. 4. The signed type is converted to the unsigned type." Obviously, if it's not doing this, it's a bug, but it's always seemed to work for me.Calculating pixel positions need to be truncated to integer values.Can anyone think of a counter example that shows a commonly desired outcome that is the current default behaviour?I'm not convinced that /is/ the current default behavior. D works the same way as C and C++.The Euphoria language does it the way Regan wants... c:\temp>type test.ex atom a integer b b = 3335 a = b / 100 printf(1, "%f\n", a) c:\temp>ex test 33.350000 c:\temp> And D definitely does not ... c:\temp>type test.d import std.stdio; void main() { float a; int b; b = 3335; a = b / 100; writef("%f\n", a); } c:\temp>dmd test C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi; c:\temp>test 33.000000 c:\temp> But if you make one tiny change, one gets ... c:\temp>type test.d import std.stdio; void main() { float a; int b; b = 3335; a = b / 100.0; // <-- Explicit float literal writef("%f\n", a); } c:\temp>dmd test C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi; c:\temp>test 33.349998 c:\temp> Well almost, the precision isn't so hot. To get better, change 'a' to double or real. -- Derek Melbourne, Australia 27/Jul/04 6:10:32 PMHow does Java handle this sort of thing? What about python or Ruby?I think Java /also/ works the same way as C, C++ and D (except that Java doesn't have unsigned types apart from char).
Jul 27 2004
On Tue, 27 Jul 2004 18:32:28 +1000, Derek Parnell <derek psych.ward> wrote:On Tue, 27 Jul 2004 07:46:07 +0000 (UTC), Arcane Jill wrote:Exactly! I didn't think I had to spell this out, obviously this mistake/bug/problem is not as comman as I thought, I have had it numerous times.In article <opsbrqxd1l5a2sq9 digitalmars.com>, Regan Heath says...It is doing this, but this is not what is wanted by Regan. The expression 'a = b/100' is probable assessed thus ... ** b is an int. 100 is an int. Rule 5 applies. They remain 'int' as they are the same size integer. Thus the result of the calculation is an int too. ** a is a float, result is an int. Rule 4 applies. The result is converted to a float. The answer (assignment) is a float. But, not the expected value. It gets truncated to an int prior to conversion to a float.the current behaviour. eg. float a; int b; a = b/100; if 'b' and '100' are promoted to float before the calculation you get a different answer, and it's the answer you actually wanted in most cases. Currently you have to write the above as: a = cast(float)b/cast(float)100; or perhaps a = cast(float)b/100.0; I would argue the more common intent should be the default behaviour.Are you sure about D's current behavior. The way I read it, it currently does exactly what you want. From the manual: "The usual arithmetic conversions convert operands of binary operators to a common type. The operands must already be of arithmetic types. The following rules are applied in order: 1. Typedefs are converted to their underlying type. 2. If either operand is real, the other operand is converted to real. 3. Else if either operand is double, the other operand is converted to double. 4. Else if either operand is float, the other operand is converted to float. 5. Else the integer promotions are done on each operand, followed by: 1. If both are the same type, no more conversions are done. 2. If both are signed or both are unsigned, the smaller type is converted to the larger. 3. If the signed type is larger than the unsigned type, the unsigned type is converted to the signed type. 4. The signed type is converted to the unsigned type." Obviously, if it's not doing this, it's a bug, but it's always seemed to work for me.Maybe a better way would be for the compiler to recognize that the coder is asking for an assignment to a float, so all left-hand expressions need to be at least a float, but possibly promoted to real during calculation then truncated to float on assignment.That is what I have been suggesting.If the coder wishes to cause the resulting left hand expression to be truncated to an integer, she could use an explicit cast. float a; int b; a = cast(int)(b/100);Yep.The key word in my request was "commonly", I do not believe the above to be common. So while it's a good example that it needs to be possible, it's not the commonly desired outcome, and in fact if you were doing the above you'd remember to ensure it happens, correct?Calculating pixel positions need to be truncated to integer values.Can anyone think of a counter example that shows a commonly desired outcome that is the current default behaviour?Good examples. Thanks. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/I'm not convinced that /is/ the current default behavior. D works the same way as C and C++.The Euphoria language does it the way Regan wants... c:\temp>type test.ex atom a integer b b = 3335 a = b / 100 printf(1, "%f\n", a) c:\temp>ex test 33.350000 c:\temp> And D definitely does not ... c:\temp>type test.d import std.stdio; void main() { float a; int b; b = 3335; a = b / 100; writef("%f\n", a); } c:\temp>dmd test C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi; c:\temp>test 33.000000 c:\temp> But if you make one tiny change, one gets ... c:\temp>type test.d import std.stdio; void main() { float a; int b; b = 3335; a = b / 100.0; // <-- Explicit float literal writef("%f\n", a); } c:\temp>dmd test C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi; c:\temp>test 33.349998 c:\temp> Well almost, the precision isn't so hot. To get better, change 'a' to double or real.How does Java handle this sort of thing? What about python or Ruby?I think Java /also/ works the same way as C, C++ and D (except that Java doesn't have unsigned types apart from char).
Jul 27 2004
On Tue, 27 Jul 2004 07:46:07 +0000 (UTC), Arcane Jill <Arcane_member pathlink.com> wrote:In article <opsbrqxd1l5a2sq9 digitalmars.com>, Regan Heath says...I assumed it was the same as C/C++.the current behaviour. eg. float a; int b; a = b/100; if 'b' and '100' are promoted to float before the calculation you get a different answer, and it's the answer you actually wanted in most cases. Currently you have to write the above as: a = cast(float)b/cast(float)100; or perhaps a = cast(float)b/100.0; I would argue the more common intent should be the default behaviour.Are you sure about D's current behavior.The way I read it, it currently does exactly what you want. From the manual: "The usual arithmetic conversions convert operands of binary operators to a common type. The operands must already be of arithmetic types. The following rules are applied in order: 1. Typedefs are converted to their underlying type. 2. If either operand is real, the other operand is converted to real. 3. Else if either operand is double, the other operand is converted to double. 4. Else if either operand is float, the other operand is converted to float. 5. Else the integer promotions are done on each operand, followed by: 1. If both are the same type, no more conversions are done. 2. If both are signed or both are unsigned, the smaller type is converted to the larger. 3. If the signed type is larger than the unsigned type, the unsigned type is converted to the signed type. 4. The signed type is converted to the unsigned type." Obviously, if it's not doing this, it's a bug, but it's always seemed to work for me.These rules do not help for: a = b/100 (if a is a float and b is an int) they do help for: a = b/100 (if b is a float) a = b/100.0 (as 100.0 is a float) maybe it's just me, I do not think "100.0" when I think "one hundred" I think of "100" so I'll write "100", and it will give the wrong result.The problem I have mentioned _is_ one I have in C.Can anyone think of a counter example that shows a commonly desired outcome that is the current default behaviour?I'm not convinced that /is/ the current default behavior. D works the same way as C and C++.I don't want types to be expanded, why does everyone think that is what I am after... "type expansion", to me, suggests making an 'int' into a 'long' because the value assigned to it is too big for an 'int', I don't want that at all. I simply want the type promotion it would do to the result to be done to the operands before the expression is evaluated. eg. float a; int b; a = b/100 causes: - b is promoted to float - 100 is promoted to float - expression evaluated - result assigned to a; Yes, this causes more promotions to be done. Yes, this changes the result of the expression, such that in C it would give a different result. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/How does Java handle this sort of thing? What about python or Ruby?I think Java /also/ works the same way as C, C++ and D (except that Java doesn't have unsigned types apart from char). Can't speak for those languages, but I can tell you that PHP is really weird. It expands numbers as required, like Python, and doesn't have unsigned types, so the constant 0xFFFFFFFF is a /double/. Actually I don't like this.
Jul 27 2004
In article <opsbqjhxmf5a2sq9 digitalmars.com>, Regan Heath says...Hi, I just got bitten by a type promotion problem, I was wondering whether people here think this is a bug, or otherwise.I suspect it's probably not a bug, but defined behaviour. From "Lexical": The type of the integer is resolved as follows: 1. If it is decimal it is the last representable of ulong, long, or int. 2. If it is not decimal, it is the last representable of ulong, long, uint, or int. 3. If it has the 'u' suffix, it is the last representable of ulong or uint. 4. If it has the 'l' suffix, it is the last representable of ulong or long. 5. If it has the 'u' and 'l' suffixes, it is ulong. So, I guess what you need to do is one of:
Jul 26 2004
On Mon, 26 Jul 2004 11:50:23 +0000 (UTC), Arcane Jill <Arcane_member pathlink.com> wrote:In article <opsbqjhxmf5a2sq9 digitalmars.com>, Regan Heath says...I figured that might be the case. Thanks for the above, I didn't find it in my searching.Hi, I just got bitten by a type promotion problem, I was wondering whether people here think this is a bug, or otherwise.I suspect it's probably not a bug, but defined behaviour. From "Lexical": The type of the integer is resolved as follows: 1. If it is decimal it is the last representable of ulong, long, or int. 2. If it is not decimal, it is the last representable of ulong, long, uint, or int. 3. If it has the 'u' suffix, it is the last representable of ulong or uint. 4. If it has the 'l' suffix, it is the last representable of ulong or long. 5. If it has the 'u' and 'l' suffixes, it is ulong.So, I guess what you need to do is one of:Uppercase L works too, and is easier to see. Regan. -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 26 2004
D cares along wholesale the C/C++ rules on integral promotions in arithmetic expressions, which is what you're seeing. Changing this would mean very subtle problems will crop up when converting C/C++ code into D, something I think is worse.
Jul 27 2004