[fpc-pascal]isprime()

Anton Tichawa anton.tichawa at chello.at
Sun Feb 9 13:52:26 CET 2003


Hi, Franco Milani!

To me it seems that your function works properly. I compared the results for 
all cardinal values, using your algorithm (cprimes_v.create below) against 
the results of my own algorithm (cprimes_m.create below), which I updated to 
32 bits tonight. All I changed in your function (isprime) is that I renamed 
it to 'is_prime' and moved the constants and variables into the function's 
context. The comparison was done file-to-file (about 257 MB).

The report file may shed some light on the timing trend behaviour of the 
algorithms - see report below. Note that due to a bug, my primes_m num_primes 
values shown are too low by 1 for all but the last two runs (bug).

As I use a different algorithm, the function may be considered to be tested 
by diversification (?).

Shouldn't the function behaviour for n = 0 be discussed? Maybe it's worth 
thinking about returning true or even throwing an exception for n = 0?

Compared to yours, my approach to primes is a 'synthetic' one - I build a 
series of primes to work with, whereas you analytically check one single 
number for primality. Did you know that using a series of primes as input to 
'turtle graphics', where prime modulos determine turtle movement, and each 
turtle move changes pixel colors, leads to very impressive images?

A note on efficiency: On a typical PC, with enough memory but performance 
needs, it might be better to use a one-time created table instead of run-time 
calculation. When the the sieve of Erasthotenes (?) is applied with a defined 
order, there is a relation of similar order from a given cardinal number to 
the number (index) within the set of "sieved" numbers. The table then holds a 
primality flag for each "sieved" number. The table is calculated once, and 
allows very fast primality checking: At runtime, the sieve is applied, and 
those numbers "falling through the sieve" are looked up in the table. The 
higher the order, the smaller the table. But that's an idea - it's not coded 
yet. The most simple example is a table that contains at index (n div 2) a 
primality flag for each odd number (sieve order 1), and holds high(cardinal) 
div 2 entries.

In the first lines of assembly, I found a possible optimization, so I dared 
skipping the rest of the assembly text. This optimization would be checking > 
66 instead of > 61, which speeds up the function for the non-prime numbers 62 
.. 66.

here's my procedure testing your algorithm:

constructor cprimes_v.create(aname: string);
var
  i: cardinal;
  s: string;  // -tbo-
  fc: coutputtextfile;  // -tbn- the common report file
  f: coutputtextfile;
  my_num_primes: cardinal;
  duration: cardinal;
begin
  log('* cprimes_v.create');
  duration := getabsticks;
  my_num_primes := 0;
  fc := coutputtextfile.create('/io/txt/primes.txt');
  fc.append;
  f := coutputtextfile.create('/io/txt/primes_v.txt');
  inherited create(aname);
  for i := 0 to max_prime_mask do begin
    if is_prime(i) then begin
      s := intstr(i);
      f.writeln(s);
      inc(my_num_primes);
      // add_string(s);
    end;
  end;
  duration := getabsticks - duration;
  fc.writeln('primes_v:');
  fc.writeln('  max_prime_mask ' + intstr(max_prime_mask, 10));
  fc.writeln('  num_primes     ' + intstr(my_num_primes, 10));
  fc.writeln('  duration (ms)  ' + intstr(duration, 10));
  fc.free;
  f.free;
  log('+ cprimes_v.create');
end;

here's my procedure testing my algorithm:

constructor cprimes_m.create(aname: string);
var fc: coutputtextfile;  // -tbn- common report file
var f: coutputtextfile;
var i: cardinal;
var j: cardinal;
var q: cardinal;
var my_num_roots: cardinal;
var my_num_primes: cardinal;
var my_primes: array [0 .. max_prime_root - 1] of cardinal;
var my_overrun: boolean;
var duration: cardinal;
begin
  log('* cprimes.create');
  inherited create(aname);
  fc := coutputtextfile.create('/io/txt/primes.txt');
  fc.append;
  f := coutputtextfile.create('/io/txt/primes_m.txt');
  duration := getabsticks;
  my_num_primes := 1;
  my_primes [0] := 2;
  my_num_roots := 1;
  f.writeln('2');  // -tbo-
  i := 3;
  my_overrun := false;
  repeat
    for j := 0 to my_num_roots - 1 do begin
      q := my_primes [j];
      // log('checking i ' + intstr(i) + ' q ' + intstr(q));
      if (i div q) * q = i then begin
        // log('  no');
        break;
      end;
      // log('  yes');
      if q * q >= i then begin
        inc(my_num_primes);
        f.writeln(intstr(i));
        if my_num_roots < max_prime_root then begin
          my_primes [my_num_roots] := i;
          inc(my_num_roots);
        end;
        break;
      end;
    end;
    if my_overrun then begin
      break;
    end;
    if i >= max_prime_mask then begin
      break;
    end;
    inc(i);
  until false;
  if my_overrun then begin
    f.writeln('overrun');
  end;
  duration := getabsticks - duration;
  fc.writeln('primes_m:');
  fc.writeln('  max_prime_mask ' + intstr(max_prime_mask, 10));
  fc.writeln('  num_primes     ' + intstr(my_num_primes, 10));
  fc.writeln('  duration (ms)  ' + intstr(duration, 10));
  fc.free;
  f.free;
  log('+ cprimes.create');
end;

here's the report (file '/io/txt/primes.txt'):

primes_m:
  max_prime_mask     999999
  num_primes          78497  // should read 78498
  duration (ms)        1347
primes_v:
  max_prime_mask     999999
  num_primes          78498
  duration (ms)        1526
primes_m:
  max_prime_mask    9999999
  num_primes         664578  // .. '9
  duration (ms)       27956
primes_v:
  max_prime_mask    9999999
  num_primes         664579
  duration (ms)        9619
primes_m:
  max_prime_mask    3999999
  num_primes         283145  // .. '6
  duration (ms)        8757
primes_v:
  max_prime_mask    3999999
  num_primes         283146
  duration (ms)        3764
primes_m:
  max_prime_mask   39999999
  num_primes        2433653  // .. '4
  duration (ms)      172097
primes_v:
  max_prime_mask   39999999
  num_primes        2433654
  duration (ms)       44459
primes_m:
  max_prime_mask   99999999
  num_primes        5761454  // .. '5
  duration (ms)      582844
primes_v:
  max_prime_mask   99999999
  num_primes        5761455
  duration (ms)      114538
primes_m:
  max_prime_mask  499999999
  num_primes       26355867  // ok
  duration (ms)     5146543
primes_v:
  max_prime_mask  499999999
  num_primes       26355867
  duration (ms)      606424
primes_m:
  max_prime_mask       9999
  num_primes           1229  // ok
  duration (ms)         357
primes_v:
  max_prime_mask       9999
  num_primes           1229
  duration (ms)         358

Another note: During inclusion of your sources, I had to convert characters 
of order 160 (0xA0) to spaces - where do those characters come from?

Hope this Helps.

Anton Tichawa.



----------

"Adas Methode war, wie sich zeigen wird, Tagträume in offenbar korrekte 
Berechnungen einzuweben."

Doris Langley Moore: Ada, Countess of Lovelace (London 1977).

----------

Anton Tichawa
Volkertstrasse 19 / 20
A-1020 Wien
mobil: +43 664 52 07 907
email: anton.tichawa at chello.at

----------



More information about the fpc-pascal mailing list