I'm trying to understand some bitstring functions.
Is it ok that we can write:
# let b = BITSTRING { min_int : 31 : unsigned } ;;
val b : Bitstring.bitstring = ("\128\000\000\000", 0, 31)
# Bitstring.hexdump_bitstring stdout b;;
00000000 80 00 00 00
|.... |
- : unit = ()
I would have allowed only values between 0 and max_int?
I'm asking this, because I'm currently adding _signed functions to
bitstring,
and restricted allowed values like this :
let range_signed v bits =
if
bits = 31
then
v >= min_int && v <= max_int
else
let succ_max_val = 1 lsl pred bits in
v < succ_max_val &&
v > (- succ_max_val - 1)
But I'm not sure it is the same logic as the range_unsigned function?
Salutations
Matthieu
This is a tricky point. If we only allowed unsigned values there
(ie. >= 0) then you could not express the full 31 bit range of values.
This is because the range of unsigned values expressible in an OCaml
int [on a 32 bit platform] is 0..max_int which is 0x3fff_ffff. That's
30 bits, not 31 bits.
So if we restricted values to be positive, then we'd need to change
the type of the value to be an int64, and that would break the
assumptions in this table:
http://people.redhat.com/~rjones/bitstring/html/Bitstring.html#integertypes
Users would have to worry about whether the type was signed or
unsigned, and the corner cases around the 30/31/32 bit point in that
table would become really nasty.
So I think it's better to allow a signed value there, which means the
code above is *not* a bug.
Do you agree?
> I'm asking this, because I'm currently adding _signed functions to
> bitstring,
> and restricted allowed values like this :
>
> let range_signed v bits =
> if
> bits = 31
> then
> v >= min_int && v <= max_int
> else
> let succ_max_val = 1 lsl pred bits in
> v < succ_max_val &&
> v > (- succ_max_val - 1)
>
> But I'm not sure it is the same logic as the range_unsigned function?
I think you should just restrict based on the number of bits, so
let range_signed = range_unsigned.
Rich.
--
Richard Jones
Red Hat
Yes. Simpler is better.
> …
>
> Do you agree?
>
Of course! I just asked to be sure.
>> I'm asking this, because I'm currently adding _signed functions to
>> bitstring,
>> and restricted allowed values like this :
>>
>> let range_signed v bits =
>> if
>> bits = 31
>> then
>> v>= min_int&& v<= max_int
>> else
>> let succ_max_val = 1 lsl pred bits in
>> v< succ_max_val&&
>> v> (- succ_max_val - 1)
>>
>> But I'm not sure it is the same logic as the range_unsigned function?
>>
> I think you should just restrict based on the number of bits, so
> let range_signed = range_unsigned.
>
OK. I will stick to the original version, and add some unit tests to
validate my code.
Thanks for this library, that made my code more readable.
Matt
Hello again,
I think this is not ok for signed integers, because negative integers
are not allowed by construct_char_unsigned or by range_unsigned (except
if bits = 31).
We do need a range_signed function.
Consider 3 bits integers (this is only an example; I'm speaking about
both construct_char_signed and construct_int_*_signed)
bin u s
000 0 0
001 1 1
010 2 2
011 3 3
100 4 -4
101 5 -3
110 6 -2
111 7 -1
BITSTRING { n : 3 } will work for n in [0..7]. OK.
But what about BITSTRING {n : 3 : signed }?
We can allow either:
* n in [-4..3]
* or n in [-4..7]
What do you think is better?
I implemented the second solution (see later) because it allows to do:
BITSTRING {7:3:signed}, which bitmatched again { n:3:signed } would
return -1 and { n:3:unsigned } would return 7.
Salutations
Matt