Maybe floating point isn't that bad of an idea.

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Maybe floating point isn't that bad of an idea.
by on (#239813)
Let's say you have an 8-bit mantissa, and a 5-bit exponent and a sign bit like this:

00seeeee mmmmmmmm

Lets say an exponent of "16" is a whole number. In order to multiply a number you could add the exponent bytes together, then subtract 16. Then multiply the 8-bit mantissas together, and then shift the 16-bit product right until it's less than 256, while incrementing the exponent byte.

For the signed bit, just as long as the 5-bit exponent doesn't overflow, the sign bits should automatically EOR eachother when adding, followed by AND #$3F to clear out the top 2 bits.

Now with converting it back into fixed point, there's several ways:

1) Use an extremely long LUT
2) Split up the exponent byte between the low 3 bits and the high 2 bits. Use the low 3 bits to count how many times you shift the accumulator left, and use the top two bits as an index.
3) Do the same except use a LUT for accumulator shifts instead.
Re: Maybe floating point isn't that bad of an idea.
by on (#239819)
I'm lost, What is it for?.
Re: Maybe floating point isn't that bad of an idea.
by on (#239825)
psycopathicteen wrote:
Then multiply the 8-bit mantissas together, and then shift the 16-bit product right until it's less than 256, while incrementing the exponent byte.


When writing code in a high-level language, floating-point avoids the need to keep track of many differing types with different levels of range and precision. It also makes it practical to have libraries that can be used for many different purposes that would involve numbers with different ranges. From a computational efficiency standpoint, almost anything that can be done with floating-point could be done more efficiently with suitably-chosen fixed-point formats if one evaluated the required size and range of each object before writing the code.

The amount of absolute precision that a particular object needs generally won't diminish with the scale of the value that happens to be within it. If one has a game with acceleration, velocity values may need more precision than absolute-position values, and a single floating-point type may handle that job better than would a single fixed-point type, but using separate fixed-point position, velocity, and acceleration types would be better yet.
Re: Maybe floating point isn't that bad of an idea.
by on (#239832)
There are a few other complications involved.

Addition is nowhere near as simple, as you need to align the exponents first. The barrel shifting for that will not be quick in '816.
Catching and handling exponent overflow and underflow do need to be done.

Usually you want to have zero be special cased, with an exponent of 0, which mostly lets the usual comparisons work (aside from catching/eliminating -0)

For the proposed format, s00eeeee mmmmmmmm would probably be a bit better, as then you can check the sign as if it were a normal 16 bit integer.

On the upside, treating them as 16 bit signed integers for comparison generally Just Works.
Re: Maybe floating point isn't that bad of an idea.
by on (#239833)
Señor Ventura wrote:
I'm lost, What is it for?.


I'm trying to make a 3D spinning ring of ball sprites and it's taking a lot of CPU power to do the math on 16 balls, because it's taking 8 multiplications and 2 divisions per sprite. I'm trying not to use the mode-7 multiplication registers because I might want to later do this effect during a mode-7 level, but I'll do it as a last resort. Floating point looks like a good idea, because I only need to do one 8x8 multiplication. The downside is the need to convert back into fixed point, so I would have to count cycles, before making the decision to use it or not.
Re: Maybe floating point isn't that bad of an idea.
by on (#239834)
No need for a floating number then, made in fixed-point numbers.

You know that the PS1 had no floating numbers?
All the 3D calculations was 16 bits
(It seems to me that the Sega Saturn too)

The PS2 also has a 16-bit fixed-point (for vertices / textures), but you perform floating-point calculations (with FTOI and ITOF instructions for conversions). Sony has kept 16-bits fixed-point to speed up transfers between RAM and memory VU.
And the GPU also takes only 16-bit fixed-point ah ah so forced to do a lot of conversion (but the instruction is fast you can run 2 instructions / cycles if you pay attention to the pipeline).

Dreamcast allowed 16-bit floating numbers for texture coordinates (to reduce transfers)
Re: Maybe floating point isn't that bad of an idea.
by on (#239836)
What doesn't the exponent fill the whole byte? What are those two 0 bits for? I do second the notion that the sign bit should be in the high bit at least, but why not make that whole byte a signed 8-bit number and keep it simpler that way?

FWIW I think software floating points can be very useful for some specific purposes, though I must admit those purposes have never come up in my retro game platform endeavours.
Re: Maybe floating point isn't that bad of an idea.
by on (#239838)
psycopathicteen wrote:
Señor Ventura wrote:
I'm lost, What is it for?.


I'm trying to make a 3D spinning ring of ball sprites and it's taking a lot of CPU power to do the math on 16 balls, because it's taking 8 multiplications and 2 divisions per sprite. I'm trying not to use the mode-7 multiplication registers because I might want to later do this effect during a mode-7 level, but I'll do it as a last resort. Floating point looks like a good idea, because I only need to do one 8x8 multiplication. The downside is the need to convert back into fixed point, so I would have to count cycles, before making the decision to use it or not.


That is interesting, How much processing, more or less, can you gain with the multipliers of the PPU1?.
Re: Maybe floating point isn't that bad of an idea.
by on (#239842)
rainwarrior wrote:
What doesn't the exponent fill the whole byte? What are those two 0 bits for? I do second the notion that the sign bit should be in the high bit at least, but why not make that whole byte a signed 8-bit number and keep it simpler that way?


I was thinking of a way to avoid making the LUT too big, but I realize that I can get around that by checking if floating point value is in range and using the LUT if in the range, and loading a #0 if not it range. It should take about 12kB.
Re: Maybe floating point isn't that bad of an idea.
by on (#239852)
By the way, Do you mean using multiplications out of the mode 7?.
Re: Maybe floating point isn't that bad of an idea.
by on (#239853)
Something that just occurred to me, is I could reduce the number of multiplications from 8 per sprite to 6 per sprite by calculating a 2x3 rotational matrix first, and then do matrix multiplication on every sprite in the 3d ring.

Señor Ventura wrote:
By the way, Do you mean using multiplications out of the mode 7?.


I'm talking about $211b and $211c.
Re: Maybe floating point isn't that bad of an idea.
by on (#239860)
Something like this you probably need to "fake it".

you can make a parabola with fixed maths addition right, and a circle can be made with 2 of them. So basically you fake it. Or add the C4 chip, or SuperFX.
Re: Maybe floating point isn't that bad of an idea.
by on (#239863)
psycopathicteen wrote:
I'm talking about $211b and $211c.


I have here noted that the registers for the PPU are $4202 and $4203, and the registers of the mode 7 are $211b, $211c, $211d, and $211e

So, Do i must understand that you are in mode 7, but you can use that multipliers for sprites?
Re: Maybe floating point isn't that bad of an idea.
by on (#239864)
Señor Ventura wrote:
psycopathicteen wrote:
I'm talking about $211b and $211c.


I have here noted that the registers for the PPU are $4202 and $4203, and the registers of the mode 7 are $211b, $211c, $211d, and $211e

So, Do i must understand that you are in mode 7, but you can use that multipliers for sprites?


There are two sets of multiplication registers:

$211b/$211c/$2134 for signed 8x16 multiplication
$4202/$4203/$4216 for unsigned 8x8 multiplication

However the first set of registers also control the Mode-7 layer, so if you're using mode-7 using the signed 8x16 multiplication will screw up the mode-7 layer.
Re: Maybe floating point isn't that bad of an idea.
by on (#239868)
Señor Ventura wrote:
I have here noted that the registers for the PPU are $4202 and $4203

PPU = $2100..$2183
5A22 = $4016..$4017 and $4200..$437F
Re: Maybe floating point isn't that bad of an idea.
by on (#239881)
I also want to try out logarithms as well.