Marty:
I also got trapped in the morass of byte+endians playing with this
yesterday. "Enough!" I said. Just let me do this:
select bit_and(intval1, intval2) as intval3;
Or even
select intval1 && intval2 as intval3;
It's portable, and has no harmful side-effects!
Cheers
John
From: Martin Bowes [mailto:martin.bowes (AT) ctsu (DOT) ox.ac.uk]
Sent: Thursday, August 13, 2009 5:38 AM
To: Ingres and related product discussion forum
Cc: John Saroka
Subject: RE: [Info-Ingres] bit masks
Hi John et al,
And to think this all started out as an innocuous and very poorly
phrased question from an evil programmer.
I wasn't confident when I was looking at the bit-wise functions
descriptions in the SQL guide for 9.2.0 and examined the description of
bit_not() and intextract(), neither look good! The description of the
byte() function also sucks a good deal of arse.
It appears that the addition of the optional second parameter to the
byte function causes it to convert the first operand (an integer) to a
char. Which was not what I would expect!
For example:
1) select hex(byte(1,1)); --> yields 31
2) select hex(byte(1)); --> yields 0100
3) select hex('1'); --> yields 31
4) select hex(1); --> yields 0001
This was done on II 9.2.0 (a64.lnx/143)NPTL + 13468.
The output from the second and fourth line leads me to wonder whether or
not the byte function is correctly handling big-endian/little endian
features. I'm reasonably confident the hex() function is OK. Try select
hex(256).
The hex() function clearly displays data in a big-endian format. Which
is cool as it has to handle all the data types so I expect hex('ABC') to
display 414243 as the 'A' should come before the 'C' in memory.
But Linux is little endian, so an integer 1 is stored in memory order as
01 00. So the byte function is storing in big endian format 00 01
But I can now put all of this togethor and allow for the big-endian,
little-endian and generaly screwed nature of this by adjusting my bit
mask and writing....
select case when bit_and(byte(int4(1024)), X'00040000') != byte(int4(0))
then 1 else 0 end as bit_11_set;
I'm thinking:
* The mod and div feature mentioned elsewhere is the preferred
option....
* The byte(m,n) function is broken.
* This was not the best way to spend a morning.
Quote:
I think the bit_* functions would be much more useful if they took
integer operands, and returned integer values.
|
Absolutley!
Marty
From: info-ingres-bounces (AT) kettleriver...ting (DOT) com
[mailto:info-ingres-bounces (AT) kettleriverconsulting (DOT) com] On Behalf Of John
Saroka
Sent: 12 August 2009 21:55
To: Ingres and related product discussion forum
Subject: Re: [Info-Ingres] bit masks
Hi Marty:
The bit_and() function seems to work fine as a bit masker:
select hex(bit_and(X'00000401', X'00000001'))\g
00000001
The problem is that it requires operands of type byte, rather than also
allowing the integer types, which are natural for bit-twiddling
(although limited to 8 bytes worth for a single test).
The byte() function has what I think is non-intuitive behavior:
select hex(byte(1,4))\g
31000000 /* integer literal "promoted" to char, I don't think this
is what you wanted */
So then we get
select hex(bit_and(byte(1,4), X'00000400'))\g
00000000 /* the correct byte-by-byte result of AND */
Which is not the same as
select hex(byte(0,4))\g
30000000 /* another number-to-character conversion */
And not the same as
select hex(byte(0))\g
0000 /* I'm assuming the case expr converts the literal 0 to byte,
and the test fails because the lengths are different */
Finally:
select hex(byte(0, 2))\g
3000 /* What I expected for the above query, not sure why it
should be different */
So I believe that the results you're seeing are correct, based on the
peculiarities of byte and byte(). This testing was done on Ingres 9.3.0
int.lnx.
I think the bit_* functions would be much more useful if they took
integer operands, and returned integer values.
Regards,
John
From: info-ingres-bounces (AT) kettleriver...ting (DOT) com
[mailto:info-ingres-bounces (AT) kettleriverconsulting (DOT) com] On Behalf Of Ian
Kirkham
Sent: Wednesday, August 12, 2009 12:10 PM
To: Ingres and related product discussion forum
Subject: Re: [Info-Ingres] bit masks
Hi Marty,
Have a look at the iitables view definition - not pretty but works...
It uses MOD() and integer divide.
Regards,
Ian
________________________________
From: info-ingres-bounces (AT) kettleriver...ting (DOT) com
[mailto:info-ingres-bounces (AT) kettleriverconsulting (DOT) com] On Behalf Of
Martin Bowes
Sent: 12 August 2009 15:20
To: Ingres and related product discussion forum
Subject: [Info-Ingres] bit masks
Hi All,
How do I tell if a specific bit in the binary representation of an
integer4 item is set?
For example I want to see if the 11th bit is set...in the number 1.
I've tried...
select case when bit_and(byte(1, 4), X'00000400') != byte(0, 4) then 1
else 0 end as bit_11_set;
select case when bit_and(byte(1, 4), X'00000400') != 0 then 1 else 0 end
as bit_11_set;
But these both return 1 when they should return 0.
Running on 9.2.0
Are there bit masking functions? IIRC these were being deveolped in the
last Ingres Codesprint in London but it may be some time before they are
available.
Martin Bowes