Standard source definitions of DLSHIFT and DRSHIFT (double number left
shift and right shift), over full shift range, per discussion in prior thread.
Tests needed.
Standard source definitions of DLSHIFT and DRSHIFT (double number left
shift and right shift), over full shift range, per discussion in prior thread.
...
1 64 LSHIFT . \ expected to get zero
1 \ instead, got 1
Then, I looked at the spec. for LSHIFT and, indeed, there is an
ambiguous condition for u >= BITS_PER_CELL .
6.1.1805
LSHIFT “l-shift”
CORE
( x1 u – – x2 )
Perform a logical left shift of u bit-places on x1, giving x2. Put
zeroes into the least significant bits vacated by the shift. An
ambiguous condition exists if u is greater than or equal to the number
of bits in a cell.
Gforth does the same thing
1 64 LSHIFT . 1
1 65 LSHIFT . 2
etc.
We shouldn't have an ambiguous condition here because of some
idiosyncratic behavior of the SHL instruction!
u 64 LSHIFT should be zero on all systems with cell sizes up to 64 bits.
Standard source definitions of DLSHIFT and DRSHIFT (double number left
shift and right shift), over full shift range, per discussion in prior >thread.
Tests needed.
--
Krishna Myneni
=== Start Code ===
1 cells 3 lshift constant BITS_PER_CELL
BITS_PER_CELL 2* constant BITS_PER_DOUBLE
\ Return the u least significant bits of cell value u1
\ as the most significant bits of u2
: lsbits ( u1 u -- u2 )
BITS_PER_CELL min
BITS_PER_CELL - negate
lshift ;
\ Return the u most significant bits of cell value u1
\ as the least significant bits of u2
: msbits ( u1 u -- u2 )
BITS_PER_CELL min
BITS_PER_CELL - negate
rshift ;
0 value ubits
\ u is the number of bits to shift
: DLSHIFT ( ud u -- ud2 )
dup 0= IF drop EXIT THEN
BITS_PER_DOUBLE min dup to ubits
BITS_PER_CELL > IF
drop \ high double has been left shifted out
ubits BITS_PER_CELL - lshift
0 swap \ new low double
ELSE
ubits lshift swap
dup >r
ubits msbits or
r> ubits lshift
swap
THEN ;
: DRSHIFT ( ud u -- ud2 )
dup 0= IF drop EXIT THEN
BITS_PER_DOUBLE min dup to ubits
BITS_PER_CELL > IF
nip \ low double has been right shifted out
ubits BITS_PER_CELL - rshift
0 \ new high double
ELSE
swap ubits rshift
swap dup >r
ubits lsbits or
r> ubits rshift
THEN ;
=== End Code ===
On 2024-03-27 04:57, Krishna Myneni wrote:
On 3/26/24 17:01, Krishna Myneni wrote:[...]
Standard source definitions of DLSHIFT and DRSHIFT (double number
left shift and right shift), over full shift range, per discussion in
prior thread.
Tests needed.
Just tested DLSHIFT and found weird things going on. Traced the
problem to LSHIFT.
kforth64
1 64 LSHIFT . \ expected to get zero
1 \ instead, got 1
Then, I looked at the spec. for LSHIFT and, indeed, there is an
ambiguous condition for u >= BITS_PER_CELL .
6.1.1805
LSHIFT “l-shift”
CORE
( x1 u – – x2 )
Perform a logical left shift of u bit-places on x1, giving x2. Put
zeroes into the least significant bits vacated by the shift. An
ambiguous condition exists if u is greater than or equal to the number
of bits in a cell.
We shouldn't have an ambiguous condition here because of some
idiosyncratic behavior of the SHL instruction!
u 64 LSHIFT should be zero on all systems with cell sizes up to 64 bits.
Ideally — yes.
My rationale (see [1]) is that for any `x` and `u`, the result of a
single shift of `x` by `u` bits should always be equivalent to `u`
sequential shifts by 1 bit.
In article <utvgki$2ciso$1@dont-email.me>,...
Krishna Myneni <krishna.myneni@ccreweb.org> wrote:
Standard source definitions of DLSHIFT and DRSHIFT (double number left
shift and right shift), over full shift range, per discussion in prior
thread.
Tests needed.
These words should be in assembler anyway.
So a rigorous testset is more valuable than a supposedly
standard implementation.
Krishna Myneni <krishna.myneni@ccreweb.org> writes:...
1 64 LSHIFT . \ expected to get zero
1 \ instead, got 1
Then, I looked at the spec. for LSHIFT and, indeed, there is an
ambiguous condition for u >= BITS_PER_CELL .
6.1.1805
LSHIFT “l-shift”
CORE
( x1 u – – x2 )
Perform a logical left shift of u bit-places on x1, giving x2. Put
zeroes into the least significant bits vacated by the shift. An
ambiguous condition exists if u is greater than or equal to the number
of bits in a cell.
One interesting case is Java, which specifies the language pretty
completely in order to make Java write-once-run-everywhere. Java's
designers chose to go along with the common practice in computer
architecture <https://docs.oracle.com/javase/specs/jls/se21/html/jls-15.html#jls-15.19>:
|If the promoted type of the left-hand operand is int, then only the
|five lowest-order bits of the right-hand operand are used as the shift |distance.
|If the promoted type of the left-hand operand is long, then only the
|six lowest-order bits of the right-hand operand are used as the shift |distance.
On 27/03/2024 10:26 pm, Ruvim wrote:
On 2024-03-27 04:57, Krishna Myneni wrote:
[...]
We shouldn't have an ambiguous condition here because of some idiosyncratic behavior of the SHL instruction!
u 64 LSHIFT should be zero on all systems with cell sizes up to 64 bits.
Ideally — yes.
My rationale (see [1]) is that for any `x` and `u`, the result of a single shift of `x` by `u` bits should always be equivalent to `u` sequential shifts by 1 bit.
But neither the standard nor implementations follow this idea.
The same occurred with 2/ and 2 / . Those who saw Forth as a language wanted consistent results; whereas those who saw Forth as a toolkit said give us what
the hardware provides.
On 2024-03-27 07:14, Krishna Myneni wrote:...
On 3/26/24 17:01, Krishna Myneni wrote:
Standard source definitions of DLSHIFT and DRSHIFT (double number
left shift and right shift), over full shift range, per discussion in
prior thread.
...
I wrote a simpler implementation a long time ago. The file
"double-shift.fth" below is a translation from [2] using different names
for constants.
=== "double-shift.fth"
:NONAME 0 -1 BEGIN DUP WHILE SWAP 1+ SWAP 1 RSHIFT REPEAT DROP ; EXECUTE CONSTANT BITS-PER-CELL
BITS-PER-CELL 1- CONSTANT MAX-FOR-SHIFT1
BITS-PER-CELL 2* 1- CONSTANT MAX-FOR-SHIFT2
: (DLSHIFT) ( xd1 u -- xd2 )
( x.lo x.hi u )
TUCK LSHIFT >R
2DUP NEGATE BITS-PER-CELL + RSHIFT >R
LSHIFT 2R> OR
;
: DLSHIFT ( xd1 u -- xd2 )
DUP 0= IF DROP EXIT THEN
DUP MAX-FOR-SHIFT2 U> IF DROP 2DROP 0. EXIT THEN
DUP MAX-FOR-SHIFT1 U> IF NIP BITS-PER-CELL - LSHIFT 0 SWAP EXIT THEN
(DLSHIFT)
;
: (DRSHIFT) ( xd1 u -- xd2 )
( x.lo x.hi u )
2DUP RSHIFT >R
TUCK NEGATE BITS-PER-CELL + LSHIFT >R
RSHIFT R> OR R>
;
: DRSHIFT ( xd1 u -- xd2 )
DUP 0= IF DROP EXIT THEN
DUP MAX-FOR-SHIFT2 U> IF DROP 2DROP 0. EXIT THEN
DUP MAX-FOR-SHIFT1 U> IF >R NIP R> BITS-PER-CELL - RSHIFT 0 EXIT THEN
(DRSHIFT)
;
=== End of "double-shift.fth"
I really think it is a bad idea to have UB in the spec of LSHIFT and
RSHIFT due to the arbitrariness of low level shift operations at the
hardware level. Here we have a chance to remove that UB and guarantee that
1 BITS_PER_CELL LSHIFT returns zero
and
1 BITS_PER_CELL RSHIFT returns zero
so that the expected result for a shift operation on the cell operand
does not have UB.
Efficiency because of extra instructions needed to implement this
guarantee are not even worth bothering about -- we are not C.
These words should be in assembler anyway.
Krishna Myneni <krishna.myneni@ccreweb.org> writes:
I really think it is a bad idea to have UB in the spec of LSHIFT and
RSHIFT due to the arbitrariness of low level shift operations at the
hardware level. Here we have a chance to remove that UB and guarantee that >>
1 BITS_PER_CELL LSHIFT returns zero
and
1 BITS_PER_CELL RSHIFT returns zero
so that the expected result for a shift operation on the cell operand
does not have UB.
I guess you mean the ambiguous condition in the specification of
LSHIFT and RSHIFT, which is more like implementation-defined behaviour
in some other languages (and the advocates of undefined behaviour make
a lot of wind about the difference between implementation-defined and undefined).
Well, if you want to see this happen, you have to convince some Forth
system implementors, so common practice moves in the direction you
prefer, and once that is done, make a proposal.
You could point out that the extra cost of the check is only incurred
for shifts with non-constant shift amounts, and if you could provide
data on the frequency of constant and non-constant shift amounts, this
might help convince system implementors. Of course, for commercial implementors, you may get the usual answer that their customers have
not complained to them, but if you don't try, you can't win.
Efficiency because of extra instructions needed to implement this
guarantee are not even worth bothering about -- we are not C.
I am sure someone can produce some saying by Chuck Moore that
contradicts this attitude. Sure, Forth is not C, but it's just as performance-conscious.
=== "double-shift.fth"
:NONAME 0 -1 BEGIN DUP WHILE SWAP 1+ SWAP 1 RSHIFT REPEAT DROP ; EXECUTE >>> CONSTANT BITS-PER-CELL
BITS-PER-CELL 1- CONSTANT MAX-FOR-SHIFT1
BITS-PER-CELL 2* 1- CONSTANT MAX-FOR-SHIFT2
: (DLSHIFT) ( xd1 u -- xd2 )
( x.lo x.hi u )
TUCK LSHIFT >R
2DUP NEGATE BITS-PER-CELL + RSHIFT >R
LSHIFT 2R> OR
;
: DLSHIFT ( xd1 u -- xd2 )
DUP 0= IF DROP EXIT THEN
DUP MAX-FOR-SHIFT2 U> IF DROP 2DROP 0. EXIT THEN
DUP MAX-FOR-SHIFT1 U> IF NIP BITS-PER-CELL - LSHIFT 0 SWAP EXIT THEN >>> (DLSHIFT)
;
: (DRSHIFT) ( xd1 u -- xd2 )
( x.lo x.hi u )
2DUP RSHIFT >R
TUCK NEGATE BITS-PER-CELL + LSHIFT >R
RSHIFT R> OR R>
;
: DRSHIFT ( xd1 u -- xd2 )
DUP 0= IF DROP EXIT THEN
DUP MAX-FOR-SHIFT2 U> IF DROP 2DROP 0. EXIT THEN
DUP MAX-FOR-SHIFT1 U> IF >R NIP R> BITS-PER-CELL - RSHIFT 0 EXIT
THEN
(DRSHIFT)
;
=== End of "double-shift.fth"
Does it succeed on all of the tests I gave?
Of course, I checked — it succeed your tests.
On 3/27/24 13:46, Anton Ertl wrote:
You could point out that the extra cost of the check is only incurred
for shifts with non-constant shift amounts, and if you could provide
data on the frequency of constant and non-constant shift amounts, this
might help convince system implementors.
May I ask for what you need these double cell shifts?
I know of some crypto routines, but these require even much wider cell
sizes.
Another example: in my field pseudo random number generators are common technique.
However PRNGs are closely related to prime numbers and they often require rotations of sub-cell chunks (linear feedback shift registers).
On 28/03/2024 2:44 am, Krishna Myneni wrote:instructions.
On 3/27/24 08:57, dxf wrote:
On 27/03/2024 10:26 pm, Ruvim wrote:
On 2024-03-27 04:57, Krishna Myneni wrote:
[...]
We shouldn't have an ambiguous condition here because of some idiosyncratic behavior of the SHL instruction!Ideally — yes.
u 64 LSHIFT should be zero on all systems with cell sizes up to 64 bits. >>>>
My rationale (see [1]) is that for any `x` and `u`, the result of a single shift of `x` by `u` bits should always be equivalent to `u` sequential shifts by 1 bit.
But neither the standard nor implementations follow this idea.
The same occurred with 2/ and 2 / . Those who saw Forth as a language wanted
consistent results; whereas those who saw Forth as a toolkit said give us what
the hardware provides.
If one needs the machine shift instructions, they should be using the Forth assembler to write the word in which it is needed. The language specification has no justification (that I can see) for undefined behavior for the LSHIFT and RSHIFT
Some 40 years ago Intel told their customers there's no justification for shifting
a full cell of bits. ANS told the same thing to forthers.
On 3/28/24 03:06, minforth wrote:
May I ask for what you need these double cell shifts?
I'm interested in writing a portable IEEE 754 quad precision arithmetic library in Forth.
Krishna Myneni <krishna.myneni@ccreweb.org> writes:
On 3/27/24 13:46, Anton Ertl wrote:
You could point out that the extra cost of the check is only incurred
for shifts with non-constant shift amounts, and if you could provide
data on the frequency of constant and non-constant shift amounts, this
might help convince system implementors.
Here's some data about the occurences in the Gforth image:
Non-constant shift amount:
2 lshift
1 rshift
0 arshift
Constant shift amount:
18 lit lshift
41 lit rshift
0 lit arshift
On 27-03-2024 20:49, Krishna Myneni wrote:
On 3/27/24 11:36, Ruvim wrote:
=== "double-shift.fth"
:NONAME 0 -1 BEGIN DUP WHILE SWAP 1+ SWAP 1 RSHIFT REPEAT DROP ;
EXECUTE
CONSTANT BITS-PER-CELL
BITS-PER-CELL 1- CONSTANT MAX-FOR-SHIFT1
BITS-PER-CELL 2* 1- CONSTANT MAX-FOR-SHIFT2
: (DLSHIFT) ( xd1 u -- xd2 )
( x.lo x.hi u )
TUCK LSHIFT >R
2DUP NEGATE BITS-PER-CELL + RSHIFT >R
LSHIFT 2R> OR
;
: DLSHIFT ( xd1 u -- xd2 )
DUP 0= IF DROP EXIT THEN
DUP MAX-FOR-SHIFT2 U> IF DROP 2DROP 0. EXIT THEN
DUP MAX-FOR-SHIFT1 U> IF NIP BITS-PER-CELL - LSHIFT 0 SWAP EXIT >>>>> THEN
(DLSHIFT)
;
: (DRSHIFT) ( xd1 u -- xd2 )
( x.lo x.hi u )
2DUP RSHIFT >R
TUCK NEGATE BITS-PER-CELL + LSHIFT >R
RSHIFT R> OR R>
;
: DRSHIFT ( xd1 u -- xd2 )
DUP 0= IF DROP EXIT THEN
DUP MAX-FOR-SHIFT2 U> IF DROP 2DROP 0. EXIT THEN
DUP MAX-FOR-SHIFT1 U> IF >R NIP R> BITS-PER-CELL - RSHIFT 0
EXIT THEN
(DRSHIFT)
;
=== End of "double-shift.fth"
Can't make it any shorter than this. And no idea what happens with less robust LSHIFT or RSHIFT implementations. CELL-BITS should be most
obvious, : SPIN SWAP ROT ; should fix most porting issues, replace ;THEN
with EXIT THEN. It passes all tests.
: dlshift
dup 0> 0= if drop ;then
>r over 0 invert cell-bits r@ - dup >r lshift and r> rshift swap
r@ lshift or swap r> lshift swap
;
: drshift
dup 0> 0= if drop ;then
>r dup 0 invert cell-bits r@ - dup >r rshift and r> lshift swap
r@ rshift spin r> rshift or swap
;
On 3/26/24 17:01, Krishna Myneni wrote:
Standard source definitions of DLSHIFT and DRSHIFT (double number left
shift and right shift), over full shift range, per discussion in prior
thread.
Tests needed.
Just tested DLSHIFT and found weird things going on. Traced the problem
to LSHIFT.
kforth64
1 64 LSHIFT . \ expected to get zero
1 \ instead, got 1
Then, I looked at the spec. for LSHIFT and, indeed, there is an
ambiguous condition for u >= BITS_PER_CELL .
6.1.1805
LSHIFT “l-shift”
CORE
( x1 u – – x2 )
Perform a logical left shift of u bit-places on x1, giving x2. Put
zeroes into the least significant bits vacated by the shift. An
ambiguous condition exists if u is greater than or equal to the number
of bits in a cell.
Gforth does the same thing
1 64 LSHIFT . 1
1 65 LSHIFT . 2
etc.
We shouldn't have an ambiguous condition here because of some
idiosyncratic behavior of the SHL instruction!
u 64 LSHIFT should be zero on all systems with cell sizes up to 64 bits.
On 3/28/24 03:49, Anton Ertl wrote:
Here's some data about the occurences in the Gforth image:...
Non-constant shift amount:
2 lshift
1 rshift
0 arshift
Constant shift amount:
18 lit lshift
41 lit rshift
0 lit arshift
Checking the Forth code base which I use, I find ~ 100:1 ratio between
uses of constant shift amount to non-constant shifts. The existing
instances of non-constant shifts are comparable to yours: two in number >theory programs e.g., finding an exact fraction for a floating point
number, and one use in the assembler.
I don't know what to conclude from this other than the kind of
application development I have been doing favors one over the other.
Krishna Myneni <krishna.myneni@ccreweb.org> writes:
On 3/28/24 03:49, Anton Ertl wrote:
Here's some data about the occurences in the Gforth image:...
Non-constant shift amount:
2 lshift
1 rshift
0 arshift
Constant shift amount:
18 lit lshift
41 lit rshift
0 lit arshift
Checking the Forth code base which I use, I find ~ 100:1 ratio between
uses of constant shift amount to non-constant shifts. The existing
instances of non-constant shifts are comparable to yours: two in number
theory programs e.g., finding an exact fraction for a floating point
number, and one use in the assembler.
I don't know what to conclude from this other than the kind of
application development I have been doing favors one over the other.
It shows that Forth systems that support special code generation for operations with constants (probably all native-code systems, as well
as Gforth) would be able to generate the same code in the vast
majority of cases even with the change you propose. Only in the few non-constant cases a few extra instructions would be needed.
Ah, so optimizing Forth compilers can do a compile-time check for
literal shifts and not have to insert instructions for compare and
branch
While your double-shift algorithm produces the correct results (not shown here),
the intermediate values presented to each RSHIFT/LSHIFT can be quite out-of-bounds
e.g. a shift of 40 and -20 (actually FFFFFFE0) would concern me. That an 'unambiguous'
RSHIFT/LSHIFT will mask questionable parameters fed to it and return a result of 0,
I for one find problematic. IMO it were better that RSHIFT/LSHIFT should fail than
do this.
On 27.03.2024 13:28, Krishna Myneni wrote:
I really think it is a bad idea to have UB in the spec of LSHIFT and
RSHIFT due to the arbitrariness of low level shift operations at the
hardware level.
It's not UB, it is IB and thus it should be required that an implementer >documents the respective behaviour of their system.
Here we have a chance to remove that UB and guarantee that>
1 BITS_PER_CELL LSHIFT returns zero
and
1 BITS_PER_CELL RSHIFT returns zero
so that the expected result for a shift operation on the cell operand
does not have UB.
Efficiency because of extra instructions needed to implement this
guarantee are not even worth bothering about -- we are not C.
Forth does care about efficiency. Otherwise you could eliminate over the
half of the ambiguous conditions in the Forth standard that only arise
from the fact that hardware platforms differ in their behaviour.
[snip]
For the rare situation that a variable shift count is needed, and is not
per se restricted to 0..ADDRESS-UNIT-BITS - 1, you can always write either
0 MAX S" ADDRESS-UNIT-BITS" 1- MIN LSHIFT ( or RSHIFT)
or
DUP 0< INVERT IF DUP S" ADDRESS-UNIT-BITS" < IF LSHIFT ( or RSHIFT)
ELSE ( whatever to do if shift-amount < 0)
ELSE ( whatever to do if shift-amount >= cell width)
THEN THEN
or simply
DUP 0< ABORT" shift amount less than 0"
DUP S" ADDRESS-UNIT-BITS" 1- > ABORT" shift amount greater/equal cell width) >LSHIFT ( or RSHIFT)
NB: The behaviour of most processors to only regard the 5 or 6 LSBs is
useful for expressions like -1 64 <n> - LSHIFT to produce bit masks,
these can simply be expressed as <n> NEGATE LSHIFT (with an
environmental dependency on processors that behave this way).
----
Bernd Linsel
In article <uu1pmo$305br$1@dont-email.me>,
Bernd Linsel <bl1-thispartdoesnotbelonghere@gmx.com> wrote:
NB: The behaviour of most processors to only regard the 5 or 6 LSBs is >>useful for expressions like -1 64 <n> - LSHIFT to produce bit masks,
these can simply be expressed as <n> NEGATE LSHIFT (with an
environmental dependency on processors that behave this way).
The only viable alternative is:
: DLSHIFT ( xd1 n -- xd2) 0 ?do d2* loop ;
: DRSHIFT ( xd1 n -- xd2) 0 ?do d2/ loop ;
On 1/04/2024 7:03 pm, minforth wrote:
dxf wrote:
While your double-shift algorithm produces the correct results (not shown here),
the intermediate values presented to each RSHIFT/LSHIFT can be quite out-of-bounds
e.g. a shift of 40 and -20 (actually FFFFFFE0) would concern me. That an 'unambiguous'
RSHIFT/LSHIFT will mask questionable parameters fed to it and return a result of 0,
I for one find problematic. IMO it were better that RSHIFT/LSHIFT should fail than
do this.
Doesn't make sense during fp number addition/subtraction.
Example?
On 02-04-2024 02:56, Krishna Myneni wrote:
On 4/1/24 10:18, Hans Bezemer wrote:
...
The only viable alternative is:
: DLSHIFT ( xd1 n -- xd2) 0 ?do d2* loop ;
: DRSHIFT ( xd1 n -- xd2) 0 ?do d2/ loop ;
DRSHIFT cannot be coded with D2/ which is an arithmetic right shift,
i.e. it preserves the sign bit. DRSHIFT has to pad from the left with
zero bits.
True, but if you know my coding style - this is not it. And it is acknowledged as such in the source:
\ DXForth MISC.SCR, Copyright Ed, 2011-03-25
\ Albert van der Horst, Thursday 09 April 2015 19:57:13, c.l.f
So it's not uncommon to define it like this. Apart from that - "D2/" is
not a standardized word - so it can mean anything. Although I do agree
with you that your definition is the most likely one.
Hans Bezemer
That led to this Jan 1992 message:
https://groups.google.com/g/comp.lang.forth/c/DqrKMIiyLWc/m/1XUyYBaHyfYJ
The bidirectional shift operator is probably a result of the parsimony|
of Forth philosophy; why have two operators when one will do.
On 12/04/2024 1:11 am, albert@spenarnc.xs4all.nl wrote:
While others indulge in endless discussions about DRSHIFT
I thought to attempt some literate programming.
It didn't prompt you to test your own implementation?
( D0= D0<> D0< D= D< D- M+ DRSHIFT DLSHIFT DU< ) \ AvdH B6Mar22
: DLSHIFT >R SWAP DUP R@ LSHIFT SWAP 8 CELLS R@ - RSHIFT ROT R>
LSHIFT OR ;
: DRSHIFT >R DUP R@ RSHIFT SWAP 8 CELLS R@ - LSHIFT ROT R>
RSHIFT OR SWAP ;
0 4 d. 17179869184 ok
0 4 0 drshift d. 17179869188 ok
4 0 d. 4 ok
4 0 0 dlshift d. 17179869188 ok
Just tested DLSHIFT and found weird things going on. Traced the problem[..]
to LSHIFT.
1 64 LSHIFT . \ expected to get zero
1 \ instead, got 1
Then, I looked at the spec. for LSHIFT and, indeed, there is an
ambiguous condition for u >= BITS_PER_CELL .
6.1.1805
LSHIFT “l-shift”
CORE
( x1 u – – x2 )
Perform a logical left shift of u bit-places on x1, giving x2. Put
zeroes into the least significant bits vacated by the shift. An
ambiguous condition exists if u is greater than or equal to the number
of bits in a cell.
Krishna Myneni wrote:
[..]
Just tested DLSHIFT and found weird things going on. Traced the[..]
problem to LSHIFT.
1 64 LSHIFT . \ expected to get zero
1 \ instead, got 1
Then, I looked at the spec. for LSHIFT and, indeed, there is an
ambiguous condition for u >= BITS_PER_CELL .
6.1.1805
LSHIFT “l-shift”
CORE
( x1 u – – x2 )
Perform a logical left shift of u bit-places on x1, giving x2. Put
zeroes into the least significant bits vacated by the shift. An
ambiguous condition exists if u is greater than or equal to the number
of bits in a cell.
Interesting. Apparently this was changed somewhere in
the course of time, as my local version of the spec. says:
LSHIFT CORE
( u1 u -- u2 )
Perform a logical shift of u bit-places on u1, giving u2. Shift the bits
n places toward the most significant bit. Put zero into the places
"uncovered" by the shift. When u is greater than or equal to the number
of bits in a cell, u2 wraps around.
Fortunately, this is exactly what AMD/Intel hardware does, and leads to
FORTH> 1 64 lshift . 1 ok
-marcel
On 12/04/2024 6:27 pm, albert@spenarnc.xs4all.nl wrote:
In article <66188ab1$1@news.ausics.net>, dxf <dxforth@gmail.com> wrote:
On 12/04/2024 1:11 am, albert@spenarnc.xs4all.nl wrote:
While others indulge in endless discussions about DRSHIFT
I thought to attempt some literate programming.
It didn't prompt you to test your own implementation?
( D0= D0<> D0< D= D< D- M+ DRSHIFT DLSHIFT DU< ) \ AvdH B6Mar22
: DLSHIFT >R SWAP DUP R@ LSHIFT SWAP 8 CELLS R@ - RSHIFT ROT R>
LSHIFT OR ;
: DRSHIFT >R DUP R@ RSHIFT SWAP 8 CELLS R@ - LSHIFT ROT R>
RSHIFT OR SWAP ;
0 4 d. 17179869184 ok
0 4 0 drshift d. 17179869188 ok
4 0 d. 4 ok
4 0 0 dlshift d. 17179869188 ok
Good catch! Shifting over 8 CELLS is an ambiguous condition.
insert
DUP 0= IF EXIT THEN
in front of the code.
That handles the specific case '0 shift' but the ambiguous condition
you mention arises again here:
HEX
03 01 8 cells dlshift .( Expected: 00 03 Got: ) swap u. u. cr
FF 00 8 cells dlshift .( Expected: 00 FF Got: ) swap u. u. cr
00 01 8 cells drshift .( Expected: 01 00 Got: ) swap u. u. cr
00 FF 8 cells drshift .( Expected: FF 00 Got: ) swap u. u. cr
DECIMAL
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 504 |
Nodes: | 16 (2 / 14) |
Uptime: | 245:00:53 |
Calls: | 9,891 |
Files: | 13,794 |
Messages: | 6,294,415 |