LDIV/LMOD
=========
DIV is an operator which performs an integer divide:
PRINT 5 DIV 2 prints 2
PRINT -5 DIV 2 prints -3
MOD is an operator which gives the modulus, or remainder of the division
above:
PRINT 5 MOD 2 prints 1
PRINT -5 MOD 2 prints 1
DIV and MOD on QDOS and Minerva can only work with word, ie 16 bit, integers.
Both the Q-Liberator and Turbo compilers are limited in the same way. SMSQ/E
can handle 32 bit integers, but this does not pass through to the compilers,
which use their own internal routines.
The functions LDIV and LMOD work with 32 bit integers accross all platforms,
whether compiled or not. However, where the two arguments have opposite signs
they produce slightly different results to those above. This is not an error,
merely a different viewpoint.
The "flooring" i.e. rounding down approach, as above, is (according to Tobias
Fröschle) normally chosen to make sure that
x = a *(x DIV a) + x MOD a
stays valid for negative numbers. That would not necessarily be the case if
rounding towards 0.
Here is a sample of the difference in output between the two approaches. Being
number-theoretically naive, the method Ive chosen feels more "natural" to me,
not least because these are the results I would expect to get if I worked
out the division by hand:
100 CLS
110 DivMod 5, 2
120 DivMod -5, 2
130 DivMod -5, -2
140 DivMod 5, -2
150 :
160 DEFine PROCedure DivMod(a, b)
170 PRINT P$(a)! ' DIV'! P$(b)! '='! P$(a DIV b); ', ';
180 PRINT P$(a)! ' MOD'! P$(b)! '='! P$(a MOD b)
190 PRINT P$(a)! 'LDIV'! P$(b)! '='! P$(LDIV(a, b)); ', ';
200 PRINT P$(a)! 'LMOD'! P$(b)! '='! P$(LMOD(a, b))
210 PRINT
220 END DEFine
230 :
240 DEFine FuNction P$(n)
250 RETurn FILL$(" ", 3 - LEN(n)) & n
260 END DEFine P$
prints:
5 DIV 2 = 2, 5 MOD 2 = 1
5 LDIV 2 = 2, 5 LMOD 2 = 1
-5 DIV 2 = -3, -5 MOD 2 = 1
-5 LDIV 2 = -2, -5 LMOD 2 = -1
-5 DIV -2 = 2, -5 MOD -2 = -1
-5 LDIV -2 = 2, -5 LMOD -2 = -1
5 DIV -2 = -3, 5 MOD -2 = -1
5 LDIV -2 = -2, 5 LMOD -2 = 1
My LDIV/LMOD works by removing the sign(s), then doing the division (based on
an "algorithm" from my grandfather's old mechanical calculator!) and then adds
back the sign(s) afterwards. More details may be found in the assembler
source files.
Source code
-----------
The code here is normally part of a larger toolkit, but has been cobbled
together so it compiles as a stand-alone keyword. It is prepared for
QUANTA's QMAC assembler and linker, and the commercial QMake make program,
available from Jochen Merz Software (see below). Minor modifications may be
required to assemble it under other flavours. When unzipping, it creates a
(sub)directory called ldv_ and a number of subdirectories under that. This
is more for my convenience than yours! To assemble it yourself, the
simplest is to unzip it to ram1_
To maintain some kind of order and sanity, it has become traditional to
keep SMSQ/E-style key files under the DEV device, specifically dev8_. DEV
is a pseudo- or virtual-device and can point to any real device. DEV is
native under SMSQ/E but can be found as an add-on extension for other
systems. The key files in question are part of the SMSQ/E sources
distribution, available for download from the Official SMSQ/E site.
Program Status
--------------
You are free to use this software for your own non-commercial purposes and
to distribute it freely, provided you acknowledge it provenance.
No guarantees! Use at own risk!
Happy coding!
pjw, January 9th 2017
Links
-----
See the Contacts page
Conditions of use and DISCLAIMER as per Knoware.no
QL Software
