diff options
author | Matthias Kramm <kramm@quiss.org> | 2009-10-20 15:58:12 -0700 |
---|---|---|
committer | Matthias Kramm <kramm@quiss.org> | 2009-10-20 15:58:12 -0700 |
commit | d2ea72a8f8a8e1d2bc8d1e86fde1d7db449b1ded (patch) | |
tree | 02c3e6cfacb2a63517e3d29ccbfbf8f7b009ddab | |
parent | fc3df0f53530963da1dd423e2454ac31318169ed (diff) |
refactored F16 implementation
-rw-r--r-- | lib/rfxswf.c | 131 |
1 files changed, 42 insertions, 89 deletions
diff --git a/lib/rfxswf.c b/lib/rfxswf.c index a729f6d7..bba220fd 100644 --- a/lib/rfxswf.c +++ b/lib/rfxswf.c @@ -410,115 +410,68 @@ int swf_SetU30String(TAG*tag, const char*str, int l) float swf_GetF16(TAG * t) { - U16 f1 = swf_GetU16(t); - if(!f1) return 0; -#if 0 - // D16 is 1-5-10 - // D32 is 1-8-23 + U16 f1 = swf_GetU16(t); + if(!(f1&0x3ff)) return 0.0; + + // IEEE 16 is 1-5-10 + // IEEE 32 is 1-8-23 /* gcc 4.1.2 seems to require a union here. *(float*)u doesn't work */ union { U32 u; float f; } f2; - f2.u = (f1&0x8000)<<16; //sign - f2.u |= ((f1&0x7c00)<<13)+(0x40000000-(0x4000<<13)); //exp - f2.u |= (f1&0x03ff)<<13; //mantissa - return *(float*)&f2; -#endif - double d = (f1 & 32768L) != 1L ? 1.0 : -1.0; - int i = (int)((f1 & 0x7c00) >> 10) - 16; - double d1 = (double)(f1 & 1023) / 1024.0; - //FloatingPointValue floatingpointvalue = new FloatingPointValue(d1, i); - double value = d1 * pow(2, i); - -#if 0 - if(t->id != 0) { - TAG*tag = swf_InsertTag(0, 0); - //swf_SetF16(tag, value); - swf_SetF16(tag, 84.0/1024.0); - U16 f = swf_GetU16(tag); - tag->pos = 0; - fprintf(stderr, "%04x -> %f -> %04x -> %f\n", (int)f1, d*value, f, swf_GetF16(tag)*1024.0); - swf_DeleteTag(0,tag); + U16 e = (f1>>10)&0x1f; + U16 m = f1&0x3ff; + /* find highest bit in mantissa */ + int h=0; + while(!(m&0x400)) { + m<<=1; + h++; } -#endif + m&=0x3ff; + e -= h; + e += 0x6f; - return (float)(d*value); + f2.u = (f1&0x8000)<<16; //sign + f2.u |= e<<23; //exponent + f2.u |= m<<13; //mantissa + return *(float*)&f2; } void swf_SetF16(TAG * t, float f) { -#if 0 - U32 f1 = *(U32*)&f; - U16 f2 = (f1>>16)&0x8000; - int exp = ((f1>>23)&0xff)-0x80+0x10; - if(exp<0) { - if(exp!=(16-128)) { - fprintf(stderr, "Exponent underflow in FLOAT16 encoding %d\n", exp); - } + union { + U32 u; + float f; + } v; + v.f = f; + + U16 result = (v.u>>16)&0x8000; //sign + int exp = ((v.u>>23)&0xff)-0x7f+0x10; + U16 m = (v.u>>13)&0x3ff; + //fprintf(stderr, "%f: %04x sign, %d exp, %04x mantissa\n", f, result, exp, m); + if(exp<-10) { + // underflow (clamp to 0.0) + exp = 0; + m = 0; + } else if(exp<0) { + // partial underflow- strip some bits + m = (m|0x400)>>-exp; exp = 0; } else if(exp>=32) { exp = 31; + m = 0x3ff; fprintf(stderr, "Exponent overflow in FLOAT16 encoding\n"); - } - f2 |= exp<<10; - f2 |= (f1>>13)&0x3ff; - swf_SetU16(t, f2); -#endif - - if(f == 0.0F) - { - swf_SetU16(t, 0); - return; - } - union { - double value; - long long l; - } x; - x.value = (double)f; - - double mantissa; - double exp; - if(x.value == 0.0) - { - exp = 0; - mantissa = 0.0; - } else { - union { - double d; - long long l; - } u; - u.l = (0x800fffffffffffffLL & x.l) | 0x3fe0000000000000LL; - mantissa = u.d; - exp = (int)(((0x7ff0000000000000LL & x.l) >> 52) - 1022L); - } - - double d = mantissa; - int i = exp; - int j = i + 16; - if(j < 0 || j > 31) - { - fprintf(stderr, "too large or too small\n"); - swf_SetU16(t, 0); - return; - } - U16 p; - if(d >= 0.0) { - p = 0; } else { - d *= -1; - p = 32768; + exp++; + m = (m>>1)|0x200; } - p |= j << 10; - p |= (int)(d * 1024); - - //fprintf(stderr, "%f/%f -> %04x\n", mantissa, exp, p); - - swf_SetU16(t, p); + result |= exp<<10; + result |= m; + swf_SetU16(t, result); } - double swf_GetD64(TAG*tag) { /* FIXME: this is not big-endian compatible */ |