Big Integers in Turbo Pascal 3.01A (4)

As promised, time for a little bit of benchmarking using a common prime number algorithm. To build a little suspense, I compiled and ran my code under Free Pascal 3.04 on a Raspberry Pi B – an original 2012 version with 256Mb RAM that normally does duty as my audio server.

Sieve of Eratosthenes

The algorithm used (BigInt version) is in the code snippet below. The inbuilt Integer version is identical, swapping BigInts for Integers (or LongInts (32 bit) on the Raspberry Pi version) and the comparison, square root, modulo and add functions for their inbuilt counterparts.

...

type Primea = array [1..255] of BigInt;
var primearray: Primea;
    limit, next: BigInt;
    primecount : Integer;

function sieve(var number: BigInt; var pc: integer; var p: primea): boolean;
var count :Integer;
var sr, test :BigInt;
var foundprime :Boolean;
begin
  sr := isqrt(number);
  count := 1;
  foundprime := TRUE;
  while ((count <= pc) and foundprime) do begin
    test := p[count];
    if le(test,sr) and (modulo(number,test)='0') then
      foundprime := FALSE;
    count := count+1
  end;
  sieve := foundprime
end;

begin
   limit := '100'; { Find all primes less than limit }
   primecount := 0;
   next := '3';
   write('2');
   while (le(next,limit)) do
   begin
     if sieve(next,primecount,primearray) then
     begin
       if primecount < 255 then
       begin
         primecount := primecount+1;
         primearray[primecount] := next
       end;
       write(', ',next)
     end;
     next := add(next,'2')
   end;
   writeln(' ')
end.

Raspberry Pi Model B Results

All primes < nInbuilt LongInt (32 bit) typeBigInt typePerformance difference (magnitude)
1000.02s0.07s3.5x
1,0000.05s0.97s19.4x
10,0000.27s16.5s61.1x
32,000 (*)0.85s71.0s83.5x
100,0002.3s302s131x
1,000,00022.3s5,993s269x
(*) Chosen to be close to the standard 16 bit Pascal integer type limit of 32,767

Unsurprisingly the library is slower than using an inbuilt type … but it gets exponentially slower as the number of primes generated increases. This suggests there’s plenty of room for improvement!

If you’re of a nervous disposition, look away now as I’m about to attempt the same benchmark on a RC2014 with 64K RAM with a Z80 processor under CP/M. This may take some time …

RC2014 Results

All primes < nInbuilt Integer (16 bit) typeBigInt typePerformance difference (magnitude)
1001s73s73x
5004s912s228x
1,00010s
10,000140s
32,000445s
Corrected table (27/05/2023), after finding that I’d commented out some error checking code only when I started to implement some optimisations … d’oh! And the performance of my library is far worse than I thought.

Even allowing for the difference in computational speed of a Z80 processor running at 7.3728MHz and a single core ARM1176JZF-S running at 700MHz, these figures indicate that there’s plenty of optimisation potential left to find, or alternatively, that I should stop working on this project now. But where would be the fun in that?

The results of a walk and a long lunch … all the primes to 3,067 in a mere 3 hours or so. I don’t think we’re going to break any speed records here …

The fifth and final post in this series will cover some thoughts on optimisation and provide a link to all the code I’ve produced so far, should anyone else feel inclined to take this further.