digitalmars.D - Is there any reason why arithmetic operation on shorts and bytes
- d coder <dlang.coder gmail.com> Dec 11 2012
- "monarch_dodra" <monarchdodra gmail.com> Dec 11 2012
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Dec 11 2012
- Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> Dec 11 2012
- Walter Bright <newshound2 digitalmars.com> Dec 11 2012
- Walter Bright <newshound2 digitalmars.com> Dec 11 2012
- d coder <dlang.coder gmail.com> Dec 11 2012
- d coder <dlang.coder gmail.com> Dec 11 2012
- "Peter Alexander" <peter.alexander.au gmail.com> Dec 11 2012
- d coder <dlang.coder gmail.com> Dec 11 2012
- "bearophile" <bearophileHUGS lycos.com> Dec 11 2012
- "Rene Zwanenburg" <renezwanenburg gmail.com> Dec 11 2012
- d coder <dlang.coder gmail.com> Dec 11 2012
- "bearophile" <bearophileHUGS lycos.com> Dec 11 2012
- Nick Sabalausky <SeeWebsiteToContactMe semitwist.com> Dec 11 2012
- "foobar" <foo bar.com> Dec 11 2012
- "js.mdnq" <js_adddot+mdng gmail.com> Dec 11 2012
- d coder <dlang.coder gmail.com> Dec 11 2012
- "Denis Koroskin" <2korden gmail.com> Dec 11 2012
- d coder <dlang.coder gmail.com> Dec 11 2012
- "Simen Kjaeraas" <simen.kjaras gmail.com> Dec 12 2012
- Jonathan M Davis <jmdavisProg gmx.com> Dec 12 2012
- "Simen Kjaeraas" <simen.kjaras gmail.com> Dec 12 2012
- "js.mdnq" <js_adddot+mdng gmail.com> Dec 12 2012
- "Jonathan M Davis" <jmdavisProg gmx.com> Dec 12 2012
- Walter Bright <newshound2 digitalmars.com> Dec 12 2012
- Walter Bright <newshound2 digitalmars.com> Dec 13 2012
- Walter Bright <newshound2 digitalmars.com> Dec 14 2012
- Walter Bright <newshound2 digitalmars.com> Dec 14 2012
- Walter Bright <newshound2 digitalmars.com> Dec 14 2012
- "Jonathan M Davis" <jmdavisProg gmx.com> Dec 12 2012
- "Simen Kjaeraas" <simen.kjaras gmail.com> Dec 13 2012
- kenji hara <k.hara.pg gmail.com> Dec 13 2012
- "Simen Kjaeraas" <simen.kjaras gmail.com> Dec 13 2012
- "H. S. Teoh" <hsteoh quickfur.ath.cx> Dec 13 2012
- "H. S. Teoh" <hsteoh quickfur.ath.cx> Dec 14 2012
- "Adam D. Ruppe" <destructionator gmail.com> Dec 14 2012
- "Era Scarecrow" <rtcvb32 yahoo.com> Dec 16 2012
--047d7b2ee28369fc0f04d092c180
Content-Type: text/plain; charset=ISO-8859-1
Greetings
The following code prints FFFF0000. Similar thing happens when a and b are
bytes.
Is this intended?
Regards
- Puneet
void main()
{
import std.stdio;
ushort a = 0x55AA;
ushort b = 0xAA55;
writefln("%X", ~(a | b));
}
--047d7b2ee28369fc0f04d092c180
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
<div>Greetings</div><div><br></div><div>The following code prints FFFF0000.=
Similar thing happens when a and b are bytes.</div><div>Is this intended?<=
/div><div><br></div><div>Regards</div><div>- Puneet</div><div><br></div>
<div><div>void main()</div><div>{</div><div>=A0 import std.stdio;</div><div=
=A0 ushort a =3D 0x55AA;</div><div>=A0 ushort b =3D 0xAA55;</div><div>=A0 =
--047d7b2ee28369fc0f04d092c180--
Dec 11 2012
On Tuesday, 11 December 2012 at 12:24:14 UTC, d coder wrote:Greetings The following code prints FFFF0000. Similar thing happens when a and b are bytes. Is this intended? Regards - Puneet void main() { import std.stdio; ushort a = 0x55AA; ushort b = 0xAA55; writefln("%X", ~(a | b)); }
integer operations are always promoted to at least int. That's standard fare since C. I think it is a performance thing: Unpack into ints, oeprate, repack into ints. D's stance regarding integer operations is "if it compiles, it creates the same output as in C". It's kind of a gotcha, but not that big a deal.
Dec 11 2012
On 12/11/12 8:03 AM, d coder wrote:On Tue, Dec 11, 2012 at 6:23 PM, monarch_dodra <monarchdodra gmail.com <mailto:monarchdodra gmail.com>> wrote: D's stance regarding integer operations is "if it compiles, it creates the same output as in C". Thanks Monarch. So it is a gotcha we inherit from C. :-)
No, it's a fix of a gotcha from C. The C code would just allow the assignment. Andrei
Dec 11 2012
On 12/11/12 8:24 AM, d coder wrote:No, it's a fix of a gotcha from C. The C code would just allow the assignment. Yes Andrei. But it does not look clean if you have to write: byte a, b, c; a = cast(byte) (b + c); Well I know the advantages (safety). But imagine having to write all that when working with bytes and shorts. Makes it really difficult to work with shorts and bytes in D.
Value range propagation automatically avoids the need for a lot of those casts. http://www.drdobbs.com/tools/value-range-propagation/229300211Would I be asking for too much if I ask DMD to provide a compiler flag that makes it return bytes and shorts for operations on them?
That won't happen. Andrei
Dec 11 2012
On 12/11/12 11:36 AM, d coder wrote:Thanks Everybody for responding. I have another query which is off-topic but related. Why is the following allowed in D? long a; int b; b += a; // Allowed -- no explicit cast
RMW operations are allowed without a cast. Andrei
Dec 11 2012
On 12/11/2012 5:24 AM, d coder wrote:Would I be asking for too much if I ask DMD to provide a compiler flag that makes it return bytes and shorts for operations on them? So the deal would be, if you use this compiler flag, code behavior would be different from that of C/C++.
Having compiler flags that fundamentally change the behavior of the language are a disaster from about every point of view.
Dec 11 2012
On 12/11/2012 10:12 AM, Nick Sabalausky wrote:Let's not entertain any thoughts of allowing D to venture down that path.
No worries there :-) I feel pretty dang strongly about this issue, from bad experience. Even if a language behaves "wrong", it is still usable if it is predictable.
Dec 11 2012
--e89a8ff1bf66bda77304d093506b Content-Type: text/plain; charset=ISO-8859-1 On Tue, Dec 11, 2012 at 6:23 PM, monarch_dodra <monarchdodra gmail.com>wrote:D's stance regarding integer operations is "if it compiles, it creates the same output as in C".
Thanks Monarch. So it is a gotcha we inherit from C. :-) Regards - Puneet --e89a8ff1bf66bda77304d093506b Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br><br><div class=3D"gmail_quote">On Tue, Dec 11, 2012 at 6:23 PM, monarch= _dodra <span dir=3D"ltr"><<a href=3D"mailto:monarchdodra gmail.com" targ= et=3D"_blank">monarchdodra gmail.com</a>></span> wrote:<br><blockquote c= lass=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;= padding-left:1ex"> <div id=3D":8">D's stance regarding integer operations is "if it c= ompiles, it creates the same output as in C".<br></div></blockquote></= div><br><div>Thanks Monarch. So it is a gotcha we inherit from C. :-)</div> <div><br></div><div>Regards</div><div>- Puneet</div> --e89a8ff1bf66bda77304d093506b--
Dec 11 2012
--f46d042ef46ffc754304d0939a11 Content-Type: text/plain; charset=ISO-8859-1No, it's a fix of a gotcha from C. The C code would just allow the assignment.
Yes Andrei. But it does not look clean if you have to write: byte a, b, c; a = cast(byte) (b + c); Well I know the advantages (safety). But imagine having to write all that when working with bytes and shorts. Makes it really difficult to work with shorts and bytes in D. Would I be asking for too much if I ask DMD to provide a compiler flag that makes it return bytes and shorts for operations on them? So the deal would be, if you use this compiler flag, code behavior would be different from that of C/C++. What we get would be more practical short and byte behavior. Regards - Puneet --f46d042ef46ffc754304d0939a11 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br><div class=3D"gmail_quote"><blockquote class=3D"gmail_quote" style=3D"m= argin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> No, it's a fix of a gotcha from C. The C code would just allow the assi= gnment.</blockquote><div><br></div><div>Yes Andrei.</div><div><br></div><di= v>But it does not look clean if you have to write:</div><div><br></div> <div>byte a, b, c;</div><div>a =3D cast(byte) (b + c);</div><div><br></div>= <div>Well I know the advantages (safety). But imagine having to write all t= hat when working with bytes and shorts. Makes it really difficult to work w= ith shorts and bytes in D. Would I be asking for too much if I ask DMD to p= rovide a compiler flag that makes it return bytes and shorts for operations= on them? So the deal would be, if you use this compiler flag, code behavio= r would be different from that of C/C++.</div> <div><br></div><div>What we get would be more practical short and byte beha= vior.</div><div><br></div><div>Regards</div><div>- Puneet</div><div><br></d= iv></div> --f46d042ef46ffc754304d0939a11--
Dec 11 2012
On Tuesday, 11 December 2012 at 13:24:59 UTC, d coder wrote:But it does not look clean if you have to write: byte a, b, c; a = cast(byte) (b + c);
That's the whole point. What you are doing is dangerous, so it requires the cast. Adding a compiler flag to change the semantics of the language sounds like a recipe for disaster.
Dec 11 2012
--f46d042ef4f97a69c404d09422a3 Content-Type: text/plain; charset=ISO-8859-1 On Tue, Dec 11, 2012 at 7:05 PM, Peter Alexander < peter.alexander.au gmail.com> wrote:That's the whole point. What you are doing is dangerous, so it requires the cast.
What I am doing is not dangerous. I am operating at byte/short level. Tell me, if what I am doing is dangerous, how come doing the following is not dangerous. It is allowed by D. int a, b, c; a = b + c; Also the sense of safety that you get for short and byte too is not complete. Consider: void main() { import std.stdio; ushort a = ushort.max; ushort b = ushort.max; a += b; writeln(a); } Is it too much to ask for consistent behavior across the built-in types? Regards - Puneet --f46d042ef4f97a69c404d09422a3 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br><br><div class=3D"gmail_quote">On Tue, Dec 11, 2012 at 7:05 PM, Peter A= lexander <span dir=3D"ltr"><<a href=3D"mailto:peter.alexander.au gmail.c= om" target=3D"_blank">peter.alexander.au gmail.com</a>></span> wrote:<br=<blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1=
<div id=3D":vt">That's the whole point. What you are doing is dangerous= , so it requires the cast.<br></div></blockquote></div><br><div><br></div><= div>What I am doing is not dangerous. I am operating at byte/short level.</= div> <div>Tell me, if what I am doing is dangerous, how come doing the following= is not dangerous. It is allowed by D.</div><div><br></div><div>int a, b, c= ;</div><div>a =3D b + c;</div><div><br></div><div>Also the sense of safety = that you get for short and byte too is not complete. Consider:</div> <div><br></div><div><div>void main() {</div><div>=A0 import std.stdio;</div=<div>=A0 ushort a =3D ushort.max;</div><div>=A0 ushort b =3D ushort.max;</=
v><br></div> <div><br></div><div>Is it too much to ask for consistent behavior across th= e built-in types?</div><div><br></div><div>Regards</div><div>- Puneet</div>= <div><br></div> --f46d042ef4f97a69c404d09422a3--
Dec 11 2012
d coder:Tell me, if what I am doing is dangerous, how come doing the following is not dangerous. It is allowed by D. int a, b, c; a = b + c;
I think this dis-uniformity was added because: - Statistically it's more common to have an overflow when you sum two bytes compared to summing two ints. - If the sum of two ints/uints requires a cast, you need to fill your code with casts. And casts are not safe at all, they are sharp powertools. (I have asked many times for runtime integral overflows in D (as in C#/Delphi), that can be disabled with a compilation switch. But D designers come from the great unsafety of C-like languages and do not agree with me on the dangers/bugs of fixnum operations). Bye, bearophile
Dec 11 2012
On Tuesday, 11 December 2012 at 13:24:59 UTC, d coder wrote:No, it's a fix of a gotcha from C. The C code would just allow the assignment.
Yes Andrei. But it does not look clean if you have to write: byte a, b, c; a = cast(byte) (b + c); Well I know the advantages (safety). But imagine having to write all that when working with bytes and shorts. Makes it really difficult to work with shorts and bytes in D. Would I be asking for too much if I ask DMD to provide a compiler flag that makes it return bytes and shorts for operations on them? So the deal would be, if you use this compiler flag, code behavior would be different from that of C/C++. What we get would be more practical short and byte behavior. Regards - Puneet
If the compiler can statically verify that some integer value fits in a byte or short, you don't need the cast. So to rewrite your example: byte a, b, c; a = (b + c) & 0xFF; Also: short a; byte b, c; a = b + c; Still not exactly what you're looking for, but the mask looks nicer than a cast IMO. It's also safer.
Dec 11 2012
--f46d042f945ad7f69304d0964b15 Content-Type: text/plain; charset=ISO-8859-1 Thanks Everybody for responding. I have another query which is off-topic but related. Why is the following allowed in D? long a; int b; b += a; // Allowed -- no explicit cast b = a + b; // Not allowed b = a; // Not allowed --f46d042f945ad7f69304d0964b15 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Thanks Everybody for responding. I have another query which is off-topic bu= t related.<div><br></div><div>Why is the following allowed in D?</div><div>= <br></div><div>long a;</div><div>int b;</div><div><br></div><div>b +=3D a; = // Allowed -- no explicit cast</div> <div>b =3D a + b; // Not allowed</div><div>b =3D a; =A0 =A0 =A0// Not allow= ed</div><div><br></div> --f46d042f945ad7f69304d0964b15--
Dec 11 2012
d coder:Why is the following allowed in D? long a; int b; b += a; // Allowed -- no explicit cast b = a + b; // Not allowed b = a; // Not allowed
Seems a bug of range analysis. Bye, bearophile
Dec 11 2012
On Tue, 11 Dec 2012 09:47:33 -0800 Walter Bright <newshound2 digitalmars.com> wrote:On 12/11/2012 5:24 AM, d coder wrote:Would I be asking for too much if I ask DMD to provide a compiler flag that makes it return bytes and shorts for operations on them? So the deal would be, if you use this compiler flag, code behavior would be different from that of C/C++.
Having compiler flags that fundamentally change the behavior of the language are a disaster from about every point of view.
Yea, I'd hate to see D turn into PHP. That's one of the biggest reasons I despise PHP - code can't rely on fucking *anything* in it to ever work in any particular way. Pick any random line of PHP code, and there's about 20 different things it might do, even on the exact same version of PHP, all depending on a billion different configuration settings. Any library written in PHP is *inherently* broken simply by being one codebase intending to be "usable" on different servers. Let's not entertain any thoughts of allowing D to venture down that path.
Dec 11 2012
On Tuesday, 11 December 2012 at 16:09:14 UTC, Andrei Alexandrescu wrote:On 12/11/12 8:24 AM, d coder wrote:No, it's a fix of a gotcha from C. The C code would just allow the assignment. Yes Andrei. But it does not look clean if you have to write: byte a, b, c; a = cast(byte) (b + c); Well I know the advantages (safety). But imagine having to write all that when working with bytes and shorts. Makes it really difficult to work with shorts and bytes in D.
Value range propagation automatically avoids the need for a lot of those casts. http://www.drdobbs.com/tools/value-range-propagation/229300211Would I be asking for too much if I ask DMD to provide a compiler flag that makes it return bytes and shorts for operations on them?
That won't happen. Andrei
But than we have a bug in the value range propagation algorithm. E.g in the original program: void main() { import std.stdio; ushort a = 0x55AA; ushort b = 0xAA55; writefln("%X", ~(a | b)); } (a | b) will be in the range of ushort values and ~ of that also remains in the same value range. In other words, it makes no sense that boolean ops (and, or, xor, 1's compliment, 2's compliment) will require type promotion as they cannot exceed the original width of the values. This is unlike arithmetic which can require promotion.
Dec 11 2012
On Tuesday, 11 December 2012 at 14:02:52 UTC, d coder wrote:On Tue, Dec 11, 2012 at 7:05 PM, Peter Alexander < peter.alexander.au gmail.com> wrote:That's the whole point. What you are doing is dangerous, so it requires the cast.
What I am doing is not dangerous. I am operating at byte/short level. Tell me, if what I am doing is dangerous, how come doing the following is not dangerous. It is allowed by D. int a, b, c; a = b + c; Also the sense of safety that you get for short and byte too is not complete. Consider: void main() { import std.stdio; ushort a = ushort.max; ushort b = ushort.max; a += b; writeln(a); } Is it too much to ask for consistent behavior across the built-in types? Regards - Puneet
What if you create a new type that creates the proper functionality and does the implicit casting and such? This would hide away the details but maybe at a cost of efficiency. e.g., struct bbyte { byte value; ... } bbyte a; bbyte b; b = a + b; // uses bbyte's operators and casts to do the computation and assignment but then returns a bbyte instead of an int. You should have no problems implicitly converting bbyte to built in types or built in types to bbyte.
Dec 11 2012
--047d7b2e0bff50342c04d09f220e Content-Type: text/plain; charset=ISO-8859-1 On Wed, Dec 12, 2012 at 3:40 AM, Walter Bright <newshound2 digitalmars.com>wrote:No worries there :-) I feel pretty dang strongly about this issue, from bad experience. Even if a language behaves "wrong", it is still usable if it is predictable.
Agreed. How about this. 1. Let "char" and "short" behave the C/C++ way. These can return integers. This will make C/C++ code work in D. 2. Make D "byte" operations return bytes. And create another type (named say dbyte or shortint) and make operations on the new type return shortints. This will make these types more usable in D code. Well we end up adding another keyword, but we shall get workable and safe 8-bit and 16-bit integrals. Regards - Puneet --047d7b2e0bff50342c04d09f220e Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br><br><div class=3D"gmail_quote">On Wed, Dec 12, 2012 at 3:40 AM, Walter = Bright <span dir=3D"ltr"><<a href=3D"mailto:newshound2 digitalmars.com" = target=3D"_blank">newshound2 digitalmars.com</a>></span> wrote:<br><bloc= kquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #cc= c solid;padding-left:1ex"> <div id=3D":1d8">No worries there :-) I feel pretty dang strongly about thi= s issue, from bad experience.<br> <br> Even if a language behaves "wrong", it is still usable if it is p= redictable.</div></blockquote></div><br><div>Agreed.</div><div><br></div><d= iv>How about this.</div><div><br></div><div>1. Let "char" and &qu= ot;short" behave the C/C++ way. These can return integers. This will m= ake C/C++ code work in D.</div> <div>2. Make D "byte" operations return bytes. And create another= type (named say dbyte or shortint) and make operations on the new type ret= urn shortints. This will make these types more usable in D code. Well we en= d up adding another keyword, but we shall get workable and safe 8-bit and 1= 6-bit integrals.</div> <div><br></div><div>Regards</div><div>- Puneet</div> --047d7b2e0bff50342c04d09f220e--
Dec 11 2012
On Wednesday, 12 December 2012 at 03:10:15 UTC, d coder wrote:On Wed, Dec 12, 2012 at 3:40 AM, Walter Bright <newshound2 digitalmars.com>wrote:No worries there :-) I feel pretty dang strongly about this issue, from bad experience. Even if a language behaves "wrong", it is still usable if it is predictable.
Agreed. How about this. 1. Let "char" and "short" behave the C/C++ way. These can return integers. This will make C/C++ code work in D. 2. Make D "byte" operations return bytes. And create another type (named say dbyte or shortint) and make operations on the new type return shortints. This will make these types more usable in D code. Well we end up adding another keyword, but we shall get workable and safe 8-bit and 16-bit integrals. Regards - Puneet
What's now is safer than what you propose. You can always create your own data type that would automatically truncate result if you wish so.
Dec 11 2012
--f46d042f945a781bb304d0a05396 Content-Type: text/plain; charset=ISO-8859-1 On Wed, Dec 12, 2012 at 9:07 AM, Denis Koroskin <2korden gmail.com> wrote:What's now is safer than what you propose. You can always create your own data type that would automatically truncate result if you wish so.
:-) I should not have used the word "safe" there. All I meant was "safer" than C++ which allows implicit conversion form int to short and long to int. Yes, I am now using my own User Type. Regards - Puneet --f46d042f945a781bb304d0a05396 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br><br><div class=3D"gmail_quote">On Wed, Dec 12, 2012 at 9:07 AM, Denis K= oroskin <span dir=3D"ltr"><<a href=3D"mailto:2korden gmail.com" target= =3D"_blank">2korden gmail.com</a>></span> wrote:<br><blockquote class=3D= "gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding= -left:1ex"> What's now is safer than what you propose. You can always create your o= wn data type that would automatically truncate result if you wish so.</bloc= kquote></div><br><div>:-)</div><div><br></div><div>I should not have used t= he word "safe" there. All I meant was "safer" than C++ = which allows implicit conversion form int to short and long to int.</div> <div><br></div><div>Yes, I am now using my own User Type.</div><div><br></d= iv><div>Regards</div><div>- Puneet</div> --f46d042f945a781bb304d0a05396--
Dec 11 2012
On 2012-09-12 00:12, js.mdnq <js_adddot+mdng gmail.com> wrote:struct bbyte { byte value; ... } bbyte a; bbyte b; b = a + b; // uses bbyte's operators and casts to do the computation and assignment but then returns a bbyte instead of an int. You should have no problems implicitly converting bbyte to built in types or built in types to bbyte.
Not entirely true. Converting from bbyte to built-in works, but these are to my knowledge currently impossible: void foo(bbyte b); byte b; foo(b); // No conversion. bbyte bar( ) { byte b; return b; } -- Simen
Dec 12 2012
On Wednesday, December 12, 2012 09:23:35 Simen Kjaeraas wrote:On 2012-09-12 00:12, js.mdnq <js_adddot+mdng gmail.com> wrote:struct bbyte { byte value; ... } bbyte a; bbyte b; b = a + b; // uses bbyte's operators and casts to do the computation and assignment but then returns a bbyte instead of an int. You should have no problems implicitly converting bbyte to built in types or built in types to bbyte.
Not entirely true. Converting from bbyte to built-in works, but these are to my knowledge currently impossible: void foo(bbyte b); byte b; foo(b); // No conversion. bbyte bar( ) { byte b; return b; }
You can do it with alias this, but the current lack of ability to have multiple alias thises probably makes it so that you can't use it for converting in both directions unless you want to directly alias it to the member variable holding the value (which eans no checks or whatever else you might want to do in bbyte). Once we can have multiple alias thises though, that shouldn't be problem anymore. - Jonathan M Davis
Dec 12 2012
On 2012-17-12 10:12, Jonathan M Davis <jmdavisProg gmx.com> wrote:On Wednesday, December 12, 2012 09:23:35 Simen Kjaeraas wrote:On 2012-09-12 00:12, js.mdnq <js_adddot+mdng gmail.com> wrote:struct bbyte { byte value; ... } bbyte a; bbyte b; b = a + b; // uses bbyte's operators and casts to do the computation
assignment but then returns a bbyte instead of an int. You should have no problems implicitly converting bbyte to built in types or built in types to bbyte.
Not entirely true. Converting from bbyte to built-in works, but these are to my knowledge currently impossible: void foo(bbyte b); byte b; foo(b); // No conversion. bbyte bar( ) { byte b; return b; }
You can do it with alias this, but the current lack of ability to have multiple alias thises probably makes it so that you can't use it for converting in both directions unless you want to directly alias it to the member variable holding the value (which eans no checks or whatever else you might want to do in bbyte). Once we can have multiple alias thises though, that shouldn't be problem anymore.
Really? This certainly does not compile for me: struct bbyte { byte b; alias b this; } void bar(bbyte b) {} bbyte baz() { byte b; return b; // cannot implicitly convert expression (b) of type byte to bbyte } void main() { byte b; bar(b); // function bar (bbyte b) is not callable using argument types (byte) } This is also the reason for bug #8570 http://d.puremagic.com/issues/show_bug.cgi?id=8570 -- Simen
Dec 12 2012
On Wednesday, 12 December 2012 at 08:23:48 UTC, Simen Kjaeraas wrote:On 2012-09-12 00:12, js.mdnq <js_adddot+mdng gmail.com> wrote:struct bbyte { byte value; ... } bbyte a; bbyte b; b = a + b; // uses bbyte's operators and casts to do the computation and assignment but then returns a bbyte instead of an int. You should have no problems implicitly converting bbyte to built in types or built in types to bbyte.
Not entirely true. Converting from bbyte to built-in works, but these are to my knowledge currently impossible: void foo(bbyte b); byte b; foo(b); // No conversion. bbyte bar( ) { byte b; return b; }
What I mean is that you use bbyte for all your arithmetic operations and computations. When you need to convert it to a byte(hopefully at the end of the process), you can use an implicit cast. struct bbyte { byte b; byte opCast(bbyte a) { return a.b; } alias b this; bbyte bar(byte b) { bbyte q; q.b = b; return q; } byte foo(bbyte b) { return b.b; } } byte bar2(byte b) { return b; } int main(string[] argv) { bbyte bb; byte b; bb.foo(bb); bb.bar(b); b = bb; bb = b; } the point is no explicit op casts are required. Essentially a bbyte is a byte. One can overload all the operators that are needed for bit manipulation, even using asm if necessary and one should be able to hide most of the details. `alias this` might not stop some of the value propagation in some cases. If one only converts to the built-in types when actually needed(when passing to and from routines that use them) but uses bbyte for all bit manipulations it shouldn't be much of a problem(if at all). The idea is that conversion from bbyte to byte does not induce an expansion to int, only the arithmetic operations. Hence, overriding them can stop that. but something like byte b1; byte b2; bbyte b3 = b1 + b2; is computing the arithmetic operation from byte(which converts to an int). This is why I say one must use bbytes for all arithmetic operations to solve that problem. (or write a cast for int, if you just don't want to deal with it but don't mind the expansion) But this works: byte b1; byte b2; bbyte b3; b3 = b1 + b2; if one has bbyte opAssign(int i) { this.b = cast(byte)i; return this; } in bbyte. which avoids having to do b3 = cast(byte)(b1 + b2) which I think was what the original post was about.
Dec 12 2012
On Wednesday, December 12, 2012 10:42:31 Simen Kjaeraas wrote:Really? This certainly does not compile for me: struct bbyte { byte b; alias b this; } void bar(bbyte b) {} bbyte baz() { byte b; return b; // cannot implicitly convert expression (b) of type byte to bbyte } void main() { byte b; bar(b); // function bar (bbyte b) is not callable using argument types (byte) } This is also the reason for bug #8570 http://d.puremagic.com/issues/show_bug.cgi?id=8570
If alias this isn't do an implict conversion, then there's a bug in alias this. That's how implict conversion is done in D, and it's the whole point of alias this. - Jonathan M Davis
Dec 12 2012
On 12/12/2012 10:25 AM, Jonathan M Davis wrote:If alias this isn't do an implict conversion, then there's a bug in alias this. That's how implict conversion is done in D, and it's the whole point of alias this.
And it does, as I relied on this to do the halffloat implementation.
Dec 12 2012
On 12/13/2012 6:30 AM, Simen Kjaeraas wrote:Walter does not seem to agree (see his post in this discussion).
Note that the following implementation of halffloat does work, allowing explicit cast to halffloat and implicit conversion from. (The halffloat literals don't work at the moment because of a limitation in CTFE, I'm working with Don to resolve that.) ----------------------------------------------------------- /* * References: * http://en.wikipedia.org/wiki/Half-precision_floating-point_format */ module halffloat; struct HF { /* Provide implicit conversion of HF to float */ property float toFloat() { return shortToFloat(s); } alias toFloat this; /* Done as a template in order to prevent implicit conversion * of argument to float. */ this(T : float)(T f) { static assert(is(T == float)); s = floatToShort(f); } /* These are done as properties to avoid * circular reference problems. */ static property HF min_normal() { HF hf = void; hf.s = 0x0400; return hf; /* fp16!0x1p-14; */ } static property HF max() { HF hf = void; hf.s = 0x7BFF; return hf; /* fp16!0x1.FFCp+15; */ } static property HF nan() { HF hf = void; hf.s = EXPMASK | 1; return hf; /* fp16!(float.nan); */ } static property HF infinity() { HF hf = void; hf.s = EXPMASK; return hf; /* fp16!(float.infinity); */ } static property HF epsilon() { HF hf = void; hf.s = 0x3C01; return hf; /* fp16!0x1p-10; */ } enum dig = 3; enum mant_dig = 11; enum max_10_exp = 5; enum max_exp = 16; enum min_10_exp = -5; enum min_exp = -14; private: ushort s = EXPMASK | 1; // .init is HF.nan } /******************** * User defined literal for Half Float. */ template fp16(float v) { enum fp16 = HF(v); } private: // Half float values enum SIGNMASK = 0x8000; enum EXPMASK = 0x7C00; enum MANTMASK = 0x03FF; enum HIDDENBIT = 0x0400; // float values enum FSIGNMASK = 0x80000000; enum FEXPMASK = 0x7F800000; enum FMANTMASK = 0x007FFFFF; enum FHIDDENBIT = 0x00800000; // Rounding mode enum ROUND { TONEAREST, UPWARD, DOWNWARD, TOZERO }; enum ROUNDMODE = ROUND.TONEAREST; union U { uint u; float f; } ushort floatToShort(float f) { /* If the target CPU has a conversion instruction, this code could be * replaced with inline asm or a compiler intrinsic, but leave this * as the CTFE path so CTFE can work on it. */ /* The code currently does not set INEXACT, UNDERFLOW, or OVERFLOW, * but is marked where those would go. */ U uf = void; uf.f = f; uint s = uf.u; ushort u = (s & FSIGNMASK) ? SIGNMASK : 0; int exp = s & FEXPMASK; if (exp == FEXPMASK) // if nan or infinity { if ((s & FMANTMASK) == 0) // if infinity { u |= EXPMASK; } else // else nan { u |= EXPMASK | 1; } return u; } uint significand = s & FMANTMASK; if (exp == 0) // if subnormal or zero { if (significand == 0) // if zero return u; /* A subnormal float is going to give us a zero result anyway, * so just set UNDERFLOW and INEXACT and return +-0. */ return u; } else // else normal { // normalize exponent and remove bias exp = (exp >> 23) - 127; significand |= FHIDDENBIT; } exp += 15; // bias the exponent bool guard = false; // guard bit bool sticky = false; // sticky bit uint shift = 13; // lop off rightmost 13 bits if (exp <= 0) // if subnormal { shift += -exp + 1; // more bits to lop off exp = 0; } if (shift > 23) { // Set UNDERFLOW, INEXACT, return +-0 return u; } // Lop off rightmost 13 bits, but save guard and sticky bits guard = (significand & (1 << (shift - 1))) != 0; sticky = (significand & ((1 << (shift - 1)) - 1)) != 0; significand >>= shift; if (guard || sticky) { // Lost some bits, so set INEXACT and round the result switch (ROUNDMODE) { case ROUND.TONEAREST: if (guard && (sticky || (significand & 1))) ++significand; break; case ROUND.UPWARD: if (!(s & FSIGNMASK)) ++significand; break; case ROUND.DOWNWARD: if (s & FSIGNMASK) ++significand; break; case ROUND.TOZERO: break; default: assert(0); } if (exp == 0) // if subnormal { if (significand & HIDDENBIT) // and not a subnormal no more ++exp; } else if (significand & (HIDDENBIT << 1)) { significand >>= 1; ++exp; } } if (exp > 30) { // Set OVERFLOW and INEXACT, return +-infinity return u | EXPMASK; } /* Add exponent and significand into result. */ u |= exp << 10; // exponent u |= (significand & ~HIDDENBIT); // significand return u; } float shortToFloat(ushort s) { /* If the target CPU has a conversion instruction, this code could be * replaced with inline asm or a compiler intrinsic, but leave this * as the CTFE path so CTFE can work on it. */ /* This one is fairly easy because there are no possible errors * and no necessary rounding. */ int exp = s & EXPMASK; if (exp == EXPMASK) // if nan or infinity { float f; if ((s & MANTMASK) == 0) // if infinity { f = float.infinity; } else // else nan { f = float.nan; } return (s & SIGNMASK) ? -f : f; } uint significand = s & MANTMASK; if (exp == 0) // if subnormal or zero { if (significand == 0) // if zero return (s & SIGNMASK) ? -0.0f : 0.0f; // Normalize by shifting until the hidden bit is 1 while (!(significand & HIDDENBIT)) { significand <<= 1; --exp; } significand &= ~HIDDENBIT; // hidden bit is, well, hidden exp -= 14; } else // else normal { // normalize exponent and remove bias exp = (exp >> 10) - 15; } /* Assemble sign, exponent, and significand into float. * Don't have to deal with overflow, inexact, or subnormal * because the range of floats is big enough. */ assert(-126 <= exp && exp <= 127); // just to be sure //printf("exp = %d, significand = x%x\n", exp, significand); uint u = (s & SIGNMASK) << 16; // sign bit u |= (exp + 127) << 23; // bias the exponent and shift into position u |= significand << (23 - 10); U uf = void; uf.u = u; return uf.f; } import std.stdio; void main() { // HF h = fp16!27.2f; // HF j = cast(HF)( fp16!3.5f + fp16!5 ); HF f = HF(0.0f); f.s = 0x3C00; writeln("1 ", cast(float)f); f.s = 0x3C01; writeln("1.0009765625 ", cast(float)f); assert(f == HF.epsilon); f.s = 0xC000; writeln("-2 ", cast(float)f); f.s = 0x7BFF; writeln("65504 ", cast(float)f); assert(f == HF.max); f.s = 0x0400; writeln("6.10352e-5 ", cast(float)f); assert(f == HF.min_normal); f.s = 0x03FF; writeln("6.09756e-5 ", cast(float)f); f.s = 1; writeln("5.96046e-8 ", cast(float)f); f.s = 0; writeln("0 ", cast(float)f); assert(f == 0.0f); f.s = 0x8000; writeln("-0 ", cast(float)f); assert(f == -0.0f); f.s = 0x7C00; writeln("infinity ", cast(float)f); assert(f == HF.infinity); f.s = 0xFC00; writeln("-infinity ", cast(float)f); assert(f == -HF.infinity); f.s = 0x3555; writeln("0.33325 ", cast(float)f); }
Dec 13 2012
On 12/13/2012 10:19 PM, H. S. Teoh wrote:This is cool, I've never thought of using alias this on a property function. I'll have to start using that in my code. :-)
That's actually why I wrote it - as a "template" for how to do similar user defined types.The rest of the code is tl;dr, but I think it does showcase quite well the power of user-defined types in D. Now we just have to iron out implicit conversion from literals (and I mean that in general, not just for this particular example), and it will just be great.
Yup. Once all that works, I'd like to incorporate halffloat into Phobos.
Dec 14 2012
On 12/14/2012 4:02 PM, H. S. Teoh wrote:I'm so impressed by this trick that I decided to do a writeup of it on the wiki: http://wiki.dlang.org/Implicit_conversions_in_user_types
I'd prefer to call it a "technique" rather than a "trick", because this is what alias this was designed for!
Dec 14 2012
On 12/14/2012 6:27 PM, Adam D. Ruppe wrote:BTW is there any idea for the timetable of multiple alas this like described in Andrei's book?
Not at the moment.
Dec 14 2012
On Wednesday, December 12, 2012 13:35:59 Walter Bright wrote:On 12/12/2012 10:25 AM, Jonathan M Davis wrote:If alias this isn't do an implict conversion, then there's a bug in alias this. That's how implict conversion is done in D, and it's the whole point of alias this.
And it does, as I relied on this to do the halffloat implementation.
Simen's example doesn't seem to work though, so he appears to have found a bug. Certainly, I don't see anything wrong with it, but alias this doesn't seem to work for it. Regardless, my point was that if there's a case where alias this isn't doing an implicit conversion, then it's a bug, because that's the whole reason that it exists. - Jonathan M Davis
Dec 12 2012
On 2012-22-13 04:12, Jonathan M Davis <jmdavisProg gmx.com> wrote:On Wednesday, December 12, 2012 13:35:59 Walter Bright wrote:On 12/12/2012 10:25 AM, Jonathan M Davis wrote:If alias this isn't do an implict conversion, then there's a bug in
this. That's how implict conversion is done in D, and it's the whole
of alias this.
And it does, as I relied on this to do the halffloat implementation.
Simen's example doesn't seem to work though, so he appears to have found a bug. Certainly, I don't see anything wrong with it, but alias this doesn't seem to work for it. Regardless, my point was that if there's a case where alias this isn't doing an implicit conversion, then it's a bug, because that's the whole reason that it exists.
So it is supposed to work? I've always thought this was a deliberate design choice. I guess I'll file a bug, then. Here: http://d.puremagic.com/issues/show_bug.cgi?id=9147 Kenji, you here? :p -- Simen
Dec 13 2012
--f46d04374ee16b9b4804d0bb602e Content-Type: text/plain; charset=UTF-8 D does not support such implicit *construction* in return statement and function argument. It is a current language design, and not a bug. Kenji Hara 2012/12/13 Simen Kjaeraas <simen.kjaras gmail.com>On 2012-22-13 04:12, Jonathan M Davis <jmdavisProg gmx.com> wrote: On Wednesday, December 12, 2012 13:35:59 Walter Bright wrote:On 12/12/2012 10:25 AM, Jonathan M Davis wrote:If alias this isn't do an implict conversion, then there's a bug in
this. That's how implict conversion is done in D, and it's the whole
of alias this.
And it does, as I relied on this to do the halffloat implementation.
Simen's example doesn't seem to work though, so he appears to have found a bug. Certainly, I don't see anything wrong with it, but alias this doesn't seem to work for it. Regardless, my point was that if there's a case where alias this isn't doing an implicit conversion, then it's a bug, because that's the whole reason that it exists.
So it is supposed to work? I've always thought this was a deliberate design choice. I guess I'll file a bug, then. Here: http://d.puremagic.com/issues/**show_bug.cgi?id=9147<http://d.puremagic.com/issues/show_bug.cgi?id=9147> Kenji, you here? :p -- Simen
--f46d04374ee16b9b4804d0bb602e Content-Type: text/html; charset=UTF-8 D does not support such implicit *construction* in return statement and function argument.<div>It is a current language design, and not a bug.<br></div><div><br></div><div>Kenji Hara</div><div class="gmail_extra"><br><br><div class="gmail_quote"> 2012/12/13 Simen Kjaeraas <span dir="ltr"><<a href="mailto:simen.kjaras gmail.com" target="_blank">simen.kjaras gmail.com</a>></span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> <div class="HOEnZb"><div class="h5">On <a href="tel:2012-22-13%2004" value="+12012221304" target="_blank">2012-22-13 04</a>:12, Jonathan M Davis <<a href="mailto:jmdavisProg gmx.com" target="_blank">jmdavisProg gmx.com</a>> wrote:<br> <br> <blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> On Wednesday, December 12, 2012 13:35:59 Walter Bright wrote:<br> <blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> On 12/12/2012 10:25 AM, Jonathan M Davis wrote:<br> > If alias this isn't do an implict conversion, then there's a bug in alias<br> > this. That's how implict conversion is done in D, and it's the whole point<br> > of alias this.<br> <br> And it does, as I relied on this to do the halffloat implementation.<br> </blockquote> <br> Simen's example doesn't seem to work though, so he appears to have found a<br> bug. Certainly, I don't see anything wrong with it, but alias this doesn't<br> seem to work for it. Regardless, my point was that if there's a case where<br> alias this isn't doing an implicit conversion, then it's a bug, because that's<br> the whole reason that it exists.<br> </blockquote> <br></div></div> So it is supposed to work? I've always thought this was a deliberate design<br> choice. I guess I'll file a bug, then. Here:<br> <br> <a href="http://d.puremagic.com/issues/show_bug.cgi?id=9147" target="_blank">http://d.puremagic.com/issues/<u></u>show_bug.cgi?id=9147</a><br> <br> Kenji, you here? :p<span class="HOEnZb"><font color="#888888"><br> <br> -- <br> Simen<br> </font></span></blockquote></div><br></div> --f46d04374ee16b9b4804d0bb602e--
Dec 13 2012
On 2012-51-13 13:12, kenji hara <k.hara.pg gmail.com> wrote:D does not support such implicit *construction* in return statement and function argument. It is a current language design, and not a bug.
Walter does not seem to agree (see his post in this discussion). Previous discussions with Andrei (see bug #8570[1] and related discussion[2]) indicates he also thinks alias this (or some other language feature) should support this. I guess this is not really relevant to this discussion, so I'll make a separate thread. [1]: http://d.puremagic.com/issues/show_bug.cgi?id=8570 [2]: http://forum.dlang.org/thread/sedknwtlaefrxuflnbez forum.dlang.org?page=8#postjul0qv:242l9d:241:40digitalmars.com -- Simen
Dec 13 2012
On Thu, Dec 13, 2012 at 05:44:23PM -0800, Walter Bright wrote:On 12/13/2012 6:30 AM, Simen Kjaeraas wrote:Walter does not seem to agree (see his post in this discussion).
Note that the following implementation of halffloat does work, allowing explicit cast to halffloat and implicit conversion from. (The halffloat literals don't work at the moment because of a limitation in CTFE, I'm working with Don to resolve that.) -----------------------------------------------------------
Nice!! [...]/* Provide implicit conversion of HF to float */ property float toFloat() { return shortToFloat(s); } alias toFloat this;
This is cool, I've never thought of using alias this on a property function. I'll have to start using that in my code. :-) The rest of the code is tl;dr, but I think it does showcase quite well the power of user-defined types in D. Now we just have to iron out implicit conversion from literals (and I mean that in general, not just for this particular example), and it will just be great. T -- Which is worse: ignorance or apathy? Who knows? Who cares? -- Erich Schubert
Dec 13 2012
On Fri, Dec 14, 2012 at 12:39:04AM -0800, Walter Bright wrote:On 12/13/2012 10:19 PM, H. S. Teoh wrote:This is cool, I've never thought of using alias this on a property function. I'll have to start using that in my code. :-)
That's actually why I wrote it - as a "template" for how to do similar user defined types.
I'm so impressed by this trick that I decided to do a writeup of it on the wiki: http://wiki.dlang.org/Implicit_conversions_in_user_types T -- If Java had true garbage collection, most programs would delete themselves upon execution. -- Robert Sewell
Dec 14 2012
On Saturday, 15 December 2012 at 02:23:18 UTC, Walter Bright wrote:I'd prefer to call it a "technique" rather than a "trick", because this is what alias this was designed for!
BTW is there any idea for the timetable of multiple alas this like described in Andrei's book?
Dec 14 2012
On Tuesday, 11 December 2012 at 12:53:38 UTC, monarch_dodra wrote:integer operations are always promoted to at least int. That's standard fare since C. I think it is a performance thing: Unpack into ints, oeprate, repack into ints.
If memory serves me right, promotion to int is based more on CPU efficiency and code size than anything else (and yes packing and unpacking takes some 6 extra steps). Also with libraries possibly written by different compilers may have different results if they don't all agree on a common (default) type to return. Also most x86 operations for ints can be written as 1 byte opcodes, although for modern CPUs that kind of code generation may not be as efficient as it used to be. http://www.codeproject.com/Articles/6154/Writing-Efficient-C-and-C-Code-Optimization
Dec 16 2012









Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> 