Qbasicnews.com

Full Version: FB not a number-cruncher?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
I have tested this old prime number generator, by Rich Geldreich.
Uses a priority queue instead of a sieve.All integer...

Timings for primes from 2 to 100,000,000
Code:
Freebasic         730 sec
QB4.5             191 sec
DevC++4.01         12 sec

The original QB version used a buffer to write to file.
The buffer is not present in the FB and DEV C versions.

Is FreeBasic slower than QB when graphics are not involved?

This is the FB source.
Code:
'Prime number generator
DEFINT A-Z
option explicit
DECLARE SUB PutPrime (a&)
CONST HeapSize = 9000
OPEN "primebuf.bin" FOR OUTPUT AS #1: CLOSE #1
OPEN "primebuf.bin" FOR BINARY AS #1

dim dd as byte
DIM SHARED LastPrime&
dim SHARED tt!
dIM HeapQ(1 TO HeapSize) AS LONG
DIM HeapQ1(1 TO HeapSize) AS LONG
DIM HeapQ2(1 TO HeapSize) AS LONG
dim mprime&
DIM SHARED candid AS LONG
DIM t AS LONG
DIM Q AS LONG, Q1 AS LONG, Q2 AS LONG
DIM TQ AS LONG, TQ1 AS LONG
DIM u AS LONG,d as long
dim r as integer,r2 as integer,i as integer, j as integer,cnt%,a as integer, b as integer
dim k$

Lastprime&=5
candid = 7
CNT=3
d = 4
r = 1
r2=r+1
t=25
HeapQ(1) = 25
HeapQ1(1) = 10
HeapQ2(1) = 30
tt! = TIMER

INPUT "Max prime:"; mprime&
DO  
  
  DO
    Q = HeapQ(1)
    Q1 = HeapQ1(1)
    Q2 = HeapQ2(1)

    TQ = Q + Q1
    TQ1 = Q2 - Q1

    i = 1
    DO
        j = i shl 1
        IF j <= r THEN
            IF j < r THEN
                IF HeapQ(j) > HeapQ(j + 1) THEN
                  j = j + 1
                END IF
            END IF

            IF TQ > HeapQ(j) THEN
                HeapQ(i) = HeapQ(j)
                HeapQ1(i) = HeapQ1(j)
                HeapQ2(i) = HeapQ2(j)
                i = j
            ELSE
                EXIT DO
            END IF
        ELSE
            EXIT DO
        END IF
    LOOP
    HeapQ(i) = TQ
    HeapQ1(i) = TQ1
    HeapQ2(i) = Q2
    '***

  LOOP UNTIL candid <= Q

  DO WHILE candid < Q
  ' print candid;
    dd=(candid-lastprime&) shr 1
    put #1,,dd
    lastprime&=candid
    cnt%=cnt%+1
    if (cnt% and &h1fFFF)=0 then locate 2,1: print cnt%;" primes ";candid
    if r2<=Heapsize then
      HeapQ(r2)=candid
      r2=r2+1
    end if
    candid = candid + d
    d = 6 - d
  LOOP

  IF candid = t THEN

    u = HeapQ(r+1)
    t = u * u

    j = r + 1
    DO
      i = j shr 1
      IF i = 0 THEN
        EXIT DO
      END IF
      IF HeapQ(i) <= t THEN
        EXIT DO
      END IF
      HeapQ(j) = HeapQ(i)
      HeapQ1(j) = HeapQ1(i)
      HeapQ2(j) = HeapQ2(i)
      j = i
    LOOP
    '***
    HeapQ(j) = t
    IF (u MOD 3) = 2 THEN
      HeapQ1(j) =  u shl 1
    ELSE
      HeapQ1(j) =  u shl 2
    END IF
    HeapQ2(j) = 6 * u

    r = r + 1

  END IF

  candid = candid + d
  d = 6 - d

LOOP until r>= HeapSize or LEN(INKEY$)>0 or candid > mprime&
print cnt%;" primes in "; timer-TT! ;" seconds"
close #1
OPEN "primebuf.bin" FOR BINARY AS #1
k$=input$(1)
cls
locate 1,2:print "2"
locate 1,12:print "3"
locate 1,22:print "5"

lastprime&=5
cnt%=3
while not eof(1)
get #1,,dd
candid=lastprime&+(dd shl 1)
I=1+(cnt%\8)
j=1+10*(cnt% mod 8)
locate i,j

print candid,
lastprime&=candid
cnt%=cnt%+1
if cnt%=200 then cnt%=0
wend
close #1
k$=input$(1)
end
It could be the screen/file io that is slow and not the math (thats not exactly a good test for math purely) but it is a bit sad. Im still betting if the print/put routines were speeded up that it would fly.

Btw, how many times did you test the results?
C'mon, it's simple to see.. erase that inkey$, testing number crunching and involving the OS at same time, eh? That has nothing to do with FB, Windows will try to idle the current process when getkey's is called, i can bet it..

Results:

C:\prg\code\bas\FREEBA~1>fbprimes.exe

Calculating: 1000000000 max primes, please wait...............................
3720273 primes in 8.547 seconds

C:\prg\code\bas\FREEBA~1>qbprimes.exe

Calculating: 1000000000 max primes, please wait...............................
3720273 primes in 39.2734375 seconds


Test it by yourselves: http://freebasic.bad-logic.com/downloads/primes.zip

The only difference between both is this line:
Code:
dim dd as short 'integer
Otherwise FB would save twice as more data if INTEGER was used, ast ints are 32-bit in FB.
V1ctor:

You're right!
The C version was'nt checking for a key at each loop...:oops:


But you did a little unfair change to my code: you reduced the heapsize to 1000. Heapsize should be 3100 or bigger to hold all primes up to the SQRT of the maximum candidate 1e9. So you were checking each candidate against less divisors than required...

By increasing the heapsize to 4096 I got these results:

DevC 143 seconds
FB 0.06 220 seconds

Not bad at all!!!! :bounce:

I did'nt tested QB for the correct heapsize, it should need around 30 minutes. :barf:
Yeah, i used 1000 coz othewise the QB version would need dynamic arrays, what wouldn't be fair.

Anyway, the results with the original 9000 heap size was:

C:\prg\code\bas\freeBASIC>primes

Calculating: 1000000000 max primes, please wait.................................
................................................................................
................................................................................
................................................................................
................................................................................
.....................................
50847534 primes in 163.89 seconds

I gave up the qb version after 5 minutes.. had to use 2 Redim's on HeapQ1 and HeapQ2, what slowed it too much.. a 100mb result file is created, ouch..
All this explains a curious thing that puzzled me:
The version with INKEY$ ran MUCH faster in a slow portable with W98 than in my faster desktop with W2000.
It must be that W98 handles keyboard input a lot faster than W2000...
Win98 doesent put DOS programs (console programs) in suspend mode if they just sit there without receiveing use input.

If you never ask for input the program is never put in suspend mode.