Shop OBEX P1 Docs P2 Docs Learn Events
Bit twiddling in spin — Parallax Forums

Bit twiddling in spin

mhm21mhm21 Posts: 14
edited 2013-05-08 08:00 in Propeller 1
I would like to pare down the following if-else statement for rounding using some clever logical operations. I realize that shifting would solve a large portion of this problem, but my time step is fixed at "10". I feel comfortable doing this in assembly with flags and such, but this application requires spin...
if A < 0
    B += (A - 5)/10
  else
    B += (A + 5)/10

I feel stupid for asking this, but I'm lost!

Comments

  • mhm21mhm21 Posts: 14
    edited 2013-05-02 23:10
    Perhaps I should elaborate a little bit. Is there a clever way of extracting the sign of "A" and applying it to the 5. I suppose I am looking for a bitwise method for casting the MSB in "A" to a boolean type 1,-1 value to change the sign of the 5.
  • lonesocklonesock Posts: 917
    edited 2013-05-02 23:43
    this seems even more awkward (and is untested):

    B += (A + 5 + 10 * (A ~> 31)) / 10

    EDIT: but, looking at that, the 10 / 10 can be reduced...looks like it might work? (no prop here to test)

    B += (A + 5) / 10 + (A ~> 31)

    Jonathan
  • kuronekokuroneko Posts: 3,623
    edited 2013-05-03 01:11
    lonesock wrote: »
    EDIT: but, looking at that, the 10 / 10 can be reduced...looks like it might work? (no prop here to test)

    B += (A + 5) / 10 + (A ~> 31)
    That doesn't work for A in {-1..-4}. But the first version is OK. So is B += (A + 5 * (1 <# A #> -1)) / 10.
  • mhm21mhm21 Posts: 14
    edited 2013-05-03 08:11
    Genius as usual! Thanks a million! This saved me more repetitious lines of code that I would care to admit.
  • lonesocklonesock Posts: 917
    edited 2013-05-03 11:02
    kuroneko wrote: »
    ...
    So is B += (A + 5 * (1 <# A #> -1)) / 10.
    Great idea! You can then save one byte with:
    B += (A + (5 <# A #> -5)) / 10
    The only cases where the limits are not -5 or 5 are when you wouldn't round up anyway. [8^)

    Jonathan
  • LawsonLawson Posts: 870
    edited 2013-05-03 12:22
    Another way to extract the sign of a value is to take advantage of integer values of boolean logic operation results. TRUE == -1 and FALSE == 0. For example "(A<0)<<1 + 1" will be -1 if "A" is less than zero or 1 if "A" is greater than zero.

    Lawson
  • HydraHackerHydraHacker Posts: 77
    edited 2016-04-29 14:36
    Hi,
    This is my new equation below:

    B+=(A+((A<0)|1*5))/10
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2013-05-06 21:40
    I use the following:

    Y := (X + X // 10) / 10

    in general to round off a number when dividing by factor N:
    Y := (X + X // N) / N

    This works because the // operator in Spin in is symmetric around zero, X//N = -(-X//N), e.g., -14//10 = -4 and 14//10 = 4.

    quick demo attached.
  • lonesocklonesock Posts: 917
    edited 2013-05-07 07:54
    Nice, Tracy!

    This is a great example of a speed / size tradeoff. The // version is 3 bytes smaller and 160 clocks slower than the limit version. If doing this in PASM I would definitely go the limit route, since the // operation is expensive whereas the limit operation is native PASM. If doing this in Spin I would use the // version, especially when 'N' is not a constant.

    Jonathan
    .
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2013-05-08 08:00
    Jonathan, thanks for looking into the speed/size tradeoff. I was wondering about that. I'll add the limit method to the toolkit too, (X+(N/2 <# X #> -N/2))/N, nice.
Sign In or Register to comment.