Search code examples
prologclpfd

relational prolog and bit mask manipulations


I am trying my hand at relational prolog. Part of my program needs to deal with bitmasks. It however seems that prolog code handles bit makes, such as to set a bit or clear a bit doesn't work relationally -- i.e. it only works in setting a bit, but not in the other direction, identifying what bit is set.

For example:

setbit(X, N, V) :-
    N1 #= 1<< N,
    V #= X \/ N1.

this code only work in one direction, where X and N are given and V is calculated. If one provides V and N, then X is not derived, but rather its left as an uninstantiated expression.

Does this mean that calculating with bit maps and masks is out of scope of relational prolog.

?- setbit(0,1,X).
X = 2.

?- setbit(X, 1, 2).
2#=X\/2.

the latter doesn't bind X to 0.

thank you,

Daniel

Edit: based on the comments below, the following code works very well:

setbit(X, N, V) :-
    X in 0..1,
    label([X]),
    N1 #= 1<< N,
    V #= X \/ N1.

clearbit(X, N, V) :-
    X in 0..1,
    label([X]),
    current_prolog_flag(max_tagged_integer, MTI),   
    N1 #= MTI /\ \(1<<N),
%   N1 #= 0xffffffffffffff /\ \(1<<N),
    V #= X /\ N1

Note, the current_prolog_flag -- it retrieves the maximum integer fitting into one word on the current machine architecture -- on 64 bit its 54 bits, the rest of the bits are used for housekeeping.


Solution

  • I am not great at clpfd, but I think the problem here is that you haven't given X a finite domain or asked for its values to be enumerated. This works:

    ?- setbit(X, 1, 2), X in 0..1, label([X]).
    X = 0 ;
    false.
    

    The second expression there, X in 0..1 says you want X to be zero or one, and the third says, "give me the values X can obtain."