Author Topic: float to int using slightly different magic number (seems unstable)  (Read 8234 times)

0 Members and 1 Guest are viewing this topic.

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
Sorry for dragging up an old topic but looking into float->int again and come up with this:

Code: [Select]
'setup data and unions for floor(float)->short
    union floor_float_to_short_data
        _float_in as double
        type
            _pad as short
            _short_out as short
        end type
    end union
    dim as const double floor_float_to_short_magic = 2^35 + 2^36
'************************************************************************


dim as floor_float_to_short_data floor

floor._float_in = floor_float_to_short_magic + 15000.999992

print floor._short_out

sleep
end

It floors (not perfect but pretty well) a float to a short so it's in the range -32768>32767

After reading your post there Jim I'm now wondering if this can be used with the magic outside the loop now.

EDIT: seems to work fine.
« Last Edit: March 21, 2010 by Stonemonkey »

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
And can now use different magic numbers to give different rounding modes:

Code: [Select]
'setup data types and unions for rounding to short

    union float_to_short
        _float_in as double
        type
            _pad as short
            _short_out as short
        end type
    end union
   
'magic numbers for different rounding modes

    dim as const double floor_float_to_short = 2^35 + 2^36
   
    dim shared as double ceil_float_to_short = 2^35 + 2^36
    *cast ( integer pointer , @ceil_float_to_short ) = 65535

    dim shared as double nearest_float_to_short = 2^35 + 2^36
    *cast ( integer pointer , @nearest_float_to_short ) = 32768


'rounding float to short macros

    dim shared as float_to_short round_to_short

    #macro round_down(my_float,my_short)
        round_to_short._float_in = floor_float_to_short + my_float
        my_short = round_to_short._short_out
    #endmacro

    #macro round_up(my_float,my_short)
        round_to_short._float_in = ceil_float_to_short + my_float
        my_short = round_to_short._short_out
    #endmacro

    #macro round_nearest(my_float,my_short)
        round_to_short._float_in = nearest_float_to_short + my_float
        my_short = round_to_short._short_out
    #endmacro

'**********************************************************************

I'd prefer to make them all consts but I can't see how to put in the data, I guess it won't make much difference anyway since const floats aren't assembled the same way as const ints.

The 'nearest' will always round down xx.5
If you change 32767 to 32768 it'll always round up xx.5

I've still to try it in a real situation but it looks like it's possible to do the interpolation including perspective correction with the magic number added beforehand with the fpu almost acting like 16:16 fixed point and the padding could be split into 2 bytes with the high byte giving the fraction for bi-linear filtering.
« Last Edit: March 21, 2010 by Stonemonkey »

Offline Stonemonkey

  • Pentium
  • *****
  • Posts: 1315
  • Karma: 96
    • View Profile
G_triangle function to draw to any buffer given the start address and the buffer dimensions so can draw to any array or whatever. Not really sure about the speed or accuracy so if anyone finds any problems let me know. It uses the idea from above to have 16:16 fixed point in the low 32 bits of the double. I might have a go at doing this in asm.
« Last Edit: March 27, 2010 by Stonemonkey »