Shop OBEX P1 Docs P2 Docs Learn Events
Why is there no Shift Arithmetic Left — Parallax Forums

Why is there no Shift Arithmetic Left

Bobb FwedBobb Fwed Posts: 1,119
edited 2013-05-06 16:08 in Propeller 1
I am converting a 32 signed value to a 24-bit signed value and back again. But I need to use shift arithmetic left to complete the conversion, but it doesn't exist.

Why not?

(am I missing something obvious, like it won't work?)

Comments

  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2013-05-06 14:59
    I understand that just using the 24-bits I need works, but what if I wanted to do an arithmetic shift left, and wanted the values to shift off the register (like a normal shift), while still maintaining the current sign/high bit?
  • SRLMSRLM Posts: 5,045
    edited 2013-05-06 15:14
    I imagine a shift arithmetic left filling the low order bits with whatever bit 0 is. IE,

    0b101011101 <<~ 5 == 10101110111111

    Is that what you had it mind? It sounds instead like you meant

    0b101011101 <<~ 3 == 111101000

    (ie, the high bit remains the same regardless of the left arithmetic shift amount).

    If you have a 24 bit number, the upper 8 bits are all the "sign bit" (in 2's complement). But, you don't really want to think of having a "sign" bit, since the number as a whole represents a negative or positive number. It's simply a convenience that the upper bit denotes negative or positive.

    Could you post what you are trying to do?
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2013-05-06 15:45
    SRLM wrote: »
    Is that what you had it mind? It sounds instead like you meant

    0b101011101 <<~ 3 == 111101000

    (ie, the high bit remains the same regardless of the left arithmetic shift amount).

    If you have a 24 bit number, the upper 8 bits are all the "sign bit" (in 2's complement). But, you don't really want to think of having a "sign" bit, since the number as a whole represents a negative or positive number. It's simply a convenience that the upper bit denotes negative or positive.

    Could you post what you are trying to do?
    I would imagine it working like the standard shift, and just shifting in zeros.
    Like I said, I understand if I just use the 24 bits I'm fine, if my value is always less than 23-bits + sign.

    It works fine until the value is greater than 23-bits. I want to maintain the sign above all else. So if the method is supplied a 30-bit value, and I just take the 24-bits, but new sign bit is unknown. To maintain the sign (but not he value), I have to store bit 31, then set that to bit 23. Which is what I was hoping a shift arithmetic left/shift right combo would do.

    I can't post exactly what I am doing, but it breaks down to this (not optimized or complete):
    PUB get (value)
      'value <~= 8 '' doesn't work
      'value >>= 8
      value &= $FFFFFF ' so I do this instead -- to force just the lower 24-bits
    
      RETURN encode(value)
    
    PUB put (encoded) : value
      value := decode(encoded)
    
      value <<= 8 ' shift to place sign bit
      value ~>= 8 ' shift arithmetic to get value
    
  • Mike GreenMike Green Posts: 23,101
    edited 2013-05-06 16:04
    In arithmetic units with only a single bit shift, there's never an arithmetic shift left because that's always done by adding a number to itself which is equivalent to multiplying by two. In the case of a barrel shifter, like that in the Propeller, you still don't find an arithmetic shift left because, for valid values, an arithmetic shift left is equivalent to a logical shift left. If the sign changes, you've generated an overflow which isn't valid.

    In your case, you should be able to use a logical shift left followed by an arithmetic shift right to change from a signed 24-bit value to a signed 32-bit value and an and with $FFFFFF to change from a signed 32-bit value to a signed 24-bit value. Your values can only range from -2^23 to +2^23-1 though. Anything else is invalid and is considered to result in an overflow. It's essentially what you seem to be doing already.
  • Bobb FwedBobb Fwed Posts: 1,119
    edited 2013-05-06 16:05
    I figured as much.
    Thanks for the replies.

    I'll make things work.
  • lonesocklonesock Posts: 917
    edited 2013-05-06 16:08
    Maybe this as a workaround?

    m2 := ((m1 << 8) - constant( |<8 - 1 ) * (m1 < 0)) -> 8

    untested

    Jonathan
Sign In or Register to comment.