IGNORED

# Signed division by powers of 2 in IntyBASIC

## Recommended Posts

Is there a way to make IntyBASIC perform signed-division by powers of 2?

Even for signed 16-bit variables, the generated assembly code uses "logical shift" instead of "arithmetic shift" operations, which do not propagate the sign.

-dZ.

##### Share on other sites

no, the manual is clear about it

##### Share on other sites

8 minutes ago, artrag said:

no, the manual is clear about it

Thanks, I must have missed that.  I think this is clearly a flaw.

Other then busting out an ASM directive, is there a way to coerce the compiler into issuing a SAR instruction, perhaps with some convoluted IntyBASIC construct?

dZ.

##### Share on other sites

Oh, darn!  I just realized that I encountered this problem two years ago when I started my project, and I had solved it.  I had completely forgotten it.

Here's a handy macro.  Not optimal, but what can you do.

```'' ======================================================================== ''
''  SignedPow2Division(val, div)                                                ''
''      Divides a signed number by a power of two, retaining its sign.      ''
''                                                                          ''
''      Arguments:                                                          ''
''          val:        The value to divide.                                ''
''          div:        The divisor.  Must be a power of two constant.      ''
''                                                                          ''
''      Output:                                                             ''
''          The signed value "val" divided by power of two "div".           ''
'' ======================================================================== ''
DEF FN SignedPow2Division(val, div) = (((((val) / (div)) Xor (\$8000 / (div))) - (\$8000 / (div))) AND \$FFFF)```

If anybody has be better way, let me know.

-dZ.

##### Share on other sites

And to give credit where it's due:  I got that solution from an example provided by @intvnut.  The "accel" program in the "contrib" folder of the IntyBASIC distribution did that trick to retain the sign when dividing by 4, and I just generalized it into a macro for any power of 2.

-dZ.

##### Share on other sites

• 4 weeks later...
On 4/1/2023 at 3:01 PM, artrag said:

no, the manual is clear about it

On 4/1/2023 at 3:12 PM, DZ-Jay said:

I think this is clearly a flaw.

It's documented, so it's a feature.

WJI

• 1
• 1
##### Share on other sites

On 4/2/2023 at 4:23 AM, DZ-Jay said:

Other then busting out an ASM directive, is there a way to coerce the compiler into issuing a SAR instruction, perhaps with some convoluted IntyBASIC construct?  ... Oh, darn!  I just realized that I encountered this problem two years ago when I started my project, and I had solved it.  I had completely forgotten it.

Here's a handy macro.  Not optimal, but what can you do.

```'' ======================================================================== ''
''  SignedPow2Division(val, div)                                                ''
''      Divides a signed number by a power of two, retaining its sign.      ''
''                                                                          ''
''      Arguments:                                                          ''
''          val:        The value to divide.                                ''
''          div:        The divisor.  Must be a power of two constant.      ''
''                                                                          ''
''      Output:                                                             ''
''          The signed value "val" divided by power of two "div".           ''
'' ======================================================================== ''
DEF FN SignedPow2Division(val, div) = (((((val) / (div)) Xor (\$8000 / (div))) - (\$8000 / (div))) AND \$FFFF)```

If anybody has be better way, let me know.

Cute. The XOR clears the residual sign bit, the subtraction sets the propagated sign bits and that final AND \$FFFF tells you who's paying attention.

Although THREE general-purpose software divides (two of which are the same!) is a steep price to pay for an operation that could be easily done with a few native shifts, if your function is fast enough to work for you it's fast enough. You should probably let less experienced readers know that they can improve performance somewhat by sacrificing the elegance of the function for a subroutine that cuts the number of those divides. As to ASM directives: that's what they're for and it's no shame to use them, especially when using a primitive compiler. K&R would agree.

WJI

##### Share on other sites

1 hour ago, Walter Ives said:

Cute. The XOR clears the residual sign bit, the subtraction sets the propagated sign bits and that final AND \$FFFF tells you who's paying attention.

Although THREE general-purpose software divides (two of which are the same!) is a steep price to pay for an operation that could be easily done with a few native shifts, if your function is fast enough to work for you it's fast enough. You should probably let less experienced readers know that they can improve performance somewhat by sacrificing the elegance of the function for a subroutine that cuts the number of those divides. As to ASM directives: that's what they're for and it's no shame to use them, especially when using a primitive compiler. K&R would agree.

WJI

As primarily an assembly language programmer, I feel no shame in using assembly code.  My concern here is in building tutorials for new IntyBASIC programmers, some of which may want to make games for the IntyBASIC competition which forbids non BASIC code.

But for anybody paying attention, the down-and-dirty solution would be to shift arithmetically right, once per power of two.  Each SAR (Shift Arithmetically Right) instruction takes a secondary argument directing either one or two shifts, so you will need to use more than one for more than one power of 2.

Here is an example of dividing 8-bit variable "MyVar" by 4:

```ASM  MVI var_MYVAR, R0  ; Get the value
ASM  SAR R0, 2          ; Divide by 4 (2^2)
ASM  MVO R0, var_MYVAR  ; Store the result```

dZ.

## 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.