Jump to content



0

Reversing the sign of a signed-integer whose sign is unknown


22 replies to this topic

#1 vdub_bobby OFFLINE  

vdub_bobby

    Quadrunner

  • 5,831 posts
  • Boom bam.
  • Location:Seattle, WA

Posted Fri Feb 4, 2005 2:24 PM

Is there a real slick way to get the absolute value of a signed 8-bit number, whose sign is unknown?

I came up with this:
	lda NumberSignUnknown

	bpl NumberPositive

	lda #0

	sec

	sbc NumberSignUnknown

	bvc NumberPositive

;--if overflow set, then we ended up with +128 (i.e., -128)

	sec

	sbc #1	;make that +127

NumberPositive

;--now A holds abs(NumberSignUnknown)
(This code does a little extra also, it returns abs(-128) as 127.)

The application, in my case, is this:
I have two sprites, each with a velocity represented by a pair of signed integers: VX1, VX2, VY1, VY2. Positive velocity is up/right, Negative velocity is down/left.
So, when they bump, I need these two numbers:
X Velocity magnitude: abs(VX1) / 2 + abs(VX2) / 2
Y Velocity magnitude: abs(VY1) / 2 + abs(VY2) / 2

Anybody know any slick ways to do this?

#2 kenfused OFFLINE  

kenfused

    Stargunner

  • 1,192 posts
  • Location:Columbus, Ohio

Posted Fri Feb 4, 2005 2:59 PM

IIRC, you can get the negative of a two's complement number can by flipping all the bits and adding 1


  lda NumberSignUnknown

  bpl NumberPositive

  eor #255

  clc

  adc #1

NumberPositive:



#3 kenfused OFFLINE  

kenfused

    Stargunner

  • 1,192 posts
  • Location:Columbus, Ohio

Posted Fri Feb 4, 2005 3:02 PM

With this one though abs(-128) will return -128 though

#4 vdub_bobby OFFLINE  

vdub_bobby

    Quadrunner

  • 5,831 posts
  • Boom bam.
  • Location:Seattle, WA

Posted Fri Feb 4, 2005 3:45 PM

kenfused said:

With this one though abs(-128) will return -128 though

Thanks for the reminder! I had completely forgotten how you flip the sign of a two's complement number.

So, my new routine (returning abs(-128)=127) would be:
  lda NumberSignUnknown

  bpl NumberPositive

  eor #255

  clc

  adc #1

  bpl NumberPositive

  sec

  sbc #1

NumberPositive
My old routine was 14 bytes long; this one is....also 14 bytes long. :(

Any ideas?

#5 Tom OFFLINE  

Tom

    Moonsweeper

  • 449 posts
  • Location:Switzerland

Posted Fri Feb 4, 2005 3:55 PM

can't you replace


sec

sbc #1


with


lda #127


?

#6 vdub_bobby OFFLINE  

vdub_bobby

    Quadrunner

  • 5,831 posts
  • Boom bam.
  • Location:Seattle, WA

Posted Fri Feb 4, 2005 3:58 PM

Tom said:

can't you replace


sec

sbc #1


with


lda #127


?
Yes - and thanks for pointing out my stupidity :) Sometimes the most obvious things...

#7 Thomas Jentzsch OFFLINE  

Thomas Jentzsch

    Thrust, Jammed, SWOOPS!

  • 16,745 posts
  • Always left from right here!
  • Location:Düsseldorf, Germany

Posted Fri Feb 4, 2005 4:18 PM

vdub_bobby said:

So, my new routine (returning abs(-128)=127) would be:
  lda NumberSignUnknown

  bpl NumberPositive

  eor #255

  clc

  adc #1

  bpl NumberPositive

  sec

  sbc #1

NumberPositive
Nope, the last three instructions are superfluous.
  lda NumberSignUnknown

  bpl NumberPositive

  eor #255

  clc

  adc #1

NumberPositive
or
  lda NumberSignUnknown

  bpl NumberPositive

  sec

  sbc #1

  eor #255

NumberPositive
So, if you know the state of the carry flag, you can save one more byte. :)

#8 Thomas Jentzsch OFFLINE  

Thomas Jentzsch

    Thrust, Jammed, SWOOPS!

  • 16,745 posts
  • Always left from right here!
  • Location:Düsseldorf, Germany

Posted Fri Feb 4, 2005 4:27 PM

Oops, I should have read your question completely before answering.

Ok next try:
  lda NumberSignUnknown 

  bpl NumberPositive 

  sec

  sbc #1

  bpl NumberPositive; a = 127

  eor #255 

NumberPositive:
That's better! :)

#9 vdub_bobby OFFLINE  

vdub_bobby

    Quadrunner

  • 5,831 posts
  • Boom bam.
  • Location:Seattle, WA

Posted Fri Feb 4, 2005 4:28 PM

Thomas Jentzsch said:

Nope, the last three instructions are superfluous.
??
If I start with -128, flip all the bits and add one then I will get +128. Which is -128. Right?

Quote

  lda NumberSignUnknown

  bpl NumberPositive

  eor #255

  clc

  adc #1

NumberPositive
or
  lda NumberSignUnknown

  bpl NumberPositive

  sec

  sbc #1

  eor #255

NumberPositive
So, if you know the state of the carry flag, you can save one more byte. :)
Unfortunately, I don't know the state of the carry. :(

#10 vdub_bobby OFFLINE  

vdub_bobby

    Quadrunner

  • 5,831 posts
  • Boom bam.
  • Location:Seattle, WA

Posted Fri Feb 4, 2005 4:29 PM

Thomas Jentzsch said:

Oops, I should have read your question completely before answering.

Ok next try:
  lda NumberSignUnknown 

  bpl NumberPositive 

  sec

  sbc #1

  bpl NumberPositive; a = 127

  eor #255 

NumberPositive:
That's better! :)
Heh, thanks! Anybody beat 11 bytes? :)

#11 Thomas Jentzsch OFFLINE  

Thomas Jentzsch

    Thrust, Jammed, SWOOPS!

  • 16,745 posts
  • Always left from right here!
  • Location:Düsseldorf, Germany

Posted Fri Feb 4, 2005 4:43 PM

How about that one?
  lda NumberSignUnknown 

  bpl NumberPositive 

  asl

  sbc #2

  ror

  eor #255 

NumberPositive:
Don't ask! :D

#12 vdub_bobby OFFLINE  

vdub_bobby

    Quadrunner

  • 5,831 posts
  • Boom bam.
  • Location:Seattle, WA

Posted Fri Feb 4, 2005 5:00 PM

Thomas Jentzsch said:

How about that one?
  lda NumberSignUnknown 

  bpl NumberPositive 

  asl

  sbc #2

  ror

  eor #255 

NumberPositive:
Don't ask! :D
Holy smokes! I'm impressed...

I ran that through on paper and it didn't work - if I started with 1, it returned -128 - but then I realized that it did work for negative numbers, and that positive numbers wouldn't be manipulated at all.

Just crazy enough to work!

At this point, I don't care if somebody can beat 10 bytes, that routine is too incomprehensible; I HAVE to use it :)

#13 Kr0tki ONLINE  

Kr0tki

    Dragonstomper

  • 725 posts
  • Location:Warszawa, Poland

Posted Tue Feb 8, 2005 8:40 AM

Did you check that code for -128? It still returns -128 for that number... which makes the routine rather interesting way of wasting cycles ;)

I'm wondering if it wouldn't be easier to just assure that the velocity never exceeds 127?

#14 Thomas Jentzsch OFFLINE  

Thomas Jentzsch

    Thrust, Jammed, SWOOPS!

  • 16,745 posts
  • Always left from right here!
  • Location:Düsseldorf, Germany

Posted Tue Feb 8, 2005 10:59 AM

Kr0tki said:

Did you check that code for -128? It still returns -128 for that number... which makes the routine rather interesting way of wasting cycles ;)
I really should stop coding weird stuff at night. :roll:

#15 Thomas Jentzsch OFFLINE  

Thomas Jentzsch

    Thrust, Jammed, SWOOPS!

  • 16,745 posts
  • Always left from right here!
  • Location:Düsseldorf, Germany

Posted Tue Feb 8, 2005 11:08 AM

Next try:
  lda NumberSignUnknown 

  bpl NumberPositive 

  cmp #$81

  eor #$FF 

  adc #$00

NumberPositive:
Still 10 bytes, and now it works (does it?).

#16 vdub_bobby OFFLINE  

vdub_bobby

    Quadrunner

  • 5,831 posts
  • Boom bam.
  • Location:Seattle, WA

Posted Tue Feb 8, 2005 12:58 PM

Kr0tki said:

Did you check that code for -128? It still returns -128 for that number... which makes the routine rather interesting way of wasting cycles ;)

I'm wondering if it wouldn't be easier to just assure that the velocity never exceeds 127?
Yeah, I did check it...:) Guess not well enough.

#17 Robert M OFFLINE  

Robert M

    Stargunner

  • 1,481 posts
  • Rootbeer!
  • Location:Western NY state

Posted Tue Feb 8, 2005 1:11 PM

Its not clear to me why you are concerned that -128 -> $80 transforms into 128 -> $80. The fact is that 128 and -128 are representes by the same combination of bits. The meaning of those bits 128 or -128 is completely up to you as the programmer. Since you want all negative values to be made positive, isn't it correct then for -128 to become 128?

Regards,

#18 vdub_bobby OFFLINE  

vdub_bobby

    Quadrunner

  • 5,831 posts
  • Boom bam.
  • Location:Seattle, WA

Posted Tue Feb 8, 2005 1:47 PM

Robert M said:

Its not clear to me why you are concerned that -128 -> $80 transforms into 128 -> $80.   The fact is that 128 and -128 are representes by the same combination of bits.   The meaning of those bits 128 or -128 is completely up to you as the programmer.    Since you want all negative values to be made positive, isn't it correct then for -128 to become 128?

Regards,
Well, it is because I am using signed integers to represent velocity, so if I just left it as +128 to do my calculations, at some point I would have to transform that to +127 before I use it as velocity, or the velocity would be in the wrong direction.

Here's what I am doing:

Two sprites bump into each other, each with an X and Y velocity (signed integers): call them VX1, VY1, VX2, VY2

I want to take half the magnitude of the X velocities: VXsum = abs(VX1) / 2 + abs(VX2) / 2
and then, for the sprite who is leftmost, give him negative VXsum and give the other sprite positive VXsum.
Then I do something similar for the Y velocities.

So...if VX1 = -128 and VX2 = -128 (both sprites going full speed to the left, and suffering a glancing collision), then what I want VXsum to be is 127 - the largest positive signed integer. If my abs() function returns abs(-128)=127, then I'm fine. If it returns +128, then I get: $40 + $40 = $80 = -128
So if I then applied that velocity willy-nilly, then my two sprites would end up with velocity in the wrong direction! So I would need to check when I sum the velocities to see if the addition overflowed and, if so, reset to the maximum positive velocity. Which I could do, but it just seemed cleaner to turn -128 into 127 at the beginning which eliminates that problem completely!

But if there is a better way, I'm willing to be persuaded :)

#19 vdub_bobby OFFLINE  

vdub_bobby

    Quadrunner

  • 5,831 posts
  • Boom bam.
  • Location:Seattle, WA

Posted Tue Feb 8, 2005 1:53 PM

vdub_bobby said:

So if I then applied that velocity willy-nilly, then my two sprites would end up with velocity in the wrong direction!  So I would need to check when I sum the velocities to see if the addition overflowed and, if so, reset to the maximum positive velocity.  Which I could do, but it just seemed cleaner to turn -128 into 127 at the beginning which eliminates that problem completely!
Now that I think about it...it probably would be easier, and more efficient, to just add these statements immediately after the addition of the half-velocities:
	bvc NoOverflow

	lda #$7F

NoOverflow
Unless Thomas can come up with an abs() routine that is less than 4 bytes :D

Thanks, Robert, for making me use my brain ;)

#20 Thomas Jentzsch OFFLINE  

Thomas Jentzsch

    Thrust, Jammed, SWOOPS!

  • 16,745 posts
  • Always left from right here!
  • Location:Düsseldorf, Germany

Posted Tue Feb 8, 2005 1:54 PM

vdub_bobby said:

I want to take half the magnitude of the X velocities: VXsum = abs(VX1) / 2 + abs(VX2) / 2  
and then, for the sprite who is leftmost, give him negative VXsum and give the other sprite positive VXsum.
Hm, I don't think that will work. You need the sign for your calculation.

E.g. when sprite 1 goes into the same direction as sprite 2, just a bit faster. When they collide, by using your formular, one of them would suddenly reverse direction.

#21 vdub_bobby OFFLINE  

vdub_bobby

    Quadrunner

  • 5,831 posts
  • Boom bam.
  • Location:Seattle, WA

Posted Tue Feb 8, 2005 2:00 PM

Thomas Jentzsch said:

vdub_bobby said:

I want to take half the magnitude of the X velocities: VXsum = abs(VX1) / 2 + abs(VX2) / 2  
and then, for the sprite who is leftmost, give him negative VXsum and give the other sprite positive VXsum.
Hm, I don't think that will work. You need the sign for your calculation.

E.g. when sprite 1 goes into the same direction as sprite 2, just a bit faster. When they collide, by using your formular, one of them would suddenly reverse direction.
I think it works alright :)

But don't take my word for it! You can see it in action in my fishies game in the two-player mode: when the players are the same size, and they collide, they bounce off each other.

The routine isn't real accurate, from a Newtonian physics point of view, but I think it looks ok.

#22 vdub_bobby OFFLINE  

vdub_bobby

    Quadrunner

  • 5,831 posts
  • Boom bam.
  • Location:Seattle, WA

Posted Tue Feb 8, 2005 2:02 PM

vdub_bobby said:

The routine isn't real accurate, from a Newtonian physics point of view, but I think it looks ok.
On the other hand...if you know some super-slick, super-efficient vector addition routine, it would be cool to use that instead of the hack I'm currently using.

#23 batari OFFLINE  

batari

    )66]U('=I;B$*

  • 6,237 posts
  • begin 644 contest

Posted Sat May 28, 2005 1:33 AM

EDIT:

I replied to this thread but it turned out my reply contained incorrect info... Sorry for the distraction...

Edited by batari, Sat May 28, 2005 3:19 AM.





0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users