Re: Implicit integer casting

2012-03-19 Thread Steven Schveighoffer
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

2012-03-19 Thread Steven Schveighoffer

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

2012-03-19 Thread Andrej Mitrovic
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

2012-03-18 Thread Manu
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

2012-03-18 Thread Kevin Cox
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

2012-03-18 Thread Tove

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

2012-03-18 Thread Manu
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

2012-03-18 Thread Andrej Mitrovic
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

2012-03-18 Thread Simen Kjærås

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

2012-03-18 Thread James Miller
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

2012-03-18 Thread Andrei Alexandrescu

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

2012-03-18 Thread bearophile

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

2012-03-18 Thread James Miller
 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