Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Help: bitwise operations on a 56 bit word

1 view
Skip to first unread message

Ralph Silverman

unread,
Apr 14, 1997, 3:00:00 AM4/14/97
to

Tim Rogstad (timothy....@jpl.nasa.gov) wrote:
: Hello,

: I have a 56 bit word that I need to do bitwise operations on (namely,
: shift operations and complements.)
: How do I do this in C? If I want to take the 2s complement and I split
: it up into two 32 bit words, there'll be a possible shift when I add one to
: the lower word (after a complement). How do I catch the shift in order to
: carry it over to the other word? Does C provide for this type of thing?
: Any comments or ideas on doing bitwise operations on 'longer than int'
: words would be much appreciated.

: Thanks,

: T

--
****************begin r.s. response*******************

one could not reasonably
expect a language like
the 'c' programming language
to provide such indefinite capabilities
...
if integer data types are too small
here ...
either of finding, or writing,
a library ( of functions, or macros )
to do this,
is appropriate ...

****************end r.s. response*********************
Ralph Silverman
z007...@bcfreenet.seflin.lib.fl.us


Kaz Kylheku

unread,
Apr 14, 1997, 3:00:00 AM4/14/97
to

In article <5itdqp$k...@nntp.seflin.org>,

Ralph Silverman <z007...@bcfreenet.seflin.org> wrote:
>Tim Rogstad (timothy....@jpl.nasa.gov) wrote:
>: Hello,
>
>: I have a 56 bit word that I need to do bitwise operations on (namely,
>: shift operations and complements.)
>: How do I do this in C? If I want to take the 2s complement and I split
>: it up into two 32 bit words, there'll be a possible shift when I add one to
>: the lower word (after a complement). How do I catch the shift in order to
>: carry it over to the other word? Does C provide for this type of thing?
>: Any comments or ideas on doing bitwise operations on 'longer than int'
>: words would be much appreciated.
>
>: Thanks,
>
>: T
>
>--
>****************begin r.s. response*******************
>
> one could not reasonably
> expect a language like
> the 'c' programming language
> to provide such indefinite capabilities

More useless bullshit from Silverman. A 56 bit word can be readily manipulated
using two unsigned long quantities. It's not the same as providing a
general-purpose multi-precision library.

My guess is that this fellow is trying to manipulate DES keys.

Now, to answer the question, how do you overflow shifted bits from one word to
another? What you do is you shift in the opposite direction and save
the result. For example:

void shift_left(unsigned long a[], int n, int shift, int do_rotate)
{
unsigned long carry_in = 0, carry_out;
int i;

for (i = 0; i < n; i++) {
carry_out = (a[i] & 0xffffffful) >> (32 - shift);
a[i] = ((a[i] << shift) | carry_in) & 0xfffffful;
carry_in = carry_out;
}

if (do_rotate)
a[0] |= carry_out;
}

See how the carry out is computed by shifting bits in the opposite direction?
This stores bits in a handy form that can just be ORed into the next word.

The & 0xfffffffful operations force results to 32 bits in case unsigned long
is larger than 32 bits. A good compiler will get rid of these operations if
unsigned long is exactly 32 bits.

I would tailor the routine to your particular needs. E.g. if n is small, you
can unroll the loop manually. If shift is fixed, replace it by a constant.
Etc.

Scott Nudds

unread,
Apr 19, 1997, 3:00:00 AM4/19/97
to

(Kaz Kylheku) wrote:
: Now, to answer the question, how do you overflow shifted bits from one word


: to another? What you do is you shift in the opposite direction and save
: the result. For example:

: void shift_left(unsigned long a[], int n, int shift, int do_rotate)
: {
: unsigned long carry_in = 0, carry_out;
: int i;

: for (i = 0; i < n; i++) {
: carry_out = (a[i] & 0xffffffful) >> (32 - shift);
: a[i] = ((a[i] << shift) | carry_in) & 0xfffffful;
: carry_in = carry_out;
: }

: if (do_rotate)
: a[0] |= carry_out;

: }

More non-functional code from Kylheku.
Kylheku assumes unsigned long has a size of 32 bits.
Kylheku also "ands" by an improper value in the line containing the
shift right.
Similarly her "ands" by an improper value in the line containing the
shift left.
He fails to document that a[0] is the LSWord
He fails do document what any of his input variables represent.
His technique fails for negative numbers.


(Kaz Kylheku) wrote:
: The & 0xfffffffful operations force results to 32 bits in case unsigned


: long is larger than 32 bits.

If unsigned long is > 32 bits, then the technique presented above
truncates the upper bits.


(Kaz Kylheku) wrote:
: I would tailor the routine to your particular needs.

I recommending finding code that works.

--
<---->


Dik T. Winter

unread,
Apr 21, 1997, 3:00:00 AM4/21/97
to

In article <5ja273$r...@james.freenet.hamilton.on.ca> af...@james.freenet.hamilton.on.ca (Scott Nudds) writes:
> Kylheku assumes unsigned long has a size of 32 bits.
So what?

> Kylheku also "ands" by an improper value in the line containing the
> shift right.
What is improper with 0xffffffful, considering the assumption?

> Similarly her "ands" by an improper value in the line containing the
> shift left.
What is improper with 0xfffffful, considering the assumption?

> (Kaz Kylheku) wrote:
> : I would tailor the routine to your particular needs.
>
> I recommending finding code that works.

Why not provide it?
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/

Josef Moellers

unread,
Apr 21, 1997, 3:00:00 AM4/21/97
to

Scott Nudds wrote:

[ ... ]

> Kylheku assumes unsigned long has a size of 32 bits.

Kaz was never challenged to write a portable version of this.

Your "portable assembler" has no predefined word size then?

[ ... ]

John Adelsberger

unread,
Apr 22, 1997, 3:00:00 AM4/22/97
to

Scott Nudds (af...@james.freenet.hamilton.on.ca) wrote:
: (Kaz Kylheku) wrote:

: More non-functional code from Kylheku.

: Kylheku assumes unsigned long has a size of 32 bits.

Ok, he could go to limits.h and improve that. Try finding limits.h in
your assembler, moron.

: Kylheku also "ands" by an improper value in the line containing the
: shift right.
: Similarly her "ands" by an improper value in the line containing the
: shift left.

I'm not even going to argue. Unless you want to claim that it _cannot_
be done correctly, your argument is meaningless.

: He fails to document that a[0] is the LSWord


: He fails do document what any of his input variables represent.

Well, clearly if he doesn't comment it such that you are satisfied,
it won't work, will it?

: His technique fails for negative numbers.

It also fails depending on the endianness of the machine. This sort of
thing is why libraries to perform such tasks are written that have the
same interface across platforms, and this same sort of thing is why
no assembler will ever be 'portable.'

: I recommending finding code that works.

Then obviously we can't write it in PASM, because that won't work without
a vaporware assembler.

--
John J. Adelsberger III St. Louis, MO: (314)434-3067
j...@umr.edu

"I'm the root of all that's evil, but you can call me Cookie." - Bloodhound
Gang

Scott Nudds

unread,
Apr 22, 1997, 3:00:00 AM4/22/97
to

Scott Nudds wrote:
: > Kylheku assumes unsigned long has a size of 32 bits.

Josef Moellers (molle...@sni.de) wrote:
: Kaz was never challenged to write a portable version of this.

C pushers constantly write non-portable code while proclaiming to the
world that C is portable.

They misrepresent reality in order to promote their religion.

Josef Moellers wrote:
: Your "portable assembler" has no predefined word size then?

It does. Implementation provides security and portability.

Kaz Kylheku

unread,
Apr 23, 1997, 3:00:00 AM4/23/97
to

In article <E8ypI...@cwi.nl>, Dik T. Winter <d...@cwi.nl> wrote:
>In article <5ja273$r...@james.freenet.hamilton.on.ca> af...@james.freenet.hamilton.on.ca (Scott Nudds) writes:
> > Kylheku assumes unsigned long has a size of 32 bits.
>So what?

> > Kylheku also "ands" by an improper value in the line containing the
> > shift right.
>What is improper with 0xffffffful, considering the assumption?

Because it should be 0xfffffffful---the intended effect is to reduce the
value modulo 2^32. Indeed, Scott Nudds has applied himself well. I'm surprised
he caught the errors.

What is improper with 0xfffffful is that it will send pieces of your data
to the great bit bucket in the sky. My apologies.

I basically code such things by twitching my finger randomly over the 'f'.
Then I stand back and eyeball the constant to see whether it has approximately
the right length. About 3/4 inches is good for a 32 bit constant on most
terminals, give or take a few sixteenths.

Kaz Kylheku

unread,
Apr 23, 1997, 3:00:00 AM4/23/97
to

In article <5ja273$r...@james.freenet.hamilton.on.ca>,

Scott Nudds <af...@james.freenet.hamilton.on.ca> wrote:
>
>(Kaz Kylheku) wrote:
>: Now, to answer the question, how do you overflow shifted bits from one word
>: to another? What you do is you shift in the opposite direction and save
>: the result. For example:
>
>: void shift_left(unsigned long a[], int n, int shift, int do_rotate)
>: {
>: unsigned long carry_in = 0, carry_out;
>: int i;
>
>: for (i = 0; i < n; i++) {
>: carry_out = (a[i] & 0xffffffful) >> (32 - shift);
>: a[i] = ((a[i] << shift) | carry_in) & 0xfffffful;
>: carry_in = carry_out;
>: }
>
>: if (do_rotate)
>: a[0] |= carry_out;
>: }
>
> More non-functional code from Kylheku.

What ``more'' are you talking about? Cite a previous example of non-working
code to back up your claim, asshole.

Yes it is non-functional. I typed this ``off the cuff of my sleeve'' so
to speak. The masks are gapingly wrong, they should be:

0xfffffffful /* eight f's */

Other than that, I can't see anything wrong.

> Kylheku assumes unsigned long has a size of 32 bits.

Where?

> Kylheku also "ands" by an improper value in the line containing the
> shift right.

Yes, I admit my mistake.

> Similarly her "ands" by an improper value in the line containing the
> shift left.

And you just misspelled 'he' as 'her'. So what?

> He fails to document that a[0] is the LSWord

It isn't.

> He fails do document what any of his input variables represent.

It's your problem that you don't understand it. The purpose of the
code is pretty obvious.

> His technique fails for negative numbers.

What negative numbers? Are you smoking dope? You mean negative shifts? It is
not intended to be used with negative shifts. That's why it's called
``shift_left'' rather than ``shift_bidirectional'' or some such thing. The C
language doesn't even define what happens when a negative operand appers on the
left side of the << operator, you dimwit. The result is implementation
defined. Okay, so the interface could be changed so that the shift amount is an
unsigned int. (But that won't prevent someone from trying to pass in a negative
number which will get reduced to an unsigned one).

In a real project, I would definitely assert the preconditions:

assert(shift > 0 && shift < 32);

Happy?

>(Kaz Kylheku) wrote:
>: The & 0xfffffffful operations force results to 32 bits in case unsigned
>: long is larger than 32 bits.

See? That little blurb shows my intent that the masks should be 0xfffffffful.
It's not like you don't make typos.

> If unsigned long is > 32 bits, then the technique presented above
>truncates the upper bits.

No shit, Sherlock! The whole intent here is to do arithmetic modulo
32 bits in a portable manner, not to take advantage of the implementation's
full unsigned long precision. Hence the masks. If I wished to take
advantage of the full precision, I would have coded it differently.

Either way it's portable ANSI C.

>(Kaz Kylheku) wrote:
>: I would tailor the routine to your particular needs.
>

> I recommending finding code that works.

I do too, because it surely won't emerge from among Scott Nudd's constructive
criticisms.

Still, it serves me right to be chastized for posting untested code.
I apologize to the original poster for the incorrect constants.

Kaz Kylheku

unread,
Apr 23, 1997, 3:00:00 AM4/23/97
to

In article <5jipiu$qr2$2...@news.cc.umr.edu>,

John Adelsberger <j...@ultra5.cc.umr.edu> wrote:
>Scott Nudds (af...@james.freenet.hamilton.on.ca) wrote:
>: (Kaz Kylheku) wrote:
>
>: More non-functional code from Kylheku.
>: Kylheku assumes unsigned long has a size of 32 bits.
>
>Ok, he could go to limits.h and improve that. Try finding limits.h in
>your assembler, moron.

Whether that would be an improvement is a matter of opinion and depends
on as of yet unstated requirements. A strictly conforming program need
not take advantage of precisions beyond the minimum limits.
There is no assumption in the code that unsigned long has a size of 32
bits, only that it has at least 32 bits. That's why the mask operations
to ensure arithmetic modulo 2^32 rather than modulo ULONG_MAX + 1.

>: His technique fails for negative numbers.
>
>It also fails depending on the endianness of the machine. This sort of
>thing is why libraries to perform such tasks are written that have the
>same interface across platforms, and this same sort of thing is why
>no assembler will ever be 'portable.'

That is absolutely false. There is no endianness dependency in the function
at all. How could such a dependency arise, when only abstract operations
(shifts and bitwise logical operators) are used? Endianness and representation
issues arise when an integral object is accesseed in terms of its individual
bytes of storage, a dubious programming practice that was not used in my
example. It _is_ assumed, however, that a[0] is the least significant word,
hence the left shift moves in the direction a[0] -> a[1] -> ...

M. Prasad

unread,
Apr 23, 1997, 3:00:00 AM4/23/97
to

Kaz Kylheku wrote:
>
> In article <E8ypI...@cwi.nl>, Dik T. Winter <d...@cwi.nl> wrote:
> >In article <5ja273$r...@james.freenet.hamilton.on.ca> af...@james.freenet.hamilton.on.ca (Scott Nudds) writes:
> > > Kylheku assumes unsigned long has a size of 32 bits.
> >So what?

> > > Kylheku also "ands" by an improper value in the line containing the
> > > shift right.
> >What is improper with 0xffffffful, considering the assumption?
>
> Because it should be 0xfffffffful---the intended effect is to reduce the
> value modulo 2^32. Indeed, Scott Nudds has applied himself well. I'm surprised
> he caught the errors.

Actually, it shows why the gentleman is upset with C!
Here he is, with fine tuned skills which are of great
use in assembly but of much less use in C. (Never mind
other languages which are a little more abstract than C.)

No wonder he would like the world to work in assembler.
A nice form of assembler, with all good things, such as
portability, readability, apple-pie... thrown in. As long
as it is assembler -- which to Scott Nudds, means some environment
where his abilities such as being able to read hexadecimal
well and being able to find typos and wrong offset numbers easily,
have significant meaning and are appreciated.

Maybe if the skills of programming were being replaced with
the skills of giving commands to robots -- many others
of us would feel the same way and plead desperately
to continue the old ways, in the face of common sense.
(I sure hope if this comes about, we fare better than
that.)

Josef Moellers

unread,
Apr 24, 1997, 3:00:00 AM4/24/97
to

Scott Nudds wrote:
>
> Scott Nudds wrote:
> : > Kylheku assumes unsigned long has a size of 32 bits.
>
> Josef Moellers (molle...@sni.de) wrote:
> : Kaz was never challenged to write a portable version of this.
>
> C pushers constantly write non-portable code while proclaiming to the
> world that C is portable.
>
> They misrepresent reality in order to promote their religion.

Here again, rather than admit your failure, you resort to insulting and
re-iterating your mindless tripe.

>
> Josef Moellers wrote:
> : Your "portable assembler" has no predefined word size then?
>
> It does. Implementation provides security and portability.

What's the word size, then? 32 bits?
Then it will never be able to run on 64 bit machines.

The code Kaz has posted was never meant to be portable.
It is indeed possible to write non-portable code in C.
Whoever denies this, is indeed a "C pusher".

However, it is possible to write portable code in C and one could even
re-write Kaz' code to be portable to 64 bits and beyond:

# include <sys/param.h>


void shift_left(unsigned long a[], int n, int shift, int do_rotate)
{
unsigned long carry_in = 0, carry_out;
int i;

for (i = 0; i < n; i++) {

! carry_out = (a[i] & 0xffffffful) >> (32 - shift);
carry_out = a[i] >> (NBBY * sizeof(unsigned long) - shift);
! a[i] = ((a[i] << shift) | carry_in) & 0xfffffful;
a[i] = (a[i] << shift) | carry_in;
carry_in = carry_out;
}

if (do_rotate)
a[0] |= carry_out;
}

(The lines marked with a '!' are the original lines)

NOTES
Now this code still doesn't work if n exceeds the size of an unsigned
long, but that's an entirely different problem.
Also, the code doesn't have comments, but that too, is not the issue
here.
By referring to the number of bits per byte by using NBBY (defined in
sys/types.h), the code even works for systems that don't have 8 bits per
byte! But even if that is not requested (after all, there are not much
left), NBBY can be recognized to mean "Number of Bits per BYte", much
better than the constant "8".

Scott Nudds

unread,
Apr 24, 1997, 3:00:00 AM4/24/97
to

Scott Nudds wrote:
: > Kylheku assumes unsigned long has a size of 32 bits.

(Dik T. Winter) wrote:
: So what?

It may not be the case.


Scott Nudds wrote:
: > Kylheku also "ands" by an improper value in the line containing the
: > shift right.

(Dik T. Winter) wrote:
: What is improper with 0xffffffful, considering the assumption?

The assumption that is wrong, along with the mask.


Scott Nudds wrote:
: > Similarly her "ands" by an improper value in the line containing the
: > shift left.

(Dik T. Winter) wrote:
: What is improper with 0xfffffful, considering the assumption?

The assumption that is wrong, along with the mask.


: > (Kaz Kylheku) wrote:
: > : I would tailor the routine to your particular needs.

Scott Nudds wrote:
: > I recommending finding code that works.

(Dik T. Winter) wrote:
: Why not provide it?

I prefer avoiding bastard languages like C.


--
<---->


Scott Nudds

unread,
Apr 27, 1997, 3:00:00 AM4/27/97
to

"M. Prasad" <pra...@polaroid.com> wrote:
: As long

: as it is assembler -- which to Scott Nudds, means some environment
: where his abilities such as being able to read hexadecimal
: well and being able to find typos and wrong offset numbers easily,
: have significant meaning and are appreciated.

M. Prasad's attempt to psychoanalyze miss the mark. My primary
interest is code generation efficiency. My secondary interest is
readability. My next highest interest is the promotion of a secure
programming environment - which includes #2 as a component.

Given a high level language that adequately addressed these concerns,
there would no longer be a need for assembler.

C is a spectacular failure in all three areas. It is one of the worst
languages ever created.

--
<---->


John Adelsberger

unread,
Apr 27, 1997, 3:00:00 AM4/27/97
to

Kaz Kylheku (k...@vision.crest.nt.com) wrote:

: In article <5jipiu$qr2$2...@news.cc.umr.edu>,
: John Adelsberger <j...@ultra5.cc.umr.edu> wrote:
: >Ok, he could go to limits.h and improve that. Try finding limits.h in
: >your assembler, moron.

: Whether that would be an improvement is a matter of opinion and depends
: on as of yet unstated requirements. A strictly conforming program need
: not take advantage of precisions beyond the minimum limits.

: There is no assumption in the code that unsigned long has a size of 32
: bits, only that it has at least 32 bits. That's why the mask operations


: to ensure arithmetic modulo 2^32 rather than modulo ULONG_MAX + 1.

Ok, but is there anything lost in using ULONG_MAX? I don't have the code
in front of me and don't remember the reason for writing it, but I can't
think why you _wouldn't_ do it.

: >: His technique fails for negative numbers.


: >
: >It also fails depending on the endianness of the machine. This sort of
: >thing is why libraries to perform such tasks are written that have the
: >same interface across platforms, and this same sort of thing is why
: >no assembler will ever be 'portable.'

: That is absolutely false. There is no endianness dependency in the function
: at all. How could such a dependency arise, when only abstract operations
: (shifts and bitwise logical operators) are used? Endianness and representation
: issues arise when an integral object is accesseed in terms of its individual
: bytes of storage, a dubious programming practice that was not used in my
: example. It _is_ assumed, however, that a[0] is the least significant word,
: hence the left shift moves in the direction a[0] -> a[1] -> ...

My mistake. I forgot that the C bitshift makes all machines look to be
big-endian. Too long spent writing MIPS assembly for me:-) I hardly
ever use the C bitshifts(should, but don't,) and so I tend to confuse
myself occasionally.

Later,

Scott Nudds

unread,
Apr 27, 1997, 3:00:00 AM4/27/97
to

: Scott Nudds wrote:
: : More non-functional code from Kylheku.
: : Kylheku assumes unsigned long has a size of 32 bits.

(John Adelsberger) wrote:
: Ok, he could go to limits.h and improve that. Try finding limits.h in
: your assembler, moron.

I doubt if a header file will correct for Kylheku's programming
errors. I am amused you think it will.

As to limits.h. Why should I look for such a thing with my assembler.
The size of variables are well defined and immutable.

Assembler is not like the C pusher hell where a programmer is kept
completely ignorant about the size of his variables.

Scott Nudds wrote:
: : Kylheku also "ands" by an improper value in the line containing the
: : shift right.

: : Similarly her "ands" by an improper value in the line containing the
: : shift left.

(John Adelsberger) wrote:
: I'm not even going to argue. Unless you want to claim that it _cannot_


: be done correctly, your argument is meaningless.

You are wise not to argue in defense of Kylheku's flawed and
unworkable code. I am amused you consider the identification of flawed
and unworkable code, "meaningless".

C pushers will say anything.


Scott Nudds wrote:
: : His technique fails for negative numbers.

(John Adelsberger) wrote:
: It also fails depending on the endianness of the machine. This sort of
: thing is why libraries to perform such tasks are written that have the
: same interface across platforms, and this same sort of thing is why
: no assembler will ever be 'portable.'

How unfortunate for Kylheku that he was attempting to show that a
library was not required.


--
<---->


Scott Nudds

unread,
Apr 27, 1997, 3:00:00 AM4/27/97
to


(Kaz Kylheku) wrote:
: Yes it is non-functional. I typed this ``off the cuff of my sleeve'' so


: to speak. The masks are gapingly wrong, they should be:

: 0xfffffffful /* eight f's */

I am happy to see you admitting to your mistake Mr. Kylheku. If I can
have honesty, mistakes are easier to overlook.


(Kaz Kylheku) wrote:
: Other than that, I can't see anything wrong.

: > Kylheku assumes unsigned long has a size of 32 bits.

(Kaz Kylheku) wrote:
: Where?

Your array is of type unsigned long. Storing a value that requires
more than 32 bits into an array element will cause your routine to fail.

C should support fixed size variable sizes and a syntax like the
following.

carry_in = 0 ; set initial carry
for (all elements in a[], index i) begin ; for all elements in array
carry_out=0 ; set local carry
(carry_out:a[i]<<shift) ; shift value
a[i] |= carry_in ; mask in carry from previous shift
carry_in = carry_out ; preserve carry for next iteration
next

But this wouldn't be necessary for the initial problem if C had
provided 64 bit integers variables. Then the shift would have been
immediate.

(var<<shift) & mask

Scott Nudds wrote:
: > Kylheku also "ands" by an improper value in the line containing the
: > shift right.

(Kaz Kylheku) wrote:
: Yes, I admit my mistake.

Forgiven.


Scott Nudds wrote:
: > Similarly her "ands" by an improper value in the line containing the
: > shift left.

(Kaz Kylheku) wrote:
: And you just misspelled 'he' as 'her'. So what?

Your mistake is not so easily forgotten.

Scott Nudds wrote:
: > He fails to document that a[0] is the LSWord

(Kaz Kylheku) wrote:
: It isn't.

That's funny, I thought you were shifting left. Perhaps the label
"shift_left" gave me the wrong impression. But the code certainly did
not.

/---v /---v
|< < |< |< <--<--<--<
a0,a1,a2,a3 a3,a2,a1,a0
^ |___^ | |_________^
|_______|
do_rotate

Are you denying that shift left shifts toward the MSBit or are you
claiming that your rotation option is incorrect?


Scott Nudds wrote:
: > He fails do document what any of his input variables represent.

(Kaz Kylheku) wrote:
: It's your problem that you don't understand it. The purpose of the
: code is pretty obvious.

Oh, clearly I understand the code. I also understand that it is
incorrect and inadequate for a number of reasons.


Scott Nudds wrote:
: > His technique fails for negative numbers.

(Kaz Kylheku) wrote:
: What negative numbers? Are you smoking dope? You mean negative shifts? It


: is not intended to be used with negative shifts.

No, I mean negative numbers in the array. The number that is being
shifted.

You should at least document that it does not support negative numbers.


(Kaz Kylheku) wrote:
: That's why it's called


: ``shift_left'' rather than ``shift_bidirectional'' or some such thing. The C
: language doesn't even define what happens when a negative operand appers on
: the left side of the << operator, you dimwit.

Another hole in the specification. Are the bureaucrats at ANSI so
cowardly that they can not define it is an illegal operation?

No, that would be too much to ask from those brain dead old men and
the festering religionists that worship them.

(Kaz Kylheku) wrote:
: In a real project, I would definitely assert the preconditions:


: assert(shift > 0 && shift < 32);
: Happy?

Of course not. This solution is garbage for two reasons. First it
is best prevented at compile time, and second because no meaningful
error message is printed by the assert macro. The program just bails
out with the message "shift > 0 && shift < 32".

I guess the mindless old geezers at ANSI have no imagination. Perhaps
they should spend a couple of decades debating among themselves if
their imagination == 0.


Scott Nudds wrote:
: > If unsigned long is > 32 bits, then the technique presented above
: >truncates the upper bits.

Kaz Kylheku wrote:
: No shit, Sherlock! The whole intent here is to do arithmetic modulo


: 32 bits in a portable manner, not to take advantage of the implementation's
: full unsigned long precision. Hence the masks.

Pity the code wouldn't work. Even more a pity that you don't document
that the variables in a[i] can not be used in full precision, and that
doing so will cause the upper bits to be lost when you call your shift
function.


Kaz Kylheku wrote:
: If I wished to take


: advantage of the full precision, I would have coded it differently.

A much cleaner solution is to have the language support fixed size 64
bit variables.


Kaz Kylheku wrote:
: Still, it serves me right to be chastized for posting untested code.


: I apologize to the original poster for the incorrect constants.

I remember Kylheku complaining bitterly about some untested code I
posted about 6 months ago. He must have complained about a dozen times
(perhaps more) over a period of a month or two.

Once again we see that C pushers have one rule for themselves and
another for everyone else.

--
<---->


Kaz Kylheku

unread,
Apr 28, 1997, 3:00:00 AM4/28/97
to

In article <5jvtks$m...@james.freenet.hamilton.on.ca>,

Scott Nudds <af...@james.freenet.hamilton.on.ca> wrote:
>: Scott Nudds wrote:
>: : More non-functional code from Kylheku.
>: : Kylheku assumes unsigned long has a size of 32 bits.
>
>(John Adelsberger) wrote:
>: Ok, he could go to limits.h and improve that. Try finding limits.h in
>: your assembler, moron.
>
> I doubt if a header file will correct for Kylheku's programming
>errors. I am amused you think it will.
>
> As to limits.h. Why should I look for such a thing with my assembler.
>The size of variables are well defined and immutable.
>
> Assembler is not like the C pusher hell where a programmer is kept
>completely ignorant about the size of his variables.

Apparently the designers behind Ada 95 also didn't think that fixing the
sizes of the fundamental types was a good idea.

3.5.4 Integer Types

...

If Long_Integer is predefined for an implementation, then its range
shall include the range -2**31+1 .. +2**31-1.

(From ISO/IEC 8652:1995 Information Technology---Programming
Languages--Ada)

The above clause essentially means that a Long_Integer shall have _at least_
the stated range, exactly as in C.

> You are wise not to argue in defense of Kylheku's flawed and
>unworkable code. I am amused you consider the identification of flawed
>and unworkable code, "meaningless".

So, have you found any other errors in the code other than the unfortunate
masks? You are blowing the typos way out of proportion. Perhaps you have
feelings of inferiority about your own programming abilities.

> How unfortunate for Kylheku that he was attempting to show that a
>library was not required.

I was not attempting to do any such thing.

Chris Lomont

unread,
Apr 28, 1997, 3:00:00 AM4/28/97
to

Please list your ordering of languages, from best to worst. If C is near
the bottom, as you claim, list the top and bottom 10 in order (in your
opinion, of course). I'm just curious where you get your ideas.

Chris Lomont

Kaz Kylheku

unread,
Apr 28, 1997, 3:00:00 AM4/28/97
to

In article <5jvtme$m...@james.freenet.hamilton.on.ca>,

Scott Nudds <af...@james.freenet.hamilton.on.ca> wrote:
>
>
>(Kaz Kylheku) wrote:
>: Yes it is non-functional. I typed this ``off the cuff of my sleeve'' so
>: to speak. The masks are gapingly wrong, they should be:
>
>: 0xfffffffful /* eight f's */
>
> I am happy to see you admitting to your mistake Mr. Kylheku. If I can
>have honesty, mistakes are easier to overlook.

I always admit mistakes and post retractions.

>(Kaz Kylheku) wrote:
>: Other than that, I can't see anything wrong.
>
>: > Kylheku assumes unsigned long has a size of 32 bits.
>
>(Kaz Kylheku) wrote:
>: Where?
>
> Your array is of type unsigned long. Storing a value that requires
>more than 32 bits into an array element will cause your routine to fail.

No, the routine will simply destroy the extra bits. Using the extra bits would
violate a fundamental invariant of the selected data representation. It would
make the program internally inconsistent. I could use assertions to enforce
the preconditions and invariants.

> C should support fixed size variable sizes and a syntax like the
>following.
>
>carry_in = 0 ; set initial carry
>for (all elements in a[], index i) begin ; for all elements in array
> carry_out=0 ; set local carry
> (carry_out:a[i]<<shift) ; shift value
> a[i] |= carry_in ; mask in carry from previous shift
> carry_in = carry_out ; preserve carry for next iteration
>next

This can be done if you elect to use the full available precision of unsigned
long. This, of course, is equivalent to a change in the representation.

Perhaps you would be happier in Ada. In that language, you can define
subtypes with constrained ranges. You can even define special integral types
that do modulo arithmetic with just about any modulus, for example:

type Hash_Index is mod 97; -- prime modulus

The range of possible moduli is constrained, of course.

If you don't like twiddling and masking, don't use C.

> But this wouldn't be necessary for the initial problem if C had
>provided 64 bit integers variables. Then the shift would have been
>immediate.

Yes, but then what if you had the 64 bit variables but need to shift a 256 bit
quantity? Either you have a language that works with large-precision integers
idirectly, or you have to represent them using more fundamental types.

As an exmaple, the BC language can readily raise 3 to the power of 500:

$ bc

3 ^ 500
363602917958699368423852670795433191180233850260016230403460358325806\
0019158389548419850826297938878330817970253440385575285593151701306614\
2992430916562025780021771247847643450125342836565813209972590371590152\
578728008385990139795377610001

Not bad for command driven trash. :)

Craig Franck

unread,
Apr 28, 1997, 3:00:00 AM4/28/97
to

k...@vision.crest.nt.com (Kaz Kylheku) wrote:
>In article <5jvtks$m...@james.freenet.hamilton.on.ca>,

>Scott Nudds <af...@james.freenet.hamilton.on.ca> wrote:
>>: Scott Nudds wrote:
>>: : More non-functional code from Kylheku.
>>: : Kylheku assumes unsigned long has a size of 32 bits.

>> You are wise not to argue in defense of Kylheku's flawed and
>>unworkable code. I am amused you consider the identification of flawed
>>and unworkable code, "meaningless".
>
>So, have you found any other errors in the code other than the unfortunate
>masks? You are blowing the typos way out of proportion.

That is a debate technique that Scott is using. SN is 85% technique
and 15% actual substance (of that, 13% is inaccurate, disinformation
or mischaracterization).

>Perhaps you have
>feelings of inferiority about your own programming abilities.

You would get farther arguing with the devil himself.

--
Craig
clfr...@worldnet.att.net
Manchester, NH
All evolution in thought and conduct must at first appear
as heresy and misconduct. -- George Bernard Shaw

James S. Rogers

unread,
Apr 28, 1997, 3:00:00 AM4/28/97
to

Kaz Kylheku wrote:
>
> Apparently the designers behind Ada 95 also didn't think that fixing the
> sizes of the fundamental types was a good idea.
>
> 3.5.4 Integer Types
>
> ...
>
> If Long_Integer is predefined for an implementation, then its range
> shall include the range -2**31+1 .. +2**31-1.
>
> (From ISO/IEC 8652:1995 Information Technology---Programming
> Languages--Ada)
>
> The above clause essentially means that a Long_Integer shall have _at least_
> the stated range, exactly as in C.

This is true. It is also true that the Ada 95 standard defines a number of
attributes. The one appropriate to this discussion is the 'Size attribute.
The 'Size attribute is defined as:

Appendix K Language Defined Attributes

S'Size For every subtype S:

If S is definite, denotes the size (in bits) that the implementation
would choose for the following objects of subtype S:

* A record component of subtype S when the record type is packed

* The formal parameter of an instance of Unchecked_Conversion that
converts from subtype S to some other subtype.

If S is indefinite, the meaning is implementation defined. The value of
this attribute is of type universal_integer.

From International Standard ANSI/ISO/IEC-8652:1995
Information technology - Programming languages - Ada

This gives the Ada programmer complete access to the size of any definite subtype.
This clearly differs from the C or C++ sizeof operator. Sizeof does not report
a size in bits. Of course, the number of bits of a type can be calculated in C
or C++, assuming everything is packaged in neat chunks of 8-bit bytes. For most
C or C++ applications this is not a problem. The problem only arises when using
bit fields. C and C++ cannot define a type which is a three bit field. They
can define three bit fields, just not a type to associate them with.

In Ada I can define a three bit field in the following manner:

type bit_3 is mod 2**3;

Likewise a 5 bit field is defined as

type bit_5 is mod 2**5;

I can then combine these fields in a record to define a byte broken into
a three bit field and a 5 bit field:

type bitfields is record
mode : bit_3;
status : bit_5;
end record;

pragma pack(bitfields);

bitfields'Size yields 8
bit_3'Size yields 3
bit_5'Size yields 5

You can begin to see Ada's pedigree in embedded systems programming in
this discussion.

Nonetheless, Ada does yield entirely consistent and reliable knowledge of
the sizes of types. The same cannot be said of C or C++.

Jim Rogers
Colorado Springs, Colorado
--------------------------
Team Ada

Scott Nudds

unread,
Apr 28, 1997, 3:00:00 AM4/28/97
to

: > Josef Moellers wrote:
: > : Your "portable assembler" has no predefined word size then?
: >
: > It does. Implementation provides security and portability.

Josef Moellers wrote:
: What's the word size, then? 32 bits?

Variable sizes are 1, 2, 4, 8, 16 bytes for integer types.


Josef Moellers wrote:
: The code Kaz has posted was never meant to be portable.

C pushers claim that C is portable yet they never seem able to post
portable code that does anything useful. And when they do anything
useful, it never seems to be with portable code.

They are scam artists playing two card monte.

Josef Moellers wrote:
: However, it is possible to write portable code in C and one could even


: re-write Kaz' code to be portable to 64 bits and beyond:

: # include <sys/param.h>
: void shift_left(unsigned long a[], int n, int shift, int do_rotate)
: {
: unsigned long carry_in = 0, carry_out;
: int i;

: for (i = 0; i < n; i++) {
: ! carry_out = (a[i] & 0xffffffful) >> (32 - shift);
: carry_out = a[i] >> (NBBY * sizeof(unsigned long) - shift);
: ! a[i] = ((a[i] << shift) | carry_in) & 0xfffffful;
: a[i] = (a[i] << shift) | carry_in;
: carry_in = carry_out;
: }

: if (do_rotate)
: a[0] |= carry_out;
: }

: (The lines marked with a '!' are the original lines)

So the above code is portable is it?
None of my compilers have a param.h file.
None of them have a types.h file.
No header file defines anything called NBBY.

Your "portable" code doesn't even compile.

If C were a rationally defined language, rather than a piece of shit,
you would not have been a failure at trying to produce a portable
program.

C is an abortion. Admit it.

--
<---->


John Adelsberger

unread,
Apr 29, 1997, 3:00:00 AM4/29/97
to

On 27 Apr 1997, Scott Nudds wrote:

> M. Prasad's attempt to psychoanalyze miss the mark. My primary
> interest is code generation efficiency. My secondary interest is

If you want efficient code, keep this in mind:

Even if you write assembler for the Java machine, it has to be translated
into native assembler for the target platform. To be fair, the Java
VM is _so_ CISC that the difficulty in doing so is probably comparable
to the difficulty in translating C, so I your Java assembler is unlikely
to be any more efficient than C.

Dik T. Winter

unread,
Apr 29, 1997, 3:00:00 AM4/29/97
to

In article <33656E...@worldnet.att.net> "James S. Rogers" <JimMaure...@worldnet.att.net> writes:
> This gives the Ada programmer complete access to the size of any definite
> subtype. This clearly differs from the C or C++ sizeof operator. Sizeof
> does not report a size in bits. Of course, the number of bits of a type
> can be calculated in C or C++, assuming everything is packaged in neat
> chunks of 8-bit bytes.

Which is wrong. If you assume it is packaged in bytes of CHAR_BIT bits
the assumption is correct. So?

John Winters

unread,
Apr 29, 1997, 3:00:00 AM4/29/97
to

In article <5k05bc$613$2...@news.cc.umr.edu>,
John Adelsberger <j...@ultra4.cc.umr.edu> wrote:
[snip]

>My mistake. I forgot that the C bitshift makes all machines look to be
>big-endian. Too long spent writing MIPS assembly for me:-) I hardly
>ever use the C bitshifts(should, but don't,) and so I tend to confuse
>myself occasionally.

Sorry, I didn't quite follow that. Could you explain how C bitshifts
make all machines look big-endian please?

TIA,
John

--
John Winters. Wallingford, Oxon, England.

Corey Brenner

unread,
Apr 29, 1997, 3:00:00 AM4/29/97
to

Scott Nudds (af...@james.freenet.hamilton.on.ca) wrote:
: M. Prasad's attempt to psychoanalyze miss the mark. My primary
: interest is code generation efficiency. My secondary interest is
: readability. My next highest interest is the promotion of a secure

: programming environment - which includes #2 as a component.

: Given a high level language that adequately addressed these concerns,
: there would no longer be a need for assembler.

Like C?

--
Corey D. Brenner -- (bre...@umr.edu, bre...@acm.cs.umr.edu)
==========================================================================
#include <std_disclaimer.h> | Look here soon for new, improved
| drivel. I have No Earthly Idea [tm]
This .signature is in | what I'll put here, but rest assured,
>>>FEEL-AROUND<<< | I'll find it humorous. If you do,
| cool. If not, well, it _IS_ _MY_ .sig.
==========================================================================
"I yam Popeye of Borg. Resistinks is futile. You will be askimilgrated."

Kaz Kylheku

unread,
Apr 29, 1997, 3:00:00 AM4/29/97
to

In article <33656E...@worldnet.att.net>,

James S. Rogers <JimMaure...@worldnet.att.net> wrote:

>Appendix K Language Defined Attributes
>
>S'Size For every subtype S:
>
> If S is definite, denotes the size (in bits) that the implementation
> would choose for the following objects of subtype S:
>
> * A record component of subtype S when the record type is packed
>
> * The formal parameter of an instance of Unchecked_Conversion that
> converts from subtype S to some other subtype.
>
> If S is indefinite, the meaning is implementation defined. The value of
> this attribute is of type universal_integer.
>
>From International Standard ANSI/ISO/IEC-8652:1995
>Information technology - Programming languages - Ada
>

>This gives the Ada programmer complete access to the size of any definite subtype.
>This clearly differs from the C or C++ sizeof operator. Sizeof does not report
>a size in bits. Of course, the number of bits of a type can be calculated in C

>or C++, assuming everything is packaged in neat chunks of 8-bit bytes. For most

That is false. The size of a byte is in <limits.h>, a symbol known as CHAR_BIT.
You can multiply the size of a type by CHAR_BIT, thus eliminating the
dependency on eight. With this multiplication, what you will get is the number
of bits that the type occupies in storage, not the actual number of bits of
precision. There may be unused bits in the representation of a type which don't
contribute to its value (however the char types are defined such that they have
no unused bits). For example, a 9 bit implementation could have a 35 bit
integer that occupies a 36 bit word of storage, but chars would be 9 bits.

In programming, what is of interest is the number of value-contributing bits,
not the total bits of storage. In C, the value contributing bits can only be
computed at run-time, or externally configured at compile time.

>C or C++ applications this is not a problem. The problem only arises when using
>bit fields. C and C++ cannot define a type which is a three bit field. They

Sure it can:

struct foo {
unsigned bitfield : 3;
}

That is a three bit field. It may hold the values 0 through 7.

>can define three bit fields, just not a type to associate them with.

It has a type ``unsigned int''. However, bitfields do not exist alone,
just as structure members. And the way these structure members are actually
laid out in storage is very specific to an implementation. The only
maximally portable way to use bitfields is as a way of saving storage
at a potential execution penalty.

>In Ada I can define a three bit field in the following manner:
>
>type bit_3 is mod 2**3;
>
>Likewise a 5 bit field is defined as
>
>type bit_5 is mod 2**5;
>
>I can then combine these fields in a record to define a byte broken into
>a three bit field and a 5 bit field:
>
>type bitfields is record
> mode : bit_3;
> status : bit_5;
>end record;
>
>pragma pack(bitfields);
>
>bitfields'Size yields 8
>bit_3'Size yields 3
>bit_5'Size yields 5
>
>You can begin to see Ada's pedigree in embedded systems programming in
>this discussion.

Not really, to tell the truth. For one thing, what if you packed a mod 2**6
and a mod 2**7? Would the size of bitfields be 13? What would an array
of these structures look like? Could there be padding at the end of the
record, yet the 'Size attribute still report 13?

Furthermore, it's not clear (from this discussion) that the above mechanism
could be used to conform to an external layout in a portable fashion.

>Nonetheless, Ada does yield entirely consistent and reliable knowledge of
>the sizes of types. The same cannot be said of C or C++.

Actually it can. Whereas you don't have the slick attribute system (which
would't really serve a useful purpose in C's type system anyway), nearly all
the information you need is in <limits.h>. The only aggravation is having to
compute the number of bits in an integral type other than char or unsigned
char, because <limits.h> only provides the ranges of the larger integral types,
not the number of value bits used in their representation. This information
is occassionally valuable, but not often enough to make it a major nuisance.

Kaz Kylheku

unread,
Apr 29, 1997, 3:00:00 AM4/29/97
to

In article <5k597q$6...@polo.demon.co.uk>,

John Winters <jo...@polo.demon.co.uk> wrote:
>In article <5k05bc$613$2...@news.cc.umr.edu>,
>John Adelsberger <j...@ultra4.cc.umr.edu> wrote:
>[snip]
>>My mistake. I forgot that the C bitshift makes all machines look to be
>>big-endian. Too long spent writing MIPS assembly for me:-) I hardly
>>ever use the C bitshifts(should, but don't,) and so I tend to confuse
>>myself occasionally.
>
>Sorry, I didn't quite follow that. Could you explain how C bitshifts
>make all machines look big-endian please?

It's easy. Lexically, we write numbers from most significant digit to least
significant digit. This is basically big endian.

The shift left and shift right operators are aligned with this lexical
convention. Hence they look big endian.

Ha! :)

John Adelsberger

unread,
Apr 29, 1997, 3:00:00 AM4/29/97
to

Scott Nudds (af...@james.freenet.hamilton.on.ca) wrote:

: : > Josef Moellers wrote:
: : > : Your "portable assembler" has no predefined word size then?
: : >
: : > It does. Implementation provides security and portability.

: Josef Moellers wrote:
: : What's the word size, then? 32 bits?

: Variable sizes are 1, 2, 4, 8, 16 bytes for integer types.

So it is a FACT that it will run suboptimally on 32 and 64 bit architectures
that simplify decoding by alignment. You will likely waste upwards of
3/4 of every machine word worth of memory because of this inanity. Yeah,
that'll reduce code bloat. Of course, since your data segment just grew
by a factor greater than 4, you're still going to need more RAM than you
think will ever be found on a PC. (Yes, you could write bitshift routines
to access integers packed 2 or 4 or more to a word - guess what - it'd
be nonportable and hideously slow.)

Scott Nudds

unread,
May 7, 1997, 3:00:00 AM5/7/97
to

Scott Nudds wrote:
: : Variable sizes are 1, 2, 4, 8, 16 bytes for integer types.

(John Adelsberger) wrote:
: So it is a FACT that it will run suboptimally on 32 and 64 bit architectures


: that simplify decoding by alignment.

You are an idiot.

A variable of size n bits need not be held in a register of n bits.
The only need is that the variable be manipulated as if it had the
specified size.


(John Adelsberger) wrote:
: You will likely waste upwards of


: 3/4 of every machine word worth of memory because of this inanity.

You have one choice when implementing a 0-200 counter in a 32 bit
register. You must avoid using the upper 24 bits. 3/4'ths of the
register are unused.

How do you propose to make use of the unused portion of the register?
Change the loop count?

You are a moron.


(John Adelsberger) wrote:
: Of course, since your data segment just grew


: by a factor greater than 4, you're still going to need more RAM than you
: think will ever be found on a PC.

Why should the data segment grow by a factor of 4, when byte sized
variables are held in byte sized registers rather than word sized
registers?

Clearly, storing byte sized data in byte sized registers can only
reduce storage requirements in the aggregate.

You are a twit.


--
<---->


John Adelsberger

unread,
May 10, 1997, 3:00:00 AM5/10/97
to

Scott Nudds (af...@james.freenet.hamilton.on.ca) wrote:

: Scott Nudds wrote:
: : : Variable sizes are 1, 2, 4, 8, 16 bytes for integer types.

: (John Adelsberger) wrote:
: : So it is a FACT that it will run suboptimally on 32 and 64 bit architectures
: : that simplify decoding by alignment.

: You are an idiot.

: A variable of size n bits need not be held in a register of n bits.
: The only need is that the variable be manipulated as if it had the
: specified size.

Then why bother to specify? It can only mean that extra code will be
needed to check the bounds of every single reference to the variable.
That might be nice for debugging purposes, but it will result in
hideously slow production code.

0 new messages