[solved] Math Guru III How to normalize floating point ?

General discussion for topics related to the FreeBASIC project or its community.
Post Reply
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

[solved] Math Guru III How to normalize floating point ?

Post by D.J.Peters »

Hello math guru you can help and teach me if you like :-)

Today I got for my 8-bit retro computer project an AM9511 8-bit coprocessor. am9511_datasheet.pdf
Currently I write an assembler and BASIC compiler (a subset of FreeBASIC) for the Motorola 6800 / 6803 MCU.
(I wrote an MC 6803 emulator in FreeBASIC also: http://www.freebasic.net/forum/viewtopi ... =8&t=22944)

The problem I don't know how to get from ASCII string like "const PI = 3.141592654" the 4 bytes for the AM9511 coprocessor.

Here are the binary floating point format of the AM9511 it must be normailzed so bit 23 is allways 1:
Image

What I need is a good commented pair of function like:

function StringToLong(value as string) as long

function LongToString(value as long) as string

If I know how it works I have to write it as 8-bit assembler code.

Thank you

Joshy
Last edited by D.J.Peters on Oct 03, 2017 8:14, edited 3 times in total.
marcov
Posts: 3462
Joined: Jun 16, 2005 9:45
Location: Netherlands
Contact:

Re: Math Guru III How to normalize floating point ?

Post by marcov »

No code, just some hints:

To me it looks like this type is a kind nonstandard SINGLE. (one bit more mantissa, one bit less exponent).

So as intermediate type, use double (single might not have enough precision), and create double2AM951 and vice versa procedures. Then you can create the functions you want with the relevant double<->string conversion routines and these.

Get the individual parts (mantisse,exponent,sign) from the double, round them properly and put them in the 32-bits value. Watch out for special encoding schemes (like not storing the first bit of the mantissa, or having a biassed exponent, which means that an exponent x (e.g. an exponent -127<x<127 is stored as x+128)
srvaldez
Posts: 3383
Joined: Sep 25, 2005 21:54

Re: Math Guru III How to normalize floating point ?

Post by srvaldez »

hello Joshy
hope you will not be offended by a beginner's response, here's a small test for double

Code: Select all

union dbl
	as double df
	as ulongint li
end union

dim as dbl pi

pi.df=3.141592653589793*10 '31.41592653589793
dim as ulongint m, x=pi.li
dim as long expbits=11, expbias=1023, mbits=52, sign, e
e=x shr mbits 'get the 12 most significant bits
sign=(e and &h800) shr expbits 'zero-out all but the sign bit
e=e and &h7ff 'zero-out the sign bit
m=x and &b000000000001111111111111111111111111111111111111111111111111111 '52 + one implied mantissa bits
m=m or  &b000000000010000000000000000000000000000000000000000000000000000 'set bit 53 in the mantissa
print hex(x),hex(m),m,hex(e),e,sign
print "sign=";sign," abs double value = ",m/(2^(expbias-e+mbits))
if (e-expbias)>0 and (e-expbias)<52 then
	print "sign=";sign," abs integer part = ",m shr (expbias-e+mbits) 'integer part
end if
Last edited by srvaldez on Oct 27, 2016 0:26, edited 2 times in total.
badidea
Posts: 2594
Joined: May 24, 2007 22:10
Location: The Netherlands

Re: Math Guru III How to normalize floating point ?

Post by badidea »

While DuckDuckGoing, I found this: http://www.atarimagazines.com/compute/i ... OUTINE.php
Is this what you are looking for?
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: Math Guru III How to normalize floating point ?

Post by D.J.Peters »

thanks guys here are my first naive try.
i know left most bit (if set) of the matissa = 0.5 the second = 0.25 the third = 0.625 and so on ...
if the sign bit are set then the exponent are negative ...

NOTE: The IEEE-754 standard are defined in 1985 my (retro) Am9511 are one decade older (~1976) so it use it's own floating point format !

IEEE-754 = FPU (floating point unit)
Am9511 = APU (arithmetic processing unit)

Joshy

Code: Select all

' Am9511
const as ulong sign_mask  = &B10000000000000000000000000000000
const as ulong expo_mask  = &B01111111000000000000000000000000
const as ulong mant_mask  = &B00000000111111111111111111111111
' PI in Am9511 binary format
const as ulong Am9511_PI = &H02C90FDA
' PI in IEEE 754 format
dim as single PI = atn(1)*4

function floatToString(byval value as ulong) as string
  dim as single  exponent = 2 ^ ((value and expo_mask) shr 24)
  dim as single  mantisse = value and mant_mask
  dim as single  bitval   = .5
  dim as integer bitpos   = 2^23
  dim as single  result
  if (value and sign_mask) then exponent=-exponent
  for i as integer = 1 to 23
    if (mantisse and bitpos) then result += bitval
    bitval  *=0.5
    bitpos shr=1
  next
  return str(exponent * result)
end function

print "single " & str(pi)
print "Am9511 " & floatToString(Am9511_PI)
print "Am9511"  & floatToString(Am9511_PI or sign_mask)
print 
print "IEEE 754 0x" & hex(*cast(long ptr,@pi),8)
print "Am9511   0x" & hex(Am9511_PI,8)
print
print "IEEE 754 " & bin(*cast(long ptr,@pi),32)
print "Am9511   " & bin(Am9511_PI,32)
sleep
srvaldez
Posts: 3383
Joined: Sep 25, 2005 21:54

Re: Math Guru III How to normalize floating point ?

Post by srvaldez »

made a correction in my example code, I thought that I could set the 53rd bit with and but it does not always work, so I changed the mantissa mask to 52-bits and set the 53rd bit with or, also changed some variable types to prevent incorrect result when using unsigned integer.
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: Math Guru III How to normalize floating point ?

Post by D.J.Peters »

Looks like my naive way works for PI in both directions.

But i'm waiting for a math genius to get a more clever solution.

Joshy

Code: Select all

' Am9511
const as ulong sign_mask  = &B10000000000000000000000000000000
const as ulong expo_mask  = &B01111111000000000000000000000000
const as ulong mant_mask  = &B00000000111111111111111111111111
' PI in Am9511 binary format
const as ulong Am9511_PI = &H02C90FDA
' PI in IEEE 754 format
dim as single PI = atn(1)*4

' build text from a 4 byte Am9511 binary floating point number
function LongToString(byval value as ulong) as string
  dim as single  exponent = 2 ^ ((value and expo_mask) shr 24)
  dim as single  mantisse = value and mant_mask
  dim as single  bitval   = 1.0
  dim as integer bitpos   = 2^23
  dim as single  mantissa
  if (value and sign_mask) then exponent=-exponent
  for i as integer = 1 to 24
    bitval  *=0.5
    if (mantisse and bitpos) then mantissa += bitval
    bitpos shr=1
  next
  return str(mantissa * exponent)
end function

' build a 4 byte Am9511 binary floating point number from text
function StringToLong(byval txt as string) as ulong
  dim as single bitval
  dim as integer bitpos
  dim as ulong result
  var nChars = len(txt)
  if nChars=0 then return result
  dim as single value=val(txt)
  if value=0 then return result
  if value<0 then result =2^31 : value=-value
  dim as single exponent=int(log(value)/log(2))+1
  dim as single mantissa=value / 2 ^ exponent
  if exponent>0 then
    bitval=128.0 : bitpos=2^30
    for i as integer=1 to 7
      bitval /= 2
      if exponent>=bitval then result or= bitpos : exponent -= bitval
      bitpos shr= 1
    next
  else
    result or=2^30 : bitval=-64.0 : bitpos=2^29
    for i as integer = 2 to 7
      bitval /= 2
      if exponent>=bitval then result or= bitpos : exponent -= bitval
      bitpos shr= 1
    next
  end if
  bitval=1.0 : bitpos=2^23 
  for i as integer=8 to 31
    bitval /= 2
    if mantissa>=bitval then result or=bitpos : mantissa-=bitval
    bitpos shr=1
  next
  return result
end function


print "single " & str(pi)
print "Am9511 " & LongToString(Am9511_PI)
print "Am9511"  & LongToString(Am9511_PI or sign_mask)
var pi_binary = Stringtolong("3.1415926")
print "binary "  & LongToString(pi_binary)
print 

print "IEEE 754 " & bin(*cast(long ptr,@pi),32)
print "Am9511   " & bin(Am9511_PI,32)
print "PI       " & bin(pi_binary,32)
print
print "IEEE 754 0x" & hex(*cast(long ptr,@pi),8)
print "Am9511   0x" & hex(Am9511_PI,8)
print "PI       0x" & hex(pi_binary,8)

sleep
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: Math Guru III How to normalize floating point ?

Post by D.J.Peters »

Here are my last version looks like I run in to the "egg or chicken dilemma" !

Putting a float in the source code of my OS / assembler / linker / compiler means I must convert it to a 4 byte value (dec or hex)
loop: I use log() and ^ (power of) to convert the float to binary and the Am9511 has this commands
but I need first the binary value of the float's to use log and power on the Am9511 goto loop :-(

I hope a genius can help and give me a stringToLong function
that will only parse the ASCII chars and build the 4 byte binary value of it (without val(),log() and "^")

Without this more tricky function I have to write a cross compiler assembler at first.

Joshy

Code: Select all

' Am9511
const as ulong sign_mask  = &B10000000000000000000000000000000
const as ulong expo_mask  = &B01111111000000000000000000000000
const as ulong mant_mask  = &B00000000111111111111111111111111

' PI in IEEE 754 format
dim as single PI = atn(1)*4


' PI in Am9511 binary format
const as ulong Am9511_PI = &H02C90FDA

const as ulong Am9511_5  = &H03A00000


' build text from a 4 byte Am9511 binary floating point number
function LongToString(byval value as ulong) as string
  dim as single  exponent = 2 ^ ((value and expo_mask) shr 24)
  dim as single  mantisse = value and mant_mask
  dim as single  bitval   = 1.0
  dim as integer bitpos   = 2^23
  dim as single  mantissa
  if (value and sign_mask) then exponent=-exponent
  for i as integer = 1 to 24
    bitval  *=0.5
    if (mantisse and bitpos) then mantissa += bitval
    bitpos shr=1
  next
  return str(mantissa * exponent)
end function

' build a 4 byte Am9511 binary floating point number from text
function StringToLong(byval txt as string) as ulong
  dim as single bitval
  dim as integer exponent,bitpos,bits
  dim as ulong result
  dim as single mantissa,value=val(txt)
  if value=0 then return result
  ' set sign bit and make value positive abs()
  if value<0 then result =2^31 : value=-value
  ' get integer exponent and mantissa
  exponent=int(log(value)/log(2))+1
  mantissa=value / 2 ^ exponent

  if exponent>0 then ' positive 7 bit loop
    bitval = 128 : bitpos = 2^30 : bits = 7
  else               ' negative 6 bit loop
    bitval = -64 : bitpos = 2^29 : bits = 6 : result or=2^30
  end if
  
  ' build bits of the exponent
  for i as integer=1 to bits
    bitval /= 2
    if exponent>=bitval then result or= bitpos : exponent -= bitval
    bitpos shr= 1
  next
  ' build bits of the mantissa
  bitval = 1 : bitpos = 2^23 : bits = 24
  for i as integer=1 to bits
    bitval /= 2
    if mantissa>=bitval then result or= bitpos : mantissa -= bitval
    bitpos shr=1
  next
  return result
end function


print "single " & str(pi)
print "Am9511 " & LongToString(Am9511_PI)
print "Am9511"  & LongToString(Am9511_PI or sign_mask)
var pi_binary = Stringtolong("3.1415926")
print "binary "  & LongToString(pi_binary)
print 

print "IEEE 754 " & bin(*cast(long ptr,@pi),32)
print "Am9511   " & bin(Am9511_PI,32)
print "PI       " & bin(pi_binary,32)
print
print "IEEE 754 0x" & hex(*cast(long ptr,@pi),8)
print "Am9511   0x" & hex(Am9511_PI,8)
print "PI       0x" & hex(pi_binary,8)

sleep
Last edited by D.J.Peters on Oct 27, 2016 13:01, edited 1 time in total.
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: Math Guru III How to normalize floating point ?

Post by D.J.Peters »

Ok I write a cross assembler/linker/compiler suite :-)

Joshy
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: Math Guru III How to normalize floating point ?

Post by D.J.Peters »

badidea wrote:While DuckDuckGoing, I found this: http://www.atarimagazines.com/compute/i ... OUTINE.php
Is this what you are looking for?
Ups I overread your post and it's indeed very helpful.

The good old 6502 assembler code is near the same as 6803 so I can read it without any problems.

More than two years ago but it`s never to late to say thank you.

Joshy
Post Reply