Logtalk 2.28.2 files.

git-svn-id: https://yap.svn.sf.net/svnroot/yap/trunk@1713 b08c6af1-5177-4d33-ba66-4b1c6b8b522a
This commit is contained in:
pmoura
2006-11-07 18:47:24 +00:00
parent 2d7ccc1278
commit 3ac73c8881
36 changed files with 2454 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
=================================================================
Logtalk - Object oriented extension to Prolog
Release 2.28.2
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
=================================================================
This folder contains some examples of multi-threading programming.
Multi-threading programming is only supported on some Prolog compilers.
Currently this includes SWI-Prolog and YAP. Moreover, multi-threading
is turned off by default. In order to run the examples, you will need
to first turn on multi-threading support on the Prolog config files.

View File

@@ -0,0 +1,19 @@
=================================================================
Logtalk - Object oriented extension to Prolog
Release 2.28.2
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
=================================================================
To load this example and for sample queries, please see the SCRIPT file.
This folder contains a simple multi-threading example illustrating the
use of the "atomic" option on threaded_call/2 calls to cope with methods
that have side-effects.
The object defined in the example source file, "atomic.lgt", defines a
predicate named waste_time/0 that is used to delay the execuion of goals
in order to better illustrate the semantics of the "atomic" option. This
predicate uses a counter that you might need to adjust, depending on your
Prolog compiler and computer performance.

View File

@@ -0,0 +1,71 @@
=================================================================
Logtalk - Object oriented extension to Prolog
Release 2.28.2
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
=================================================================
% start by loading the loading the example:
| ?- logtalk_load(atomic(loader)).
...
% send three asynchronous messages whose corresponding methods perform output operations:
| ?- threaded_call(nasty1::io(alpha), [noreply]), threaded_call(nasty1::io(digit), [noreply]), threaded_call(nasty1::io(alpha), [noreply]).
a0ab1bc2c3ddefef45gg6hh7ii8jkjk9
llmmnnopopqqrrsstztzyyxxwwuv
uv
Yes
% the same three asynchronous messages but making them atomic for the receiver object:
| ?- threaded_call(nasty1::io(alpha), [atomic, noreply]), threaded_call(nasty1::io(digit), [atomic, noreply]), threaded_call(nasty1::io(alpha), [atomic, noreply]).
abcdefghijklmnopqrstzyxwuv
0123456789
abcdefghijklmnopqrstzyxwuv
Yes
% send three asynchronous messages whose corresponding methods perform database updates
% (this may or may not work, most likely will throw an exception):
| ?- threaded_call(nasty1::update_db(_), [noreply]), threaded_call(nasty1::update_db(_), [noreply]), threaded_call(nasty1::update_db(_), [noreply]).
No
% the same three asynchronous messages but making them atomic for the receiver object
% (this should always work):
| ?- threaded_call(nasty1::update_db(_), [atomic, noreply]), threaded_call(nasty1::update_db(_), [atomic, noreply]), threaded_call(nasty1::update_db(_), [atomic, noreply]).
Yes
% a better solution is to declare predicates that need to be thread syncronized as "atomic",
% as exemplified in object "nasty2":
| ?- nasty2::(io(alpha), io(digit), io(alpha)).
abcdefghijklmnopqrstzyxwuv
0123456789
abcdefghijklmnopqrstzyxwuv
Yes
| ?- nasty2::(update_db(X), update_db(Y), update_db(Z)).
X = 1
Y = 2
Z = 3
Yes

View File

@@ -0,0 +1,121 @@
:- object(nasty1).
:- info([
version is 1.0,
author is 'Paulo Moura',
date is 2006/04/14,
comment is 'Simple example for using the "atomic" option for multi-threading calls with side-effects.']).
:- threaded.
:- public(update_db/1).
:- mode(update_db(-integer), one).
:- info(update_db/1, [
comment is 'Perform a database update with a long delay between retracting the old information and asserting the new one.',
argnames is ['New']]).
:- private(db/1).
:- dynamic(db/1).
:- public(io/1).
:- mode(io(+atom), one).
:- info(io/1, [
comment is 'Write some characters to the standard output stream with a long delay between each write operation.',
argnames is ['Chars']]).
db(0).
update_db(New) :-
retract(db(Old)),
waste_time,
New is Old + 1,
waste_time,
assertz(db(New)).
io(alpha) :-
write(a), waste_time, write(b), waste_time, write(c), waste_time, write(d), waste_time, write(e),
write(f), waste_time, write(g), waste_time, write(h), waste_time, write(i), waste_time, write(j),
write(k), waste_time, write(l), waste_time, write(m), waste_time, write(n), waste_time, write(o),
write(p), waste_time, write(q), waste_time, write(r), waste_time, write(s), waste_time, write(t),
write(z), waste_time, write(y), waste_time, write(x), waste_time, write(w), waste_time, write(u),
write(v), nl.
io(digit) :-
write(0), waste_time, write(1), waste_time, write(2), waste_time, write(3), waste_time, write(4),
write(5), waste_time, write(6), waste_time, write(7), waste_time, write(8), waste_time, write(9), nl.
waste_time :-
between(1, 10000, _),
fail.
waste_time.
between(Lower, _, Lower).
between(Lower, Upper, Integer) :-
Lower < Upper,
Next is Lower + 1,
between(Next, Upper, Integer).
:- end_object.
:- object(nasty2).
:- info([
version is 1.0,
author is 'Paulo Moura',
date is 2006/04/14,
comment is 'Simple example for using the "atomic" option for multi-threading calls with side-effects.']).
:- threaded.
:- public(update_db/1).
:- atomic(update_db/1).
:- mode(update_db(-integer), one).
:- info(update_db/1, [
comment is 'Perform a database update with a long delay between retracting the old information and asserting the new one.',
argnames is ['New']]).
:- private(db/1).
:- dynamic(db/1).
:- public(io/1).
:- atomic(io/1).
:- mode(io(+atom), one).
:- info(io/1, [
comment is 'Write some characters to the standard output stream with a long delay between each write operation.',
argnames is ['Chars']]).
db(0).
update_db(New) :-
retract(db(Old)),
waste_time,
New is Old + 1,
waste_time,
assertz(db(New)).
io(alpha) :-
write(a), waste_time, write(b), waste_time, write(c), waste_time, write(d), waste_time, write(e),
write(f), waste_time, write(g), waste_time, write(h), waste_time, write(i), waste_time, write(j),
write(k), waste_time, write(l), waste_time, write(m), waste_time, write(n), waste_time, write(o),
write(p), waste_time, write(q), waste_time, write(r), waste_time, write(s), waste_time, write(t),
write(z), waste_time, write(y), waste_time, write(x), waste_time, write(w), waste_time, write(u),
write(v), nl.
io(digit) :-
write(0), waste_time, write(1), waste_time, write(2), waste_time, write(3), waste_time, write(4),
write(5), waste_time, write(6), waste_time, write(7), waste_time, write(8), waste_time, write(9), nl.
waste_time :-
between(1, 100000, _),
fail.
waste_time.
between(Lower, _, Lower).
between(Lower, Upper, Integer) :-
Lower < Upper,
Next is Lower + 1,
between(Next, Upper, Integer).
:- end_object.

View File

@@ -0,0 +1,13 @@
:- initialization(
logtalk_load(
atomic)).
/*
If you intend to use the FOP XSL:FO processor for generating PDF documenting
files, comment the directive above and uncomment the directive below
:- initialization(
logtalk_load(
atomic, [xmlsref(standalone)])).
*/

View File

@@ -0,0 +1,12 @@
=================================================================
Logtalk - Object oriented extension to Prolog
Release 2.28.2
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
=================================================================
To load this example and for sample queries, please see the SCRIPT file.
This folder contains a simple multi-threading example with agents and
their birthdays.

View File

@@ -0,0 +1,52 @@
=================================================================
Logtalk - Object oriented extension to Prolog
Release 2.28.2
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
=================================================================
% start by loading the "event_handlersp" protocol:
| ?- logtalk_load(library(event_handlersp)).
...
% now you are ready for loading the example:
| ?- logtalk_load(birthdays(loader)).
...
% create two new agents, Paul and Nathalie:
| ?- agent::(new(paul, 40, male), new(nathalie, 32, female)).
Yes
% make them friends:
| ?- paul::new_friend(nathalie).
Yes
% it's birthday for Nathalie:
| ?- nathalie::birthday.
Happy birthday from paul!
Thanks! Here, have a slice of cake, paul.
Thanks for the cake nathalie!
Yes
% tell Paul to ask Nathalie her age:
| ?- paul::ask_age(nathalie, Age).
Age = 33
Yes

View File

@@ -0,0 +1,90 @@
:- object(agent,
implements(event_handlersp)).
:- info([
version is 1.0,
author is 'Peter Robinson and Paulo Moura',
date is 2006/04/09,
comment is 'Simple multi-threading example with agents and their birthdays.']).
:- threaded.
:- public(new/3).
:- mode(new(+atom, +integer, +atom), one).
:- info(new/3, [
comment is 'Creates a new agent given its name, age, and gender.',
argnames is ['Name', 'Age', 'Gender']]).
:- public(age/1).
:- dynamic(age/1).
:- mode(age(?integer), zero_or_one).
:- info(age/1, [
comment is 'Agent age.']).
:- public(ask_age/2).
:- mode(ask_age(+atom, ?integer), zero_or_one).
:- info(ask_age/2, [
comment is 'Ask a friend his/her age.',
argnames is ['Name', 'Age']]).
:- public(gender/1).
:- dynamic(gender/1).
:- mode(gender(?integer), zero_or_one).
:- info(gender/1, [
comment is 'Agent gender.']).
:- public(birthday/0).
:- mode(birthday, one).
:- info(birthday/0, [
comment is 'Increments an agent age, an unfortunate side-effect of its birthday.']).
:- public(happy_birthday/1).
:- mode(happy_birthday(+object_identifier), one).
:- info(happy_birthday/1, [
comment is 'Happy birthday message from a friend.',
argnames is ['From']]).
:- public(cake_slice/1).
:- mode(cake_slice(+object_identifier), one).
:- info(cake_slice/1, [
comment is 'Offer a slice of birthday cake to a friend.',
argnames is ['From']]).
:- public(new_friend/1).
:- mode(new_friend(+object_identifier), one).
:- info(new_friend/1, [
comment is 'New friend, watch out for his/her birthday.',
argnames is ['Name']]).
new(Name, Age, Gender) :-
this(This),
create_object(Name, [extends(This)], [threaded], [age(Age), gender(Gender)]).
ask_age(Friend, Age) :-
threaded_call(Friend::age(Age)),
threaded_exit(Friend::age(Age)).
birthday :-
::retract(age(Old)),
New is Old + 1,
::assertz(age(New)).
happy_birthday(From) :-
self(Self),
write('Happy birthday from '), write(From), write('!'), nl,
write('Thanks! Here, have a slice of cake, '), write(From), write('.'), nl,
threaded_call(From::cake_slice(Self), [noreply]).
cake_slice(From) :-
write('Thanks for the cake '), write(From), write('!'), nl.
new_friend(Friend) :-
self(Self),
define_events(after, Friend, birthday, _, Self).
after(Friend, birthday, _) :-
self(Self),
threaded_call(Friend::happy_birthday(Self), [noreply]).
:- end_object.

View File

@@ -0,0 +1,13 @@
:- initialization(
logtalk_load(
[birthdays], [events(on)])).
/*
If you intend to use the FOP XSL:FO processor for generating PDF documenting
files, comment the directive above and uncomment the directive below
:- initialization(
logtalk_load(
[birthdays], [events(on), xmlsref(standalone)])).
*/

View File

@@ -0,0 +1,14 @@
=================================================================
Logtalk - Object oriented extension to Prolog
Release 2.28.2
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
=================================================================
To load this example and for sample queries, please see the SCRIPT file.
This folder contains a simple multi-threading example illustrating how
to create threads for competing goals, which one performing the same
task using diferent methods. The first goal to complete leads to the
immediate termination of the threads running the remaining goals.

View File

@@ -0,0 +1,65 @@
=================================================================
Logtalk - Object oriented extension to Prolog
Release 2.28.2
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
=================================================================
% start by loading the loading the example:
| ?- logtalk_load(functions(loader)).
...
% find the roots of some functions using each one of provided methods:
| ?- bisection::find_root(f1, 1.0, 2.3, 1e-15, Zero).
Zero = 2.0
yes
| ?- newton::find_root(f1, 1.0, 2.3, 1e-15, Zero).
Zero = 2.0
yes
| ?- muller::find_root(f1, 1.0, 2.3, 1e-15, Zero).
Zero = 2.0
yes
| ?- bisection::find_root(f2, 1.0, 1.3, 1e-15, Zero).
Zero = 1.25809265664599
yes
| ?- newton::find_root(f2, 1.0, 1.3, 1e-15, Zero).
Zero = 1.25809265664599
yes
| ?- muller::find_root(f2, 1.0, 1.3, 1e-15, Zero).
Zero = 1.25809265664599
yes
% find the roots of some functions running all methods at once using multi-threading:
| ?- function_root::find_root(f1, 1.0, 2.3, 1e-15, Zero, Method).
Zero = 2.0
Method = bisection
yes
| ?- function_root::find_root(f2, 1.0, 1.3, 1e-15, Zero, Method).
Zero = 1.25809265664599
Method = newton
yes
| ?- function_root::find_root(f3, 0.0, 3.0, 1e-15, Zero, Method).
Zero = 1.4142135623731
Method = newton
yes

View File

@@ -0,0 +1,268 @@
:- protocol(find_rootp).
:- info([
version is 1.0,
date is 2006/4/21,
author is 'Paulo Nunes',
comment is 'Default protocol for root find algorithms.']).
:- public(find_root/5).
:- mode(find_root(+object_identifier, +float, +float, +float, -float), one).
:- info(find_root/5, [
comment is 'Find the root of a function in the interval [A, B] given a maximum aproximation error.',
argnames is ['Function', 'A', 'B', 'Error', 'Zero']]).
:- public(find_root/6).
:- mode(find_root(+object_identifier, +float, +float, +float, -float, -object_identifier), one).
:- info(find_root/6, [
comment is 'Find the root of a function in the interval [A, B] given a maximum aproximation error. Return the method used.',
argnames is ['Function', 'A', 'B', 'Error', 'Zero', 'Method']]).
:- end_protocol.
:- protocol(functionp).
:- info([
version is 1.0,
date is 2006/4/21,
author is 'Paulo Nunes',
comment is 'Default protocol for real functions of a single real variable.']).
:- public(eval/2).
:- mode(eval(+float, -float), one).
:- info(eval/2, [
comment is 'Calculate the function value.',
argnames is ['X', 'Fx']]).
:- public(evald/2).
:- mode(evald(+float, -float), one).
:- info(evald/2, [
comment is 'Calculate the value of the function derivative.',
argnames is ['X', 'DFx']]).
:- end_protocol.
:- object(f1,
implements(functionp)).
% x^2 - 4
% 2.0
eval(X, Y) :-
Y is X * X - 4.
evald(X, Y) :-
Y is 2 * X.
:- end_object.
:- object(f2,
implements(functionp)).
% x^7 + 9x^5 - 13x - 17
% 1.29999999999945448
eval(X, Y) :-
Y is X**7 + 9*X**5 - 13*X - 17.
evald(X, Y) :-
Y is 7*X**6 + 45*X**4 - 13.
:- end_object.
:- object(f3,
implements(functionp)).
% (x - sqrt(2))^7
% 1.41421356237309537
eval(X, Y) :-
Y is (X - sqrt(2.0))**8.
evald(X, Y) :-
Y is 8*(X - sqrt(2.0))**7.
:- end_object.
:- object(function_root,
implements(find_rootp)).
:- info([
version is 1.0,
date is 2006/4/21,
author is 'Paulo Nunes',
comment is 'Multi-threading interface to root finding algorithms.']).
:- threaded.
find_root(Function, A, B, Error, Zero) :-
find_root(Function, A, B, Error, Zero, _).
find_root(Function, A, B, Error, Zero, Algorithm) :-
threaded_call(
( try_method(bisection, Function, A, B, Error, Zero)
; try_method(newton, Function, A, B, Error, Zero)
; try_method(muller, Function, A, B, Error, Zero)
)),
threaded_exit(try_method(Algorithm, Function, A, B, Error, Zero)).
try_method(Algorithm, Function, A, B, Error, Zero) :-
Algorithm::find_root(Function, A, B, Error, Zero).
:- end_object.
:- object(bisection,
implements(find_rootp)).
:- info([
version is 1.0,
date is 2006/4/21,
author is 'Paulo Nunes',
comment is 'Bisection algorithm.']).
find_root(Function, A, B, Error, Zero) :-
Function::eval(A, Fa),
Function::eval(B, Fb),
( Fa > 0.0, Fb < 0.0 ->
true
; Fa < 0.0, Fb > 0.0
),
X0 is (A + B) / 2,
Function::eval(X0, F0),
bisection(Function, A, B, X0, F0, Error, Zero).
bisection(_, _, _, Xn1, 0.0, _, Xn1) :-
!.
bisection(_, Xn1, Xn, _, _, Error, Xn1) :-
abs(Xn1 - Xn) < Error,
!.
bisection(Function, An, Bn, _, _, Error, Zero) :-
Xn1 is (An + Bn) / 2,
Function::eval(Xn1, Fn1),
Function::eval(An, FAn),
( Fn1*FAn < 0.0 ->
An1 is An,
Bn1 is Xn1
; An1 is Xn1,
Bn1 is Bn
),
bisection(Function, An1, Bn1, Xn1, Fn1, Error, Zero).
:- end_object.
:- object(newton,
implements(find_rootp)).
:- info([
version is 1.0,
date is 2006/4/21,
author is 'Paulo Nunes',
comment is 'Newton algorithm.']).
find_root(Function, Xa, Xb, Deviation, Zero) :-
X0 is (Xa + Xb) / 2,
newton(Function, X0, Deviation, Zero).
newton(Function, X0, Deviation, Zero) :-
Xn1 is X0,
Function::eval(Xn1, Fn1),
Function::evald(Xn1, DFn1),
Ac is -(Fn1 / DFn1),
newton(Function, Xn1, Deviation, Fn1, Ac, Zero).
% test deviation
newton(_, Xn1, Deviation, _, Ac, Xn1) :-
abs(Ac) < Deviation,
!.
% test solution
newton(_, Xn1, _, 0.0, _, Xn1) :-
!.
% calc
newton(Function, Xn, Deviation, _, Ac, Zero) :-
Xn1 is Xn + Ac,
Function::eval(Xn1, Fn1),
Function::evald(Xn1, DFn1),
Ac1 is (-(Fn1 / DFn1)),
newton(Function, Xn1, Deviation, Fn1, Ac1, Zero).
:- end_object.
:- object(muller,
implements(find_rootp)).
:- info([
version is 1.0,
date is 2006/4/21,
author is 'Paulo Nunes',
comment is 'Muller algorithm.']).
find_root(Function, Xa, Xb, Deviation, Zero) :-
Xc is (Xa + Xb) / 2,
muller(Function, Xa, Xc, Xb, Deviation, Zero).
muller(Function, Xa, Xb, Xc, Deviation, Zero) :-
Function::eval(Xa, Ya),
Function::eval(Xb, Yb),
Function::eval(Xc, Yc),
H1 is (Xb - Xa),
DDba is ((Yb - Ya) / H1),
Ac is (Deviation + 1),
muller(Function, Xa, Xb, Xc, Deviation, Ya, Yb, Yc, Ac, H1, DDba, Zero).
% complex
muller(_, _, _, complex, _, _, _, _, _, _, _, complex) :-
!.
% test deviation
muller(_, _, _, Xc, Deviation, _, _, _, Ac, _, _, Xc) :-
abs(Ac) < Deviation,
!.
% test solution
muller(_, _, _, Xc, _, _, _, 0.0, _, _, _, Xc) :-
!.
% calc
muller(Function, Xa, Xb, Xc, Deviation, _, Yb, Yc, _, _, DDba, Zero) :-
H2n is (Xc - Xb),
DDcbn is ((Yc - Yb) / H2n),
Cn is ((DDcbn - DDba) / (Xc - Xa)),
Bn is (DDcbn + H2n * Cn),
Rn is (Bn * Bn - 4.0 * Yc * Cn),
% complex
% write(Rn),
( Rn < 0.0 ->
muller(Function, _, _, complex, Deviation, _, _, _, _, _, _, Zero),
!, fail
; V is sqrt(Rn)
),
( Bn > 0.0 ->
Dn is (Bn + V)
; Dn is (Bn - V)
),
Acn is (-(2 * Yc / Dn)),
Xan is Xb,
Xbn is Xc,
Xcn is Xc + Acn,
Yan is Yb,
Ybn is Yc,
Function::eval(Xcn, Ycn),
H1n is H2n,
DDban is DDcbn,
muller(Function, Xan, Xbn, Xcn, Deviation, Yan, Ybn, Ycn, Acn, H1n, DDban, Zero).
:- end_object.

View File

@@ -0,0 +1,13 @@
:- initialization(
logtalk_load(
functions)).
/*
If you intend to use the FOP XSL:FO processor for generating PDF documenting
files, comment the directive above and uncomment the directive below
:- initialization(
logtalk_load(
functions, [xmlsref(standalone)])).
*/

View File

@@ -0,0 +1,15 @@
=================================================================
Logtalk - Object oriented extension to Prolog
Release 2.28.2
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
=================================================================
To load this example and for sample queries, please see the SCRIPT file.
This folder contains a simple multi-threading example with calculating
prime numbers on a given interval. Try to run the example in single and
multi-processor (or multi-core) computers and compare the results. Most
Prolog compilers allows you to measure the time taken for proving a goal
using proprietary predicates.

View File

@@ -0,0 +1,29 @@
=================================================================
Logtalk - Object oriented extension to Prolog
Release 2.28.2
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
=================================================================
% start by loading the loading the example:
| ?- logtalk_load(nondet(loader)).
...
% make a threaded call with a non-deterministic goal:
| ?- threaded_call(lists::member(X, [1,2,3])).
X = _G189
yes
% retrieve through backtracking all solutions for the non-deterministic goal:
| ?- threaded_exit(lists::member(X, [1,2,3])).
X = 1 ;
X = 2 ;
X = 3 ;
no

View File

@@ -0,0 +1,13 @@
:- initialization(
logtalk_load(
nondet)).
/*
If you intend to use the FOP XSL:FO processor for generating PDF documenting
files, comment the directive above and uncomment the directive below
:- initialization(
logtalk_load(
nondet, [xmlsref(standalone)])).
*/

View File

@@ -0,0 +1,12 @@
:- object(lists).
:- threaded.
:- public(member/2).
member(H, [H| _]).
member(H, [_| T]) :-
member(H, T).
:- end_object.

View File

@@ -0,0 +1,15 @@
=================================================================
Logtalk - Object oriented extension to Prolog
Release 2.28.2
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
=================================================================
To load this example and for sample queries, please see the SCRIPT file.
This folder contains a simple multi-threading example with calculating
prime numbers on a given interval. Try to run the example in single and
multi-processor (or multi-core) computers and compare the results. Most
Prolog compilers allows you to measure the time taken for proving a goal
using proprietary predicates.

View File

@@ -0,0 +1,31 @@
=================================================================
Logtalk - Object oriented extension to Prolog
Release 2.28.2
Copyright (c) 1998-2006 Paulo Moura. All Rights Reserved.
=================================================================
% start by loading the loading the example:
| ?- logtalk_load(primes(loader)).
...
% calculate the prime numbers in a given interval using a single thread:
| ?- primes::st_prime_numbers(1, 200000, Primes).
Primes = [199999, 199967, 199961, 199933, 199931, 199921, 199909, 199889, 199877|...]
Yes
% calculate the prime numbers in a given interval by splitting the interval
% in two sub-intervals and using a thread pere interval:
| ?- primes::mt_prime_numbers(1, 200000, Primes).
Primes = [199999, 199967, 199961, 199933, 199931, 199921, 199909, 199889, 199877|...]
Yes

View File

@@ -0,0 +1,13 @@
:- initialization(
logtalk_load(
primes)).
/*
If you intend to use the FOP XSL:FO processor for generating PDF documenting
files, comment the directive above and uncomment the directive below
:- initialization(
logtalk_load(
primes, [xmlsref(standalone)])).
*/

View File

@@ -0,0 +1,62 @@
:- object(primes).
:- info([
version is 1.0,
author is 'Paulo Moura',
date is 2006/04/14,
comment is 'Simple example for comparing single and multi-threading calculation of prime numbers.']).
:- threaded.
:- public(st_prime_numbers/3).
:- mode(st_prime_numbers(+integer, +integer, -list), one).
:- info(st_prime_numbers/3, [
comment is 'Returns all prime numbers in the given interval using a single calculation thread.',
argnames is ['Inf', 'Sup', 'Primes']]).
:- public(mt_prime_numbers/3).
:- mode(mt_prime_numbers(+integer, +integer, -list), one).
:- info(mt_prime_numbers/3, [
comment is 'Returns all prime numbers in the given interval using two calculation threads.',
argnames is ['Inf', 'Sup', 'Primes']]).
st_prime_numbers(N, M, Primes) :-
M > N,
prime_numbers(N, M, [], Primes).
mt_prime_numbers(N, M, Primes) :-
M > N,
N1 is N + (M - N) // 2,
N2 is N1 + 1,
threaded_call(prime_numbers(N, N1, [], Acc)),
threaded_call(prime_numbers(N2, M, Acc, Primes)),
threaded_exit(prime_numbers(N, N1, [], Acc)),
threaded_exit(prime_numbers(N2, M, Acc, Primes)).
prime_numbers(N, M, Primes, Primes) :-
N > M,
!.
prime_numbers(N, M, Acc, Primes) :-
( is_prime(N) ->
Acc2 = [N| Acc]
; Acc2 = Acc),
N2 is N + 1,
prime_numbers(N2, M, Acc2, Primes).
is_prime(2) :- !.
is_prime(Prime):-
Prime > 2,
Prime mod 2 =:= 1,
Sqrt is sqrt(Prime),
is_prime(3, Sqrt, Prime).
is_prime(N, Sqrt, Prime):-
( N > Sqrt ->
true
; Prime mod N > 0,
N2 is N + 2,
is_prime(N2, Sqrt, Prime)
).
:- end_object.