Slow fixed point math

If you have questions about any aspect of QBasic programming, or would like to help fellow programmers solve their problems, check out this board!

Moderators: Pete, Mods

Post Reply
User avatar
Codemss
Veteran
Posts: 124
Joined: Sun Jun 24, 2007 6:49 am
Location: Utrecht, The Netherlands
Contact:

Slow fixed point math

Post by Codemss »

I wrote a Julia animator a while ago, and yesterday I decided to optimize it with fixed point math. But when I used ffix with the floating point math, it was much faster then when I used integer or long integer fixed point math. I though that this was maybe because of the extra multipications and (integer) divides that you have to use to keep the iteration in range, but I was still suprised. Am I doing something wrong? I read in a tutorial that with fractals, fixed point math is usually much faster. You can have my code, and try it yourself, I commented the relevant parts:

Code: Select all

'When you compile, dont forget to uncomment
'either the fixed point version or the floating point version
'(scroll down till you see it)
DECLARE SUB ffix ()
CLS
SCREEN 13
DEFINT A-Z
CONST max = 25

ffix
FOR c = 0 TO max
  OUT &H3C8, c
  OUT &H3C9, c / max * 63
  OUT &H3C9, c / max * 63
  OUT &H3C9, c / max * 63
NEXT

DIM p AS LONG, p2 AS LONG
'Make this line a comment if you want to use floating point math.
DIM zr AS LONG, zi AS LONG, cr AS LONG, ci AS LONG, zr2 AS LONG, zi2 AS LONG
LINE (21, 13)-(298, 186), max, B
DEF SEG = &HA000
t1! = TIMER
DO UNTIL LEN(INKEY$)
  p = 4502
  p2 = 59497
  a! = a! + .05
  scr! = COS(a!)
  sci! = SIN(a!)
  ci = sci! * 256
  cr = scr! * 256
  FOR y = 14 TO 100
    FOR x = 22 TO 297

      ''''Floating point version
      'zr! = (x / 319) * 4 - 2
      'zi! = (y / 199) * 4 - 2
      'c = 0
      'zr2! = zr! * zr!: zi2! = zi! * zi!
      'DO
      '  zi! = (2 * zr! * zi!) + sci!
      '  zr! = zr2! - zi2! + scr!
      '  zr2! = zr! * zr!
      '  zi2! = zi! * zi!
      '  c = c + 1
      'LOOP UNTIL (zr2! + zi2!) >= 4 OR c = max
       ''End

      
      '''Fixed point version
      'zr = (x * 3.2 - 512)
      'zi = (y * 5.12 - 512)
      'c = 0
      'zr2 = (zr * zr) \ 256: zi2 = (zi * zi) \ 256
      'DO
      '  zi = (zr * zi) \ 128 + ci
      '  zr = zr2 - zi2 + cr
      '  zr2 = (zr * zr) \ 256
      '  zi2 = (zi * zi) \ 256
      '  c = c + 1
      'LOOP UNTIL (zr2 + zi2) >= 1024 OR c = max
      '''End

      POKE p, c
      POKE p2, c
      p = p + 1
      p2 = p2 - 1
    NEXT
    p = p + 44
    p2 = p2 - 44
  NEXT
LOOP
t2! = TIMER
DEF SEG
PRINT "Fps:" + STR$((a! / .05) / (t2! - t1!))
SLEEP
END
Check out my site: <a href="http://members.lycos.nl/rubynl">Click here</a>
Hope you like it. Send some feedback if you want: <a href="mailto:basicallybest@live.nl">Mail me</a>
Codemss, before known as RubyNL
Mac
Veteran
Posts: 151
Joined: Mon Aug 06, 2007 2:00 pm

Re: Slow fixed point math

Post by Mac »

Codemss wrote:Am I doing something wrong?
Well, Ruby, I kept waiting for someone to answer your question so I could finally see what you're talking about. I can't even understand the question.

The program below will clearly illustrate that fixed is better than float. But you do not have a clean $$$. You are solving some problem two different ways and note that one of those ways is faster than the other. Duhhh! Why would you be surprised?

Well the answer must be that I have missed something. I only see that you are comparing
zr! = (x / 319) * 4 - 2
zr = (x * 3.2 - 512)
and wondering why the latter, being fixed point, is not faster than the former.

??? Confused Mac gives up

Code: Select all

DIM a1 AS INTEGER, b1 AS LONG
DIM a2 AS SINGLE, b2 AS SINGLE
DO
b1 = 0: b2 = 0
t = TIMER
a1 = 1
DO
  b1 = b1 + 1
LOOP WHILE b1 < 1000000
PRINT TIMER - t
t = TIMER
a2 = 1
DO
  b2 = b2 + 1
LOOP WHILE b2 < 1000000
PRINT TIMER - t
LOOP
Mac
Veteran
Posts: 151
Joined: Mon Aug 06, 2007 2:00 pm

Re: Slow fixed point math

Post by Mac »

[quote="Mac"]you do not have a clean $$$.[/quote]

The word "c o m p a r i s o n" was changed by the system to "$$$".

That's the strangest thing. Is "c o m p a r i s o n" a keyword?

When I try to edit my post, $$$ shows up like I originally typed it.

Mac

P.S. I tried "c x m p a r i s o n" and got the same result. Here is me typing that word without spaces: "$$$"
User avatar
Codemss
Veteran
Posts: 124
Joined: Sun Jun 24, 2007 6:49 am
Location: Utrecht, The Netherlands
Contact:

Post by Codemss »

OK, let me clearify:
I converted the program into fixed point math. Now, the program is much slower. But I used ffix (speeds floating point math up) for the floating point. So is floating point faster then fixed point when you use ffix?
(I admit that the julia fractal thing is a bit complex :P).

BTW, I am not suprised that one of the two manners is faster, but I'm suprised because the floating point version is faster, while everybody always screams that floating point math sucks etc.

Indeed weird that c o m p a r i s o n is censored (or something like it xD)
Check out my site: <a href="http://members.lycos.nl/rubynl">Click here</a>
Hope you like it. Send some feedback if you want: <a href="mailto:basicallybest@live.nl">Mail me</a>
Codemss, before known as RubyNL
Mac
Veteran
Posts: 151
Joined: Mon Aug 06, 2007 2:00 pm

Post by Mac »

Codemss wrote:I converted the program into fixed point math.
You say "everybody rants about INTEGER". True, but they mean applications where the user is working in whole numbers, for example x and y coordinates of the screen. They do not speak of converting applications from decimal numbers to whole numbers.

Below is an demo that sorts an array where all the numbers are in the range 1 to 99 and any number is at max 6 characters. Stuff like
6.4339 46.03 98.455 7.6348

One sort uses SINGLE. The other uses INTEGER.

The INTEGER sucks. That is because the effort to make the application work using INTEGER compares uses more time than INTEGER saves.

I imagine your conversion is analogous.

Mac

Code: Select all

CLS
PRINT "Move the mouse around for fair time tests"
PRINT "(Otherwise the window loses time to other tasks)"
PRINT
1
CONST TestSize = 500
DIM A(TestSize) AS STRING, B(TestSize) AS STRING
DIM i AS INTEGER, j AS INTEGER
RANDOMIZE TIMER
DO: Seed = RND * 999999: LOOP WHILE Seed < 99999 ' Test Start
' Build Test Data (strings which are numbers)
FOR i = 1 TO TestSize
  w$ = LTRIM$(STR$(1 + FIX(RND * 100000)))
  IF RND > .5 THEN
    w$ = LEFT$(w$, 1) + "." + MID$(w$, 2)
  ELSE
    w$ = LEFT$(w$, 2) + "." + MID$(w$, 3)
  END IF
  A(i) = w$: B(i) = w$
NEXT i
LINE INPUT "Press Enter to start test"; e$

' Sort these tables by their numeric data using SINGLE
x = RND(-Seed)' Just so RND is the same
PRINT "patience"; : LOCATE , 1
t = TIMER
FOR i = 1 TO TestSize - 1
  FOR j = i + 1 TO TestSize
    Ai! = VAL(A(i))
    Aj! = VAL(A(j))
    IF Ai > Aj THEN SWAP A(i), A(j)
  NEXT j
NEXT i
PRINT TIMER - t; "Time to sort using SINGLE"

FOR i = 1 TO TestSize - 1
  IF VAL(A(i)) > VAL(A(i + 1)) THEN STOP
NEXT i

'Sort these tables by their numeric data using INTEGER
PRINT "patience"; : LOCATE , 1
x = RND(-Seed)' Just so RND is the same
t = TIMER
FOR i = 1 TO TestSize - 1
  FOR j = i + 1 TO TestSize
    Bi$ = B(i): WHILE LEN(Bi$) < 6: Bi$ = Bi$ + "0": WEND
    IF INSTR(Bi$, ".") = 2 THEN
      Bi1% = VAL(MID$(Bi$, 1, 1))
      Bi2% = VAL(MID$(Bi$, 3))
    ELSE
      Bi1% = VAL(MID$(Bi$, 1, 2))
      Bi2% = VAL(MID$(Bi$, 4))
    END IF
    Bj$ = B(j): WHILE LEN(Bj$) < 6: Bj$ = Bj$ + "0": WEND
    IF INSTR(Bj$, ".") = 2 THEN
      Bj1% = VAL(MID$(Bj$, 1, 1))
      bj2% = VAL(MID$(Bj$, 3))
    ELSE
      Bj1% = VAL(MID$(Bj$, 1, 2))
      bj2% = VAL(MID$(Bj$, 4))
    END IF
    IF Bi1% > Bj1% THEN
       SWAP B(i), B(j)
    ELSEIF Bi1% = Bj1% THEN
       IF Bi2% > bj2% THEN SWAP B(i), B(j)
    END IF
  NEXT j
NEXT i
PRINT TIMER - t; "Time to sort using INTEGER"

FOR i = 1 TO TestSize - 1
  IF VAL(B(i)) > VAL(B(i + 1)) THEN STOP
NEXT i

' Final Test
FOR i = 1 TO TestSize
  IF A(i) <> B(i) THEN STOP: 'bug in program
NEXT i
LINE INPUT "Enter X to exit: "; e$
IF UCASE$(e$) <> "X" THEN RUN 1
CLS
SYSTEM
Post Reply