"Sukit Tretriluxana" <[EMAIL PROTECTED]> wrote in message
news:[EMAIL PROTECTED]
>
> Could someone please shed some light how I can perform
> bit operations on integers? Basically, I am getting a series of
> bytes that represent an integer number. This number in turn
> actually represent a bit pattern that determines whether
> something on or off. I want to be able to check say if if
> bit 13, for example, is on or off.
>
I was actually asking myself similar questions last week [well, more about
bit shifting / rotating], and after a little exploration of this issue I
*think* I can answer your question [I'll try to, anyway :)].
As you've already found out Oz does not implement the usual crop of C-like
bitwise operations [i.e. left-shift, right-shift etc] on integer or
integer-related types. Instead it offers facilities, specifically the:
* BitString
* BitArray
types, which may be used to effect such tasks. Put another way, you can't
just simply code up [ala C] the following:
IntegerValue >> 4
or:
IntegerValue & Mask
but must take a more indirect route involving the earlier-mentioned types.
Both types offer roughly similar bit manipulation capability in that you
can:
* Test whether individual bits are set ['test' in 'BitArray', 'get' in
'BitString']
* Set and clear specified bits ['set' and 'clear' in 'BitArray', 'put'
in 'BitString']
* Perform the bitwise Boolean operations, AND ['conj'] and OR
['disj']
* Extract a list of the indexes set to 1 [At first I thought this was
a rather odd feature (as compared to a list of all bits), but later
found that it not only offers a very compact representation of
the bit data, but also makes implementing bit shifting a trivial
task - pretty neat, after all !]
For my purposes I found 'BitString' more useful primarily because you can
initialise it with a specified bit value [via a list of indexes] something
that doesn't appear possible with 'BitArray' [you have to 'set' each bit, a
rather painful exercise I should think !].
Anyway, I'm sure a couple of your questions have already been answered,
albeit indirectly, but I'll now address some specifics. Assuming you've
built a 8 bit 'BitString' instance:
BS = {BitString.make [2 3 5]}
testing to see whether bit 3 [using a zero-based index scheme] is as simple
as:
% Is bit 3 set ?
if {BitString.get BS 3}then
...
As for building a 'BitString' representation of an 'integer' out of a series
of 'bytes' it really is simply a matter of appropriately joining these
entities together as a list [being mindful of endianness, that is, whether
byte zero starts on the left side or the right side of the 'integer'], and
converting this list to a list of indexes of bits to be set. The routines,
'IntToBitString' and 'MakeIndexList', in the code below illustrate one
approach [hopefully a reasonably efficient one !] to this task.
Finally, I hope this response is of help to you. I've been exploring the Oz
language [in far too short time bursts !] for a number of months now, and
have really enjoyed doing so. While I have found it relatively easy to use,
expressive, and ideal for building simple abstractions [like the example
below] it does require that you let go of some preconceived notions [like
assumptions about bit manipulation :)] in order to facilitate learning.
Cheers,
Anthony Borla
Some sample code appears below. Be warned, it is woefully incomplete, and
not thoroughly tested, but hopefully enough to illustrate some basic ideas
about Oz bit manipulations and simple abstraction building.
functor
import
System(show showInfo print printInfo) Application(exit)
define
fun {NewInteger Value}
local
%% Helpers
fun {I2BS I Bin}
if I =< 0 then
Bin
else D = I div 2 M = I mod 2 in
{I2BS D (M + &0)|Bin}
end
end
fun {I2BL I Bin}
if I =< 0 then
Bin
else D = I div 2 M = I mod 2 in
{I2BL D M|Bin}
end
end
fun {BL2I Bin}
P = fun {$ X Y} Y + {Number.pow 2 X} end
in
{List.foldR Bin P 0}
end
fun {MakeIndexList L AC}
case L of nil then nil
elseof H|T then
if H == 1 then
AC|{MakeIndexList T (AC + 1)}
else
{MakeIndexList T (AC + 1)}
end
end
end
fun {IntToBitString I}
{BitString.make 32 {MakeIndexList {List.reverse {I2BL I ""}} 0}}
end
fun {BitStringToInt Bin}
{BL2I {BitString.toList Bin}}
end
fun {BitListToInt Bin}
{BL2I Bin}
end
fun {IntToBinaryString I}
{I2BS I ""}
end
fun {BinaryStringToInt Bin}
P = fun {$ I X Y} Y + (X - 48) * {Number.pow 2 (I - 1)} end
in
{List.foldRInd {List.reverse Bin} P 0}
end
%% Private Data
Integer = {NewCell Value}
IBS = {NewCell {IntToBitString Value}}
in
%% Interface
fun {GetValue}
@Integer
end
proc {SetValue I}
Integer := I
IBS := {IntToBitString I}
end
fun {AsBitString}
@IBS
end
fun {AsBinaryString}
{IntToBinaryString @Integer}
end
fun {Shift N}
P = fun {$ X} X + N end
Q = fun {$ X} X >= 0 end
in
if N == 0 then
% Clone current
{NewInteger @Integer}
elseif N > 0 then
% Right Shift
{NewInteger {BitListToInt {List.map {BitString.toList @IBS} P}}}
else
% Left Shift
{NewInteger {BitListToInt {List.filter {List.map {BitString.toList
@IBS} P} Q}}}
end
end
%% ... incomplete ...
fun {Rotate N}
@Integer
end
fun {AND I}
@Integer
end
fun {OR I}
@Integer
end
fun {XOR I}
@Integer
end
fun {NEG I}
@Integer
end
fun {CMPL2 I}
@Integer
end
end
in
ops(getValue:GetValue setValue:SetValue asBitString:AsBitString
asBinaryString:AsBinaryString shift:Shift rotate:Rotate
bitAND:AND bitOR:OR bitXOR:XOR neg:NEG cmpl2:CMPL2)
end
%% Quick Demonstration Harness
I
in
I = {NewInteger 5}
{System.show {I.getValue}}
{System.showInfo {IntToString {I.getValue}}}
{System.showInfo {I.asBinaryString}}
{System.showInfo {{I.shift 2}.getValue} }
{I.setValue 20}
{System.showInfo {{I.shift ~1}.getValue} }
{System.show {I.asBitString}}
{Application.exit 0}
end
_________________________________________________________________________________
mozart-users mailing list
[email protected]
http://www.mozart-oz.org/mailman/listinfo/mozart-users