Re: Converting to and from FAC

From: Steve Judd (sjudd_at_ffd2.com)
Date: 2000-10-18 19:09:29

Hi Nick,

> Does any one know how, of have a good reference for, converting floating
> point numbers to and from the 5-byte format used in the FAC and by all the
> Kernal routines?

The 5-byte format is pretty easy to understand, and is actually quite
similar to the IEEE floating-point formats.  Just to put things in
context, allow me a few paragraphs to explain representation of numbers on
a computer.

Let's start by writing a number in binary: 0101.0110 (I just made
that up), which is 2^2 + 2^0 + 2^-2 + 2^-3 = 5 + 1/4 + 1/8 = 5.375.

In a fixed point scheme, the decimal point stays, well, fixed -- in
this case, each number might be one byte, with four digits to the left
of the decimal point and four to the right.  So after, say, multiplying
two numbers together, the routine would fix up the result so that there
would be four bits to the left and four to the right.

In a floating point scheme, the idea is to let the decimal point move
around, by using an extra byte for the exponent.  That is, numbers are
now represented as A * 2^B -- A is the mantissa, B is the exponent.

In the example above, you could represent the "floating point" number
in a lot of ways -- 0101.0110 * 2^0, 01.010110 * 2^2, 01010110*2^-4,
and so on.  The first thing to notice is that any leading zeros are
wasted bits -- you can always keep shifting the number left until a "1" is
hit, and let the exponent keep track of the decimal point.  And as long as
the first bit is _always_ a 1, there's no reason to waste a bit on it!
This will hopefully become clear shortly.

So, the C64 represents floating point numbers using five bytes.  The first
byte is the exponent plus 129.  An exponent of zero represents the number
zero (Mapping the 64 is wrong in their description).

The next four bytes represent the mantissa of the number, in big-endian
format (not the usual lo-hi format of the 6510), except for the very
first bit.  Because the first digit is always assumed to be a "1" -- any
nonzero number has to have a "1" in it somewhere -- the very first bit is
used to represent the sign of the number, 0 being positive.

So let's do an example: 85 00 00 00 00

The exponent is $85 -- subtract 129 to get 4.
The first bit is zero, so the number is positive.
The mantissa is 1 + .00 00 00 00 = 1.
So the final value is 1 * 2^4, or 16.

Second example: 84 20 00 00 00

Exponent is 3.
Sign is positive.
Mantissa is 1.0100000 0000 0000 0000 (leading bit is always 1)
Value is 1.01 ^ 2^3 = 1010 = 10.

Third example: 80 80 00 00 00

Exponent is -1.
Sign is negative.
Mantissa is 1.
Value is -1 * 2^-1 = -0.5.

There are lots of constant floating point numbers in the kernal, if you
want to try converting some more (e.g. at $B9D6).  Oh, what the heck:
81 35 04 f3 34

Exponent = 0.  Number = b5 04 f3 34 * 2^-31 = 181 4 243 52 * 2^-31
		      = 1.4142136 = sqrt(2).

So, an algorithm to convert C64 5-byte floats would look like:

- Read first byte.  If zero then number is zero, else subtract 129 to get
  exponent.

- Read next four bytes = mantissa.  If high bit is 1 then sign=-1, else
  sign=1.

- ORA $80 00 00 00 to mantissa to get leading 1.

- Number is sign*mantissa*2^(exponent-31).  The -31 is only needed if you
  represent the mantissa as a positive integer (remember that there's
  actually a decimal point to the left of the 4-byte mantissa).

To convert to a 5-byte fp number, basically you just reverse the steps
(but how you do it will depend on how your numbers are represented).
One possibility is to convert the numbers to binary and process them in
binary; perhaps someone here will offer up a decent algorithm.

Hope that helps,

-Steve

-
This message was sent through the cbm-hackers mailing list.
To unsubscribe: echo unsubscribe | mail cbm-hackers-request@dot.tml.hut.fi.

Archive generated by hypermail 2.1.1.