floating cast different than float pointer cast?

14 views
Skip to first unread message

Valcortez

unread,
Mar 9, 2018, 2:41:35 PM3/9/18
to cython-users
Hi,

I have a unsigned int which is actually a c float (4 bytes) and needs to be casted to float and then sent to python. However, I get different values depending on whether I cast it as float or cast as a float pointer and then read the value. Here's the code:

def get_cam_abs_setting_value(self, offset):
    cdef
unsigned int value = self.get_register(offset + 0x8)
   
return (<float *>&value)[0], <float>value, value



This print (8.016032218933105, 1090535808.0, 1090535851). The first value is the correct decimal value. The middle one is incorrect. Did I forget something about c type casting or is this a cython issue?

For reference, the generated code is:

 /* "pyflycap2/interface.pyx":388
 *

 *         cdef unsigned int value = self.get_register(offset + 0x8)
 *         return (<float *>&value)[0], <float>value, value             # <<<<<<<<<<<<<<
 *
 *     def set_cam_abs_setting_value(self, setting, value):
 */

  __Pyx_XDECREF
(__pyx_r);
  __pyx_t_3
= PyFloat_FromDouble((((float *)(&__pyx_v_value))[0])); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 388, __pyx_L1_error)
  __Pyx_GOTREF
(__pyx_t_3);
  __pyx_t_4
= PyFloat_FromDouble(((float)__pyx_v_value)); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 388, __pyx_L1_error)
  __Pyx_GOTREF
(__pyx_t_4);
  __pyx_t_5
= __Pyx_PyInt_From_unsigned_int(__pyx_v_value); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 388, __pyx_L1_error)
  __Pyx_GOTREF
(__pyx_t_5);
  __pyx_t_7
= PyTuple_New(3); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 388, __pyx_L1_error)
  __Pyx_GOTREF
(__pyx_t_7);
  __Pyx_GIVEREF
(__pyx_t_3);
 
PyTuple_SET_ITEM(__pyx_t_7, 0, __pyx_t_3);
  __Pyx_GIVEREF
(__pyx_t_4);
 
PyTuple_SET_ITEM(__pyx_t_7, 1, __pyx_t_4);
  __Pyx_GIVEREF
(__pyx_t_5);
 
PyTuple_SET_ITEM(__pyx_t_7, 2, __pyx_t_5);
  __pyx_t_3
= 0;
  __pyx_t_4
= 0;
  __pyx_t_5
= 0;
  __pyx_r
= __pyx_t_7;
  __pyx_t_7
= 0;
 
goto __pyx_L0;


Robert Bradshaw

unread,
Mar 9, 2018, 2:54:08 PM3/9/18
to cython...@googlegroups.com
On Fri, Mar 9, 2018 at 11:41 AM, Valcortez <moiei...@gmail.com> wrote:
> Hi,
>
> I have a unsigned int which is actually a c float (4 bytes) and needs to be
> casted to float and then sent to python. However, I get different values
> depending on whether I cast it as float or cast as a float pointer and then
> read the value. Here's the code:
>
> def get_cam_abs_setting_value(self, offset):
> cdef unsigned int value = self.get_register(offset + 0x8)
> return (<float *>&value)[0], <float>value, value

This is exactly as it works in C. The statement

(<float *>&value)[0]

says take the address that stores the integer "value", treat it as if
the memory pointed to (these four bytes) were a float rather than an
integer, and then return that float value. A cast like <float>value
invokes a conversion, e.g. <float>1 is 1.0, regardless of what the
underlying representation is in bytes.

It's unclear why you would ever get the bytes of a c float as an
unsigned int, but in that case the re-interpretation of these bytes
via casting the pointer pointer is the correct thing to do.
> --
>
> ---
> You received this message because you are subscribed to the Google Groups
> "cython-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to cython-users...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Valcortez

unread,
Mar 9, 2018, 3:19:01 PM3/9/18
to cython-users
On Friday, March 9, 2018 at 2:54:08 PM UTC-5, Robert Bradshaw wrote:
On Fri, Mar 9, 2018 at 11:41 AM, Valcortez <moiei...@gmail.com> wrote:
> Hi,
>
> I have a unsigned int which is actually a c float (4 bytes) and needs to be
> casted to float and then sent to python. However, I get different values
> depending on whether I cast it as float or cast as a float pointer and then
> read the value. Here's the code:
>
> def get_cam_abs_setting_value(self, offset):
>     cdef unsigned int value = self.get_register(offset + 0x8)
>     return (<float *>&value)[0], <float>value, value

This is exactly as it works in C. The statement

(<float *>&value)[0]

says take the address that stores the integer "value", treat it as if
the memory pointed to (these four bytes) were a float rather than an
integer, and then return that float value. A cast like <float>value
invokes a conversion, e.g. <float>1 is 1.0, regardless of what the
underlying representation is in bytes.

It's unclear why you would ever get the bytes of a c float as an
unsigned int, but in that case the re-interpretation of these bytes
via casting the pointer pointer is the correct thing to do.


Hmm, I guess I forgot how c casting works. I thought the normal cast was the same as a pointer cast.
The reason I have a float represented as an integer is that I'm reading it from a device's registry which represents
everything as unsigned ints.

Thanks!
Reply all
Reply to author
Forward
0 new messages