PDA

View Full Version : Function CheckPrime (plugin)



mixster
03-08-2008, 10:01 PM
After making a script to run through all the 11 digit prime numbers, I realised it ran excruciatingly slow. To make it just that lot better, I decided to import to Delphi then back via a plguin. It has 3 things to fill in - Number, which is the number you want to check (int64), divisible which is a var int64 and holds the number that Number can be divided by (if it's not prime) and lastly Debug (boolean) which outputs a lot of text with larger numbers (says what number it is currently testing, which number it is dividing Number by and the 2 numbers I use for the comparison, which conists of checking if Round(a)=a. The function then outputs a boolean, with true meaning it is prime and false meaning it's not. I'll probably remove the Debug bit as I just used that for making sure it worked completely, but not 100% sure yet.
Also, it's the same plugin as found in my '11 digit prime number' thread.
Edit: Tried without the debug and it run quite a lot faster, so I've made a new compact version. Enjoy!
Edit2: Added source code.

library CheckPrimePlugin_small;

uses
FastShareMem,
SysUtils,
Classes,
Windows,
Graphics;

{$R *.res}

type
TSCARPlugFunc = record
Name: string;
Ptr: Pointer;
end;

TOneStrProc = procedure(s: string);

var
Writeln: TOneStrProc;

function CheckPrime(number: Int64; var divisible: Int64): Boolean; stdcall;
var
i,ii: Int64;
a,b: Extended;
begin
ii:= Trunc(Sqrt(StrToFloat(IntToStr(number))))+2;
i:= 2;
Result:= True;
repeat
a:= number/i;
b:= Round(a);
if(a=b) then
begin
Result:= False;
divisible:= i;
Break;
end;
i:= i+1;
until(i>=ii);
if(number=2) then
Result:= True
else if(number=1) then
Result:= False;
end;


function GetFunctionCount(): Integer; stdcall; export;
begin
Result := 1;
end;

function GetFunctionInfo(x: Integer; var ProcAddr: Pointer; var ProcDef: PChar): Integer; stdcall;
begin
case x of
0:
begin
ProcAddr := @CheckPrime;
StrPCopy(ProcDef, 'function CheckPrime(number: Int64; var divisible: Int64): Boolean;');
end;
else
x := -1;
end;
Result := x;
end;

procedure SetFunctions(Funcs: array of TSCARPlugFunc); stdcall;
var
i: Integer;
begin
for i := 0 to Length(Funcs) - 1 do
if Funcs[i].Name = 'Writeln' then
Writeln := Funcs[i].Ptr;
end;

//***************************
// Don't change below this
exports GetFunctionCount;
exports GetFunctionInfo;
exports SetFunctions;

end.

Harry
03-08-2008, 10:03 PM
Nice, a registerd user making plugins :D Make a RS script and apply already ;)

mixster
03-08-2008, 10:22 PM
I'm too lazy to make RS scripts, not to mention I've stopped playing/autoing since jagex killed the game so meh. Anyway, it's not that big of a feat as it was pretty much a copy and paste of my final working scar version and then change a few other bits (TestPlugin.dpr ftw!) In fact, finding a delphi 7 download and making it work with Int64's was harder :)

bullzeye95
03-08-2008, 11:02 PM
Could you post the source please?

mixster
03-09-2008, 10:21 AM
Added the source to the first post. Also, 6 views and only 2 people have replied? It makes me feel cold and lonely inside :(

mastaraymond
03-09-2008, 10:29 AM
Added the source to the first post. Also, 6 views and only 2 people have replied? It makes me feel cold and lonely inside :(
You better get used to it ;). Thats the way it goes around here :(

Negaal
03-09-2008, 11:56 AM
Yeah, lately I just feel post, not that I want to get that cup. But just, why should I? What does it gives to me?

...err, postcount.

Anyways your plugin is nice, actually not the code is not so much worth to mention but that you made a plugin. xD

And yes, wanted to say that scar's debug box outputs are slow.

Freddy haven't made IntToFloat yet...? =/

Edit: Actually, I can't understand nothing what the Checkprime() does.
Since my math sucks. now, in american system, it could say it's F at the moment.

Edit: Completely understand you, what you don't want to make a Rs script. it's boring. i'd like to something what has to deal with some big math. since im stupid, I can't. Or some nice functions, I like to do aswell.

Edit:
program New;
var
t, i : integer;
begin
t := getsystemtime;
for i:=0 to 999 do
writeln('');
writeln(inttostr(getsystemtime - t))
end.

Always aproch 1800-1850.

mixster
03-09-2008, 07:21 PM
CheckPrime just checks if a number is prime (as only has 2 whole number multiples - 1 and itself). If it is, it returns true, if not it returns false. If it's false, then the variable divisible holds the lowest number that is divisible by it (like when checking 6, it outputs false and assigns divisible 2).
My next plugin will hopefully use something a bit more sophisticated than that (looking at another method of finding prime numbers) and also checks a range of numbers, like 100 to 1000, then outputs as an array of integers, though I don't know if delphi can output arrays - always gives me an error when I try to...
Also, I wasn't talking about the Writeln's running slowly (though they do - when using checking around 50,000 numbers, it took longer to write them out than check the numbers :p). It takes 5 minutes+ for the scar script to check 10000000001, while the plugin takes under a second, now that's quick :)
Post counts are great though - they help expand your virtual penis as long as you have enough free time!

Rikje
03-09-2008, 07:24 PM
Dude thats nice :)

just one side note: why all those Prime checkers these days? :p

sherlockmeister
03-10-2008, 07:54 PM
your really wouldn't need to compile it if the algorithm was better like this
program new;

var
Time: Integer;
Primes: array of Integer;

function CheckPrime(Number: Integer): Boolean;
var
I, II, Sqrt1, Sqrt2: Integer;
Prime: Boolean;
begin
Number := Round(Abs(Number));
if Number < 4 then
begin
Result := true;
Exit;
end;
if Number mod 2 = 0 then
begin
Result := false;
Exit;
end;
Sqrt1 := Round(Sqrt(Number));
for I := 0 to High(Primes) do
begin
if Primes[I] > Sqrt1 then
begin
Result := true;
Exit;
end;
if Number mod Primes[I] = 0 then
begin
Result := false;
Exit;
end;
I := I + 1;
end;
if Length(Primes) > 0 then
I := Primes[High(Primes)] + 2
else
I := 3;
while Sqrt1 > I - 1 do
begin
Sqrt2 := Trunc(Sqrt(I));
Prime := true;
for II := 0 to High(Primes) do
begin
if Primes[II] > Sqrt2 then Break;
if I mod Primes[II] = 0 then
begin
Prime := false;
Break;
end;
II := II + 1;
end;
if Prime then
begin
if Number mod I = 0 then
begin
Result := false;
Exit;
end;
SetLength(Primes, Length(Primes) + 1);
Primes[High(Primes)] := I;
end;
I := I + 2;
end;
Result := true;
end;

begin
Time := GetTimeRunning;
WriteLn(BoolToStr(CheckPrime(22307 * 22307)));
WriteLn(IntToStr(GetTimeRunning - Time));
Time := GetTimeRunning;
WriteLn(BoolToStr(CheckPrime(2038074743)));
WriteLn(IntToStr(GetTimeRunning - Time));
Time := GetTimeRunning;
WriteLn(BoolToStr(CheckPrime(2147483647)));
WriteLn(IntToStr(GetTimeRunning - Time));
end.
solves a prime that it almost as large as the max int value in about 4500 ms
edit: you're right my code was slightly wrong, this will be much faster considering it caches the primes

mixster
03-10-2008, 08:32 PM
Mine solves any int number up to the Int64 limit in like under a second. The whole point of delphi plugins is to save time or do something that you are unable to do in Scar. Please don't disrespect my plugin, it's awesome :) (and will also have the CheckPrimeRange child soon using a faster, more efficient way, rather than checking all numbers individualy). Edit: I also checked a few numbers using your method, and it got 2038074747 wrong - it can be divided by 3 :) And I also got my CheckPrimeRange sorted and now just making sure it works 100% and is user-friendly. Had to use a custom type to return though as delphi doesn't let you return array's for functions, but ahwell, atleast it works.

mastaraymond
03-11-2008, 06:45 PM
Mine solves any int number up to the Int64 limit in like under a second. The whole point of delphi plugins is to save time or do something that you are unable to do in Scar. Please don't disrespect my plugin, it's awesome :) (and will also have the CheckPrimeRange child soon using a faster, more efficient way, rather than checking all numbers individualy). Edit: I also checked a few numbers using your method, and it got 2038074747 wrong - it can be divided by 3 :) And I also got my CheckPrimeRange sorted and now just making sure it works 100% and is user-friendly. Had to use a custom type to return though as delphi doesn't let you return array's for functions, but ahwell, atleast it works.

Return a known type? TIntegerArray :rolleyes:

mixster
03-11-2008, 06:59 PM
I tried that (I think) but delphi's mean and making a custom type seemed the only option (I even googled it) and it will be imported with the plugin anyway, but I'll double-check anyway (I just use cTInteger defined as an array of Integer, so atleast I know it works). I'm also not sure how often to return info in the plugin as it can take a while when checking large ranges - have it set up to every 5% of numbers it goes through it writes a line out. Not sure how much it slows down the procedure, but it doesn't appear to seriously affect it.
Edit: Delphi doesn't have TIntegerArray, but I'll try using that and see if scar uses the ordinary one over it when assigning.
Edit2: It works... kind of... only problem is I use Int64's and TIntegerArray holds regular Int's, so I'm still going to have to go with a custom type to hold the data. Ahwell