forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Bitwise intrinsic functions

 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> General
View previous topic :: View next topic  
Author Message
sparge



Joined: 11 Apr 2005
Posts: 371

PostPosted: Fri Oct 01, 2010 12:35 pm    Post subject: Bitwise intrinsic functions Reply with quote

Have been making some use of these functions recently. Was doing OK until today when I started messing around with trying to store and extract bit patterns and they seem to be coming out the other way round when I extract them. Was assuming that IBITS would extract "in the direction of decreasing significance". FTN95 manual talks about how the result is based on right-shifting of the pattern. Other compiler documentations say things like "bit positions number from right to left" Rolling Eyes and even underline it, to emphasize how important it is to get it right. As I am finding. But what is "right to left" supposed to mean in the context of memory, when individual bytes are displayed in reverse order and back to front? Oh yes, and another thing, saying that the function extracts LEN bytes starting at position POS is all very well, but is POS inclusive or non-inclusive?

Aaaaargggh ...
Back to top
View user's profile Send private message Send e-mail
IanLambley



Joined: 17 Dec 2006
Posts: 490
Location: Sunderland

PostPosted: Fri Oct 01, 2010 3:54 pm    Post subject: Reply with quote

This might help
Code:

winapp
program bitwise
include <windows.ins>
common/integer_number/intval
character*32 textval
common/character_number/textval
external iprint_binary,ishiftp,ishiftn

i=winio@('%ca[Bitwise operations]%bg[btnface]&')
i=winio@('Enter an integer%`bg[white] %^rd&',intval,iprint_binary)
i=winio@('%ffBinary value%`bg[white] %`rs&',textval)
i=winio@('%ff%nlFunction ishft %^tt[Positive]%^tt[Negative]',ishiftp,ishiftn)
end


Integer*4 function iprint_binary()
common/integer_number/intval
character*32 textval
common/character_number/textval
iprint_binary = 1
write(textval,'(b32.32)')intval
end
Integer*4 function ishiftp()
common/integer_number/intval
character*32 textval
common/character_number/textval
ishiftp = 1
intval = ishft(intval,+1)
i=iprint_binary()
end
Integer*4 function ishiftn()
common/integer_number/intval
character*32 textval
common/character_number/textval
ishiftn = 1
intval = ishft(intval,-1)
i=iprint_binary()
end


Normal convention is to have the most significant bit at the left and least at the right, just like hundreds, tens and units.
Regards
Ian


Last edited by IanLambley on Fri Oct 01, 2010 6:10 pm; edited 1 time in total
Back to top
View user's profile Send private message Send e-mail
sparge



Joined: 11 Apr 2005
Posts: 371

PostPosted: Fri Oct 01, 2010 4:52 pm    Post subject: Reply with quote

Thank you! It might have helped, hours ago Smile I still can't get my head around it though. The convention you refer to makes perfect sense, but then the convention for indexing the bits is back to front (31 to 0 reading from left to right) ... so with IBITS and MVBITS, which work with LEN bits starting from position POS, position N ought to be "from the right" but it's from the left. It's not the bit index. So stuff has to get written out back to front, because IBSET, IBCLR, BTEST etc are based on bit index.

I got my thing to work in the end but only by dint of writing something out on paper, pressing heavily, and then turning it over and holding it up to the light Embarassed . Think I must have my stupid head on today.

My only consolation is that I seem to have discovered a (somewhat academic) bug, in the function IBITS ...

INTEGER FUNCTION IBITS (I, POS, LEN)

This returns LEN bits from integer I starting at position POS, right-shifted and padded with remaining bits off. So I would expect (not that anyone would do it, it's pointless unless one is wrestling to understand something, like I was) that:

J = IBITS (I, 0, 32)

should return I. But it doesn't - it returns 0. It does what I expect for all values of the third argument from 0 to 31 inclusive, though ...

Cheers,

Andy
Back to top
View user's profile Send private message Send e-mail
IanLambley



Joined: 17 Dec 2006
Posts: 490
Location: Sunderland

PostPosted: Fri Oct 01, 2010 6:10 pm    Post subject: Reply with quote

Andy,
From right to left is the convention irrespective of the base of the number system. In decimal, the right hand position contains the count of values which are 10^0, i.e. the 1s; the next position to the left contains the count of values which are 10^2, i.e. the 10s.

In binary, the are in the order of:
2^31, 2^30 ..........2^3, 2^2, 2^1, 2^0
or for the right most 8 columns, these denote the existence of values of
128, 64, 32, 16, 8, 4, 2, 1

Therefore, the index position is simply the power to which 2 is raised for that bit position.

To account for positive and negative numbers, the left most bit denotes the sign and the remainder denote the magnitude and a "twos-complement" method is used.
That is the "ones-complement" plus 1 - a bit of a tongue in cheek name!
For example, using a single byte (signed), the value for 7 in binary is:
00000111
and minus 7 is obtained by first reversing the bits to give the "ones-compliment", that is
11111000
and adding 1 to give
11111001

Check this by adding 7 in binary and performing the necessary carries giving:
11111001 +
00000111
-----------
00000000

So a 1 in the fist bit denotes a negative, and a zero denotes a positive (or zero).
0 = 00000000
+1 = 00000001
-1 = 11111111

and the ibits function probably will only work up to 31, because for a 4byte integer, whilst there are 32 bits, these are numbered from 0 to 31 and 32 does not exist. Try using an integer*8 variable with the bit range of 0 to 63 and remember that the highest indexed bit is the sign bit.

Ian
Back to top
View user's profile Send private message Send e-mail
sparge



Joined: 11 Apr 2005
Posts: 371

PostPosted: Mon Oct 04, 2010 9:15 am    Post subject: Re: Reply with quote

I don't see your logic. Bit patterns are independent of their interpretation as integers, +ve or negative, or anything else for that matter - they're just patterns.

IanLambley wrote:
the ibits function probably will only work up to 31, because for a 4byte integer, whilst there are 32 bits, these are numbered from 0 to 31 and 32 does not exist.


It's this kind of thing - functions with arguments one of which is base 0 indexed and another of which is base 1 indexed - that really highlights the downside of ordinal/cardinal schizophrenia Smile

The bits are indexed from 0 to 31, yes, and there are 32 of them, yes. In index terms, the 32nd bit does not exist, yes, in headcount terms the 32nd bit does exist, because there are 32 of them. So asking for any headcount of bits from 0 to 32, inclusive, starting from bit with index 0, is a perfectly reasonable request - unless the starting bit is an exclusive marker i.e. not returned as part of the payload. And this is not the case.

If I have 32-bit integers T and S for target and source, then:

T = IBITS (S, 0, 0) should leave T unchanged, or fill it with zeroes (not sure which)
T = IBITS (S, 0, 1) to T = IBITS (S, 0, 32) should should fill T with from 1 to 32 bits of S, padded with unset bits
T = IBITS (S, 0, 33) is the first one that should fail, possibly in an interesting way since the documentation says only that LEN must be non-negative, not that it must satisfy 0 <= LEN <= BIT_SIZE (S)

Exactly the same logic applies for any starting POS other than 0 e.g.:

T = IBITS (S, 10, 0) should leave T unchanged, or fill it with zeroes (not sure which)
T = IBITS (S, 10, 1) to T = IBITS (S, 10, 22) should should fill T with from 1 to 22 bits of S, padded with unset bits
T = IBITS (S, 10, 23) is the first one that should fail since there are only 22 bits available starting from number 10 inclusive (bits 0-9 are 10 bits altogether, so there are 22 left over).

For POS = 31, the only calls that make sense are:

T = IBITS (S, 31, 0)
T = IBITS (S, 31, 1)
Back to top
View user's profile Send private message Send e-mail
IanLambley



Joined: 17 Dec 2006
Posts: 490
Location: Sunderland

PostPosted: Mon Oct 04, 2010 12:35 pm    Post subject: Reply with quote

The bits are numbered from 0 to 31 and it is these numbers that are being referred to in the function.

The problem of where a number system starts; zero or one, has caused difficulties throughout history. I believe the Babylonians did not originally have a character for zero and were a bit stuck for a while when one of their digit positions was not in the range 1 to 10 or 1 to 6 depending on the digit position. This was eventually solved by using a particular digit turned on its side in that digit position to denote a missing or zero digit.

The Venrable Bede also avoided the use of the year zero when he popularised the AD year numbering system in 731. (He lived just around the corner from me and, as a lad, I went to Bede School). Hence 1BC and 1AD are adjacent years!

Of course, something we havn't tried yet is referfing to digits greater than 31 in an integer*4 array. I must try that sometime.

I think that:
T = IBITS (S, 0, 0) should transfer the least significant bit of S into T with bits 1 to 31 of T being set to zero.
T = IBITS (S, 0, 1) the two least significant bits of S are moved to T with bits 2 to 31 of T being set to zero.
T = IBITS (S, 0, 32) If S is not an array, I would hope that this would give an error, if it does not, then there would be an attempt to transfer 33 bits from S, which only contains 32, to T and the 33rd bit (called bit 32) would be lost. it is possible that if a check on the length of the input value "S" is not made, then an attempt would be made to transfer data from the next variable in storage which it may assume to be the second element in an array. If T=IBITS(S,1,32) were used, this may pick up 32 bits starting at the second bit of S and overflowing into the first bit of the next byte in storage and would be like not applying bounds checking to arrays. I remember my boss at work many years ago who wrote a program in an antique language called "Telcomp" otherwise known as ICL "Jean" or DEC "Focal" in which he had two arrays A(100),B(100) and he accessed A(101) which was actually B(1). In doing so, he accidently improved the convergence of his algorithm. When I converted it to Fortran, it just didn't work.

I hope this helps.

Regards
Ian
Back to top
View user's profile Send private message Send e-mail
sparge



Joined: 11 Apr 2005
Posts: 371

PostPosted: Mon Oct 04, 2010 3:07 pm    Post subject: Re: Reply with quote

IanLambley wrote:
The bits are numbered from 0 to 31 and it is these numbers that are being referred to in the function.


Yes, in the second argument, which is a position, an index, a label, an ordinal number. No in the third argument which is a count, a cardinal number. We don't say we want to extract 31 bits because we happen to index from 0 and the last bit thus happens to have index 31. We say we want to extract 32 bits because there are 32 of them, regardless of how they are indexed. We could index from base whatever we like, and the last bit would thus have index (whatever we like+31), but we'd still say we want to extract 32 bits.

The Venerable Bede knew whereof he spoke. My strong preference has always been for indexing from 1 - though I can see why, in a software context, where an index can be interpreted as an offset from a base location, it makes sense to "index" from 0 - but if an offset is what is wanted/needed, why not recognise that it's a more general concept than an index (it doesn't have always to be 1 more than the last one, for a start), and calculate it from the index?

It just seems to me that indexing from 1 gives invaluable consistency between ordinal and cardinal numbering:

"How many bits are in that 4 byte integer?"
"32. Look, I'll count them for you: 1, 2, 3, .... 30, 31, 32. See?"

I don't see any corresponding trump card in favour of indexing from 0, though I'd rather that than have to live with both alternatives cheek by jowl. The scope for "off by 1" errors would be largely eliminated if the world would just agree on one or the other. When I am in charge I will Make It So.
Back to top
View user's profile Send private message Send e-mail
Sebastian



Joined: 20 Feb 2008
Posts: 177

PostPosted: Tue Oct 05, 2010 8:48 am    Post subject: Reply with quote

Did you check what happens with negative values for I? As INTEGER is signed and (in the *4 default case) has 31 significant digits and maybe this function does something special with respect to the sign (always-keep or whatever).
Back to top
View user's profile Send private message
sparge



Joined: 11 Apr 2005
Posts: 371

PostPosted: Tue Oct 05, 2010 12:32 pm    Post subject: Re: Reply with quote

Sebastian wrote:
Did you check what happens with negative values for I? As INTEGER is signed and (in the *4 default case) has 31 significant digits and maybe this function does something special with respect to the sign (always-keep or whatever).


Ooh, that's an interesting idea! I shall do so.

OK, it returns 0 for LEN = 32 again. I was going to say all results for less than full length are positive integers, but that's not true, is it; they are taken from and returned into integer "receptacles", but neither they nor the receptacles are really integers, any more than they are if I is positive.

I can see why the sign bit might be under suspicion, but however I read the documentation, I fail to see how LEN = 32 is a special case:

The result has the value of the sequence of LEN bits in I beginning at bit POS, right-adjusted with all other bits zero.

Any integer value of I is valid input and has a value, and the sequence of all 32 bits of I, beginning at position 0, has that value. No right-adjustment required. So there is no impediment to returning all 32 bits into another integer J, which will then also have that value. Where is the flaw in that logic?
Back to top
View user's profile Send private message Send e-mail
IanLambley



Joined: 17 Dec 2006
Posts: 490
Location: Sunderland

PostPosted: Tue Oct 05, 2010 1:41 pm    Post subject: Reply with quote

Modification to my test program:
Code:

winapp
program bitwise
include <windows.ins>
common/integer_number/intval1,intval2,ibits_result,ibits_start,ibits_len
character*32 textval1,textval2,textval3
common/character_number/textval1,textval2,textval3
external iprint_binary,ishiftp,ishiftn

i=winio@('%ca[Bitwise operations]%bg[btnface]&')
i=winio@('Enter integers %ta%`bg[white]%^rd&',intval1,iprint_binary)
i=winio@('%ta%`bg[white]%^rd&',intval2,iprint_binary)
i=winio@('%ffBinary values%ta%`bg[white]%`rs&',textval1)
i=winio@('%ff%ta%ta%`bg[white]%`rs&',textval2)
i=winio@('%ffIbits pos%ta%ta%`bg[white]%^rd&',ibits_start,iprint_binary)
i=winio@('  ibits len  %`bg[white]%^rd&',ibits_len,iprint_binary)
i=winio@('%ffibits result%ta%ta%`bg[white]%`rs&',textval3)
i=winio@('%ff%nlFunction ishft %^tt[Positive]%^tt[Negative]',ishiftp,ishiftn)
end


Integer*4 function iprint_binary()
common/integer_number/intval1,intval2,ibits_result,ibits_start,ibits_len
character*32 textval1,textval2,textval3
common/character_number/textval1,textval2,textval3
iprint_binary = 1
write(textval1,'(b32.32)')intval1
write(textval2,'(b32.32)')intval2
if(ibits_start .ge. 0 .and. ibits_len .ge. 0)then
  write(textval3,'(b32.32)')ibits(intval1,ibits_start,ibits_len)
else
  textval3 = 'Invalid parameters'
endif
end
Integer*4 function ishiftp()
common/integer_number/intval1,intval2,ibits_result,ibits_start,ibits_len
character*32 textval1,textval2,textval3
common/character_number/textval1,textval2,textval3
ishiftp = 1
intval1 = ishft(intval1,+1)
i=iprint_binary()
end
Integer*4 function ishiftn()
common/integer_number/intval1,intval2,ibits_result,ibits_start,ibits_len
character*32 textval1,textval2,textval3
common/character_number/textval1,textval2,textval3
ishiftn = 1
intval1 = ishft(intval1,-1)
i=iprint_binary()
end

This demonstrates:
1. For a negative number the left most bit is 1.
2. The left most bit can be extracted and transferred only if all bits are not beng transferred, that is the sign bit is lost and the result becomes meaningless
3. There is no attempt to transfer anything from the next storage location. ( not tested if "intval1" is an array)
4. If the length is greater than the available up to a limit of 63, then all available bits are transferred including the sign bit as long as the start position is greater than 0.
5. If the length is greater than 63, then things revert to 1, 2, 3 etc, i.e. only the rightmost 6 bits of the length parameter are used and 64 is equivalent to 0,... 71 and 7 are equivalent etc.

Test data -2147000000
pos 0 len 31
pos 0 len 32
pos 1 len 31 etc....

It appears that you cannot extract the whole number including the sign bit and a value of 32 does not work when starting from position zero for integer* 4. I need to try integer*1, *2 & *8 to see if the sign bit performs similarly for lengths of 8, 16 & 64 respectively.

Perhaps it is an error that it does not respond to a length of 32. Any comments Paul.
Ian
Back to top
View user's profile Send private message Send e-mail
IanLambley



Joined: 17 Dec 2006
Posts: 490
Location: Sunderland

PostPosted: Tue Oct 05, 2010 5:26 pm    Post subject: Reply with quote

Perhaps the ISO standard for Fortran (ISO/IEC 1539-1) will clarify the situation.
Quote:

13.3 Bit model
The bit manipulation procedures are ten elemental functions and one elemental subroutine. Logical
operations on bits are provided by the elemental functions IOR, IAND, NOT, and IEOR; shift operations
are provided by the elemental functions ISHFT and ISHFTC; bit subfields may be referenced by the
elemental function IBITS and by the elemental subroutine MVBITS; single-bit processing is provided
by the elemental functions BTEST, IBSET, and IBCLR.
For the purposes of these procedures, a bit is defined to be a binary digit w located at position k of a
nonnegative integer scalar object based on a model nonnegative integer defined by:

j = sum of (Wk x 2^k) for k=0 to z-1

and for which Wk may have the value 0 or 1. An example of a model number compatible with the
examples used in 13.4 would have z = 32, thereby defining a 32-bit integer.
An inquiry function BIT SIZE is available to determine the parameter z of the model.
Effectively, this model defines an integer object to consist of z bits in sequence numbered from right
to left from 0 to z-1. This model is valid only in the context of the use of such an object as the
argument or result of one of the bit manipulation procedures. In all other contexts, the model defined
for an integer in 13.4 applies. In particular, whereas the models are identical for Wz-1 = 0, they do not
correspond for Wz−1 = 1 and the interpretation of bits in such objects is processor dependent.

And that probably states why the function works the way it does as the last sentence make the handling of the sign bit processor dependent. The section 13.4 referred to, applies a sign to the sum of the bits. and therefore one less bit is available for specifying the magnitude of the number for any particular word size.

Regards
Ian
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> General All times are GMT + 1 Hour
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group