[FFmpeg-devel] [PATCH 2/2] libavutil: Make changes in softfloat needed for fixed point aac decoder.

Nedeljko Babic Nedeljko.Babic at imgtec.com
Mon Apr 20 15:33:16 CEST 2015


>> -static av_const SoftFloat av_div_sf(SoftFloat a, SoftFloat b){
>> -    a.exp -= b.exp+1;
>> -    a.mant = ((int64_t)a.mant<<(ONE_BITS+1)) / b.mant;
>> -    return av_normalize1_sf(a);
>> +    return av_normalize1_sf((SoftFloat){a.mant, --a.exp});
>                                                    ^^^^^^
>                                                    a.exp - 1

Ok.
I will change this.

>
>>  }
>>  
>>  static inline av_const int av_cmp_sf(SoftFloat a, SoftFloat b){
>> @@ -102,11 +101,18 @@ static inline av_const int av_cmp_sf(SoftFloat a, SoftFloat b){
>>      else    return  a.mant          - (b.mant >> t);
>>  }
>>  
>> +static inline av_const int av_gt_sf(SoftFloat a, SoftFloat b)
>> +{
>> +    int t= a.exp - b.exp;
>> +    if(t<0) return (a.mant >> (-t)) >  b.mant      ;
>> +    else    return  a.mant          > (b.mant >> t);
>> +}
>> +
>>  static inline av_const SoftFloat av_add_sf(SoftFloat a, SoftFloat b){
>>      int t= a.exp - b.exp;
>> -    if      (t <-31) return b;
>> -    else if (t <  0) return av_normalize1_sf((SoftFloat){b.mant + (a.mant >> (-t)), b.exp});
>> -    else if (t < 32) return av_normalize1_sf((SoftFloat){a.mant + (b.mant >>   t ), a.exp});
>> +    if      (t <=-31) return b;
>> +    else if (t <  0) return av_normalize_sf(av_normalize1_sf((SoftFloat){ b.mant + (a.mant >> (-t)), b.exp}));
>> +    else if (t < 32) return av_normalize_sf(av_normalize1_sf((SoftFloat){ a.mant + (b.mant >>   t ), a.exp}));
>>      else             return a;
>>  }
>>  
>> @@ -114,19 +120,146 @@ static inline av_const SoftFloat av_sub_sf(SoftFloat a, SoftFloat b){
>>      return av_add_sf(a, (SoftFloat){ -b.mant, b.exp});
>>  }
>>  
>> -//FIXME sqrt, log, exp, pow, sin, cos
>> +static inline av_const SoftFloat av_recip_sf(SoftFloat a)
>> +{
>> +    int s = a.mant >> 31;
>> +
>> +    a.exp = 1 - a.exp;
>> +    a.mant = (a.mant ^ s) - s;
>> +    a.mant = av_divtbl_sf[(a.mant - 0x20000000) >> 22];
>> +    a.mant = (a.mant ^ s) - s;
>> +
>> +    return a;
>> +}
>> +
>
>> +static av_always_inline SoftFloat av_div_sf(SoftFloat a, SoftFloat b){
>
>missing documentation

I'll add it.

>is this exact ?
>if not what are the gurantees to the user
>

On our tests
For 80.3% of input values the output is exact
For 19.2% of input values the error is one LSB bit of mantissa
For 0.5% of input values the error is two LSB bits of mantissa

>
>    > +#if 0
>> +    a.exp -= b.exp + 1;
>> +    a.mant = ((int64_t)a.mant<<(ONE_BITS+1)) / b.mant;
>> +    return av_normalize1_sf(a);
>> +#else
>
>enabing this breaks the tests
>

This is av_div_sf as it was before our changes.
I left it here in case someone wants to develop this function based on what it
was before changes.
Of course, it would be better if I just left code history to git...
Maybe it would be best if I just remove this.

>
>also is it really an advantage to have this av_always_inline ?
>it looks a bit big for always inlining it
>

I guess it depends on compiler and the system on which this will be used.
In any case I suppose that there will not be great performance loss if I remove
av_always_inline.

>
>> +    SoftFloat res;
>> +    SoftFloat iB, tmp;
>> +
>> +    if (b.mant != 0)
>> +    {
>> +        iB = av_recip_sf(b);
>> +        /* Newton iteration to double precision */
>> +        tmp = av_sub_sf(FLOAT_1, av_mul_sf(b, iB));
>> +        iB = av_add_sf(iB, av_mul_sf(iB, tmp));
>> +        tmp = av_sub_sf(FLOAT_1, av_mul_sf(b, iB));
>> +        iB = av_add_sf(iB, av_mul_sf(iB, tmp));
>> +        tmp = av_sub_sf(FLOAT_1, av_mul_sf(b, iB));
>> +        iB = av_add_sf(iB, av_mul_sf(iB, tmp));
>> +        res = av_mul_sf(a, iB);
>> +    }
>> +    else
>> +    {
>> +        /* handle division-by-zero */
>> +        res.mant = 1;
>> +        res.exp = 0x7FFFFFFF;
>> +    }
>> +
>> +    return res;
>> +#endif
>> +}
>> +
>> +//FIXME log, exp, pow
>>  
>
>>  static inline av_const SoftFloat av_int2sf(int v, int frac_bits){
>> -    return av_normalize_sf((SoftFloat){v, ONE_BITS-frac_bits});
>> +    return av_normalize_sf((SoftFloat){v, frac_bits});
>>  }
>
>missing documentation

I'll add it.

>also please make sure that the parameters make some logic sense
>and do not depend on the precission choosen by the implementation
>
>so a "1.0" shwould be generated from the same arguments no matter
>what the precision used in the implementation is

I am not sure I understand you on this.

Basic implementation of this function is the same as in original except
"ONE_BITS-frac_bits" is changed with "frac_bits".
This was done since algorithm is adjusted to be usable in implementation
of fixed point aac decoder.

Thanks,
Nedeljko


More information about the ffmpeg-devel mailing list