November 18, 2012
On Sun, 18 Nov 2012 05:21:27 -0600, Manu <turkeyman@gmail.com> wrote:

> I've often wondered about having an official 'half' type.
> It's very common in rendering/image processing, supported by most video
> cards (so compression routines interacting with this type are common), and
> it's also supported in hardware by some cpu's.
>
> ARM for instance supports 'half's in hardware, and GCC has an __fp16 type
> which would map nicely if D supported the type in the front end.
>
> The alternative us to use ushort everywhere, which is awkward, because it
> is neither unsigned, nor is it an integer, and it's not typesafe (allows
> direct assignment to ints and stuff)...
> It would be nice if: cast(half)someFloat would yield the proper value, even
> if it is performed in software in most architectures, it could be mapped to
> hardware for those that do it.
>
> It could be done in a library, but then GCC couldn't map it properly to the
> hardware type, and since D has no way to describe implicit casts (that I
> know of?) it becomes awkward to use.
> someFloat = someHalf <- doesn't work, because a cast operator expects an
> explicit cast, even though this is a lossless conversion and should be
> exactly the same as someDouble = someFloat.
>
> Thoughts?
>

Vote--.

The a half data type is already part of std.numeric. From the docs:

// Define a 16-bit floating point values
   CustomFloat!16                                x;     // Using the number of bits
   CustomFloat!(10, 5)                           y;     // Using the precision and exponent width
   CustomFloat!(10, 5,CustomFloatFlags.ieee)     z;     // Using the precision, exponent width and format flags
   CustomFloat!(10, 5,CustomFloatFlags.ieee, 15) w;     // Using the precision, exponent width, format flags and exponent offset bias

   // Use the 16-bit floats mostly like normal numbers
   w = x*y - 1;
   writeln(w);

   // Functions calls require conversion
   z = sin(+x)           + cos(+y);                     // Use uniary plus to concisely convert to a real
   z = sin(x.re)         + cos(y.re);                   // Or use the .re property to convert to a real
   z = sin(x.get!float)  + cos(y.get!float);            // Or use get!T
   z = sin(cast(float)x) + cos(cast(float)y);           // Or use cast(T) to explicitly convert

   // Define a 8-bit custom float for storing probabilities
   alias CustomFloat!(4, 4, CustomFloatFlags.ieee^CustomFloatFlags.probability^CustomFloatFlags.signed ) Probability;
   auto p = Probability(0.5);
November 18, 2012
On Sun, 18 Nov 2012 05:21:27 -0600, Manu <turkeyman@gmail.com> wrote:

> I've often wondered about having an official 'half' type.
> It's very common in rendering/image processing, supported by most video
> cards (so compression routines interacting with this type are common), and
> it's also supported in hardware by some cpu's.
>
> ARM for instance supports 'half's in hardware, and GCC has an __fp16 type
> which would map nicely if D supported the type in the front end.
>
> The alternative us to use ushort everywhere, which is awkward, because it
> is neither unsigned, nor is it an integer, and it's not typesafe (allows
> direct assignment to ints and stuff)...
> It would be nice if: cast(half)someFloat would yield the proper value, even
> if it is performed in software in most architectures, it could be mapped to
> hardware for those that do it.
>
> It could be done in a library, but then GCC couldn't map it properly to the
> hardware type, and since D has no way to describe implicit casts (that I
> know of?) it becomes awkward to use.
> someFloat = someHalf <- doesn't work, because a cast operator expects an
> explicit cast, even though this is a lossless conversion and should be
> exactly the same as someDouble = someFloat.
>
> Thoughts?
>

Vote--.

The a half data type is already part of std.numeric. From the docs:

// Define a 16-bit floating point values
   CustomFloat!16                                x;     // Using the number of bits
   CustomFloat!(10, 5)                           y;     // Using the precision and exponent width
   CustomFloat!(10, 5,CustomFloatFlags.ieee)     z;     // Using the precision, exponent width and format flags
   CustomFloat!(10, 5,CustomFloatFlags.ieee, 15) w;     // Using the precision, exponent width, format flags and exponent offset bias

   // Use the 16-bit floats mostly like normal numbers
   w = x*y - 1;
   writeln(w);

   // Functions calls require conversion
   z = sin(+x)           + cos(+y);                     // Use uniary plus to concisely convert to a real
   z = sin(x.re)         + cos(y.re);                   // Or use the .re property to convert to a real
   z = sin(x.get!float)  + cos(y.get!float);            // Or use get!T
   z = sin(cast(float)x) + cos(cast(float)y);           // Or use cast(T) to explicitly convert

   // Define a 8-bit custom float for storing probabilities
   alias CustomFloat!(4, 4, CustomFloatFlags.ieee^CustomFloatFlags.probability^CustomFloatFlags.signed ) Probability;
   auto p = Probability(0.5);
November 18, 2012
I'm sure that's true, I've just always used it to gain access to members of embedded types, kinda of like abstraction for 'struct's. It hadn't occurred to me to support explicit casting in that way.


On 18 November 2012 18:31, Andrei Alexandrescu < SeeWebsiteForEmail@erdani.org> wrote:

> On 11/18/12 7:30 AM, Manu wrote:
>
>> On 18 November 2012 14:01, David Nadlinger <see@klickverbot.at
>>
>> <mailto:see@klickverbot.at>> wrote:
>>
>>     On Sunday, 18 November 2012 at 11:21:37 UTC, Manu wrote:
>>
>>         someFloat = someHalf <- doesn't work, because a cast operator
>>         expects an
>>         explicit cast, even though this is a lossless conversion and
>>         should be
>>         exactly the same as someDouble = someFloat.
>>
>>         Thoughts?
>>
>>
>>     ---
>>     struct Half {
>>          float toFloat() { return 3.14f; }
>>          alias toFloat this;
>>     }
>>
>>     void test() {
>>          Half h;
>>          float f = h;
>>          double d = h;
>>     }
>>     ---
>>
>>     Works for you?
>>
>>
>> Interesting approach to the implicit cast problem. Very handy trick.
>>
>
> Well that was quite explicitly part of the purpose of alias this.
>
> Andrei
>


November 19, 2012
On 19 November 2012 01:08, Robert Jacques <sandford@jhu.edu> wrote:

> On Sun, 18 Nov 2012 05:21:27 -0600, Manu <turkeyman@gmail.com> wrote:
>
>  I've often wondered about having an official 'half' type.
>> It's very common in rendering/image processing, supported by most video cards (so compression routines interacting with this type are common), and it's also supported in hardware by some cpu's.
>>
>> ARM for instance supports 'half's in hardware, and GCC has an __fp16 type which would map nicely if D supported the type in the front end.
>>
>> The alternative us to use ushort everywhere, which is awkward, because it
>> is neither unsigned, nor is it an integer, and it's not typesafe (allows
>> direct assignment to ints and stuff)...
>> It would be nice if: cast(half)someFloat would yield the proper value,
>> even
>> if it is performed in software in most architectures, it could be mapped
>> to
>> hardware for those that do it.
>>
>> It could be done in a library, but then GCC couldn't map it properly to
>> the
>> hardware type, and since D has no way to describe implicit casts (that I
>> know of?) it becomes awkward to use.
>> someFloat = someHalf <- doesn't work, because a cast operator expects an
>> explicit cast, even though this is a lossless conversion and should be
>> exactly the same as someDouble = someFloat.
>>
>> Thoughts?
>>
>>
> Vote--.
>
> The a half data type is already part of std.numeric. From the docs:
>
> // Define a 16-bit floating point values
>    CustomFloat!16                                x;     // Using the
> number of bits
>    CustomFloat!(10, 5)                           y;     // Using the
> precision and exponent width
>    CustomFloat!(10, 5,CustomFloatFlags.ieee)     z;     // Using the
> precision, exponent width and format flags
>    CustomFloat!(10, 5,CustomFloatFlags.ieee, 15) w;     // Using the
> precision, exponent width, format flags and exponent offset bias
>
>    // Use the 16-bit floats mostly like normal numbers
>    w = x*y - 1;
>    writeln(w);
>
>    // Functions calls require conversion
>    z = sin(+x)           + cos(+y);                     // Use uniary plus
> to concisely convert to a real
>    z = sin(x.re)         + cos(y.re);                   // Or use the .re
> property to convert to a real
>    z = sin(x.get!float)  + cos(y.get!float);            // Or use get!T
>    z = sin(cast(float)x) + cos(cast(float)y);           // Or use cast(T)
> to explicitly convert
>
>    // Define a 8-bit custom float for storing probabilities
>    alias CustomFloat!(4, 4, CustomFloatFlags.ieee^**
> CustomFloatFlags.probability^**CustomFloatFlags.signed ) Probability;
>    auto p = Probability(0.5);
>

I still can't buy arguments like this. It completely changes the syntax.
If I told you this is how real should be implemented, would you vote ++?
What about double? Why?
Why not float for that matter? There seems like no reason for the language
to define any floating point type at all if you consider this acceptable...

'half' isn't some custom float for niche use, it's an established standard, implemented in vastly more hardware than implements 'real'.


November 19, 2012
On 19 November 2012 01:58, Manu <turkeyman@gmail.com> wrote:

> I'm sure that's true, I've just always used it to gain access to members of embedded types, kinda of like abstraction for 'struct's. It hadn't occurred to me to support explicit casting in that way.


**cough** IMPLICIT casting.

On 18 November 2012 18:31, Andrei Alexandrescu <
> SeeWebsiteForEmail@erdani.org> wrote:
>
>> On 11/18/12 7:30 AM, Manu wrote:
>>
>>> On 18 November 2012 14:01, David Nadlinger <see@klickverbot.at
>>>
>>> <mailto:see@klickverbot.at>> wrote:
>>>
>>>     On Sunday, 18 November 2012 at 11:21:37 UTC, Manu wrote:
>>>
>>>         someFloat = someHalf <- doesn't work, because a cast operator
>>>         expects an
>>>         explicit cast, even though this is a lossless conversion and
>>>         should be
>>>         exactly the same as someDouble = someFloat.
>>>
>>>         Thoughts?
>>>
>>>
>>>     ---
>>>     struct Half {
>>>          float toFloat() { return 3.14f; }
>>>          alias toFloat this;
>>>     }
>>>
>>>     void test() {
>>>          Half h;
>>>          float f = h;
>>>          double d = h;
>>>     }
>>>     ---
>>>
>>>     Works for you?
>>>
>>>
>>> Interesting approach to the implicit cast problem. Very handy trick.
>>>
>>
>> Well that was quite explicitly part of the purpose of alias this.
>>
>> Andrei
>
>


November 19, 2012
On 11/18/2012 4:31 PM, Manu wrote:
> If I told you this is how real should be implemented, would you vote ++? What
> about double? Why?
> Why not float for that matter? There seems like no reason for the language to
> define any floating point type at all if you consider this acceptable...

Because they are implemented in hardware. It's pretty dang hard for a compiler to look at a floating point emulator and figure out "gee, I have a nice hardware instruction that does the same thing as this 2K of code!"

> 'half' isn't some custom float for niche use, it's an established standard,
> implemented in vastly more hardware than implements 'real'.

It's implemented in GPUs, sure, but it is it implemented in hardware that D runs on? (I do know about this: http://gcc.gnu.org/onlinedocs/gcc/Half_002dPrecision.html)

There is no major technical difficulty in implementing it as a basic type, but I want to be sure we've exhausted the library approach first.
November 19, 2012
On 19 November 2012 06:19, Walter Bright <newshound2@digitalmars.com> wrote:

> On 11/18/2012 4:31 PM, Manu wrote:
>
>> If I told you this is how real should be implemented, would you vote ++?
>> What
>> about double? Why?
>> Why not float for that matter? There seems like no reason for the
>> language to
>> define any floating point type at all if you consider this acceptable...
>>
>
> Because they are implemented in hardware. It's pretty dang hard for a compiler to look at a floating point emulator and figure out "gee, I have a nice hardware instruction that does the same thing as this 2K of code!"


Right, and this is my point precisely. It's hard for GDC for instance to hook some complex library because it happens to have hardware to do it.

 'half' isn't some custom float for niche use, it's an established standard,
>> implemented in vastly more hardware than implements 'real'.
>>
>
> It's implemented in GPUs, sure, but it is it implemented in hardware that
> D runs on? (I do know about this: http://gcc.gnu.org/onlinedocs/**
> gcc/Half_002dPrecision.html<http://gcc.gnu.org/onlinedocs/gcc/Half_002dPrecision.html>
> )
>
> There is no major technical difficulty in implementing it as a basic type, but I want to be sure we've exhausted the library approach first.
>

Well it's available in hardware on basically all mobile devices (that's a
LOT of devices (in the billions)), but even if it's just implemented in
software (x86), the values are consumed by the GPU, and the validity of the
values is no less important. It still seems like a valuable 1st class type;
why shouldn't it enjoy the same casting, assignment, literal, range
checking rules as the rest of the floats? Additionally, convenience and
compatibility with generic code would be significantly improved.
I don't see how it can be made to feel seamless with a lib... and that
sounds like an awful lot more work.


Anyway, I'm not desperate for this personally. I just wondered how people felt about it in general, and if it was something that should/would be seriously considered.


November 19, 2012
On 19 November 2012 16:04, Manu <turkeyman@gmail.com> wrote:
> On 19 November 2012 06:19, Walter Bright <newshound2@digitalmars.com> wrote:
>>
>> On 11/18/2012 4:31 PM, Manu wrote:
>>>
>>> If I told you this is how real should be implemented, would you vote ++?
>>> What
>>> about double? Why?
>>> Why not float for that matter? There seems like no reason for the
>>> language to
>>> define any floating point type at all if you consider this acceptable...
>>
>>
>> Because they are implemented in hardware. It's pretty dang hard for a compiler to look at a floating point emulator and figure out "gee, I have a nice hardware instruction that does the same thing as this 2K of code!"
>
>
> Right, and this is my point precisely. It's hard for GDC for instance to hook some complex library because it happens to have hardware to do it.
>
>>> 'half' isn't some custom float for niche use, it's an established
>>> standard,
>>> implemented in vastly more hardware than implements 'real'.
>>
>>
>> It's implemented in GPUs, sure, but it is it implemented in hardware that D runs on? (I do know about this: http://gcc.gnu.org/onlinedocs/gcc/Half_002dPrecision.html)
>>
>> There is no major technical difficulty in implementing it as a basic type, but I want to be sure we've exhausted the library approach first.
>
>
> Well it's available in hardware on basically all mobile devices (that's a
> LOT of devices (in the billions)), but even if it's just implemented in
> software (x86), the values are consumed by the GPU, and the validity of the
> values is no less important. It still seems like a valuable 1st class type;
> why shouldn't it enjoy the same casting, assignment, literal, range checking
> rules as the rest of the floats? Additionally, convenience and compatibility
> with generic code would be significantly improved.
> I don't see how it can be made to feel seamless with a lib... and that
> sounds like an awful lot more work.
>
>
> Anyway, I'm not desperate for this personally. I just wondered how people felt about it in general, and if it was something that should/would be seriously considered.

I'm neither here nor there.  I'm just pointing out that you are proposing a dedicated type to be introduced that is supported on only one platform. :-)


-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
November 19, 2012
On 19 November 2012 19:28, Iain Buclaw <ibuclaw@ubuntu.com> wrote:

> On 19 November 2012 16:04, Manu <turkeyman@gmail.com> wrote:
> > On 19 November 2012 06:19, Walter Bright <newshound2@digitalmars.com>
> wrote:
> >>
> >> On 11/18/2012 4:31 PM, Manu wrote:
> >>>
> >>> If I told you this is how real should be implemented, would you vote
> ++?
> >>> What
> >>> about double? Why?
> >>> Why not float for that matter? There seems like no reason for the
> >>> language to
> >>> define any floating point type at all if you consider this
> acceptable...
> >>
> >>
> >> Because they are implemented in hardware. It's pretty dang hard for a compiler to look at a floating point emulator and figure out "gee, I
> have a
> >> nice hardware instruction that does the same thing as this 2K of code!"
> >
> >
> > Right, and this is my point precisely. It's hard for GDC for instance to hook some complex library because it happens to have hardware to do it.
> >
> >>> 'half' isn't some custom float for niche use, it's an established
> >>> standard,
> >>> implemented in vastly more hardware than implements 'real'.
> >>
> >>
> >> It's implemented in GPUs, sure, but it is it implemented in hardware
> that
> >> D runs on? (I do know about this:
> >> http://gcc.gnu.org/onlinedocs/gcc/Half_002dPrecision.html)
> >>
> >> There is no major technical difficulty in implementing it as a basic
> type,
> >> but I want to be sure we've exhausted the library approach first.
> >
> >
> > Well it's available in hardware on basically all mobile devices (that's a
> > LOT of devices (in the billions)), but even if it's just implemented in
> > software (x86), the values are consumed by the GPU, and the validity of
> the
> > values is no less important. It still seems like a valuable 1st class
> type;
> > why shouldn't it enjoy the same casting, assignment, literal, range
> checking
> > rules as the rest of the floats? Additionally, convenience and
> compatibility
> > with generic code would be significantly improved.
> > I don't see how it can be made to feel seamless with a lib... and that
> > sounds like an awful lot more work.
> >
> >
> > Anyway, I'm not desperate for this personally. I just wondered how people felt about it in general, and if it was something that should/would be seriously considered.
>
> I'm neither here nor there.  I'm just pointing out that you are proposing a dedicated type to be introduced that is supported on only one platform. :-)
>

real is only supported on one platform (x86, it's deprecated in x64 and x87
will likely be removed/emulated in the future), but I think many here
consider it valuable(?).
And that's not strictly true either, virtually every machine has a GPU, and
host software still has to process data for it. I'm mainly encouraging this
for the sake of correctness/type safety, though hardware support on ARM
would be a particularly nice bonus.

I also wanted to gauge the interest/opposition.


November 19, 2012
On Monday, November 19, 2012 19:57:37 Manu wrote:
> I also wanted to gauge the interest/opposition.

I'd never even _heard_ of half types before this discussion came up. But then again, the same goes for SIMD. And IIRC, there was some sort of function attribute relating to pointers and registers that you or some other gaming person was insisting on a while back, and I'd never heard of it existing in C++ either (as an extension or otherwise). You clearly program in a very different world than I do. I care about high performance in what I do but nothing on _that_ level. I suspect that this is another one of those things that certain folks would really like to have, and most of the rest of us don't have any real interest in and often know nothing about in the first place. I don't know that I really care whether it's added to the language though. I'll leave that sort of decision up to Walter.

If anything, I just find it interesting how many low level things folks like you keep coming up with as must-haves or very strong wants that I've never even heard of and will almost certainly never care about aside perhaps from how having them in D might help D catch on.

- Jonathan M Davis