Jump to content
IGNORED

Signed division by powers of 2 in IntyBASIC


DZ-Jay

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.

 

 

Link to comment
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.

Link to comment
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.

  • Like 1
Link to comment
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.

Link to comment
Share on other sites

  • 4 weeks later...
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

  • Like 1
Link to comment
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.

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...