%%% File    : ibits.erl
%%% Author  :  <klacke@hyber.org>
%%% Description : 
%%% Created : 14 Jul 2005 by  <klacke@hyber.org>

%% some functions to do integer arithmetics on
%% bitfields
%% Pos is counted from the right and Size is the number 
%% of bits in the integer
%% example 
%% 2#11000
%% Pos = 3, Size = 2, Value=3 (which is also the maxvalue for 2 bits)

%% overflow is handled by keeping the maxvalue
%% negative values not handled, so 3-5 == 0
%% I use this code to save space in large mnesia tables


-module(ibits).
-compile(export_all).


get(Pos, Size, BitFields) ->
    M = (ones_mask(Size) bsl Pos),
    (BitFields band M) bsr Pos.


set(Pos, Size, BitFields, Value0) ->
    Ones = ones_mask(Size),
    Value = if Value0 > Ones ->
		    Ones;
	       Value0 < 0 ->
		    0;
	       true ->
		    Value0
	    end,
    Mask = Ones bsl Pos,
    (BitFields band (bnot Mask)) bor ((Value bsl Pos) band Mask).


add(Pos, Size, BitFields, Value) ->
    Old = get(Pos, Size, BitFields),
    set(Pos, Size, BitFields, Old+Value).

subtr(Pos, Size, BitFields, Value) ->
    Old = get(Pos, Size, BitFields),
    set(Pos, Size, BitFields, Old-Value).
		

incr(Pos, Size, BitFields) ->
    add(Pos, Size, BitFields, 1).

decr(Pos, Size, BitFields) ->
    subtr(Pos, Size, BitFields,1).
			     

ones_mask(Size) ->
    (1 bsl Size) - 1.

print(I) ->
    io:format("~.2#", [I]).
