/* poly_10 benchmark in Picat v3. bench/poly_10.pl https://github.com/SWI-Prolog/bench Changes: - x less_than -> less_than(x,y) - $ escaped term and poly - added output This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ main => go. go ?=> test_poly(P), poly_exp(10, P, X), println(X), nl. go => true. % """ % generated: 8 March 1990 % option(s): NO_TERM_COMPARE % % (poly) poly_10 % % Ralph Haygood (based on Prolog version by Rick McGeer % based on Lisp version by R. P. Gabriel) % % raise a polynomial (1+x+y+z) to the 10th power (symbolically) % """ % :-op(700,xfx,less_than). % hakank: not supported in Picat v3.0 top:-poly_10. poly_10 :- test_poly(P), poly_exp(10, P, _). % test polynomial definition test_poly(P) :- poly_add($poly(x,$[term(0,1),term(1,1)]),$poly(y,[term(1,1)]),Q), poly_add($poly(z,$[term(1,1)]),Q,P). % 'less_than'/2 for x, y, z % x less_than y. % y less_than z. % x less_than z. less_than(x, y). less_than(y, z). less_than(x, z). % polynomial addition poly_add(poly(Var,Terms1), poly(Var,Terms2), poly(Var,Terms)) :- !, term_add(Terms1, Terms2, Terms). poly_add(poly(Var1,Terms1), poly(Var2,Terms2), poly(Var1,Terms)) :- less_than(Var1,Var2), !, add_to_order_zero_term(Terms1, $poly(Var2,Terms2), Terms). poly_add(Poly, poly(Var,Terms2), poly(Var,Terms)) :- !, add_to_order_zero_term(Terms2, Poly, Terms). poly_add(poly(Var,Terms1), C, poly(Var,Terms)) :- !, add_to_order_zero_term(Terms1, C, Terms). poly_add(C1, C2, C) :- C is C1+C2. % term addition term_add([], X, X) :- !. term_add(X, [], X) :- !. term_add([term(E,C1)|Terms1], [term(E,C2)|Terms2], [term(E,C)|Terms]) :- !, poly_add(C1, C2, C), term_add(Terms1, Terms2, Terms). term_add([term(E1,C1)|Terms1], [term(E2,C2)|Terms2], [term(E1,C1)|Terms]) :- E1 < E2, !, term_add(Terms1, $[term(E2,C2)|Terms2], Terms). term_add(Terms1, [term(E2,C2)|Terms2], [term(E2,C2)|Terms]) :- term_add(Terms1, Terms2, Terms). add_to_order_zero_term([term(0,C1)|Terms], C2, [term(0,C)|Terms]) :- !, poly_add(C1, C2, C). add_to_order_zero_term(Terms, C, [term(0,C)|Terms]). % polynomial exponentiation poly_exp(0, _, 1) :- !. poly_exp(N, Poly, Result) :- M is N>>1, N is M<<1, !, poly_exp(M, Poly, Part), poly_mul(Part, Part, Result). poly_exp(N, Poly, Result) :- M is N-1, poly_exp(M, Poly, Part), poly_mul(Poly, Part, Result). % polynomial multiplication poly_mul(poly(Var,Terms1), poly(Var,Terms2), poly(Var,Terms)) :- !, term_mul(Terms1, Terms2, Terms). poly_mul(poly(Var1,Terms1), poly(Var2,Terms2), poly(Var1,Terms)) :- less_than(Var1, Var2), !, mul_through(Terms1, poly(Var2,Terms2), Terms). poly_mul(P, poly(Var,Terms2), poly(Var,Terms)) :- !, mul_through(Terms2, P, Terms). poly_mul(poly(Var,Terms1), C, poly(Var,Terms)) :- !, mul_through(Terms1, C, Terms). poly_mul(C1, C2, C) :- C is C1*C2. term_mul([], _, []) :- !. term_mul(_, [], []) :- !. term_mul([Term|Terms1], Terms2, Terms) :- single_term_mul(Terms2, Term, PartA), term_mul(Terms1, Terms2, PartB), term_add(PartA, PartB, Terms). single_term_mul([], _, []) :- !. single_term_mul([term(E1,C1)|Terms1], term(E2,C2), [term(E,C)|Terms]) :- E is E1+E2, poly_mul(C1, C2, C), single_term_mul(Terms1, $term(E2,C2), Terms). mul_through([], _, []) :- !. mul_through([term(E,Term)|Terms], Poly, [term(E,NewTerm)|NewTerms]) :- poly_mul(Term, Poly, NewTerm), mul_through(Terms, Poly, NewTerms).