Skip to content
Snippets Groups Projects
Commit a2fd6043 authored by Michael Niedermayer's avatar Michael Niedermayer
Browse files

floating point "emulation" code

unused currently, but might come in handy for some fpu-less cpus

Originally committed as revision 5955 to svn://svn.ffmpeg.org/ffmpeg/trunk
parent bcfa3e58
No related branches found
No related tags found
No related merge requests found
#include <inttypes.h>
#include <stdio.h>
#include <assert.h>
#include "softfloat.h"
#include "common.h"
#include "log.h"
#undef printf
int main(){
SoftFloat one= av_int2sf(1, 0);
SoftFloat sf1, sf2;
double d1, d2;
int i, j;
av_log_level = AV_LOG_DEBUG;
d1= 1;
for(i= 0; i<10; i++){
d1= 1/(d1+1);
}
printf("test1 double=%d\n", (int)(d1 * (1<<24)));
sf1= one;
for(i= 0; i<10; i++){
sf1= av_div_sf(one, av_normalize_sf(av_add_sf(one, sf1)));
}
printf("test1 sf =%d\n", av_sf2int(sf1, 24));
for(i= 0; i<100; i++){
START_TIMER
d1= i;
d2= i/100.0;
for(j= 0; j<1000; j++){
d1= (d1+1)*d2;
}
STOP_TIMER("float add mul")
}
printf("test2 double=%d\n", (int)(d1 * (1<<24)));
for(i= 0; i<100; i++){
START_TIMER
sf1= av_int2sf(i, 0);
sf2= av_div_sf(av_int2sf(i, 2), av_int2sf(200, 3));
for(j= 0; j<1000; j++){
sf1= av_mul_sf(av_add_sf(sf1, one),sf2);
}
STOP_TIMER("softfloat add mul")
}
printf("test2 sf =%d (%d %d)\n", av_sf2int(sf1, 24), sf1.exp, sf1.mant);
return 0;
}
//copyright Michael Niedermayer 2006 license:LGPL
#define MIN_EXP -126
#define MAX_EXP 126
#define ONE_BITS 29
typedef struct SoftFloat{
int32_t exp;
int32_t mant;
}SoftFloat;
static SoftFloat av_normalize_sf(SoftFloat a){
if(a.mant){
#if 1
while((a.mant + 0x20000000U)<0x40000000U){
a.mant += a.mant;
a.exp -= 1;
}
#else
int s=ONE_BITS + 1 - av_log2(a.mant ^ (a.mant<<1));
a.exp -= s;
a.mant <<= s;
#endif
if(a.exp < MIN_EXP){
a.exp = MIN_EXP;
a.mant= 0;
}
}else{
a.exp= MIN_EXP;
}
return a;
}
static inline SoftFloat av_normalize1_sf(SoftFloat a){
#if 1
if(a.mant + 0x40000000 < 0){
a.exp++;
a.mant>>=1;
}
return a;
#elif 1
int t= a.mant + 0x40000000 < 0;
return (SoftFloat){a.exp+t, a.mant>>t};
#else
int t= (a.mant + 0x40000000U)>>31;
return (SoftFloat){a.exp+t, a.mant>>t};
#endif
}
/**
*
* @return will not be more denormalized then a+b, so if either input is
* normalized then the output wont be worse then the other input
* if both are normalized then the output will be normalized
*/
static inline SoftFloat av_mul_sf(SoftFloat a, SoftFloat b){
a.exp += b.exp;
a.mant = (a.mant * (int64_t)b.mant) >> ONE_BITS;
return av_normalize1_sf(a);
}
/**
*
* b has to be normalized and not zero
* @return will not be more denormalized then a
*/
static 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);
}
static inline int av_cmp_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 SoftFloat av_add_sf(SoftFloat a, SoftFloat b){
int t= a.exp - b.exp;
if(t<0) return av_normalize1_sf((SoftFloat){b.exp, b.mant + (a.mant >> (-t))});
else return av_normalize1_sf((SoftFloat){a.exp, a.mant + (b.mant >> t )});
}
static inline SoftFloat av_sub_sf(SoftFloat a, SoftFloat b){
return av_add_sf(a, (SoftFloat){b.exp, -b.mant});
}
//FIXME sqrt, log, exp, pow, sin, cos
static inline SoftFloat av_int2sf(int v, int frac_bits){
return av_normalize_sf((SoftFloat){ONE_BITS-frac_bits, v});
}
/**
*
* rounding is to -inf
*/
static inline int av_sf2int(SoftFloat v, int frac_bits){
v.exp += frac_bits - ONE_BITS;
if(v.exp >= 0) return v.mant << v.exp ;
else return v.mant >>(-v.exp);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment