short to single precision floating point conversion
Started by ●December 31, 2005
Reply by ●January 7, 20062006-01-07
Hi Shlomo,
In fact it's very simple, don't take it too serious.
First (by an example), try a small piece of code:
float r0, r1;
r0 = _rcpsp (32768.0) - 1.0/32768.0;
r1 = _rcpsp (32767.0) - 1.0/32767.0;
You'll see the difference at once! The first input is 2**15, the second
one is 2**15-1. The trick is there :)
Second,
> As you correctly said,
> the Newton-Raphson iteration results in a reciprocal accurate to 8 bits.
no, I never said *exactly* this! NR method can produce an arbitrary number
of correct bits, which depends on the number of iterations performed.
Assume we have 1 correct bit as the iteration 0. Each NR iteration
effectively doubles the number of correct bits, therefore on the first
iteration we'd have 2 correct bits, on the second it'd be four, etc.
Third is a corollary of (1), or better, (1) is the corollary of (3):
> What is the significance of " ... the floating point
> representation of 2**(-15) does not have non-zero bits in the significand
> at all ..."
your algorithm needs a floating point reciprocal of 2**15, which is
of course 2**(-15). You approximate it by the intrinsic _rcpsp(x),
which returns an 8 bit accurate estimate of a single precision number's
reciprocal.
The floating point representation of 2**(-15) is
0 112 1.000...000 , there are 23 zeros in the fractional
part, therefore the 8 bit reciprocal estimate of 2**15 is as good as 1 bit,
2 bits, 12 bits, it produces the right result for this number.
Certainly, this is not so with other numbers, that are not powers of 2.
Had you needed a reciprocal of 3, just a single _rcpsp() would not have
been enough for that.
On the other hand, there are numbers that are not powers of 2, like 2/3,
and yet a single _rcpsp() would yuild a correct result for them.
Regards,
Andrew
> Date: 06-Jan-2006 16:25:18 -0800
> From: Shlomo K. <shlomo_kashani@shlo...>
> To: Andrew Nesterov <andrew.nesterov@andr...>, c6x@c6x@...
> Subject: Re: [c6x] Re: short to single precision floating point conversion
>
> Andrew,
> The build in C67xx library function _rcpsp maps directly to the assembly
> instruction rcpsp which is used to approximate 1/X. As you correctly said,
> the Newton-Raphson iteration results in a reciprocal accurate to 8 bits.
> Actually, I was neither aware of the error I have done nor have I understood
> your explanation. What is the significance of " ... the floating point
> representation of 2**(-15) does not have non-zero bits in the significand at
> all ..."
>
> Thanks,
> Shlomo.
>
> Andrew Nesterov <andrew.nesterov@andr...> wrote:
>
> It's often quite amazing for me of how well the world's been constructed,
> except, of course, the Windows OS :)
>
> You've been used a wrong method with "good" data, that's why you never
> spotted the error. I might be wrong here and you might quite well know
> what's the trick, but just in case look at the Table 8?5. TMS320C6700
> C/C++ Compiler Intrinsics in spru187 :)
>
> The problem is that _rscsp() returns only an 8 bit correct reciprocal
> estimate to a number further used in N-R type iterations. The "good"
> thing is that the floating point representation of 2**(-15) does not
> have non-zero bits in the significand at all :) That's why the 8 bit
> good approximation is exact for any number of bit in mantissa.
>
> Regards,
>
> Andrew
>
> P.S. Sorry, last time I kind of "foobar"-ed the subject line...
>
>> Date: Wed, 04 Jan 2006 19:04:03 -0000
>> From: "shlomo_kashani"
>> Subject: Re: Digest Number 1358
>>
>> Dear Andrew,
>> Thanks for the reply.
>>
>> Invocation of the _rcpsp(32678) function returns a single precision
>> floating point value of normalizedScale=3.0517578125e-5 which is
>> later used for the conversion and is the value you have quoted.
>> I did not define 3.051758e-05 as a constant ... I used whatever the
>> function was returning ... it was the fault of the "watch window"
>> which ignored the last 3 bits (125). I DID use the correct value, the
>> code comment was just showing the value from the watch window.
>> Anyway, thanks for pointing that out.
>>
>> Shlomo.
>>
>>
>> --- In c6x@c6x@..., Andrew Nesterov
>> wrote:
>>>
>>>
>>> Happy New Year to all.
>>>
>>>> Date: Mon, 2 Jan 2006 17:51:16 -0800 (PST)
>>>> From: "Shlomo K."
>>>> Subject: Re: short to single precision floating point conversion
>>>>
>>>> I followed your suggestion to use x_n = ldexpf (x_n, -15); I am
>> just not
>>>> sure that this library routine is faster then multiplication on
>> the C6711.
>>>
>>> In this very patricular case calling ldepf() is absolutely waste of
>> time.
>>> Sorry.
>>>
>>> If you know for sure that there are no floating point exact zeroes
>> in your
>>> data, you can subtract 15 from the exponent bits of the floating
>> point number
>>> to be scaled, which takes only 1 cycle of the CPU time.
>>>
>>> Alternatively, if you are not sure about exact zeroes, modify your
>> factor
>>>
>>>> float normalizedScale=0.0f;
>>>> /* Updated in lmsInit to 3.051758e-05 */
>>>
>>> to be 3.0517578125e-5, which is *exact* 1/32768 in floating point
>>> (check the hex masks) and scale by this factor. It takes 4 cycles.
>>> The value you've used so far is not an exact reciprocal of 32768,
>>> so when you convert back by multiplying by 32768, you've got
>>> incorrect results.
>>>
>>> Rgds,
>>>
>>> Andrew
>>>
>>
> >
>
> ---------------------------------
> Yahoo! Photos
> Ring in the New Year with Photo Calendars. Add photos, events, holidays, whatever.
Reply by ●January 16, 20062006-01-16
Shlomo-
> Thanks again. I am trying to work on an offline version of the
> algorithm with data exported from a PCM file using MATLAB. One issue is
> I have 3 WAV signals read into the vectors d, v1 and v2 and I mix d +v1
> to the LEFT channel and v2 goes to the RIGHT channel. When I add the
> two signals d+v1, in MATLAB I have values larger then 32768 which are
> an undesired result. What would be the best way to avoid the overflow?
This is sometimes referred to in audio/acoustic systems as "down-mix" or
"monauralizing". The most common method to downmix to a mono channel is something
like:
(a*L + b*R)/2, where a+b = 1
You can extend that to tri-input. Algorithms like DTS, Dolby AC-3, etc can get very
sophisticated, using frequency domain and encoded channel techniques.
> I tried attenuating the signals by a -6dB boost but the generated sound
> file is faint. I also tried normalizing the resulting file by dividing
> by the max value.
Normalization on file basis would be Ok for simulation purposes, but in a real-time
system you'd have to modify that to use a long-term averaging filter to find the
"local maximum". That value would be changing based on content, something like an
AGC circuit.
-Jeff
> Thanks again. I am trying to work on an offline version of the
> algorithm with data exported from a PCM file using MATLAB. One issue is
> I have 3 WAV signals read into the vectors d, v1 and v2 and I mix d +v1
> to the LEFT channel and v2 goes to the RIGHT channel. When I add the
> two signals d+v1, in MATLAB I have values larger then 32768 which are
> an undesired result. What would be the best way to avoid the overflow?
This is sometimes referred to in audio/acoustic systems as "down-mix" or
"monauralizing". The most common method to downmix to a mono channel is something
like:
(a*L + b*R)/2, where a+b = 1
You can extend that to tri-input. Algorithms like DTS, Dolby AC-3, etc can get very
sophisticated, using frequency domain and encoded channel techniques.
> I tried attenuating the signals by a -6dB boost but the generated sound
> file is faint. I also tried normalizing the resulting file by dividing
> by the max value.
Normalization on file basis would be Ok for simulation purposes, but in a real-time
system you'd have to modify that to use a long-term averaging filter to find the
"local maximum". That value would be changing based on content, something like an
AGC circuit.
-Jeff






