Quick compare of two CBM floats

Basic and Machine Language

Moderator: Moderators

Post Reply
nippur72
de Lagash
Posts: 574
Joined: Thu Sep 07, 2006 8:35 am

Quick compare of two CBM floats

Post by nippur72 »

There's the ROM routine CMPFAC that compares two floats (<,=,>), but let's say I want to implement a quick equality compare (only =)... can I use a byte-by-byte check? E.g.

Code: Select all

ldx #4
loop:
   lda num1,x
   cmp num2,x
   bne false
   dex
   bpl loop
true:
   rts
false:   
   rts
In other words is the cbm float representation unique?
nippur72
de Lagash
Posts: 574
Joined: Thu Sep 07, 2006 8:35 am

Re: Quick compare of two CBM floats

Post by nippur72 »

I think I've found the reply to my own question, according to the C64 wiki:
The mantissa is normalized, which means it is always a number in the range from 0.5 to 1, so that 0.5 ≤ m < 1, [...] the floats could be easily compared in a lexical way without doing a full subtract operation.
nippur72
de Lagash
Posts: 574
Joined: Thu Sep 07, 2006 8:35 am

Re: Quick compare of two CBM floats

Post by nippur72 »

Yet I am not sure about the case of comparing zero with zero, what about if the exponent is $80 on both but they have different mantissa?
User avatar
Kweepa
Vic 20 Scientist
Posts: 1315
Joined: Fri Jan 04, 2008 5:11 pm
Location: Austin, Texas
Occupation: Game maker

Re: Quick compare of two CBM floats

Post by Kweepa »

It certainly looks like the mantissa could be anything in that case. Seems safer to early out if both exponents are $80.
User avatar
Mike
Herr VC
Posts: 4846
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Quick compare of two CBM floats

Post by Mike »

With the mantissa interpreted as m = 0.5 .. 0.9999..., the exponent is stored in excess-128 representation, i.e. 0.5 ^= $80 $00 $00 $00 $00, where the most significant bit of the mantissa isn't stored, rather replaced by the sign (0 ^= +ve, 1 ^= -ve).

The canonical representation of zero (and what is always delivered from the arithmetic routines as result) is all bytes $00. A zero exponent with non-0 mantissa isn't defined for CBM floats, but the float routines of BASIC only check the exponent byte if they want to compare with zero.

...

I'd like to add that the comparison of two numbers for (in)equality is a rather vague concept in Numerical analysis. Chances are, that two numbers, that 'ought' to be equal (in the mathematical sense) won't come out as equal when computed in two different ways with machine numbers on any float library of your choice. That's the reason a lot of numeric algorithms check error bounds instead, like in |x_2 - x_1| < eps ... I know this isn't exactly that what you wanted (i.e., quick) - but it's surely more robust.
User avatar
Kweepa
Vic 20 Scientist
Posts: 1315
Joined: Fri Jan 04, 2008 5:11 pm
Location: Austin, Texas
Occupation: Game maker

Re: Quick compare of two CBM floats

Post by Kweepa »

On the other hand, most programming languages use exact comparisons for floating point equality so you are in good company if you do the same. It's up to the programmer to decide what is an acceptable epsilon, as it strongly depends on what she is doing.
User avatar
Mike
Herr VC
Posts: 4846
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Quick compare of two CBM floats

Post by Mike »

By that measure, I don't quite understand the critique on the compare routine in the CBM BASIC float library (see $DC5B..$DC98).

It checks the signs and then the exponents for a very quick bailout, only if both are equal, it checks the mantissa bytes in an unrolled loop and also does a quick bailout as soon as two mantissa bytes don't compare equal. That's about as fast as you can get, and not much slower than the handcrafted version in the OP, if two machine numbers actually compare equal.

The very fact that two numbers compare equal is (as I've already hinted at above) the most improbable case, so you'd rather expect them not to be equal - and in this case, I'd rather want the information which of the two numbers is bigger.
User avatar
Kweepa
Vic 20 Scientist
Posts: 1315
Joined: Fri Jan 04, 2008 5:11 pm
Location: Austin, Texas
Occupation: Game maker

Re: Quick compare of two CBM floats

Post by Kweepa »

Numbers being equal is pretty common in CBM BASIC, where ints are stored as floats.
I forget what nippur is up to but it could be something similarly flexible.
But yes, the ROM routine sounds fast enough, and would save some memory :)
User avatar
Mike
Herr VC
Posts: 4846
Joined: Wed Dec 01, 2004 1:57 pm
Location: Munich, Germany
Occupation: electrical engineer

Re: Quick compare of two CBM floats

Post by Mike »

Numbers being equal or not equal is a much more robust concept when you're dealing with integer numbers, that should go without saying. I stand by my case however, that when I see program code that actually compares two float numbers just for equality (or non-equality) I may strongly suspect the programmer didn't quite know what he is doing there ...
User avatar
Kweepa
Vic 20 Scientist
Posts: 1315
Joined: Fri Jan 04, 2008 5:11 pm
Location: Austin, Texas
Occupation: Game maker

Re: Quick compare of two CBM floats

Post by Kweepa »

I agree 99.9999038%
nippur72
de Lagash
Posts: 574
Joined: Thu Sep 07, 2006 8:35 am

Re: Quick compare of two CBM floats

Post by nippur72 »

My original idea was to optimize the Mospeed basic compiler in a very specific case: "IF B=C THEN ..." when B and C are simple variables or constants (no expressions that is).

The current implementation is to load B on the FAC and then compare it with C using the CMPFAC routine in ROM:

Code: Select all

LDA #<VAR_B
LDY #>VAR_B
JSR REALFAC  ; load into fac
LDA #<VAR_C
LDY #>VAR_C
JSR CMPFAC  ; compare
BNE SKIP
...
SKIP:
But for the simple case of "IF B=C THEN..." there is no reason to use the FAC alltogether, it's enough to do a quick inline compare which is also shorter (13 bytes vs. 16 bytes):

Code: Select all

ldx #4
loop:
  lda VAR_B, x
  cmp VAR_C, x
  bne skip
  dex
bpl loop
...
skip:
The issue is when dealing with the 0 case. If I can assume the mantissa is 0,0,0,0 there are no problems, otherwise I have to add extra code resulting in a 27 byte routine that is difficult to inline.

I guess it all depends on what the ROM actually does when returning 0 in the various functions.
wimoos
Vic 20 Afficionado
Posts: 350
Joined: Tue Apr 14, 2009 8:15 am
Website: http://wimbasic.webs.com
Location: Netherlands
Occupation: farmer

Re: Quick compare of two CBM floats

Post by wimoos »

The routine at $DC9B (convert float to fix), that is part of the INT() function actually sets the mantissa to zero when $61 is zero.
Other settings of FAC1 to zero is done by setting $61 (exp) and $66 (sign) to zero.

All checks for zero in FAC1 are done by checking $61 only.

Regards,

Wim.
VICE; selfwritten 65asmgen; tasm; maintainer of WimBasic
Post Reply