Jump to page: 1 24  
Page
Thread overview
half datatype?
Nov 18, 2012
Manu
Nov 18, 2012
Zoadian
Nov 18, 2012
ponce
Nov 18, 2012
David Nadlinger
Nov 18, 2012
Manu
Nov 18, 2012
Manu
Nov 19, 2012
Manu
Nov 18, 2012
Dmitry Olshansky
Nov 18, 2012
Manu
Nov 18, 2012
Dmitry Olshansky
Nov 18, 2012
Iain Buclaw
Nov 18, 2012
Robert Jacques
Nov 19, 2012
Manu
Nov 19, 2012
Walter Bright
Nov 19, 2012
Manu
Nov 19, 2012
Walter Bright
Nov 19, 2012
Iain Buclaw
Nov 19, 2012
Manu
Nov 19, 2012
Iain Buclaw
Nov 18, 2012
Robert Jacques
Nov 19, 2012
Jonathan M Davis
Nov 19, 2012
Rob T
Nov 19, 2012
Walter Bright
Nov 20, 2012
Jonathan M Davis
Nov 20, 2012
Manu
Nov 20, 2012
Manu
Nov 20, 2012
Jacob Carlborg
Nov 20, 2012
Manu
Nov 20, 2012
Era Scarecrow
Nov 21, 2012
Kagamin
Nov 20, 2012
Rob T
Nov 19, 2012
monarch_dodra
Nov 20, 2012
Don Clugston
November 18, 2012
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?


November 18, 2012
+1

i'm using halffloat regularly, would be nice to have them builtin.
November 18, 2012
I tend to agree with your aguments, because the half type could
be very useful to reduce memory usage of data stored as float for
lack of a smaller type.

> 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)...

For better or worse, you can use a wrapper type around this
ushort:
https://github.com/p0nce/gfm/blob/master/math/half.d

> 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.

When I first implemented half floats in D I came to the same
conclusion. Built-ins types have implicit conversion but one
can't define new ones.

Yet it's a trade-off probably choosen for good reasons. How to
make sure people won't abuse them? What to do with chained
implicit conversions?



November 18, 2012
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?

David
November 18, 2012
11/18/2012 3:21 PM, Manu пишет:
> 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.

I guess half(someFloat) will do for conversion.

>
> 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.

alias this should work.
Just tried it, works wonders:

import std.math;

struct half{
    ushort data; //this one should be __fp16 where it works
//other overloaded ops, etc.

    alias getFloat this;
    //***only for the purpose of showing implicit conversion ***
    float getFloat(){ return data * 0.1; }
}

void main(){
    float x = half(12);
    assert(abs(x - 1.2) < 1e-6);
}

> 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?

Everything but hardware support is doable as is. I'm not sure if it's possible and/or feasible to make _efficient_ wrapper type that uses hardware support.

The easiest path seems to be:
- convince GDC to add __fp16 type as an extension that maps to GCC's one
- use it on GDC, and fallback to emulation on DMD

That being said I personally have no objections to add half type to built-ins in DMD.

-- 
Dmitry Olshansky
November 18, 2012
On 18 November 2012 14:01, David Nadlinger <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.


November 18, 2012
On 18 November 2012 14:13, Dmitry Olshansky <dmitry.olsh@gmail.com> wrote:

> 11/18/2012 3:21 PM, Manu пишет:
>
>> 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.
>>
>
> I guess half(someFloat) will do for conversion.


How do you define 'will do'? It still behaves differently than proper types.
someFloat = someDouble without a cast is a compile error, likewise should
be true in this case, but I don't know how to do that.
someHalf = someFloat should require an explicit cast too, or use a 1.0h
literal ;)

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.
>>
>
> alias this should work.
> Just tried it, works wonders:
>
> import std.math;
>
> struct half{
>     ushort data; //this one should be __fp16 where it works
> //other overloaded ops, etc.
>
>     alias getFloat this;
>     //***only for the purpose of showing implicit conversion ***
>     float getFloat(){ return data * 0.1; }
> }
>
> void main(){
>     float x = half(12);
>     assert(abs(x - 1.2) < 1e-6);
>
> }
>

Yup, that solves the up-cast problem perfectly! I didn't think of that trick.

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?
>>
>
> Everything but hardware support is doable as is. I'm not sure if it's possible and/or feasible to make _efficient_ wrapper type that uses hardware support.
>
> The easiest path seems to be:
> - convince GDC to add __fp16 type as an extension that maps to GCC's one
> - use it on GDC, and fallback to emulation on DMD
>
> That being said I personally have no objections to add half type to built-ins in DMD.


I'm sure it's already accessible in GDC, but it's not portable unless it
gets a proper name in the front end.
The point would be to name the type, add the conversion functions to
druntime for fallback/portability, and a literal 1.0h would be handy to
identify the type to templates.


November 18, 2012
11/18/2012 4:41 PM, Manu пишет:
>         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.
>
>
>     I guess half(someFloat) will do for conversion.
>
>
> How do you define 'will do'? It still behaves differently than proper types.
> someFloat = someDouble without a cast is a compile error, likewise
> should be true in this case, but I don't know how to do that.
> someHalf = someFloat should require an explicit cast too, or use a 1.0h
> literal ;)

The point was it does now. Wrapper struct doesn't accept direct assignments from float (unless you want it to and defined opAssign to do that).

alias this trick makes it magical r-value of type float where it makes sense. Obviously on assignment it doesn't ;)

In code:
half myHalf = half(1.23);
myHalf = 35; //doesn't compile
myHalf = half(35); //works

The example though demonstrates one painful limitation of a wrapper - no value range propagation. Basically since 35 fits into a half, no explicit cast should be needed.

And that's a big deal sometimes:
ubyte flags = 0x80 | 0x40; //no casts, thank God

>     Everything but hardware support is doable as is. I'm not sure if
>     it's possible and/or feasible to make _efficient_ wrapper type that
>     uses hardware support.
>
>     The easiest path seems to be:
>     - convince GDC to add __fp16 type as an extension that maps to GCC's one
>     - use it on GDC, and fallback to emulation on DMD
>
>     That being said I personally have no objections to add half type to
>     built-ins in DMD.
>
>
> I'm sure it's already accessible in GDC,

Good to know.

> The point would be to name the type, add the conversion functions to
> druntime for fallback/portability, and a literal 1.0h would be handy to
> identify the type to templates.

Mmm the literal. Dunno but '1h' looks like 1 hour to me :)

Another trick to pull is to use UFCS:

@property auto hf(T)(T value)
if(isFloatingPoint!T || isIntegral!T)
{
	return half(value);
}

Then 1.0.hf && 32.hf both should work. Not as nice as true suffix but damn close.


-- 
Dmitry Olshansky
November 18, 2012
On 18 November 2012 12:41, Manu <turkeyman@gmail.com> wrote:
> On 18 November 2012 14:13, Dmitry Olshansky <dmitry.olsh@gmail.com> wrote:
>>
>> 11/18/2012 3:21 PM, Manu пишет:
>>>
>>> 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.
>>
>>
>> I guess half(someFloat) will do for conversion.
>
>
> How do you define 'will do'? It still behaves differently than proper types.
> someFloat = someDouble without a cast is a compile error, likewise should be
> true in this case, but I don't know how to do that.
> someHalf = someFloat should require an explicit cast too, or use a 1.0h
> literal ;)
>
>>> 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.
>>
>>
>> alias this should work.
>> Just tried it, works wonders:
>>
>> import std.math;
>>
>> struct half{
>>     ushort data; //this one should be __fp16 where it works
>> //other overloaded ops, etc.
>>
>>     alias getFloat this;
>>     //***only for the purpose of showing implicit conversion ***
>>     float getFloat(){ return data * 0.1; }
>> }
>>
>> void main(){
>>     float x = half(12);
>>     assert(abs(x - 1.2) < 1e-6);
>>
>> }
>
>
> Yup, that solves the up-cast problem perfectly! I didn't think of that trick.
>
>>> 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?
>>
>>
>> Everything but hardware support is doable as is. I'm not sure if it's possible and/or feasible to make _efficient_ wrapper type that uses hardware support.
>>
>> The easiest path seems to be:
>> - convince GDC to add __fp16 type as an extension that maps to GCC's one
>> - use it on GDC, and fallback to emulation on DMD
>>
>> That being said I personally have no objections to add half type to built-ins in DMD.
>
>
> I'm sure it's already accessible in GDC, but it's not portable unless it
> gets a proper name in the front end.
> The point would be to name the type, add the conversion functions to
> druntime for fallback/portability, and a literal 1.0h would be handy to
> identify the type to templates.

The two modes guaranteed to exist in GDC are single and double (reals
could be a vagarity of sizes).  Half I believe is only defined
(internally) for ARM.

-- 
Iain Buclaw

*(p < e ? p++ : p) = (c & 0x0f) + '0';
November 18, 2012
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
« First   ‹ Prev
1 2 3 4