oN fRI, 14 Apr 2006, Mauro Carvalho Chehab wrote: > I've decided to use u64, instead of all those shifts. This way, we can > improve the precision for lower BER rates. Here, it worked like a charm: It was only a single shift. Anyway, the 64 bit math isn't being done correctly. Here is a graph were you can see the problem clearly: http://www.speakeasy.org/~xyzzy/ber-error.png BTW, If you look at the graph of the function you're now using, it really doesn't make a lot of sense. Maybe you should just toss out the old exponential and make a new one. Maybe you already know this, but there could be others reading who don't. The thing to remember is that C "promotes from within." That is to say, the type of an expression is determined by the types of the terms within the expression, the types of the terms outside the expression have no effect. Consider this generic expression, where 'op' could be addition, multiplication, assignment, etc. (term1 op1 term2) op2 term3) In this case the bit-size of the arithmetic performed by op1 is based solely on the types of term1 and term2. The type of term3 doesn't matter at all. If you consider what is effectivly in the patch: u64 = s32*(s32 - s32)/s32 + s32; u16 = (u32)u64; The innermost expression is the subtraction, both terms are s32, so it's done with signed 32-bit arithmetic and produces a s32 result. Then the multiplication is done as signed 32-bit, since both of its terms are signed 32-bit. This may overflow! The rest of the math is done as signed 32-bit as well, producing a s32 result. Finally, that is promoted to unsigned 64-bit by the assignment. In the next line, it's converted to unsigned 32-bit by the cast, and then to unsigned 16-bit by the assignment. If you want a 64-bit multiplication, you need to make one of the terms of the multiplication 64-bit: u16 = (s64)s32*(s32 - s32)/s32 + s32; The comments about BER being 24-bit are wrong too. If you look at the code to get BER, it's clearly a 22-bit value. This means the table going up past 4 million or so is pointless. This is how the table is working: BER from 0 to about 5000 is linearly scaled to 100% to 99% BER from about 5000 to the maximum is log scaled to 99% to 40% I think it might be a good idea to revisit what exactly you want SNR to return. Do you want SNR in dB scaled by some constant? Or do you want something that even ranges from 0xffff for good to 0 for bad? _______________________________________________ linux-dvb@xxxxxxxxxxx http://www.linuxtv.org/cgi-bin/mailman/listinfo/linux-dvb