From: linnix on
On Mar 23, 6:51 pm, Grant Edwards <inva...(a)invalid.invalid> wrote:
> On 2010-03-24, Jamie <jamie_ka1lpa_not_valid_after_ka1l...(a)charter.net> wrote:
>
> > Last time I knew, that just cast the object into what you want, but it's
> > not going to magically convert a FLOAT to a unsigned char..
>
> That's exactly what a cast does.  (Though there's nothing magical
> about the conversion -- it's a well-defined operation.)
>
> >   Its only going to instruct the compiler that the contents of memory the
> > "F" occupies is a unsigned char and simply moves the data from that
> > from ever it is in memory to "u"
>
> No, it isn't.  It instructs the compiler to do the conversion.
>
> >    simply speaking..
> >     u = f; isn't the same as u = (unsigned char) f; where I come from..
>
> I'm not sure where you come from. Here on Earth, when using the C
> language, it's exactly the same.
>
> Here's an example program:
>
>    extern volatile unsigned char u1,u2;
>    extern volatile float f;
>
>    void foo1(void)
>    {
>      u1 = f;
>    }
>
>    void foo2(void)
>    {
>      u2 = (unsigned char)f;
>    }
>
> And here's the generated code using gcc for IA32.  Note that the code
> generated for the two cases is identical:
>
>            .file   "testit.c"
>            .text
>            .p2align 4,,15
>    .globl foo1
>            .type   foo1, @function
>    foo1:
>            subl    $8, %esp
>            fnstcw  6(%esp)
>            flds    f
>            movzwl  6(%esp), %eax
>            movb    $12, %ah
>            movw    %ax, 4(%esp)
>            fldcw   4(%esp)
>            fistps  2(%esp)
>            fldcw   6(%esp)
>            movzwl  2(%esp), %eax
>            movb    %al, u1
>            addl    $8, %esp
>            ret
>            .size   foo1, .-foo1
>            .p2align 4,,15
>    .globl foo2
>            .type   foo2, @function
>    foo2:
>            subl    $8, %esp
>            fnstcw  6(%esp)
>            flds    f
>            movzwl  6(%esp), %eax
>            movb    $12, %ah
>            movw    %ax, 4(%esp)
>            fldcw   4(%esp)
>            fistps  2(%esp)
>            fldcw   6(%esp)
>            movzwl  2(%esp), %eax
>            movb    %al, u2
>            addl    $8, %esp
>            ret
>            .size   foo2, .-foo2
>            .ident  "GCC: (Gentoo 4.3.4 p1.0, pie-10.1.5) 4.3.4"
>            .section        .note.GNU-stack,"",@progbits
>
> >   And the last time I knew, AVR's do not have native support for
> > floating point math. UNless I've been out of the loop here?
>
> Doesn't matter.
>
> >     Instead, the compiler should be loading a default RTL that contains
> > low level code to give you that results.. This of course is compiler
> > linked and thus, makes it look natural to you, the coder.
>
> No idea what your point is.
>
> >    And if the C compiler is standardized like most other compilers...
>
> >   u = (unsigned char) f; simply tells the compiler to treat the object
> >   of "F" as if it was a char instead. No conversion is taking
> > place here.
>
> Yes, a conversion _is_ taking place here.  That's what a cast _is_:
> it's an explicit conversion operation.
>
> >     As far as how the floats are implemented for the binary format of
> > this compiler will dictate what value of data will be returned..
>
> No, it won't.  It will take the integer portion of the float value and
> store that value (modulo 256) into the unsigned char.
>
> >    I can only assume it may support the Mantissa and other elements
> > of a floating point number, in which case, the above will not work as
> > you may think..
> >    But who am I, I don't know anything..
>
> I wouldn't say you don't know anything, but you don't seem to know
> what a typecast does in a C program.
>
> >   stick with the "u = f;" and the compiler should be happy with that
> > and call one of it's floattointeger conversion TRL functions.. But If
> > you want to know how the float if constructed to represent a floating
> > point number, I guess you could hack it with the cast. I think only
> > the authors of the compiler would understand it's meanings..
>
> A typecast doesn't to at all what you think it does.
>
> --
> Grant

And here is the AVR version for foo1, foo2 is identical except for the
labels. Trust me.

..global foo1
.type foo1, @function
foo1:
push r29
push r28
in r28,__SP_L__
in r29,__SP_H__
/* prologue: function */
/* frame size = 0 */
lds r24,f
lds r25,(f)+1
lds r26,(f)+2
lds r27,(f)+3
movw r22,r24
movw r24,r26
call __fixunssfsi
movw r26,r24
movw r24,r22
sts u1,r24
/* epilogue start */
pop r28
pop r29
ret
From: David Brown on
On 24/03/2010 03:09, Jamie wrote:
> linnix wrote:
>
>> On Mar 23, 12:35 pm, Hans-Bernhard Br�ker <HBBroe...(a)t-online.de>
>> wrote:
>>
>>> Albert van der Horst wrote:
>>>
>>>
>>>> In article <4ba32898$0$22919$e4fe5...(a)news.xs4all.nl>,
>>>> Meindert Sprang <m...(a)NOJUNKcustomORSPAMware.nl> wrote:
>>>>
>>>>> Apart from that, as others have said, u = f should have worked too
>>>>> when the integer part of f is in the range of 0-255.
>>
>>
>> Yes, and we will scale f to fit within 255 first. We are only
>> interested in relative magnitude of an array.
>>
>>
>>>> It works on any integer.
>>>
>>> No, it doesn't. That's been clarified days ago in this thread.
>>>
>>>
>>>> Unsigned char's are supposed to work modulo
>>>> their range.
>>>
>>> Yes, but that only applies once you _have_ an unsigned char. The
>>> problem under consideration doesn't have one --- it's trying to build
>>> one.
>>>
>>>
>>>> Now I think
>>>> u = (unsigned char) f;
>>>> is brain damaged.
>>>
>>> You think incorrectly, there.
>>
>>
>> The compiler is smart enough to understand "u = f or i = f" as well.
>> The casting is for human reading the code. It may be unnecessary, but
>> not brain damaged.
>>
>>
>>>> This tells the compiler to convert the float converted to an integer,
>>>> then take it modulo 256.
>>>
>>> No, it doesn't. It instructs the compiler to generate code that does
>>> exactly what the code says: convert the float to an unsigned char.
>>> That's another thing that has been clarified days ago.
>>
>>
>> It is mainly for storage. Unsigned char (8 bits) takes less space than
>> float (16 bits) or double (32 bits). We don't really care how the
>> compiler does it, but storage is important for a 1K SRAM chip.
>>
> Last time I knew, that just cast the object into what you want, but it's
> not going to magically convert a FLOAT to a unsigned char..
> Its only going to instruct the compiler that the contents of memory the
> "F" occupies is a unsigned char and simply moves the data from that from
> ever it is in memory to "u"
> simply speaking..
> u = f; isn't the same as u = (unsigned char) f; where I come from..
>

You are getting this entirely wrong. When you assign an expression of
one type to a lvalue of another type, there is always a cast. These two
assignments are always the same:

x = exp;
x = (typeof(x)) exp;

The OP wrote out the cast explicitly to make his code clearer - that's
good programming practice.


You are mixing this up with pointer casts. Casting a float to an int
(of any size and signedness) causes a proper conversion. But casting a
pointer to a float to a pointer to an int accesses the memory contents
without any interpretation. To get the effect you are worried about
here, you must write :

u = *((unsigned char *) &f);

But of course that's not what the OP wanted, so it's not what he wrote.

> And the last time I knew, AVR's do not have native support for floating
> point math. UNless I've been out of the loop here?
> Instead, the compiler should be loading a default RTL that contains low
> level code to give you that results.. This of course is compiler linked
> and thus, makes it look natural to you, the coder.
>

It doesn't make any difference whether floating point is implemented in
a hardware FPU or with software functions. The compiler (and library)
give you the same functionality for floats and doubles regardless of the
underlying implementation.

Clearly the implementation makes a difference for speed. It /may/ make
a difference if your code relies on the underlying format and your
toolset uses a non-IEEE format. But that would be a weird piece of
source code, and an unusual compiler - most compilers, including
avr-gcc, use IEEE format for their software floating point. It /may/
also make a difference if you are looking for IEEE corner-case
functionality - NaNs, signed zeros, rounding modes, etc. But again,
that's not the case in most software.

> And if the C compiler is standardized like most other compilers..
>

avr-gcc is as standard as it gets - but what you are describing is /not/
standard C behaviour.

> u = (unsigned char) f; simply tells the compiler to treat the object
> of "F" as if it was a char instead. No conversion is taking
> place here.
> As far as how the floats are implemented for the binary format of this
> compiler will dictate what value of data will be returned..
>
> I can only assume it may support the Mantissa and other elements of a
> floating point number, in which case, the above will not work as you may
> think..
> But who am I, I don't know anything..
>

I'm not going to generalise, but you are certainly getting this one wrong.

> stick with the "u = f;" and the compiler should be happy with that and
> call one of it's floattointeger conversion TRL functions.. But If you
> want to know how the float if constructed to represent a floating point
> number, I guess you could hack it with the cast. I think only the
> authors of the compiler would understand it's meanings..
>
>
>

From: Albert van der Horst on
In article <hob8mg$b1c$02$1(a)news.t-online.com>,
=?ISO-8859-1?Q?Hans-Bernhard_Br=F6ker?= <HBBroeker(a)t-online.de> wrote:
>Albert van der Horst wrote:
>> In article <4ba32898$0$22919$e4fe514c(a)news.xs4all.nl>,
>> Meindert Sprang <ms(a)NOJUNKcustomORSPAMware.nl> wrote:
>
>>> Apart from that, as others have said, u = f should have worked too
>>> when the integer part of f is in the range of 0-255.
>
>> It works on any integer.
>
>No, it doesn't. That's been clarified days ago in this thread.
>
>> Unsigned char's are supposed to work modulo
>> their range.
>
>Yes, but that only applies once you _have_ an unsigned char. The
>problem under consideration doesn't have one --- it's trying to build one.
>
>> Now I think
>> u = (unsigned char) f;
>> is brain damaged.
>
>You think incorrectly, there.
>
>> This tells the compiler to convert the float converted to an integer,
>> then take it modulo 256.
>
>No, it doesn't. It instructs the compiler to generate code that does
>exactly what the code says: convert the float to an unsigned char.
>That's another thing that has been clarified days ago.
>

I stand corrected.

iso 9899-1990 c-standard

6.2.1.3
When a value of floating type is converted to an integral type
the fractional part is discarded. If the value of the integral part
cannot be represented by the integral type, the behaviour is undefined.

So undefined would be invoked outside 0.00000-255.99999999999999999

Groetjes Albert

--
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert(a)spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

From: Bob on
linnix wrote:
> On Mar 23, 12:35 pm, Hans-Bernhard Br�ker <HBBroe...(a)t-online.de>
> wrote:

<snip>

>
> It is mainly for storage. Unsigned char (8 bits) takes less space than
> float (16 bits) or double (32 bits). We don't really care how the
> compiler does it, but storage is important for a 1K SRAM chip.
>

Really? I've never run across a 16 bit float. Every compiler I've worked
with uses 32 bits for float (sign, 8 bit exp, 23 bit mantissa w/ implied
MSB) and 64 bits for double. It's been a long time since I read IEEE-754
and it wouldn't surprise me that it allowed for other formats, I've just
never seen them.

Bob
From: linnix on
On Mar 24, 9:27 am, Bob <SkiBoy...(a)excite.com> wrote:
> linnix wrote:
> > On Mar 23, 12:35 pm, Hans-Bernhard Bröker <HBBroe...(a)t-online.de>
> > wrote:
>
> <snip>
>
>
>
> > It is mainly for storage. Unsigned char (8 bits) takes less space than
> > float (16 bits) or double (32 bits).  We don't really care how the
> > compiler does it, but storage is important for a 1K SRAM chip.
>
> Really? I've never run across a 16 bit float. Every compiler I've worked
> with uses 32 bits for float (sign, 8 bit exp, 23 bit mantissa w/ implied
> MSB) and 64 bits for double. It's been a long time since I read IEEE-754
> and it wouldn't surprise me that it allowed for other formats, I've just
> never seen them.
>
> Bob

Yes, my mistake. As you can see in the example, it transferred 4
bytes.

lds r24,f
lds r25,(f)+1
lds r26,(f)+2
lds r27,(f)+3
First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4 5 6 7 8 9 10
Prev: ATI Catalyst 10.3 Preview Edition
Next: Network fabric