]> Repositorios git - scryer-prolog.git/commitdiff
ADDED: popcount(+Integer)
authorMarkus Triska <[email protected]>
Thu, 17 Jun 2021 18:18:01 +0000 (20:18 +0200)
committerMarkus Triska <[email protected]>
Thu, 17 Jun 2021 18:18:36 +0000 (20:18 +0200)
Example:

    ?- X #= popcount(3+5).
       X = 1.

This builds on #986 provided by @Regan-Koopmans. Many thanks!

src/lib/clpz.pl

index 6be3a1102c8ad42c0ad2ecce22f851bc6c63e2cf..32622f724f563282d7d7d42e39619bfd2e420732 100644 (file)
 :- use_module(library(error), [domain_error/3, type_error/3]).
 :- use_module(library(si)).
 :- use_module(library(freeze)).
+:- use_module(library(arithmetic)).
 
 % :- use_module(library(types)).
 
@@ -2567,7 +2568,7 @@ parse_clpz(E, R,
              m(\A)             => [p(pfunction(\, A, R))],
              m(msb(A))         => [p(pfunction(msb, A, R))],
              m(lsb(A))         => [p(pfunction(lsb, A, R))],
-             m(popcount(A))    => [p(pfunction(popcount, A, R))],
+             m(popcount(A))    => [p(ppopcount(A, R))],
              m(A<<B)           => [p(pfunction(<<, A, B, R))],
              m(A>>B)           => [p(pfunction(>>, A, B, R))],
              m(A/\B)           => [p(pfunction(/\, A, B, R))],
@@ -2954,7 +2955,9 @@ expr_conds(A0\/B0, A\/B) --> expr_conds(A0, A), expr_conds(B0, B).
 expr_conds(xor(A0,B0), xor(A,B)) --> expr_conds(A0, A), expr_conds(B0, B).
 expr_conds(lsb(A0), lsb(A)) --> expr_conds(A0, A).
 expr_conds(msb(A0), msb(A)) --> expr_conds(A0, A).
-expr_conds(popcount(A0), popcount(A)) --> expr_conds(A0, A).
+expr_conds(popcount(A0), Count) -->
+        expr_conds(A0, A),
+        [I is A, arithmetic:popcount(I, Count)].
 
 clpz_expandable(_ in _).
 clpz_expandable(_ #= _).
@@ -5472,6 +5475,18 @@ run_propagator(pexp(X,Y,Z), MState) -->
             fd_put(Z, ZD1, ZPs)
         ;   true
         ).
+
+%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% % Y = popcount(X)
+
+run_propagator(ppopcount(X,Y), MState) -->
+        (   nonvar(X) ->
+            kill(MState),
+            queue_goal(popcount(X, Y))
+        ;   true
+        ).
+
+
 %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %% % Z = X xor Y
 
@@ -7679,6 +7694,7 @@ attribute_goal_(prem(X,Y,Z))           --> [?(X) rem ?(Y) #= ?(Z)].
 attribute_goal_(pmax(X,Y,Z))           --> [?(Z) #= max(?(X),?(Y))].
 attribute_goal_(pmin(X,Y,Z))           --> [?(Z) #= min(?(X),?(Y))].
 attribute_goal_(pxor(X,Y,Z))           --> [?(Z) #= xor(?(X), ?(Y))].
+attribute_goal_(ppopcount(X,Y))        --> [?(Y) #= popcount(?(X))].
 attribute_goal_(scalar_product_neq(Cs,Vs,C)) -->
         [Left #\= Right],
         { scalar_product_left_right([-1|Cs], [C|Vs], Left, Right) }.