www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - >>>

reply Arcane Jill <Arcane_member pathlink.com> writes:
The docs say:
"<< is a left shift. >> is a signed right shift. >>> is an unsigned right
shift."

Now, here's the thing:

We don't have separate operators for signed multiply and unsigned multiply. Why
not? Because one operator does both jobs, based on the type of its arguments.

We don't have separate operators for signed divide and unsigned divide. Why not?
Because one operator does both jobs, based on the type of its arguments.

Same goes for %.

And yet, we DO have separater operators for signed right shift and unsigned
right shift. C doesn't. C++ doesn't. But D does.

?

And, if I have understood the documentation correctly, these operators the
actual sign of the arguments (which means that D's (uint >> uint) will behave
differently from C).

I believe that Java has both >> and >>> - but with good reason. Java has no
unsigned integers, and so you need a separate operator (>>>) to do unsigned
shift right. This logic does not apply to D.

Is there a point to all this? Or is it just a case of "Oh yeah, that. I was
going to fix that years ago but there always seemed be more important things to
do"?

Arcane Jill (confused)
Jul 27 2004
next sibling parent reply Berin Loritsch <bloritsch d-haven.org> writes:
Arcane Jill wrote:

 The docs say:
 "<< is a left shift. >> is a signed right shift. >>> is an unsigned right
 shift."
 

Question: what is the difference between a signed shift and an unsigned shift? I know there is a difference between a Roll-Over and a Shift. A simple shift will set the overflow flag with the bit shoved off the end and simply fill in zeros in the empty space. For example: 00001111 >> 1 == 00000111 A roll over will operate the same way the shift does, except it uses the value of the overflow flag to fill in the empty space. This results in what appears to be a roll over: 00001111 >>> 1 == 10000111 These are two separate operations, with very different results. This is why Java really has the >> and >>> operators. It has nothing to do with signed and unsigned numbers. It has to do with predictable roll over vs. shift operations. These are bitwise operations and really have nothing to do with sign. Most folks know that the shift function is a Q&D multiply/divide by 2. The roll over is different, and used in hash functions among other things.
Jul 27 2004
next sibling parent Berin Loritsch <bloritsch d-haven.org> writes:
Berin Loritsch wrote:

 Arcane Jill wrote:
 
 The docs say:
 "<< is a left shift. >> is a signed right shift. >>> is an unsigned right
 shift."

Question: what is the difference between a signed shift and an unsigned shift? I know there is a difference between a Roll-Over and a Shift. A simple shift will set the overflow flag with the bit shoved off the end and simply fill in zeros in the empty space. For example: 00001111 >> 1 == 00000111 A roll over will operate the same way the shift does, except it uses the value of the overflow flag to fill in the empty space. This results in what appears to be a roll over: 00001111 >>> 1 == 10000111

Oops, I forgot to mention that most processors also have a BOF (Branch on Overflow). This is the reason that the overflow flag is involved. This info dates back to when I did assembly work (not so much anymore).
Jul 27 2004
prev sibling next sibling parent reply Ilya Minkov <minkov cs.tum.edu> writes:
Berin Loritsch schrieb:

 Question: what is the difference between a signed shift and an unsigned 
 shift?

To fill up the "empty" bit which appears when shifting right, unsigned shift inserts a zero there. Signed shift replicates the old leftmost bit. If you're puzzled, look up "2's complement". Unsigned shift right, is just that - a shift, which appears to divide a positive integer by 2 (or a power thereof). Signed shift right divides by 2 (or a power thereof) taking the sign into attention. With left shifts, there is no difference between signed and unsigned - always fill up with zero, and always correspond to multiplication by 2 (or a power thereof). -eye
Jul 27 2004
parent reply Berin Loritsch <bloritsch d-haven.org> writes:
Ilya Minkov wrote:

 Berin Loritsch schrieb:
 
 Question: what is the difference between a signed shift and an 
 unsigned shift?

To fill up the "empty" bit which appears when shifting right, unsigned shift inserts a zero there. Signed shift replicates the old leftmost bit. If you're puzzled, look up "2's complement". Unsigned shift right, is just that - a shift, which appears to divide a positive integer by 2 (or a power thereof). Signed shift right divides by 2 (or a power thereof) taking the sign into attention. With left shifts, there is no difference between signed and unsigned - always fill up with zero, and always correspond to multiplication by 2 (or a power thereof).

Ok, Signed SHift == Roll Over, and Unsigned Shift == shift
Jul 27 2004
parent Ilya Minkov <minkov cs.tum.edu> writes:
Berin Loritsch schrieb:

 Ok, Signed SHift == Roll Over, and Unsigned Shift == shift

No. it's *not* a roll! Read again, or consult someone who can explain it better. The *leftmost* bit gets replicated, not the one which is shifted out! -eye
Jul 27 2004
prev sibling next sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <ce5lrj$26js$1 digitaldaemon.com>, Berin Loritsch says...

Arcane Jill wrote:

 The docs say:
 "<< is a left shift. >> is a signed right shift. >>> is an unsigned right
 shift."
 

Question: what is the difference between a signed shift and an unsigned shift?

I would have expected you to know this, coming from a Java background. Java clearly has both, as documented at Sun's Java website: http://java.sun.com/docs/books/tutorial/java/nutsandbolts/bitwise.html (x >> 1) is the same thing as (x / 2) if x is signed (x >>> 1) is the same thing as (x / 2) if x is unsigned
A simple shift will set the overflow flag with the bit shoved off the 
end and simply fill in zeros in the empty space.  For example:

00001111 >> 1 == 00000111

A roll over will operate the same way the shift does, except it uses the
value of the overflow flag to fill in the empty space.  This results in
what appears to be a roll over:

00001111 >>> 1 == 10000111

These are two separate operations, with very different results.  This
is why Java really has the >> and >>> operators.  It has nothing to do
with signed and unsigned numbers.  It has to do with predictable roll
over vs. shift operations.

That's not what it says on the Java web site. Anyway, if >>> does rotate-right, then why is there no corresponding <<< for rotate-left?
Most folks know that the shift function is a Q&D multiply/divide by 2.

Q and D?
The roll over is different, and used in hash functions among other
things.

Of course, you can use the ROL and ROR instructions in D using inline assembler. But this has got nothing to do with >>> (so I'm changing the thread title). It might be useful to have these functions in std.intrinsic though. Jill
Jul 27 2004
parent Berin Loritsch <bloritsch d-haven.org> writes:
Arcane Jill wrote:

 In article <ce5lrj$26js$1 digitaldaemon.com>, Berin Loritsch says...
 
 
Arcane Jill wrote:


The docs say:
"<< is a left shift. >> is a signed right shift. >>> is an unsigned right
shift."

Question: what is the difference between a signed shift and an unsigned shift?

I would have expected you to know this, coming from a Java background. Java clearly has both, as documented at Sun's Java website: http://java.sun.com/docs/books/tutorial/java/nutsandbolts/bitwise.html (x >> 1) is the same thing as (x / 2) if x is signed (x >>> 1) is the same thing as (x / 2) if x is unsigned

Honestly, I have always parsed this in light of my old assembly experience, and really don't get hopped up on reading specs.
 
 That's not what it says on the Java web site. Anyway, if >>> does rotate-right,
 then why is there no corresponding <<< for rotate-left?
 

Good question
 
 
Most folks know that the shift function is a Q&D multiply/divide by 2.

Q and D?

Quick and Dirty
The roll over is different, and used in hash functions among other
things.

Of course, you can use the ROL and ROR instructions in D using inline assembler. But this has got nothing to do with >>> (so I'm changing the thread title). It might be useful to have these functions in std.intrinsic though.

Right.
Jul 27 2004
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Tue, 27 Jul 2004 09:37:56 -0400, Berin Loritsch wrote:

 Arcane Jill wrote:
 
 The docs say:
 "<< is a left shift. >> is a signed right shift. >>> is an unsigned right
 shift."
 

Question: what is the difference between a signed shift and an unsigned shift? I know there is a difference between a Roll-Over and a Shift. A simple shift will set the overflow flag with the bit shoved off the end and simply fill in zeros in the empty space. For example: 00001111 >> 1 == 00000111 A roll over will operate the same way the shift does, except it uses the value of the overflow flag to fill in the empty space. This results in what appears to be a roll over: 00001111 >>> 1 == 10000111 These are two separate operations, with very different results. This is why Java really has the >> and >>> operators. It has nothing to do with signed and unsigned numbers. It has to do with predictable roll over vs. shift operations. These are bitwise operations and really have nothing to do with sign. Most folks know that the shift function is a Q&D multiply/divide by 2. The roll over is different, and used in hash functions among other things.

I thought the difference was that in unsigned-shift-left, all bits were shifted but in signed-shift-left, all *except* the left-most bit were shifted. 10000011 >> 10000001 10000011 >>> 01000001 The net result is the signed shift keeps the sign of the operand and an unsigned shift will always result in a positive value. -- Derek Melbourne, Australia 28/Jul/04 9:58:36 AM
Jul 27 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <ce6qk5$2ohe$1 digitaldaemon.com>, Derek Parnell says...
I thought the difference was that in unsigned-shift-left, all bits were
shifted but in signed-shift-left, all *except* the left-most bit were
shifted.

   10000011  >>  10000001
   10000011  >>> 01000001

The net result is the signed shift keeps the sign of the operand and an
unsigned shift will always result in a positive value.

In fact, it goes like this: # 10000010 >> 1 = 11000001 (if the LHS is signed) # 10000010 >> 1 = 01000001 (if the LHS is unsigned) # 10000010 >>> 1 = 01000001 (regardless of the sign of the LHS) It's actually a documentation error, the claim that >> is a "signed" shift right. In fact, it appears to be the same as C's >> (which is good). Arcane Jill
Jul 28 2004
parent Derek Parnell <derek psych.ward> writes:
On Wed, 28 Jul 2004 07:24:25 +0000 (UTC), Arcane Jill wrote:

 In article <ce6qk5$2ohe$1 digitaldaemon.com>, Derek Parnell says...
I thought the difference was that in unsigned-shift-left, all bits were
shifted but in signed-shift-left, all *except* the left-most bit were
shifted.

   10000011  >>  10000001
   10000011  >>> 01000001

The net result is the signed shift keeps the sign of the operand and an
unsigned shift will always result in a positive value.

In fact, it goes like this: # 10000010 >> 1 = 11000001 (if the LHS is signed) # 10000010 >> 1 = 01000001 (if the LHS is unsigned) # 10000010 >>> 1 = 01000001 (regardless of the sign of the LHS) It's actually a documentation error, the claim that >> is a "signed" shift right. In fact, it appears to be the same as C's >> (which is good).

Oh, okay. But I don't think I'd be wanting to bit shifts on 'signed' expressions anyway. -- Derek Melbourne, Australia 28/Jul/04 5:31:53 PM
Jul 28 2004
prev sibling next sibling parent Jan-Eric Duden <jeduden whisset.com> writes:
Arcane Jill wrote:
 The docs say:
 "<< is a left shift. >> is a signed right shift. >>> is an unsigned right
 shift."
 
 Now, here's the thing:
 
 We don't have separate operators for signed multiply and unsigned multiply. Why
 not? Because one operator does both jobs, based on the type of its arguments.
 
 We don't have separate operators for signed divide and unsigned divide. Why
not?
 Because one operator does both jobs, based on the type of its arguments.
 
 Same goes for %.
 
 And yet, we DO have separater operators for signed right shift and unsigned
 right shift. C doesn't. C++ doesn't. But D does.
 
 ?
 
 And, if I have understood the documentation correctly, these operators the
 actual sign of the arguments (which means that D's (uint >> uint) will behave
 differently from C).
 
 I believe that Java has both >> and >>> - but with good reason. Java has no
 unsigned integers, and so you need a separate operator (>>>) to do unsigned
 shift right. This logic does not apply to D.
 
 Is there a point to all this? Or is it just a case of "Oh yeah, that. I was
 going to fix that years ago but there always seemed be more important things to
 do"?
 
 Arcane Jill (confused)
 
 
 

In Java >>> operator makes sense, since Java has only signed types, but you are right: The >>> operator doesn't make much sense in D.
Jul 27 2004
prev sibling parent reply Kazuhiro Inaba <Kazuhiro_member pathlink.com> writes:
In article <ce5jsr$260p$1 digitaldaemon.com>, Arcane Jill says...
Is there a point to all this?

http://www.digitalmars.com/d/ctod.html#ushr ? -- Kaz.
Jul 27 2004
parent Arcane Jill <Arcane_member pathlink.com> writes:
In article <ce5ubo$2bhe$1 digitaldaemon.com>, Kazuhiro Inaba says...
In article <ce5jsr$260p$1 digitaldaemon.com>, Arcane Jill says...
Is there a point to all this?

http://www.digitalmars.com/d/ctod.html#ushr ? -- Kaz.

Aha - I missed that. Thanks for pointing that out. It does make perfect sense now. Well, I suppose the point is that the docs say: "<< is a left shift. >> is a signed right shift. >>> is an unsigned right shift." Which means that the docs are wrong, and this is in fact a documentation error. So the phrase ">> is a signed right shift" should read ">> is a right shift, which is signed if the left hand argument is signed, or unsigned if the left hand argument is unsigned". Jill
Jul 27 2004