Giving this a little push upwards. Is there really no function that can do that?

10 views (last 30 days)

Show older comments

Hi there,

I am currently having trouble with the above mentioned task. Basically, this is what I want to do:

x = fi(1300,true,11,0) (9bit signed integer)

x.bin = 10100010100

c = fi(0,true,8,0)

c = x.bin(1:8)

c.bin = 10100010

c = 162

In other words: I would like to extract the first 8 bit of x to another variable, which than will have the according value. Does the fixed point toolbox has any function that makes this possible. Everything I tried so far ended up in a requantization of the value, which I don't want.

Any help would be highly appreciated!

Thank you very much!

Regards,

Lennart

Andy Bartlett
on 5 Apr 2021

Two Key Ways

There are two key ways to extract the bits from a fixed-point number.

One way is to use bitsliceget as Walter pointed out.

The other way is to do a cast operation configured for overflows to wrap and rounding toward floor.

Consider the following input value.

a = fi( -5.0625, 1, 8, 4)

The bits of a are the following.

'10101111'

Suppose the goal is to extract the 6 most significant bits from a. This can be done with bitsliceget as follows.

b = bitsliceget( a, 8, 3 )

or using fi to do a cast.

fmWrapFloor = fimath('RoundingMethod', 'Floor', 'OverflowAction', 'Wrap');

c = fi( a, 1, 6, 2, fmWrapFloor )

Both approaches produce the same set of bits in their outputs.

'101011'

But the outputs have different data types and different real world values.

Term bin_SI type RealWorldValue

a 10101111 numerictype(1,8,4) -5.0625

bitsliceget( a, 8, 3 ) 101011 numerictype(0,6,0) 43

fi( a, 1, 6, 2, fmWrapFloor ) 101011 numerictype(1,6,2) -5.25

Using bitsliceget returns the stored integer bits in an unsigned type with no scaling.

Casting using fi will retain the scaling appropriate to the bits. Signedness can be kept or discared as desired. Casting via fi will also attempt to keep the output real world value close to the input real world value to the extent allowed by rounding and overflow. Notice in the example above that the input real world value is -5.0625 and after dropping the least significant two bits the output is rounded to real world value -5.25.

Randomly generated examples

The attached script randomly creates some examples showing the differences. For a example, one run produced this random output examples.

>> example_bitslice

Term bin_SI type RealWorldValue

a 00001110 numerictype(1,8,4) 0.875

bitsliceget( a, 8, 2 ) 0000111 numerictype(0,7,0) 7

bitsliceget( a, 8, 3 ) 000011 numerictype(0,6,0) 3

bitsliceget( a, 8, 4 ) 00001 numerictype(0,5,0) 1

bitsliceget( a, 6, 1 ) 001110 numerictype(0,6,0) 14

bitsliceget( a, 6, 3 ) 0011 numerictype(0,4,0) 3

bitsliceget( a, 3, 1 ) 110 numerictype(0,3,0) 6

Term bin_SI type RealWorldValue

a 00001110 numerictype(1,8,4) 0.875

fi( a, 1, 7, 3, fmWrapFloor ) 0000111 numerictype(1,7,3) 0.875

fi( a, 1, 6, 2, fmWrapFloor ) 000011 numerictype(1,6,2) 0.75

fi( a, 1, 5, 1, fmWrapFloor ) 00001 numerictype(1,5,1) 0.5

fi( a, 1, 6, 4, fmWrapFloor ) 001110 numerictype(1,6,4) 0.875

fi( a, 1, 4, 2, fmWrapFloor ) 0011 numerictype(1,4,2) 0.75

fi( a, 1, 3, 4, fmWrapFloor ) 110 numerictype(1,3,4) -0.125

Term bin_SI type RealWorldValue

a 10101111 numerictype(1,8,4) -5.0625

bitsliceget( a, 8, 2 ) 1010111 numerictype(0,7,0) 87

bitsliceget( a, 8, 3 ) 101011 numerictype(0,6,0) 43

bitsliceget( a, 8, 4 ) 10101 numerictype(0,5,0) 21

bitsliceget( a, 6, 1 ) 101111 numerictype(0,6,0) 47

bitsliceget( a, 6, 3 ) 1011 numerictype(0,4,0) 11

bitsliceget( a, 3, 1 ) 111 numerictype(0,3,0) 7

Term bin_SI type RealWorldValue

a 10101111 numerictype(1,8,4) -5.0625

fi( a, 1, 7, 3, fmWrapFloor ) 1010111 numerictype(1,7,3) -5.125

fi( a, 1, 6, 2, fmWrapFloor ) 101011 numerictype(1,6,2) -5.25

fi( a, 1, 5, 1, fmWrapFloor ) 10101 numerictype(1,5,1) -5.5

fi( a, 1, 6, 4, fmWrapFloor ) 101111 numerictype(1,6,4) -1.0625

fi( a, 1, 4, 2, fmWrapFloor ) 1011 numerictype(1,4,2) -1.25

fi( a, 1, 3, 4, fmWrapFloor ) 111 numerictype(1,3,4) -0.0625

Which approach to use?

Sometimes the intent of a design section is bit oriented. For example, a collection of bits may represent several independent boolean flags. The design intent may be to pack and unpack these bits in to a larger variable. In this case, bitsliceget is a more natural fit to the design intent.

Other times, the intent is oriented towards math operations. As an example, suppose a variable represents the output from an angle sensor with units being revolutions. To efficiently compute trig operations, like cosine, on this variable, it is useful to perform a modulo operation so that the angle is in the closed open interval [0,1). A great advantage to using revolutions, instead of degrees or radians, is that this modulo can be performed by simply dropping all the bits to the left of the variables binary point. Extracting the bits to the right of the binary point could be done with bitsliceget but the scaling would be lost and the real world value of the output would no longer be revolutions. In contrast, casting via fi would preserve the wrapped real world value in revolutions. For math oriented intent, extracting bit using a wrapping floor fi cast is usually a more natural fit.

uAngleRevolutions = fi( 3.2470703125, 0, 16, 10 )

fmWrapFloor = fimath('RoundingMethod', 'Floor', 'OverflowAction', 'Wrap');

modOne_of_uAngleRevolutions = fi( uAngleRevolutions, 0, 10, 10, fmWrapFloor );

modOne_of_uAngleRevolutions = removefimath( modOne_of_uAngleRevolutions )

This outputs

uAngleRevolutions =

3.2470703125

numerictype(0,16,10)

modOne_of_uAngleRevolutions =

0.2470703125

numerictype(0,10,10)

The original angle is three full revolutions around the circle plus roughly an additional quarter revolution. Modulo one of this angle is just the roughly quarter revolution around the circle. Using a wrapping fi cast, performed the module one operation and nicely preserved the real world meaning.

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!