IGNORED

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

## Recommended Posts

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?

##### Share on other sites

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

NumberPositive:

```

##### Share on other sites

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

##### Share on other sites

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

bpl NumberPositive

sec

sbc #1

NumberPositive```

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

Any ideas?

##### Share on other sites

can't you replace

```
sec

sbc #1

```

with

```
lda #127

```

?

##### Share on other sites

can't you replace

```
sec

sbc #1

```

with

```
lda #127

```

?

Yes - and thanks for pointing out my stupidity Sometimes the most obvious things...
##### Share on other sites

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

bpl NumberPositive

eor #255

clc

bpl NumberPositive

sec

sbc #1

NumberPositive```

Nope, the last three instructions are superfluous.

```  lda NumberSignUnknown

bpl NumberPositive

eor #255

clc

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.

##### Share on other sites

Ok next try:

```  lda NumberSignUnknown

bpl NumberPositive

sec

sbc #1

bpl NumberPositive; a = 127

eor #255

NumberPositive:```

That's better!

##### Share on other sites

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?

```  lda NumberSignUnknown

bpl NumberPositive

eor #255

clc

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.
##### Share on other sites

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?
##### Share on other sites

```  lda NumberSignUnknown

bpl NumberPositive

asl

sbc #2

ror

eor #255

NumberPositive:```

##### Share on other sites

```  lda NumberSignUnknown

bpl NumberPositive

asl

sbc #2

ror

eor #255

NumberPositive:```

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

##### Share on other sites

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?

##### Share on other sites

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.

##### Share on other sites

Next try:

```  lda NumberSignUnknown

bpl NumberPositive

cmp #\$81

eor #\$FF

NumberPositive:```

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

##### Share on other sites

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.
##### Share on other sites

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,

##### Share on other sites

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

##### Share on other sites

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

Thanks, Robert, for making me use my brain

##### Share on other sites

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.

##### Share on other sites

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.

##### Share on other sites

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.

##### Share on other sites

• 3 months later...

EDIT:

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

Edited by batari

## Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.