Sorry if this is a bit of a numpty question!

With reference to BF561, suppose I have:

a = 0.95 and b = 123

and I do, c = a*b = 116.85

If I am only interested in keeping '116' (so can discard the fraction) what is the best way of doing the math?

Is it still more efficient (due to nature of BF561) to make a & c as fract16 or could I do:

a = 95, b = 123. So c = a*b/100

Or just typecast? Or is there another way altogether?

Thanks Prasanth for your reply.

So, what would the result be of fract16 res = mult_fr1x16(float_to_fr16(0.95),123); --> Is it a fract16 fixed point representation of 116? Or a fixed point representation of 116.85?

I guess what I'm asking, how do I get to the '116' from the result...

And, is the above more efficient than a = 95, b = 123. So c = a*b/100? (Bearing in mind I'm only interested in '116' and can discard the fraction remainder '0.85'.

Message was edited by: hdp

You get a 116 which is a fract16 value. When you multiplied, you actually passed the fract16 values: (2^15) * 0.95 & (2^15) * (123/2^15), so the fractional values you provided were 0.95 & 123/2^15, and therefore you multiplied between the two. When you convert the result 116 from fract16 to fractional value, you get 116/2^15 (which is basically 0.95 * 123/2^15), but since you had 2^15 in denominator during multiplication, you would do a (116/2^15) * (2^15) = 116!.

You basically deal with fract16, emulated float or integer in your algorithm. It is how your represent the data that matters, with each representation having its own reasons for usage in an algorithm. What you realize like a division of 100 is dependent on how it is represented in the processor. If you need to know more about the differences in implementation etc, then I would suggest reading the Programming Ref Manual as well as the Compiler manual (say, for fractional types and builtins as above).

- Prasanth.

VisualDSP++ Update 9 introduces native fractional types to C (not C++), which will make this sort of thing much easlier.

In VisualDSP++, fract16 is really just a typedef to "short", which is why you need various built-in operations to do arithmetic with fractional semantics. However, in Update 9, fract (not fract16) is a true, 16-bit fractional type.

So:

fract16 a = 0.5r16; // really short a = 0x4000

fract16 b = a * a; // really short = short * short - not what you're after.

fract16 c = mult_fr1x16(a, a); // does fractional semantics.

But:

fract x = 0.5r; // really *is* 0.5, fixed-point.

fract y = x * x; // really does do fract * fract, saturating.

VisualDSP++'s fractional implementation is based on ISO/IEC draft document Technical Report 18037, which also defines the type promotions. These promotions aren't useful for mixing integer and fractional operations, since promoting one operand to the type of the other means you lose all the relevant data. However, TR18037 does define mixed-type functions for this purpose. For example, the muli

*fx*() family of functions allows you to multiply an integer value by a fractional value and get an integer result, which is what you want here:#include <stdfix.h>

#include <stdio.h>

int main(void) {

int i = 123;

fract f = 0.95r;

int r = mulir(i, f); // mulir() is the mulifx-variant that takes int and fract parameters.

printf("%d\n", r);

}

The

*Blackfin C/C++ Compiler and Library Manual*contains extensive documentation, in*Using Native Fixed-Point Types*which explains all this in much more detail.

Fractional computation is preferred if you don't want to lose accuracy. You cannot match fixed point result against floating point operations, unless you emulate the same. Emulation consumes cyles, and therefore using a fractional value is more desirable because the end result of a fractional multiplication is again a fractional value.

You could do :: fract16 res = mult_fr1x16(float_to_fr16(0.95),123);

In the above, you are doing a fractional computation with truncation. If you don't do that, then for integer multiplication you need to convert the float value 0.95 to integer, which is 1, but then you loose accuracy, because 123 * 1 is far from 123 * 0.95.

The above is usual the case where you deal with data from ADCs & you perform fract16 computations with the available libraries. Note that fract16 is a typedef of 'short' and it is up to the algorithm to interpret this as a fractional representation.

- Prasanth.