| www.retrosoftware.co.uk http://www.retrosoftware.co.uk/forum/ |
|
| Fixed-point 8-bit multiplication http://www.retrosoftware.co.uk/forum/viewtopic.php?f=73&t=349 |
Page 2 of 2 |
| Author: | RichTW [ Mon Sep 21, 2009 9:46 am ] |
| Post subject: | Re: Fixed-point 8-bit multiplication |
ThomasHarte wrote: Then you get a 16bit number, and you suggest that you can just pass the two bytes separately through the same 8bit multiplication table and also add/subtract the results normally. But that doesn't quite work. a = +1 = 7f b = -128/127 = ff80 a * b = ((7f * ff)*127) + (7f*00) = (+1 * -1/127)*127 + (+1 * 00) = -127/127 = -1 (applying the split as described in your post; low 6 bits to one multiplication, 7 bits on top of those 6 bits to the other) Just to try and further explain things using one of your examples: In this instance, the value 'b' will be considered a 15-bit signed integer. It's not a fixed127. Therefore its value (FF80) is -128. Not -128/127ths. It's not a fixed127. This wouldn't be useful! The only useful meaning of a 2-byte long number is as a signed integer, which we can multiply by a fractional value between -1.0 and 1.0 (i.e. the fixed127). So, when we split FF80 into the two chunks, we get: bits 7-14: FF (as a signed integer, equivalent to -1) bits 0-6: 0 Then, we multiply by components: -1 * 1.0 = -1 * 127 / 127 = -1 (multiplied by 128) + 0 * 1.0 = 0 * 127 / 127 = 0 ---------------- result = -128, which is the correct answer |
|
| Author: | ThomasHarte [ Tue Sep 22, 2009 3:04 pm ] |
| Post subject: | Re: Fixed-point 8-bit multiplication |
Hi, sorry, on holiday and tapping this out on an iPhone. See your point about the tables, but still concerned about big value multiplications: if you divide by 128 then you know exactly where the result will end in terms of binary digits after the decimal place. Obviously there's no such guarantee with dividing by 127. Would suggest that an 8.8 scheme for the lookup-table would be appropriate if sufficient memory is available. Learnt on the Sam that even 2.8 precision produces poor precision on large 8.8 numbers re: the computed position of an object relative to the camera if you use the ordinary matrix stuff. Found it was much better to multiply 3x3s alone, work out offset as difference in global positions mapped forward once through the camera matrix (rather than, effectively, object position through composed matrix minus camera position through composed matrix). Limits you to exactly two matrices rather than a GL-style stack, but I think would probably be smart here too, as I think it's the only thing that involves big numbers. Hoping to get some sort of simplistic 3d display going soon, will give fixed127s a shot, see how it looks. |
|
| Author: | RichTW [ Tue Sep 22, 2009 3:44 pm ] |
| Post subject: | Re: Fixed-point 8-bit multiplication |
Quote: See your point about the tables, but still concerned about big value multiplications: if you divide by 128 then you know exactly where the result will end in terms of binary digits after the decimal place. Obviously there's no such guarantee with dividing by 127. Would suggest that an 8.8 scheme for the lookup-table would be appropriate if sufficient memory is available. The problem will be whether 128 discrete values representing the range of 0.0 to 1.0 inclusive is sufficient. The multiplication routine produces surprisingly accurate results, even for s15 * fixed127: results accurate to within +/-1.0: 92% results accurate to within +/-1.5: 99.5% The lookup table already is 8.8 (i.e. each entry contains (x^2/4)/127, stored as an 8-bit integer part, and an 8-bit fractional part). Quote: Found it was much better to multiply 3x3s alone, work out offset as difference in global positions mapped forward once through the camera matrix (rather than, effectively, object position through composed matrix minus camera position through composed matrix). Yeah, this is more or less what I proposed a little while ago I think... you transform model space coords through a unit 3x3 rotation matrix, and then add a global translation afterwards to get it into 15-bit coordinates. From an old post: Code: x' = x . LW . CW^-1 = (x . LWr + LWt) . (CWr + CWt)^-1 = (x . LWr + LWt) . CWr^-1 - CWt . CWr^-1 = x . (LWr . CWr^-1) + [(LWt - CWt) . CWr^-1] ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ 8-bit rotation 16-bit translation This is in fact what the hardware of the original PlayStation did, and it worked well there! Is this the sort of thing you mean? Look forward to seeing if this works ok or not... The nice thing about the fixed127s being only one byte in size is that they hugely simplify a matrix multiply, e.g. Code: ; multiply X component LDX vec+0:LDY matrix+0:JSR S8_x_Fixed STA vecresult+0 LDX vec+1:LDY matrix+3:JSR S8_x_Fixed CLC:ADC vecresult+0:STA vecresult+0 LDX vec+2:LDY matrix+6:JSR S8_x_Fixed CLC:ADC vecresult+0:STA vecresult+0 ; similar for the other two components In the case where two fixed127s are multiplied, it'd perhaps be necessary to put in some extra checks to clamp the results of the adds to +/-1.0. Also, at a speed cost, it'd be possible to make the S8_x_Fixed multiply routine a little more accurate, which might also be necessary when composing matrices. We'll have to see... Enjoy your holiday! |
|
| Page 2 of 2 | All times are UTC [ DST ] |
| Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group http://www.phpbb.com/ |
|