Re: Implicit integer casting
On Sun, 18 Mar 2012 15:53:56 -0400, Andrej Mitrovic andrej.mitrov...@gmail.com wrote: On 3/18/12, Manu turkey...@gmail.com wrote: I'm finding that in this code I'm writing, casts are taking up more space on many lines than the actual term being assigned. Another classic which fails to compile is: import std.random; ubyte c = uniform(0, 256); In the call uniform returns a number anywhere from 0 to and including 255, which can fit perfectly in a ubyte. But I have to use a cast (which is error-prone if I change the right interval), or use a to!ubyte call (which is verbose). Granted for simple-purpose random number generation a cast might be safe.. What if you don't have std.random's source, all you (the compiler) have is the function signature? BTW, you can use this instead of a cast: ubyte c = uniform(0, 256) 0xff; -Steve
Re: Implicit integer casting
On Sun, 18 Mar 2012 22:46:56 -0400, James Miller ja...@aatch.net wrote: Another thing I have noticed, is that that compared to a cast, to!type is incredibly slow. Most of the time it doesn't matter, but I was doing some work with noise generation, and found that casting the floats to integers was an order of magnitude faster than using to!int. There's a check involved, and possibly inlining doesn't make it for whatever reason. Andrei Oh, I wasn't complaining, more just making an observation that the safe to!type is slower than an unsafe cast. Probably obvious, but worth mentioning nonetheless. Given the utility of D's templates, the achievable goal should be to make it equivalent. It's worth pointing out, and should be filed as a bug. I'd bet that it was lack of inlining, possibly due to usage of enforce (haven't looked at the code). -Steve
Re: Implicit integer casting
On 3/19/12, Steven Schveighoffer schvei...@yahoo.com wrote: What if you don't have std.random's source, all you (the compiler) have is the function signature? I know there are what ifs, but in this case it's a template.
Implicit integer casting
So D is really finicky with integer casts. Basically everything that might produce a loss of data warning in C is an outright compile error. This results in a lot of explicit casting. Now I don't take issue with this, actually I think it's awesome, but I think there's one very important usability feature missing from the compiler with such strict casting rules... Does the compiler currently track the range of a value, if it is known? And if it is known, can the compiler stop complaining about down casts and perform the cast silently when it knows the range of values is safe. int x = 123456; x = 0xFF; // x is now in range 0..255; now fits in a ubyte ubyte y = x; // assign silently, cast can safely be implicit I have about 200 lines of code that would be so much more readable if this were supported. I'm finding that in this code I'm writing, casts are taking up more space on many lines than the actual term being assigned. They are really getting in the way and obscuring the readability. Not only masks, comparisons are also often used of limit the range of values. Add D's contracts, there is good chance the compiler will have fairly rich information about the range of integers, and it should consider that while performing casts.
Re: Implicit integer casting
On Mar 18, 2012 3:09 PM, Manu turkey...@gmail.com wrote int x = 123456; x = 0xFF; // x is now in range 0..255; now fits in a ubyte ubyte y = x; // assign silently, cast can safely be implicit This is related to Go's infinitely sized constants. If an expression produces a value out of range then brings it back in range in a constant it still works. int i = 1 100 98; assert( i == 4); Not exactly related but similar idea.
Re: Implicit integer casting
On Sunday, 18 March 2012 at 19:08:54 UTC, Manu wrote: So D is really finicky with integer casts. Basically everything that might produce a loss of data warning in C is an outright compile error. This results in a lot of explicit casting. Now I don't take issue with this, actually I think it's awesome, but I think there's one very important usability feature missing from the compiler with such strict casting rules... Does the compiler currently track the range of a value, if it is known? And if it is known, can the compiler stop complaining about down casts and perform the cast silently when it knows the range of values is safe. int x = 123456; x = 0xFF; // x is now in range 0..255; now fits in a ubyte ubyte y = x; // assign silently, cast can safely be implicit I have about 200 lines of code that would be so much more readable if this were supported. I'm finding that in this code I'm writing, casts are taking up more space on many lines than the actual term being assigned. They are really getting in the way and obscuring the readability. Not only masks, comparisons are also often used of limit the range of values. Add D's contracts, there is good chance the compiler will have fairly rich information about the range of integers, and it should consider that while performing casts. Walter even wrote an article about it: http://drdobbs.com/blogs/tools/229300211
Re: Implicit integer casting
On 18 March 2012 21:15, Tove t...@fransson.se wrote: On Sunday, 18 March 2012 at 19:08:54 UTC, Manu wrote: So D is really finicky with integer casts. Basically everything that might produce a loss of data warning in C is an outright compile error. This results in a lot of explicit casting. Now I don't take issue with this, actually I think it's awesome, but I think there's one very important usability feature missing from the compiler with such strict casting rules... Does the compiler currently track the range of a value, if it is known? And if it is known, can the compiler stop complaining about down casts and perform the cast silently when it knows the range of values is safe. int x = 123456; x = 0xFF; // x is now in range 0..255; now fits in a ubyte ubyte y = x; // assign silently, cast can safely be implicit I have about 200 lines of code that would be so much more readable if this were supported. I'm finding that in this code I'm writing, casts are taking up more space on many lines than the actual term being assigned. They are really getting in the way and obscuring the readability. Not only masks, comparisons are also often used of limit the range of values. Add D's contracts, there is good chance the compiler will have fairly rich information about the range of integers, and it should consider that while performing casts. Walter even wrote an article about it: http://drdobbs.com/blogs/**tools/229300211http://drdobbs.com/blogs/tools/229300211 Interesting. This article claims: Can we do better? Yes, with Value Range Propagation, a historically obscure compiler optimization that became a handy feature in the D programming language. But it doesn't seem to work. Am I just doing something wrong?
Re: Implicit integer casting
On 3/18/12, Manu turkey...@gmail.com wrote: I'm finding that in this code I'm writing, casts are taking up more space on many lines than the actual term being assigned. Another classic which fails to compile is: import std.random; ubyte c = uniform(0, 256); In the call uniform returns a number anywhere from 0 to and including 255, which can fit perfectly in a ubyte. But I have to use a cast (which is error-prone if I change the right interval), or use a to!ubyte call (which is verbose). Granted for simple-purpose random number generation a cast might be safe..
Re: Implicit integer casting
On Sun, 18 Mar 2012 20:30:15 +0100, Manu turkey...@gmail.com wrote: On 18 March 2012 21:15, Tove t...@fransson.se wrote: On Sunday, 18 March 2012 at 19:08:54 UTC, Manu wrote: So D is really finicky with integer casts. Basically everything that might produce a loss of data warning in C is an outright compile error. This results in a lot of explicit casting. Now I don't take issue with this, actually I think it's awesome, but I think there's one very important usability feature missing from the compiler with such strict casting rules... Does the compiler currently track the range of a value, if it is known? And if it is known, can the compiler stop complaining about down casts and perform the cast silently when it knows the range of values is safe. int x = 123456; x = 0xFF; // x is now in range 0..255; now fits in a ubyte ubyte y = x; // assign silently, cast can safely be implicit I have about 200 lines of code that would be so much more readable if this were supported. I'm finding that in this code I'm writing, casts are taking up more space on many lines than the actual term being assigned. They are really getting in the way and obscuring the readability. Not only masks, comparisons are also often used of limit the range of values. Add D's contracts, there is good chance the compiler will have fairly rich information about the range of integers, and it should consider that while performing casts. Walter even wrote an article about it: http://drdobbs.com/blogs/**tools/229300211http://drdobbs.com/blogs/tools/229300211 Interesting. This article claims: Can we do better? Yes, with Value Range Propagation, a historically obscure compiler optimization that became a handy feature in the D programming language. But it doesn't seem to work. Am I just doing something wrong? It only works within one expression. This works: int n = foo(); byte b = n 0xFF; This does not: int n = foo() 0xFF; byte b = n;
Re: Implicit integer casting
On 19 March 2012 08:53, Andrej Mitrovic andrej.mitrov...@gmail.com wrote: Another classic which fails to compile is: import std.random; ubyte c = uniform(0, 256); In the call uniform returns a number anywhere from 0 to and including 255, which can fit perfectly in a ubyte. But I have to use a cast (which is error-prone if I change the right interval), or use a to!ubyte call (which is verbose). Granted for simple-purpose random number generation a cast might be safe.. Another thing I have noticed, is that that compared to a cast, to!type is incredibly slow. Most of the time it doesn't matter, but I was doing some work with noise generation, and found that casting the floats to integers was an order of magnitude faster than using to!int. Now I understand that this is about auto-casting, but I thought I'd add the knowledge that to!type is slow, since it does runtime checks on things like range, though I know that it cannot be outside certain ranges. Not that to!type is actually slow in the general case, but the difference is significant when doing on the order of 10^6 casts. -- James Miller
Re: Implicit integer casting
On 3/18/12 4:12 PM, James Miller wrote: On 19 March 2012 08:53, Andrej Mitrovicandrej.mitrov...@gmail.com wrote: Another classic which fails to compile is: import std.random; ubyte c = uniform(0, 256); In the call uniform returns a number anywhere from 0 to and including 255, which can fit perfectly in a ubyte. But I have to use a cast (which is error-prone if I change the right interval), or use a to!ubyte call (which is verbose). Granted for simple-purpose random number generation a cast might be safe.. Another thing I have noticed, is that that compared to a cast, to!type is incredibly slow. Most of the time it doesn't matter, but I was doing some work with noise generation, and found that casting the floats to integers was an order of magnitude faster than using to!int. There's a check involved, and possibly inlining doesn't make it for whatever reason. Andrei
Re: Implicit integer casting
Andrej Mitrovic: Another classic which fails to compile is: import std.random; ubyte c = uniform(0, 256); It's legit to ask a compiler to help in this case. But currently the D type system can't help you here. The D syntax and type system tell apart sharply run-time values from compile-time ones. And the type system doesn't work on run-time values. This is another very simple case that currently the D compilers and D language don't signal as error at compile-time (a decent C lint is able to find a similar bug at compile time, if you use malloc/calloc to allocate the buffer a): void main() { int[] a = new int[5]; a[10] = 1; } So to do that in D you currently need to create a different uniform function that accepts compile-time values. If correctly implemented this doesn't need a cast to compile: ubyte c = uniformCT!(0, 256)(); There are some ways to improve this situation. One way is to introduce ranged numerical values (like the Ada ones) in the D language. This is why implementing them in library code isn't good enough. With them you are able to tell the type system that a value is in an arbitrarily compile-time-defined range, and later the type system is able to use this information for all kind of things. Another harder way to improve the situation is to offer the D programmer some way to tell if a regular argument of a regular function is known at compile-time (like it being a literal). If you use this feature inside a regular function, this function essentially becomes a template :-) In GCC-C there is something related, named __builtin_constant_p(exp): http://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html (If you improve that idea you obtain a handmade poor's man version of partial compilation, that is useful in a system language.) I think Walter tried a bit to do a simpler version of this, with this syntax: void foo(int x, static int y) {} Here x is a run-time value and y most be known at compile-time, so it's similar to (but this conversion doesn't work if y is an array, I never understood why D templates refuse arrays are compile-time arguments yet they accept all kind of strings, despite strings are a subset of dynamic arrays. And alias argument are not the same thing): void foo(int y)(int x) {} One difference here is that this template syntax is not transparent at the calling point, you must use the template instantiation syntax: foo!(5)(n) Bye, bearophile
Re: Implicit integer casting
Another thing I have noticed, is that that compared to a cast, to!type is incredibly slow. Most of the time it doesn't matter, but I was doing some work with noise generation, and found that casting the floats to integers was an order of magnitude faster than using to!int. There's a check involved, and possibly inlining doesn't make it for whatever reason. Andrei Oh, I wasn't complaining, more just making an observation that the safe to!type is slower than an unsafe cast. Probably obvious, but worth mentioning nonetheless. -- James Miller